1 /* This file is part of the YAZ toolkit.
2 * Copyright (C) 1995-2010 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_read_chunk(const char *buf, int i, int len)
213 /* inside chunked body .. */
222 for (j = i; j <= i+3; j++)
223 printf ("%c", buf[j]);
227 /* read chunk length */
231 printf ("returning incomplete read at 1\n");
232 printf ("i=%d len=%d\n", i, len);
235 } else if (isdigit(buf[i]))
236 chunk_len = chunk_len * 16 +
238 else if (isupper(buf[i]))
239 chunk_len = chunk_len * 16 +
240 (buf[i++] - ('A'-10));
241 else if (islower(buf[i]))
242 chunk_len = chunk_len * 16 +
243 (buf[i++] - ('a'-10));
255 if (skip_crlf(buf, len, &i))
261 printf ("chunk_len=%d\n", chunk_len);
266 if (!skip_crlf(buf, len, &i))
269 /* consider trailing headers .. */
272 if (skip_crlf(buf, len, &i))
274 if (skip_crlf(buf, len, &i))
281 printf ("returning incomplete read at 2\n");
282 printf ("i=%d len=%d\n", i, len);
287 static int cs_complete_http(const char *buf, int len, int head_only)
289 /* deal with HTTP request/response */
290 int i = 2, content_len = 0, chunked = 0;
295 /* if dealing with HTTP responses - then default
296 content length is unlimited (socket close) */
297 if (!head_only && !memcmp(buf, "HTTP/", 5))
301 printf("len = %d\n", len);
302 fwrite (buf, 1, len, stdout);
303 printf("----------\n");
309 return i; /* do not allow more than 8K HTTP header */
311 if (skip_crlf(buf, len, &i))
313 if (skip_crlf(buf, len, &i))
317 return cs_read_chunk(buf, i, len);
319 { /* not chunked ; inside body */
320 if (content_len == -1)
321 return 0; /* no content length */
322 else if (len >= i + content_len)
324 return i + content_len;
329 else if (i < len - 20 &&
330 !strncasecmp((const char *) buf+i, "Transfer-Encoding:", 18))
333 while (buf[i] == ' ')
336 if (!strncasecmp((const char *) buf+i, "chunked", 7))
339 else if (i < len - 17 &&
340 !strncasecmp((const char *)buf+i, "Content-Length:", 15))
343 while (buf[i] == ' ')
346 while (i <= len-4 && isdigit(buf[i]))
347 content_len = content_len*10 + (buf[i++] - '0');
348 if (content_len < 0) /* prevent negative offsets */
360 static int cs_complete_auto_x(const char *buf, int len, int head_only)
362 if (len > 5 && buf[0] >= 0x20 && buf[0] < 0x7f
363 && buf[1] >= 0x20 && buf[1] < 0x7f
364 && buf[2] >= 0x20 && buf[2] < 0x7f)
366 int r = cs_complete_http(buf, len, head_only);
369 return completeBER((const unsigned char *) buf, len);
373 int cs_complete_auto(const char *buf, int len)
375 return cs_complete_auto_x(buf, len, 0);
378 int cs_complete_auto_head(const char *buf, int len)
380 return cs_complete_auto_x(buf, len, 1);
383 void cs_set_max_recv_bytes(COMSTACK cs, int max_recv_bytes)
385 cs->max_recv_bytes = max_recv_bytes;
391 * c-file-style: "Stroustrup"
392 * indent-tabs-mode: nil
394 * vim: shiftwidth=4 tabstop=8 expandtab