1 /* This file is part of the YAZ toolkit.
2 * Copyright (C) 1995-2009 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
29 #if HAVE_OPENSSL_SSL_H
33 static const char *cs_errlist[] =
35 "No error or unspecified error",
36 "System (lower-layer) error",
37 "Operation out of state",
38 "No data (operation would block)",
39 "New data while half of old buffer is on the line (flow control)",
42 "Too large incoming buffer"
45 const char *cs_errmsg(int n)
49 if (n < CSNONE || n > CSLASTERROR) {
50 sprintf(buf, "unknown comstack error %d", n);
54 sprintf(buf, "%s: %s", cs_errlist[n], strerror(errno));
60 const char *cs_strerror(COMSTACK h)
62 return cs_errmsg(h->cerrno);
65 void cs_get_host_args(const char *type_and_host, const char **args)
69 if (*type_and_host && strncmp(type_and_host, "unix:", 5))
72 cp = strstr(type_and_host, "://");
83 static int cs_parse_host(const char *uri, const char **host,
84 CS_TYPE *t, enum oid_proto *proto,
88 if (strncmp(uri, "connect:", 8) == 0)
90 const char *cp = strchr(uri, ',');
93 size_t len = cp - (uri + 8);
94 *connect_host = (char *) xmalloc(len+1);
95 memcpy(*connect_host, uri + 8, len);
96 (*connect_host)[len] = '\0';
101 if (strncmp (uri, "tcp:", 4) == 0)
105 *proto = PROTO_Z3950;
107 else if (strncmp (uri, "ssl:", 4) == 0)
112 *proto = PROTO_Z3950;
117 else if (strncmp (uri, "unix:", 5) == 0)
122 *proto = PROTO_Z3950;
127 else if (strncmp(uri, "http:", 5) == 0)
131 while (**host == '/')
135 else if (strncmp(uri, "https:", 6) == 0)
140 while (**host == '/')
149 *proto = PROTO_Z3950;
156 COMSTACK cs_create_host(const char *vhost, int blocking, void **vp)
158 enum oid_proto proto = PROTO_Z3950;
159 const char *host = 0;
162 char *connect_host = 0;
164 cs_parse_host(vhost, &host, &t, &proto, &connect_host);
168 cs = yaz_tcpip_create(-1, blocking, proto, connect_host ? host : 0);
172 cs = cs_create(t, blocking, proto);
176 if (!(*vp = cs_straddr(cs, connect_host ? connect_host : host)))
186 int cs_look (COMSTACK cs)
191 static int skip_crlf(const char *buf, int len, int *i)
195 if (buf[*i] == '\r' && *i < len-1 && buf[*i + 1] == '\n')
200 else if (buf[*i] == '\n')
209 #define CHUNK_DEBUG 0
211 static int cs_complete_http(const char *buf, int len, int head_only)
213 /* deal with HTTP request/response */
214 int i = 2, content_len = 0, chunked = 0;
219 /* if dealing with HTTP responses - then default
220 content length is unlimited (socket close) */
221 if (!head_only && !memcmp(buf, "HTTP/", 5))
225 printf("len = %d\n", len);
226 fwrite (buf, 1, len, stdout);
227 printf("----------\n");
233 return i; /* do not allow more than 8K HTTP header */
235 if (skip_crlf(buf, len, &i))
237 if (skip_crlf(buf, len, &i))
242 /* inside chunked body .. */
251 for (j = i; j <= i+3; j++)
252 printf ("%c", buf[j]);
256 /* read chunk length */
260 printf ("returning incomplete read at 1\n");
261 printf ("i=%d len=%d\n", i, len);
264 } else if (isdigit(buf[i]))
265 chunk_len = chunk_len * 16 +
267 else if (isupper(buf[i]))
268 chunk_len = chunk_len * 16 +
269 (buf[i++] - ('A'-10));
270 else if (islower(buf[i]))
271 chunk_len = chunk_len * 16 +
272 (buf[i++] - ('a'-10));
284 if (skip_crlf(buf, len, &i))
290 printf ("chunk_len=%d\n", chunk_len);
295 if (!skip_crlf(buf, len, &i))
298 /* consider trailing headers .. */
301 if (skip_crlf(buf, len, &i))
303 if (skip_crlf(buf, len, &i))
310 printf ("returning incomplete read at 2\n");
311 printf ("i=%d len=%d\n", i, len);
316 { /* not chunked ; inside body */
317 if (content_len == -1)
318 return 0; /* no content length */
319 else if (len >= i + content_len)
321 return i + content_len;
326 else if (i < len - 20 &&
327 !strncasecmp((const char *) buf+i, "Transfer-Encoding:", 18))
330 while (buf[i] == ' ')
333 if (!strncasecmp((const char *) buf+i, "chunked", 7))
336 else if (i < len - 17 &&
337 !strncasecmp((const char *)buf+i, "Content-Length:", 15))
340 while (buf[i] == ' ')
343 while (i <= len-4 && isdigit(buf[i]))
344 content_len = content_len*10 + (buf[i++] - '0');
345 if (content_len < 0) /* prevent negative offsets */
357 static int cs_complete_auto_x(const char *buf, int len, int head_only)
359 if (len > 5 && buf[0] >= 0x20 && buf[0] < 0x7f
360 && buf[1] >= 0x20 && buf[1] < 0x7f
361 && buf[2] >= 0x20 && buf[2] < 0x7f)
363 int r = cs_complete_http(buf, len, head_only);
366 return completeBER((const unsigned char *) buf, len);
370 int cs_complete_auto(const char *buf, int len)
372 return cs_complete_auto_x(buf, len, 0);
375 int cs_complete_auto_head(const char *buf, int len)
377 return cs_complete_auto_x(buf, len, 1);
380 void cs_set_max_recv_bytes(COMSTACK cs, int max_recv_bytes)
382 cs->max_recv_bytes = max_recv_bytes;
388 * c-file-style: "Stroustrup"
389 * indent-tabs-mode: nil
391 * vim: shiftwidth=4 tabstop=8 expandtab