X-Git-Url: http://git.indexdata.com/?a=blobdiff_plain;f=comstack%2Ftcpip.c;h=22a8ae5227194ddefd6749b8ec232661770f2d6e;hb=8af7fd342d3c905ddd1e6be521242d881510ba14;hp=b467f20bf209396d2879f39e7a0c6279134b61fa;hpb=1edc4e2e9b58c9ec9fe830eb7c991946084911b0;p=yaz-moved-to-github.git diff --git a/comstack/tcpip.c b/comstack/tcpip.c index b467f20..22a8ae5 100644 --- a/comstack/tcpip.c +++ b/comstack/tcpip.c @@ -1,184 +1,8 @@ /* - * Copyright (c) 1995-2000, Index Data + * Copyright (c) 1995-2001, Index Data * See the file LICENSE for details. - * Sebastian Hammer, Adam Dickmeiss - * - * $Log: tcpip.c,v $ - * Revision 1.35 2000-11-27 15:17:40 adam - * Using SSLeay_add_all_algorithms instead of OpenSSL_add_all_algorithms. - * - * Revision 1.34 2000/11/23 10:58:32 adam - * SSL comstack support. Separate POSIX thread support library. - * - * Revision 1.33 2000/09/04 08:27:11 adam - * Work on error handling for tcpip_accept. - * - * Revision 1.32 1999/11/30 13:47:11 adam - * Improved installation. Moved header files to include/yaz. - * - * Revision 1.31 1999/04/29 07:31:23 adam - * Changed tcpip_strtoaddr_ex so that only part 'till '/' is considered - * part of hostname. - * - * Revision 1.30 1999/04/20 09:56:48 adam - * Added 'name' paramter to encoder/decoder routines (typedef Odr_fun). - * Modified all encoders/decoders to reflect this change. - * - * Revision 1.29 1999/04/16 14:45:55 adam - * Added interface for tcpd wrapper for access control. - * - * Revision 1.28 1999/03/31 11:11:14 adam - * Function getprotobyname only called once. Minor change in tcpip_get - * to handle multi-threaded conditions. - * - * Revision 1.27 1999/02/02 13:57:31 adam - * Uses preprocessor define WIN32 instead of WINDOWS to build code - * for Microsoft WIN32. - * - * Revision 1.26 1999/01/08 11:23:14 adam - * Added const modifier to some of the BER/ODR encoding routines. - * - * Revision 1.25 1998/07/07 15:49:23 adam - * Added braces to avoid warning. - * - * Revision 1.24 1998/06/29 07:59:17 adam - * Minor fix. - * - * Revision 1.23 1998/06/23 15:37:50 adam - * Added type cast to prevent warning. - * - * Revision 1.22 1998/06/22 11:32:36 adam - * Added 'conditional cs_listen' feature. - * - * Revision 1.21 1998/05/20 09:55:32 adam - * Function tcpip_get treats EINPROGRESS error in the same way as - * EWOULDBLOCK. EINPROGRESS shouldn't be returned - but it is on - * Solaris in some cases. - * - * Revision 1.20 1998/05/18 10:10:40 adam - * Minor change to avoid C++ warning. - * - * Revision 1.19 1998/02/11 11:53:33 adam - * Changed code so that it compiles as C++. - * - * Revision 1.18 1997/09/29 07:15:25 adam - * Changed use of setsockopt to avoid warnings on MSVC. - * - * Revision 1.17 1997/09/17 12:10:30 adam - * YAZ version 1.4. - * - * Revision 1.16 1997/09/01 08:49:14 adam - * New windows NT/95 port using MSV5.0. Minor changes only. - * - * Revision 1.15 1997/05/14 06:53:33 adam - * C++ support. - * - * Revision 1.14 1997/05/01 15:06:32 adam - * Moved WINSOCK init. code to tcpip_init routine. - * - * Revision 1.13 1996/11/01 08:45:18 adam - * Bug fix: used close on MS-Windows. Fixed to closesocket. - * - * Revision 1.12 1996/07/06 19:58:30 quinn - * System headerfiles gathered in yconfig - * - * Revision 1.11 1996/02/23 10:00:39 quinn - * WAIS Work - * - * Revision 1.10 1996/02/20 12:52:11 quinn - * WAIS protocol support. - * - * Revision 1.9 1996/02/10 12:23:11 quinn - * Enablie inetd operations fro TCP/IP stack - * - * Revision 1.8 1995/11/01 13:54:27 quinn - * Minor adjustments - * - * Revision 1.7 1995/10/30 12:41:16 quinn - * Added hostname lookup for server. - * - * Revision 1.6 1995/09/29 17:12:00 quinn - * Smallish - * - * Revision 1.5 1995/09/29 17:01:48 quinn - * More Windows work - * - * Revision 1.4 1995/09/28 10:12:26 quinn - * Windows-support changes - * - * Revision 1.3 1995/09/27 15:02:45 quinn - * Modified function heads & prototypes. - * - * Revision 1.2 1995/06/15 12:30:06 quinn - * Added @ as hostname alias for INADDR ANY. - * - * Revision 1.1 1995/06/14 09:58:20 quinn - * Renamed yazlib to comstack. - * - * Revision 1.20 1995/05/16 08:51:16 quinn - * License, documentation, and memory fixes - * - * Revision 1.19 1995/04/10 10:24:08 quinn - * Some bug-fixes. - * - * Revision 1.18 1995/03/30 13:29:27 quinn - * Added REUSEADDR in tcpip_bind - * - * Revision 1.17 1995/03/27 08:36:10 quinn - * Some work on nonblocking operation in xmosi.c and rfct.c. - * Added protocol parameter to cs_create() - * - * Revision 1.16 1995/03/21 15:53:41 quinn - * Added rcvconnect - * - * Revision 1.15 1995/03/21 12:31:27 quinn - * Added check for EINPROGRESS on connect. - * - * Revision 1.14 1995/03/20 09:47:21 quinn - * Added server-side support to xmosi.c - * Fixed possible problems in rfct - * Other little mods - * - * Revision 1.13 1995/03/15 16:15:13 adam - * Removed p_write. - * - * Revision 1.12 1995/03/15 15:36:27 quinn - * Mods to support nonblocking I/O - * - * Revision 1.11 1995/03/15 08:37:57 quinn - * Now we're pretty much set for nonblocking I/O. - * - * Revision 1.10 1995/03/14 17:00:07 quinn - * Bug-fixes - added tracing info to tcpip.c - * - * Revision 1.9 1995/03/14 10:28:42 quinn - * Adding server-side support to tcpip.c and fixing bugs in nonblocking I/O - * - * Revision 1.8 1995/03/10 14:22:50 quinn - * Removed debug output. - * - * Revision 1.7 1995/03/10 11:44:59 quinn - * Fixes and debugging - * - * Revision 1.6 1995/03/07 10:26:55 quinn - * Initialized type field in the comstacks. - * - * Revision 1.5 1995/02/14 20:40:07 quinn - * Various stuff. - * - * Revision 1.4 1995/02/14 11:54:49 quinn - * Beginning to add full CCL. - * - * Revision 1.3 1995/02/10 18:58:10 quinn - * Fixed tcpip_get (formerly tcpip_read). - * Turned tst (cli) into a proper, event-driven thingy. - * - * Revision 1.2 1995/02/10 15:55:47 quinn - * Small things. - * - * Revision 1.1 1995/02/09 15:51:52 quinn - * Works better now. * + * $Id: tcpip.c,v 1.44 2001-11-06 17:01:25 adam Exp $ */ #include @@ -211,6 +35,7 @@ int tcpip_bind(COMSTACK h, void *address, int mode); int tcpip_listen(COMSTACK h, char *raddr, int *addrlen, int (*check_ip)(void *cd, const char *a, int len, int type), void *cd); +int static tcpip_set_blocking(COMSTACK p, int blocking); #if HAVE_OPENSSL_SSL_H int ssl_get(COMSTACK h, char **buf, int *bufsize); @@ -263,15 +88,8 @@ static int tcpip_init (void) return 1; } #else -static int proto_number = 0; - static int tcpip_init (void) { - struct protoent *proto; - /* only call getprotobyname once, in case it allocates memory */ - if (!(proto = getprotobyname("tcp"))) - return 0; - proto_number = proto->p_proto; return 1; } #endif @@ -293,13 +111,8 @@ COMSTACK tcpip_type(int s, int blocking, int protocol, void *vp) return 0; if (s < 0) { -#ifdef WIN32 if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) return 0; -#else - if ((s = socket(AF_INET, SOCK_STREAM, proto_number)) < 0) - return 0; -#endif new_socket = 1; } else @@ -333,8 +146,9 @@ COMSTACK tcpip_type(int s, int blocking, int protocol, void *vp) p->f_accept = tcpip_accept; p->f_addrstr = tcpip_addrstr; p->f_straddr = tcpip_straddr; + p->f_set_blocking = tcpip_set_blocking; - p->state = new_socket ? CS_UNBND : CS_IDLE; /* state of line */ + p->state = new_socket ? CS_ST_UNBND : CS_ST_IDLE; /* state of line */ p->event = CS_NONE; p->cerrno = 0; p->stackerr = 0; @@ -467,7 +281,7 @@ int tcpip_connect(COMSTACK h, void *address) TRC(fprintf(stderr, "tcpip_connect\n")); h->io_pending = 0; - if (h->state == CS_UNBND) + if (h->state == CS_ST_UNBND) { r = connect(h->iofile, (struct sockaddr *) add, sizeof(*add)); if (r < 0) @@ -475,23 +289,27 @@ int tcpip_connect(COMSTACK h, void *address) #ifdef WIN32 if (WSAGetLastError() == WSAEWOULDBLOCK) { - h->state = CS_CONNECTING; + h->event = CS_CONNECT; + h->state = CS_ST_CONNECTING; h->io_pending = CS_WANT_WRITE; return 1; } #else if (errno == EINPROGRESS) { - h->state = CS_CONNECTING; + h->event = CS_CONNECT; + h->state = CS_ST_CONNECTING; h->io_pending = CS_WANT_WRITE|CS_WANT_READ; return 1; } #endif + h->cerrno = CSYSERR; return -1; } - h->state = CS_CONNECTING; + h->event = CS_CONNECT; + h->state = CS_ST_CONNECTING; } - if (h->state != CS_CONNECTING) + if (h->state != CS_ST_CONNECTING) { h->cerrno = CSOUTSTATE; return -1; @@ -522,21 +340,53 @@ int tcpip_connect(COMSTACK h, void *address) h->io_pending = CS_WANT_WRITE; return 1; } + h->cerrno = CSERRORSSL; return -1; } } #endif - h->state = CS_DATAXFER; + h->event = CS_DATA; + h->state = CS_ST_DATAXFER; return 0; } /* * nop */ -int tcpip_rcvconnect(COMSTACK h) +int tcpip_rcvconnect(COMSTACK cs) { TRC(fprintf(stderr, "tcpip_rcvconnect\n")); - return 0; + + if (cs->event == CS_CONNECT) + { + int fd = cs->iofile; + fd_set input, output; + struct timeval tv; + int r; + + tv.tv_sec = 0; + tv.tv_usec = 1; + + FD_ZERO(&input); + FD_ZERO(&output); + FD_SET (fd, &input); + FD_SET (fd, &output); + + r = select (fd+1, &input, &output, 0, &tv); + if (r > 0) + { + if (FD_ISSET(cs->iofile, &output)) + { + cs->event = CS_DATA; + return 0; /* write OK, we're OK */ + } + else + return -1; /* an error, for sure */ + } + else if (r == 0) + return 0; /* timeout - incomplete */ + } + return -1; /* wrong state or bad select */ } #define CERTF "ztest.pem" @@ -588,13 +438,15 @@ int tcpip_bind(COMSTACK h, void *address, int mode) #else TRC (fprintf (stderr, "tcpip_bind\n")); #endif +#ifndef WIN32 if (setsockopt(h->iofile, SOL_SOCKET, SO_REUSEADDR, (char*) &one, sizeof(one)) < 0) { h->cerrno = CSYSERR; return -1; } - if (bind(h->iofile, addr, sizeof(struct sockaddr_in)) < 0) +#endif + if (bind(h->iofile, addr, sizeof(struct sockaddr_in))) { h->cerrno = CSYSERR; return -1; @@ -604,7 +456,8 @@ int tcpip_bind(COMSTACK h, void *address, int mode) h->cerrno = CSYSERR; return -1; } - h->state = CS_IDLE; + h->state = CS_ST_IDLE; + h->event = CS_LISTEN; return 0; } @@ -613,10 +466,14 @@ int tcpip_listen(COMSTACK h, char *raddr, int *addrlen, void *cd) { struct sockaddr_in addr; +#ifdef __cplusplus + socklen_t len = sizeof(addr); +#else int len = sizeof(addr); +#endif TRC(fprintf(stderr, "tcpip_listen pid=%d\n", getpid())); - if (h->state != CS_IDLE) + if (h->state != CS_ST_IDLE) { h->cerrno = CSOUTSTATE; return -1; @@ -628,7 +485,12 @@ int tcpip_listen(COMSTACK h, char *raddr, int *addrlen, #ifdef WIN32 WSAGetLastError() == WSAEWOULDBLOCK #else - errno == EWOULDBLOCK + errno == EWOULDBLOCK +#ifdef EAGAIN +#if EAGAIN != EWOULDBLOCK + || errno == EAGAIN +#endif +#endif #endif ) h->cerrno = CSNODATA; @@ -652,7 +514,7 @@ int tcpip_listen(COMSTACK h, char *raddr, int *addrlen, h->newfd = -1; return -1; } - h->state = CS_INCON; + h->state = CS_ST_INCON; return 0; } @@ -665,7 +527,7 @@ COMSTACK tcpip_accept(COMSTACK h) #endif TRC(fprintf(stderr, "tcpip_accept\n")); - if (h->state == CS_INCON) + if (h->state == CS_ST_INCON) { if (!(cnew = (COMSTACK)xmalloc(sizeof(*cnew)))) { @@ -723,8 +585,8 @@ COMSTACK tcpip_accept(COMSTACK h) state->altsize = state->altlen = 0; state->towrite = state->written = -1; state->complete = st->complete; - cnew->state = CS_ACCEPT; - h->state = CS_IDLE; + cnew->state = CS_ST_ACCEPT; + h->state = CS_ST_IDLE; #if HAVE_OPENSSL_SSL_H state->ctx = st->ctx; @@ -738,7 +600,7 @@ COMSTACK tcpip_accept(COMSTACK h) #endif h = cnew; } - if (h->state == CS_ACCEPT) + if (h->state == CS_ST_ACCEPT) { #if HAVE_OPENSSL_SSL_H tcpip_state *state = (tcpip_state *)h->cprivate; @@ -773,7 +635,8 @@ COMSTACK tcpip_accept(COMSTACK h) return 0; } h->io_pending = 0; - h->state = CS_DATAXFER; + h->state = CS_ST_DATAXFER; + h->event = CS_DATA; return h; } @@ -828,10 +691,13 @@ int tcpip_get(COMSTACK h, char **buf, int *bufsize) else return -1; #else - if (errno == EWOULDBLOCK -#ifdef EINPROGRESS - || errno == EINPROGRESS + if (errno == EWOULDBLOCK +#ifdef EAGAIN +#if EAGAIN != EWOULDBLOCK + || errno == EAGAIN +#endif #endif + || errno == EINPROGRESS ) { h->io_pending = CS_WANT_READ; @@ -929,6 +795,7 @@ int ssl_get(COMSTACK h, char **buf, int *bufsize) } if (res == 0) return 0; + h->cerrno = CSERRORSSL; return -1; } hasread += res; @@ -971,6 +838,7 @@ int tcpip_put(COMSTACK h, char *buf, int size) TRC(fprintf(stderr, "tcpip_put: size=%d\n", size)); h->io_pending = 0; + h->event = CS_DATA; if (state->towrite < 0) { state->towrite = size; @@ -983,14 +851,26 @@ int tcpip_put(COMSTACK h, char *buf, int size) } while (state->towrite > state->written) { - if ((res = send(h->iofile, buf + state->written, size - - state->written, 0)) < 0) + if ((res = + send(h->iofile, buf + state->written, size - + state->written, +#ifdef MSG_NOSIGNAL + MSG_NOSIGNAL +#else + 0 +#endif + )) < 0) { if ( #ifdef WIN32 WSAGetLastError() == WSAEWOULDBLOCK #else - errno == EAGAIN + errno == EWOULDBLOCK +#ifdef EAGAIN +#if EAGAIN != EWOULDBLOCK + || errno == EAGAIN +#endif +#endif #endif ) { @@ -1024,6 +904,7 @@ int ssl_put(COMSTACK h, char *buf, int size) TRC(fprintf(stderr, "ssl_put: size=%d\n", size)); h->io_pending = 0; + h->event = CS_DATA; if (state->towrite < 0) { state->towrite = size; @@ -1053,6 +934,7 @@ int ssl_put(COMSTACK h, char *buf, int size) yaz_log (LOG_LOG, "SSL_write. want_write"); return 1; } + h->cerrno = CSERRORSSL; return -1; } state->written += res; @@ -1127,3 +1009,26 @@ char *tcpip_addrstr(COMSTACK h) #endif return buf; } + +int static tcpip_set_blocking(COMSTACK p, int blocking) +{ + unsigned long flag; + + if (p->blocking == blocking) + return 1; +#ifdef WIN32 + flag = 1; + if (ioctlsocket(p->iofile, FIONBIO, &flag) < 0) + return 0; +#else + flag = fcntl(p->iofile, F_GETFL, 0); + if(!blocking) + flag = flag & ~O_NONBLOCK; + else + flag = flag | O_NONBLOCK; + if (fcntl(p->iofile, F_SETFL, flag) < 0) + return 0; +#endif + p->blocking = blocking; + return 1; +}