For accept/recv/send check for EAGAIN if it's differs from EWOULDBLOCK.
[yaz-moved-to-github.git] / comstack / tcpip.c
1 /*
2  * Copyright (c) 1995-2001, Index Data
3  * See the file LICENSE for details.
4  *
5  * $Log: tcpip.c,v $
6  * Revision 1.41  2001-10-12 21:49:26  adam
7  * For accept/recv/send check for EAGAIN if it's differs from EWOULDBLOCK.
8  *
9  * Revision 1.40  2001/08/23 09:02:46  adam
10  * WIN32 fixes: Socket not re-used for bind. yaz_log logs WIN32 error
11  * message.
12  *
13  * Revision 1.39  2001/07/19 19:49:40  adam
14  * Fixed bug in tcpip_set_blocking.
15  *
16  * Revision 1.38  2001/03/21 12:43:36  adam
17  * Implemented cs_create_host. Better error reporting for SSL comstack.
18  *
19  * Revision 1.37  2001/03/08 20:18:55  adam
20  * Added cs_set_blocking. Patch from Matthew Carey.
21  *
22  * Revision 1.36  2001/02/21 13:46:53  adam
23  * C++ fixes.
24  *
25  * Revision 1.35  2000/11/27 15:17:40  adam
26  * Using SSLeay_add_all_algorithms instead of OpenSSL_add_all_algorithms.
27  *
28  * Revision 1.34  2000/11/23 10:58:32  adam
29  * SSL comstack support. Separate POSIX thread support library.
30  *
31  * Revision 1.33  2000/09/04 08:27:11  adam
32  * Work on error handling for tcpip_accept.
33  *
34  * Revision 1.32  1999/11/30 13:47:11  adam
35  * Improved installation. Moved header files to include/yaz.
36  *
37  * Revision 1.31  1999/04/29 07:31:23  adam
38  * Changed tcpip_strtoaddr_ex so that only part 'till '/' is considered
39  * part of hostname.
40  *
41  * Revision 1.30  1999/04/20 09:56:48  adam
42  * Added 'name' paramter to encoder/decoder routines (typedef Odr_fun).
43  * Modified all encoders/decoders to reflect this change.
44  *
45  * Revision 1.29  1999/04/16 14:45:55  adam
46  * Added interface for tcpd wrapper for access control.
47  *
48  * Revision 1.28  1999/03/31 11:11:14  adam
49  * Function getprotobyname only called once. Minor change in tcpip_get
50  * to handle multi-threaded conditions.
51  *
52  * Revision 1.27  1999/02/02 13:57:31  adam
53  * Uses preprocessor define WIN32 instead of WINDOWS to build code
54  * for Microsoft WIN32.
55  *
56  * Revision 1.26  1999/01/08 11:23:14  adam
57  * Added const modifier to some of the BER/ODR encoding routines.
58  *
59  * Revision 1.25  1998/07/07 15:49:23  adam
60  * Added braces to avoid warning.
61  *
62  * Revision 1.24  1998/06/29 07:59:17  adam
63  * Minor fix.
64  *
65  * Revision 1.23  1998/06/23 15:37:50  adam
66  * Added type cast to prevent warning.
67  *
68  * Revision 1.22  1998/06/22 11:32:36  adam
69  * Added 'conditional cs_listen' feature.
70  *
71  * Revision 1.21  1998/05/20 09:55:32  adam
72  * Function tcpip_get treats EINPROGRESS error in the same way as
73  * EWOULDBLOCK. EINPROGRESS shouldn't be returned - but it is on
74  * Solaris in some cases.
75  *
76  * Revision 1.20  1998/05/18 10:10:40  adam
77  * Minor change to avoid C++ warning.
78  *
79  * Revision 1.19  1998/02/11 11:53:33  adam
80  * Changed code so that it compiles as C++.
81  *
82  * Revision 1.18  1997/09/29 07:15:25  adam
83  * Changed use of setsockopt to avoid warnings on MSVC.
84  *
85  * Revision 1.17  1997/09/17 12:10:30  adam
86  * YAZ version 1.4.
87  *
88  * Revision 1.16  1997/09/01 08:49:14  adam
89  * New windows NT/95 port using MSV5.0. Minor changes only.
90  *
91  * Revision 1.15  1997/05/14 06:53:33  adam
92  * C++ support.
93  *
94  * Revision 1.14  1997/05/01 15:06:32  adam
95  * Moved WINSOCK init. code to tcpip_init routine.
96  *
97  * Revision 1.13  1996/11/01 08:45:18  adam
98  * Bug fix: used close on MS-Windows. Fixed to closesocket.
99  *
100  * Revision 1.12  1996/07/06 19:58:30  quinn
101  * System headerfiles gathered in yconfig
102  *
103  * Revision 1.11  1996/02/23  10:00:39  quinn
104  * WAIS Work
105  *
106  * Revision 1.10  1996/02/20  12:52:11  quinn
107  * WAIS protocol support.
108  *
109  * Revision 1.9  1996/02/10  12:23:11  quinn
110  * Enablie inetd operations fro TCP/IP stack
111  *
112  * Revision 1.8  1995/11/01  13:54:27  quinn
113  * Minor adjustments
114  *
115  * Revision 1.7  1995/10/30  12:41:16  quinn
116  * Added hostname lookup for server.
117  *
118  * Revision 1.6  1995/09/29  17:12:00  quinn
119  * Smallish
120  *
121  * Revision 1.5  1995/09/29  17:01:48  quinn
122  * More Windows work
123  *
124  * Revision 1.4  1995/09/28  10:12:26  quinn
125  * Windows-support changes
126  *
127  * Revision 1.3  1995/09/27  15:02:45  quinn
128  * Modified function heads & prototypes.
129  *
130  * Revision 1.2  1995/06/15  12:30:06  quinn
131  * Added @ as hostname alias for INADDR ANY.
132  *
133  * Revision 1.1  1995/06/14  09:58:20  quinn
134  * Renamed yazlib to comstack.
135  *
136  * Revision 1.20  1995/05/16  08:51:16  quinn
137  * License, documentation, and memory fixes
138  *
139  * Revision 1.19  1995/04/10  10:24:08  quinn
140  * Some bug-fixes.
141  *
142  * Revision 1.18  1995/03/30  13:29:27  quinn
143  * Added REUSEADDR in tcpip_bind
144  *
145  * Revision 1.17  1995/03/27  08:36:10  quinn
146  * Some work on nonblocking operation in xmosi.c and rfct.c.
147  * Added protocol parameter to cs_create()
148  *
149  * Revision 1.16  1995/03/21  15:53:41  quinn
150  * Added rcvconnect
151  *
152  * Revision 1.15  1995/03/21  12:31:27  quinn
153  * Added check for EINPROGRESS on connect.
154  *
155  * Revision 1.14  1995/03/20  09:47:21  quinn
156  * Added server-side support to xmosi.c
157  * Fixed possible problems in rfct
158  * Other little mods
159  *
160  * Revision 1.13  1995/03/15  16:15:13  adam
161  * Removed p_write.
162  *
163  * Revision 1.12  1995/03/15  15:36:27  quinn
164  * Mods to support nonblocking I/O
165  *
166  * Revision 1.11  1995/03/15  08:37:57  quinn
167  * Now we're pretty much set for nonblocking I/O.
168  *
169  * Revision 1.10  1995/03/14  17:00:07  quinn
170  * Bug-fixes - added tracing info to tcpip.c
171  *
172  * Revision 1.9  1995/03/14  10:28:42  quinn
173  * Adding server-side support to tcpip.c and fixing bugs in nonblocking I/O
174  *
175  * Revision 1.8  1995/03/10  14:22:50  quinn
176  * Removed debug output.
177  *
178  * Revision 1.7  1995/03/10  11:44:59  quinn
179  * Fixes and debugging
180  *
181  * Revision 1.6  1995/03/07  10:26:55  quinn
182  * Initialized type field in the comstacks.
183  *
184  * Revision 1.5  1995/02/14  20:40:07  quinn
185  * Various stuff.
186  *
187  * Revision 1.4  1995/02/14  11:54:49  quinn
188  * Beginning to add full CCL.
189  *
190  * Revision 1.3  1995/02/10  18:58:10  quinn
191  * Fixed tcpip_get (formerly tcpip_read).
192  * Turned tst (cli) into a proper, event-driven thingy.
193  *
194  * Revision 1.2  1995/02/10  15:55:47  quinn
195  * Small things.
196  *
197  * Revision 1.1  1995/02/09  15:51:52  quinn
198  * Works better now.
199  *
200  */
201
202 #include <stdio.h>
203 #include <string.h>
204 #include <stdlib.h>
205 #ifndef WIN32
206 #include <unistd.h>
207 #endif
208 #include <errno.h>
209 #include <fcntl.h>
210 #if HAVE_OPENSSL_SSL_H
211 #include <openssl/ssl.h>
212 #include <openssl/err.h>
213 #endif
214
215 #include <yaz/comstack.h>
216 #include <yaz/tcpip.h>
217 #include <yaz/log.h>
218
219 /* Chas added the following, so we get the definition of completeBER */
220 #include <yaz/odr.h>
221
222 int tcpip_close(COMSTACK h);
223 int tcpip_put(COMSTACK h, char *buf, int size);
224 int tcpip_get(COMSTACK h, char **buf, int *bufsize);
225 int tcpip_connect(COMSTACK h, void *address);
226 int tcpip_more(COMSTACK h);
227 int tcpip_rcvconnect(COMSTACK h);
228 int tcpip_bind(COMSTACK h, void *address, int mode);
229 int tcpip_listen(COMSTACK h, char *raddr, int *addrlen,
230                  int (*check_ip)(void *cd, const char *a, int len, int type),
231                  void *cd);
232 int static tcpip_set_blocking(COMSTACK p, int blocking);
233
234 #if HAVE_OPENSSL_SSL_H
235 int ssl_get(COMSTACK h, char **buf, int *bufsize);
236 int ssl_put(COMSTACK h, char *buf, int size);
237 #endif
238
239 COMSTACK tcpip_accept(COMSTACK h);
240 char *tcpip_addrstr(COMSTACK h);
241 void *tcpip_straddr(COMSTACK h, const char *str);
242
243 #if 0
244 #define TRC(x) x
245 #else
246 #define TRC(X)
247 #endif
248
249 /* this state is used for both SSL and straight TCP/IP */
250 typedef struct tcpip_state
251 {
252     char *altbuf; /* alternate buffer for surplus data */
253     int altsize;  /* size as xmalloced */
254     int altlen;   /* length of data or 0 if none */
255
256     int written;  /* -1 if we aren't writing */
257     int towrite;  /* to verify against user input */
258     int (*complete)(const unsigned char *buf, int len); /* length/comple. */
259     struct sockaddr_in addr;  /* returned by cs_straddr */
260     char buf[128]; /* returned by cs_addrstr */
261 #if HAVE_OPENSSL_SSL_H
262     SSL_CTX *ctx;
263     SSL_CTX *ctx_alloc;
264     SSL *ssl;
265 #endif
266 } tcpip_state;
267
268 #ifdef WIN32
269 static int tcpip_init (void)
270 {
271     static int initialized = 0;
272     if (!initialized)
273     {
274         WORD requested;
275         WSADATA wd;
276
277         requested = MAKEWORD(1, 1);
278         if (WSAStartup(requested, &wd))
279             return 0;
280         initialized = 1;
281     }
282     return 1;
283 }
284 #else
285 static int proto_number = 0;
286
287 static int tcpip_init (void)
288 {
289     struct protoent *proto;
290     /* only call getprotobyname once, in case it allocates memory */
291     if (!(proto = getprotobyname("tcp")))
292         return 0;
293     proto_number = proto->p_proto;
294     return 1;
295 }
296 #endif
297
298 /*
299  * This function is always called through the cs_create() macro.
300  * s >= 0: socket has already been established for us.
301  */
302 COMSTACK tcpip_type(int s, int blocking, int protocol, void *vp)
303 {
304     COMSTACK p;
305     tcpip_state *state;
306     int new_socket;
307 #ifdef WIN32
308     unsigned long tru = 1;
309 #endif
310
311     if (!tcpip_init ())
312         return 0;
313     if (s < 0)
314     {
315 #ifdef WIN32
316         if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0)
317             return 0;
318 #else
319         if ((s = socket(AF_INET, SOCK_STREAM, proto_number)) < 0)
320             return 0;
321 #endif
322         new_socket = 1;
323     }
324     else
325         new_socket = 0;
326     if (!(p = (struct comstack *)xmalloc(sizeof(struct comstack))))
327         return 0;
328     if (!(state = (struct tcpip_state *)(p->cprivate =
329                                          xmalloc(sizeof(tcpip_state)))))
330         return 0;
331
332 #ifdef WIN32
333     if (!(p->blocking = blocking) && ioctlsocket(s, FIONBIO, &tru) < 0)
334 #else
335     if (!(p->blocking = blocking) && fcntl(s, F_SETFL, O_NONBLOCK) < 0)
336 #endif
337         return 0;
338
339     p->io_pending = 0;
340     p->iofile = s;
341     p->type = tcpip_type;
342     p->protocol = (enum oid_proto) protocol;
343
344     p->f_connect = tcpip_connect;
345     p->f_rcvconnect = tcpip_rcvconnect;
346     p->f_get = tcpip_get;
347     p->f_put = tcpip_put;
348     p->f_close = tcpip_close;
349     p->f_more = tcpip_more;
350     p->f_bind = tcpip_bind;
351     p->f_listen = tcpip_listen;
352     p->f_accept = tcpip_accept;
353     p->f_addrstr = tcpip_addrstr;
354     p->f_straddr = tcpip_straddr;
355     p->f_set_blocking = tcpip_set_blocking;
356
357     p->state = new_socket ? CS_UNBND : CS_IDLE; /* state of line */
358     p->event = CS_NONE;
359     p->cerrno = 0;
360     p->stackerr = 0;
361
362 #if HAVE_OPENSSL_SSL_H
363     state->ctx = state->ctx_alloc = 0;
364     state->ssl = 0;
365 #endif
366
367     state->altbuf = 0;
368     state->altsize = state->altlen = 0;
369     state->towrite = state->written = -1;
370     if (protocol == PROTO_WAIS)
371         state->complete = completeWAIS;
372     else
373         state->complete = completeBER;
374
375     p->timeout = COMSTACK_DEFAULT_TIMEOUT;
376     TRC(fprintf(stderr, "Created new TCPIP comstack\n"));
377
378     return p;
379 }
380
381 #if HAVE_OPENSSL_SSL_H
382
383 COMSTACK ssl_type(int s, int blocking, int protocol, void *vp)
384 {
385     tcpip_state *state;
386     COMSTACK p;
387     yaz_log(LOG_LOG, "ssl_type begin");
388
389     p = tcpip_type (s, blocking, protocol, 0);
390     if (!p)
391         return 0;
392     p->f_get = ssl_get;
393     p->f_put = ssl_put;
394     p->type = ssl_type;
395     state = (tcpip_state *) p->cprivate;
396     if (vp)
397         state->ctx = vp;
398     else
399     {
400         SSL_load_error_strings();
401         SSLeay_add_all_algorithms();
402
403         state->ctx = state->ctx_alloc = SSL_CTX_new (SSLv23_method());
404         if (!state->ctx)
405         {
406             tcpip_close(p);
407             return 0;
408         }
409     }
410     /* note: we don't handle already opened socket in SSL mode - yet */
411     yaz_log(LOG_LOG, "ssl_type end");
412     return p;
413 }
414 #endif
415
416 int tcpip_strtoaddr_ex(const char *str, struct sockaddr_in *add)
417 {
418     struct hostent *hp;
419     char *p, buf[512];
420     short int port = 210;
421     unsigned tmpadd;
422
423     if (!tcpip_init ())
424         return 0;
425     TRC(fprintf(stderr, "tcpip_strtoaddress: %s\n", str ? str : "NULL"));
426     add->sin_family = AF_INET;
427     strncpy(buf, str, 511);
428     buf[511] = 0;
429     if ((p = strchr(buf, '/')))
430         *p = 0;
431     if ((p = strchr(buf, ':')))
432     {
433         *p = 0;
434         port = atoi(p + 1);
435     }
436     add->sin_port = htons(port);
437     if (!strcmp("@", buf))
438         add->sin_addr.s_addr = INADDR_ANY;
439     else if ((hp = gethostbyname(buf)))
440         memcpy(&add->sin_addr.s_addr, *hp->h_addr_list,
441                sizeof(struct in_addr));
442     else if ((tmpadd = (unsigned) inet_addr(buf)) != 0)
443         memcpy(&add->sin_addr.s_addr, &tmpadd, sizeof(struct in_addr));
444     else
445         return 0;
446     return 1;
447 }
448
449 void *tcpip_straddr(COMSTACK h, const char *str)
450 {
451     tcpip_state *sp = (tcpip_state *)h->cprivate;
452
453     if (!tcpip_strtoaddr_ex (str, &sp->addr))
454         return 0;
455     return &sp->addr;
456 }
457
458 struct sockaddr_in *tcpip_strtoaddr(const char *str)
459 {
460     static struct sockaddr_in add;
461     
462     if (!tcpip_strtoaddr_ex (str, &add))
463         return 0;
464     return &add;
465 }
466
467 int tcpip_more(COMSTACK h)
468 {
469     tcpip_state *sp = (tcpip_state *)h->cprivate;
470     
471     return sp->altlen && (*sp->complete)((unsigned char *) sp->altbuf,
472         sp->altlen);
473 }
474
475 /*
476  * connect(2) will block (sometimes) - nothing we can do short of doing
477  * weird things like spawning subprocesses or threading or some weird junk
478  * like that.
479  */
480 int tcpip_connect(COMSTACK h, void *address)
481 {
482     struct sockaddr_in *add = (struct sockaddr_in *)address;
483 #if HAVE_OPENSSL_SSL_H
484         tcpip_state *sp = (tcpip_state *)h->cprivate;
485 #endif
486     int r;
487
488     TRC(fprintf(stderr, "tcpip_connect\n"));
489     h->io_pending = 0;
490     if (h->state == CS_UNBND)
491     {
492         r = connect(h->iofile, (struct sockaddr *) add, sizeof(*add));
493         if (r < 0)
494         {
495 #ifdef WIN32
496             if (WSAGetLastError() == WSAEWOULDBLOCK)
497             {
498                 h->state = CS_CONNECTING;
499                 h->io_pending = CS_WANT_WRITE;
500                 return 1;
501             }
502 #else
503             if (errno == EINPROGRESS)
504             {
505                 h->state = CS_CONNECTING;
506                 h->io_pending = CS_WANT_WRITE|CS_WANT_READ;
507                 return 1;
508             }
509 #endif
510             h->cerrno = CSYSERR;
511             return -1;
512         }
513         h->state = CS_CONNECTING;
514     }
515     if (h->state != CS_CONNECTING)
516     {
517         h->cerrno = CSOUTSTATE;
518         return -1;
519     }
520 #if HAVE_OPENSSL_SSL_H
521     if (sp->ctx)
522     {
523         int res;
524
525         if (!sp->ssl)
526         {
527             sp->ssl = SSL_new (sp->ctx);
528             SSL_set_fd (sp->ssl, h->iofile);
529         }
530         res = SSL_connect (sp->ssl);
531         if (res <= 0)
532         {
533             int err = SSL_get_error(sp->ssl, res);
534             if (err == SSL_ERROR_WANT_READ)
535             {
536                 yaz_log (LOG_LOG, "SSL_connect. want_read");
537                 h->io_pending = CS_WANT_READ;
538                 return 1;
539             }
540             if (err == SSL_ERROR_WANT_WRITE)
541             {
542                 yaz_log (LOG_LOG, "SSL_connect. want_write");
543                 h->io_pending = CS_WANT_WRITE;
544                 return 1;
545             }
546             h->cerrno = CSERRORSSL;
547             return -1;
548         }
549     }
550 #endif
551     h->state = CS_DATAXFER;
552     return 0;
553 }
554
555 /*
556  * nop
557  */
558 int tcpip_rcvconnect(COMSTACK h)
559 {
560     TRC(fprintf(stderr, "tcpip_rcvconnect\n"));
561     return 0;
562 }
563
564 #define CERTF "ztest.pem"
565 #define KEYF "ztest.pem"
566
567 int tcpip_bind(COMSTACK h, void *address, int mode)
568 {
569     struct sockaddr *addr = (struct sockaddr *)address;
570 #ifdef WIN32
571     BOOL one = 1;
572 #else
573     unsigned long one = 1;
574 #endif
575
576 #if HAVE_OPENSSL_SSL_H
577     tcpip_state *sp = (tcpip_state *)h->cprivate;
578     if (sp->ctx)
579     {
580         if (sp->ctx_alloc)
581         {
582             int res;
583             res = SSL_CTX_use_certificate_file (sp->ctx, CERTF,
584                                                 SSL_FILETYPE_PEM);
585             if (res <= 0)
586             {
587                 ERR_print_errors_fp(stderr);
588                 exit (2);
589             }
590             res = SSL_CTX_use_PrivateKey_file (sp->ctx, KEYF,
591                                                SSL_FILETYPE_PEM);
592             if (res <= 0)
593             {
594                 ERR_print_errors_fp(stderr);
595                 exit (3);
596             }
597             res = SSL_CTX_check_private_key (sp->ctx);
598             if (res <= 0)
599             {
600                 ERR_print_errors_fp(stderr);
601                 exit(5);
602             }
603         }
604         TRC (fprintf (stderr, "ssl_bind\n"));
605     }
606     else
607     {
608         TRC (fprintf (stderr, "tcpip_bind\n"));
609     }
610 #else
611     TRC (fprintf (stderr, "tcpip_bind\n"));
612 #endif
613 #ifndef WIN32
614     if (setsockopt(h->iofile, SOL_SOCKET, SO_REUSEADDR, (char*) 
615         &one, sizeof(one)) < 0)
616     {
617         h->cerrno = CSYSERR;
618         return -1;
619     }
620 #endif
621     if (bind(h->iofile, addr, sizeof(struct sockaddr_in)))
622     {
623         h->cerrno = CSYSERR;
624         return -1;
625     }
626     if (mode == CS_SERVER && listen(h->iofile, 3) < 0)
627     {
628         h->cerrno = CSYSERR;
629         return -1;
630     }
631     h->state = CS_IDLE;
632     return 0;
633 }
634
635 int tcpip_listen(COMSTACK h, char *raddr, int *addrlen,
636                  int (*check_ip)(void *cd, const char *a, int len, int t),
637                  void *cd)
638 {
639     struct sockaddr_in addr;
640 #ifdef __cplusplus
641     socklen_t len = sizeof(addr);
642 #else
643     int len = sizeof(addr);
644 #endif
645
646     TRC(fprintf(stderr, "tcpip_listen pid=%d\n", getpid()));
647     if (h->state != CS_IDLE)
648     {
649         h->cerrno = CSOUTSTATE;
650         return -1;
651     }
652     h->newfd = accept(h->iofile, (struct sockaddr*)&addr, &len);
653     if (h->newfd < 0)
654     {
655         if (
656 #ifdef WIN32
657             WSAGetLastError() == WSAEWOULDBLOCK
658 #else
659             errno == EWOULDBLOCK 
660 #ifdef EAGAIN
661 #if EAGAIN != EWOULDBLOCK
662             || errno == EAGAIN
663 #endif
664 #endif
665 #endif
666             )
667             h->cerrno = CSNODATA;
668         else
669             h->cerrno = CSYSERR;
670         return -1;
671     }
672     if (addrlen && (size_t) (*addrlen) >= sizeof(struct sockaddr_in))
673         memcpy(raddr, &addr, *addrlen = sizeof(struct sockaddr_in));
674     else if (addrlen)
675         *addrlen = 0;
676     if (check_ip && (*check_ip)(cd, (const char *) &addr,
677         sizeof(addr), AF_INET))
678     {
679         h->cerrno = CSDENY;
680 #ifdef WIN32
681         closesocket(h->newfd);
682 #else
683         close(h->newfd);
684 #endif
685         h->newfd = -1;
686         return -1;
687     }
688     h->state = CS_INCON;
689     return 0;
690 }
691
692 COMSTACK tcpip_accept(COMSTACK h)
693 {
694     COMSTACK cnew;
695     tcpip_state *state, *st = (tcpip_state *)h->cprivate;
696 #ifdef WIN32
697     unsigned long tru = 1;
698 #endif
699
700     TRC(fprintf(stderr, "tcpip_accept\n"));
701     if (h->state == CS_INCON)
702     {
703         if (!(cnew = (COMSTACK)xmalloc(sizeof(*cnew))))
704         {
705             h->cerrno = CSYSERR;
706 #ifdef WIN32
707             closesocket(h->newfd);
708 #else
709             close(h->newfd);
710 #endif
711             h->newfd = -1;
712             return 0;
713         }
714         memcpy(cnew, h, sizeof(*h));
715         cnew->iofile = h->newfd;
716         cnew->io_pending = 0;
717         if (!(state = (tcpip_state *)
718               (cnew->cprivate = xmalloc(sizeof(tcpip_state)))))
719         {
720             h->cerrno = CSYSERR;
721             if (h->newfd != -1)
722             {
723 #ifdef WIN32
724                 closesocket(h->newfd);
725 #else
726                 close(h->newfd);
727 #endif
728                 h->newfd = -1;
729             }
730             return 0;
731         }
732         if (!cnew->blocking && 
733 #ifdef WIN32
734             (ioctlsocket(cnew->iofile, FIONBIO, &tru) < 0)
735 #else
736             (!cnew->blocking && fcntl(cnew->iofile, F_SETFL, O_NONBLOCK) < 0)
737 #endif
738             )
739         {
740             h->cerrno = CSYSERR;
741             if (h->newfd != -1)
742             {
743 #ifdef WIN32
744                 closesocket(h->newfd);
745 #else
746                 close(h->newfd);
747 #endif
748                 h->newfd = -1;
749             }
750             xfree (cnew);
751             xfree (state);
752             return 0;
753         }
754         h->newfd = -1;
755         state->altbuf = 0;
756         state->altsize = state->altlen = 0;
757         state->towrite = state->written = -1;
758         state->complete = st->complete;
759         cnew->state = CS_ACCEPT;
760         h->state = CS_IDLE;
761         
762 #if HAVE_OPENSSL_SSL_H
763         state->ctx = st->ctx;
764         state->ctx_alloc = 0;
765         state->ssl = st->ssl;
766         if (state->ctx)
767         {
768             state->ssl = SSL_new (state->ctx);
769             SSL_set_fd (state->ssl, cnew->iofile);
770         }
771 #endif
772         h = cnew;
773     }
774     if (h->state == CS_ACCEPT)
775     {
776 #if HAVE_OPENSSL_SSL_H
777         tcpip_state *state = (tcpip_state *)h->cprivate;
778         if (state->ctx)
779         {
780             int res = SSL_accept (state->ssl);
781             TRC(fprintf(stderr, "SSL_accept\n"));
782             if (res <= 0)
783             {
784                 int err = SSL_get_error(state->ssl, res);
785                 if (err == SSL_ERROR_WANT_READ)
786                 {
787                     h->io_pending = CS_WANT_READ;
788                     yaz_log (LOG_LOG, "SSL_accept. want_read");
789                     return h;
790                 }
791                 if (err == SSL_ERROR_WANT_WRITE)
792                 {
793                     h->io_pending = CS_WANT_WRITE;
794                     yaz_log (LOG_LOG, "SSL_accept. want_write");
795                     return h;
796                 }
797                 cs_close (h);
798                 return 0;
799             }
800         }
801 #endif
802     }
803     else
804     {
805         h->cerrno = CSOUTSTATE;
806         return 0;
807     }
808     h->io_pending = 0;
809     h->state = CS_DATAXFER;
810     return h;
811 }
812
813 #define CS_TCPIP_BUFCHUNK 4096
814
815 /*
816  * Return: -1 error, >1 good, len of buffer, ==1 incomplete buffer,
817  * 0=connection closed.
818  */
819 int tcpip_get(COMSTACK h, char **buf, int *bufsize)
820 {
821     tcpip_state *sp = (tcpip_state *)h->cprivate;
822     char *tmpc;
823     int tmpi, berlen, rest, req, tomove;
824     int hasread = 0, res;
825
826     TRC(fprintf(stderr, "tcpip_get: bufsize=%d\n", *bufsize));
827     if (sp->altlen) /* switch buffers */
828     {
829         TRC(fprintf(stderr, "  %d bytes in altbuf (0x%x)\n", sp->altlen,
830             (unsigned) sp->altbuf));
831         tmpc = *buf;
832         tmpi = *bufsize;
833         *buf = sp->altbuf;
834         *bufsize = sp->altsize;
835         hasread = sp->altlen;
836         sp->altlen = 0;
837         sp->altbuf = tmpc;
838         sp->altsize = tmpi;
839     }
840     h->io_pending = 0;
841     while (!(berlen = (*sp->complete)((unsigned char *)*buf, hasread)))
842     {
843         if (!*bufsize)
844         {
845             if (!(*buf = (char *)xmalloc(*bufsize = CS_TCPIP_BUFCHUNK)))
846                 return -1;
847         }
848         else if (*bufsize - hasread < CS_TCPIP_BUFCHUNK)
849             if (!(*buf =(char *)xrealloc(*buf, *bufsize *= 2)))
850                 return -1;
851         res = recv(h->iofile, *buf + hasread, CS_TCPIP_BUFCHUNK, 0);
852         TRC(fprintf(stderr, "  recv res=%d, hasread=%d\n", res, hasread));
853         if (res < 0)
854         {
855 #ifdef WIN32
856             if (WSAGetLastError() == WSAEWOULDBLOCK)
857             {
858                 h->io_pending = CS_WANT_READ;
859                 break;
860             }
861             else
862                 return -1;
863 #else
864             if (errno == EWOULDBLOCK 
865 #ifdef EAGAIN   
866 #if EAGAIN != EWOULDBLOCK
867                 || errno == EAGAIN
868 #endif
869 #endif
870                 || errno == EINPROGRESS
871                 )
872             {
873                 h->io_pending = CS_WANT_READ;
874                 break;
875             }
876             else if (errno == 0)
877                 continue;
878             else
879                 return -1;
880 #endif
881         }
882         else if (!res)
883             return 0;
884         hasread += res;
885     }
886     TRC (fprintf (stderr, "  Out of read loop with hasread=%d, berlen=%d\n",
887                   hasread, berlen));
888     /* move surplus buffer (or everything if we didn't get a BER rec.) */
889     if (hasread > berlen)
890     {
891         tomove = req = hasread - berlen;
892         rest = tomove % CS_TCPIP_BUFCHUNK;
893         if (rest)
894             req += CS_TCPIP_BUFCHUNK - rest;
895         if (!sp->altbuf)
896         {
897             if (!(sp->altbuf = (char *)xmalloc(sp->altsize = req)))
898                 return -1;
899         } else if (sp->altsize < req)
900             if (!(sp->altbuf =(char *)xrealloc(sp->altbuf, sp->altsize = req)))
901                 return -1;
902         TRC(fprintf(stderr, "  Moving %d bytes to altbuf(0x%x)\n", tomove,
903             (unsigned) sp->altbuf));
904         memcpy(sp->altbuf, *buf + berlen, sp->altlen = tomove);
905     }
906     if (berlen < CS_TCPIP_BUFCHUNK - 1)
907         *(*buf + berlen) = '\0';
908     return berlen ? berlen : 1;
909 }
910
911
912 #if HAVE_OPENSSL_SSL_H
913 /*
914  * Return: -1 error, >1 good, len of buffer, ==1 incomplete buffer,
915  * 0=connection closed.
916  */
917 int ssl_get(COMSTACK h, char **buf, int *bufsize)
918 {
919     tcpip_state *sp = (tcpip_state *)h->cprivate;
920     char *tmpc;
921     int tmpi, berlen, rest, req, tomove;
922     int hasread = 0, res;
923
924     TRC(fprintf(stderr, "ssl_get: bufsize=%d\n", *bufsize));
925     if (sp->altlen) /* switch buffers */
926     {
927         TRC(fprintf(stderr, "  %d bytes in altbuf (0x%x)\n", sp->altlen,
928             (unsigned) sp->altbuf));
929         tmpc = *buf;
930         tmpi = *bufsize;
931         *buf = sp->altbuf;
932         *bufsize = sp->altsize;
933         hasread = sp->altlen;
934         sp->altlen = 0;
935         sp->altbuf = tmpc;
936         sp->altsize = tmpi;
937     }
938     h->io_pending = 0;
939     while (!(berlen = (*sp->complete)((unsigned char *)*buf, hasread)))
940     {
941         if (!*bufsize)
942         {
943             if (!(*buf = (char *)xmalloc(*bufsize = CS_TCPIP_BUFCHUNK)))
944                 return -1;
945         }
946         else if (*bufsize - hasread < CS_TCPIP_BUFCHUNK)
947             if (!(*buf =(char *)xrealloc(*buf, *bufsize *= 2)))
948                 return -1;
949         res = SSL_read (sp->ssl, *buf + hasread, CS_TCPIP_BUFCHUNK);
950         TRC(fprintf(stderr, "  SSL_read res=%d, hasread=%d\n", res, hasread));
951         if (res <= 0)
952         {
953             int ssl_err = SSL_get_error(sp->ssl, res);
954             if (ssl_err == SSL_ERROR_WANT_READ)
955             {
956                 h->io_pending = CS_WANT_READ;
957                 yaz_log (LOG_LOG, "SSL_read. want_read");
958                 break;
959             }
960             if (ssl_err == SSL_ERROR_WANT_WRITE)
961             {
962                 h->io_pending = CS_WANT_WRITE;
963                 yaz_log (LOG_LOG, "SSL_read. want_write");
964                 break;
965             }
966             if (res == 0)
967                 return 0;
968             h->cerrno = CSERRORSSL;
969             return -1;
970         }
971         hasread += res;
972     }
973     TRC (fprintf (stderr, "  Out of read loop with hasread=%d, berlen=%d\n",
974         hasread, berlen));
975     /* move surplus buffer (or everything if we didn't get a BER rec.) */
976     if (hasread > berlen)
977     {
978         tomove = req = hasread - berlen;
979         rest = tomove % CS_TCPIP_BUFCHUNK;
980         if (rest)
981             req += CS_TCPIP_BUFCHUNK - rest;
982         if (!sp->altbuf)
983         {
984             if (!(sp->altbuf = (char *)xmalloc(sp->altsize = req)))
985                 return -1;
986         } else if (sp->altsize < req)
987             if (!(sp->altbuf =(char *)xrealloc(sp->altbuf, sp->altsize = req)))
988                 return -1;
989         TRC(fprintf(stderr, "  Moving %d bytes to altbuf(0x%x)\n", tomove,
990             (unsigned) sp->altbuf));
991         memcpy(sp->altbuf, *buf + berlen, sp->altlen = tomove);
992     }
993     if (berlen < CS_TCPIP_BUFCHUNK - 1)
994         *(*buf + berlen) = '\0';
995     return berlen ? berlen : 1;
996 }
997 #endif
998
999 /*
1000  * Returns 1, 0 or -1
1001  * In nonblocking mode, you must call again with same buffer while
1002  * return value is 1.
1003  */
1004 int tcpip_put(COMSTACK h, char *buf, int size)
1005 {
1006     int res;
1007     struct tcpip_state *state = (struct tcpip_state *)h->cprivate;
1008
1009     TRC(fprintf(stderr, "tcpip_put: size=%d\n", size));
1010     h->io_pending = 0;
1011     if (state->towrite < 0)
1012     {
1013         state->towrite = size;
1014         state->written = 0;
1015     }
1016     else if (state->towrite != size)
1017     {
1018         h->cerrno = CSWRONGBUF;
1019         return -1;
1020     }
1021     while (state->towrite > state->written)
1022     {
1023         if ((res = send(h->iofile, buf + state->written, size -
1024                         state->written, 0)) < 0)
1025         {
1026             if (
1027 #ifdef WIN32
1028                 WSAGetLastError() == WSAEWOULDBLOCK
1029 #else
1030                 errno == EWOULDBLOCK 
1031 #ifdef EAGAIN
1032 #if EAGAIN != EWOULDBLOCK
1033              || errno == EAGAIN
1034 #endif
1035 #endif
1036 #endif
1037                 )
1038             {
1039                 TRC(fprintf(stderr, "  Flow control stop\n"));
1040                 h->io_pending = CS_WANT_WRITE;
1041                 return 1;
1042             }
1043             h->cerrno = CSYSERR;
1044             return -1;
1045         }
1046         state->written += res;
1047         TRC(fprintf(stderr, "  Wrote %d, written=%d, nbytes=%d\n",
1048                     res, state->written, size));
1049     }
1050     state->towrite = state->written = -1;
1051     TRC(fprintf(stderr, "  Ok\n"));
1052     return 0;
1053 }
1054
1055
1056 #if HAVE_OPENSSL_SSL_H
1057 /*
1058  * Returns 1, 0 or -1
1059  * In nonblocking mode, you must call again with same buffer while
1060  * return value is 1.
1061  */
1062 int ssl_put(COMSTACK h, char *buf, int size)
1063 {
1064     int res;
1065     struct tcpip_state *state = (struct tcpip_state *)h->cprivate;
1066
1067     TRC(fprintf(stderr, "ssl_put: size=%d\n", size));
1068     h->io_pending = 0;
1069     if (state->towrite < 0)
1070     {
1071         state->towrite = size;
1072         state->written = 0;
1073     }
1074     else if (state->towrite != size)
1075     {
1076         h->cerrno = CSWRONGBUF;
1077         return -1;
1078     }
1079     while (state->towrite > state->written)
1080     {
1081         res = SSL_write (state->ssl, buf + state->written,
1082                          size - state->written);
1083         if (res <= 0)
1084         {
1085             int ssl_err = SSL_get_error(state->ssl, res);
1086             if (ssl_err == SSL_ERROR_WANT_READ)
1087             {
1088                 h->io_pending = CS_WANT_READ;
1089                 yaz_log (LOG_LOG, "SSL_write. want_read");
1090                 return 1;
1091             }
1092             if (ssl_err == SSL_ERROR_WANT_WRITE)
1093             {
1094                 h->io_pending = CS_WANT_WRITE;
1095                 yaz_log (LOG_LOG, "SSL_write. want_write");
1096                 return 1;
1097             }
1098             h->cerrno = CSERRORSSL;
1099             return -1;
1100         }
1101         state->written += res;
1102         TRC(fprintf(stderr, "  Wrote %d, written=%d, nbytes=%d\n",
1103                     res, state->written, size));
1104     }
1105     state->towrite = state->written = -1;
1106     TRC(fprintf(stderr, "  Ok\n"));
1107     return 0;
1108 }
1109 #endif
1110
1111 int tcpip_close(COMSTACK h)
1112 {
1113     tcpip_state *sp = (struct tcpip_state *)h->cprivate;
1114
1115     TRC(fprintf(stderr, "tcpip_close\n"));
1116     if (h->iofile != -1)
1117     {
1118 #if HAVE_OPENSSL_SSL_H
1119         if (sp->ssl)
1120         {
1121             SSL_shutdown (sp->ssl);
1122         }
1123 #endif
1124 #ifdef WIN32
1125         closesocket(h->iofile);
1126 #else
1127         close(h->iofile);
1128 #endif
1129     }
1130     if (sp->altbuf)
1131         xfree(sp->altbuf);
1132 #if HAVE_OPENSSL_SSL_H
1133     if (sp->ssl)
1134     {
1135         TRC (fprintf(stderr, "SSL_free\n"));
1136         SSL_free (sp->ssl);
1137     }
1138     sp->ssl = 0;
1139     if (sp->ctx_alloc)
1140         SSL_CTX_free (sp->ctx_alloc);
1141 #endif
1142     xfree(sp);
1143     xfree(h);
1144     return 0;
1145 }
1146
1147 char *tcpip_addrstr(COMSTACK h)
1148 {
1149     struct sockaddr_in addr;
1150     tcpip_state *sp = (struct tcpip_state *)h->cprivate;
1151     char *r, *buf = sp->buf;
1152     size_t len;
1153     struct hostent *host;
1154     
1155     len = sizeof(addr);
1156     if (getpeername(h->iofile, (struct sockaddr*) &addr, &len) < 0)
1157     {
1158         h->cerrno = CSYSERR;
1159         return 0;
1160     }
1161     if ((host = gethostbyaddr((char*)&addr.sin_addr, sizeof(addr.sin_addr),
1162                               AF_INET)))
1163         r = (char*) host->h_name;
1164     else
1165         r = inet_ntoa(addr.sin_addr);
1166     sprintf(buf, "tcp:%s", r);
1167 #if HAVE_OPENSSL_SSL_H
1168     if (sp->ctx)
1169         sprintf(buf, "ssl:%s", r);
1170 #endif
1171     return buf;
1172 }
1173
1174 int static tcpip_set_blocking(COMSTACK p, int blocking)
1175 {
1176     unsigned long flag;
1177     
1178     if (p->blocking == blocking)
1179         return 1;
1180 #ifdef WIN32
1181     flag = 1;
1182     if (ioctlsocket(p->iofile, FIONBIO, &flag) < 0)
1183         return 0;
1184 #else
1185     flag = fcntl(p->iofile, F_GETFL, 0);
1186     if(!blocking)
1187         flag = flag & ~O_NONBLOCK;
1188     else
1189         flag = flag | O_NONBLOCK;
1190     if (fcntl(p->iofile, F_SETFL, flag) < 0)
1191         return 0;
1192 #endif
1193     p->blocking = blocking;
1194     return 1;
1195 }