2 * Copyright (C) 1995-2006, Index Data ApS
3 * See the file LICENSE for details.
5 * $Id: comstack.c,v 1.16 2006-08-24 13:25:45 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 #define CHUNK_DEBUG 0
150 int cs_complete_auto(const unsigned char *buf, int len)
152 if (len > 5 && buf[0] >= 0x20 && buf[0] < 0x7f
153 && buf[1] >= 0x20 && buf[1] < 0x7f
154 && buf[2] >= 0x20 && buf[2] < 0x7f)
156 /* deal with HTTP request/response */
157 int i = 2, content_len = 0, chunked = 0;
159 /* if dealing with HTTP responses - then default
160 content length is unlimited (socket close) */
161 if (!memcmp(buf, "HTTP/", 5))
168 return i; /* do not allow more than 8K HTTP header */
170 if (buf[i] == '\r' && buf[i+1] == '\n')
173 if (buf[i] == '\r' && buf[i+1] == '\n')
177 /* inside chunked body .. */
180 int j, chunk_len = 0;
188 for (j = i; j <= i+4; j++)
189 printf ("%c", buf[j]);
193 /* read chunk length */
198 printf ("XXXXXXXX not there yet 1\n");
199 printf ("i=%d len=%d\n", i, len);
202 } else if (isdigit(buf[i]))
203 chunk_len = chunk_len * 16 +
205 else if (isupper(buf[i]))
206 chunk_len = chunk_len * 16 +
207 (buf[i++] - ('A'-10));
208 else if (islower(buf[i]))
209 chunk_len = chunk_len * 16 +
210 (buf[i++] - ('a'-10));
213 /* move forward until CRLF - skip chunk ext */
215 while (buf[i] != '\r' && buf[i+1] != '\n')
218 return 0; /* need more buffer .. */
220 return i; /* enough.. stop */
225 printf ("XXXXXX chunk_len=%d\n", chunk_len);
228 return i+2; /* bad chunk_len */
233 /* consider trailing headers .. */
236 if (buf[i] == '\r' && buf[i+1] == '\n' &&
237 buf[i+2] == '\r' && buf[i+3] == '\n')
244 printf ("XXXXXXXXX not there yet 2\n");
245 printf ("i=%d len=%d\n", i, len);
250 { /* not chunked ; inside body */
251 /* i += 2 seems not to work with GCC -O2 ..
252 so i+2 is used instead .. */
253 if (content_len == -1)
254 return 0; /* no content length */
255 else if (len >= (i+2)+ content_len)
257 return (i+2)+ content_len;
262 else if (i < len - 20 &&
263 !strncasecmp((const char *) buf+i, "Transfer-Encoding:", 18))
266 while (buf[i] == ' ')
269 if (!strncasecmp((const char *) buf+i, "chunked", 7))
272 else if (i < len - 17 &&
273 !strncasecmp((const char *)buf+i, "Content-Length:", 15))
276 while (buf[i] == ' ')
279 while (i <= len-4 && isdigit(buf[i]))
280 content_len = content_len*10 + (buf[i++] - '0');
281 if (content_len < 0) /* prevent negative offsets */
292 return completeBER(buf, len);
295 void cs_set_max_recv_bytes(COMSTACK cs, int max_recv_bytes)
297 cs->max_recv_bytes = max_recv_bytes;
303 * indent-tabs-mode: nil
305 * vim: shiftwidth=4 tabstop=8 expandtab