From: Adam Dickmeiss Date: Sun, 7 Oct 2007 08:53:26 +0000 (+0000) Subject: Added HTTP tunnel facility for COMSTACK, bug #1752. X-Git-Tag: YAZ.3.0.16~61 X-Git-Url: http://git.indexdata.com/?p=yaz-moved-to-github.git;a=commitdiff_plain;h=29cc293e92725df0aaf70fa4897600597dd8db9b Added HTTP tunnel facility for COMSTACK, bug #1752. This is a facility that allows a Web proxy, such as squid, to tunnel Z39.50 traffic. This facility is "transparent" to must applications using YAZ. It's enabled by using pseudo transport connect: followed bý the we proxy address, followed by command, then follwed by he regular "virtual" addresss. For example, connect:webproxy.com:3128,tcp:z3950.loc.gov:7090/voyager . --- diff --git a/NEWS b/NEWS index 295d7f9..1bae7fd 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,11 @@ +Added HTTP tunnel facility for COMSTACK, bug #1752. +This is a facility that allows a Web proxy, such as squid, to tunnel +Z39.50 traffic. This facility is "transparent" to must applications +using YAZ. It's enabled by using pseudo transport connect: followed bý +the we proxy address, followed by command, then follwed by he regular +"virtual" addresss. For example, +connect:webproxy.com:3128,tcp:z3950.loc.gov:7090/voyager . + --- 3.0.14 2007/09/21 Fixed bad memory reference in ZOOM_record - cuased by member not being diff --git a/include/yaz/comstack.h b/include/yaz/comstack.h index 3307a91..bbfbe52 100644 --- a/include/yaz/comstack.h +++ b/include/yaz/comstack.h @@ -24,7 +24,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* $Id: comstack.h,v 1.28 2007-10-05 16:46:55 adam Exp $ */ +/* $Id: comstack.h,v 1.29 2007-10-07 08:53:26 adam Exp $ */ /** * \file comstack.h @@ -126,16 +126,14 @@ YAZ_EXPORT const char *cs_errmsg(int n); YAZ_EXPORT COMSTACK cs_create_host(const char *type_and_host, int blocking, void **vp); YAZ_EXPORT void cs_get_host_args(const char *type_and_host, const char **args); +YAZ_EXPORT int cs_complete_auto_head(const unsigned char *buf, int len); YAZ_EXPORT int cs_complete_auto(const unsigned char *buf, int len); YAZ_EXPORT void *cs_get_ssl(COMSTACK cs); YAZ_EXPORT int cs_set_ssl_ctx(COMSTACK cs, void *ctx); YAZ_EXPORT int cs_set_ssl_certificate_file(COMSTACK cs, const char *fname); YAZ_EXPORT int cs_get_peer_certificate_x509(COMSTACK cs, char **buf, int *len); YAZ_EXPORT void cs_set_max_recv_bytes(COMSTACK cs, int max_recv_bytes); -YAZ_EXPORT int cs_complete_http(const char *buf, int len); -YAZ_EXPORT int cs_parse_host(const char *uri, const char **host, - CS_TYPE *t, enum oid_proto *proto); - + /* * error management. */ diff --git a/include/yaz/tcpip.h b/include/yaz/tcpip.h index 0208450..8269d8c 100644 --- a/include/yaz/tcpip.h +++ b/include/yaz/tcpip.h @@ -24,7 +24,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* $Id: tcpip.h,v 1.12 2007-04-12 13:52:57 adam Exp $ */ +/* $Id: tcpip.h,v 1.13 2007-10-07 08:53:26 adam Exp $ */ /** * \file tcpip.h @@ -41,6 +41,8 @@ YAZ_BEGIN_CDECL YAZ_EXPORT int completeWAIS(const unsigned char *buf, int len); YAZ_EXPORT COMSTACK tcpip_type(int s, int flags, int protocol, void *vp); YAZ_EXPORT COMSTACK ssl_type(int s, int flags, int protocol, void *vp); +YAZ_EXPORT COMSTACK yaz_tcpip_create(int s, int flags, int protocol, + const char *connect_host); YAZ_END_CDECL diff --git a/src/comstack.c b/src/comstack.c index 6934ea6..62978da 100644 --- a/src/comstack.c +++ b/src/comstack.c @@ -2,7 +2,7 @@ * Copyright (C) 1995-2007, Index Data ApS * See the file LICENSE for details. * - * $Id: comstack.c,v 1.19 2007-10-05 16:46:55 adam Exp $ + * $Id: comstack.c,v 1.20 2007-10-07 08:53:26 adam Exp $ */ /** @@ -74,9 +74,24 @@ void cs_get_host_args(const char *type_and_host, const char **args) } } -int cs_parse_host(const char *uri, const char **host, - CS_TYPE *t, enum oid_proto *proto) +static int cs_parse_host(const char *uri, const char **host, + CS_TYPE *t, enum oid_proto *proto, + char **connect_host) { + *connect_host = 0; + if (strncmp(uri, "connect:", 8) == 0) + { + const char *cp = strchr(uri, ','); + if (cp) + { + size_t len = cp - (uri + 8); + *connect_host = xmalloc(len+1); + memcpy(*connect_host, uri + 8, len); + (*connect_host)[len] = '\0'; + uri = cp+1; + } + } + if (strncmp (uri, "tcp:", 4) == 0) { *t = tcpip_type; @@ -138,18 +153,27 @@ COMSTACK cs_create_host(const char *vhost, int blocking, void **vp) const char *host = 0; COMSTACK cs; CS_TYPE t; + char *connect_host = 0; - cs_parse_host(vhost, &host, &t, &proto); + cs_parse_host(vhost, &host, &t, &proto, &connect_host); - cs = cs_create(t, blocking, proto); - if (!cs) - return 0; - - if (!(*vp = cs_straddr(cs, host))) + if (t == tcpip_type) { - cs_close (cs); - return 0; - } + cs = yaz_tcpip_create(-1, blocking, proto, connect_host ? host : 0); + } + else + { + cs = cs_create(t, blocking, proto); + } + if (cs) + { + if (!(*vp = cs_straddr(cs, connect_host ? connect_host : host))) + { + cs_close (cs); + cs = 0; + } + } + xfree(connect_host); return cs; } @@ -178,7 +202,7 @@ static int skip_crlf(const char *buf, int len, int *i) #define CHUNK_DEBUG 0 -int cs_complete_http(const char *buf, int len) +static int cs_complete_http(const char *buf, int len, int head_only) { /* deal with HTTP request/response */ int i = 2, content_len = 0, chunked = 0; @@ -188,7 +212,7 @@ int cs_complete_http(const char *buf, int len) /* if dealing with HTTP responses - then default content length is unlimited (socket close) */ - if (!memcmp(buf, "HTTP/", 5)) + if (!head_only && !memcmp(buf, "HTTP/", 5)) content_len = -1; #if 0 @@ -324,18 +348,29 @@ int cs_complete_http(const char *buf, int len) return 0; } -int cs_complete_auto(const unsigned char *buf, int len) +static int cs_complete_auto_x(const unsigned char *buf, int len, int head_only) { if (len > 5 && buf[0] >= 0x20 && buf[0] < 0x7f && buf[1] >= 0x20 && buf[1] < 0x7f && buf[2] >= 0x20 && buf[2] < 0x7f) { - int r = cs_complete_http((const char *) buf, len); + int r = cs_complete_http((const char *) buf, len, head_only); return r; } return completeBER(buf, len); } + +int cs_complete_auto(const unsigned char *buf, int len) +{ + return cs_complete_auto_x(buf, len, 0); +} + +int cs_complete_auto_head(const unsigned char *buf, int len) +{ + return cs_complete_auto_x(buf, len, 1); +} + void cs_set_max_recv_bytes(COMSTACK cs, int max_recv_bytes) { cs->max_recv_bytes = max_recv_bytes; diff --git a/src/tcpip.c b/src/tcpip.c index 8ffdfe8..b1f9fa9 100644 --- a/src/tcpip.c +++ b/src/tcpip.c @@ -2,7 +2,7 @@ * Copyright (C) 1995-2007, Index Data ApS * See the file LICENSE for details. * - * $Id: tcpip.c,v 1.34 2007-01-19 10:28:42 adam Exp $ + * $Id: tcpip.c,v 1.35 2007-10-07 08:53:26 adam Exp $ */ /** * \file tcpip.c @@ -65,6 +65,8 @@ static int tcpip_close(COMSTACK h); static int tcpip_put(COMSTACK h, char *buf, int size); static int tcpip_get(COMSTACK h, char **buf, int *bufsize); +static int tcpip_put_connect(COMSTACK h, char *buf, int size); +static int tcpip_get_connect(COMSTACK h, char **buf, int *bufsize); static int tcpip_connect(COMSTACK h, void *address); static int tcpip_more(COMSTACK h); static int tcpip_rcvconnect(COMSTACK h); @@ -115,6 +117,10 @@ typedef struct tcpip_state SSL *ssl; char cert_fname[256]; #endif + char *connect_request_buf; + int connect_request_len; + char *connect_response_buf; + int connect_response_len; } tcpip_state; #ifdef WIN32 @@ -201,12 +207,38 @@ COMSTACK tcpip_type(int s, int flags, int protocol, void *vp) else sp->complete = cs_complete_auto; + sp->connect_request_buf = 0; + sp->connect_request_len = 0; + sp->connect_response_buf = 0; + sp->connect_response_len = 0; + p->timeout = COMSTACK_DEFAULT_TIMEOUT; TRC(fprintf(stderr, "Created new TCPIP comstack\n")); return p; } +COMSTACK yaz_tcpip_create(int s, int flags, int protocol, + const char *connect_host) +{ + COMSTACK p = tcpip_type(s, flags, protocol, 0); + if (!p) + return 0; + if (connect_host) + { + tcpip_state *sp = (tcpip_state *) p->cprivate; + sp->connect_request_buf = xmalloc(strlen(connect_host) + 30); + sprintf(sp->connect_request_buf, "CONNECT %s HTTP/1.0\r\n\r\n", + connect_host); + sp->connect_request_len = strlen(sp->connect_request_buf); + p->f_put = tcpip_put_connect; + p->f_get = tcpip_get_connect; + sp->complete = cs_complete_auto_head; /* only want HTTP header */ + } + return p; +} + + #if HAVE_OPENSSL_SSL_H COMSTACK ssl_type(int s, int flags, int protocol, void *vp) @@ -792,6 +824,8 @@ COMSTACK tcpip_accept(COMSTACK h) state->ssl = SSL_new (state->ctx); SSL_set_fd (state->ssl, cnew->iofile); } + state->connect_request_buf = 0; + state->connect_response_buf = 0; #endif h = cnew; } @@ -1208,6 +1242,8 @@ int tcpip_close(COMSTACK h) if (sp->ai) freeaddrinfo(sp->ai); #endif + xfree(sp->connect_request_buf); + xfree(sp->connect_response_buf); xfree(sp); xfree(h); return 0; @@ -1375,6 +1411,38 @@ int cs_set_ssl_certificate_file(COMSTACK cs, const char *fname) } #endif + +static int tcpip_put_connect(COMSTACK h, char *buf, int size) +{ + struct tcpip_state *state = (struct tcpip_state *)h->cprivate; + + int r = tcpip_put(h, state->connect_request_buf, + state->connect_request_len); + if (r == 0) + { + /* it's sent */ + h->f_put = tcpip_put; /* switch to normal tcpip put */ + r = tcpip_put(h, buf, size); + } + return r; +} + +static int tcpip_get_connect(COMSTACK h, char **buf, int *bufsize) +{ + struct tcpip_state *state = (struct tcpip_state *)h->cprivate; + int r; + + r = tcpip_get(h, &state->connect_response_buf, + &state->connect_response_len); + if (r < 1) + return r; + /* got the connect response completely */ + state->complete = cs_complete_auto; /* switch to normal tcpip get */ + h->f_get = tcpip_get; + return tcpip_get(h, buf, bufsize); +} + + /* * Local variables: * c-basic-offset: 4