2 * Copyright (C) 1995-2007, Index Data ApS
3 * See the file LICENSE for details.
5 * $Id: comstack.c,v 1.18 2007-01-11 10:30:41 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 COMSTACK cs_create_host(const char *type_and_host, int blocking, void **vp)
79 enum oid_proto proto = PROTO_Z3950;
84 if (strncmp (type_and_host, "tcp:", 4) == 0)
87 host = type_and_host + 4;
89 else if (strncmp (type_and_host, "ssl:", 4) == 0)
91 #if HAVE_OPENSSL_SSL_H
93 host = type_and_host + 4;
98 else if (strncmp (type_and_host, "unix:", 5) == 0)
102 host = type_and_host + 5;
107 else if (strncmp(type_and_host, "http:", 5) == 0)
110 host = type_and_host + 5;
111 while (host[0] == '/')
115 else if (strncmp(type_and_host, "https:", 6) == 0)
117 #if HAVE_OPENSSL_SSL_H
119 host = type_and_host + 6;
120 while (host[0] == '/')
130 host = type_and_host;
132 cs = cs_create (t, blocking, proto);
136 if (!(*vp = cs_straddr(cs, host)))
144 int cs_look (COMSTACK cs)
149 static int skip_crlf(const char *buf, int len, int *i)
153 if (buf[*i] == '\r' && *i < len-1 && buf[*i + 1] == '\n')
158 else if (buf[*i] == '\n')
167 #define CHUNK_DEBUG 0
169 int cs_complete_http(const char *buf, int len)
171 /* deal with HTTP request/response */
172 int i = 2, content_len = 0, chunked = 0;
177 /* if dealing with HTTP responses - then default
178 content length is unlimited (socket close) */
179 if (!memcmp(buf, "HTTP/", 5))
183 printf("len = %d\n", len);
184 fwrite (buf, 1, len, stdout);
185 printf("----------\n");
191 return i; /* do not allow more than 8K HTTP header */
193 if (skip_crlf(buf, len, &i))
195 if (skip_crlf(buf, len, &i))
200 /* inside chunked body .. */
209 for (j = i; j <= i+3; j++)
210 printf ("%c", buf[j]);
214 /* read chunk length */
218 printf ("returning incomplete read at 1\n");
219 printf ("i=%d len=%d\n", i, len);
222 } else if (isdigit(buf[i]))
223 chunk_len = chunk_len * 16 +
225 else if (isupper(buf[i]))
226 chunk_len = chunk_len * 16 +
227 (buf[i++] - ('A'-10));
228 else if (islower(buf[i]))
229 chunk_len = chunk_len * 16 +
230 (buf[i++] - ('a'-10));
242 if (skip_crlf(buf, len, &i))
248 printf ("chunk_len=%d\n", chunk_len);
253 if (!skip_crlf(buf, len, &i))
256 /* consider trailing headers .. */
259 if (skip_crlf(buf, len, &i))
261 if (skip_crlf(buf, len, &i))
268 printf ("returning incomplete read at 2\n");
269 printf ("i=%d len=%d\n", i, len);
274 { /* not chunked ; inside body */
275 if (content_len == -1)
276 return 0; /* no content length */
277 else if (len >= i + content_len)
279 return i + content_len;
284 else if (i < len - 20 &&
285 !strncasecmp((const char *) buf+i, "Transfer-Encoding:", 18))
288 while (buf[i] == ' ')
291 if (!strncasecmp((const char *) buf+i, "chunked", 7))
294 else if (i < len - 17 &&
295 !strncasecmp((const char *)buf+i, "Content-Length:", 15))
298 while (buf[i] == ' ')
301 while (i <= len-4 && isdigit(buf[i]))
302 content_len = content_len*10 + (buf[i++] - '0');
303 if (content_len < 0) /* prevent negative offsets */
315 int cs_complete_auto(const unsigned char *buf, int len)
317 if (len > 5 && buf[0] >= 0x20 && buf[0] < 0x7f
318 && buf[1] >= 0x20 && buf[1] < 0x7f
319 && buf[2] >= 0x20 && buf[2] < 0x7f)
321 int r = cs_complete_http((const char *) buf, len);
324 return completeBER(buf, len);
327 void cs_set_max_recv_bytes(COMSTACK cs, int max_recv_bytes)
329 cs->max_recv_bytes = max_recv_bytes;
335 * indent-tabs-mode: nil
337 * vim: shiftwidth=4 tabstop=8 expandtab