X-Git-Url: http://git.indexdata.com/?p=yaz-moved-to-github.git;a=blobdiff_plain;f=src%2Ftcpip.c;h=ac0001e8ef222695fc47cea455051fd5f6450c39;hp=3c448dd53860bf31d356dd8dba070f8ebf7bf9a9;hb=fcc2b1bffbd6dd86fc8f95f1e2e6e8b2a94e731e;hpb=4341559a11eeaa00d60efbefd0b3538abb2ef622 diff --git a/src/tcpip.c b/src/tcpip.c index 3c448dd..ac0001e 100644 --- a/src/tcpip.c +++ b/src/tcpip.c @@ -118,6 +118,7 @@ typedef struct tcpip_state int (*complete)(const char *buf, int len); /* length/complete. */ #if HAVE_GETADDRINFO struct addrinfo *ai; + struct addrinfo *ai_connect; #else struct sockaddr_in addr; /* returned by cs_straddr */ #endif @@ -205,6 +206,7 @@ COMSTACK tcpip_type(int s, int flags, int protocol, void *vp) #if HAVE_GETADDRINFO sp->ai = 0; + sp->ai_connect = 0; #endif sp->altbuf = 0; sp->altsize = sp->altlen = 0; @@ -418,13 +420,16 @@ void *tcpip_straddr(COMSTACK h, const char *str) if (sp->ai && h->state == CS_ST_UNBND) { int s = -1; - for (ai = sp->ai; ai; ai = ai->ai_next) + if (ipv6_only >= 0) { - if (ai->ai_family == AF_INET6) + for (ai = sp->ai; ai; ai = ai->ai_next) { - s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); - if (s != -1) - break; + if (ai->ai_family == AF_INET6) + { + s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); + if (s != -1) + break; + } } } if (s == -1) @@ -438,6 +443,7 @@ void *tcpip_straddr(COMSTACK h, const char *str) } if (s == -1) return 0; + TRC(fprintf(stderr, "First socket fd=%d\n", s)); assert(ai); h->iofile = s; if (ai->ai_family == AF_INET6 && ipv6_only >= 0 && @@ -489,6 +495,43 @@ int tcpip_more(COMSTACK h) return sp->altlen && (*sp->complete)(sp->altbuf, sp->altlen); } +static int cont_connect(COMSTACK h) +{ +#if HAVE_GETADDRINFO + tcpip_state *sp = (tcpip_state *)h->cprivate; + struct addrinfo *ai = sp->ai_connect; + while (ai && (ai = ai->ai_next)) + { + int s; + s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); + if (s != -1) + { +#if HAVE_GNUTLS_H + if (h->type == ssl_type && sp->session) + { + gnutls_bye(sp->session, GNUTLS_SHUT_WR); + gnutls_deinit(sp->session); + sp->session = 0; + } +#endif +#ifdef WIN32 + closesocket(h->iofile); +#else + close(h->iofile); +#endif + TRC(fprintf(stderr, "Other socket call fd=%d\n", s)); + h->state = CS_ST_UNBND; + h->iofile = s; + tcpip_set_blocking(h, h->flags); + return tcpip_connect(h, ai); + } +#endif + } + h->cerrno = CSYSERR; + return -1; +} + + /* * connect(2) will block (sometimes) - nothing we can do short of doing * weird things like spawning subprocesses or threading or some weird junk @@ -512,8 +555,7 @@ int tcpip_connect(COMSTACK h, void *address) } #if HAVE_GETADDRINFO r = connect(h->iofile, ai->ai_addr, ai->ai_addrlen); - freeaddrinfo(sp->ai); - sp->ai = 0; + sp->ai_connect = ai; #else r = connect(h->iofile, (struct sockaddr *) add, sizeof(*add)); #endif @@ -530,14 +572,14 @@ int tcpip_connect(COMSTACK h, void *address) #else if (yaz_errno() == EINPROGRESS) { + TRC(fprintf(stderr, "Pending fd=%d\n", h->iofile)); 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; + return cont_connect(h); } h->event = CS_CONNECT; h->state = CS_ST_CONNECTING; @@ -582,7 +624,7 @@ int tcpip_rcvconnect(COMSTACK h) { if (ssl_check_error(h, sp, res)) return 1; - return -1; + return cont_connect(h); } } #endif @@ -613,10 +655,7 @@ static int tcpip_bind(COMSTACK h, void *address, int mode) if (h->type == ssl_type && !sp->session) { int res; - gnutls_global_init(); - tcpip_create_cred(h); - res = gnutls_certificate_set_x509_key_file(sp->cred_ptr->xcred, sp->cert_fname, sp->cert_fname, @@ -1144,8 +1183,7 @@ int tcpip_put(COMSTACK h, char *buf, int size) h->io_pending = CS_WANT_WRITE; return 1; } - h->cerrno = CSYSERR; - return -1; + return cont_connect(h); } state->written += res; TRC(fprintf(stderr, " Wrote %d, written=%d, nbytes=%d\n",