+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
* (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
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.
*/
* (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
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
* 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 $
*/
/**
}
}
-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;
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;
}
#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;
/* 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
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;
* 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
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);
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
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)
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;
}
if (sp->ai)
freeaddrinfo(sp->ai);
#endif
+ xfree(sp->connect_request_buf);
+ xfree(sp->connect_response_buf);
xfree(sp);
xfree(h);
return 0;
}
#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