No more @-tag for MARC
[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.46 2002-02-19 20:02:40 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 int tcpip_close(COMSTACK h);
30 int tcpip_put(COMSTACK h, char *buf, int size);
31 int tcpip_get(COMSTACK h, char **buf, int *bufsize);
32 int tcpip_connect(COMSTACK h, void *address);
33 int tcpip_more(COMSTACK h);
34 int tcpip_rcvconnect(COMSTACK h);
35 int tcpip_bind(COMSTACK h, void *address, int mode);
36 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 int static tcpip_set_blocking(COMSTACK p, int blocking);
40
41 #if HAVE_OPENSSL_SSL_H
42 int ssl_get(COMSTACK h, char **buf, int *bufsize);
43 int ssl_put(COMSTACK h, char *buf, int size);
44 #endif
45
46 COMSTACK tcpip_accept(COMSTACK h);
47 char *tcpip_addrstr(COMSTACK h);
48 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 /* this state is used for both SSL and straight TCP/IP */
57 typedef struct tcpip_state
58 {
59     char *altbuf; /* alternate buffer for surplus data */
60     int altsize;  /* size as xmalloced */
61     int altlen;   /* length of data or 0 if none */
62
63     int written;  /* -1 if we aren't writing */
64     int towrite;  /* to verify against user input */
65     int (*complete)(const unsigned char *buf, int len); /* length/comple. */
66     struct sockaddr_in addr;  /* returned by cs_straddr */
67     char buf[128]; /* returned by cs_addrstr */
68 #if HAVE_OPENSSL_SSL_H
69     SSL_CTX *ctx;
70     SSL_CTX *ctx_alloc;
71     SSL *ssl;
72 #endif
73 } tcpip_state;
74
75 #ifdef WIN32
76 static int tcpip_init (void)
77 {
78     static int initialized = 0;
79     if (!initialized)
80     {
81         WORD requested;
82         WSADATA wd;
83
84         requested = MAKEWORD(1, 1);
85         if (WSAStartup(requested, &wd))
86             return 0;
87         initialized = 1;
88     }
89     return 1;
90 }
91 #else
92 static int tcpip_init (void)
93 {
94     return 1;
95 }
96 #endif
97
98 /*
99  * This function is always called through the cs_create() macro.
100  * s >= 0: socket has already been established for us.
101  */
102 COMSTACK tcpip_type(int s, int blocking, int protocol, void *vp)
103 {
104     COMSTACK p;
105     tcpip_state *state;
106     int new_socket;
107 #ifdef WIN32
108     unsigned long tru = 1;
109 #endif
110
111     if (!tcpip_init ())
112         return 0;
113     if (s < 0)
114     {
115         if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0)
116             return 0;
117         new_socket = 1;
118     }
119     else
120         new_socket = 0;
121     if (!(p = (struct comstack *)xmalloc(sizeof(struct comstack))))
122         return 0;
123     if (!(state = (struct tcpip_state *)(p->cprivate =
124                                          xmalloc(sizeof(tcpip_state)))))
125         return 0;
126
127 #ifdef WIN32
128     if (!(p->blocking = blocking) && ioctlsocket(s, FIONBIO, &tru) < 0)
129         return 0;
130 #else
131     if (!(p->blocking = blocking))
132     {   
133         if (fcntl(s, F_SETFL, O_NONBLOCK) < 0)
134             return 0;
135 #ifndef MSG_NOSIGNAL
136         signal (SIGPIPE, SIG_IGN);
137 #endif
138     }
139 #endif
140
141     p->io_pending = 0;
142     p->iofile = s;
143     p->type = tcpip_type;
144     p->protocol = (enum oid_proto) protocol;
145
146     p->f_connect = tcpip_connect;
147     p->f_rcvconnect = tcpip_rcvconnect;
148     p->f_get = tcpip_get;
149     p->f_put = tcpip_put;
150     p->f_close = tcpip_close;
151     p->f_more = tcpip_more;
152     p->f_bind = tcpip_bind;
153     p->f_listen = tcpip_listen;
154     p->f_accept = tcpip_accept;
155     p->f_addrstr = tcpip_addrstr;
156     p->f_straddr = tcpip_straddr;
157     p->f_set_blocking = tcpip_set_blocking;
158
159     p->state = new_socket ? CS_ST_UNBND : CS_ST_IDLE; /* state of line */
160     p->event = CS_NONE;
161     p->cerrno = 0;
162     p->stackerr = 0;
163
164 #if HAVE_OPENSSL_SSL_H
165     state->ctx = state->ctx_alloc = 0;
166     state->ssl = 0;
167 #endif
168
169     state->altbuf = 0;
170     state->altsize = state->altlen = 0;
171     state->towrite = state->written = -1;
172     if (protocol == PROTO_WAIS)
173         state->complete = completeWAIS;
174     else
175         state->complete = completeBER;
176
177     p->timeout = COMSTACK_DEFAULT_TIMEOUT;
178     TRC(fprintf(stderr, "Created new TCPIP comstack\n"));
179
180     return p;
181 }
182
183 #if HAVE_OPENSSL_SSL_H
184
185 COMSTACK ssl_type(int s, int blocking, int protocol, void *vp)
186 {
187     tcpip_state *state;
188     COMSTACK p;
189     yaz_log(LOG_LOG, "ssl_type begin");
190
191     p = tcpip_type (s, blocking, protocol, 0);
192     if (!p)
193         return 0;
194     p->f_get = ssl_get;
195     p->f_put = ssl_put;
196     p->type = ssl_type;
197     state = (tcpip_state *) p->cprivate;
198     if (vp)
199         state->ctx = vp;
200     else
201     {
202         SSL_load_error_strings();
203         SSLeay_add_all_algorithms();
204
205         state->ctx = state->ctx_alloc = SSL_CTX_new (SSLv23_method());
206         if (!state->ctx)
207         {
208             tcpip_close(p);
209             return 0;
210         }
211     }
212     /* note: we don't handle already opened socket in SSL mode - yet */
213     yaz_log(LOG_LOG, "ssl_type end");
214     return p;
215 }
216 #endif
217
218 int tcpip_strtoaddr_ex(const char *str, struct sockaddr_in *add)
219 {
220     struct hostent *hp;
221     char *p, buf[512];
222     short int port = 210;
223     unsigned tmpadd;
224
225     if (!tcpip_init ())
226         return 0;
227     TRC(fprintf(stderr, "tcpip_strtoaddress: %s\n", str ? str : "NULL"));
228     add->sin_family = AF_INET;
229     strncpy(buf, str, 511);
230     buf[511] = 0;
231     if ((p = strchr(buf, '/')))
232         *p = 0;
233     if ((p = strchr(buf, ':')))
234     {
235         *p = 0;
236         port = atoi(p + 1);
237     }
238     add->sin_port = htons(port);
239     if (!strcmp("@", buf))
240         add->sin_addr.s_addr = INADDR_ANY;
241     else if ((hp = gethostbyname(buf)))
242         memcpy(&add->sin_addr.s_addr, *hp->h_addr_list,
243                sizeof(struct in_addr));
244     else if ((tmpadd = (unsigned) inet_addr(buf)) != 0)
245         memcpy(&add->sin_addr.s_addr, &tmpadd, sizeof(struct in_addr));
246     else
247         return 0;
248     return 1;
249 }
250
251 void *tcpip_straddr(COMSTACK h, const char *str)
252 {
253     tcpip_state *sp = (tcpip_state *)h->cprivate;
254
255     if (!tcpip_strtoaddr_ex (str, &sp->addr))
256         return 0;
257     return &sp->addr;
258 }
259
260 struct sockaddr_in *tcpip_strtoaddr(const char *str)
261 {
262     static struct sockaddr_in add;
263     
264     if (!tcpip_strtoaddr_ex (str, &add))
265         return 0;
266     return &add;
267 }
268
269 int tcpip_more(COMSTACK h)
270 {
271     tcpip_state *sp = (tcpip_state *)h->cprivate;
272     
273     return sp->altlen && (*sp->complete)((unsigned char *) sp->altbuf,
274         sp->altlen);
275 }
276
277 /*
278  * connect(2) will block (sometimes) - nothing we can do short of doing
279  * weird things like spawning subprocesses or threading or some weird junk
280  * like that.
281  */
282 int tcpip_connect(COMSTACK h, void *address)
283 {
284     struct sockaddr_in *add = (struct sockaddr_in *)address;
285 #if HAVE_OPENSSL_SSL_H
286     tcpip_state *sp = (tcpip_state *)h->cprivate;
287 #endif
288     int r;
289
290     TRC(fprintf(stderr, "tcpip_connect\n"));
291     h->io_pending = 0;
292     if (h->state != CS_ST_UNBND)
293     {
294         h->cerrno = CSOUTSTATE;
295         return -1;
296     }
297     r = connect(h->iofile, (struct sockaddr *) add, sizeof(*add));
298     if (r < 0)
299     {
300 #ifdef WIN32
301         if (WSAGetLastError() == WSAEWOULDBLOCK)
302         {
303             h->event = CS_CONNECT;
304             h->state = CS_ST_CONNECTING;
305             h->io_pending = CS_WANT_WRITE;
306             return 1;
307         }
308 #else
309         if (errno == EINPROGRESS)
310         {
311             h->event = CS_CONNECT;
312             h->state = CS_ST_CONNECTING;
313             h->io_pending = CS_WANT_WRITE|CS_WANT_READ;
314             return 1;
315         }
316 #endif
317         h->cerrno = CSYSERR;
318         return -1;
319     }
320     h->event = CS_CONNECT;
321     h->state = CS_ST_CONNECTING;
322
323     return tcpip_rcvconnect (h);
324 }
325
326 /*
327  * nop
328  */
329 int tcpip_rcvconnect(COMSTACK h)
330 {
331     tcpip_state *sp = (tcpip_state *)h->cprivate;
332     TRC(fprintf(stderr, "tcpip_rcvconnect\n"));
333
334     if (h->state == CS_ST_DATAXFER)
335         return 0;
336     if (h->state != CS_ST_CONNECTING)
337     {
338         h->cerrno = CSOUTSTATE;
339         return -1;
340     }
341 #if HAVE_OPENSSL_SSL_H
342     if (sp->ctx)
343     {
344         int res;
345
346         if (!sp->ssl)
347         {
348             sp->ssl = SSL_new (sp->ctx);
349             SSL_set_fd (sp->ssl, h->iofile);
350         }
351         res = SSL_connect (sp->ssl);
352         if (res <= 0)
353         {
354             int err = SSL_get_error(sp->ssl, res);
355             if (err == SSL_ERROR_WANT_READ)
356             {
357                 h->io_pending = CS_WANT_READ;
358                 return 1;
359             }
360             if (err == SSL_ERROR_WANT_WRITE)
361             {
362                 h->io_pending = CS_WANT_WRITE;
363                 return 1;
364             }
365             h->cerrno = CSERRORSSL;
366             return -1;
367         }
368     }
369 #endif
370     h->event = CS_DATA;
371     h->state = CS_ST_DATAXFER;
372     return 0;
373 }
374
375 #define CERTF "ztest.pem"
376 #define KEYF "ztest.pem"
377
378 int tcpip_bind(COMSTACK h, void *address, int mode)
379 {
380     struct sockaddr *addr = (struct sockaddr *)address;
381 #ifdef WIN32
382     BOOL one = 1;
383 #else
384     unsigned long one = 1;
385 #endif
386
387 #if HAVE_OPENSSL_SSL_H
388     tcpip_state *sp = (tcpip_state *)h->cprivate;
389     if (sp->ctx)
390     {
391         if (sp->ctx_alloc)
392         {
393             int res;
394             res = SSL_CTX_use_certificate_file (sp->ctx, CERTF,
395                                                 SSL_FILETYPE_PEM);
396             if (res <= 0)
397             {
398                 ERR_print_errors_fp(stderr);
399                 exit (2);
400             }
401             res = SSL_CTX_use_PrivateKey_file (sp->ctx, KEYF,
402                                                SSL_FILETYPE_PEM);
403             if (res <= 0)
404             {
405                 ERR_print_errors_fp(stderr);
406                 exit (3);
407             }
408             res = SSL_CTX_check_private_key (sp->ctx);
409             if (res <= 0)
410             {
411                 ERR_print_errors_fp(stderr);
412                 exit(5);
413             }
414         }
415         TRC (fprintf (stderr, "ssl_bind\n"));
416     }
417     else
418     {
419         TRC (fprintf (stderr, "tcpip_bind\n"));
420     }
421 #else
422     TRC (fprintf (stderr, "tcpip_bind\n"));
423 #endif
424 #ifndef WIN32
425     if (setsockopt(h->iofile, SOL_SOCKET, SO_REUSEADDR, (char*) 
426         &one, sizeof(one)) < 0)
427     {
428         h->cerrno = CSYSERR;
429         return -1;
430     }
431 #endif
432     if (bind(h->iofile, addr, sizeof(struct sockaddr_in)))
433     {
434         h->cerrno = CSYSERR;
435         return -1;
436     }
437     if (mode == CS_SERVER && listen(h->iofile, 3) < 0)
438     {
439         h->cerrno = CSYSERR;
440         return -1;
441     }
442     h->state = CS_ST_IDLE;
443     h->event = CS_LISTEN;
444     return 0;
445 }
446
447 int tcpip_listen(COMSTACK h, char *raddr, int *addrlen,
448                  int (*check_ip)(void *cd, const char *a, int len, int t),
449                  void *cd)
450 {
451     struct sockaddr_in addr;
452 #ifdef __cplusplus
453     socklen_t len = sizeof(addr);
454 #else
455     int len = sizeof(addr);
456 #endif
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             errno == EWOULDBLOCK 
472 #ifdef EAGAIN
473 #if EAGAIN != EWOULDBLOCK
474             || 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 (errno == EWOULDBLOCK 
676 #ifdef EAGAIN   
677 #if EAGAIN != EWOULDBLOCK
678                 || errno == EAGAIN
679 #endif
680 #endif
681                 || errno == EINPROGRESS
682                 )
683             {
684                 h->io_pending = CS_WANT_READ;
685                 break;
686             }
687             else if (errno == 0)
688                 continue;
689             else
690                 return -1;
691 #endif
692         }
693         else if (!res)
694             return 0;
695         hasread += res;
696     }
697     TRC (fprintf (stderr, "  Out of read loop with hasread=%d, berlen=%d\n",
698                   hasread, berlen));
699     /* move surplus buffer (or everything if we didn't get a BER rec.) */
700     if (hasread > berlen)
701     {
702         tomove = req = hasread - berlen;
703         rest = tomove % CS_TCPIP_BUFCHUNK;
704         if (rest)
705             req += CS_TCPIP_BUFCHUNK - rest;
706         if (!sp->altbuf)
707         {
708             if (!(sp->altbuf = (char *)xmalloc(sp->altsize = req)))
709                 return -1;
710         } else if (sp->altsize < req)
711             if (!(sp->altbuf =(char *)xrealloc(sp->altbuf, sp->altsize = req)))
712                 return -1;
713         TRC(fprintf(stderr, "  Moving %d bytes to altbuf(0x%x)\n", tomove,
714             (unsigned) sp->altbuf));
715         memcpy(sp->altbuf, *buf + berlen, sp->altlen = tomove);
716     }
717     if (berlen < CS_TCPIP_BUFCHUNK - 1)
718         *(*buf + berlen) = '\0';
719     return berlen ? berlen : 1;
720 }
721
722
723 #if HAVE_OPENSSL_SSL_H
724 /*
725  * Return: -1 error, >1 good, len of buffer, ==1 incomplete buffer,
726  * 0=connection closed.
727  */
728 int ssl_get(COMSTACK h, char **buf, int *bufsize)
729 {
730     tcpip_state *sp = (tcpip_state *)h->cprivate;
731     char *tmpc;
732     int tmpi, berlen, rest, req, tomove;
733     int hasread = 0, res;
734
735     TRC(fprintf(stderr, "ssl_get: bufsize=%d\n", *bufsize));
736     if (sp->altlen) /* switch buffers */
737     {
738         TRC(fprintf(stderr, "  %d bytes in altbuf (0x%x)\n", sp->altlen,
739             (unsigned) sp->altbuf));
740         tmpc = *buf;
741         tmpi = *bufsize;
742         *buf = sp->altbuf;
743         *bufsize = sp->altsize;
744         hasread = sp->altlen;
745         sp->altlen = 0;
746         sp->altbuf = tmpc;
747         sp->altsize = tmpi;
748     }
749     h->io_pending = 0;
750     while (!(berlen = (*sp->complete)((unsigned char *)*buf, hasread)))
751     {
752         if (!*bufsize)
753         {
754             if (!(*buf = (char *)xmalloc(*bufsize = CS_TCPIP_BUFCHUNK)))
755                 return -1;
756         }
757         else if (*bufsize - hasread < CS_TCPIP_BUFCHUNK)
758             if (!(*buf =(char *)xrealloc(*buf, *bufsize *= 2)))
759                 return -1;
760         res = SSL_read (sp->ssl, *buf + hasread, CS_TCPIP_BUFCHUNK);
761         TRC(fprintf(stderr, "  SSL_read res=%d, hasread=%d\n", res, hasread));
762         if (res <= 0)
763         {
764             int ssl_err = SSL_get_error(sp->ssl, res);
765             if (ssl_err == SSL_ERROR_WANT_READ)
766             {
767                 h->io_pending = CS_WANT_READ;
768                 break;
769             }
770             if (ssl_err == SSL_ERROR_WANT_WRITE)
771             {
772                 h->io_pending = CS_WANT_WRITE;
773                 break;
774             }
775             if (res == 0)
776                 return 0;
777             h->cerrno = CSERRORSSL;
778             return -1;
779         }
780         hasread += res;
781     }
782     TRC (fprintf (stderr, "  Out of read loop with hasread=%d, berlen=%d\n",
783         hasread, berlen));
784     /* move surplus buffer (or everything if we didn't get a BER rec.) */
785     if (hasread > berlen)
786     {
787         tomove = req = hasread - berlen;
788         rest = tomove % CS_TCPIP_BUFCHUNK;
789         if (rest)
790             req += CS_TCPIP_BUFCHUNK - rest;
791         if (!sp->altbuf)
792         {
793             if (!(sp->altbuf = (char *)xmalloc(sp->altsize = req)))
794                 return -1;
795         } else if (sp->altsize < req)
796             if (!(sp->altbuf =(char *)xrealloc(sp->altbuf, sp->altsize = req)))
797                 return -1;
798         TRC(fprintf(stderr, "  Moving %d bytes to altbuf(0x%x)\n", tomove,
799             (unsigned) sp->altbuf));
800         memcpy(sp->altbuf, *buf + berlen, sp->altlen = tomove);
801     }
802     if (berlen < CS_TCPIP_BUFCHUNK - 1)
803         *(*buf + berlen) = '\0';
804     return berlen ? berlen : 1;
805 }
806 #endif
807
808 /*
809  * Returns 1, 0 or -1
810  * In nonblocking mode, you must call again with same buffer while
811  * return value is 1.
812  */
813 int tcpip_put(COMSTACK h, char *buf, int size)
814 {
815     int res;
816     struct tcpip_state *state = (struct tcpip_state *)h->cprivate;
817
818     TRC(fprintf(stderr, "tcpip_put: size=%d\n", size));
819     h->io_pending = 0;
820     h->event = CS_DATA;
821     if (state->towrite < 0)
822     {
823         state->towrite = size;
824         state->written = 0;
825     }
826     else if (state->towrite != size)
827     {
828         h->cerrno = CSWRONGBUF;
829         return -1;
830     }
831     while (state->towrite > state->written)
832     {
833         if ((res =
834              send(h->iofile, buf + state->written, size -
835                   state->written, 
836 #ifdef MSG_NOSIGNAL
837                   MSG_NOSIGNAL
838 #else
839                   0
840 #endif
841                  )) < 0)
842         {
843             if (
844 #ifdef WIN32
845                 WSAGetLastError() == WSAEWOULDBLOCK
846 #else
847                 errno == EWOULDBLOCK 
848 #ifdef EAGAIN
849 #if EAGAIN != EWOULDBLOCK
850              || errno == EAGAIN
851 #endif
852 #endif
853 #endif
854                 )
855             {
856                 TRC(fprintf(stderr, "  Flow control stop\n"));
857                 h->io_pending = CS_WANT_WRITE;
858                 return 1;
859             }
860             h->cerrno = CSYSERR;
861             return -1;
862         }
863         state->written += res;
864         TRC(fprintf(stderr, "  Wrote %d, written=%d, nbytes=%d\n",
865                     res, state->written, size));
866     }
867     state->towrite = state->written = -1;
868     TRC(fprintf(stderr, "  Ok\n"));
869     return 0;
870 }
871
872
873 #if HAVE_OPENSSL_SSL_H
874 /*
875  * Returns 1, 0 or -1
876  * In nonblocking mode, you must call again with same buffer while
877  * return value is 1.
878  */
879 int ssl_put(COMSTACK h, char *buf, int size)
880 {
881     int res;
882     struct tcpip_state *state = (struct tcpip_state *)h->cprivate;
883
884     TRC(fprintf(stderr, "ssl_put: size=%d\n", size));
885     h->io_pending = 0;
886     h->event = CS_DATA;
887     if (state->towrite < 0)
888     {
889         state->towrite = size;
890         state->written = 0;
891     }
892     else if (state->towrite != size)
893     {
894         h->cerrno = CSWRONGBUF;
895         return -1;
896     }
897     while (state->towrite > state->written)
898     {
899         res = SSL_write (state->ssl, buf + state->written,
900                          size - state->written);
901         if (res <= 0)
902         {
903             int ssl_err = SSL_get_error(state->ssl, res);
904             if (ssl_err == SSL_ERROR_WANT_READ)
905             {
906                 h->io_pending = CS_WANT_READ;
907                 return 1;
908             }
909             if (ssl_err == SSL_ERROR_WANT_WRITE)
910             {
911                 h->io_pending = CS_WANT_WRITE;
912                 return 1;
913             }
914             h->cerrno = CSERRORSSL;
915             return -1;
916         }
917         state->written += res;
918         TRC(fprintf(stderr, "  Wrote %d, written=%d, nbytes=%d\n",
919                     res, state->written, size));
920     }
921     state->towrite = state->written = -1;
922     TRC(fprintf(stderr, "  Ok\n"));
923     return 0;
924 }
925 #endif
926
927 int tcpip_close(COMSTACK h)
928 {
929     tcpip_state *sp = (struct tcpip_state *)h->cprivate;
930
931     TRC(fprintf(stderr, "tcpip_close\n"));
932     if (h->iofile != -1)
933     {
934 #if HAVE_OPENSSL_SSL_H
935         if (sp->ssl)
936         {
937             SSL_shutdown (sp->ssl);
938         }
939 #endif
940 #ifdef WIN32
941         closesocket(h->iofile);
942 #else
943         close(h->iofile);
944 #endif
945     }
946     if (sp->altbuf)
947         xfree(sp->altbuf);
948 #if HAVE_OPENSSL_SSL_H
949     if (sp->ssl)
950     {
951         TRC (fprintf(stderr, "SSL_free\n"));
952         SSL_free (sp->ssl);
953     }
954     sp->ssl = 0;
955     if (sp->ctx_alloc)
956         SSL_CTX_free (sp->ctx_alloc);
957 #endif
958     xfree(sp);
959     xfree(h);
960     return 0;
961 }
962
963 char *tcpip_addrstr(COMSTACK h)
964 {
965     struct sockaddr_in addr;
966     tcpip_state *sp = (struct tcpip_state *)h->cprivate;
967     char *r, *buf = sp->buf;
968     size_t len;
969     struct hostent *host;
970     
971     len = sizeof(addr);
972     if (getpeername(h->iofile, (struct sockaddr*) &addr, &len) < 0)
973     {
974         h->cerrno = CSYSERR;
975         return 0;
976     }
977     if ((host = gethostbyaddr((char*)&addr.sin_addr, sizeof(addr.sin_addr),
978                               AF_INET)))
979         r = (char*) host->h_name;
980     else
981         r = inet_ntoa(addr.sin_addr);
982     sprintf(buf, "tcp:%s", r);
983 #if HAVE_OPENSSL_SSL_H
984     if (sp->ctx)
985         sprintf(buf, "ssl:%s", r);
986 #endif
987     return buf;
988 }
989
990 int static tcpip_set_blocking(COMSTACK p, int blocking)
991 {
992     unsigned long flag;
993     
994     if (p->blocking == blocking)
995         return 1;
996 #ifdef WIN32
997     flag = 1;
998     if (ioctlsocket(p->iofile, FIONBIO, &flag) < 0)
999         return 0;
1000 #else
1001     flag = fcntl(p->iofile, F_GETFL, 0);
1002     if(!blocking)
1003         flag = flag & ~O_NONBLOCK;
1004     else
1005         flag = flag | O_NONBLOCK;
1006     if (fcntl(p->iofile, F_SETFL, flag) < 0)
1007         return 0;
1008 #endif
1009     p->blocking = blocking;
1010     return 1;
1011 }