1 /* This file is part of the YAZ toolkit.
2 * Copyright (C) 1995-2011 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 enum oid_proto proto = PROTO_Z3950;
161 const char *host = 0;
164 char *connect_host = 0;
166 cs_parse_host(vhost, &host, &t, &proto, &connect_host);
170 cs = yaz_tcpip_create(-1, blocking, proto, connect_host ? host : 0);
174 cs = cs_create(t, blocking, proto);
178 if (!(*vp = cs_straddr(cs, connect_host ? connect_host : host)))
188 int cs_look (COMSTACK cs)
193 static int skip_crlf(const char *buf, int len, int *i)
197 if (buf[*i] == '\r' && *i < len-1 && buf[*i + 1] == '\n')
202 else if (buf[*i] == '\n')
211 #define CHUNK_DEBUG 0
213 static int cs_read_chunk(const char *buf, int i, int len)
215 /* inside chunked body .. */
224 for (j = i; j <= i+3; j++)
225 printf ("%c", buf[j]);
229 /* read chunk length */
233 printf ("returning incomplete read at 1\n");
234 printf ("i=%d len=%d\n", i, len);
237 } else if (yaz_isdigit(buf[i]))
238 chunk_len = chunk_len * 16 +
240 else if (yaz_isupper(buf[i]))
241 chunk_len = chunk_len * 16 +
242 (buf[i++] - ('A'-10));
243 else if (yaz_islower(buf[i]))
244 chunk_len = chunk_len * 16 +
245 (buf[i++] - ('a'-10));
257 if (skip_crlf(buf, len, &i))
263 printf ("chunk_len=%d\n", chunk_len);
268 if (!skip_crlf(buf, len, &i))
271 /* consider trailing headers .. */
274 if (skip_crlf(buf, len, &i))
276 if (skip_crlf(buf, len, &i))
283 printf ("returning incomplete read at 2\n");
284 printf ("i=%d len=%d\n", i, len);
289 static int cs_complete_http(const char *buf, int len, int head_only)
291 /* deal with HTTP request/response */
292 int i = 2, content_len = 0, chunked = 0;
297 /* if dealing with HTTP responses - then default
298 content length is unlimited (socket close) */
299 if (!head_only && !memcmp(buf, "HTTP/", 5))
303 printf("len = %d\n", len);
304 fwrite (buf, 1, len, stdout);
305 printf("----------\n");
311 return i; /* do not allow more than 8K HTTP header */
313 if (skip_crlf(buf, len, &i))
315 if (skip_crlf(buf, len, &i))
319 return cs_read_chunk(buf, i, len);
321 { /* not chunked ; inside body */
322 if (content_len == -1)
323 return 0; /* no content length */
324 else if (len >= i + content_len)
326 return i + content_len;
331 else if (i < len - 20 &&
332 !strncasecmp((const char *) buf+i, "Transfer-Encoding:", 18))
335 while (buf[i] == ' ')
338 if (!strncasecmp((const char *) buf+i, "chunked", 7))
341 else if (i < len - 17 &&
342 !strncasecmp((const char *)buf+i, "Content-Length:", 15))
345 while (buf[i] == ' ')
348 while (i <= len-4 && yaz_isdigit(buf[i]))
349 content_len = content_len*10 + (buf[i++] - '0');
350 if (content_len < 0) /* prevent negative offsets */
362 static int cs_complete_auto_x(const char *buf, int len, int head_only)
364 if (len > 5 && buf[0] >= 0x20 && buf[0] < 0x7f
365 && buf[1] >= 0x20 && buf[1] < 0x7f
366 && buf[2] >= 0x20 && buf[2] < 0x7f)
368 int r = cs_complete_http(buf, len, head_only);
371 return completeBER((const unsigned char *) buf, len);
375 int cs_complete_auto(const char *buf, int len)
377 return cs_complete_auto_x(buf, len, 0);
380 int cs_complete_auto_head(const char *buf, int len)
382 return cs_complete_auto_x(buf, len, 1);
385 void cs_set_max_recv_bytes(COMSTACK cs, int max_recv_bytes)
387 cs->max_recv_bytes = max_recv_bytes;
393 * c-file-style: "Stroustrup"
394 * indent-tabs-mode: nil
396 * vim: shiftwidth=4 tabstop=8 expandtab