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