X-Git-Url: http://git.indexdata.com/?p=yaz-moved-to-github.git;a=blobdiff_plain;f=src%2Fcomstack.c;h=cec2fd3dd6f40f75f74ef128146698ae8768e029;hp=6934ea68b5ad2728cb2c31b50a6d069136acc16e;hb=fe42f72dc30321041420cf2d1a83867b1c450f38;hpb=019eca69c2a438db0aea7b8760685c618cb5f552 diff --git a/src/comstack.c b/src/comstack.c index 6934ea6..cec2fd3 100644 --- a/src/comstack.c +++ b/src/comstack.c @@ -1,19 +1,19 @@ -/* - * Copyright (C) 1995-2007, Index Data ApS +/* This file is part of the YAZ toolkit. + * Copyright (C) 1995-2012 Index Data * See the file LICENSE for details. - * - * $Id: comstack.c,v 1.19 2007-10-05 16:46:55 adam Exp $ */ - -/** +/** * \file comstack.c * \brief Implements Generic COMSTACK functions */ +#if HAVE_CONFIG_H +#include +#endif #include -#include #include +#include #include #include #include @@ -24,6 +24,14 @@ #define strncasecmp _strnicmp #endif +#if HAVE_GNUTLS_H +#define ENABLE_SSL 1 +#endif + +#if HAVE_OPENSSL_SSL_H +#define ENABLE_SSL 1 +#endif + static const char *cs_errlist[] = { "No error or unspecified error", @@ -58,9 +66,17 @@ const char *cs_strerror(COMSTACK h) void cs_get_host_args(const char *type_and_host, const char **args) { - + *args = ""; - if (*type_and_host && strncmp(type_and_host, "unix:", 5)) + if (!strncmp(type_and_host, "unix:", 5)) + { + const char *cp = strchr(type_and_host + 5, ':'); + if (cp) + type_and_host = cp + 1; + else + type_and_host += strlen(type_and_host); /* empty string */ + } + if (*type_and_host) { const char *cp; cp = strstr(type_and_host, "://"); @@ -74,18 +90,62 @@ 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; + + *t = tcpip_type; + if (strncmp(uri, "connect:", 8) == 0) + { + const char *cp = strchr(uri, ','); + if (cp) + { + size_t len; + + uri += 8; + len = cp - uri; + *connect_host = (char *) xmalloc(len + 1); + memcpy(*connect_host, uri, len); + (*connect_host)[len] = '\0'; + uri = cp + 1; + } + } + else if (strncmp(uri, "unix:", 5) == 0) + { + const char *cp; + + uri += 5; + cp = strchr(uri, ':'); + if (cp) + { + size_t len = cp - uri; + *connect_host = (char *) xmalloc(len + 1); + memcpy(*connect_host, uri, len); + (*connect_host)[len] = '\0'; + uri = cp + 1; + } + else + { + *connect_host = xstrdup(uri); + uri += strlen(uri); /* set to "" */ + } +#ifdef WIN32 + return 0; +#else + *t = unix_type; +#endif + } + if (strncmp (uri, "tcp:", 4) == 0) { - *t = tcpip_type; *host = uri + 4; *proto = PROTO_Z3950; } else if (strncmp (uri, "ssl:", 4) == 0) { -#if HAVE_OPENSSL_SSL_H +#if ENABLE_SSL *t = ssl_type; *host = uri + 4; *proto = PROTO_Z3950; @@ -93,19 +153,8 @@ int cs_parse_host(const char *uri, const char **host, return 0; #endif } - else if (strncmp (uri, "unix:", 5) == 0) - { -#ifndef WIN32 - *t = unix_type; - *host = uri + 5; - *proto = PROTO_Z3950; -#else - return 0; -#endif - } else if (strncmp(uri, "http:", 5) == 0) { - *t = tcpip_type; *host = uri + 5; while (**host == '/') (*host)++; @@ -113,7 +162,7 @@ int cs_parse_host(const char *uri, const char **host, } else if (strncmp(uri, "https:", 6) == 0) { -#if HAVE_OPENSSL_SSL_H +#if ENABLE_SSL *t = ssl_type; *host = uri + 6; while (**host == '/') @@ -125,31 +174,48 @@ int cs_parse_host(const char *uri, const char **host, } else { - *proto = PROTO_Z3950; - *t = tcpip_type; *host = uri; + *proto = PROTO_Z3950; } return 1; } COMSTACK cs_create_host(const char *vhost, int blocking, void **vp) { + return cs_create_host_proxy(vhost, blocking, vp, 0); +} + +COMSTACK cs_create_host_proxy(const char *vhost, int blocking, void **vp, + const char *proxy_host) +{ enum oid_proto proto = PROTO_Z3950; const char *host = 0; COMSTACK cs; CS_TYPE t; + char *connect_host = 0; - cs_parse_host(vhost, &host, &t, &proto); - - cs = cs_create(t, blocking, proto); - if (!cs) + if (!cs_parse_host(vhost, &host, &t, &proto, &connect_host)) 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 (proxy_host) + host = proxy_host; + if (!(*vp = cs_straddr(cs, connect_host ? connect_host : host))) + { + cs_close (cs); + cs = 0; + } + } + xfree(connect_host); return cs; } @@ -178,7 +244,83 @@ 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_read_chunk(const char *buf, int i, int len) +{ + /* inside chunked body .. */ + while (1) + { + int chunk_len = 0; +#if CHUNK_DEBUG + if (i < len-2) + { + printf ("\n<<<"); + int j; + for (j = i; j <= i+3; j++) + printf ("%c", buf[j]); + printf (">>>\n"); + } +#endif + /* read chunk length */ + while (1) + if (i >= len-2) { +#if CHUNK_DEBUG + printf ("returning incomplete read at 1\n"); + printf ("i=%d len=%d\n", i, len); +#endif + return 0; + } else if (yaz_isdigit(buf[i])) + chunk_len = chunk_len * 16 + + (buf[i++] - '0'); + else if (yaz_isupper(buf[i])) + chunk_len = chunk_len * 16 + + (buf[i++] - ('A'-10)); + else if (yaz_islower(buf[i])) + chunk_len = chunk_len * 16 + + (buf[i++] - ('a'-10)); + else + break; + if (chunk_len == 0) + break; + if (chunk_len < 0) + return i; + + while (1) + { + if (i >= len -1) + return 0; + if (skip_crlf(buf, len, &i)) + break; + i++; + } + /* got CRLF */ +#if CHUNK_DEBUG + printf ("chunk_len=%d\n", chunk_len); +#endif + i += chunk_len; + if (i >= len-2) + return 0; + if (!skip_crlf(buf, len, &i)) + return 0; + } + /* consider trailing headers .. */ + while (i < len) + { + if (skip_crlf(buf, len, &i)) + { + if (skip_crlf(buf, len, &i)) + return i; + } + else + i++; + } +#if CHUNK_DEBUG + printf ("returning incomplete read at 2\n"); + printf ("i=%d len=%d\n", i, len); +#endif + return 0; +} + +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,8 +330,8 @@ 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)) - content_len = -1; + if (!head_only && !memcmp(buf, "HTTP/", 5)) + content_len = -1; #if 0 printf("len = %d\n", len); @@ -208,80 +350,7 @@ int cs_complete_http(const char *buf, int len) { /* inside content */ if (chunked) - { - /* inside chunked body .. */ - while(1) - { - int chunk_len = 0; -#if CHUNK_DEBUG - if (i < len-2) - { - printf ("\n<<<"); - int j; - for (j = i; j <= i+3; j++) - printf ("%c", buf[j]); - printf (">>>\n"); - } -#endif - /* read chunk length */ - while (1) - if (i >= len-2) { -#if CHUNK_DEBUG - printf ("returning incomplete read at 1\n"); - printf ("i=%d len=%d\n", i, len); -#endif - return 0; - } else if (isdigit(buf[i])) - chunk_len = chunk_len * 16 + - (buf[i++] - '0'); - else if (isupper(buf[i])) - chunk_len = chunk_len * 16 + - (buf[i++] - ('A'-10)); - else if (islower(buf[i])) - chunk_len = chunk_len * 16 + - (buf[i++] - ('a'-10)); - else - break; - if (chunk_len == 0) - break; - if (chunk_len < 0) - return i; - - while (1) - { - if (i >= len -1) - return 0; - if (skip_crlf(buf, len, &i)) - break; - i++; - } - /* got CRLF */ -#if CHUNK_DEBUG - printf ("chunk_len=%d\n", chunk_len); -#endif - i += chunk_len; - if (i >= len-2) - return 0; - if (!skip_crlf(buf, len, &i)) - return 0; - } - /* consider trailing headers .. */ - while (i < len) - { - if (skip_crlf(buf, len, &i)) - { - if (skip_crlf(buf, len, &i)) - return i; - } - else - i++; - } -#if CHUNK_DEBUG - printf ("returning incomplete read at 2\n"); - printf ("i=%d len=%d\n", i, len); -#endif - return 0; - } + return cs_read_chunk(buf, i, len); else { /* not chunked ; inside body */ if (content_len == -1) @@ -293,7 +362,7 @@ int cs_complete_http(const char *buf, int len) } break; } - else if (i < len - 20 && + else if (i < len - 20 && !strncasecmp((const char *) buf+i, "Transfer-Encoding:", 18)) { i+=18; @@ -310,7 +379,7 @@ int cs_complete_http(const char *buf, int len) while (buf[i] == ' ') i++; content_len = 0; - while (i <= len-4 && isdigit(buf[i])) + while (i <= len-4 && yaz_isdigit(buf[i])) content_len = content_len*10 + (buf[i++] - '0'); if (content_len < 0) /* prevent negative offsets */ content_len = 0; @@ -324,16 +393,27 @@ 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 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(buf, len, head_only); return r; } - return completeBER(buf, len); + return completeBER((const unsigned char *) buf, len); +} + + +int cs_complete_auto(const char *buf, int len) +{ + return cs_complete_auto_x(buf, len, 0); +} + +int cs_complete_auto_head(const char *buf, int len) +{ + return cs_complete_auto_x(buf, len, 1); } void cs_set_max_recv_bytes(COMSTACK cs, int max_recv_bytes) @@ -344,6 +424,7 @@ void cs_set_max_recv_bytes(COMSTACK cs, int max_recv_bytes) /* * Local variables: * c-basic-offset: 4 + * c-file-style: "Stroustrup" * indent-tabs-mode: nil * End: * vim: shiftwidth=4 tabstop=8 expandtab