Make private functions static
[yaz-moved-to-github.git] / comstack / tcpip.c
1 /*
2  * Copyright (c) 1995-2002, Index Data
3  * See the file LICENSE for details.
4  *
5  * $Id: tcpip.c,v 1.51 2002-12-16 13:11:24 adam Exp $
6  */
7
8 #include <stdio.h>
9 #include <string.h>
10 #include <stdlib.h>
11 #ifndef WIN32
12 #include <unistd.h>
13 #endif
14 #include <errno.h>
15 #include <fcntl.h>
16 #include <signal.h>
17 #if HAVE_OPENSSL_SSL_H
18 #include <openssl/ssl.h>
19 #include <openssl/err.h>
20 #endif
21
22 #include <yaz/comstack.h>
23 #include <yaz/tcpip.h>
24 #include <yaz/log.h>
25
26 /* Chas added the following, so we get the definition of completeBER */
27 #include <yaz/odr.h>
28
29 static int tcpip_close(COMSTACK h);
30 static int tcpip_put(COMSTACK h, char *buf, int size);
31 static int tcpip_get(COMSTACK h, char **buf, int *bufsize);
32 static int tcpip_connect(COMSTACK h, void *address);
33 static int tcpip_more(COMSTACK h);
34 static int tcpip_rcvconnect(COMSTACK h);
35 static int tcpip_bind(COMSTACK h, void *address, int mode);
36 static int tcpip_listen(COMSTACK h, char *raddr, int *addrlen,
37                  int (*check_ip)(void *cd, const char *a, int len, int type),
38                  void *cd);
39 static int tcpip_set_blocking(COMSTACK p, int blocking);
40
41 #if HAVE_OPENSSL_SSL_H
42 static int ssl_get(COMSTACK h, char **buf, int *bufsize);
43 static int ssl_put(COMSTACK h, char *buf, int size);
44 #endif
45
46 static COMSTACK tcpip_accept(COMSTACK h);
47 static char *tcpip_addrstr(COMSTACK h);
48 static void *tcpip_straddr(COMSTACK h, const char *str);
49
50 #if 0
51 #define TRC(x) x
52 #else
53 #define TRC(X)
54 #endif
55
56 #ifndef YAZ_SOCKLEN_T
57 #define YAZ_SOCKLEN_T int
58 #endif
59
60 /* this state is used for both SSL and straight TCP/IP */
61 typedef struct tcpip_state
62 {
63     char *altbuf; /* alternate buffer for surplus data */
64     int altsize;  /* size as xmalloced */
65     int altlen;   /* length of data or 0 if none */
66
67     int written;  /* -1 if we aren't writing */
68     int towrite;  /* to verify against user input */
69     int (*complete)(const unsigned char *buf, int len); /* length/comple. */
70     struct sockaddr_in addr;  /* returned by cs_straddr */
71     char buf[128]; /* returned by cs_addrstr */
72 #if HAVE_OPENSSL_SSL_H
73     SSL_CTX *ctx;
74     SSL_CTX *ctx_alloc;
75     SSL *ssl;
76 #endif
77 } tcpip_state;
78
79 #ifdef WIN32
80 static int tcpip_init (void)
81 {
82     static int initialized = 0;
83     if (!initialized)
84     {
85         WORD requested;
86         WSADATA wd;
87
88         requested = MAKEWORD(1, 1);
89         if (WSAStartup(requested, &wd))
90             return 0;
91         initialized = 1;
92     }
93     return 1;
94 }
95 #else
96 static int tcpip_init (void)
97 {
98     return 1;
99 }
100 #endif
101
102 /*
103  * This function is always called through the cs_create() macro.
104  * s >= 0: socket has already been established for us.
105  */
106 COMSTACK tcpip_type(int s, int blocking, int protocol, void *vp)
107 {
108     COMSTACK p;
109     tcpip_state *state;
110     int new_socket;
111 #ifdef WIN32
112     unsigned long tru = 1;
113 #endif
114
115     if (!tcpip_init ())
116         return 0;
117     if (s < 0)
118     {
119         if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0)
120             return 0;
121         new_socket = 1;
122     }
123     else
124         new_socket = 0;
125     if (!(p = (struct comstack *)xmalloc(sizeof(struct comstack))))
126         return 0;
127     if (!(state = (struct tcpip_state *)(p->cprivate =
128                                          xmalloc(sizeof(tcpip_state)))))
129         return 0;
130
131 #ifdef WIN32
132     if (!(p->blocking = blocking) && ioctlsocket(s, FIONBIO, &tru) < 0)
133         return 0;
134 #else
135     if (!(p->blocking = blocking))
136     {   
137         if (fcntl(s, F_SETFL, O_NONBLOCK) < 0)
138             return 0;
139 #ifndef MSG_NOSIGNAL
140         signal (SIGPIPE, SIG_IGN);
141 #endif
142     }
143 #endif
144
145     p->io_pending = 0;
146     p->iofile = s;
147     p->type = tcpip_type;
148     p->protocol = (enum oid_proto) protocol;
149
150     p->f_connect = tcpip_connect;
151     p->f_rcvconnect = tcpip_rcvconnect;
152     p->f_get = tcpip_get;
153     p->f_put = tcpip_put;
154     p->f_close = tcpip_close;
155     p->f_more = tcpip_more;
156     p->f_bind = tcpip_bind;
157     p->f_listen = tcpip_listen;
158     p->f_accept = tcpip_accept;
159     p->f_addrstr = tcpip_addrstr;
160     p->f_straddr = tcpip_straddr;
161     p->f_set_blocking = tcpip_set_blocking;
162
163     p->state = new_socket ? CS_ST_UNBND : CS_ST_IDLE; /* state of line */
164     p->event = CS_NONE;
165     p->cerrno = 0;
166     p->stackerr = 0;
167
168 #if HAVE_OPENSSL_SSL_H
169     state->ctx = state->ctx_alloc = 0;
170     state->ssl = 0;
171 #endif
172
173     state->altbuf = 0;
174     state->altsize = state->altlen = 0;
175     state->towrite = state->written = -1;
176     if (protocol == PROTO_WAIS)
177         state->complete = completeWAIS;
178     else
179         state->complete = completeBER;
180
181     p->timeout = COMSTACK_DEFAULT_TIMEOUT;
182     TRC(fprintf(stderr, "Created new TCPIP comstack\n"));
183
184     return p;
185 }
186
187 #if HAVE_OPENSSL_SSL_H
188
189 COMSTACK ssl_type(int s, int blocking, int protocol, void *vp)
190 {
191     tcpip_state *state;
192     COMSTACK p;
193     yaz_log(LOG_LOG, "ssl_type begin");
194
195     p = tcpip_type (s, blocking, protocol, 0);
196     if (!p)
197         return 0;
198     p->f_get = ssl_get;
199     p->f_put = ssl_put;
200     p->type = ssl_type;
201     state = (tcpip_state *) p->cprivate;
202     if (vp)
203         state->ctx = vp;
204     else
205     {
206         SSL_load_error_strings();
207         SSLeay_add_all_algorithms();
208
209         state->ctx = state->ctx_alloc = SSL_CTX_new (SSLv23_method());
210         if (!state->ctx)
211         {
212             tcpip_close(p);
213             return 0;
214         }
215     }
216     /* note: we don't handle already opened socket in SSL mode - yet */
217     yaz_log(LOG_LOG, "ssl_type end");
218     return p;
219 }
220 #endif
221
222 int tcpip_strtoaddr_ex(const char *str, struct sockaddr_in *add)
223 {
224     struct hostent *hp;
225     char *p, buf[512];
226     short int port = 210;
227     unsigned tmpadd;
228
229     if (!tcpip_init ())
230         return 0;
231     TRC(fprintf(stderr, "tcpip_strtoaddress: %s\n", str ? str : "NULL"));
232     add->sin_family = AF_INET;
233     strncpy(buf, str, 511);
234     buf[511] = 0;
235     if ((p = strchr(buf, '/')))
236         *p = 0;
237     if ((p = strchr(buf, ':')))
238     {
239         *p = 0;
240         port = atoi(p + 1);
241     }
242     add->sin_port = htons(port);
243     if (!strcmp("@", buf))
244         add->sin_addr.s_addr = INADDR_ANY;
245     else if ((hp = gethostbyname(buf)))
246         memcpy(&add->sin_addr.s_addr, *hp->h_addr_list,
247                sizeof(struct in_addr));
248     else if ((tmpadd = (unsigned) inet_addr(buf)) != 0)
249         memcpy(&add->sin_addr.s_addr, &tmpadd, sizeof(struct in_addr));
250     else
251         return 0;
252     return 1;
253 }
254
255 void *tcpip_straddr(COMSTACK h, const char *str)
256 {
257     tcpip_state *sp = (tcpip_state *)h->cprivate;
258
259     if (!tcpip_strtoaddr_ex (str, &sp->addr))
260         return 0;
261     return &sp->addr;
262 }
263
264 struct sockaddr_in *tcpip_strtoaddr(const char *str)
265 {
266     static struct sockaddr_in add;
267     
268     if (!tcpip_strtoaddr_ex (str, &add))
269         return 0;
270     return &add;
271 }
272
273 int tcpip_more(COMSTACK h)
274 {
275     tcpip_state *sp = (tcpip_state *)h->cprivate;
276     
277     return sp->altlen && (*sp->complete)((unsigned char *) sp->altbuf,
278         sp->altlen);
279 }
280
281 /*
282  * connect(2) will block (sometimes) - nothing we can do short of doing
283  * weird things like spawning subprocesses or threading or some weird junk
284  * like that.
285  */
286 int tcpip_connect(COMSTACK h, void *address)
287 {
288     struct sockaddr_in *add = (struct sockaddr_in *)address;
289 #if HAVE_OPENSSL_SSL_H
290     tcpip_state *sp = (tcpip_state *)h->cprivate;
291 #endif
292     int r;
293
294     TRC(fprintf(stderr, "tcpip_connect\n"));
295     h->io_pending = 0;
296     if (h->state != CS_ST_UNBND)
297     {
298         h->cerrno = CSOUTSTATE;
299         return -1;
300     }
301     r = connect(h->iofile, (struct sockaddr *) add, sizeof(*add));
302     if (r < 0)
303     {
304 #ifdef WIN32
305         if (WSAGetLastError() == WSAEWOULDBLOCK)
306         {
307             h->event = CS_CONNECT;
308             h->state = CS_ST_CONNECTING;
309             h->io_pending = CS_WANT_WRITE;
310             return 1;
311         }
312 #else
313         if (yaz_errno() == EINPROGRESS)
314         {
315             h->event = CS_CONNECT;
316             h->state = CS_ST_CONNECTING;
317             h->io_pending = CS_WANT_WRITE|CS_WANT_READ;
318             return 1;
319         }
320 #endif
321         h->cerrno = CSYSERR;
322         return -1;
323     }
324     h->event = CS_CONNECT;
325     h->state = CS_ST_CONNECTING;
326
327     return tcpip_rcvconnect (h);
328 }
329
330 /*
331  * nop
332  */
333 int tcpip_rcvconnect(COMSTACK h)
334 {
335     tcpip_state *sp = (tcpip_state *)h->cprivate;
336     TRC(fprintf(stderr, "tcpip_rcvconnect\n"));
337
338     if (h->state == CS_ST_DATAXFER)
339         return 0;
340     if (h->state != CS_ST_CONNECTING)
341     {
342         h->cerrno = CSOUTSTATE;
343         return -1;
344     }
345 #if HAVE_OPENSSL_SSL_H
346     if (sp->ctx)
347     {
348         int res;
349
350         if (!sp->ssl)
351         {
352             sp->ssl = SSL_new (sp->ctx);
353             SSL_set_fd (sp->ssl, h->iofile);
354         }
355         res = SSL_connect (sp->ssl);
356         if (res <= 0)
357         {
358             int err = SSL_get_error(sp->ssl, res);
359             if (err == SSL_ERROR_WANT_READ)
360             {
361                 h->io_pending = CS_WANT_READ;
362                 return 1;
363             }
364             if (err == SSL_ERROR_WANT_WRITE)
365             {
366                 h->io_pending = CS_WANT_WRITE;
367                 return 1;
368             }
369             h->cerrno = CSERRORSSL;
370             return -1;
371         }
372     }
373 #endif
374     h->event = CS_DATA;
375     h->state = CS_ST_DATAXFER;
376     return 0;
377 }
378
379 #define CERTF "ztest.pem"
380 #define KEYF "ztest.pem"
381
382 int tcpip_bind(COMSTACK h, void *address, int mode)
383 {
384     struct sockaddr *addr = (struct sockaddr *)address;
385 #ifdef WIN32
386     BOOL one = 1;
387 #else
388     unsigned long one = 1;
389 #endif
390
391 #if HAVE_OPENSSL_SSL_H
392     tcpip_state *sp = (tcpip_state *)h->cprivate;
393     if (sp->ctx)
394     {
395         if (sp->ctx_alloc)
396         {
397             int res;
398             res = SSL_CTX_use_certificate_file (sp->ctx, CERTF,
399                                                 SSL_FILETYPE_PEM);
400             if (res <= 0)
401             {
402                 ERR_print_errors_fp(stderr);
403                 exit (2);
404             }
405             res = SSL_CTX_use_PrivateKey_file (sp->ctx, KEYF,
406                                                SSL_FILETYPE_PEM);
407             if (res <= 0)
408             {
409                 ERR_print_errors_fp(stderr);
410                 exit (3);
411             }
412             res = SSL_CTX_check_private_key (sp->ctx);
413             if (res <= 0)
414             {
415                 ERR_print_errors_fp(stderr);
416                 exit(5);
417             }
418         }
419         TRC (fprintf (stderr, "ssl_bind\n"));
420     }
421     else
422     {
423         TRC (fprintf (stderr, "tcpip_bind\n"));
424     }
425 #else
426     TRC (fprintf (stderr, "tcpip_bind\n"));
427 #endif
428 #ifndef WIN32
429     if (setsockopt(h->iofile, SOL_SOCKET, SO_REUSEADDR, (char*) 
430         &one, sizeof(one)) < 0)
431     {
432         h->cerrno = CSYSERR;
433         return -1;
434     }
435 #endif
436     if (bind(h->iofile, addr, sizeof(struct sockaddr_in)))
437     {
438         h->cerrno = CSYSERR;
439         return -1;
440     }
441     if (mode == CS_SERVER && listen(h->iofile, 3) < 0)
442     {
443         h->cerrno = CSYSERR;
444         return -1;
445     }
446     h->state = CS_ST_IDLE;
447     h->event = CS_LISTEN;
448     return 0;
449 }
450
451 int tcpip_listen(COMSTACK h, char *raddr, int *addrlen,
452                  int (*check_ip)(void *cd, const char *a, int len, int t),
453                  void *cd)
454 {
455     struct sockaddr_in addr;
456     YAZ_SOCKLEN_T len = sizeof(addr);
457
458     TRC(fprintf(stderr, "tcpip_listen pid=%d\n", getpid()));
459     if (h->state != CS_ST_IDLE)
460     {
461         h->cerrno = CSOUTSTATE;
462         return -1;
463     }
464     h->newfd = accept(h->iofile, (struct sockaddr*)&addr, &len);
465     if (h->newfd < 0)
466     {
467         if (
468 #ifdef WIN32
469             WSAGetLastError() == WSAEWOULDBLOCK
470 #else
471             yaz_errno() == EWOULDBLOCK 
472 #ifdef EAGAIN
473 #if EAGAIN != EWOULDBLOCK
474             || yaz_errno() == EAGAIN
475 #endif
476 #endif
477 #endif
478             )
479             h->cerrno = CSNODATA;
480         else
481             h->cerrno = CSYSERR;
482         return -1;
483     }
484     if (addrlen && (size_t) (*addrlen) >= sizeof(struct sockaddr_in))
485         memcpy(raddr, &addr, *addrlen = sizeof(struct sockaddr_in));
486     else if (addrlen)
487         *addrlen = 0;
488     if (check_ip && (*check_ip)(cd, (const char *) &addr,
489         sizeof(addr), AF_INET))
490     {
491         h->cerrno = CSDENY;
492 #ifdef WIN32
493         closesocket(h->newfd);
494 #else
495         close(h->newfd);
496 #endif
497         h->newfd = -1;
498         return -1;
499     }
500     h->state = CS_ST_INCON;
501     return 0;
502 }
503
504 COMSTACK tcpip_accept(COMSTACK h)
505 {
506     COMSTACK cnew;
507     tcpip_state *state, *st = (tcpip_state *)h->cprivate;
508 #ifdef WIN32
509     unsigned long tru = 1;
510 #endif
511
512     TRC(fprintf(stderr, "tcpip_accept\n"));
513     if (h->state == CS_ST_INCON)
514     {
515         if (!(cnew = (COMSTACK)xmalloc(sizeof(*cnew))))
516         {
517             h->cerrno = CSYSERR;
518 #ifdef WIN32
519             closesocket(h->newfd);
520 #else
521             close(h->newfd);
522 #endif
523             h->newfd = -1;
524             return 0;
525         }
526         memcpy(cnew, h, sizeof(*h));
527         cnew->iofile = h->newfd;
528         cnew->io_pending = 0;
529         if (!(state = (tcpip_state *)
530               (cnew->cprivate = xmalloc(sizeof(tcpip_state)))))
531         {
532             h->cerrno = CSYSERR;
533             if (h->newfd != -1)
534             {
535 #ifdef WIN32
536                 closesocket(h->newfd);
537 #else
538                 close(h->newfd);
539 #endif
540                 h->newfd = -1;
541             }
542             return 0;
543         }
544         if (!cnew->blocking && 
545 #ifdef WIN32
546             (ioctlsocket(cnew->iofile, FIONBIO, &tru) < 0)
547 #else
548             (!cnew->blocking && fcntl(cnew->iofile, F_SETFL, O_NONBLOCK) < 0)
549 #endif
550             )
551         {
552             h->cerrno = CSYSERR;
553             if (h->newfd != -1)
554             {
555 #ifdef WIN32
556                 closesocket(h->newfd);
557 #else
558                 close(h->newfd);
559 #endif
560                 h->newfd = -1;
561             }
562             xfree (cnew);
563             xfree (state);
564             return 0;
565         }
566         h->newfd = -1;
567         state->altbuf = 0;
568         state->altsize = state->altlen = 0;
569         state->towrite = state->written = -1;
570         state->complete = st->complete;
571         cnew->state = CS_ST_ACCEPT;
572         h->state = CS_ST_IDLE;
573         
574 #if HAVE_OPENSSL_SSL_H
575         state->ctx = st->ctx;
576         state->ctx_alloc = 0;
577         state->ssl = st->ssl;
578         if (state->ctx)
579         {
580             state->ssl = SSL_new (state->ctx);
581             SSL_set_fd (state->ssl, cnew->iofile);
582         }
583 #endif
584         h = cnew;
585     }
586     if (h->state == CS_ST_ACCEPT)
587     {
588 #if HAVE_OPENSSL_SSL_H
589         tcpip_state *state = (tcpip_state *)h->cprivate;
590         if (state->ctx)
591         {
592             int res = SSL_accept (state->ssl);
593             TRC(fprintf(stderr, "SSL_accept\n"));
594             if (res <= 0)
595             {
596                 int err = SSL_get_error(state->ssl, res);
597                 if (err == SSL_ERROR_WANT_READ)
598                 {
599                     h->io_pending = CS_WANT_READ;
600                     return h;
601                 }
602                 if (err == SSL_ERROR_WANT_WRITE)
603                 {
604                     h->io_pending = CS_WANT_WRITE;
605                     return h;
606                 }
607                 cs_close (h);
608                 return 0;
609             }
610         }
611 #endif
612     }
613     else
614     {
615         h->cerrno = CSOUTSTATE;
616         return 0;
617     }
618     h->io_pending = 0;
619     h->state = CS_ST_DATAXFER;
620     h->event = CS_DATA;
621     return h;
622 }
623
624 #define CS_TCPIP_BUFCHUNK 4096
625
626 /*
627  * Return: -1 error, >1 good, len of buffer, ==1 incomplete buffer,
628  * 0=connection closed.
629  */
630 int tcpip_get(COMSTACK h, char **buf, int *bufsize)
631 {
632     tcpip_state *sp = (tcpip_state *)h->cprivate;
633     char *tmpc;
634     int tmpi, berlen, rest, req, tomove;
635     int hasread = 0, res;
636
637     TRC(fprintf(stderr, "tcpip_get: bufsize=%d\n", *bufsize));
638     if (sp->altlen) /* switch buffers */
639     {
640         TRC(fprintf(stderr, "  %d bytes in altbuf (0x%x)\n", sp->altlen,
641             (unsigned) sp->altbuf));
642         tmpc = *buf;
643         tmpi = *bufsize;
644         *buf = sp->altbuf;
645         *bufsize = sp->altsize;
646         hasread = sp->altlen;
647         sp->altlen = 0;
648         sp->altbuf = tmpc;
649         sp->altsize = tmpi;
650     }
651     h->io_pending = 0;
652     while (!(berlen = (*sp->complete)((unsigned char *)*buf, hasread)))
653     {
654         if (!*bufsize)
655         {
656             if (!(*buf = (char *)xmalloc(*bufsize = CS_TCPIP_BUFCHUNK)))
657                 return -1;
658         }
659         else if (*bufsize - hasread < CS_TCPIP_BUFCHUNK)
660             if (!(*buf =(char *)xrealloc(*buf, *bufsize *= 2)))
661                 return -1;
662         res = recv(h->iofile, *buf + hasread, CS_TCPIP_BUFCHUNK, 0);
663         TRC(fprintf(stderr, "  recv res=%d, hasread=%d\n", res, hasread));
664         if (res < 0)
665         {
666 #ifdef WIN32
667             if (WSAGetLastError() == WSAEWOULDBLOCK)
668             {
669                 h->io_pending = CS_WANT_READ;
670                 break;
671             }
672             else
673                 return -1;
674 #else
675             if (yaz_errno() == EWOULDBLOCK 
676 #ifdef EAGAIN   
677 #if EAGAIN != EWOULDBLOCK
678                 || yaz_errno() == EAGAIN
679 #endif
680 #endif
681                 || yaz_errno() == EINPROGRESS
682 #ifdef __sun__
683                 || yaz_errno() == ENOENT /* Sun's sometimes set errno to this */
684 #endif
685                 )
686             {
687                 h->io_pending = CS_WANT_READ;
688                 break;
689             }
690             else if (yaz_errno() == 0)
691                 continue;
692             else
693                 return -1;
694 #endif
695         }
696         else if (!res)
697             return 0;
698         hasread += res;
699     }
700     TRC (fprintf (stderr, "  Out of read loop with hasread=%d, berlen=%d\n",
701                   hasread, berlen));
702     /* move surplus buffer (or everything if we didn't get a BER rec.) */
703     if (hasread > berlen)
704     {
705         tomove = req = hasread - berlen;
706         rest = tomove % CS_TCPIP_BUFCHUNK;
707         if (rest)
708             req += CS_TCPIP_BUFCHUNK - rest;
709         if (!sp->altbuf)
710         {
711             if (!(sp->altbuf = (char *)xmalloc(sp->altsize = req)))
712                 return -1;
713         } else if (sp->altsize < req)
714             if (!(sp->altbuf =(char *)xrealloc(sp->altbuf, sp->altsize = req)))
715                 return -1;
716         TRC(fprintf(stderr, "  Moving %d bytes to altbuf(0x%x)\n", tomove,
717             (unsigned) sp->altbuf));
718         memcpy(sp->altbuf, *buf + berlen, sp->altlen = tomove);
719     }
720     if (berlen < CS_TCPIP_BUFCHUNK - 1)
721         *(*buf + berlen) = '\0';
722     return berlen ? berlen : 1;
723 }
724
725
726 #if HAVE_OPENSSL_SSL_H
727 /*
728  * Return: -1 error, >1 good, len of buffer, ==1 incomplete buffer,
729  * 0=connection closed.
730  */
731 int ssl_get(COMSTACK h, char **buf, int *bufsize)
732 {
733     tcpip_state *sp = (tcpip_state *)h->cprivate;
734     char *tmpc;
735     int tmpi, berlen, rest, req, tomove;
736     int hasread = 0, res;
737
738     TRC(fprintf(stderr, "ssl_get: bufsize=%d\n", *bufsize));
739     if (sp->altlen) /* switch buffers */
740     {
741         TRC(fprintf(stderr, "  %d bytes in altbuf (0x%x)\n", sp->altlen,
742             (unsigned) sp->altbuf));
743         tmpc = *buf;
744         tmpi = *bufsize;
745         *buf = sp->altbuf;
746         *bufsize = sp->altsize;
747         hasread = sp->altlen;
748         sp->altlen = 0;
749         sp->altbuf = tmpc;
750         sp->altsize = tmpi;
751     }
752     h->io_pending = 0;
753     while (!(berlen = (*sp->complete)((unsigned char *)*buf, hasread)))
754     {
755         if (!*bufsize)
756         {
757             if (!(*buf = (char *)xmalloc(*bufsize = CS_TCPIP_BUFCHUNK)))
758                 return -1;
759         }
760         else if (*bufsize - hasread < CS_TCPIP_BUFCHUNK)
761             if (!(*buf =(char *)xrealloc(*buf, *bufsize *= 2)))
762                 return -1;
763         res = SSL_read (sp->ssl, *buf + hasread, CS_TCPIP_BUFCHUNK);
764         TRC(fprintf(stderr, "  SSL_read res=%d, hasread=%d\n", res, hasread));
765         if (res <= 0)
766         {
767             int ssl_err = SSL_get_error(sp->ssl, res);
768             if (ssl_err == SSL_ERROR_WANT_READ)
769             {
770                 h->io_pending = CS_WANT_READ;
771                 break;
772             }
773             if (ssl_err == SSL_ERROR_WANT_WRITE)
774             {
775                 h->io_pending = CS_WANT_WRITE;
776                 break;
777             }
778             if (res == 0)
779                 return 0;
780             h->cerrno = CSERRORSSL;
781             return -1;
782         }
783         hasread += res;
784     }
785     TRC (fprintf (stderr, "  Out of read loop with hasread=%d, berlen=%d\n",
786         hasread, berlen));
787     /* move surplus buffer (or everything if we didn't get a BER rec.) */
788     if (hasread > berlen)
789     {
790         tomove = req = hasread - berlen;
791         rest = tomove % CS_TCPIP_BUFCHUNK;
792         if (rest)
793             req += CS_TCPIP_BUFCHUNK - rest;
794         if (!sp->altbuf)
795         {
796             if (!(sp->altbuf = (char *)xmalloc(sp->altsize = req)))
797                 return -1;
798         } else if (sp->altsize < req)
799             if (!(sp->altbuf =(char *)xrealloc(sp->altbuf, sp->altsize = req)))
800                 return -1;
801         TRC(fprintf(stderr, "  Moving %d bytes to altbuf(0x%x)\n", tomove,
802             (unsigned) sp->altbuf));
803         memcpy(sp->altbuf, *buf + berlen, sp->altlen = tomove);
804     }
805     if (berlen < CS_TCPIP_BUFCHUNK - 1)
806         *(*buf + berlen) = '\0';
807     return berlen ? berlen : 1;
808 }
809 #endif
810
811 /*
812  * Returns 1, 0 or -1
813  * In nonblocking mode, you must call again with same buffer while
814  * return value is 1.
815  */
816 int tcpip_put(COMSTACK h, char *buf, int size)
817 {
818     int res;
819     struct tcpip_state *state = (struct tcpip_state *)h->cprivate;
820
821     TRC(fprintf(stderr, "tcpip_put: size=%d\n", size));
822     h->io_pending = 0;
823     h->event = CS_DATA;
824     if (state->towrite < 0)
825     {
826         state->towrite = size;
827         state->written = 0;
828     }
829     else if (state->towrite != size)
830     {
831         h->cerrno = CSWRONGBUF;
832         return -1;
833     }
834     while (state->towrite > state->written)
835     {
836         if ((res =
837              send(h->iofile, buf + state->written, size -
838                   state->written, 
839 #ifdef MSG_NOSIGNAL
840                   MSG_NOSIGNAL
841 #else
842                   0
843 #endif
844                  )) < 0)
845         {
846             if (
847 #ifdef WIN32
848                 WSAGetLastError() == WSAEWOULDBLOCK
849 #else
850                 yaz_errno() == EWOULDBLOCK 
851 #ifdef EAGAIN
852 #if EAGAIN != EWOULDBLOCK
853              || yaz_errno() == EAGAIN
854 #endif
855 #endif
856 #endif
857                 )
858             {
859                 TRC(fprintf(stderr, "  Flow control stop\n"));
860                 h->io_pending = CS_WANT_WRITE;
861                 return 1;
862             }
863             h->cerrno = CSYSERR;
864             return -1;
865         }
866         state->written += res;
867         TRC(fprintf(stderr, "  Wrote %d, written=%d, nbytes=%d\n",
868                     res, state->written, size));
869     }
870     state->towrite = state->written = -1;
871     TRC(fprintf(stderr, "  Ok\n"));
872     return 0;
873 }
874
875
876 #if HAVE_OPENSSL_SSL_H
877 /*
878  * Returns 1, 0 or -1
879  * In nonblocking mode, you must call again with same buffer while
880  * return value is 1.
881  */
882 int ssl_put(COMSTACK h, char *buf, int size)
883 {
884     int res;
885     struct tcpip_state *state = (struct tcpip_state *)h->cprivate;
886
887     TRC(fprintf(stderr, "ssl_put: size=%d\n", size));
888     h->io_pending = 0;
889     h->event = CS_DATA;
890     if (state->towrite < 0)
891     {
892         state->towrite = size;
893         state->written = 0;
894     }
895     else if (state->towrite != size)
896     {
897         h->cerrno = CSWRONGBUF;
898         return -1;
899     }
900     while (state->towrite > state->written)
901     {
902         res = SSL_write (state->ssl, buf + state->written,
903                          size - state->written);
904         if (res <= 0)
905         {
906             int ssl_err = SSL_get_error(state->ssl, res);
907             if (ssl_err == SSL_ERROR_WANT_READ)
908             {
909                 h->io_pending = CS_WANT_READ;
910                 return 1;
911             }
912             if (ssl_err == SSL_ERROR_WANT_WRITE)
913             {
914                 h->io_pending = CS_WANT_WRITE;
915                 return 1;
916             }
917             h->cerrno = CSERRORSSL;
918             return -1;
919         }
920         state->written += res;
921         TRC(fprintf(stderr, "  Wrote %d, written=%d, nbytes=%d\n",
922                     res, state->written, size));
923     }
924     state->towrite = state->written = -1;
925     TRC(fprintf(stderr, "  Ok\n"));
926     return 0;
927 }
928 #endif
929
930 int tcpip_close(COMSTACK h)
931 {
932     tcpip_state *sp = (struct tcpip_state *)h->cprivate;
933
934     TRC(fprintf(stderr, "tcpip_close\n"));
935     if (h->iofile != -1)
936     {
937 #if HAVE_OPENSSL_SSL_H
938         if (sp->ssl)
939         {
940             SSL_shutdown (sp->ssl);
941         }
942 #endif
943 #ifdef WIN32
944         closesocket(h->iofile);
945 #else
946         close(h->iofile);
947 #endif
948     }
949     if (sp->altbuf)
950         xfree(sp->altbuf);
951 #if HAVE_OPENSSL_SSL_H
952     if (sp->ssl)
953     {
954         TRC (fprintf(stderr, "SSL_free\n"));
955         SSL_free (sp->ssl);
956     }
957     sp->ssl = 0;
958     if (sp->ctx_alloc)
959         SSL_CTX_free (sp->ctx_alloc);
960 #endif
961     xfree(sp);
962     xfree(h);
963     return 0;
964 }
965
966 char *tcpip_addrstr(COMSTACK h)
967 {
968     struct sockaddr_in addr;
969     tcpip_state *sp = (struct tcpip_state *)h->cprivate;
970     char *r, *buf = sp->buf;
971     YAZ_SOCKLEN_T len;
972     struct hostent *host;
973     
974     len = sizeof(addr);
975     if (getpeername(h->iofile, (struct sockaddr*) &addr, &len) < 0)
976     {
977         h->cerrno = CSYSERR;
978         return 0;
979     }
980     if ((host = gethostbyaddr((char*)&addr.sin_addr, sizeof(addr.sin_addr),
981                               AF_INET)))
982         r = (char*) host->h_name;
983     else
984         r = inet_ntoa(addr.sin_addr);
985     sprintf(buf, "tcp:%s", r);
986 #if HAVE_OPENSSL_SSL_H
987     if (sp->ctx)
988         sprintf(buf, "ssl:%s", r);
989 #endif
990     return buf;
991 }
992
993 int static tcpip_set_blocking(COMSTACK p, int blocking)
994 {
995     unsigned long flag;
996     
997     if (p->blocking == blocking)
998         return 1;
999 #ifdef WIN32
1000     flag = 1;
1001     if (ioctlsocket(p->iofile, FIONBIO, &flag) < 0)
1002         return 0;
1003 #else
1004     flag = fcntl(p->iofile, F_GETFL, 0);
1005     if(!blocking)
1006         flag = flag & ~O_NONBLOCK;
1007     else
1008         flag = flag | O_NONBLOCK;
1009     if (fcntl(p->iofile, F_SETFL, flag) < 0)
1010         return 0;
1011 #endif
1012     p->blocking = blocking;
1013     return 1;
1014 }