1 /* This file is part of the YAZ toolkit.
2 * Copyright (C) 1995-2012 Index Data
3 * See the file LICENSE for details.
7 * \brief Implements Generic COMSTACK functions
16 #include <yaz/yaz-iconv.h>
18 #include <yaz/comstack.h>
19 #include <yaz/tcpip.h>
24 #define strncasecmp _strnicmp
31 #if HAVE_OPENSSL_SSL_H
35 static const char *cs_errlist[] =
37 "No error or unspecified error",
38 "System (lower-layer) error",
39 "Operation out of state",
40 "No data (operation would block)",
41 "New data while half of old buffer is on the line (flow control)",
44 "Too large incoming buffer"
47 const char *cs_errmsg(int n)
51 if (n < CSNONE || n > CSLASTERROR) {
52 sprintf(buf, "unknown comstack error %d", n);
56 sprintf(buf, "%s: %s", cs_errlist[n], strerror(errno));
62 const char *cs_strerror(COMSTACK h)
64 return cs_errmsg(h->cerrno);
67 void cs_get_host_args(const char *type_and_host, const char **args)
71 if (*type_and_host && strncmp(type_and_host, "unix:", 5))
74 cp = strstr(type_and_host, "://");
85 static int cs_parse_host(const char *uri, const char **host,
86 CS_TYPE *t, enum oid_proto *proto,
90 if (strncmp(uri, "connect:", 8) == 0)
92 const char *cp = strchr(uri, ',');
95 size_t len = cp - (uri + 8);
96 *connect_host = (char *) xmalloc(len+1);
97 memcpy(*connect_host, uri + 8, len);
98 (*connect_host)[len] = '\0';
103 if (strncmp (uri, "tcp:", 4) == 0)
107 *proto = PROTO_Z3950;
109 else if (strncmp (uri, "ssl:", 4) == 0)
114 *proto = PROTO_Z3950;
119 else if (strncmp (uri, "unix:", 5) == 0)
124 *proto = PROTO_Z3950;
129 else if (strncmp(uri, "http:", 5) == 0)
133 while (**host == '/')
137 else if (strncmp(uri, "https:", 6) == 0)
142 while (**host == '/')
151 *proto = PROTO_Z3950;
158 COMSTACK cs_create_host(const char *vhost, int blocking, void **vp)
160 return cs_create_host_proxy(vhost, blocking, vp, 0);
163 COMSTACK cs_create_host_proxy(const char *vhost, int blocking, void **vp,
164 const char *proxy_host)
166 enum oid_proto proto = PROTO_Z3950;
167 const char *host = 0;
170 char *connect_host = 0;
172 if (!cs_parse_host(vhost, &host, &t, &proto, &connect_host))
177 cs = yaz_tcpip_create(-1, blocking, proto, connect_host ? host : 0);
181 cs = cs_create(t, blocking, proto);
187 if (!(*vp = cs_straddr(cs, connect_host ? connect_host : host)))
197 int cs_look (COMSTACK cs)
202 static int skip_crlf(const char *buf, int len, int *i)
206 if (buf[*i] == '\r' && *i < len-1 && buf[*i + 1] == '\n')
211 else if (buf[*i] == '\n')
220 #define CHUNK_DEBUG 0
222 static int cs_read_chunk(const char *buf, int i, int len)
224 /* inside chunked body .. */
233 for (j = i; j <= i+3; j++)
234 printf ("%c", buf[j]);
238 /* read chunk length */
242 printf ("returning incomplete read at 1\n");
243 printf ("i=%d len=%d\n", i, len);
246 } else if (yaz_isdigit(buf[i]))
247 chunk_len = chunk_len * 16 +
249 else if (yaz_isupper(buf[i]))
250 chunk_len = chunk_len * 16 +
251 (buf[i++] - ('A'-10));
252 else if (yaz_islower(buf[i]))
253 chunk_len = chunk_len * 16 +
254 (buf[i++] - ('a'-10));
266 if (skip_crlf(buf, len, &i))
272 printf ("chunk_len=%d\n", chunk_len);
277 if (!skip_crlf(buf, len, &i))
280 /* consider trailing headers .. */
283 if (skip_crlf(buf, len, &i))
285 if (skip_crlf(buf, len, &i))
292 printf ("returning incomplete read at 2\n");
293 printf ("i=%d len=%d\n", i, len);
298 static int cs_complete_http(const char *buf, int len, int head_only)
300 /* deal with HTTP request/response */
301 int i = 2, content_len = 0, chunked = 0;
306 /* if dealing with HTTP responses - then default
307 content length is unlimited (socket close) */
308 if (!head_only && !memcmp(buf, "HTTP/", 5))
312 printf("len = %d\n", len);
313 fwrite (buf, 1, len, stdout);
314 printf("----------\n");
320 return i; /* do not allow more than 8K HTTP header */
322 if (skip_crlf(buf, len, &i))
324 if (skip_crlf(buf, len, &i))
328 return cs_read_chunk(buf, i, len);
330 { /* not chunked ; inside body */
331 if (content_len == -1)
332 return 0; /* no content length */
333 else if (len >= i + content_len)
335 return i + content_len;
340 else if (i < len - 20 &&
341 !strncasecmp((const char *) buf+i, "Transfer-Encoding:", 18))
344 while (buf[i] == ' ')
347 if (!strncasecmp((const char *) buf+i, "chunked", 7))
350 else if (i < len - 17 &&
351 !strncasecmp((const char *)buf+i, "Content-Length:", 15))
354 while (buf[i] == ' ')
357 while (i <= len-4 && yaz_isdigit(buf[i]))
358 content_len = content_len*10 + (buf[i++] - '0');
359 if (content_len < 0) /* prevent negative offsets */
371 static int cs_complete_auto_x(const char *buf, int len, int head_only)
373 if (len > 5 && buf[0] >= 0x20 && buf[0] < 0x7f
374 && buf[1] >= 0x20 && buf[1] < 0x7f
375 && buf[2] >= 0x20 && buf[2] < 0x7f)
377 int r = cs_complete_http(buf, len, head_only);
380 return completeBER((const unsigned char *) buf, len);
384 int cs_complete_auto(const char *buf, int len)
386 return cs_complete_auto_x(buf, len, 0);
389 int cs_complete_auto_head(const char *buf, int len)
391 return cs_complete_auto_x(buf, len, 1);
394 void cs_set_max_recv_bytes(COMSTACK cs, int max_recv_bytes)
396 cs->max_recv_bytes = max_recv_bytes;
402 * c-file-style: "Stroustrup"
403 * indent-tabs-mode: nil
405 * vim: shiftwidth=4 tabstop=8 expandtab