X-Git-Url: http://git.indexdata.com/?p=yaz-moved-to-github.git;a=blobdiff_plain;f=comstack%2Ftcpip.c;h=ab08873e7921043b0ccfe2a762d09c351bbfc7b8;hp=a7d33d23de30ffddc955a1e2bc13695db5c498db;hb=c71d717ada2a9ef730d527f161eb5ba9aa641a9f;hpb=fa4bfbc45c934a9431f40588c519085eff9e8ae6 diff --git a/comstack/tcpip.c b/comstack/tcpip.c index a7d33d2..ab08873 100644 --- a/comstack/tcpip.c +++ b/comstack/tcpip.c @@ -1,16 +1,19 @@ /* - * Copyright (c) 1995-2002, Index Data + * Copyright (c) 1995-2003, Index Data * See the file LICENSE for details. * - * $Id: tcpip.c,v 1.49 2002-09-20 22:23:13 adam Exp $ + * $Id: tcpip.c,v 1.59 2003-10-08 21:47:15 adam Exp $ */ #include #include #include -#ifndef WIN32 + +#ifdef WIN32 +#else #include #endif + #include #include #include @@ -22,30 +25,33 @@ #include #include #include +#include -/* Chas added the following, so we get the definition of completeBER */ -#include +#ifdef WIN32 +#else +#include +#endif -int tcpip_close(COMSTACK h); -int tcpip_put(COMSTACK h, char *buf, int size); -int tcpip_get(COMSTACK h, char **buf, int *bufsize); -int tcpip_connect(COMSTACK h, void *address); -int tcpip_more(COMSTACK h); -int tcpip_rcvconnect(COMSTACK h); -int tcpip_bind(COMSTACK h, void *address, int mode); -int tcpip_listen(COMSTACK h, char *raddr, int *addrlen, +static int tcpip_close(COMSTACK h); +static int tcpip_put(COMSTACK h, char *buf, int size); +static int tcpip_get(COMSTACK h, char **buf, int *bufsize); +static int tcpip_connect(COMSTACK h, void *address); +static int tcpip_more(COMSTACK h); +static int tcpip_rcvconnect(COMSTACK h); +static int tcpip_bind(COMSTACK h, void *address, int mode); +static 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); +static int tcpip_set_blocking(COMSTACK p, int blocking); #if HAVE_OPENSSL_SSL_H -int ssl_get(COMSTACK h, char **buf, int *bufsize); -int ssl_put(COMSTACK h, char *buf, int size); +static int ssl_get(COMSTACK h, char **buf, int *bufsize); +static int ssl_put(COMSTACK h, char *buf, int size); #endif -COMSTACK tcpip_accept(COMSTACK h); -char *tcpip_addrstr(COMSTACK h); -void *tcpip_straddr(COMSTACK h, const char *str); +static COMSTACK tcpip_accept(COMSTACK h); +static char *tcpip_addrstr(COMSTACK h); +static void *tcpip_straddr(COMSTACK h, const char *str); #if 0 #define TRC(x) x @@ -128,19 +134,19 @@ COMSTACK tcpip_type(int s, int blocking, int protocol, void *vp) xmalloc(sizeof(tcpip_state))))) return 0; + if (!((p->blocking = blocking)&1)) + { #ifdef WIN32 - if (!(p->blocking = blocking) && ioctlsocket(s, FIONBIO, &tru) < 0) - return 0; + if (ioctlsocket(s, FIONBIO, &tru) < 0) + return 0; #else - if (!(p->blocking = blocking)) - { if (fcntl(s, F_SETFL, O_NONBLOCK) < 0) return 0; #ifndef MSG_NOSIGNAL signal (SIGPIPE, SIG_IGN); #endif - } #endif + } p->io_pending = 0; p->iofile = s; @@ -176,7 +182,7 @@ COMSTACK tcpip_type(int s, int blocking, int protocol, void *vp) if (protocol == PROTO_WAIS) state->complete = completeWAIS; else - state->complete = completeBER; + state->complete = cs_complete_auto; p->timeout = COMSTACK_DEFAULT_TIMEOUT; TRC(fprintf(stderr, "Created new TCPIP comstack\n")); @@ -219,11 +225,12 @@ COMSTACK ssl_type(int s, int blocking, int protocol, void *vp) } #endif -int tcpip_strtoaddr_ex(const char *str, struct sockaddr_in *add) +int tcpip_strtoaddr_ex(const char *str, struct sockaddr_in *add, + int default_port) { struct hostent *hp; char *p, buf[512]; - short int port = 210; + short int port = default_port; unsigned tmpadd; if (!tcpip_init ()) @@ -255,8 +262,12 @@ int tcpip_strtoaddr_ex(const char *str, struct sockaddr_in *add) void *tcpip_straddr(COMSTACK h, const char *str) { tcpip_state *sp = (tcpip_state *)h->cprivate; + int port = 210; - if (!tcpip_strtoaddr_ex (str, &sp->addr)) + if (h->protocol == PROTO_HTTP) + port = 80; + + if (!tcpip_strtoaddr_ex (str, &sp->addr, port)) return 0; return &sp->addr; } @@ -265,7 +276,7 @@ struct sockaddr_in *tcpip_strtoaddr(const char *str) { static struct sockaddr_in add; - if (!tcpip_strtoaddr_ex (str, &add)) + if (!tcpip_strtoaddr_ex (str, &add, 210)) return 0; return &add; } @@ -290,7 +301,10 @@ int tcpip_connect(COMSTACK h, void *address) tcpip_state *sp = (tcpip_state *)h->cprivate; #endif int r; - +#ifdef __sun__ + int recbuflen; + YAZ_SOCKLEN_T rbufsize = sizeof(recbuflen); +#endif TRC(fprintf(stderr, "tcpip_connect\n")); h->io_pending = 0; if (h->state != CS_ST_UNBND) @@ -298,6 +312,32 @@ int tcpip_connect(COMSTACK h, void *address) h->cerrno = CSOUTSTATE; return -1; } +#ifdef __sun__ + /* On Suns, you must set a bigger Receive Buffer BEFORE a call to connect + * This gives the connect a chance to negotiate with the other side + * (see 'man tcp') + */ + if ( getsockopt(h->iofile, SOL_SOCKET, SO_RCVBUF, (void *)&recbuflen, &rbufsize ) < 0 ) + { + h->cerrno = CSYSERR; + return -1; + } + TRC(fprintf( stderr, "Current Size of TCP Receive Buffer= %d\n", + recbuflen )); + recbuflen *= 10; /* lets be optimistic */ + if ( setsockopt(h->iofile, SOL_SOCKET, SO_RCVBUF, (void *)&recbuflen, rbufsize ) < 0 ) + { + h->cerrno = CSYSERR; + return -1; + } + if ( getsockopt(h->iofile, SOL_SOCKET, SO_RCVBUF, (void *)&recbuflen, &rbufsize ) ) + { + h->cerrno = CSYSERR; + return -1; + } + TRC(fprintf( stderr, "New Size of TCP Receive Buffer = %d\n", + recbuflen )); +#endif r = connect(h->iofile, (struct sockaddr *) add, sizeof(*add)); if (r < 0) { @@ -310,7 +350,7 @@ int tcpip_connect(COMSTACK h, void *address) return 1; } #else - if (errno == EINPROGRESS) + if (yaz_errno() == EINPROGRESS) { h->event = CS_CONNECT; h->state = CS_ST_CONNECTING; @@ -332,7 +372,9 @@ int tcpip_connect(COMSTACK h, void *address) */ int tcpip_rcvconnect(COMSTACK h) { +#if HAVE_OPENSSL_SSL_H tcpip_state *sp = (tcpip_state *)h->cprivate; +#endif TRC(fprintf(stderr, "tcpip_rcvconnect\n")); if (h->state == CS_ST_DATAXFER) @@ -379,7 +421,28 @@ int tcpip_rcvconnect(COMSTACK h) #define CERTF "ztest.pem" #define KEYF "ztest.pem" -int tcpip_bind(COMSTACK h, void *address, int mode) +static void tcpip_setsockopt (int fd) +{ +#if 0 + int len = 4096; + int set = 1; + + if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int))) + { + yaz_log(LOG_WARN|LOG_ERRNO, "setsockopt TCP_NODELAY"); + } + if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int))) + { + yaz_log(LOG_WARN|LOG_ERRNO, "setsockopt SNDBUF"); + } + if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int))) + { + yaz_log(LOG_WARN|LOG_ERRNO, "setsockopt RCVBUF"); + } +#endif +} + +static int tcpip_bind(COMSTACK h, void *address, int mode) { struct sockaddr *addr = (struct sockaddr *)address; #ifdef WIN32 @@ -433,6 +496,7 @@ int tcpip_bind(COMSTACK h, void *address, int mode) return -1; } #endif + tcpip_setsockopt(h->iofile); if (bind(h->iofile, addr, sizeof(struct sockaddr_in))) { h->cerrno = CSYSERR; @@ -468,10 +532,10 @@ int tcpip_listen(COMSTACK h, char *raddr, int *addrlen, #ifdef WIN32 WSAGetLastError() == WSAEWOULDBLOCK #else - errno == EWOULDBLOCK + yaz_errno() == EWOULDBLOCK #ifdef EAGAIN #if EAGAIN != EWOULDBLOCK - || errno == EAGAIN + || yaz_errno() == EAGAIN #endif #endif #endif @@ -498,6 +562,7 @@ int tcpip_listen(COMSTACK h, char *raddr, int *addrlen, return -1; } h->state = CS_ST_INCON; + tcpip_setsockopt (h->newfd); return 0; } @@ -541,11 +606,11 @@ COMSTACK tcpip_accept(COMSTACK h) } return 0; } - if (!cnew->blocking && + if (!(cnew->blocking&1) && #ifdef WIN32 (ioctlsocket(cnew->iofile, FIONBIO, &tru) < 0) #else - (!cnew->blocking && fcntl(cnew->iofile, F_SETFL, O_NONBLOCK) < 0) + (fcntl(cnew->iofile, F_SETFL, O_NONBLOCK) < 0) #endif ) { @@ -659,10 +724,17 @@ int tcpip_get(COMSTACK h, char **buf, int *bufsize) else if (*bufsize - hasread < CS_TCPIP_BUFCHUNK) if (!(*buf =(char *)xrealloc(*buf, *bufsize *= 2))) return -1; +#ifdef __sun__ + yaz_set_errno( 0 ); + /* unfortunatly, sun sometimes forgets to set errno in recv + when EWOULDBLOCK etc. would be required (res = -1) */ +#endif res = recv(h->iofile, *buf + hasread, CS_TCPIP_BUFCHUNK, 0); TRC(fprintf(stderr, " recv res=%d, hasread=%d\n", res, hasread)); if (res < 0) { + TRC(fprintf(stderr, " recv errno=%d, (%s)\n", yaz_errno(), + strerror(yaz_errno()))); #ifdef WIN32 if (WSAGetLastError() == WSAEWOULDBLOCK) { @@ -672,25 +744,25 @@ int tcpip_get(COMSTACK h, char **buf, int *bufsize) else return -1; #else - if (errno == EWOULDBLOCK + if (yaz_errno() == EWOULDBLOCK #ifdef EAGAIN #if EAGAIN != EWOULDBLOCK - || errno == EAGAIN + || yaz_errno() == EAGAIN #endif #endif - || errno == EINPROGRESS + || yaz_errno() == EINPROGRESS #ifdef __sun__ - || errno == ENOENT /* Sun's sometimes set errno to this */ + || yaz_errno() == ENOENT /* Sun's sometimes set errno to this */ #endif ) { h->io_pending = CS_WANT_READ; break; } - else if (errno == 0) + else if (yaz_errno() == 0) continue; else - return -1; + return -1; #endif } else if (!res) @@ -847,12 +919,16 @@ int tcpip_put(COMSTACK h, char *buf, int size) #ifdef WIN32 WSAGetLastError() == WSAEWOULDBLOCK #else - errno == EWOULDBLOCK + yaz_errno() == EWOULDBLOCK #ifdef EAGAIN #if EAGAIN != EWOULDBLOCK - || errno == EAGAIN + || yaz_errno() == EAGAIN #endif #endif +#ifdef __sun__ + || yaz_errno() == ENOENT /* Sun's sometimes set errno to this value! */ +#endif + || yaz_errno() == EINPROGRESS #endif ) { @@ -967,7 +1043,7 @@ char *tcpip_addrstr(COMSTACK h) { struct sockaddr_in addr; tcpip_state *sp = (struct tcpip_state *)h->cprivate; - char *r, *buf = sp->buf; + char *r = 0, *buf = sp->buf; YAZ_SOCKLEN_T len; struct hostent *host; @@ -977,15 +1053,25 @@ char *tcpip_addrstr(COMSTACK h) h->cerrno = CSYSERR; return 0; } - if ((host = gethostbyaddr((char*)&addr.sin_addr, sizeof(addr.sin_addr), + if (!(h->blocking&2)) { + if ((host = gethostbyaddr((char*)&addr.sin_addr, sizeof(addr.sin_addr), AF_INET))) - r = (char*) host->h_name; - else + r = (char*) host->h_name; + } + if (!r) r = inet_ntoa(addr.sin_addr); - sprintf(buf, "tcp:%s", r); + if (h->protocol == PROTO_HTTP) + sprintf(buf, "http:%s", r); + else + sprintf(buf, "tcp:%s", r); #if HAVE_OPENSSL_SSL_H if (sp->ctx) - sprintf(buf, "ssl:%s", r); + { + if (h->protocol == PROTO_HTTP) + sprintf(buf, "https:%s", r); + else + sprintf(buf, "ssl:%s", r); + } #endif return buf; } @@ -1002,7 +1088,7 @@ int static tcpip_set_blocking(COMSTACK p, int blocking) return 0; #else flag = fcntl(p->iofile, F_GETFL, 0); - if(!blocking) + if(!(blocking&1)) flag = flag & ~O_NONBLOCK; else flag = flag | O_NONBLOCK;