1 /* This file is part of the YAZ toolkit.
2 * Copyright (C) 1995-2008 Index Data
3 * See the file LICENSE for details.
8 * \brief Implements Generic COMSTACK functions
16 #include <yaz/comstack.h>
17 #include <yaz/tcpip.h>
22 #define strncasecmp _strnicmp
25 static const char *cs_errlist[] =
27 "No error or unspecified error",
28 "System (lower-layer) error",
29 "Operation out of state",
30 "No data (operation would block)",
31 "New data while half of old buffer is on the line (flow control)",
34 "Too large incoming buffer"
37 const char *cs_errmsg(int n)
41 if (n < CSNONE || n > CSLASTERROR) {
42 sprintf(buf, "unknown comstack error %d", n);
46 sprintf(buf, "%s: %s", cs_errlist[n], strerror(errno));
52 const char *cs_strerror(COMSTACK h)
54 return cs_errmsg(h->cerrno);
57 void cs_get_host_args(const char *type_and_host, const char **args)
61 if (*type_and_host && strncmp(type_and_host, "unix:", 5))
64 cp = strstr(type_and_host, "://");
75 static int cs_parse_host(const char *uri, const char **host,
76 CS_TYPE *t, enum oid_proto *proto,
80 if (strncmp(uri, "connect:", 8) == 0)
82 const char *cp = strchr(uri, ',');
85 size_t len = cp - (uri + 8);
86 *connect_host = (char *) xmalloc(len+1);
87 memcpy(*connect_host, uri + 8, len);
88 (*connect_host)[len] = '\0';
93 if (strncmp (uri, "tcp:", 4) == 0)
99 else if (strncmp (uri, "ssl:", 4) == 0)
101 #if HAVE_OPENSSL_SSL_H
104 *proto = PROTO_Z3950;
109 else if (strncmp (uri, "unix:", 5) == 0)
114 *proto = PROTO_Z3950;
119 else if (strncmp(uri, "http:", 5) == 0)
123 while (**host == '/')
127 else if (strncmp(uri, "https:", 6) == 0)
129 #if HAVE_OPENSSL_SSL_H
132 while (**host == '/')
141 *proto = PROTO_Z3950;
148 COMSTACK cs_create_host(const char *vhost, int blocking, void **vp)
150 enum oid_proto proto = PROTO_Z3950;
151 const char *host = 0;
154 char *connect_host = 0;
156 cs_parse_host(vhost, &host, &t, &proto, &connect_host);
160 cs = yaz_tcpip_create(-1, blocking, proto, connect_host ? host : 0);
164 cs = cs_create(t, blocking, proto);
168 if (!(*vp = cs_straddr(cs, connect_host ? connect_host : host)))
178 int cs_look (COMSTACK cs)
183 static int skip_crlf(const char *buf, int len, int *i)
187 if (buf[*i] == '\r' && *i < len-1 && buf[*i + 1] == '\n')
192 else if (buf[*i] == '\n')
201 #define CHUNK_DEBUG 0
203 static int cs_complete_http(const char *buf, int len, int head_only)
205 /* deal with HTTP request/response */
206 int i = 2, content_len = 0, chunked = 0;
211 /* if dealing with HTTP responses - then default
212 content length is unlimited (socket close) */
213 if (!head_only && !memcmp(buf, "HTTP/", 5))
217 printf("len = %d\n", len);
218 fwrite (buf, 1, len, stdout);
219 printf("----------\n");
225 return i; /* do not allow more than 8K HTTP header */
227 if (skip_crlf(buf, len, &i))
229 if (skip_crlf(buf, len, &i))
234 /* inside chunked body .. */
243 for (j = i; j <= i+3; j++)
244 printf ("%c", buf[j]);
248 /* read chunk length */
252 printf ("returning incomplete read at 1\n");
253 printf ("i=%d len=%d\n", i, len);
256 } else if (isdigit(buf[i]))
257 chunk_len = chunk_len * 16 +
259 else if (isupper(buf[i]))
260 chunk_len = chunk_len * 16 +
261 (buf[i++] - ('A'-10));
262 else if (islower(buf[i]))
263 chunk_len = chunk_len * 16 +
264 (buf[i++] - ('a'-10));
276 if (skip_crlf(buf, len, &i))
282 printf ("chunk_len=%d\n", chunk_len);
287 if (!skip_crlf(buf, len, &i))
290 /* consider trailing headers .. */
293 if (skip_crlf(buf, len, &i))
295 if (skip_crlf(buf, len, &i))
302 printf ("returning incomplete read at 2\n");
303 printf ("i=%d len=%d\n", i, len);
308 { /* not chunked ; inside body */
309 if (content_len == -1)
310 return 0; /* no content length */
311 else if (len >= i + content_len)
313 return i + content_len;
318 else if (i < len - 20 &&
319 !strncasecmp((const char *) buf+i, "Transfer-Encoding:", 18))
322 while (buf[i] == ' ')
325 if (!strncasecmp((const char *) buf+i, "chunked", 7))
328 else if (i < len - 17 &&
329 !strncasecmp((const char *)buf+i, "Content-Length:", 15))
332 while (buf[i] == ' ')
335 while (i <= len-4 && isdigit(buf[i]))
336 content_len = content_len*10 + (buf[i++] - '0');
337 if (content_len < 0) /* prevent negative offsets */
349 static int cs_complete_auto_x(const char *buf, int len, int head_only)
351 if (len > 5 && buf[0] >= 0x20 && buf[0] < 0x7f
352 && buf[1] >= 0x20 && buf[1] < 0x7f
353 && buf[2] >= 0x20 && buf[2] < 0x7f)
355 int r = cs_complete_http(buf, len, head_only);
358 return completeBER((const unsigned char *) buf, len);
362 int cs_complete_auto(const char *buf, int len)
364 return cs_complete_auto_x(buf, len, 0);
367 int cs_complete_auto_head(const char *buf, int len)
369 return cs_complete_auto_x(buf, len, 1);
372 void cs_set_max_recv_bytes(COMSTACK cs, int max_recv_bytes)
374 cs->max_recv_bytes = max_recv_bytes;
380 * indent-tabs-mode: nil
382 * vim: shiftwidth=4 tabstop=8 expandtab