2 * Copyright (C) 1995-2007, Index Data ApS
3 * See the file LICENSE for details.
5 * $Id: comstack.c,v 1.19 2007-10-05 16:46:55 adam Exp $
10 * \brief Implements Generic COMSTACK functions
18 #include <yaz/comstack.h>
19 #include <yaz/tcpip.h>
24 #define strncasecmp _strnicmp
27 static const char *cs_errlist[] =
29 "No error or unspecified error",
30 "System (lower-layer) error",
31 "Operation out of state",
32 "No data (operation would block)",
33 "New data while half of old buffer is on the line (flow control)",
36 "Too large incoming buffer"
39 const char *cs_errmsg(int n)
43 if (n < CSNONE || n > CSLASTERROR) {
44 sprintf(buf, "unknown comstack error %d", n);
48 sprintf(buf, "%s: %s", cs_errlist[n], strerror(errno));
54 const char *cs_strerror(COMSTACK h)
56 return cs_errmsg(h->cerrno);
59 void cs_get_host_args(const char *type_and_host, const char **args)
63 if (*type_and_host && strncmp(type_and_host, "unix:", 5))
66 cp = strstr(type_and_host, "://");
77 int cs_parse_host(const char *uri, const char **host,
78 CS_TYPE *t, enum oid_proto *proto)
80 if (strncmp (uri, "tcp:", 4) == 0)
86 else if (strncmp (uri, "ssl:", 4) == 0)
88 #if HAVE_OPENSSL_SSL_H
96 else if (strncmp (uri, "unix:", 5) == 0)
101 *proto = PROTO_Z3950;
106 else if (strncmp(uri, "http:", 5) == 0)
110 while (**host == '/')
114 else if (strncmp(uri, "https:", 6) == 0)
116 #if HAVE_OPENSSL_SSL_H
119 while (**host == '/')
128 *proto = PROTO_Z3950;
135 COMSTACK cs_create_host(const char *vhost, int blocking, void **vp)
137 enum oid_proto proto = PROTO_Z3950;
138 const char *host = 0;
142 cs_parse_host(vhost, &host, &t, &proto);
144 cs = cs_create(t, blocking, proto);
148 if (!(*vp = cs_straddr(cs, host)))
156 int cs_look (COMSTACK cs)
161 static int skip_crlf(const char *buf, int len, int *i)
165 if (buf[*i] == '\r' && *i < len-1 && buf[*i + 1] == '\n')
170 else if (buf[*i] == '\n')
179 #define CHUNK_DEBUG 0
181 int cs_complete_http(const char *buf, int len)
183 /* deal with HTTP request/response */
184 int i = 2, content_len = 0, chunked = 0;
189 /* if dealing with HTTP responses - then default
190 content length is unlimited (socket close) */
191 if (!memcmp(buf, "HTTP/", 5))
195 printf("len = %d\n", len);
196 fwrite (buf, 1, len, stdout);
197 printf("----------\n");
203 return i; /* do not allow more than 8K HTTP header */
205 if (skip_crlf(buf, len, &i))
207 if (skip_crlf(buf, len, &i))
212 /* inside chunked body .. */
221 for (j = i; j <= i+3; j++)
222 printf ("%c", buf[j]);
226 /* read chunk length */
230 printf ("returning incomplete read at 1\n");
231 printf ("i=%d len=%d\n", i, len);
234 } else if (isdigit(buf[i]))
235 chunk_len = chunk_len * 16 +
237 else if (isupper(buf[i]))
238 chunk_len = chunk_len * 16 +
239 (buf[i++] - ('A'-10));
240 else if (islower(buf[i]))
241 chunk_len = chunk_len * 16 +
242 (buf[i++] - ('a'-10));
254 if (skip_crlf(buf, len, &i))
260 printf ("chunk_len=%d\n", chunk_len);
265 if (!skip_crlf(buf, len, &i))
268 /* consider trailing headers .. */
271 if (skip_crlf(buf, len, &i))
273 if (skip_crlf(buf, len, &i))
280 printf ("returning incomplete read at 2\n");
281 printf ("i=%d len=%d\n", i, len);
286 { /* not chunked ; inside body */
287 if (content_len == -1)
288 return 0; /* no content length */
289 else if (len >= i + content_len)
291 return i + content_len;
296 else if (i < len - 20 &&
297 !strncasecmp((const char *) buf+i, "Transfer-Encoding:", 18))
300 while (buf[i] == ' ')
303 if (!strncasecmp((const char *) buf+i, "chunked", 7))
306 else if (i < len - 17 &&
307 !strncasecmp((const char *)buf+i, "Content-Length:", 15))
310 while (buf[i] == ' ')
313 while (i <= len-4 && isdigit(buf[i]))
314 content_len = content_len*10 + (buf[i++] - '0');
315 if (content_len < 0) /* prevent negative offsets */
327 int cs_complete_auto(const unsigned char *buf, int len)
329 if (len > 5 && buf[0] >= 0x20 && buf[0] < 0x7f
330 && buf[1] >= 0x20 && buf[1] < 0x7f
331 && buf[2] >= 0x20 && buf[2] < 0x7f)
333 int r = cs_complete_http((const char *) buf, len);
336 return completeBER(buf, len);
339 void cs_set_max_recv_bytes(COMSTACK cs, int max_recv_bytes)
341 cs->max_recv_bytes = max_recv_bytes;
347 * indent-tabs-mode: nil
349 * vim: shiftwidth=4 tabstop=8 expandtab