From c5fdeef41d50d5207c52507e17eadc1ba1e4c5f0 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 1 Oct 2001 08:59:17 +0000 Subject: introduced non-blocking connects --- lib/connect.c | 275 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 275 insertions(+) create mode 100644 lib/connect.c (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c new file mode 100644 index 000000000..4bff6d699 --- /dev/null +++ b/lib/connect.c @@ -0,0 +1,275 @@ +/***************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2001, Daniel Stenberg, , et al. + * + * In order to be useful for every potential user, curl and libcurl are + * dual-licensed under the MPL and the MIT/X-derivate licenses. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the MPL or the MIT/X-derivate + * licenses. You may pick one of these licenses. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * $Id$ + *****************************************************************************/ + +#include "setup.h" + +#ifndef WIN32 +#include +#include +#include +#include +#include +#include +#include +#include +#endif +#include +#include + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +#ifdef WIN32 +#define HAVE_IOCTLSOCKET +#include +#include +#define EINPROGRESS WSAEINPROGRESS +#define EWOULDBLOCK WSAEWOULDBLOCK +#endif + +#include "urldata.h" +#include "sendf.h" + +/* The last #include file should be: */ +#ifdef MALLOCDEBUG +#include "memdebug.h" +#endif + +/************************************************************************* + * Curl_nonblock + * + * Description: + * Set the socket to either blocking or non-blocking mode. + */ +static +int nonblock(int socket, /* operate on this */ + int nonblock /* TRUE or FALSE */) +{ +#undef SETBLOCK +#ifdef HAVE_O_NONBLOCK + int flags; + + flags = fcntl(socket, F_GETFL, 0); + if (TRUE == nonblock) + return fcntl(socket, F_SETFL, flags | O_NONBLOCK); + else + return fcntl(socket, F_SETFL, flags & (~O_NONBLOCK)); +#define SETBLOCK 1 +#endif + +#ifdef HAVE_FIONBIO + int flags; + + flags = nonblock; + return ioctl(socket, FIONBIO, &flags); +#define SETBLOCK 2 +#endif + +#ifdef HAVE_IOCTLSOCKET + int flags; + flags = nonblock; + return ioctlsocket(socket, FIONBIO, &flags); +#define SETBLOCK 3 +#endif + +#ifdef HAVE_IOCTLSOCKET_CASE + return IoctlSocket(socket, FIONBIO, (long)nonblock); +#define SETBLOCK 4 +#endif + +#ifdef HAVE_DISABLED_NONBLOCKING + return 0; /* returns success */ +#define SETBLOCK 5 +#endif + +#ifndef SETBLOCK +#error "no non-blocking method was found/used/set" +#endif +} + +/* + * Return 0 on fine connect, -1 on error and 1 on timeout. + */ +static +int waitconnect(int sockfd, /* socket */ + int timeout_msec) +{ + fd_set fd; + struct timeval interval; + int rc; + + /* now select() until we get connect or timeout */ + FD_ZERO(&fd); + FD_SET(sockfd, &fd); + + interval.tv_sec = timeout_msec/1000; + timeout_msec -= interval.tv_sec*1000; + + interval.tv_usec = timeout_msec*1000; + + rc = select(sockfd+1, NULL, &fd, NULL, &interval); + if(-1 == rc) + /* error, no connect here, try next */ + return -1; + + else if(0 == rc) + /* timeout, no connect today */ + return 1; + + /* we have a connect! */ + return 0; +} + +/* + * TCP connect to the given host with timeout, proxy or remote doesn't matter. + * There might be more than one IP address to try out. Fill in the passed + * pointer with the connected socket. + */ + +CURLcode Curl_connecthost(struct connectdata *conn, + int sockfd, /* input socket, or -1 if none */ + int *socket) +{ + struct SessionHandle *data = conn->data; + int rc; + +#ifdef ENABLE_IPV6 + /* + * Connecting with IPv6 support is so much easier and cleanly done + */ + if(sockfd != -1) + /* don't use any previous one, it might be of wrong type */ + sclose(sockfd); + sockfd = -1; /* none! */ + for (ai = conn->hp; ai; ai = ai->ai_next) { + sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); + if (sockfd < 0) + continue; + + /* set socket non-blocking */ + nonblock(sockfd, TRUE); + + rc = connect(sockfd, ai->ai_addr, ai->ai_addrlen); + + if(0 == rc) + /* direct connect, awesome! */ + break; + + /* asynchronous connect, wait for connect or timeout */ + rc = waitconnect(sockfd, timeout); + if(0 != rc) { + /* connect failed or timed out */ + sclose(sockfd); + sockfd = -1; + continue; + } + + /* now disable the non-blocking mode again */ + nonblock(sockfd, FALSE); + break; + } + conn->ai = ai; + if (sockfd < 0) { + failf(data, strerror(errno)); + return CURLE_COULDNT_CONNECT; + } +#else + /* + * Connecting with IPv4-only support + */ + int aliasindex; + int timeout_ms = 10000; /* while testing */ + + /* non-block socket */ + nonblock(sockfd, TRUE); + + /* This is the loop that attempts to connect to all IP-addresses we + know for the given host. One by one. */ + for(rc=-1, aliasindex=0; + rc && (struct in_addr *)conn->hp->h_addr_list[aliasindex]; + aliasindex++) { + + /* copy this particular name info to the conn struct as it might + be used later in the krb4 "system" */ + memset((char *) &conn->serv_addr, '\0', sizeof(conn->serv_addr)); + memcpy((char *)&(conn->serv_addr.sin_addr), + (struct in_addr *)conn->hp->h_addr_list[aliasindex], + sizeof(struct in_addr)); + conn->serv_addr.sin_family = conn->hp->h_addrtype; + conn->serv_addr.sin_port = htons(conn->port); + + rc = connect(sockfd, (struct sockaddr *)&(conn->serv_addr), + sizeof(conn->serv_addr)); + + if(-1 == rc) { + int error; +#ifdef WIN32 + error = (int)GetLastError(); +#else + error = errno; +#endif + switch (error) { + case EINPROGRESS: + case EWOULDBLOCK: +#if defined(EAGAIN) && EAGAIN != EWOULDBLOCK + /* On some platforms EAGAIN and EWOULDBLOCK are the + * same value, and on others they are different, hence + * the odd #if + */ + case EAGAIN: +#endif + + /* asynchronous connect, wait for connect or timeout */ + rc = waitconnect(sockfd, timeout_ms); + break; + default: + /* unknown error, fallthrough and try another address! */ + break; + } + } + + if(0 != rc) + continue; /* try next address */ + else + break; + } + if(-1 == rc) { + /* no good connect was made */ + sclose(sockfd); + *socket = -1; + failf(data, "Couldn't connect to (any) IP address"); + return CURLE_COULDNT_CONNECT; + } + + /* now disable the non-blocking mode again */ + nonblock(sockfd, FALSE); + +#endif + + *socket = sockfd; /* pass this to our parent */ + + return CURLE_OK; +} + -- cgit v1.2.1 From ede5b54edce67f9848a0190dce3dd47e17c335a6 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 1 Oct 2001 11:25:27 +0000 Subject: corrected the #include files --- lib/connect.c | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 4bff6d699..e4fd94815 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -24,14 +24,24 @@ #include "setup.h" #ifndef WIN32 +/* headers for non-win32 */ #include #include #include #include +#ifdef HAVE_UNISTD_H #include +#endif +#ifdef HAVE_NETDB_H #include -#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_NETINET_IN_H #include +#endif + #endif #include #include @@ -65,7 +75,7 @@ */ static int nonblock(int socket, /* operate on this */ - int nonblock /* TRUE or FALSE */) + int nonblock /* TRUE or FALSE */) { #undef SETBLOCK #ifdef HAVE_O_NONBLOCK @@ -149,12 +159,16 @@ int waitconnect(int sockfd, /* socket */ */ CURLcode Curl_connecthost(struct connectdata *conn, + long timeout_ms, int sockfd, /* input socket, or -1 if none */ int *socket) { struct SessionHandle *data = conn->data; int rc; + struct timeval after; + struct timeval before = Curl_tvnow(); + #ifdef ENABLE_IPV6 /* * Connecting with IPv6 support is so much easier and cleanly done @@ -178,11 +192,16 @@ CURLcode Curl_connecthost(struct connectdata *conn, break; /* asynchronous connect, wait for connect or timeout */ - rc = waitconnect(sockfd, timeout); + rc = waitconnect(sockfd, timeout_ms); if(0 != rc) { /* connect failed or timed out */ sclose(sockfd); sockfd = -1; + + /* get a new timeout for next attempt */ + after = Curl_tvnow(); + timeout_ms -= (long)(Curl_tvdiff(after, before)*1000); + before = after; continue; } @@ -200,7 +219,6 @@ CURLcode Curl_connecthost(struct connectdata *conn, * Connecting with IPv4-only support */ int aliasindex; - int timeout_ms = 10000; /* while testing */ /* non-block socket */ nonblock(sockfd, TRUE); @@ -250,8 +268,13 @@ CURLcode Curl_connecthost(struct connectdata *conn, } } - if(0 != rc) + if(0 != rc) { + /* get a new timeout for next attempt */ + after = Curl_tvnow(); + timeout_ms -= (long)(Curl_tvdiff(after, before)*1000); + before = after; continue; /* try next address */ + } else break; } -- cgit v1.2.1 From 6918427faefa32212423cd8eb3db789d84264929 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 1 Oct 2001 22:32:37 +0000 Subject: conn->hp is now conn->hostaddr changed the Curl_connethost() proto again --- lib/connect.c | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index e4fd94815..34dd72c28 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -160,6 +160,8 @@ int waitconnect(int sockfd, /* socket */ CURLcode Curl_connecthost(struct connectdata *conn, long timeout_ms, + Curl_addrinfo *remotehost, + int port, int sockfd, /* input socket, or -1 if none */ int *socket) { @@ -177,7 +179,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* don't use any previous one, it might be of wrong type */ sclose(sockfd); sockfd = -1; /* none! */ - for (ai = conn->hp; ai; ai = ai->ai_next) { + for (ai = remotehost; ai; ai = ai->ai_next) { sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (sockfd < 0) continue; @@ -219,6 +221,14 @@ CURLcode Curl_connecthost(struct connectdata *conn, * Connecting with IPv4-only support */ int aliasindex; + struct sockaddr_in serv_addr; + + if(-1 == sockfd) + /* create an ordinary socket if none was provided */ + sockfd = socket(AF_INET, SOCK_STREAM, 0); + + if(-1 == sockfd) + return CURLE_COULDNT_CONNECT; /* big time error */ /* non-block socket */ nonblock(sockfd, TRUE); @@ -226,20 +236,20 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* This is the loop that attempts to connect to all IP-addresses we know for the given host. One by one. */ for(rc=-1, aliasindex=0; - rc && (struct in_addr *)conn->hp->h_addr_list[aliasindex]; + rc && (struct in_addr *)remotehost->h_addr_list[aliasindex]; aliasindex++) { /* copy this particular name info to the conn struct as it might be used later in the krb4 "system" */ - memset((char *) &conn->serv_addr, '\0', sizeof(conn->serv_addr)); - memcpy((char *)&(conn->serv_addr.sin_addr), - (struct in_addr *)conn->hp->h_addr_list[aliasindex], + memset((char *) &serv_addr, '\0', sizeof(serv_addr)); + memcpy((char *)&(serv_addr.sin_addr), + (struct in_addr *)remotehost->h_addr_list[aliasindex], sizeof(struct in_addr)); - conn->serv_addr.sin_family = conn->hp->h_addrtype; - conn->serv_addr.sin_port = htons(conn->port); + serv_addr.sin_family = remotehost->h_addrtype; + serv_addr.sin_port = htons(port); - rc = connect(sockfd, (struct sockaddr *)&(conn->serv_addr), - sizeof(conn->serv_addr)); + rc = connect(sockfd, (struct sockaddr *)&serv_addr, + sizeof(serv_addr)); if(-1 == rc) { int error; @@ -275,8 +285,13 @@ CURLcode Curl_connecthost(struct connectdata *conn, before = after; continue; /* try next address */ } - else - break; + else { + /* copy this particular name info to the conn struct as it might + be used later in the krb4 "system" */ + memcpy((char *) &conn->serv_addr, &serv_addr, + sizeof(conn->serv_addr)); + } + break; } if(-1 == rc) { /* no good connect was made */ -- cgit v1.2.1 From dc27488c47ececa8801c9173006a103f190e73e7 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 1 Oct 2001 22:42:46 +0000 Subject: corrected for IPv6 --- lib/connect.c | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 34dd72c28..ec68162c3 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -172,6 +172,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, struct timeval before = Curl_tvnow(); #ifdef ENABLE_IPV6 + struct addrinfo *ai; /* * Connecting with IPv6 support is so much easier and cleanly done */ -- cgit v1.2.1 From 3298630500cc1ee4e71ea53c4af68301a68cb35e Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 1 Oct 2001 22:50:03 +0000 Subject: removed warning --- lib/connect.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index ec68162c3..8ff3dd16f 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -176,6 +176,8 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* * Connecting with IPv6 support is so much easier and cleanly done */ + port =0; /* we already have port in the 'remotehost' struct */ + if(sockfd != -1) /* don't use any previous one, it might be of wrong type */ sclose(sockfd); -- cgit v1.2.1 From 9f77771ff9708629cc9866909e3d0883028bca63 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 1 Oct 2001 23:25:26 +0000 Subject: faster bailout on timeouts --- lib/connect.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 8ff3dd16f..ef891d713 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -206,6 +206,8 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* get a new timeout for next attempt */ after = Curl_tvnow(); timeout_ms -= (long)(Curl_tvdiff(after, before)*1000); + if(timeout_ms < 0) + break; before = after; continue; } @@ -285,6 +287,8 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* get a new timeout for next attempt */ after = Curl_tvnow(); timeout_ms -= (long)(Curl_tvdiff(after, before)*1000); + if(timeout_ms < 0) + break; before = after; continue; /* try next address */ } -- cgit v1.2.1 From 51ca5fcbe0745cc4e245ffb69b339d1987be3b88 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 2 Oct 2001 09:40:06 +0000 Subject: major connecting updates --- lib/connect.c | 233 ++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 203 insertions(+), 30 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index ef891d713..a5c2ddeb4 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -41,10 +41,14 @@ #ifdef HAVE_NETINET_IN_H #include #endif +#ifdef HAVE_ARPA_INET_H +#include +#endif #endif #include #include +#include #ifndef TRUE #define TRUE 1 @@ -61,6 +65,7 @@ #include "urldata.h" #include "sendf.h" +#include "if2ip.h" /* The last #include file should be: */ #ifdef MALLOCDEBUG @@ -152,25 +157,189 @@ int waitconnect(int sockfd, /* socket */ return 0; } +static CURLcode bindlocal(struct connectdata *conn, + int sockfd) +{ +#if !defined(WIN32)||defined(__CYGWIN32__) + /* We don't generally like checking for OS-versions, we should make this + HAVE_XXXX based, although at the moment I don't have a decent test for + this! */ + +#ifdef HAVE_INET_NTOA + +#ifndef INADDR_NONE +#define INADDR_NONE (unsigned long) ~0 +#endif + +#ifndef ENABLE_IPV6 + struct SessionHandle *data = conn->data; + + /************************************************************* + * Select device to bind socket to + *************************************************************/ + if (strlen(data->set.device)<255) { + struct sockaddr_in sa; + struct hostent *h=NULL; + char *hostdataptr=NULL; + size_t size; + char myhost[256] = ""; + unsigned long in; + + if(Curl_if2ip(data->set.device, myhost, sizeof(myhost))) { + h = Curl_getaddrinfo(data, myhost, 0, &hostdataptr); + } + else { + if(strlen(data->set.device)>1) { + h = Curl_getaddrinfo(data, data->set.device, 0, &hostdataptr); + } + if(h) { + /* we know data->set.device is shorter than the myhost array */ + strcpy(myhost, data->set.device); + } + } + + if(! *myhost) { + /* need to fix this + h=Curl_gethost(data, + getmyhost(*myhost,sizeof(myhost)), + hostent_buf, + sizeof(hostent_buf)); + */ + if(hostdataptr) + free(hostdataptr); /* allocated by Curl_getaddrinfo() */ + return CURLE_HTTP_PORT_FAILED; + } + + infof(data, "We bind local end to %s\n", myhost); + + if ( (in=inet_addr(myhost)) != INADDR_NONE ) { + + if ( h ) { + memset((char *)&sa, 0, sizeof(sa)); + memcpy((char *)&sa.sin_addr, + h->h_addr, + h->h_length); + sa.sin_family = AF_INET; + sa.sin_addr.s_addr = in; + sa.sin_port = 0; /* get any port */ + + if( bind(sockfd, (struct sockaddr *)&sa, sizeof(sa)) >= 0) { + /* we succeeded to bind */ + struct sockaddr_in add; + + size = sizeof(add); + if(getsockname(sockfd, (struct sockaddr *) &add, + (socklen_t *)&size)<0) { + failf(data, "getsockname() failed"); + return CURLE_HTTP_PORT_FAILED; + } + } + else { + switch(errno) { + case EBADF: + failf(data, "Invalid descriptor: %d", errno); + break; + case EINVAL: + failf(data, "Invalid request: %d", errno); + break; + case EACCES: + failf(data, "Address is protected, user not superuser: %d", errno); + break; + case ENOTSOCK: + failf(data, + "Argument is a descriptor for a file, not a socket: %d", + errno); + break; + case EFAULT: + failf(data, "Inaccessable memory error: %d", errno); + break; + case ENAMETOOLONG: + failf(data, "Address too long: %d", errno); + break; + case ENOMEM: + failf(data, "Insufficient kernel memory was available: %d", errno); + break; + default: + failf(data,"errno %d\n"); + } /* end of switch */ + + return CURLE_HTTP_PORT_FAILED; + } /* end of else */ + + } /* end of if h */ + else { + failf(data,"could't find my own IP address (%s)", myhost); + return CURLE_HTTP_PORT_FAILED; + } + } /* end of inet_addr */ + + else { + failf(data, "could't find my own IP address (%s)", myhost); + return CURLE_HTTP_PORT_FAILED; + } + + if(hostdataptr) + free(hostdataptr); /* allocated by Curl_getaddrinfo() */ + + return CURLE_OK; + + } /* end of device selection support */ +#endif /* end of HAVE_INET_NTOA */ +#endif /* end of not WIN32 */ +#endif /*ENABLE_IPV6*/ + + return CURLE_HTTP_PORT_FAILED; +} + /* * TCP connect to the given host with timeout, proxy or remote doesn't matter. * There might be more than one IP address to try out. Fill in the passed * pointer with the connected socket. */ -CURLcode Curl_connecthost(struct connectdata *conn, - long timeout_ms, - Curl_addrinfo *remotehost, - int port, - int sockfd, /* input socket, or -1 if none */ - int *socket) +CURLcode Curl_connecthost(struct connectdata *conn, /* context */ + Curl_addrinfo *remotehost, /* use one in here */ + int port, /* connect to this */ + int *socket, /* the connected socket */ + Curl_ipconnect **addr) /* the one we used */ { struct SessionHandle *data = conn->data; int rc; + int sockfd; + int aliasindex=0; struct timeval after; struct timeval before = Curl_tvnow(); + /************************************************************* + * Figure out what maximum time we have left + *************************************************************/ + long timeout_ms=300000; /* milliseconds, default to five minutes */ + if(data->set.timeout || data->set.connecttimeout) { + double has_passed; + + /* Evaluate how much that that has passed */ + has_passed = Curl_tvdiff(Curl_tvnow(), data->progress.start); + +#ifndef min +#define min(a, b) ((a) < (b) ? (a) : (b)) +#endif + + /* get the most strict timeout of the ones converted to milliseconds */ + if(data->set.timeout && + (data->set.timeout>data->set.connecttimeout)) + timeout_ms = data->set.timeout*1000; + else + timeout_ms = data->set.connecttimeout*1000; + + /* subtract the passed time */ + timeout_ms -= (long)(has_passed * 1000); + + if(timeout_ms < 0) + /* a precaution, no need to continue if time already is up */ + return CURLE_OPERATION_TIMEOUTED; + } + #ifdef ENABLE_IPV6 struct addrinfo *ai; /* @@ -178,11 +347,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, */ port =0; /* we already have port in the 'remotehost' struct */ - if(sockfd != -1) - /* don't use any previous one, it might be of wrong type */ - sclose(sockfd); - sockfd = -1; /* none! */ - for (ai = remotehost; ai; ai = ai->ai_next) { + for (ai = remotehost; ai; ai = ai->ai_next, aliasindex++) { sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (sockfd < 0) continue; @@ -216,26 +381,33 @@ CURLcode Curl_connecthost(struct connectdata *conn, nonblock(sockfd, FALSE); break; } - conn->ai = ai; if (sockfd < 0) { failf(data, strerror(errno)); return CURLE_COULDNT_CONNECT; } + + if(addr) + *addr = ai; /* the address we ended up connected to */ + #else /* * Connecting with IPv4-only support */ - int aliasindex; - struct sockaddr_in serv_addr; - - if(-1 == sockfd) - /* create an ordinary socket if none was provided */ - sockfd = socket(AF_INET, SOCK_STREAM, 0); + /* create an IPv4 TCP socket */ + sockfd = socket(AF_INET, SOCK_STREAM, 0); if(-1 == sockfd) return CURLE_COULDNT_CONNECT; /* big time error */ + + if(conn->data->set.device) { + /* user selected to bind the outgoing socket to a specified "device" + before doing connect */ + CURLcode res = bindlocal(conn, sockfd); + if(res) + return res; + } - /* non-block socket */ + /* Convert socket to non-blocking type */ nonblock(sockfd, TRUE); /* This is the loop that attempts to connect to all IP-addresses we @@ -243,9 +415,9 @@ CURLcode Curl_connecthost(struct connectdata *conn, for(rc=-1, aliasindex=0; rc && (struct in_addr *)remotehost->h_addr_list[aliasindex]; aliasindex++) { + struct sockaddr_in serv_addr; - /* copy this particular name info to the conn struct as it might - be used later in the krb4 "system" */ + /* do this nasty work to do the connect */ memset((char *) &serv_addr, '\0', sizeof(serv_addr)); memcpy((char *)&(serv_addr.sin_addr), (struct in_addr *)remotehost->h_addr_list[aliasindex], @@ -279,6 +451,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, break; default: /* unknown error, fallthrough and try another address! */ + failf(data, "Failed to connect to IP number %d", aliasindex+1); break; } } @@ -287,33 +460,33 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* get a new timeout for next attempt */ after = Curl_tvnow(); timeout_ms -= (long)(Curl_tvdiff(after, before)*1000); - if(timeout_ms < 0) + if(timeout_ms < 0) { + failf(data, "Connect timeout on IP number %d", aliasindex+1); break; + } before = after; continue; /* try next address */ } - else { - /* copy this particular name info to the conn struct as it might - be used later in the krb4 "system" */ - memcpy((char *) &conn->serv_addr, &serv_addr, - sizeof(conn->serv_addr)); - } break; } if(-1 == rc) { /* no good connect was made */ sclose(sockfd); *socket = -1; - failf(data, "Couldn't connect to (any) IP address"); return CURLE_COULDNT_CONNECT; } /* now disable the non-blocking mode again */ nonblock(sockfd, FALSE); + if(addr) + /* this is the address we've connected to */ + *addr = (struct in_addr *)remotehost->h_addr_list[aliasindex]; #endif - *socket = sockfd; /* pass this to our parent */ + /* allow NULL-pointers to get passed in */ + if(socket) + *socket = sockfd; /* the socket descriptor we've connected */ return CURLE_OK; } -- cgit v1.2.1 From ced89553250030849a9896dae1d446c5ccf1ac3c Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 2 Oct 2001 11:26:53 +0000 Subject: IPv6 adjustments, connect()ing to bad ports still don't work properly for IPv6 --- lib/connect.c | 115 ++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 76 insertions(+), 39 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index a5c2ddeb4..a71e3b3e2 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -132,6 +132,7 @@ int waitconnect(int sockfd, /* socket */ int timeout_msec) { fd_set fd; + fd_set errfd; struct timeval interval; int rc; @@ -139,12 +140,15 @@ int waitconnect(int sockfd, /* socket */ FD_ZERO(&fd); FD_SET(sockfd, &fd); + FD_ZERO(&errfd); + FD_SET(sockfd, &errfd); + interval.tv_sec = timeout_msec/1000; timeout_msec -= interval.tv_sec*1000; interval.tv_usec = timeout_msec*1000; - rc = select(sockfd+1, NULL, &fd, NULL, &interval); + rc = select(sockfd+1, NULL, &fd, &errfd, &interval); if(-1 == rc) /* error, no connect here, try next */ return -1; @@ -153,10 +157,16 @@ int waitconnect(int sockfd, /* socket */ /* timeout, no connect today */ return 1; + if(FD_ISSET(sockfd, &errfd)) { + /* error condition caught */ + return 2; + } + /* we have a connect! */ return 0; } +#ifndef ENABLE_IPV6 static CURLcode bindlocal(struct connectdata *conn, int sockfd) { @@ -171,7 +181,6 @@ static CURLcode bindlocal(struct connectdata *conn, #define INADDR_NONE (unsigned long) ~0 #endif -#ifndef ENABLE_IPV6 struct SessionHandle *data = conn->data; /************************************************************* @@ -284,12 +293,12 @@ static CURLcode bindlocal(struct connectdata *conn, return CURLE_OK; } /* end of device selection support */ -#endif /* end of HAVE_INET_NTOA */ +#endif /* end of HAVE_INET_NTOA */ #endif /* end of not WIN32 */ -#endif /*ENABLE_IPV6*/ return CURLE_HTTP_PORT_FAILED; } +#endif /* end of ipv4-specific section */ /* * TCP connect to the given host with timeout, proxy or remote doesn't matter. @@ -341,54 +350,82 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ } #ifdef ENABLE_IPV6 - struct addrinfo *ai; /* * Connecting with IPv6 support is so much easier and cleanly done */ - port =0; /* we already have port in the 'remotehost' struct */ - - for (ai = remotehost; ai; ai = ai->ai_next, aliasindex++) { - sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); - if (sockfd < 0) - continue; + { + struct addrinfo *ai; - /* set socket non-blocking */ - nonblock(sockfd, TRUE); + for (ai = remotehost; ai; ai = ai->ai_next, aliasindex++) { + sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); + if (sockfd < 0) + continue; - rc = connect(sockfd, ai->ai_addr, ai->ai_addrlen); + /* set socket non-blocking */ + nonblock(sockfd, TRUE); - if(0 == rc) - /* direct connect, awesome! */ - break; - - /* asynchronous connect, wait for connect or timeout */ - rc = waitconnect(sockfd, timeout_ms); - if(0 != rc) { - /* connect failed or timed out */ - sclose(sockfd); - sockfd = -1; + rc = connect(sockfd, ai->ai_addr, ai->ai_addrlen); - /* get a new timeout for next attempt */ - after = Curl_tvnow(); - timeout_ms -= (long)(Curl_tvdiff(after, before)*1000); - if(timeout_ms < 0) + if(-1 == rc) { + int error; +#ifdef WIN32 + error = (int)GetLastError(); +#else + error = errno; +#endif + switch (error) { + case EINPROGRESS: + case EWOULDBLOCK: +#if defined(EAGAIN) && EAGAIN != EWOULDBLOCK + /* On some platforms EAGAIN and EWOULDBLOCK are the + * same value, and on others they are different, hence + * the odd #if + */ + case EAGAIN: +#endif + case EINTR: + + /* asynchronous connect, wait for connect or timeout */ + rc = waitconnect(sockfd, timeout_ms); + break; + case ECONNREFUSED: /* no one listening */ + default: + /* unknown error, fallthrough and try another address! */ + failf(data, "Failed to connect to IP number %d", aliasindex+1); + break; + } + } + if(0 == rc) + /* direct connect, awesome! */ break; - before = after; - continue; + + else { + /* connect failed or timed out */ + sclose(sockfd); + sockfd = -1; + + /* get a new timeout for next attempt */ + after = Curl_tvnow(); + timeout_ms -= (long)(Curl_tvdiff(after, before)*1000); + if(timeout_ms < 0) { + failf(data, "connect() timed out!"); + return CURLE_OPERATION_TIMEOUTED; + } + before = after; + continue; + } + } + if (sockfd < 0) { + failf(data, "connect() failed"); + return CURLE_COULDNT_CONNECT; } /* now disable the non-blocking mode again */ nonblock(sockfd, FALSE); - break; - } - if (sockfd < 0) { - failf(data, strerror(errno)); - return CURLE_COULDNT_CONNECT; - } - - if(addr) - *addr = ai; /* the address we ended up connected to */ + if(addr) + *addr = ai; /* the address we ended up connected to */ + } #else /* * Connecting with IPv4-only support -- cgit v1.2.1 From 72dbe9da72a827f16cc3c2437482397606096d3e Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 2 Oct 2001 17:18:46 +0000 Subject: praise Bjorn Reese for mastering these dusty corners of socket hacking, now we check for the error state before believing we are connected in IPv6 cases --- lib/connect.c | 82 +++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 52 insertions(+), 30 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index a71e3b3e2..6e2019e17 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -72,6 +72,16 @@ #include "memdebug.h" #endif +static +int geterrno(void) +{ +#ifdef WIN32 + return (int)GetLastError(); +#else + return errno; +#endif +} + /************************************************************************* * Curl_nonblock * @@ -300,6 +310,19 @@ static CURLcode bindlocal(struct connectdata *conn, } #endif /* end of ipv4-specific section */ +static +int socketerror(int sockfd) +{ + int err = 0; + socklen_t errSize = sizeof(err); + + if( -1 == getsockopt(sockfd, SOL_SOCKET, SO_ERROR, + (void *)&err, &errSize)) + err = geterrno(); + + return err; +} + /* * TCP connect to the given host with timeout, proxy or remote doesn't matter. * There might be more than one IP address to try out. Fill in the passed @@ -355,6 +378,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ */ { struct addrinfo *ai; + port =0; /* prevent compiler warning */ for (ai = remotehost; ai; ai = ai->ai_next, aliasindex++) { sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); @@ -367,12 +391,8 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ rc = connect(sockfd, ai->ai_addr, ai->ai_addrlen); if(-1 == rc) { - int error; -#ifdef WIN32 - error = (int)GetLastError(); -#else - error = errno; -#endif + int error=geterrno(); + switch (error) { case EINPROGRESS: case EWOULDBLOCK: @@ -391,29 +411,35 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ case ECONNREFUSED: /* no one listening */ default: /* unknown error, fallthrough and try another address! */ - failf(data, "Failed to connect to IP number %d", aliasindex+1); + failf(data, "Failed to connect"); break; } } - if(0 == rc) - /* direct connect, awesome! */ - break; + if(0 == rc) { + /* we might be connected, if the socket says it is OK! Ask it! */ + int err; - else { - /* connect failed or timed out */ - sclose(sockfd); - sockfd = -1; - - /* get a new timeout for next attempt */ - after = Curl_tvnow(); - timeout_ms -= (long)(Curl_tvdiff(after, before)*1000); - if(timeout_ms < 0) { - failf(data, "connect() timed out!"); - return CURLE_OPERATION_TIMEOUTED; - } - before = after; - continue; + err = socketerror(sockfd); + if ((0 == err) || (EISCONN == err)) { + /* we are connected, awesome! */ + break; + } + /* we are _not_ connected, it was a false alert, continue please */ } + + /* connect failed or timed out */ + sclose(sockfd); + sockfd = -1; + + /* get a new timeout for next attempt */ + after = Curl_tvnow(); + timeout_ms -= (long)(Curl_tvdiff(after, before)*1000); + if(timeout_ms < 0) { + failf(data, "connect() timed out!"); + return CURLE_OPERATION_TIMEOUTED; + } + before = after; + continue; } if (sockfd < 0) { failf(data, "connect() failed"); @@ -466,12 +492,8 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ sizeof(serv_addr)); if(-1 == rc) { - int error; -#ifdef WIN32 - error = (int)GetLastError(); -#else - error = errno; -#endif + int error=geterrno(); + switch (error) { case EINPROGRESS: case EWOULDBLOCK: -- cgit v1.2.1 From fdeaae678d4ce5152045fd034f32a29da9f6c5ff Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 5 Oct 2001 06:05:56 +0000 Subject: SM's patch applied, we should not use arguments or variables that have the same name as common functions... --- lib/connect.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 6e2019e17..206a43edc 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -308,8 +308,9 @@ static CURLcode bindlocal(struct connectdata *conn, return CURLE_HTTP_PORT_FAILED; } -#endif /* end of ipv4-specific section */ +#else /* end of ipv4-specific section */ +/* we only use socketerror() on IPv6-enabled machines */ static int socketerror(int sockfd) { @@ -322,6 +323,7 @@ int socketerror(int sockfd) return err; } +#endif /* * TCP connect to the given host with timeout, proxy or remote doesn't matter. @@ -331,9 +333,9 @@ int socketerror(int sockfd) CURLcode Curl_connecthost(struct connectdata *conn, /* context */ Curl_addrinfo *remotehost, /* use one in here */ - int port, /* connect to this */ - int *socket, /* the connected socket */ - Curl_ipconnect **addr) /* the one we used */ + int port, /* connect to this */ + int *sockconn, /* the connected socket */ + Curl_ipconnect **addr) /* the one we used */ { struct SessionHandle *data = conn->data; int rc; @@ -531,7 +533,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ if(-1 == rc) { /* no good connect was made */ sclose(sockfd); - *socket = -1; + *sockconn = -1; return CURLE_COULDNT_CONNECT; } @@ -544,8 +546,8 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ #endif /* allow NULL-pointers to get passed in */ - if(socket) - *socket = sockfd; /* the socket descriptor we've connected */ + if(sockconn) + *sockconn = sockfd; /* the socket descriptor we've connected */ return CURLE_OK; } -- cgit v1.2.1 From 7b5b60d2759a9d01f785705cef7aa7317b29d6e6 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 8 Oct 2001 06:56:00 +0000 Subject: hm, an unknown error from bind() when binding the outgoing socket would failf("%d") without the error as argument... it would always make a weird number get output --- lib/connect.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 206a43edc..1ec33ecab 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -279,8 +279,9 @@ static CURLcode bindlocal(struct connectdata *conn, failf(data, "Insufficient kernel memory was available: %d", errno); break; default: - failf(data,"errno %d\n"); - } /* end of switch */ + failf(data, "errno %d\n", errno); + break; + } /* end of switch(errno) */ return CURLE_HTTP_PORT_FAILED; } /* end of else */ -- cgit v1.2.1 From 532bca41e59e10a86c356058831cf046a3ba78c9 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 12 Oct 2001 12:32:20 +0000 Subject: Curl_tvdiff() now returns a millisecond diff, no double like before --- lib/connect.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 1ec33ecab..df34d7edc 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -353,7 +353,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ if(data->set.timeout || data->set.connecttimeout) { double has_passed; - /* Evaluate how much that that has passed */ + /* Evaluate in milliseconds how much time that has passed */ has_passed = Curl_tvdiff(Curl_tvnow(), data->progress.start); #ifndef min @@ -368,7 +368,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ timeout_ms = data->set.connecttimeout*1000; /* subtract the passed time */ - timeout_ms -= (long)(has_passed * 1000); + timeout_ms -= (long)has_passed; if(timeout_ms < 0) /* a precaution, no need to continue if time already is up */ @@ -436,7 +436,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ /* get a new timeout for next attempt */ after = Curl_tvnow(); - timeout_ms -= (long)(Curl_tvdiff(after, before)*1000); + timeout_ms -= Curl_tvdiff(after, before); if(timeout_ms < 0) { failf(data, "connect() timed out!"); return CURLE_OPERATION_TIMEOUTED; @@ -521,7 +521,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ if(0 != rc) { /* get a new timeout for next attempt */ after = Curl_tvnow(); - timeout_ms -= (long)(Curl_tvdiff(after, before)*1000); + timeout_ms -= Curl_tvdiff(after, before); if(timeout_ms < 0) { failf(data, "Connect timeout on IP number %d", aliasindex+1); break; -- cgit v1.2.1 From b585f411cde3419af383bd270aa801cdb8dc6e5c Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 22 Oct 2001 12:52:25 +0000 Subject: make sure the connect can't return OK but return a NULL as addr --- lib/connect.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index df34d7edc..4adc9f85c 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -340,7 +340,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ { struct SessionHandle *data = conn->data; int rc; - int sockfd; + int sockfd=-1; int aliasindex=0; struct timeval after; @@ -459,11 +459,18 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ /* * Connecting with IPv4-only support */ - + if(!remotehost->h_addr_list[0]) { + /* If there is no addresses in the address list, then we return + error right away */ + failf(data, "no address available"); + return CURLE_COULDNT_CONNECT; + } /* create an IPv4 TCP socket */ sockfd = socket(AF_INET, SOCK_STREAM, 0); - if(-1 == sockfd) + if(-1 == sockfd) { + failf(data, "couldn't create socket"); return CURLE_COULDNT_CONNECT; /* big time error */ + } if(conn->data->set.device) { /* user selected to bind the outgoing socket to a specified "device" -- cgit v1.2.1 From 3edd9b4dfce900fb80918c056553c2cfde10b6e1 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 29 Oct 2001 07:49:57 +0000 Subject: SM's waitconnect return code fix! --- lib/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 4adc9f85c..b952d85e8 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -538,7 +538,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ } break; } - if(-1 == rc) { + if(0 != rc) { /* no good connect was made */ sclose(sockfd); *sockconn = -1; -- cgit v1.2.1 From b07e2a08f9a98f7261d82f3ad5931ac5bcfb05a4 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 31 Oct 2001 08:44:11 +0000 Subject: nonblock => Curl_nonblock, remade the check for a live SSL connection (again) --- lib/connect.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index b952d85e8..af98242c5 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -88,9 +88,9 @@ int geterrno(void) * Description: * Set the socket to either blocking or non-blocking mode. */ -static -int nonblock(int socket, /* operate on this */ - int nonblock /* TRUE or FALSE */) + +int Curl_nonblock(int socket, /* operate on this */ + int nonblock /* TRUE or FALSE */) { #undef SETBLOCK #ifdef HAVE_O_NONBLOCK @@ -389,7 +389,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ continue; /* set socket non-blocking */ - nonblock(sockfd, TRUE); + Curl_nonblock(sockfd, TRUE); rc = connect(sockfd, ai->ai_addr, ai->ai_addrlen); @@ -450,7 +450,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ } /* now disable the non-blocking mode again */ - nonblock(sockfd, FALSE); + Curl_nonblock(sockfd, FALSE); if(addr) *addr = ai; /* the address we ended up connected to */ @@ -481,7 +481,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ } /* Convert socket to non-blocking type */ - nonblock(sockfd, TRUE); + Curl_nonblock(sockfd, TRUE); /* This is the loop that attempts to connect to all IP-addresses we know for the given host. One by one. */ @@ -546,7 +546,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ } /* now disable the non-blocking mode again */ - nonblock(sockfd, FALSE); + Curl_nonblock(sockfd, FALSE); if(addr) /* this is the address we've connected to */ -- cgit v1.2.1 From 17b18bca3cab0ab6d6df01951a41454e6f8ee5d3 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 21 Nov 2001 22:57:42 +0000 Subject: added error text for a failed connect case --- lib/connect.c | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index af98242c5..274f7b1e1 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -542,6 +542,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ /* no good connect was made */ sclose(sockfd); *sockconn = -1; + failf(data, "Couldn't connect to host"); return CURLE_COULDNT_CONNECT; } -- cgit v1.2.1 From 0e7203be8981a58be17dce6eb100cd24d92c7042 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 22 Nov 2001 13:57:00 +0000 Subject: this fix seems to make the connect fail properly even on IPv4-only Linux machines! --- lib/connect.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 274f7b1e1..277e1dfae 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -309,9 +309,8 @@ static CURLcode bindlocal(struct connectdata *conn, return CURLE_HTTP_PORT_FAILED; } -#else /* end of ipv4-specific section */ +#endif /* end of ipv4-specific section */ -/* we only use socketerror() on IPv6-enabled machines */ static int socketerror(int sockfd) { @@ -324,7 +323,6 @@ int socketerror(int sockfd) return err; } -#endif /* * TCP connect to the given host with timeout, proxy or remote doesn't matter. @@ -525,6 +523,16 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ } } + if(0 == rc) { + int err = socketerror(sockfd); + if ((0 == err) || (EISCONN == err)) { + /* we are connected, awesome! */ + break; + } + /* nope, not connected for real */ + rc = -1; + } + if(0 != rc) { /* get a new timeout for next attempt */ after = Curl_tvnow(); -- cgit v1.2.1 From f0ee7115d30f3bc0cc953b7527ba424784790337 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 23 Nov 2001 09:04:56 +0000 Subject: =?UTF-8?q?Andr=E9s=20Garc=EDa's=20minor=20fix=20to=20make=20it=20?= =?UTF-8?q?compile=20on=20win32?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/connect.c | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 277e1dfae..c045ba436 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -61,6 +61,7 @@ #include #define EINPROGRESS WSAEINPROGRESS #define EWOULDBLOCK WSAEWOULDBLOCK +#define EISCONN WSAEISCONN #endif #include "urldata.h" -- cgit v1.2.1 From 436d1479256117f21740dbd1ed4eb0c136c15de9 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 4 Dec 2001 13:03:08 +0000 Subject: Eric's #include fixes for better macos compiles --- lib/connect.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index c045ba436..69308df2b 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -44,6 +44,10 @@ #ifdef HAVE_ARPA_INET_H #include #endif +#ifdef HAVE_STDLIB_H +#include /* required for free() prototype, without it, this crashes + on macos 68K */ +#endif #endif #include -- cgit v1.2.1 From e1922617883d5a70a282ed0e9e756a27eeed6bba Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 11 Dec 2001 13:13:01 +0000 Subject: failf() calls should not have newlines in the message string! --- lib/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 69308df2b..9f8efdbd6 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -284,7 +284,7 @@ static CURLcode bindlocal(struct connectdata *conn, failf(data, "Insufficient kernel memory was available: %d", errno); break; default: - failf(data, "errno %d\n", errno); + failf(data, "errno %d", errno); break; } /* end of switch(errno) */ -- cgit v1.2.1 From fe37fb5921a590a70ddcdb146955eb94b9ecf17b Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 2 Jan 2002 10:06:47 +0000 Subject: Philip Gladstone's 64-bit sparc native compiler compatibility issues fixed. --- lib/connect.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 9f8efdbd6..06d2464ae 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -193,7 +193,7 @@ static CURLcode bindlocal(struct connectdata *conn, #ifdef HAVE_INET_NTOA #ifndef INADDR_NONE -#define INADDR_NONE (unsigned long) ~0 +#define INADDR_NONE (in_addr_t) ~0 #endif struct SessionHandle *data = conn->data; @@ -207,7 +207,7 @@ static CURLcode bindlocal(struct connectdata *conn, char *hostdataptr=NULL; size_t size; char myhost[256] = ""; - unsigned long in; + in_addr_t in; if(Curl_if2ip(data->set.device, myhost, sizeof(myhost))) { h = Curl_getaddrinfo(data, myhost, 0, &hostdataptr); @@ -236,7 +236,8 @@ static CURLcode bindlocal(struct connectdata *conn, infof(data, "We bind local end to %s\n", myhost); - if ( (in=inet_addr(myhost)) != INADDR_NONE ) { + in=inet_addr(myhost); + if (INADDR_NONE != in) { if ( h ) { memset((char *)&sa, 0, sizeof(sa)); -- cgit v1.2.1 From 6de7dc5879b3605a180dafa05f792f132eafdcaa Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 3 Jan 2002 10:22:59 +0000 Subject: Sterling Hughes' provided initial DNS cache source code. --- lib/connect.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 06d2464ae..d7add1067 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -210,11 +210,11 @@ static CURLcode bindlocal(struct connectdata *conn, in_addr_t in; if(Curl_if2ip(data->set.device, myhost, sizeof(myhost))) { - h = Curl_getaddrinfo(data, myhost, 0, &hostdataptr); + h = Curl_resolv(data, myhost, 0, &hostdataptr); } else { if(strlen(data->set.device)>1) { - h = Curl_getaddrinfo(data, data->set.device, 0, &hostdataptr); + h = Curl_resolv(data, data->set.device, 0, &hostdataptr); } if(h) { /* we know data->set.device is shorter than the myhost array */ @@ -229,8 +229,6 @@ static CURLcode bindlocal(struct connectdata *conn, hostent_buf, sizeof(hostent_buf)); */ - if(hostdataptr) - free(hostdataptr); /* allocated by Curl_getaddrinfo() */ return CURLE_HTTP_PORT_FAILED; } @@ -304,9 +302,6 @@ static CURLcode bindlocal(struct connectdata *conn, return CURLE_HTTP_PORT_FAILED; } - if(hostdataptr) - free(hostdataptr); /* allocated by Curl_getaddrinfo() */ - return CURLE_OK; } /* end of device selection support */ -- cgit v1.2.1 From d3299beec734be02a781c393a994d525e3eaaac1 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 7 Jan 2002 18:38:01 +0000 Subject: Modified to use non-blocking sockets all the time. --- lib/connect.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index d7add1067..61e45689e 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -448,8 +448,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ return CURLE_COULDNT_CONNECT; } - /* now disable the non-blocking mode again */ - Curl_nonblock(sockfd, FALSE); + /* leave the socket in non-blocking mode */ if(addr) *addr = ai; /* the address we ended up connected to */ @@ -554,9 +553,8 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ failf(data, "Couldn't connect to host"); return CURLE_COULDNT_CONNECT; } - - /* now disable the non-blocking mode again */ - Curl_nonblock(sockfd, FALSE); + + /* leave the socket in non-blocking mode */ if(addr) /* this is the address we've connected to */ -- cgit v1.2.1 From 5c6eddcadd65432b8739117a161cb8062be997d9 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 16 Jan 2002 22:26:01 +0000 Subject: fixed time-out returned without error text set --- lib/connect.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 61e45689e..34fc1e844 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -369,9 +369,11 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ /* subtract the passed time */ timeout_ms -= (long)has_passed; - if(timeout_ms < 0) + if(timeout_ms < 0) { /* a precaution, no need to continue if time already is up */ + failf(data, "Connection time-out"); return CURLE_OPERATION_TIMEOUTED; + } } #ifdef ENABLE_IPV6 -- cgit v1.2.1 From e21926f7f081b0eb18962374770e91648a8d5fc3 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 18 Feb 2002 10:05:18 +0000 Subject: connection timeout comparison fix by Emil --- lib/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 34fc1e844..b1a2560b2 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -361,7 +361,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ /* get the most strict timeout of the ones converted to milliseconds */ if(data->set.timeout && - (data->set.timeout>data->set.connecttimeout)) + (data->set.timeout < data->set.connecttimeout)) timeout_ms = data->set.timeout*1000; else timeout_ms = data->set.connecttimeout*1000; -- cgit v1.2.1 From 721b05e3436884fc1e1b55f211e7fa4251d92a2a Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 20 Feb 2002 13:46:53 +0000 Subject: Nico Baggus' VMS tweaks --- lib/connect.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index b1a2560b2..7efa9f006 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -48,6 +48,10 @@ #include /* required for free() prototype, without it, this crashes on macos 68K */ #endif +#ifdef VMS +#include +#include +#endif #endif #include -- cgit v1.2.1 From b1ffe7b74a4235efa70908d9052922171fd51e14 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 22 Feb 2002 15:44:37 +0000 Subject: better time selection for the connect timeout --- lib/connect.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 7efa9f006..749f8cb2a 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -364,8 +364,13 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ #endif /* get the most strict timeout of the ones converted to milliseconds */ - if(data->set.timeout && - (data->set.timeout < data->set.connecttimeout)) + if(data->set.timeout && data->set.connecttimeout) { + if (data->set.timeout < data->set.connecttimeout) + timeout_ms = data->set.timeout*1000; + else + timeout_ms = data->set.connecttimeout*1000; + } + else if(data->set.timeout) timeout_ms = data->set.timeout*1000; else timeout_ms = data->set.connecttimeout*1000; -- cgit v1.2.1 From 974f314f5785156af6983675aeb28313cc8ba2ea Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 19 Mar 2002 07:54:55 +0000 Subject: copyright string (year) update --- lib/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 749f8cb2a..66035dc3f 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2001, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2002, Daniel Stenberg, , et al. * * In order to be useful for every potential user, curl and libcurl are * dual-licensed under the MPL and the MIT/X-derivate licenses. -- cgit v1.2.1 From 308ae5cbf29921e27eed764416d1ae5379d3e47f Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 10 Apr 2002 14:20:24 +0000 Subject: added info in to failf() lines and added a infof() call just before the connect() so that it tells to which host and what port it is about to attempt the connection --- lib/connect.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 66035dc3f..ee52b6764 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -385,6 +385,9 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ } } + infof(data, "About to connect() to %s:%d\n", + data->change.proxy?conn->proxyhost:conn->hostname, port); + #ifdef ENABLE_IPV6 /* * Connecting with IPv6 support is so much easier and cleanly done @@ -424,7 +427,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ case ECONNREFUSED: /* no one listening */ default: /* unknown error, fallthrough and try another address! */ - failf(data, "Failed to connect"); + failf(data, "Failed to connect: %d", error); break; } } @@ -529,7 +532,8 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ break; default: /* unknown error, fallthrough and try another address! */ - failf(data, "Failed to connect to IP number %d", aliasindex+1); + failf(data, "Failed to connect to IP number %d: %d", + aliasindex+1, error); break; } } -- cgit v1.2.1 From 36e35b6f6003d061d125318bb547bed1c9a74bbe Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 22 Apr 2002 23:56:13 +0000 Subject: allow binding the local end of a connection even when using IPv6, thus we now have --interface working properly --- lib/connect.c | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index ee52b6764..3fe0e0eb0 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -185,7 +185,6 @@ int waitconnect(int sockfd, /* socket */ return 0; } -#ifndef ENABLE_IPV6 static CURLcode bindlocal(struct connectdata *conn, int sockfd) { @@ -207,22 +206,29 @@ static CURLcode bindlocal(struct connectdata *conn, *************************************************************/ if (strlen(data->set.device)<255) { struct sockaddr_in sa; - struct hostent *h=NULL; + Curl_addrinfo *h=NULL; char *hostdataptr=NULL; size_t size; char myhost[256] = ""; in_addr_t in; if(Curl_if2ip(data->set.device, myhost, sizeof(myhost))) { + /* + * We now have the numerical IPv4-style x.y.z.w in the 'myhost' buffer + */ h = Curl_resolv(data, myhost, 0, &hostdataptr); } else { if(strlen(data->set.device)>1) { + /* + * This was not an interface, resolve the name as a host name + * or IP number + */ h = Curl_resolv(data, data->set.device, 0, &hostdataptr); - } - if(h) { - /* we know data->set.device is shorter than the myhost array */ - strcpy(myhost, data->set.device); + if(h) { + /* we know data->set.device is shorter than the myhost array */ + strcpy(myhost, data->set.device); + } } } @@ -243,10 +249,13 @@ static CURLcode bindlocal(struct connectdata *conn, if ( h ) { memset((char *)&sa, 0, sizeof(sa)); - memcpy((char *)&sa.sin_addr, - h->h_addr, - h->h_length); +#ifdef ENABLE_IPV6 + memcpy((char *)&sa.sin_addr, h->ai_addr, h->ai_addrlen); + sa.sin_family = h->ai_family; +#else + memcpy((char *)&sa.sin_addr, h->h_addr, h->h_length); sa.sin_family = AF_INET; +#endif sa.sin_addr.s_addr = in; sa.sin_port = 0; /* get any port */ @@ -314,7 +323,7 @@ static CURLcode bindlocal(struct connectdata *conn, return CURLE_HTTP_PORT_FAILED; } -#endif /* end of ipv4-specific section */ + static int socketerror(int sockfd) @@ -401,6 +410,14 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ if (sockfd < 0) continue; + if(conn->data->set.device) { + /* user selected to bind the outgoing socket to a specified "device" + before doing connect */ + CURLcode res = bindlocal(conn, sockfd); + if(res) + return res; + } + /* set socket non-blocking */ Curl_nonblock(sockfd, TRUE); -- cgit v1.2.1 From 8927ddec1687a438354eae6c527da92c6c63b50b Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 25 Apr 2002 19:00:57 +0000 Subject: In order to not get problems with DNS cache pruning, we no longer store any name resolved data in any curl handle struct. That way, we won't mind if the cache entries are pruned for the next time we need them. We'll just resolve them again instead. This changes the Curl_resolv() proto. It modifies the SessionHandle struct but perhaps most importantly, it'll make the internals somewhat dependent on the DNS cache not being disabled as that will cripple operations somewhat. Especially for persistant connections. --- lib/connect.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 3fe0e0eb0..9bd1bdfbd 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -207,7 +207,6 @@ static CURLcode bindlocal(struct connectdata *conn, if (strlen(data->set.device)<255) { struct sockaddr_in sa; Curl_addrinfo *h=NULL; - char *hostdataptr=NULL; size_t size; char myhost[256] = ""; in_addr_t in; @@ -216,7 +215,7 @@ static CURLcode bindlocal(struct connectdata *conn, /* * We now have the numerical IPv4-style x.y.z.w in the 'myhost' buffer */ - h = Curl_resolv(data, myhost, 0, &hostdataptr); + h = Curl_resolv(data, myhost, 0); } else { if(strlen(data->set.device)>1) { @@ -224,7 +223,7 @@ static CURLcode bindlocal(struct connectdata *conn, * This was not an interface, resolve the name as a host name * or IP number */ - h = Curl_resolv(data, data->set.device, 0, &hostdataptr); + h = Curl_resolv(data, data->set.device, 0); if(h) { /* we know data->set.device is shorter than the myhost array */ strcpy(myhost, data->set.device); @@ -354,6 +353,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ int rc; int sockfd=-1; int aliasindex=0; + char *hostname; struct timeval after; struct timeval before = Curl_tvnow(); @@ -394,8 +394,8 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ } } - infof(data, "About to connect() to %s:%d\n", - data->change.proxy?conn->proxyhost:conn->hostname, port); + hostname = data->change.proxy?conn->proxyhost:conn->hostname; + infof(data, "About to connect() to %s:%d\n", hostname, port); #ifdef ENABLE_IPV6 /* @@ -444,7 +444,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ case ECONNREFUSED: /* no one listening */ default: /* unknown error, fallthrough and try another address! */ - failf(data, "Failed to connect: %d", error); + failf(data, "Failed connect to %s: %d", hostname, error); break; } } @@ -474,10 +474,8 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ before = after; continue; } - if (sockfd < 0) { - failf(data, "connect() failed"); + if (sockfd < 0) return CURLE_COULDNT_CONNECT; - } /* leave the socket in non-blocking mode */ @@ -549,8 +547,8 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ break; default: /* unknown error, fallthrough and try another address! */ - failf(data, "Failed to connect to IP number %d: %d", - aliasindex+1, error); + failf(data, "Failed to connect to %s IP number %d: %d", + hostname, aliasindex+1, error); break; } } @@ -582,7 +580,6 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ /* no good connect was made */ sclose(sockfd); *sockconn = -1; - failf(data, "Couldn't connect to host"); return CURLE_COULDNT_CONNECT; } -- cgit v1.2.1 From 78473f71ebc78775381cbd448b5a7238a184caff Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 10 Jun 2002 13:25:03 +0000 Subject: added a missing failf() for certain connect failures --- lib/connect.c | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 9bd1bdfbd..6babb9f42 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -457,6 +457,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ /* we are connected, awesome! */ break; } + failf(data, "socket error: %d", err); /* we are _not_ connected, it was a false alert, continue please */ } -- cgit v1.2.1 From 87afd7686f617f0d163520795fe439fcabe6dfea Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 12 Jun 2002 09:48:26 +0000 Subject: added a connect failure error message that might get empty otherwise --- lib/connect.c | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 6babb9f42..ba00b73e9 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -581,6 +581,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ /* no good connect was made */ sclose(sockfd); *sockconn = -1; + failf(data, "Connect failed"); return CURLE_COULDNT_CONNECT; } -- cgit v1.2.1 From cb895ec3356822df72eb91171a1cc63ad1845d93 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 12 Aug 2002 09:43:20 +0000 Subject: Initial fix to make the multi interface return control while waiting for the initial connect to "come through". This should work fine for connect and for FTP-PASV connects. Needs massive testing. --- lib/connect.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 88 insertions(+), 3 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index ba00b73e9..545062c66 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -337,6 +337,70 @@ int socketerror(int sockfd) return err; } +/* + * Curl_is_connected() is used from the multi interface to check if the + * firstsocket has connected. + */ + +CURLcode Curl_is_connected(struct connectdata *conn, + int sockfd, + bool *connected) +{ + int rc; + struct SessionHandle *data = conn->data; + + *connected = FALSE; /* a very negative world view is best */ + + if(data->set.timeout || data->set.connecttimeout) { + /* there is a timeout set */ + + /* Evaluate in milliseconds how much time that has passed */ + long has_passed = Curl_tvdiff(Curl_tvnow(), data->progress.start); + + /* subtract the most strict timeout of the ones */ + if(data->set.timeout && data->set.connecttimeout) { + if (data->set.timeout < data->set.connecttimeout) + has_passed -= data->set.timeout*1000; + else + has_passed -= data->set.connecttimeout*1000; + } + else if(data->set.timeout) + has_passed -= data->set.timeout*1000; + else + has_passed -= data->set.connecttimeout*1000; + + if(has_passed > 0 ) { + /* time-out, bail out, go home */ + failf(data, "Connection time-out"); + return CURLE_OPERATION_TIMEOUTED; + } + } + + /* check for connect without timeout as we want to return immediately */ + rc = waitconnect(sockfd, 0); + + if(0 == rc) { + int err = socketerror(sockfd); + if ((0 == err) || (EISCONN == err)) { + /* we are connected, awesome! */ + *connected = TRUE; + return CURLE_OK; + } + /* nope, not connected for real */ + } + + /* + * If the connection phase is "done" here, we should attempt to connect + * to the "next address" in the Curl_hostaddr structure that we resolved + * before. But we don't have that struct around anymore and we can't just + * keep a pointer since the cache might in fact have gotten pruned by the + * time we want to read this... Alas, we don't do this yet. + */ + + return CURLE_OK; +} + + /* * TCP connect to the given host with timeout, proxy or remote doesn't matter. * There might be more than one IP address to try out. Fill in the passed @@ -347,7 +411,8 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ Curl_addrinfo *remotehost, /* use one in here */ int port, /* connect to this */ int *sockconn, /* the connected socket */ - Curl_ipconnect **addr) /* the one we used */ + Curl_ipconnect **addr, /* the one we used */ + bool *connected) /* really connected? */ { struct SessionHandle *data = conn->data; int rc; @@ -437,8 +502,11 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ case EAGAIN: #endif case EINTR: - /* asynchronous connect, wait for connect or timeout */ + if(data->state.used_interface == Curl_if_multi) + /* don't hang when doing multi */ + timeout_ms = 0; + rc = waitconnect(sockfd, timeout_ms); break; case ECONNREFUSED: /* no one listening */ @@ -448,6 +516,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ break; } } + if(0 == rc) { /* we might be connected, if the socket says it is OK! Ask it! */ int err; @@ -455,11 +524,17 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ err = socketerror(sockfd); if ((0 == err) || (EISCONN == err)) { /* we are connected, awesome! */ + *connected = TRUE; /* this is truly a connect */ break; } failf(data, "socket error: %d", err); /* we are _not_ connected, it was a false alert, continue please */ } + else if(data->state.used_interface == Curl_if_multi) { + /* When running the multi interface, we bail out here */ + rc = 0; + break; + } /* connect failed or timed out */ sclose(sockfd); @@ -542,8 +617,11 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ */ case EAGAIN: #endif - /* asynchronous connect, wait for connect or timeout */ + if(data->state.used_interface == Curl_if_multi) + /* don't hang when doing multi */ + timeout_ms = 0; + rc = waitconnect(sockfd, timeout_ms); break; default: @@ -558,6 +636,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ int err = socketerror(sockfd); if ((0 == err) || (EISCONN == err)) { /* we are connected, awesome! */ + *connected = TRUE; /* this is a true connect */ break; } /* nope, not connected for real */ @@ -565,6 +644,12 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ } if(0 != rc) { + if(data->state.used_interface == Curl_if_multi) { + /* When running the multi interface, we bail out here */ + rc = 0; + break; + } + /* get a new timeout for next attempt */ after = Curl_tvnow(); timeout_ms -= Curl_tvdiff(after, before); -- cgit v1.2.1 From 30b7a9f17290d79cd5c51be287e6cbd4fd4eab90 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 12 Aug 2002 12:01:57 +0000 Subject: fixed a Curl_connecthost() bug, we should default to set connected to false --- lib/connect.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 545062c66..9bbf8409c 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -427,6 +427,9 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ * Figure out what maximum time we have left *************************************************************/ long timeout_ms=300000; /* milliseconds, default to five minutes */ + + *connected = FALSE; /* default to not connected */ + if(data->set.timeout || data->set.connecttimeout) { double has_passed; -- cgit v1.2.1 From 982c5460f0eb521ce4f9526535e9d122fe8755bd Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 26 Aug 2002 17:20:29 +0000 Subject: Andrew Francis removed the need for/use of MSVC pragmas --- lib/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 9bbf8409c..a90b87e17 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -602,7 +602,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ (struct in_addr *)remotehost->h_addr_list[aliasindex], sizeof(struct in_addr)); serv_addr.sin_family = remotehost->h_addrtype; - serv_addr.sin_port = htons(port); + serv_addr.sin_port = htons((unsigned short)port); rc = connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)); -- cgit v1.2.1 From ba4e69bebc8f7f32f3bc7faa1e13e7580754075b Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 3 Sep 2002 11:52:59 +0000 Subject: updated source code boilerplate/header --- lib/connect.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index a90b87e17..0272f2e82 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -1,4 +1,4 @@ -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | @@ -7,19 +7,19 @@ * * Copyright (C) 1998 - 2002, Daniel Stenberg, , et al. * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. - * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ #include "setup.h" -- cgit v1.2.1 From cac5251a98165bf5b6069f5276fd9d1d7331a11a Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 11 Sep 2002 10:32:37 +0000 Subject: Lukasz Czekierda correctly pointed out that curl used a bad Host: header when talking to a IPv6-server using IPv6 IP address only. --- lib/connect.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 0272f2e82..203253500 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -463,7 +463,11 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ } hostname = data->change.proxy?conn->proxyhost:conn->hostname; - infof(data, "About to connect() to %s:%d\n", hostname, port); + infof(data, "About to connect() to %s%s%s:%d\n", + conn->bits.ipv6_ip?"[":"", + hostname, + conn->bits.ipv6_ip?"]":"", + port); #ifdef ENABLE_IPV6 /* -- cgit v1.2.1 From b5bbc04ad1fa584b0862925daecfb48dbdcb70c1 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 12 Oct 2002 11:18:08 +0000 Subject: return error properly when a non-blocking connect fails using the multi interface --- lib/connect.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 203253500..0a9e97368 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -387,6 +387,8 @@ CURLcode Curl_is_connected(struct connectdata *conn, return CURLE_OK; } /* nope, not connected for real */ + if(err) + return CURLE_COULDNT_CONNECT; } /* -- cgit v1.2.1 From 2cff2518631fc538c127c1e94c47c743e2a64661 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 5 Nov 2002 10:51:41 +0000 Subject: Curl_resolv() now returns a different struct, and it contains a reference counter so that the caller needs to decrease that counter when done with the returned data. If compiled with MALLOCDEBUG I've added some extra checking that the counter is decreased before a handle is closed etc. --- lib/connect.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 0a9e97368..4da03a1bc 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -206,7 +206,7 @@ static CURLcode bindlocal(struct connectdata *conn, *************************************************************/ if (strlen(data->set.device)<255) { struct sockaddr_in sa; - Curl_addrinfo *h=NULL; + struct Curl_dns_entry *h=NULL; size_t size; char myhost[256] = ""; in_addr_t in; @@ -247,12 +247,17 @@ static CURLcode bindlocal(struct connectdata *conn, if (INADDR_NONE != in) { if ( h ) { + Curl_addrinfo *addr = h->addr; + + h->inuse--; /* decrease the use-counter, we don't need it anymore + after this function has returned */ + memset((char *)&sa, 0, sizeof(sa)); #ifdef ENABLE_IPV6 - memcpy((char *)&sa.sin_addr, h->ai_addr, h->ai_addrlen); - sa.sin_family = h->ai_family; + memcpy((char *)&sa.sin_addr, addr->ai_addr, addr->ai_addrlen); + sa.sin_family = addr->ai_family; #else - memcpy((char *)&sa.sin_addr, h->h_addr, h->h_length); + memcpy((char *)&sa.sin_addr, addr->h_addr, addr->h_length); sa.sin_family = AF_INET; #endif sa.sin_addr.s_addr = in; @@ -410,7 +415,7 @@ CURLcode Curl_is_connected(struct connectdata *conn, */ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ - Curl_addrinfo *remotehost, /* use one in here */ + struct Curl_dns_entry *remotehost, /* use this one */ int port, /* connect to this */ int *sockconn, /* the connected socket */ Curl_ipconnect **addr, /* the one we used */ @@ -479,7 +484,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ struct addrinfo *ai; port =0; /* prevent compiler warning */ - for (ai = remotehost; ai; ai = ai->ai_next, aliasindex++) { + for (ai = remotehost->addr; ai; ai = ai->ai_next, aliasindex++) { sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (sockfd < 0) continue; -- cgit v1.2.1 From 0ff1ca30c3e9e36b553c354d18de5c5f80d1af69 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 5 Nov 2002 11:07:49 +0000 Subject: ipv4-fixes for the new Curl_dns_entry struct and Curl_resolv() proto --- lib/connect.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 4da03a1bc..b97c9da90 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -576,7 +576,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ /* * Connecting with IPv4-only support */ - if(!remotehost->h_addr_list[0]) { + if(!remotehost->addr->h_addr_list[0]) { /* If there is no addresses in the address list, then we return error right away */ failf(data, "no address available"); @@ -603,16 +603,16 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ /* This is the loop that attempts to connect to all IP-addresses we know for the given host. One by one. */ for(rc=-1, aliasindex=0; - rc && (struct in_addr *)remotehost->h_addr_list[aliasindex]; + rc && (struct in_addr *)remotehost->addr->h_addr_list[aliasindex]; aliasindex++) { struct sockaddr_in serv_addr; /* do this nasty work to do the connect */ memset((char *) &serv_addr, '\0', sizeof(serv_addr)); memcpy((char *)&(serv_addr.sin_addr), - (struct in_addr *)remotehost->h_addr_list[aliasindex], + (struct in_addr *)remotehost->addr->h_addr_list[aliasindex], sizeof(struct in_addr)); - serv_addr.sin_family = remotehost->h_addrtype; + serv_addr.sin_family = remotehost->addr->h_addrtype; serv_addr.sin_port = htons((unsigned short)port); rc = connect(sockfd, (struct sockaddr *)&serv_addr, @@ -688,7 +688,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ if(addr) /* this is the address we've connected to */ - *addr = (struct in_addr *)remotehost->h_addr_list[aliasindex]; + *addr = (struct in_addr *)remotehost->addr->h_addr_list[aliasindex]; #endif /* allow NULL-pointers to get passed in */ -- cgit v1.2.1 From 66eb98bb0a3d171b91c77f8a536011f6b25c1adc Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 11 Nov 2002 22:36:00 +0000 Subject: unlock dns cache entries with a function call instead of a variable fiddle --- lib/connect.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index b97c9da90..d2080c452 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -249,8 +249,8 @@ static CURLcode bindlocal(struct connectdata *conn, if ( h ) { Curl_addrinfo *addr = h->addr; - h->inuse--; /* decrease the use-counter, we don't need it anymore - after this function has returned */ + Curl_resolv_unlock(h); + /* we don't need it anymore after this function has returned */ memset((char *)&sa, 0, sizeof(sa)); #ifdef ENABLE_IPV6 -- cgit v1.2.1 From 9ae920c1b6b274396128ed54b001b4561a1e708f Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 13 Dec 2002 13:47:58 +0000 Subject: make a little work-around for file:// in _is_connected() and voila, now the multi interface works with file:// URLs fine (previously it crashed). This won't make it work on Windows though... --- lib/connect.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index d2080c452..1a4c193eb 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -380,6 +380,11 @@ CURLcode Curl_is_connected(struct connectdata *conn, return CURLE_OPERATION_TIMEOUTED; } } + if(conn->protocol & PROT_FILE) { + /* we are connected, awesome! */ + *connected = TRUE; + return CURLE_OK; + } /* check for connect without timeout as we want to return immediately */ rc = waitconnect(sockfd, 0); -- cgit v1.2.1 From b528bde470afc6d5a6e3e72f4823428f9ec78a9a Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 13 Dec 2002 16:15:19 +0000 Subject: conn->bits.tcpconnect now keeps track of if this connection is connected or not --- lib/connect.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 1a4c193eb..151864fd7 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -380,8 +380,8 @@ CURLcode Curl_is_connected(struct connectdata *conn, return CURLE_OPERATION_TIMEOUTED; } } - if(conn->protocol & PROT_FILE) { - /* we are connected, awesome! */ + if(conn->bits.tcpconnect) { + /* we are connected already! */ *connected = TRUE; return CURLE_OK; } -- cgit v1.2.1 From 747f87f61e2278381cb9da3b9b19b9ca39a0582b Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 17 Dec 2002 10:05:00 +0000 Subject: Removed weird special multi interface condition that caused bug report #651464. --- lib/connect.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 151864fd7..2c85dc157 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -663,12 +663,6 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ } if(0 != rc) { - if(data->state.used_interface == Curl_if_multi) { - /* When running the multi interface, we bail out here */ - rc = 0; - break; - } - /* get a new timeout for next attempt */ after = Curl_tvnow(); timeout_ms -= Curl_tvdiff(after, before); -- cgit v1.2.1 From 6f35ed51dc63ddeeda3a32794b391ba841fe5caa Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 9 Jan 2003 14:52:51 +0000 Subject: This fixed yet another connect problem with the multi interface and ipv4 stack. Kjetil Jacobsen reported and verified the fix. --- lib/connect.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 2c85dc157..d3c65b4dc 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -176,10 +176,9 @@ int waitconnect(int sockfd, /* socket */ /* timeout, no connect today */ return 1; - if(FD_ISSET(sockfd, &errfd)) { + if(FD_ISSET(sockfd, &errfd)) /* error condition caught */ return 2; - } /* we have a connect! */ return 0; @@ -651,6 +650,15 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ } } + /* The '1 == rc' comes from the waitconnect(), and not from connect(). + We can be sure of this since connect() cannot return 1. */ + if((1 == rc) && (data->state.used_interface == Curl_if_multi)) { + /* Timeout when running the multi interface, we return here with a + CURLE_OK return code. */ + rc = 0; + break; + } + if(0 == rc) { int err = socketerror(sockfd); if ((0 == err) || (EISCONN == err)) { -- cgit v1.2.1 From f26a338a54e04d0a6907f5d2479d8b0fa9daf297 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 16 Jan 2003 21:08:12 +0000 Subject: copyright year update in the source header --- lib/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index d3c65b4dc..05201bab4 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2002, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2003, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms -- cgit v1.2.1 From a6c395c156a5d399edea10bb8731ea49226e7932 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 23 Jan 2003 05:38:20 +0000 Subject: Duncan Wilcox reported a crash with --interface on FreeBSD when ipv6-enabled and this has been verified to correct the problem. --- lib/connect.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 05201bab4..884425326 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -251,14 +251,23 @@ static CURLcode bindlocal(struct connectdata *conn, Curl_resolv_unlock(h); /* we don't need it anymore after this function has returned */ - memset((char *)&sa, 0, sizeof(sa)); #ifdef ENABLE_IPV6 - memcpy((char *)&sa.sin_addr, addr->ai_addr, addr->ai_addrlen); - sa.sin_family = addr->ai_family; + (void)sa; /* prevent compiler warning */ + if( bind(sockfd, addr->ai_addr, addr->ai_addrlen) >= 0) { + /* we succeeded to bind */ + struct sockaddr_in6 add; + + size = sizeof(add); + if(getsockname(sockfd, (struct sockaddr *) &add, + (socklen_t *)&size)<0) { + failf(data, "getsockname() failed"); + return CURLE_HTTP_PORT_FAILED; + } + } #else + memset((char *)&sa, 0, sizeof(sa)); memcpy((char *)&sa.sin_addr, addr->h_addr, addr->h_length); sa.sin_family = AF_INET; -#endif sa.sin_addr.s_addr = in; sa.sin_port = 0; /* get any port */ @@ -273,6 +282,7 @@ static CURLcode bindlocal(struct connectdata *conn, return CURLE_HTTP_PORT_FAILED; } } +#endif else { switch(errno) { case EBADF: -- cgit v1.2.1 From beb13a1d3e832ae97221ba1d9ad7f9bc262de798 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Barette-LaPierre Date: Tue, 4 Feb 2003 23:48:46 +0000 Subject: added the sharing of DNS cache --- lib/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 884425326..da0a5b951 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -248,7 +248,7 @@ static CURLcode bindlocal(struct connectdata *conn, if ( h ) { Curl_addrinfo *addr = h->addr; - Curl_resolv_unlock(h); + Curl_resolv_unlock(data, h); /* we don't need it anymore after this function has returned */ #ifdef ENABLE_IPV6 -- cgit v1.2.1 From 977175d4fd42090a9f462f991d8b3dabacbbb752 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 14 Feb 2003 08:02:55 +0000 Subject: Martin C. Martin's fix for multi-interface connects to non-listening ports. --- lib/connect.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index da0a5b951..b34d5776a 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -81,6 +81,10 @@ #include "memdebug.h" #endif +/* The AIX 3.2.5 system headers define a function called geterrno() which + we won't need but that interferes with our function */ +#undef geterrno + static int geterrno(void) { @@ -409,6 +413,8 @@ CURLcode Curl_is_connected(struct connectdata *conn, if(err) return CURLE_COULDNT_CONNECT; } + else if(2 == rc) + return CURLE_COULDNT_CONNECT; /* * If the connection phase is "done" here, we should attempt to connect @@ -558,6 +564,9 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ failf(data, "socket error: %d", err); /* we are _not_ connected, it was a false alert, continue please */ } + else if(2 == rc) + /* waitconnect() returned error */ + ; else if(data->state.used_interface == Curl_if_multi) { /* When running the multi interface, we bail out here */ rc = 0; -- cgit v1.2.1 From 498f3985b3a887dd76a2445076d8c0f5e1175d56 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 14 Feb 2003 09:01:01 +0000 Subject: geterrno() renamed to ourerrno() to prevent the name clash that occurred in AIX 3.2.5 and possibly other OSF-like system headers. --- lib/connect.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index b34d5776a..6e3df6627 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -81,12 +81,8 @@ #include "memdebug.h" #endif -/* The AIX 3.2.5 system headers define a function called geterrno() which - we won't need but that interferes with our function */ -#undef geterrno - static -int geterrno(void) +int ourerrno(void) { #ifdef WIN32 return (int)GetLastError(); @@ -350,7 +346,7 @@ int socketerror(int sockfd) if( -1 == getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *)&err, &errSize)) - err = geterrno(); + err = ourerrno(); return err; } @@ -523,7 +519,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ rc = connect(sockfd, ai->ai_addr, ai->ai_addrlen); if(-1 == rc) { - int error=geterrno(); + int error=ourerrno(); switch (error) { case EINPROGRESS: @@ -642,7 +638,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ sizeof(serv_addr)); if(-1 == rc) { - int error=geterrno(); + int error=ourerrno(); switch (error) { case EINPROGRESS: -- cgit v1.2.1 From c3dfe50aafb5f1687889da114d811f823791ebd7 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 14 Feb 2003 09:11:51 +0000 Subject: Fix Curl_is_connected() even more to deal with waitconnect() return codes even better (also based on input from Martin). --- lib/connect.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 6e3df6627..98bdaca31 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -144,7 +144,11 @@ int Curl_nonblock(int socket, /* operate on this */ } /* - * Return 0 on fine connect, -1 on error and 1 on timeout. + * waitconnect() returns: + * 0 fine connect + * -1 select() error + * 1 select() timeout + * 2 select() returned with an error condition */ static int waitconnect(int sockfd, /* socket */ @@ -409,7 +413,7 @@ CURLcode Curl_is_connected(struct connectdata *conn, if(err) return CURLE_COULDNT_CONNECT; } - else if(2 == rc) + else if(1 != rc) return CURLE_COULDNT_CONNECT; /* -- cgit v1.2.1 From 652683fc04c8b45f3c34592a50be758b28bc0a1d Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 11 Mar 2003 16:28:23 +0000 Subject: Martin C. Martin's fix to produce an error message in case of failure in the Curl_is_connected() function. --- lib/connect.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 98bdaca31..ab38f60dd 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -410,12 +410,15 @@ CURLcode Curl_is_connected(struct connectdata *conn, return CURLE_OK; } /* nope, not connected for real */ - if(err) - return CURLE_COULDNT_CONNECT; + failf(data, "Connection failed, socket error: %d", err); + return CURLE_COULDNT_CONNECT; } - else if(1 != rc) + else if(1 != rc) { + int error = ourerrno(); + failf(data, "Failed connect to %s:%d, errno: %d", + conn->hostname, conn->port, error); return CURLE_COULDNT_CONNECT; - + } /* * If the connection phase is "done" here, we should attempt to connect * to the "next address" in the Curl_hostaddr structure that we resolved -- cgit v1.2.1 From eb6130baa76ad0689de5eb4a24f5717eed1baa89 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 1 May 2003 13:37:05 +0000 Subject: ourerrno became Curl_ourerrno() and is now available to all libcurl --- lib/connect.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index ab38f60dd..1b7a55b5a 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -81,8 +81,7 @@ #include "memdebug.h" #endif -static -int ourerrno(void) +int Curl_ourerrno(void) { #ifdef WIN32 return (int)GetLastError(); @@ -350,7 +349,7 @@ int socketerror(int sockfd) if( -1 == getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *)&err, &errSize)) - err = ourerrno(); + err = Curl_ourerrno(); return err; } @@ -414,7 +413,7 @@ CURLcode Curl_is_connected(struct connectdata *conn, return CURLE_COULDNT_CONNECT; } else if(1 != rc) { - int error = ourerrno(); + int error = Curl_ourerrno(); failf(data, "Failed connect to %s:%d, errno: %d", conn->hostname, conn->port, error); return CURLE_COULDNT_CONNECT; @@ -526,7 +525,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ rc = connect(sockfd, ai->ai_addr, ai->ai_addrlen); if(-1 == rc) { - int error=ourerrno(); + int error=Curl_ourerrno(); switch (error) { case EINPROGRESS: @@ -645,7 +644,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ sizeof(serv_addr)); if(-1 == rc) { - int error=ourerrno(); + int error=Curl_ourerrno(); switch (error) { case EINPROGRESS: -- cgit v1.2.1 From 871358a6e552b991177446d4c96acc5dd892c213 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 12 May 2003 13:06:48 +0000 Subject: before checking for network interfaces using if2ip(), check that the given name isn't an ip address --- lib/connect.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 1b7a55b5a..125d388d8 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -213,7 +213,11 @@ static CURLcode bindlocal(struct connectdata *conn, char myhost[256] = ""; in_addr_t in; - if(Curl_if2ip(data->set.device, myhost, sizeof(myhost))) { + /* First check if the given name is an IP address */ + in=inet_addr(data->set.device); + + if((in == INADDR_NONE) && + Curl_if2ip(data->set.device, myhost, sizeof(myhost))) { /* * We now have the numerical IPv4-style x.y.z.w in the 'myhost' buffer */ -- cgit v1.2.1 From e615d117a010e068f3d0639928cc9555b14c0077 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 13 May 2003 12:12:17 +0000 Subject: Setup and use CURL_INADDR_NONE all over instead of INADDR_NONE. We setup the define accordingly in the hostip.h header to work nicely all over. --- lib/connect.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 125d388d8..9a78f1610 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -197,10 +197,6 @@ static CURLcode bindlocal(struct connectdata *conn, #ifdef HAVE_INET_NTOA -#ifndef INADDR_NONE -#define INADDR_NONE (in_addr_t) ~0 -#endif - struct SessionHandle *data = conn->data; /************************************************************* @@ -216,7 +212,7 @@ static CURLcode bindlocal(struct connectdata *conn, /* First check if the given name is an IP address */ in=inet_addr(data->set.device); - if((in == INADDR_NONE) && + if((in == CURL_INADDR_NONE) && Curl_if2ip(data->set.device, myhost, sizeof(myhost))) { /* * We now have the numerical IPv4-style x.y.z.w in the 'myhost' buffer @@ -250,7 +246,7 @@ static CURLcode bindlocal(struct connectdata *conn, infof(data, "We bind local end to %s\n", myhost); in=inet_addr(myhost); - if (INADDR_NONE != in) { + if (CURL_INADDR_NONE != in) { if ( h ) { Curl_addrinfo *addr = h->addr; -- cgit v1.2.1 From 1eef6f44ba59c051870324a4c9405c000ac1eaf2 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 26 Jun 2003 06:47:20 +0000 Subject: CURLDEBUG instead of MALLOCDEBUG --- lib/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 9a78f1610..681fc0039 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -77,7 +77,7 @@ #include "if2ip.h" /* The last #include file should be: */ -#ifdef MALLOCDEBUG +#ifdef CURLDEBUG #include "memdebug.h" #endif -- cgit v1.2.1 From b73612392d7afbf9835a119446e2a58e72384b00 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 5 Aug 2003 14:40:59 +0000 Subject: ares awareness/usage/support added. If configure --enable-ares is used, we build libcurl to use ares for asynch name resolves. --- lib/connect.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 681fc0039..9bc7d5076 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -208,6 +208,7 @@ static CURLcode bindlocal(struct connectdata *conn, size_t size; char myhost[256] = ""; in_addr_t in; + int rc; /* First check if the given name is an IP address */ in=inet_addr(data->set.device); @@ -217,7 +218,10 @@ static CURLcode bindlocal(struct connectdata *conn, /* * We now have the numerical IPv4-style x.y.z.w in the 'myhost' buffer */ - h = Curl_resolv(data, myhost, 0); + rc = Curl_resolv(conn, myhost, 0, &h); + if(rc == 1) + rc = Curl_wait_for_resolv(conn, &h); + } else { if(strlen(data->set.device)>1) { @@ -225,11 +229,14 @@ static CURLcode bindlocal(struct connectdata *conn, * This was not an interface, resolve the name as a host name * or IP number */ - h = Curl_resolv(data, data->set.device, 0); - if(h) { + rc = Curl_resolv(conn, data->set.device, 0, &h); + if(rc == 1) + rc = Curl_wait_for_resolv(conn, &h); + + if(h) /* we know data->set.device is shorter than the myhost array */ strcpy(myhost, data->set.device); - } + } } -- cgit v1.2.1 From 96fecba190b3968a2c076272e3cd80834dd66e66 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 11 Aug 2003 23:15:13 +0000 Subject: bindlocal works for Windows! --- lib/connect.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 9bc7d5076..e19a01b2d 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -70,6 +70,7 @@ #define EINPROGRESS WSAEINPROGRESS #define EWOULDBLOCK WSAEWOULDBLOCK #define EISCONN WSAEISCONN +#define ENOTSOCK WSAENOTSOCK #endif #include "urldata.h" @@ -190,11 +191,6 @@ int waitconnect(int sockfd, /* socket */ static CURLcode bindlocal(struct connectdata *conn, int sockfd) { -#if !defined(WIN32)||defined(__CYGWIN32__) - /* We don't generally like checking for OS-versions, we should make this - HAVE_XXXX based, although at the moment I don't have a decent test for - this! */ - #ifdef HAVE_INET_NTOA struct SessionHandle *data = conn->data; @@ -342,7 +338,6 @@ static CURLcode bindlocal(struct connectdata *conn, } /* end of device selection support */ #endif /* end of HAVE_INET_NTOA */ -#endif /* end of not WIN32 */ return CURLE_HTTP_PORT_FAILED; } -- cgit v1.2.1 From 57b6202eaaee82af17e0a64e643a8dbf7c3d9f9a Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sun, 5 Oct 2003 15:02:58 +0000 Subject: New code for BeOS-style non-blocking sockets, provided by Shard and Jeremy Friesner. --- lib/connect.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index e19a01b2d..92298d3fe 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -103,6 +103,7 @@ int Curl_nonblock(int socket, /* operate on this */ { #undef SETBLOCK #ifdef HAVE_O_NONBLOCK + /* most recent unix versions */ int flags; flags = fcntl(socket, F_GETFL, 0); @@ -114,6 +115,7 @@ int Curl_nonblock(int socket, /* operate on this */ #endif #ifdef HAVE_FIONBIO + /* older unix versions */ int flags; flags = nonblock; @@ -122,6 +124,7 @@ int Curl_nonblock(int socket, /* operate on this */ #endif #ifdef HAVE_IOCTLSOCKET + /* Windows? */ int flags; flags = nonblock; return ioctlsocket(socket, FIONBIO, &flags); @@ -129,13 +132,21 @@ int Curl_nonblock(int socket, /* operate on this */ #endif #ifdef HAVE_IOCTLSOCKET_CASE + /* presumably for Amiga */ return IoctlSocket(socket, FIONBIO, (long)nonblock); #define SETBLOCK 4 #endif +#ifdef HAVE_SO_NONBLOCK + /* BeOS */ + long b = nonblock ? 1 : 0; + return setsockopt(socket, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b)); +#define SETBLOCK 5 +#endif + #ifdef HAVE_DISABLED_NONBLOCKING return 0; /* returns success */ -#define SETBLOCK 5 +#define SETBLOCK 6 #endif #ifndef SETBLOCK @@ -348,11 +359,11 @@ int socketerror(int sockfd) { int err = 0; socklen_t errSize = sizeof(err); - +#ifdef SO_ERROR if( -1 == getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *)&err, &errSize)) err = Curl_ourerrno(); - +#endif return err; } -- cgit v1.2.1 From 5c52cacc98b838a891d0b0bb62c8d96a3377d60c Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 8 Oct 2003 13:32:43 +0000 Subject: - Frank Ticheler provided a patch that fixes how libcurl connects to multiple addresses, if one of them fails (ipv4-code). --- lib/connect.c | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 92298d3fe..2330e6418 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -620,23 +620,6 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ failf(data, "no address available"); return CURLE_COULDNT_CONNECT; } - /* create an IPv4 TCP socket */ - sockfd = socket(AF_INET, SOCK_STREAM, 0); - if(-1 == sockfd) { - failf(data, "couldn't create socket"); - return CURLE_COULDNT_CONNECT; /* big time error */ - } - - if(conn->data->set.device) { - /* user selected to bind the outgoing socket to a specified "device" - before doing connect */ - CURLcode res = bindlocal(conn, sockfd); - if(res) - return res; - } - - /* Convert socket to non-blocking type */ - Curl_nonblock(sockfd, TRUE); /* This is the loop that attempts to connect to all IP-addresses we know for the given host. One by one. */ @@ -645,6 +628,24 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ aliasindex++) { struct sockaddr_in serv_addr; + /* create an IPv4 TCP socket */ + sockfd = socket(AF_INET, SOCK_STREAM, 0); + if(-1 == sockfd) { + failf(data, "couldn't create socket"); + return CURLE_COULDNT_CONNECT; /* big time error */ + } + + if(conn->data->set.device) { + /* user selected to bind the outgoing socket to a specified "device" + before doing connect */ + CURLcode res = bindlocal(conn, sockfd); + if(res) + return res; + } + + /* Convert socket to non-blocking type */ + Curl_nonblock(sockfd, TRUE); + /* do this nasty work to do the connect */ memset((char *) &serv_addr, '\0', sizeof(serv_addr)); memcpy((char *)&(serv_addr.sin_addr), @@ -706,6 +707,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ if(0 != rc) { /* get a new timeout for next attempt */ + sclose(sockfd); after = Curl_tvnow(); timeout_ms -= Curl_tvdiff(after, before); if(timeout_ms < 0) { @@ -717,9 +719,9 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ } break; } + if(0 != rc) { /* no good connect was made */ - sclose(sockfd); *sockconn = -1; failf(data, "Connect failed"); return CURLE_COULDNT_CONNECT; -- cgit v1.2.1 From 749f5387c19449209615b282ac738032f2a890e7 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 14 Oct 2003 12:00:45 +0000 Subject: Gisle Vanem's IPv6-on-Windows patch applied! --- lib/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 2330e6418..69d0dd308 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -66,11 +66,11 @@ #ifdef WIN32 #define HAVE_IOCTLSOCKET #include -#include #define EINPROGRESS WSAEINPROGRESS #define EWOULDBLOCK WSAEWOULDBLOCK #define EISCONN WSAEISCONN #define ENOTSOCK WSAENOTSOCK +#define ECONNREFUSED WSAECONNREFUSED #endif #include "urldata.h" -- cgit v1.2.1 From a9af971c595fbc8b452b0cb5b51d080a314d30ac Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 15 Oct 2003 11:42:57 +0000 Subject: Avoid doing getsockopt() on Windows to verify connects. It seems that this hogs Windows machines when libcurl is being used multi-threaded (with > ~50 threads). Andrew Fuller helped us verify and test this. According to a MSDN web page on connect(), it returns 0 when the connect is done and thus we don't need the getsockopt() call anyway on Windows. --- lib/connect.c | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 69d0dd308..bf27ba29b 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -353,18 +353,27 @@ static CURLcode bindlocal(struct connectdata *conn, return CURLE_HTTP_PORT_FAILED; } - -static -int socketerror(int sockfd) +/* + * verifyconnect() returns TRUE if the connect really has happened. + */ +static bool verifyconnect(int sockfd) { +#if defined(SO_ERROR) && !defined(WIN32) int err = 0; socklen_t errSize = sizeof(err); -#ifdef SO_ERROR if( -1 == getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *)&err, &errSize)) err = Curl_ourerrno(); + + if ((0 == err) || (EISCONN == err)) + /* we are connected, awesome! */ + return TRUE; + + /* This wasn't a successful connect */ + return FALSE; +#else + return TRUE; #endif - return err; } /* @@ -415,14 +424,13 @@ CURLcode Curl_is_connected(struct connectdata *conn, rc = waitconnect(sockfd, 0); if(0 == rc) { - int err = socketerror(sockfd); - if ((0 == err) || (EISCONN == err)) { + if (verifyconnect(sockfd)) { /* we are connected, awesome! */ *connected = TRUE; return CURLE_OK; } /* nope, not connected for real */ - failf(data, "Connection failed, socket error: %d", err); + failf(data, "Connection failed"); return CURLE_COULDNT_CONNECT; } else if(1 != rc) { @@ -568,10 +576,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ if(0 == rc) { /* we might be connected, if the socket says it is OK! Ask it! */ - int err; - - err = socketerror(sockfd); - if ((0 == err) || (EISCONN == err)) { + if(verifyconnect(sockfd)) { /* we are connected, awesome! */ *connected = TRUE; /* this is truly a connect */ break; @@ -695,8 +700,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ } if(0 == rc) { - int err = socketerror(sockfd); - if ((0 == err) || (EISCONN == err)) { + if (verifyconnect(sockfd)) { /* we are connected, awesome! */ *connected = TRUE; /* this is a true connect */ break; -- cgit v1.2.1 From 7201a5a290551893cb20fba41ba818c8cfaccb87 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 15 Oct 2003 20:37:00 +0000 Subject: the previous fix left this compiler error --- lib/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index bf27ba29b..bde66b764 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -581,7 +581,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ *connected = TRUE; /* this is truly a connect */ break; } - failf(data, "socket error: %d", err); + failf(data, "socket error"); /* we are _not_ connected, it was a false alert, continue please */ } else if(2 == rc) -- cgit v1.2.1 From 5eee801d06b0447c156a935df2d71bf05f20ce7f Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 18 Oct 2003 20:34:33 +0000 Subject: don't shadow 'socket' --- lib/connect.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index bde66b764..164fe328d 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -98,7 +98,7 @@ int Curl_ourerrno(void) * Set the socket to either blocking or non-blocking mode. */ -int Curl_nonblock(int socket, /* operate on this */ +int Curl_nonblock(int sockfd, /* operate on this */ int nonblock /* TRUE or FALSE */) { #undef SETBLOCK @@ -106,11 +106,11 @@ int Curl_nonblock(int socket, /* operate on this */ /* most recent unix versions */ int flags; - flags = fcntl(socket, F_GETFL, 0); + flags = fcntl(sockfd, F_GETFL, 0); if (TRUE == nonblock) - return fcntl(socket, F_SETFL, flags | O_NONBLOCK); + return fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); else - return fcntl(socket, F_SETFL, flags & (~O_NONBLOCK)); + return fcntl(sockfd, F_SETFL, flags & (~O_NONBLOCK)); #define SETBLOCK 1 #endif @@ -119,7 +119,7 @@ int Curl_nonblock(int socket, /* operate on this */ int flags; flags = nonblock; - return ioctl(socket, FIONBIO, &flags); + return ioctl(sockfd, FIONBIO, &flags); #define SETBLOCK 2 #endif @@ -127,20 +127,20 @@ int Curl_nonblock(int socket, /* operate on this */ /* Windows? */ int flags; flags = nonblock; - return ioctlsocket(socket, FIONBIO, &flags); + return ioctlsocket(sockfd, FIONBIO, &flags); #define SETBLOCK 3 #endif #ifdef HAVE_IOCTLSOCKET_CASE /* presumably for Amiga */ - return IoctlSocket(socket, FIONBIO, (long)nonblock); + return IoctlSocket(sockfd, FIONBIO, (long)nonblock); #define SETBLOCK 4 #endif #ifdef HAVE_SO_NONBLOCK /* BeOS */ long b = nonblock ? 1 : 0; - return setsockopt(socket, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b)); + return setsockopt(sockfd, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b)); #define SETBLOCK 5 #endif -- cgit v1.2.1 From 43bb20461fd5fa000eaf6bb7a321c7c92a996ab4 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 13 Nov 2003 13:28:40 +0000 Subject: Peter Sylvester found a flaw in the connect code for ipv6-enabled hosts. I guess it seldomly happens on linux and that's why it wasn't found before. He used Solaris to notice it. I took the opportunity to rewrite the Curl_connecthost() slightly to feature less duplicate code in the two different versions (ipv4/ipv6). --- lib/connect.c | 184 ++++++++++++++++------------------------------------------ 1 file changed, 49 insertions(+), 135 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 164fe328d..96bfebbe5 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -473,6 +473,10 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ struct timeval after; struct timeval before = Curl_tvnow(); +#ifdef ENABLE_IPV6 + struct addrinfo *ai; +#endif + /************************************************************* * Figure out what maximum time we have left *************************************************************/ @@ -513,118 +517,21 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ } hostname = data->change.proxy?conn->proxyhost:conn->hostname; - infof(data, "About to connect() to %s%s%s:%d\n", - conn->bits.ipv6_ip?"[":"", - hostname, - conn->bits.ipv6_ip?"]":"", - port); + infof(data, "About to connect() to %s port %d\n", + hostname, port); #ifdef ENABLE_IPV6 /* - * Connecting with IPv6 support is so much easier and cleanly done + * Connecting with a getaddrinfo chain */ - { - struct addrinfo *ai; - port =0; /* prevent compiler warning */ - - for (ai = remotehost->addr; ai; ai = ai->ai_next, aliasindex++) { - sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); - if (sockfd < 0) - continue; - - if(conn->data->set.device) { - /* user selected to bind the outgoing socket to a specified "device" - before doing connect */ - CURLcode res = bindlocal(conn, sockfd); - if(res) - return res; - } - - /* set socket non-blocking */ - Curl_nonblock(sockfd, TRUE); - - rc = connect(sockfd, ai->ai_addr, ai->ai_addrlen); - - if(-1 == rc) { - int error=Curl_ourerrno(); - - switch (error) { - case EINPROGRESS: - case EWOULDBLOCK: -#if defined(EAGAIN) && EAGAIN != EWOULDBLOCK - /* On some platforms EAGAIN and EWOULDBLOCK are the - * same value, and on others they are different, hence - * the odd #if - */ - case EAGAIN: -#endif - case EINTR: - /* asynchronous connect, wait for connect or timeout */ - if(data->state.used_interface == Curl_if_multi) - /* don't hang when doing multi */ - timeout_ms = 0; - - rc = waitconnect(sockfd, timeout_ms); - break; - case ECONNREFUSED: /* no one listening */ - default: - /* unknown error, fallthrough and try another address! */ - failf(data, "Failed connect to %s: %d", hostname, error); - break; - } - } - - if(0 == rc) { - /* we might be connected, if the socket says it is OK! Ask it! */ - if(verifyconnect(sockfd)) { - /* we are connected, awesome! */ - *connected = TRUE; /* this is truly a connect */ - break; - } - failf(data, "socket error"); - /* we are _not_ connected, it was a false alert, continue please */ - } - else if(2 == rc) - /* waitconnect() returned error */ - ; - else if(data->state.used_interface == Curl_if_multi) { - /* When running the multi interface, we bail out here */ - rc = 0; - break; - } - - /* connect failed or timed out */ - sclose(sockfd); - sockfd = -1; - - /* get a new timeout for next attempt */ - after = Curl_tvnow(); - timeout_ms -= Curl_tvdiff(after, before); - if(timeout_ms < 0) { - failf(data, "connect() timed out!"); - return CURLE_OPERATION_TIMEOUTED; - } - before = after; - continue; - } + for (ai = remotehost->addr; ai; ai = ai->ai_next, aliasindex++) { + sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (sockfd < 0) - return CURLE_COULDNT_CONNECT; - - /* leave the socket in non-blocking mode */ - - if(addr) - *addr = ai; /* the address we ended up connected to */ - } + continue; #else /* - * Connecting with IPv4-only support + * Connecting with old style IPv4-only support */ - if(!remotehost->addr->h_addr_list[0]) { - /* If there is no addresses in the address list, then we return - error right away */ - failf(data, "no address available"); - return CURLE_COULDNT_CONNECT; - } /* This is the loop that attempts to connect to all IP-addresses we know for the given host. One by one. */ @@ -639,7 +546,16 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ failf(data, "couldn't create socket"); return CURLE_COULDNT_CONNECT; /* big time error */ } - + + /* nasty address work before connect can be made */ + memset((char *) &serv_addr, '\0', sizeof(serv_addr)); + memcpy((char *)&(serv_addr.sin_addr), + (struct in_addr *)remotehost->addr->h_addr_list[aliasindex], + sizeof(struct in_addr)); + serv_addr.sin_family = remotehost->addr->h_addrtype; + serv_addr.sin_port = htons((unsigned short)port); +#endif + if(conn->data->set.device) { /* user selected to bind the outgoing socket to a specified "device" before doing connect */ @@ -648,19 +564,16 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ return res; } - /* Convert socket to non-blocking type */ + /* set socket non-blocking */ Curl_nonblock(sockfd, TRUE); - /* do this nasty work to do the connect */ - memset((char *) &serv_addr, '\0', sizeof(serv_addr)); - memcpy((char *)&(serv_addr.sin_addr), - (struct in_addr *)remotehost->addr->h_addr_list[aliasindex], - sizeof(struct in_addr)); - serv_addr.sin_family = remotehost->addr->h_addrtype; - serv_addr.sin_port = htons((unsigned short)port); - - rc = connect(sockfd, (struct sockaddr *)&serv_addr, - sizeof(serv_addr)); + rc = connect(sockfd, +#ifdef ENABLE_IPV6 + ai->ai_addr, ai->ai_addrlen +#else + (struct sockaddr *)&serv_addr, sizeof(serv_addr) +#endif + ); if(-1 == rc) { int error=Curl_ourerrno(); @@ -679,7 +592,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ if(data->state.used_interface == Curl_if_multi) /* don't hang when doing multi */ timeout_ms = 0; - + rc = waitconnect(sockfd, timeout_ms); break; default: @@ -698,7 +611,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ rc = 0; break; } - + if(0 == rc) { if (verifyconnect(sockfd)) { /* we are connected, awesome! */ @@ -709,22 +622,20 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ rc = -1; } - if(0 != rc) { - /* get a new timeout for next attempt */ - sclose(sockfd); - after = Curl_tvnow(); - timeout_ms -= Curl_tvdiff(after, before); - if(timeout_ms < 0) { - failf(data, "Connect timeout on IP number %d", aliasindex+1); - break; - } - before = after; - continue; /* try next address */ + /* connect failed or timed out */ + sclose(sockfd); + sockfd = -1; + + /* get a new timeout for next attempt */ + after = Curl_tvnow(); + timeout_ms -= Curl_tvdiff(after, before); + if(timeout_ms < 0) { + failf(data, "connect() timed out!"); + return CURLE_OPERATION_TIMEOUTED; } - break; + before = after; } - - if(0 != rc) { + if (sockfd < 0) { /* no good connect was made */ *sockconn = -1; failf(data, "Connect failed"); @@ -733,10 +644,14 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ /* leave the socket in non-blocking mode */ - if(addr) - /* this is the address we've connected to */ + /* store the address we use */ + if(addr) { +#ifdef ENABLE_IPV6 + *addr = ai; +#else *addr = (struct in_addr *)remotehost->addr->h_addr_list[aliasindex]; #endif + } /* allow NULL-pointers to get passed in */ if(sockconn) @@ -744,4 +659,3 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ return CURLE_OK; } - -- cgit v1.2.1 From 053f6c85efd0bf698f73343989474d672d0563a8 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 7 Jan 2004 09:19:33 +0000 Subject: updated year in the copyright string --- lib/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 96bfebbe5..3fb0a65d6 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2003, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2004, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms -- cgit v1.2.1 From c5c89862b2cb8a0d695d81c2180479d14faf5113 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 14 Jan 2004 09:11:42 +0000 Subject: rearranged the connect() call so that there's no interleaved #ifdef, to make it compiler better on amigaos --- lib/connect.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 3fb0a65d6..0dc655353 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -567,13 +567,14 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ /* set socket non-blocking */ Curl_nonblock(sockfd, TRUE); - rc = connect(sockfd, + /* do not use #ifdef within the function arguments below, as connect() is + a defined macro on some platforms and some compilers don't like to mix + #ifdefs with macro usage! (AmigaOS is one such platform) */ #ifdef ENABLE_IPV6 - ai->ai_addr, ai->ai_addrlen + rc = connect(sockfd, ai->ai_addr, ai->ai_addrlen); #else - (struct sockaddr *)&serv_addr, sizeof(serv_addr) + rc = connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr); #endif - ); if(-1 == rc) { int error=Curl_ourerrno(); -- cgit v1.2.1 From 7052daf475172d6e4105e714d1486a0201b59017 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 15 Jan 2004 09:54:30 +0000 Subject: added missing parenthesis --- lib/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 0dc655353..33e16dd72 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -573,7 +573,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ #ifdef ENABLE_IPV6 rc = connect(sockfd, ai->ai_addr, ai->ai_addrlen); #else - rc = connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr); + rc = connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)); #endif if(-1 == rc) { -- cgit v1.2.1 From 4d17d6876e4b2f08380812c4ec113073b0a14639 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 29 Jan 2004 13:56:45 +0000 Subject: Dan Fandrich's cleanup patch to make pedantic compiler options cause less warnings. Minor edits by me. --- lib/connect.c | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 33e16dd72..69f8ce374 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -76,6 +76,7 @@ #include "urldata.h" #include "sendf.h" #include "if2ip.h" +#include "connect.h" /* The last #include file should be: */ #ifdef CURLDEBUG -- cgit v1.2.1 From 76a51ef4b3c4d1db80223a57ff9928019d3312cb Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 29 Jan 2004 15:29:47 +0000 Subject: 1. changed order of two include files to build fine on MPE/iX 2. now reads the socket error before check connect status, also to make us run fine on MPE/iX --- lib/connect.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 69f8ce374..0d8d278f8 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -26,8 +26,12 @@ #ifndef WIN32 /* headers for non-win32 */ #include -#include +#ifdef HAVE_SYS_TYPES_H #include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif #include #ifdef HAVE_UNISTD_H #include @@ -171,6 +175,11 @@ int waitconnect(int sockfd, /* socket */ struct timeval interval; int rc; + /* Call this function once now, and ignore the results. We do this to + "clear" the error state on the socket so that we can later read it + reliably. This is reported necessary on the MPE/iX operating system. */ + verifyconnect(); + /* now select() until we get connect or timeout */ FD_ZERO(&fd); FD_SET(sockfd, &fd); -- cgit v1.2.1 From bfe5568c8515a628e128f4ab88f139c583847e56 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 29 Jan 2004 15:37:21 +0000 Subject: added verifyconnect proto and use it correctly in the waitconnect function --- lib/connect.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 0d8d278f8..97fb15ccd 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -87,6 +87,8 @@ #include "memdebug.h" #endif +static bool verifyconnect(int sockfd); + int Curl_ourerrno(void) { #ifdef WIN32 @@ -178,7 +180,7 @@ int waitconnect(int sockfd, /* socket */ /* Call this function once now, and ignore the results. We do this to "clear" the error state on the socket so that we can later read it reliably. This is reported necessary on the MPE/iX operating system. */ - verifyconnect(); + verifyconnect(sockfd); /* now select() until we get connect or timeout */ FD_ZERO(&fd); -- cgit v1.2.1 From 6b7f169b101654a7abe8cda6da75a88dccdd8e6d Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 30 Jan 2004 07:51:51 +0000 Subject: only do the verifyconnect() clear magic on mpeix --- lib/connect.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 97fb15ccd..97e7bd38e 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -176,11 +176,12 @@ int waitconnect(int sockfd, /* socket */ fd_set errfd; struct timeval interval; int rc; - +#ifdef mpeix /* Call this function once now, and ignore the results. We do this to "clear" the error state on the socket so that we can later read it reliably. This is reported necessary on the MPE/iX operating system. */ verifyconnect(sockfd); +#endif /* now select() until we get connect or timeout */ FD_ZERO(&fd); -- cgit v1.2.1 From 3bdc883c937a656a5998c94a53615ee9f2d3d820 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 9 Feb 2004 08:34:19 +0000 Subject: some annoying compilers warn about "(void)foo;" lines so we avoid them --- lib/connect.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 97e7bd38e..e6bfbdae9 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -223,7 +223,6 @@ static CURLcode bindlocal(struct connectdata *conn, * Select device to bind socket to *************************************************************/ if (strlen(data->set.device)<255) { - struct sockaddr_in sa; struct Curl_dns_entry *h=NULL; size_t size; char myhost[256] = ""; @@ -282,7 +281,6 @@ static CURLcode bindlocal(struct connectdata *conn, /* we don't need it anymore after this function has returned */ #ifdef ENABLE_IPV6 - (void)sa; /* prevent compiler warning */ if( bind(sockfd, addr->ai_addr, addr->ai_addrlen) >= 0) { /* we succeeded to bind */ struct sockaddr_in6 add; @@ -295,21 +293,25 @@ static CURLcode bindlocal(struct connectdata *conn, } } #else - memset((char *)&sa, 0, sizeof(sa)); - memcpy((char *)&sa.sin_addr, addr->h_addr, addr->h_length); - sa.sin_family = AF_INET; - sa.sin_addr.s_addr = in; - sa.sin_port = 0; /* get any port */ + { + struct sockaddr_in sa; + + memset((char *)&sa, 0, sizeof(sa)); + memcpy((char *)&sa.sin_addr, addr->h_addr, addr->h_length); + sa.sin_family = AF_INET; + sa.sin_addr.s_addr = in; + sa.sin_port = 0; /* get any port */ - if( bind(sockfd, (struct sockaddr *)&sa, sizeof(sa)) >= 0) { - /* we succeeded to bind */ - struct sockaddr_in add; + if( bind(sockfd, (struct sockaddr *)&sa, sizeof(sa)) >= 0) { + /* we succeeded to bind */ + struct sockaddr_in add; - size = sizeof(add); - if(getsockname(sockfd, (struct sockaddr *) &add, - (socklen_t *)&size)<0) { - failf(data, "getsockname() failed"); - return CURLE_HTTP_PORT_FAILED; + size = sizeof(add); + if(getsockname(sockfd, (struct sockaddr *) &add, + (socklen_t *)&size)<0) { + failf(data, "getsockname() failed"); + return CURLE_HTTP_PORT_FAILED; + } } } #endif -- cgit v1.2.1 From 2d0b2f294f51d1f759b1c25d53ee23477740741f Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 9 Feb 2004 11:40:00 +0000 Subject: Oops. I broke the flow with the previous commit. --- lib/connect.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index e6bfbdae9..9c140c9f9 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -216,7 +216,7 @@ static CURLcode bindlocal(struct connectdata *conn, int sockfd) { #ifdef HAVE_INET_NTOA - + bool bindworked = FALSE; struct SessionHandle *data = conn->data; /************************************************************* @@ -284,6 +284,8 @@ static CURLcode bindlocal(struct connectdata *conn, if( bind(sockfd, addr->ai_addr, addr->ai_addrlen) >= 0) { /* we succeeded to bind */ struct sockaddr_in6 add; + + bindworked = TRUE; size = sizeof(add); if(getsockname(sockfd, (struct sockaddr *) &add, @@ -306,6 +308,8 @@ static CURLcode bindlocal(struct connectdata *conn, /* we succeeded to bind */ struct sockaddr_in add; + bindworked = TRUE; + size = sizeof(add); if(getsockname(sockfd, (struct sockaddr *) &add, (socklen_t *)&size)<0) { @@ -315,7 +319,7 @@ static CURLcode bindlocal(struct connectdata *conn, } } #endif - else { + if(!bindworked) { switch(errno) { case EBADF: failf(data, "Invalid descriptor: %d", errno); -- cgit v1.2.1 From fa57a8a78ef52328129b23029ca375a1e809d029 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 13 Feb 2004 09:50:23 +0000 Subject: Ben Greear's SO_BINDTODEVICE patch that binds to a network interface "even more" when the previous approach. Known to work on Linux, possibly on other platforms as well. --- lib/connect.c | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 9c140c9f9..c9578c178 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -228,6 +228,7 @@ static CURLcode bindlocal(struct connectdata *conn, char myhost[256] = ""; in_addr_t in; int rc; + bool was_iface = FALSE; /* First check if the given name is an IP address */ in=inet_addr(data->set.device); @@ -239,7 +240,10 @@ static CURLcode bindlocal(struct connectdata *conn, */ rc = Curl_resolv(conn, myhost, 0, &h); if(rc == 1) - rc = Curl_wait_for_resolv(conn, &h); + (void)Curl_wait_for_resolv(conn, &h); + + if(h) + was_iface = TRUE; } else { @@ -250,7 +254,7 @@ static CURLcode bindlocal(struct connectdata *conn, */ rc = Curl_resolv(conn, data->set.device, 0, &h); if(rc == 1) - rc = Curl_wait_for_resolv(conn, &h); + (void)Curl_wait_for_resolv(conn, &h); if(h) /* we know data->set.device is shorter than the myhost array */ @@ -266,11 +270,37 @@ static CURLcode bindlocal(struct connectdata *conn, hostent_buf, sizeof(hostent_buf)); */ + failf(data, "Couldn't bind to '%s'", data->set.device); return CURLE_HTTP_PORT_FAILED; } infof(data, "We bind local end to %s\n", myhost); +#ifdef SO_BINDTODEVICE + /* I am not sure any other OSs than Linux that provide this feature, and + * at the least I cannot test. --Ben + * + * This feature allows one to tightly bind the local socket to a + * particular interface. This will force even requests to other local + * interfaces to go out the external interface. + * + */ + if (was_iface) { + /* Only bind to the interface when specified as interface, not just as a + * hostname or ip address. + */ + if (setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, + data->set.device, strlen(data->set.device)+1) != 0) { + /* printf("Failed to BINDTODEVICE, socket: %d device: %s error: %s\n", + sockfd, data->set.device, strerror(errno)); */ + infof(data, "SO_BINDTODEVICE %s failed\n", + data->set.device); + /* This is typiclally "errno 1, error: Operation not permitted" if + you're not running as root or another suitable privileged user */ + } + } +#endif + in=inet_addr(myhost); if (CURL_INADDR_NONE != in) { -- cgit v1.2.1 From 0d3aa8b7be9c3f8423359d090148fb7da0e5ea49 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sun, 15 Feb 2004 13:55:24 +0000 Subject: Use the was_iface variable when binding a socket locally, even if no SO_BINDTODEVICE is present, to prevent compiler warnings about the variable --- lib/connect.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index c9578c178..97d5d34d0 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -244,23 +244,20 @@ static CURLcode bindlocal(struct connectdata *conn, if(h) was_iface = TRUE; - } - else { - if(strlen(data->set.device)>1) { - /* - * This was not an interface, resolve the name as a host name - * or IP number - */ - rc = Curl_resolv(conn, data->set.device, 0, &h); - if(rc == 1) - (void)Curl_wait_for_resolv(conn, &h); - if(h) - /* we know data->set.device is shorter than the myhost array */ - strcpy(myhost, data->set.device); + if(!was_iface) { + /* + * This was not an interface, resolve the name as a host name + * or IP number + */ + rc = Curl_resolv(conn, data->set.device, 0, &h); + if(rc == 1) + (void)Curl_wait_for_resolv(conn, &h); - } + if(h) + /* we know data->set.device is shorter than the myhost array */ + strcpy(myhost, data->set.device); } if(! *myhost) { -- cgit v1.2.1 From e40392ac035d2d545027659d5fca8255e586f8cb Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 4 Mar 2004 15:32:18 +0000 Subject: =?UTF-8?q?Andr=E9s=20Garc=EDa's=20patch=20to=20prevent=20warnings?= =?UTF-8?q?=20while=20compiling=20with=20mingw,=20mainly=20because=20it=20?= =?UTF-8?q?is=20now=20possible=20to=20have=20both=20WIN32=20and=20HAVE=5FC?= =?UTF-8?q?ONFIG=5FH=20defined.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/connect.c | 1 - 1 file changed, 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 97d5d34d0..3de043b94 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -68,7 +68,6 @@ #endif #ifdef WIN32 -#define HAVE_IOCTLSOCKET #include #define EINPROGRESS WSAEINPROGRESS #define EWOULDBLOCK WSAEWOULDBLOCK -- cgit v1.2.1 From 576be36249407e0450f507676a49cc5630ba6532 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 8 Mar 2004 11:36:47 +0000 Subject: waitconnect() takes the timeout argument as a long --- lib/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 3de043b94..1aedcbfcf 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -169,7 +169,7 @@ int Curl_nonblock(int sockfd, /* operate on this */ */ static int waitconnect(int sockfd, /* socket */ - int timeout_msec) + long timeout_msec) { fd_set fd; fd_set errfd; -- cgit v1.2.1 From ce5805a955c5a79d85792caad47594987f0e0b26 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 9 Mar 2004 22:52:50 +0000 Subject: Use curl_socket_t instead of int for holding sockets. The typedefs and defines are in setup.h. --- lib/connect.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 1aedcbfcf..dd4401585 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -86,7 +86,7 @@ #include "memdebug.h" #endif -static bool verifyconnect(int sockfd); +static bool verifyconnect(curl_socket_t sockfd); int Curl_ourerrno(void) { @@ -104,7 +104,7 @@ int Curl_ourerrno(void) * Set the socket to either blocking or non-blocking mode. */ -int Curl_nonblock(int sockfd, /* operate on this */ +int Curl_nonblock(curl_socket_t sockfd, /* operate on this */ int nonblock /* TRUE or FALSE */) { #undef SETBLOCK @@ -168,7 +168,7 @@ int Curl_nonblock(int sockfd, /* operate on this */ * 2 select() returned with an error condition */ static -int waitconnect(int sockfd, /* socket */ +int waitconnect(curl_socket_t sockfd, /* socket */ long timeout_msec) { fd_set fd; @@ -212,7 +212,7 @@ int waitconnect(int sockfd, /* socket */ } static CURLcode bindlocal(struct connectdata *conn, - int sockfd) + curl_socket_t sockfd) { #ifdef HAVE_INET_NTOA bool bindworked = FALSE; @@ -401,7 +401,7 @@ static CURLcode bindlocal(struct connectdata *conn, /* * verifyconnect() returns TRUE if the connect really has happened. */ -static bool verifyconnect(int sockfd) +static bool verifyconnect(curl_socket_t sockfd) { #if defined(SO_ERROR) && !defined(WIN32) int err = 0; @@ -427,7 +427,7 @@ static bool verifyconnect(int sockfd) */ CURLcode Curl_is_connected(struct connectdata *conn, - int sockfd, + curl_socket_t sockfd, bool *connected) { int rc; @@ -505,13 +505,13 @@ CURLcode Curl_is_connected(struct connectdata *conn, CURLcode Curl_connecthost(struct connectdata *conn, /* context */ struct Curl_dns_entry *remotehost, /* use this one */ int port, /* connect to this */ - int *sockconn, /* the connected socket */ + curl_socket_t *sockconn, /* the connected socket */ Curl_ipconnect **addr, /* the one we used */ bool *connected) /* really connected? */ { struct SessionHandle *data = conn->data; int rc; - int sockfd=-1; + curl_socket_t sockfd= CURL_SOCKET_BAD; int aliasindex=0; char *hostname; @@ -587,7 +587,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ /* create an IPv4 TCP socket */ sockfd = socket(AF_INET, SOCK_STREAM, 0); - if(-1 == sockfd) { + if(CURL_SOCKET_BAD == sockfd) { failf(data, "couldn't create socket"); return CURLE_COULDNT_CONNECT; /* big time error */ } -- cgit v1.2.1 From e545e33d5fd4f021220f09cf8fb05c66db2a4bf4 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 11 Mar 2004 13:13:35 +0000 Subject: Gisle Vanem's fixes to use CURL_SOCKET_BAD more instead of -1 for sockets. --- lib/connect.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index dd4401585..faa5c419a 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -417,6 +417,7 @@ static bool verifyconnect(curl_socket_t sockfd) /* This wasn't a successful connect */ return FALSE; #else + (void)sockfd; return TRUE; #endif } @@ -571,7 +572,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ */ for (ai = remotehost->addr; ai; ai = ai->ai_next, aliasindex++) { sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); - if (sockfd < 0) + if (sockfd == CURL_SOCKET_BAD) continue; #else /* @@ -681,7 +682,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ } before = after; } - if (sockfd < 0) { + if (sockfd == CURL_SOCKET_BAD) { /* no good connect was made */ *sockconn = -1; failf(data, "Connect failed"); -- cgit v1.2.1 From 5b55f9ecb34a00af236b2275ffa9adab492a93b6 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 17 Mar 2004 12:46:42 +0000 Subject: =?UTF-8?q?G=FCnter=20Knauf's=20NetWare=20changes.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/connect.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index faa5c419a..1b57e3fec 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -52,6 +52,13 @@ #include /* required for free() prototype, without it, this crashes on macos 68K */ #endif +#if (defined(HAVE_FIONBIO) && defined(__NOVELL_LIBC__)) +#include +#endif +#if (defined(NETWARE) && defined(__NOVELL_LIBC__)) +#undef in_addr_t +#define in_addr_t unsigned long +#endif #ifdef VMS #include #include -- cgit v1.2.1 From 1f61e7f8f4df121ca2695870d800f726db4dbb31 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 23 Mar 2004 14:43:42 +0000 Subject: If localbind fails, provide a more portable error message. --- lib/connect.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 1b57e3fec..adeadb59f 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -295,10 +295,10 @@ static CURLcode bindlocal(struct connectdata *conn, if (setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, data->set.device, strlen(data->set.device)+1) != 0) { /* printf("Failed to BINDTODEVICE, socket: %d device: %s error: %s\n", - sockfd, data->set.device, strerror(errno)); */ + sockfd, data->set.device, strerror(Curl_ourerrno())); */ infof(data, "SO_BINDTODEVICE %s failed\n", data->set.device); - /* This is typiclally "errno 1, error: Operation not permitted" if + /* This is typically "errno 1, error: Operation not permitted" if you're not running as root or another suitable privileged user */ } } @@ -353,34 +353,35 @@ static CURLcode bindlocal(struct connectdata *conn, } #endif if(!bindworked) { + int err = Curl_ourerrno(); switch(errno) { case EBADF: - failf(data, "Invalid descriptor: %d", errno); + failf(data, "Invalid descriptor: %d", err); break; case EINVAL: - failf(data, "Invalid request: %d", errno); + failf(data, "Invalid request: %d", err); break; case EACCES: - failf(data, "Address is protected, user not superuser: %d", errno); + failf(data, "Address is protected, user not superuser: %d", err); break; case ENOTSOCK: failf(data, "Argument is a descriptor for a file, not a socket: %d", - errno); + err); break; case EFAULT: - failf(data, "Inaccessable memory error: %d", errno); + failf(data, "Inaccessable memory error: %d", err); break; case ENAMETOOLONG: - failf(data, "Address too long: %d", errno); + failf(data, "Address too long: %d", err); break; case ENOMEM: - failf(data, "Insufficient kernel memory was available: %d", errno); + failf(data, "Insufficient kernel memory was available: %d", err); break; default: - failf(data, "errno %d", errno); + failf(data, "errno %d", err); break; - } /* end of switch(errno) */ + } /* end of switch(err) */ return CURLE_HTTP_PORT_FAILED; } /* end of else */ -- cgit v1.2.1 From fe6f0aeb26170bfe8d7765a865c92264778f712b Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 23 Mar 2004 15:48:27 +0000 Subject: switch() on the right variable! --- lib/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index adeadb59f..14d3a70b4 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -354,7 +354,7 @@ static CURLcode bindlocal(struct connectdata *conn, #endif if(!bindworked) { int err = Curl_ourerrno(); - switch(errno) { + switch(err) { case EBADF: failf(data, "Invalid descriptor: %d", err); break; -- cgit v1.2.1 From b60d6404d80ca58293761fc31ccf34df95116339 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 24 Mar 2004 22:45:37 +0000 Subject: Gisle Vanem's fix to replace the bad use of strerror(). This introduces Curl_strerror() that attempts to be thread-safe _and_ works on Windows too! --- lib/connect.c | 44 ++++++++------------------------------------ 1 file changed, 8 insertions(+), 36 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 14d3a70b4..04e3d234b 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -86,6 +86,7 @@ #include "urldata.h" #include "sendf.h" #include "if2ip.h" +#include "curl_strerror.h" #include "connect.h" /* The last #include file should be: */ @@ -295,7 +296,7 @@ static CURLcode bindlocal(struct connectdata *conn, if (setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, data->set.device, strlen(data->set.device)+1) != 0) { /* printf("Failed to BINDTODEVICE, socket: %d device: %s error: %s\n", - sockfd, data->set.device, strerror(Curl_ourerrno())); */ + sockfd, data->set.device, Curl_strerror(Curl_ourerrno())); */ infof(data, "SO_BINDTODEVICE %s failed\n", data->set.device); /* This is typically "errno 1, error: Operation not permitted" if @@ -353,38 +354,9 @@ static CURLcode bindlocal(struct connectdata *conn, } #endif if(!bindworked) { - int err = Curl_ourerrno(); - switch(err) { - case EBADF: - failf(data, "Invalid descriptor: %d", err); - break; - case EINVAL: - failf(data, "Invalid request: %d", err); - break; - case EACCES: - failf(data, "Address is protected, user not superuser: %d", err); - break; - case ENOTSOCK: - failf(data, - "Argument is a descriptor for a file, not a socket: %d", - err); - break; - case EFAULT: - failf(data, "Inaccessable memory error: %d", err); - break; - case ENAMETOOLONG: - failf(data, "Address too long: %d", err); - break; - case ENOMEM: - failf(data, "Insufficient kernel memory was available: %d", err); - break; - default: - failf(data, "errno %d", err); - break; - } /* end of switch(err) */ - + failf(data, "%s", Curl_strerror(conn, Curl_ourerrno())); return CURLE_HTTP_PORT_FAILED; - } /* end of else */ + } } /* end of if h */ else { @@ -489,8 +461,8 @@ CURLcode Curl_is_connected(struct connectdata *conn, } else if(1 != rc) { int error = Curl_ourerrno(); - failf(data, "Failed connect to %s:%d, errno: %d", - conn->hostname, conn->port, error); + failf(data, "Failed connect to %s:%d; %s", + conn->hostname, conn->port, Curl_strerror(conn,error)); return CURLE_COULDNT_CONNECT; } /* @@ -652,8 +624,8 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ break; default: /* unknown error, fallthrough and try another address! */ - failf(data, "Failed to connect to %s IP number %d: %d", - hostname, aliasindex+1, error); + failf(data, "Failed to connect to %s IP number %d: %s", + hostname, aliasindex+1, Curl_strerror(conn,error)); break; } } -- cgit v1.2.1 From bb3d6e8552f428bd0c2624854403d36ab3cf163d Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 25 Mar 2004 13:37:18 +0000 Subject: tcp-nodelay patch by Joe Halpin --- lib/connect.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 04e3d234b..28783445e 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -31,6 +31,7 @@ #endif #ifdef HAVE_SYS_SOCKET_H #include +#include /* for TCP_NODELAY */ #endif #include #ifdef HAVE_UNISTD_H @@ -476,6 +477,23 @@ CURLcode Curl_is_connected(struct connectdata *conn, return CURLE_OK; } +static void Curl_setNoDelay(struct connectdata *conn, + curl_socket_t sockfd, + int ip) +{ +#ifdef TCP_NODELAY + struct SessionHandle *data= conn->data; + socklen_t onoff = (socklen_t) data->tcp_nodelay; + infof(data,"Setting TCP_NODELAY for IPv%d\n", ip); + if(setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &onoff, sizeof(onoff)) < 0) + infof(data, "Could not set TCP_NODELAY: %s\n", + Curl_strerror(conn, Curl_ourerrno())); +#else + (void)conn; + (void)sockfd; + (void)ip; +#endif +} /* * TCP connect to the given host with timeout, proxy or remote doesn't matter. @@ -554,6 +572,9 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (sockfd == CURL_SOCKET_BAD) continue; + + else if(data->tcp_nodelay) + Curl_setNoDelay(conn, sockfd, 6); #else /* * Connecting with old style IPv4-only support @@ -573,6 +594,9 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ return CURLE_COULDNT_CONNECT; /* big time error */ } + else if(data->tcp_nodelay) + Curl_setNoDelay(conn, sockfd, 4); + /* nasty address work before connect can be made */ memset((char *) &serv_addr, '\0', sizeof(serv_addr)); memcpy((char *)&(serv_addr.sin_addr), -- cgit v1.2.1 From 762dcf0780b0100f50fad21a5d3e5e5613def267 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 25 Mar 2004 13:42:23 +0000 Subject: include the strerror.h file without curl_ prefix --- lib/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 28783445e..eb003c28f 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -87,7 +87,7 @@ #include "urldata.h" #include "sendf.h" #include "if2ip.h" -#include "curl_strerror.h" +#include "strerror.h" #include "connect.h" /* The last #include file should be: */ -- cgit v1.2.1 From e21104a8650a68601a5aaf350c4df5a0f6f38db5 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 25 Mar 2004 14:01:01 +0000 Subject: only output one line about the nodelay even if it fails --- lib/connect.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index eb003c28f..7ac47bff2 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -484,10 +484,11 @@ static void Curl_setNoDelay(struct connectdata *conn, #ifdef TCP_NODELAY struct SessionHandle *data= conn->data; socklen_t onoff = (socklen_t) data->tcp_nodelay; - infof(data,"Setting TCP_NODELAY for IPv%d\n", ip); if(setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &onoff, sizeof(onoff)) < 0) infof(data, "Could not set TCP_NODELAY: %s\n", Curl_strerror(conn, Curl_ourerrno())); + else + infof(data,"TCP_NODELAY set for IPv%d\n", ip); #else (void)conn; (void)sockfd; -- cgit v1.2.1 From db6dc49b0b2e23c0f74daddc25317fea702d6eab Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 26 Mar 2004 07:03:30 +0000 Subject: removed the ip number from the notcpdelay function --- lib/connect.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 7ac47bff2..b5c90f589 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -478,8 +478,7 @@ CURLcode Curl_is_connected(struct connectdata *conn, } static void Curl_setNoDelay(struct connectdata *conn, - curl_socket_t sockfd, - int ip) + curl_socket_t sockfd) { #ifdef TCP_NODELAY struct SessionHandle *data= conn->data; @@ -488,7 +487,7 @@ static void Curl_setNoDelay(struct connectdata *conn, infof(data, "Could not set TCP_NODELAY: %s\n", Curl_strerror(conn, Curl_ourerrno())); else - infof(data,"TCP_NODELAY set for IPv%d\n", ip); + infof(data,"TCP_NODELAY set\n"); #else (void)conn; (void)sockfd; @@ -575,7 +574,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ continue; else if(data->tcp_nodelay) - Curl_setNoDelay(conn, sockfd, 6); + Curl_setNoDelay(conn, sockfd); #else /* * Connecting with old style IPv4-only support @@ -596,7 +595,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ } else if(data->tcp_nodelay) - Curl_setNoDelay(conn, sockfd, 4); + Curl_setNoDelay(conn, sockfd); /* nasty address work before connect can be made */ memset((char *) &serv_addr, '\0', sizeof(serv_addr)); -- cgit v1.2.1 From 43137cf5950e56bb169550d750e23d6e1e35f1f4 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 26 Mar 2004 07:10:15 +0000 Subject: check for netinet/tcp.h precense before actually including it --- lib/connect.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index b5c90f589..6f45e60d3 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -31,6 +31,8 @@ #endif #ifdef HAVE_SYS_SOCKET_H #include +#endif +#ifdef HAVE_NETINET_TCP_H #include /* for TCP_NODELAY */ #endif #include -- cgit v1.2.1 From ed22afe5fbf4b68a7c7e82fb3b3f75d533963d52 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 27 Mar 2004 11:15:50 +0000 Subject: Tor fixed a left-over from the ip argument to setnodelay --- lib/connect.c | 1 - 1 file changed, 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 6f45e60d3..77bcb56d1 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -493,7 +493,6 @@ static void Curl_setNoDelay(struct connectdata *conn, #else (void)conn; (void)sockfd; - (void)ip; #endif } -- cgit v1.2.1 From d85c21994f849c8ef98152023435622f42b4dc95 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 29 Mar 2004 06:22:57 +0000 Subject: netinet/tcp.h may require netinet/in.h to be include before --- lib/connect.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 77bcb56d1..78338de65 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -32,10 +32,15 @@ #ifdef HAVE_SYS_SOCKET_H #include #endif +#ifdef HAVE_NETINET_IN_H +#include /* may need it */ +#endif #ifdef HAVE_NETINET_TCP_H #include /* for TCP_NODELAY */ #endif +#ifdef HAVE_SYS_IOCTL_H #include +#endif #ifdef HAVE_UNISTD_H #include #endif -- cgit v1.2.1 From d5b8971ff360e596cfbefbc5964f2a3c2e6415ec Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 30 Mar 2004 13:05:45 +0000 Subject: typecast setsockopt()'s 4th argument to void * to make compilers complain less --- lib/connect.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 78338de65..0d42ca14d 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -490,7 +490,8 @@ static void Curl_setNoDelay(struct connectdata *conn, #ifdef TCP_NODELAY struct SessionHandle *data= conn->data; socklen_t onoff = (socklen_t) data->tcp_nodelay; - if(setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &onoff, sizeof(onoff)) < 0) + if(setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (void *)&onoff, + sizeof(onoff)) < 0) infof(data, "Could not set TCP_NODELAY: %s\n", Curl_strerror(conn, Curl_ourerrno())); else -- cgit v1.2.1 From 40d9855df2e547e182d4c4798c7b75967b9643eb Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 31 Mar 2004 10:34:53 +0000 Subject: =?UTF-8?q?Andr=E9s=20Garc=EDa=20fixed=20a=20warning=20in=20the=20?= =?UTF-8?q?ioctlsocket()=20usage.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 0d42ca14d..b58a8be5d 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -147,7 +147,7 @@ int Curl_nonblock(curl_socket_t sockfd, /* operate on this */ #ifdef HAVE_IOCTLSOCKET /* Windows? */ - int flags; + unsigned long flags; flags = nonblock; return ioctlsocket(sockfd, FIONBIO, &flags); #define SETBLOCK 3 -- cgit v1.2.1 From 4e3aa250c4ab02a6daaebba3282faf34c89f9ba9 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 13 Apr 2004 07:16:26 +0000 Subject: Moved the 'tcp_nodelay' member to the proper 'UserDefined' struct within the sessionhandle to make the duphandle() function work as supposed. Also tried to start document functions the doxygen way (in the headers of the functions). Can't make it work though... --- lib/connect.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index b58a8be5d..8bb4e2c43 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -489,7 +489,7 @@ static void Curl_setNoDelay(struct connectdata *conn, { #ifdef TCP_NODELAY struct SessionHandle *data= conn->data; - socklen_t onoff = (socklen_t) data->tcp_nodelay; + socklen_t onoff = (socklen_t) data->set.tcp_nodelay; if(setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (void *)&onoff, sizeof(onoff)) < 0) infof(data, "Could not set TCP_NODELAY: %s\n", @@ -580,7 +580,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ if (sockfd == CURL_SOCKET_BAD) continue; - else if(data->tcp_nodelay) + else if(data->set.tcp_nodelay) Curl_setNoDelay(conn, sockfd); #else /* @@ -601,7 +601,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ return CURLE_COULDNT_CONNECT; /* big time error */ } - else if(data->tcp_nodelay) + else if(data->set.tcp_nodelay) Curl_setNoDelay(conn, sockfd); /* nasty address work before connect can be made */ -- cgit v1.2.1 From 78ebe3fa5ab9c098d2808d74e8e83aa738a241f0 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 17 Apr 2004 11:33:47 +0000 Subject: Gisle made a failed connect output the reason for it --- lib/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 8bb4e2c43..24663289d 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -696,7 +696,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ if (sockfd == CURL_SOCKET_BAD) { /* no good connect was made */ *sockconn = -1; - failf(data, "Connect failed"); + failf(data, "Connect failed; %s", Curl_strerror(conn,Curl_ourerrno())); return CURLE_COULDNT_CONNECT; } -- cgit v1.2.1 From d02587750ccea0c5cb2e3e15357279c1f42a496b Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 26 Apr 2004 07:11:06 +0000 Subject: added function headers and comments --- lib/connect.c | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 24663289d..088ca3034 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -104,6 +104,10 @@ static bool verifyconnect(curl_socket_t sockfd); +/* + * Curl_ourerrno() returns the errno (or equivalent) on this platform to + * hide platform specific for the function that calls this. + */ int Curl_ourerrno(void) { #ifdef WIN32 @@ -113,13 +117,11 @@ int Curl_ourerrno(void) #endif } -/************************************************************************* - * Curl_nonblock - * - * Description: - * Set the socket to either blocking or non-blocking mode. +/* + * Curl_nonblock() set the given socket to either blocking or non-blocking + * mode based on the 'nonblock' boolean argument. This function is highly + * portable. */ - int Curl_nonblock(curl_socket_t sockfd, /* operate on this */ int nonblock /* TRUE or FALSE */) { @@ -177,12 +179,19 @@ int Curl_nonblock(curl_socket_t sockfd, /* operate on this */ } /* - * waitconnect() returns: + * waitconnect() waits for a TCP connect on the given socket for the specified + * number if milliseconds. It returns: * 0 fine connect * -1 select() error * 1 select() timeout - * 2 select() returned with an error condition + * 2 select() returned with an error condition fd_set */ + +#define WAITCONN_CONNECTED 0 +#define WAITCONN_SELECT_ERROR -1 +#define WAITCONN_TIMEOUT 1 +#define WAITCONN_FDSET_ERROR 2 + static int waitconnect(curl_socket_t sockfd, /* socket */ long timeout_msec) @@ -213,18 +222,18 @@ int waitconnect(curl_socket_t sockfd, /* socket */ rc = select(sockfd+1, NULL, &fd, &errfd, &interval); if(-1 == rc) /* error, no connect here, try next */ - return -1; + return WAITCONN_SELECT_ERROR; else if(0 == rc) /* timeout, no connect today */ - return 1; + return WAITCONN_TIMEOUT; if(FD_ISSET(sockfd, &errfd)) /* error condition caught */ - return 2; + return WAITCONN_FDSET_ERROR; /* we have a connect! */ - return 0; + return WAITCONN_CONNECTED; } static CURLcode bindlocal(struct connectdata *conn, -- cgit v1.2.1 From 245e3122df4ec12fee41552a909be75714a268a2 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 26 Apr 2004 14:18:00 +0000 Subject: Made defines instead of plain numbers for the Curl_resolv() return code to make the code easier to read --- lib/connect.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 088ca3034..e55464cdf 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -263,7 +263,7 @@ static CURLcode bindlocal(struct connectdata *conn, * We now have the numerical IPv4-style x.y.z.w in the 'myhost' buffer */ rc = Curl_resolv(conn, myhost, 0, &h); - if(rc == 1) + if(rc == CURLRESOLV_PENDING) (void)Curl_wait_for_resolv(conn, &h); if(h) @@ -276,7 +276,7 @@ static CURLcode bindlocal(struct connectdata *conn, * or IP number */ rc = Curl_resolv(conn, data->set.device, 0, &h); - if(rc == 1) + if(rc == CURLRESOLV_PENDING) (void)Curl_wait_for_resolv(conn, &h); if(h) -- cgit v1.2.1 From 4b9f8e766d0c4d989b0188a6dfd3c667e49a93a9 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 27 Apr 2004 13:56:23 +0000 Subject: Made host name and proxy name get stored in a 'struct hostname' and set all things up to work with encoded host names internally, as well as keeping 'display names' to show in debug messages. IDN resolves work for me now using ipv6, ipv4 and ares resolving. Even cookies on IDN sites seem to do right. --- lib/connect.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index e55464cdf..c7dee3ce2 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -479,7 +479,7 @@ CURLcode Curl_is_connected(struct connectdata *conn, else if(1 != rc) { int error = Curl_ourerrno(); failf(data, "Failed connect to %s:%d; %s", - conn->hostname, conn->port, Curl_strerror(conn,error)); + conn->host.name, conn->port, Curl_strerror(conn,error)); return CURLE_COULDNT_CONNECT; } /* @@ -576,7 +576,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ } } - hostname = data->change.proxy?conn->proxyhost:conn->hostname; + hostname = data->change.proxy?conn->proxy.name:conn->host.name; infof(data, "About to connect() to %s port %d\n", hostname, port); -- cgit v1.2.1 From bbafb2eb27954c34967f91c705e74cc0c186970d Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 11 May 2004 11:30:23 +0000 Subject: curl_global_init_mem() allows the memory functions to be replaced. memory.h is included everywhere for this. --- lib/connect.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index c7dee3ce2..0eec75a48 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -96,11 +96,10 @@ #include "if2ip.h" #include "strerror.h" #include "connect.h" +#include "memory.h" /* The last #include file should be: */ -#ifdef CURLDEBUG #include "memdebug.h" -#endif static bool verifyconnect(curl_socket_t sockfd); -- cgit v1.2.1 From 05d8e56ffdf271c13033a7fa96023afb0685669b Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 13 May 2004 10:40:17 +0000 Subject: Gisle Vamem reintroduced the verifyconnect() call on windows as well, and we now use it to provide more info back on connect failures. --- lib/connect.c | 57 ++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 15 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 0eec75a48..cf54b1486 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -101,7 +101,7 @@ /* The last #include file should be: */ #include "memdebug.h" -static bool verifyconnect(curl_socket_t sockfd); +static bool verifyconnect(curl_socket_t sockfd, int *error); /* * Curl_ourerrno() returns the errno (or equivalent) on this platform to @@ -203,7 +203,7 @@ int waitconnect(curl_socket_t sockfd, /* socket */ /* Call this function once now, and ignore the results. We do this to "clear" the error state on the socket so that we can later read it reliably. This is reported necessary on the MPE/iX operating system. */ - verifyconnect(sockfd); + verifyconnect(sockfd, NULL); #endif /* now select() until we get connect or timeout */ @@ -397,25 +397,50 @@ static CURLcode bindlocal(struct connectdata *conn, /* * verifyconnect() returns TRUE if the connect really has happened. */ -static bool verifyconnect(curl_socket_t sockfd) +static bool verifyconnect(curl_socket_t sockfd, int *error) { -#if defined(SO_ERROR) && !defined(WIN32) + bool rc = TRUE; +#ifdef SO_ERROR int err = 0; socklen_t errSize = sizeof(err); + +#ifdef WIN32 + /* + * In October 2003 we effectively nullified this function on Windows due to + * problems with it using all CPU in multi-threaded cases. + * + * In May 2004, we bring it back to offer more info back on connect failures. + * Gisle Vanem could reproduce the former problems with this function, but + * could avoid them by adding this SleepEx() call below: + * + * "I don't have Rational Quantify, but the hint from his post was + * ntdll::NtRemoveIoCompletion(). So I'd assume the SleepEx (or maybe + * just Sleep(0) would be enough?) would release whatever + * mutex/critical-section the ntdll call is waiting on. + * + * Someone got to verify this on Win-NT 4.0, 2000." + */ + SleepEx(0, FALSE); +#endif + if( -1 == getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *)&err, &errSize)) err = Curl_ourerrno(); if ((0 == err) || (EISCONN == err)) /* we are connected, awesome! */ - return TRUE; - - /* This wasn't a successful connect */ - return FALSE; + rc = TRUE; + else + /* This wasn't a successful connect */ + rc = FALSE; + if (error) + *error = err; #else (void)sockfd; - return TRUE; + if (error) + *error = Curl_ourerrno(); #endif + return rc; } /* @@ -466,7 +491,7 @@ CURLcode Curl_is_connected(struct connectdata *conn, rc = waitconnect(sockfd, 0); if(0 == rc) { - if (verifyconnect(sockfd)) { + if (verifyconnect(sockfd,NULL)) { /* we are connected, awesome! */ *connected = TRUE; return CURLE_OK; @@ -524,7 +549,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ bool *connected) /* really connected? */ { struct SessionHandle *data = conn->data; - int rc; + int rc, error; curl_socket_t sockfd= CURL_SOCKET_BAD; int aliasindex=0; char *hostname; @@ -642,7 +667,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ #endif if(-1 == rc) { - int error=Curl_ourerrno(); + error = Curl_ourerrno(); switch (error) { case EINPROGRESS: @@ -679,7 +704,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ } if(0 == rc) { - if (verifyconnect(sockfd)) { + if (verifyconnect(sockfd,NULL)) { /* we are connected, awesome! */ *connected = TRUE; /* this is a true connect */ break; @@ -687,10 +712,12 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ /* nope, not connected for real */ rc = -1; } + else + verifyconnect(sockfd,&error); /* get non-blocking error */ /* connect failed or timed out */ sclose(sockfd); - sockfd = -1; + sockfd = CURL_SOCKET_BAD; /* get a new timeout for next attempt */ after = Curl_tvnow(); @@ -704,7 +731,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ if (sockfd == CURL_SOCKET_BAD) { /* no good connect was made */ *sockconn = -1; - failf(data, "Connect failed; %s", Curl_strerror(conn,Curl_ourerrno())); + failf(data, "Connect failed; %s", Curl_strerror(conn,error)); return CURLE_COULDNT_CONNECT; } -- cgit v1.2.1 From 1ab4a2f870ed4f9e62322f719336a86667107b52 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 8 Jun 2004 15:05:20 +0000 Subject: delete trailing whitespace --- lib/connect.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index cf54b1486..26bf28329 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -1,8 +1,8 @@ /*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * * Copyright (C) 1998 - 2004, Daniel Stenberg, , et al. @@ -10,7 +10,7 @@ * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://curl.haxx.se/docs/copyright.html. - * + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is * furnished to do so, under the terms of the COPYING file. @@ -222,7 +222,7 @@ int waitconnect(curl_socket_t sockfd, /* socket */ if(-1 == rc) /* error, no connect here, try next */ return WAITCONN_SELECT_ERROR; - + else if(0 == rc) /* timeout, no connect today */ return WAITCONN_TIMEOUT; @@ -255,7 +255,7 @@ static CURLcode bindlocal(struct connectdata *conn, /* First check if the given name is an IP address */ in=inet_addr(data->set.device); - + if((in == CURL_INADDR_NONE) && Curl_if2ip(data->set.device, myhost, sizeof(myhost))) { /* @@ -336,7 +336,7 @@ static CURLcode bindlocal(struct connectdata *conn, struct sockaddr_in6 add; bindworked = TRUE; - + size = sizeof(add); if(getsockname(sockfd, (struct sockaddr *) &add, (socklen_t *)&size)<0) { @@ -353,13 +353,13 @@ static CURLcode bindlocal(struct connectdata *conn, sa.sin_family = AF_INET; sa.sin_addr.s_addr = in; sa.sin_port = 0; /* get any port */ - + if( bind(sockfd, (struct sockaddr *)&sa, sizeof(sa)) >= 0) { /* we succeeded to bind */ struct sockaddr_in add; - + bindworked = TRUE; - + size = sizeof(add); if(getsockname(sockfd, (struct sockaddr *) &add, (socklen_t *)&size)<0) { @@ -373,7 +373,7 @@ static CURLcode bindlocal(struct connectdata *conn, failf(data, "%s", Curl_strerror(conn, Curl_ourerrno())); return CURLE_HTTP_PORT_FAILED; } - + } /* end of if h */ else { failf(data,"could't find my own IP address (%s)", myhost); @@ -467,7 +467,7 @@ CURLcode Curl_is_connected(struct connectdata *conn, if(data->set.timeout && data->set.connecttimeout) { if (data->set.timeout < data->set.connecttimeout) has_passed -= data->set.timeout*1000; - else + else has_passed -= data->set.connecttimeout*1000; } else if(data->set.timeout) @@ -559,7 +559,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ #ifdef ENABLE_IPV6 struct addrinfo *ai; -#endif +#endif /************************************************************* * Figure out what maximum time we have left @@ -582,7 +582,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ if(data->set.timeout && data->set.connecttimeout) { if (data->set.timeout < data->set.connecttimeout) timeout_ms = data->set.timeout*1000; - else + else timeout_ms = data->set.connecttimeout*1000; } else if(data->set.timeout) @@ -683,7 +683,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ if(data->state.used_interface == Curl_if_multi) /* don't hang when doing multi */ timeout_ms = 0; - + rc = waitconnect(sockfd, timeout_ms); break; default: @@ -702,7 +702,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ rc = 0; break; } - + if(0 == rc) { if (verifyconnect(sockfd,NULL)) { /* we are connected, awesome! */ -- cgit v1.2.1 From 9f341f9ce5ff2cc85a4cbdd38cd4b5c68b02504d Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 10 Jun 2004 11:06:21 +0000 Subject: Gisle Vanem's improved verbose output and timeout handling when connecting to a host name that resolves to multiple IP addresses. --- lib/connect.c | 113 +++++++++++++++++++++++++++++++--------------------------- 1 file changed, 61 insertions(+), 52 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 26bf28329..a2c5ad612 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -490,8 +490,8 @@ CURLcode Curl_is_connected(struct connectdata *conn, /* check for connect without timeout as we want to return immediately */ rc = waitconnect(sockfd, 0); - if(0 == rc) { - if (verifyconnect(sockfd,NULL)) { + if(WAITCONN_CONNECTED == rc) { + if (verifyconnect(sockfd, NULL)) { /* we are connected, awesome! */ *connected = TRUE; return CURLE_OK; @@ -500,7 +500,7 @@ CURLcode Curl_is_connected(struct connectdata *conn, failf(data, "Connection failed"); return CURLE_COULDNT_CONNECT; } - else if(1 != rc) { + else if(WAITCONN_TIMEOUT != rc) { int error = Curl_ourerrno(); failf(data, "Failed connect to %s:%d; %s", conn->host.name, conn->port, Curl_strerror(conn,error)); @@ -549,22 +549,22 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ bool *connected) /* really connected? */ { struct SessionHandle *data = conn->data; + curl_socket_t sockfd = CURL_SOCKET_BAD; int rc, error; - curl_socket_t sockfd= CURL_SOCKET_BAD; - int aliasindex=0; - char *hostname; + int aliasindex; + int num_addr; + const char *hostname; + bool conected; + Curl_ipconnect *curr_addr; struct timeval after; struct timeval before = Curl_tvnow(); -#ifdef ENABLE_IPV6 - struct addrinfo *ai; -#endif - /************************************************************* * Figure out what maximum time we have left *************************************************************/ - long timeout_ms=300000; /* milliseconds, default to five minutes */ + long timeout_ms=300000; /* milliseconds, default to five minutes total */ + long timeout_per_addr; *connected = FALSE; /* default to not connected */ @@ -600,31 +600,38 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ } } + /* Max time for each address */ + num_addr = Curl_num_addresses(remotehost->addr); + timeout_per_addr = timeout_ms / num_addr; + hostname = data->change.proxy?conn->proxy.name:conn->host.name; + infof(data, "About to connect() to %s port %d\n", hostname, port); + /* Below is the loop that attempts to connect to all IP-addresses we + * know for the given host. One by one until one IP succeedes. + */ #ifdef ENABLE_IPV6 /* * Connecting with a getaddrinfo chain */ - for (ai = remotehost->addr; ai; ai = ai->ai_next, aliasindex++) { - sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); - if (sockfd == CURL_SOCKET_BAD) + for (curr_addr = remotehost->addr, aliasindex=0; curr_addr; + curr_addr = curr_addr->ai_next, aliasindex++) { + sockfd = socket(curr_addr->ai_family, curr_addr->ai_socktype, + curr_addr->ai_protocol); + if (sockfd == CURL_SOCKET_BAD) { + timeout_per_addr += timeout_per_addr / (num_addr - aliasindex); continue; + } - else if(data->set.tcp_nodelay) - Curl_setNoDelay(conn, sockfd); #else /* * Connecting with old style IPv4-only support */ - - /* This is the loop that attempts to connect to all IP-addresses we - know for the given host. One by one. */ - for(rc=-1, aliasindex=0; - rc && (struct in_addr *)remotehost->addr->h_addr_list[aliasindex]; - aliasindex++) { + curr_addr = (Curl_ipconnect*)remotehost->addr->h_addr_list[0]; + for(aliasindex=0; curr_addr; + curr_addr=(Curl_ipconnect*)remotehost->addr->h_addr_list[++aliasindex]) { struct sockaddr_in serv_addr; /* create an IPv4 TCP socket */ @@ -634,18 +641,24 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ return CURLE_COULDNT_CONNECT; /* big time error */ } - else if(data->set.tcp_nodelay) - Curl_setNoDelay(conn, sockfd); - /* nasty address work before connect can be made */ memset((char *) &serv_addr, '\0', sizeof(serv_addr)); - memcpy((char *)&(serv_addr.sin_addr), - (struct in_addr *)remotehost->addr->h_addr_list[aliasindex], + memcpy((char *)&(serv_addr.sin_addr), curr_addr, sizeof(struct in_addr)); serv_addr.sin_family = remotehost->addr->h_addrtype; serv_addr.sin_port = htons((unsigned short)port); #endif + { + char addr_buf[256] = ""; + + Curl_printable_address(curr_addr, addr_buf, sizeof(addr_buf)); + infof(data, " Trying %s... ", addr_buf); + } + + if(data->set.tcp_nodelay) + Curl_setNoDelay(conn, sockfd); + if(conn->data->set.device) { /* user selected to bind the outgoing socket to a specified "device" before doing connect */ @@ -661,7 +674,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ a defined macro on some platforms and some compilers don't like to mix #ifdefs with macro usage! (AmigaOS is one such platform) */ #ifdef ENABLE_IPV6 - rc = connect(sockfd, ai->ai_addr, ai->ai_addrlen); + rc = connect(sockfd, curr_addr->ai_addr, curr_addr->ai_addrlen); #else rc = connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)); #endif @@ -682,9 +695,9 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ /* asynchronous connect, wait for connect or timeout */ if(data->state.used_interface == Curl_if_multi) /* don't hang when doing multi */ - timeout_ms = 0; + timeout_per_addr = timeout_ms = 0; - rc = waitconnect(sockfd, timeout_ms); + rc = waitconnect(sockfd, timeout_per_addr); break; default: /* unknown error, fallthrough and try another address! */ @@ -694,26 +707,27 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ } } - /* The '1 == rc' comes from the waitconnect(), and not from connect(). - We can be sure of this since connect() cannot return 1. */ - if((1 == rc) && (data->state.used_interface == Curl_if_multi)) { + /* The 'WAITCONN_TIMEOUT == rc' comes from the waitconnect(), and not from + connect(). We can be sure of this since connect() cannot return 1. */ + if((WAITCONN_TIMEOUT == rc) && + (data->state.used_interface == Curl_if_multi)) { /* Timeout when running the multi interface, we return here with a CURLE_OK return code. */ rc = 0; break; } - if(0 == rc) { - if (verifyconnect(sockfd,NULL)) { - /* we are connected, awesome! */ - *connected = TRUE; /* this is a true connect */ - break; - } - /* nope, not connected for real */ - rc = -1; + conected = verifyconnect(sockfd, &error); + + if(!rc && conected) { + /* we are connected, awesome! */ + *connected = TRUE; /* this is a true connect */ + break; } + if(WAITCONN_TIMEOUT == rc) + infof(data, "Timeout\n"); else - verifyconnect(sockfd,&error); /* get non-blocking error */ + infof(data, "%s\n", Curl_strerror(conn, error)); /* connect failed or timed out */ sclose(sockfd); @@ -727,24 +741,19 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ return CURLE_OPERATION_TIMEOUTED; } before = after; - } + } /* end of connect-to-each-address loop */ + if (sockfd == CURL_SOCKET_BAD) { /* no good connect was made */ - *sockconn = -1; - failf(data, "Connect failed; %s", Curl_strerror(conn,error)); + *sockconn = CURL_SOCKET_BAD; return CURLE_COULDNT_CONNECT; } /* leave the socket in non-blocking mode */ /* store the address we use */ - if(addr) { -#ifdef ENABLE_IPV6 - *addr = ai; -#else - *addr = (struct in_addr *)remotehost->addr->h_addr_list[aliasindex]; -#endif - } + if(addr) + *addr = curr_addr; /* allow NULL-pointers to get passed in */ if(sockconn) -- cgit v1.2.1 From d73425061ab5154b1d1218bc1f6f5c3bfea26b5c Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 22 Jun 2004 15:23:01 +0000 Subject: Moved the "About to connect() to" text to the place where the host name is actually known, as before this text lied when used in i.e FTP. --- lib/connect.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index a2c5ad612..9c2d8a235 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -507,11 +507,8 @@ CURLcode Curl_is_connected(struct connectdata *conn, return CURLE_COULDNT_CONNECT; } /* - * If the connection phase is "done" here, we should attempt to connect - * to the "next address" in the Curl_hostaddr structure that we resolved - * before. But we don't have that struct around anymore and we can't just - * keep a pointer since the cache might in fact have gotten pruned by the - * time we want to read this... Alas, we don't do this yet. + * If the connection failed here, we should attempt to connect to the "next + * address" for the given host. */ return CURLE_OK; @@ -604,11 +601,6 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ num_addr = Curl_num_addresses(remotehost->addr); timeout_per_addr = timeout_ms / num_addr; - hostname = data->change.proxy?conn->proxy.name:conn->host.name; - - infof(data, "About to connect() to %s port %d\n", - hostname, port); - /* Below is the loop that attempts to connect to all IP-addresses we * know for the given host. One by one until one IP succeedes. */ -- cgit v1.2.1 From 2494701347f73e70d803bd20ebe5b532dea77290 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 22 Jun 2004 21:25:53 +0000 Subject: the hostname variable wasn't assigned and we no longer use it --- lib/connect.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 9c2d8a235..ed5bc80ac 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -550,8 +550,8 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ int rc, error; int aliasindex; int num_addr; - const char *hostname; bool conected; + char addr_buf[256]; Curl_ipconnect *curr_addr; struct timeval after; @@ -641,12 +641,9 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ serv_addr.sin_port = htons((unsigned short)port); #endif - { - char addr_buf[256] = ""; - Curl_printable_address(curr_addr, addr_buf, sizeof(addr_buf)); - infof(data, " Trying %s... ", addr_buf); - } + Curl_printable_address(curr_addr, addr_buf, sizeof(addr_buf)); + infof(data, " Trying %s... ", addr_buf); if(data->set.tcp_nodelay) Curl_setNoDelay(conn, sockfd); @@ -693,8 +690,8 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ break; default: /* unknown error, fallthrough and try another address! */ - failf(data, "Failed to connect to %s IP number %d: %s", - hostname, aliasindex+1, Curl_strerror(conn,error)); + failf(data, "Failed to connect to %s (IP number %d): %s", + addr_buf, aliasindex+1, Curl_strerror(conn,error)); break; } } -- cgit v1.2.1 From 5f1eefd03f19814ac6f71adb35b3ad0e5e08f919 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 23 Jun 2004 06:14:23 +0000 Subject: prevent a warning --- lib/connect.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index ed5bc80ac..6d953cad3 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -608,6 +608,8 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ /* * Connecting with a getaddrinfo chain */ + (void)port; /* the port number is already included in the getaddrinfo + struct */ for (curr_addr = remotehost->addr, aliasindex=0; curr_addr; curr_addr = curr_addr->ai_next, aliasindex++) { sockfd = socket(curr_addr->ai_family, curr_addr->ai_socktype, -- cgit v1.2.1 From 818aed35e2f7c1602333c0b2ecc0444272966cc7 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 23 Jun 2004 09:08:03 +0000 Subject: static functions are better not Curl_ prefixed to make their static status more obvious --- lib/connect.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 6d953cad3..5da4ac996 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -514,8 +514,8 @@ CURLcode Curl_is_connected(struct connectdata *conn, return CURLE_OK; } -static void Curl_setNoDelay(struct connectdata *conn, - curl_socket_t sockfd) +static void tcpnodelay(struct connectdata *conn, + curl_socket_t sockfd) { #ifdef TCP_NODELAY struct SessionHandle *data= conn->data; @@ -648,7 +648,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ infof(data, " Trying %s... ", addr_buf); if(data->set.tcp_nodelay) - Curl_setNoDelay(conn, sockfd); + tcpnodelay(conn, sockfd); if(conn->data->set.device) { /* user selected to bind the outgoing socket to a specified "device" -- cgit v1.2.1 From c39858aac0584716282dcb097ce9d972b43dbcb2 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 24 Jun 2004 07:43:48 +0000 Subject: Source cleanups. The major one being that we now _always_ use a Curl_addrinfo linked list for name resolved data, even on hosts/systems with only IPv4 stacks as this simplifies a lot of code. --- lib/connect.c | 72 +++++++++-------------------------------------------------- 1 file changed, 10 insertions(+), 62 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 5da4ac996..cd024edde 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -330,7 +330,6 @@ static CURLcode bindlocal(struct connectdata *conn, Curl_resolv_unlock(data, h); /* we don't need it anymore after this function has returned */ -#ifdef ENABLE_IPV6 if( bind(sockfd, addr->ai_addr, addr->ai_addrlen) >= 0) { /* we succeeded to bind */ struct sockaddr_in6 add; @@ -344,31 +343,7 @@ static CURLcode bindlocal(struct connectdata *conn, return CURLE_HTTP_PORT_FAILED; } } -#else - { - struct sockaddr_in sa; - - memset((char *)&sa, 0, sizeof(sa)); - memcpy((char *)&sa.sin_addr, addr->h_addr, addr->h_length); - sa.sin_family = AF_INET; - sa.sin_addr.s_addr = in; - sa.sin_port = 0; /* get any port */ - - if( bind(sockfd, (struct sockaddr *)&sa, sizeof(sa)) >= 0) { - /* we succeeded to bind */ - struct sockaddr_in add; - - bindworked = TRUE; - - size = sizeof(add); - if(getsockname(sockfd, (struct sockaddr *) &add, - (socklen_t *)&size)<0) { - failf(data, "getsockname() failed"); - return CURLE_HTTP_PORT_FAILED; - } - } - } -#endif + if(!bindworked) { failf(data, "%s", Curl_strerror(conn, Curl_ourerrno())); return CURLE_HTTP_PORT_FAILED; @@ -540,9 +515,8 @@ static void tcpnodelay(struct connectdata *conn, CURLcode Curl_connecthost(struct connectdata *conn, /* context */ struct Curl_dns_entry *remotehost, /* use this one */ - int port, /* connect to this */ curl_socket_t *sockconn, /* the connected socket */ - Curl_ipconnect **addr, /* the one we used */ + Curl_addrinfo **addr, /* the one we used */ bool *connected) /* really connected? */ { struct SessionHandle *data = conn->data; @@ -552,8 +526,9 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ int num_addr; bool conected; char addr_buf[256]; + Curl_addrinfo *ai; + Curl_addrinfo *curr_addr; - Curl_ipconnect *curr_addr; struct timeval after; struct timeval before = Curl_tvnow(); @@ -601,17 +576,18 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ num_addr = Curl_num_addresses(remotehost->addr); timeout_per_addr = timeout_ms / num_addr; + ai = remotehost->addr; + /* Below is the loop that attempts to connect to all IP-addresses we * know for the given host. One by one until one IP succeedes. */ -#ifdef ENABLE_IPV6 + /* * Connecting with a getaddrinfo chain */ - (void)port; /* the port number is already included in the getaddrinfo - struct */ - for (curr_addr = remotehost->addr, aliasindex=0; curr_addr; + for (curr_addr = ai, aliasindex=0; curr_addr; curr_addr = curr_addr->ai_next, aliasindex++) { + sockfd = socket(curr_addr->ai_family, curr_addr->ai_socktype, curr_addr->ai_protocol); if (sockfd == CURL_SOCKET_BAD) { @@ -619,31 +595,6 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ continue; } -#else - /* - * Connecting with old style IPv4-only support - */ - curr_addr = (Curl_ipconnect*)remotehost->addr->h_addr_list[0]; - for(aliasindex=0; curr_addr; - curr_addr=(Curl_ipconnect*)remotehost->addr->h_addr_list[++aliasindex]) { - struct sockaddr_in serv_addr; - - /* create an IPv4 TCP socket */ - sockfd = socket(AF_INET, SOCK_STREAM, 0); - if(CURL_SOCKET_BAD == sockfd) { - failf(data, "couldn't create socket"); - return CURLE_COULDNT_CONNECT; /* big time error */ - } - - /* nasty address work before connect can be made */ - memset((char *) &serv_addr, '\0', sizeof(serv_addr)); - memcpy((char *)&(serv_addr.sin_addr), curr_addr, - sizeof(struct in_addr)); - serv_addr.sin_family = remotehost->addr->h_addrtype; - serv_addr.sin_port = htons((unsigned short)port); -#endif - - Curl_printable_address(curr_addr, addr_buf, sizeof(addr_buf)); infof(data, " Trying %s... ", addr_buf); @@ -664,11 +615,8 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ /* do not use #ifdef within the function arguments below, as connect() is a defined macro on some platforms and some compilers don't like to mix #ifdefs with macro usage! (AmigaOS is one such platform) */ -#ifdef ENABLE_IPV6 + rc = connect(sockfd, curr_addr->ai_addr, curr_addr->ai_addrlen); -#else - rc = connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)); -#endif if(-1 == rc) { error = Curl_ourerrno(); -- cgit v1.2.1 From 8d0a823124e428e002fed7bc76d3fe2c33ffc023 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 24 Jun 2004 09:13:50 +0000 Subject: only use sockaddr_in6 on ipv6-enabled hosts --- lib/connect.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index cd024edde..58506751b 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -332,7 +332,11 @@ static CURLcode bindlocal(struct connectdata *conn, if( bind(sockfd, addr->ai_addr, addr->ai_addrlen) >= 0) { /* we succeeded to bind */ +#ifdef ENABLE_IPV6 struct sockaddr_in6 add; +#else + struct sockaddr_in add; +#endif bindworked = TRUE; -- cgit v1.2.1 From 6ed5feda2b3fd15c720e04c040e470ecc3cd075c Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 29 Jun 2004 11:20:07 +0000 Subject: First attempt at making the multi interface work when connecting to a host that resolves to multiple IP addresses. --- lib/connect.c | 287 +++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 172 insertions(+), 115 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 58506751b..a30614334 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -101,8 +101,16 @@ /* The last #include file should be: */ #include "memdebug.h" +#define DEFAULT_CONNECT_TIMEOUT 300000 /* milliseconds == five minutes */ + static bool verifyconnect(curl_socket_t sockfd, int *error); +static curl_socket_t +singleipconnect(struct connectdata *conn, + Curl_addrinfo *ai, /* start connecting to this */ + long timeout_ms, + bool *connected); + /* * Curl_ourerrno() returns the errno (or equivalent) on this platform to * hide platform specific for the function that calls this. @@ -422,43 +430,74 @@ static bool verifyconnect(curl_socket_t sockfd, int *error) return rc; } +/* Used within the multi interface. Try next IP address, return TRUE if no + more address exists */ +static bool trynextip(struct connectdata *conn, + int sockindex, + long timeout, + bool *connected) +{ + curl_socket_t sockfd; + Curl_addrinfo *ai; + + if(sockindex != FIRSTSOCKET) + return TRUE; /* no next */ + + ai = conn->ip_addr->ai_next; + + while (ai) { + sockfd = singleipconnect(conn, ai, timeout, connected); + if(sockfd != CURL_SOCKET_BAD) { + /* store the new socket descriptor */ + conn->sock[sockindex] = sockfd; + return FALSE; + } + ai = ai->ai_next; + } + return TRUE; +} + /* * Curl_is_connected() is used from the multi interface to check if the * firstsocket has connected. */ CURLcode Curl_is_connected(struct connectdata *conn, - curl_socket_t sockfd, + int sockindex, bool *connected) { int rc; struct SessionHandle *data = conn->data; + CURLcode code = CURLE_OK; + curl_socket_t sockfd = conn->sock[sockindex]; + long allow = DEFAULT_CONNECT_TIMEOUT; + long has_passed; - *connected = FALSE; /* a very negative world view is best */ + curlassert(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET); - if(data->set.timeout || data->set.connecttimeout) { - /* there is a timeout set */ + *connected = FALSE; /* a very negative world view is best */ - /* Evaluate in milliseconds how much time that has passed */ - long has_passed = Curl_tvdiff(Curl_tvnow(), data->progress.start); + /* Evaluate in milliseconds how much time that has passed */ + has_passed = Curl_tvdiff(Curl_tvnow(), data->progress.start); - /* subtract the most strict timeout of the ones */ - if(data->set.timeout && data->set.connecttimeout) { - if (data->set.timeout < data->set.connecttimeout) - has_passed -= data->set.timeout*1000; - else - has_passed -= data->set.connecttimeout*1000; - } - else if(data->set.timeout) - has_passed -= data->set.timeout*1000; + /* subtract the most strict timeout of the ones */ + if(data->set.timeout && data->set.connecttimeout) { + if (data->set.timeout < data->set.connecttimeout) + allow = data->set.timeout*1000; else - has_passed -= data->set.connecttimeout*1000; + allow = data->set.connecttimeout*1000; + } + else if(data->set.timeout) { + allow = data->set.timeout*1000; + } + else if(data->set.connecttimeout) { + allow = data->set.connecttimeout*1000; + } - if(has_passed > 0 ) { - /* time-out, bail out, go home */ - failf(data, "Connection time-out"); - return CURLE_OPERATION_TIMEOUTED; - } + if(has_passed > allow ) { + /* time-out, bail out, go home */ + failf(data, "Connection time-out after %ld ms", has_passed); + return CURLE_OPERATION_TIMEOUTED; } if(conn->bits.tcpconnect) { /* we are connected already! */ @@ -476,21 +515,27 @@ CURLcode Curl_is_connected(struct connectdata *conn, return CURLE_OK; } /* nope, not connected for real */ - failf(data, "Connection failed"); - return CURLE_COULDNT_CONNECT; + infof(data, "Connection failed\n"); + if(trynextip(conn, sockindex, allow-has_passed, connected)) { + code = CURLE_COULDNT_CONNECT; + } } else if(WAITCONN_TIMEOUT != rc) { - int error = Curl_ourerrno(); - failf(data, "Failed connect to %s:%d; %s", - conn->host.name, conn->port, Curl_strerror(conn,error)); - return CURLE_COULDNT_CONNECT; + /* nope, not connected */ + infof(data, "Connection failed\n"); + if(trynextip(conn, sockindex, allow-has_passed, connected)) { + int error = Curl_ourerrno(); + failf(data, "Failed connect to %s:%d; %s", + conn->host.name, conn->port, Curl_strerror(conn,error)); + code = CURLE_COULDNT_CONNECT; + } } /* * If the connection failed here, we should attempt to connect to the "next * address" for the given host. */ - return CURLE_OK; + return code; } static void tcpnodelay(struct connectdata *conn, @@ -511,6 +556,95 @@ static void tcpnodelay(struct connectdata *conn, #endif } +/* singleipconnect() connects to the given IP only, and it may return without + having connected if used from the multi interface. */ +static curl_socket_t +singleipconnect(struct connectdata *conn, + Curl_addrinfo *ai, + long timeout_ms, + bool *connected) +{ + char addr_buf[128]; + int rc; + int error; + bool conected; + struct SessionHandle *data = conn->data; + curl_socket_t sockfd = socket(ai->ai_family, ai->ai_socktype, + ai->ai_protocol); + if (sockfd == CURL_SOCKET_BAD) + return CURL_SOCKET_BAD; + + *connected = FALSE; /* default is not connected */ + + Curl_printable_address(ai, addr_buf, sizeof(addr_buf)); + infof(data, " Trying %s... ", addr_buf); + + if(data->set.tcp_nodelay) + tcpnodelay(conn, sockfd); + + if(conn->data->set.device) { + /* user selected to bind the outgoing socket to a specified "device" + before doing connect */ + CURLcode res = bindlocal(conn, sockfd); + if(res) + return res; + } + + /* set socket non-blocking */ + Curl_nonblock(sockfd, TRUE); + + rc = connect(sockfd, ai->ai_addr, ai->ai_addrlen); + + if(-1 == rc) { + error = Curl_ourerrno(); + + switch (error) { + case EINPROGRESS: + case EWOULDBLOCK: +#if defined(EAGAIN) && EAGAIN != EWOULDBLOCK + /* On some platforms EAGAIN and EWOULDBLOCK are the + * same value, and on others they are different, hence + * the odd #if + */ + case EAGAIN: +#endif + rc = waitconnect(sockfd, timeout_ms); + break; + default: + /* unknown error, fallthrough and try another address! */ + failf(data, "Failed to connect to %s: %s", + addr_buf, Curl_strerror(conn,error)); + break; + } + } + + /* The 'WAITCONN_TIMEOUT == rc' comes from the waitconnect(), and not from + connect(). We can be sure of this since connect() cannot return 1. */ + if((WAITCONN_TIMEOUT == rc) && + (data->state.used_interface == Curl_if_multi)) { + /* Timeout when running the multi interface */ + return sockfd; + } + + conected = verifyconnect(sockfd, &error); + + if(!rc && conected) { + /* we are connected, awesome! */ + *connected = TRUE; /* this is a true connect */ + infof(data, "connected\n"); + return sockfd; + } + else if(WAITCONN_TIMEOUT == rc) + infof(data, "Timeout\n"); + else + infof(data, "%s\n", Curl_strerror(conn, error)); + + /* connect failed or timed out */ + sclose(sockfd); + + return CURL_SOCKET_BAD; +} + /* * TCP connect to the given host with timeout, proxy or remote doesn't matter. * There might be more than one IP address to try out. Fill in the passed @@ -525,11 +659,8 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ { struct SessionHandle *data = conn->data; curl_socket_t sockfd = CURL_SOCKET_BAD; - int rc, error; int aliasindex; int num_addr; - bool conected; - char addr_buf[256]; Curl_addrinfo *ai; Curl_addrinfo *curr_addr; @@ -539,7 +670,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ /************************************************************* * Figure out what maximum time we have left *************************************************************/ - long timeout_ms=300000; /* milliseconds, default to five minutes total */ + long timeout_ms= DEFAULT_CONNECT_TIMEOUT; long timeout_per_addr; *connected = FALSE; /* default to not connected */ @@ -583,98 +714,24 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ ai = remotehost->addr; /* Below is the loop that attempts to connect to all IP-addresses we - * know for the given host. One by one until one IP succeedes. + * know for the given host. One by one until one IP succeeds. */ + if(data->state.used_interface == Curl_if_multi) + /* don't hang when doing multi */ + timeout_per_addr = timeout_ms = 0; + /* - * Connecting with a getaddrinfo chain + * Connecting with a Curl_addrinfo chain */ for (curr_addr = ai, aliasindex=0; curr_addr; curr_addr = curr_addr->ai_next, aliasindex++) { - sockfd = socket(curr_addr->ai_family, curr_addr->ai_socktype, - curr_addr->ai_protocol); - if (sockfd == CURL_SOCKET_BAD) { - timeout_per_addr += timeout_per_addr / (num_addr - aliasindex); - continue; - } - - Curl_printable_address(curr_addr, addr_buf, sizeof(addr_buf)); - infof(data, " Trying %s... ", addr_buf); - - if(data->set.tcp_nodelay) - tcpnodelay(conn, sockfd); - - if(conn->data->set.device) { - /* user selected to bind the outgoing socket to a specified "device" - before doing connect */ - CURLcode res = bindlocal(conn, sockfd); - if(res) - return res; - } - - /* set socket non-blocking */ - Curl_nonblock(sockfd, TRUE); + /* start connecting to the IP curr_addr points to */ + sockfd = singleipconnect(conn, curr_addr, timeout_per_addr, connected); - /* do not use #ifdef within the function arguments below, as connect() is - a defined macro on some platforms and some compilers don't like to mix - #ifdefs with macro usage! (AmigaOS is one such platform) */ - - rc = connect(sockfd, curr_addr->ai_addr, curr_addr->ai_addrlen); - - if(-1 == rc) { - error = Curl_ourerrno(); - - switch (error) { - case EINPROGRESS: - case EWOULDBLOCK: -#if defined(EAGAIN) && EAGAIN != EWOULDBLOCK - /* On some platforms EAGAIN and EWOULDBLOCK are the - * same value, and on others they are different, hence - * the odd #if - */ - case EAGAIN: -#endif - /* asynchronous connect, wait for connect or timeout */ - if(data->state.used_interface == Curl_if_multi) - /* don't hang when doing multi */ - timeout_per_addr = timeout_ms = 0; - - rc = waitconnect(sockfd, timeout_per_addr); - break; - default: - /* unknown error, fallthrough and try another address! */ - failf(data, "Failed to connect to %s (IP number %d): %s", - addr_buf, aliasindex+1, Curl_strerror(conn,error)); - break; - } - } - - /* The 'WAITCONN_TIMEOUT == rc' comes from the waitconnect(), and not from - connect(). We can be sure of this since connect() cannot return 1. */ - if((WAITCONN_TIMEOUT == rc) && - (data->state.used_interface == Curl_if_multi)) { - /* Timeout when running the multi interface, we return here with a - CURLE_OK return code. */ - rc = 0; - break; - } - - conected = verifyconnect(sockfd, &error); - - if(!rc && conected) { - /* we are connected, awesome! */ - *connected = TRUE; /* this is a true connect */ + if(sockfd != CURL_SOCKET_BAD) break; - } - if(WAITCONN_TIMEOUT == rc) - infof(data, "Timeout\n"); - else - infof(data, "%s\n", Curl_strerror(conn, error)); - - /* connect failed or timed out */ - sclose(sockfd); - sockfd = CURL_SOCKET_BAD; /* get a new timeout for next attempt */ after = Curl_tvnow(); -- cgit v1.2.1 From ba40eccc903990378f91ed218ed32da60bafe5b2 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 30 Jun 2004 09:22:48 +0000 Subject: make the SSL connect use the same default connect timeout define as the generic connect uses --- lib/connect.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index a30614334..46d7d8e14 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -101,8 +101,6 @@ /* The last #include file should be: */ #include "memdebug.h" -#define DEFAULT_CONNECT_TIMEOUT 300000 /* milliseconds == five minutes */ - static bool verifyconnect(curl_socket_t sockfd, int *error); static curl_socket_t -- cgit v1.2.1 From 090b89cc76acfa0bb388a9eb425dfaa81f62b5ae Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 1 Jul 2004 08:10:21 +0000 Subject: Variable type cleanups to please the picky MIPSPro compiler. --- lib/connect.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 46d7d8e14..ce3d40cf1 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -219,7 +219,7 @@ int waitconnect(curl_socket_t sockfd, /* socket */ FD_ZERO(&errfd); FD_SET(sockfd, &errfd); - interval.tv_sec = timeout_msec/1000; + interval.tv_sec = (int)(timeout_msec/1000); timeout_msec -= interval.tv_sec*1000; interval.tv_usec = timeout_msec*1000; @@ -674,7 +674,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ *connected = FALSE; /* default to not connected */ if(data->set.timeout || data->set.connecttimeout) { - double has_passed; + long has_passed; /* Evaluate in milliseconds how much time that has passed */ has_passed = Curl_tvdiff(Curl_tvnow(), data->progress.start); @@ -696,7 +696,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ timeout_ms = data->set.connecttimeout*1000; /* subtract the passed time */ - timeout_ms -= (long)has_passed; + timeout_ms -= has_passed; if(timeout_ms < 0) { /* a precaution, no need to continue if time already is up */ -- cgit v1.2.1 From 4c17ba4fc044eb7eb02ed7ea8c716b8f7e6614d9 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sun, 4 Jul 2004 21:48:54 +0000 Subject: make sure the 3rd argument passed to bind() is a socklen_t --- lib/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index ce3d40cf1..de8d29726 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -336,7 +336,7 @@ static CURLcode bindlocal(struct connectdata *conn, Curl_resolv_unlock(data, h); /* we don't need it anymore after this function has returned */ - if( bind(sockfd, addr->ai_addr, addr->ai_addrlen) >= 0) { + if( bind(sockfd, addr->ai_addr, (socklen_t)addr->ai_addrlen) >= 0) { /* we succeeded to bind */ #ifdef ENABLE_IPV6 struct sockaddr_in6 add; -- cgit v1.2.1 From 55e61c092ed05b5fbe92e7f212d98bf331ba22c0 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 4 Aug 2004 12:38:01 +0000 Subject: Fixed multiple IP connects with the multi interface. This fix is influenced by Gisle Vanem's patch, only modified by me. --- lib/connect.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index de8d29726..9d29a0a27 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -432,7 +432,6 @@ static bool verifyconnect(curl_socket_t sockfd, int *error) more address exists */ static bool trynextip(struct connectdata *conn, int sockindex, - long timeout, bool *connected) { curl_socket_t sockfd; @@ -441,13 +440,15 @@ static bool trynextip(struct connectdata *conn, if(sockindex != FIRSTSOCKET) return TRUE; /* no next */ + /* try the next address */ ai = conn->ip_addr->ai_next; while (ai) { - sockfd = singleipconnect(conn, ai, timeout, connected); + sockfd = singleipconnect(conn, ai, 0L, connected); if(sockfd != CURL_SOCKET_BAD) { /* store the new socket descriptor */ conn->sock[sockindex] = sockfd; + conn->ip_addr = ai; return FALSE; } ai = ai->ai_next; @@ -514,14 +515,14 @@ CURLcode Curl_is_connected(struct connectdata *conn, } /* nope, not connected for real */ infof(data, "Connection failed\n"); - if(trynextip(conn, sockindex, allow-has_passed, connected)) { + if(trynextip(conn, sockindex, connected)) { code = CURLE_COULDNT_CONNECT; } } else if(WAITCONN_TIMEOUT != rc) { /* nope, not connected */ infof(data, "Connection failed\n"); - if(trynextip(conn, sockindex, allow-has_passed, connected)) { + if(trynextip(conn, sockindex, connected)) { int error = Curl_ourerrno(); failf(data, "Failed connect to %s:%d; %s", conn->host.name, conn->port, Curl_strerror(conn,error)); -- cgit v1.2.1 From 6cd25360480e20ce796a43a76e65bf0b07230c7c Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sun, 19 Sep 2004 14:27:56 +0000 Subject: set an error message when connection fails --- lib/connect.c | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 9d29a0a27..f6d10f60e 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -745,6 +745,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ if (sockfd == CURL_SOCKET_BAD) { /* no good connect was made */ *sockconn = CURL_SOCKET_BAD; + failf(data, "couldn't connect to host"); return CURLE_COULDNT_CONNECT; } -- cgit v1.2.1 From be1cece69b2bc7b73c07166ec5e164fabdac1c95 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 30 Sep 2004 21:01:23 +0000 Subject: - Larry Campbell added CURLINFO_OS_ERRNO to curl_easy_getinfo() that allows an app to retrieve the errno variable after a (connect) failure. It will make sense to provide this for more failures in a more generic way, but let's start like this. --- lib/connect.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index f6d10f60e..5e8c047bc 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -355,7 +355,8 @@ static CURLcode bindlocal(struct connectdata *conn, } if(!bindworked) { - failf(data, "%s", Curl_strerror(conn, Curl_ourerrno())); + data->state.os_errno = Curl_ourerrno(); + failf(data, "%s", Curl_strerror(conn, data->state.os_errno)); return CURLE_HTTP_PORT_FAILED; } @@ -508,12 +509,14 @@ CURLcode Curl_is_connected(struct connectdata *conn, rc = waitconnect(sockfd, 0); if(WAITCONN_CONNECTED == rc) { - if (verifyconnect(sockfd, NULL)) { + int error; + if (verifyconnect(sockfd, &error)) { /* we are connected, awesome! */ *connected = TRUE; return CURLE_OK; } /* nope, not connected for real */ + data->state.os_errno = error; infof(data, "Connection failed\n"); if(trynextip(conn, sockindex, connected)) { code = CURLE_COULDNT_CONNECT; @@ -635,8 +638,10 @@ singleipconnect(struct connectdata *conn, } else if(WAITCONN_TIMEOUT == rc) infof(data, "Timeout\n"); - else + else { + data->state.os_errno = error; infof(data, "%s\n", Curl_strerror(conn, error)); + } /* connect failed or timed out */ sclose(sockfd); -- cgit v1.2.1 From 39af394a1c3ae1d8ac71ad263a7c524988702c2e Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 6 Oct 2004 07:50:18 +0000 Subject: removed tabs and trailing whitespace from source --- lib/connect.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 5e8c047bc..3ff73636d 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -67,7 +67,7 @@ #undef in_addr_t #define in_addr_t unsigned long #endif -#ifdef VMS +#ifdef VMS #include #include #endif @@ -362,8 +362,8 @@ static CURLcode bindlocal(struct connectdata *conn, } /* end of if h */ else { - failf(data,"could't find my own IP address (%s)", myhost); - return CURLE_HTTP_PORT_FAILED; + failf(data,"could't find my own IP address (%s)", myhost); + return CURLE_HTTP_PORT_FAILED; } } /* end of inet_addr */ -- cgit v1.2.1 From 34342bcd194f372c48be3a216cdea075e35f2c40 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 11 Oct 2004 17:23:41 +0000 Subject: SO_NOSIGPIPE --- lib/connect.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 3ff73636d..7343756b9 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -558,6 +558,23 @@ static void tcpnodelay(struct connectdata *conn, #endif } +#ifdef SO_NOSIGPIPE +/* The preferred method on Mac OS X (10.2 and later) to prevent SIGPIPEs when + sending data to a dead peer (instead of relying on the 4th argument to send + being MSG_NOSIGNAL). Possibly also existing and in use on other BSD + systems? */ +static void nosigpipe(struct connectdata *conn, + curl_socket_t sockfd) +{ + struct SessionHandle *data= conn->data; + int onoff = 1; + if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff, + sizeof(onoff)) < 0) + infof(data, "Could not set SO_NOSIGPIPE: %s\n", + Curl_strerror(conn, Curl_ourerrno())); +} +#endif + /* singleipconnect() connects to the given IP only, and it may return without having connected if used from the multi interface. */ static curl_socket_t @@ -584,6 +601,9 @@ singleipconnect(struct connectdata *conn, if(data->set.tcp_nodelay) tcpnodelay(conn, sockfd); +#ifdef SO_NOSIGPIPE + nosigpipe(conn, sockfd); +#endif if(conn->data->set.device) { /* user selected to bind the outgoing socket to a specified "device" before doing connect */ -- cgit v1.2.1 From f4bef25b5eede9ea17f237ebae52c2f89cc211cd Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 19 Oct 2004 15:30:08 +0000 Subject: CURLINFO_NUM_CONNECTS and more --- lib/connect.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 7343756b9..5d464acbd 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -784,5 +784,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ if(sockconn) *sockconn = sockfd; /* the socket descriptor we've connected */ + data->info.numconnects++; /* to track the number of connections made */ + return CURLE_OK; } -- cgit v1.2.1 From 24d47a6e07304cf0921f2d30734b3c64360773c3 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 2 Nov 2004 10:12:22 +0000 Subject: Paul Nolan fix to make libcurl build nicely on Windows CE --- lib/connect.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 5d464acbd..c61301ad2 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -156,6 +156,7 @@ int Curl_nonblock(curl_socket_t sockfd, /* operate on this */ /* Windows? */ unsigned long flags; flags = nonblock; + return ioctlsocket(sockfd, FIONBIO, &flags); #define SETBLOCK 3 #endif @@ -406,13 +407,25 @@ static bool verifyconnect(curl_socket_t sockfd, int *error) * * Someone got to verify this on Win-NT 4.0, 2000." */ + +#ifdef _WIN32_WCE + Sleep(0); +#else SleepEx(0, FALSE); +#endif + #endif if( -1 == getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *)&err, &errSize)) err = Curl_ourerrno(); +#ifdef _WIN32_WCE + /* Always returns this error, bug in CE? */ + if(WSAENOPROTOOPT==err) + err=0; +#endif + if ((0 == err) || (EISCONN == err)) /* we are connected, awesome! */ rc = TRUE; -- cgit v1.2.1 From 5931d43a36d092d0c6a266c8cf619814c2f62d22 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 15 Nov 2004 11:27:03 +0000 Subject: clean up start time and t_startsingle use so that redirect_time works properly --- lib/connect.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index c61301ad2..1851431e8 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -491,7 +491,7 @@ CURLcode Curl_is_connected(struct connectdata *conn, *connected = FALSE; /* a very negative world view is best */ /* Evaluate in milliseconds how much time that has passed */ - has_passed = Curl_tvdiff(Curl_tvnow(), data->progress.start); + has_passed = Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle); /* subtract the most strict timeout of the ones */ if(data->set.timeout && data->set.connecttimeout) { @@ -716,7 +716,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ long has_passed; /* Evaluate in milliseconds how much time that has passed */ - has_passed = Curl_tvdiff(Curl_tvnow(), data->progress.start); + has_passed = Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle); #ifndef min #define min(a, b) ((a) < (b) ? (a) : (b)) -- cgit v1.2.1 From 1a05a90f1ce86394d7966aaaa9539adaa228c6bf Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 19 Nov 2004 08:52:33 +0000 Subject: David Phillips' FD_SETSIZE fix --- lib/connect.c | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 1851431e8..b8e1e7158 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -97,6 +97,7 @@ #include "strerror.h" #include "connect.h" #include "memory.h" +#include "select.h" /* The last #include file should be: */ #include "memdebug.h" @@ -202,9 +203,6 @@ static int waitconnect(curl_socket_t sockfd, /* socket */ long timeout_msec) { - fd_set fd; - fd_set errfd; - struct timeval interval; int rc; #ifdef mpeix /* Call this function once now, and ignore the results. We do this to @@ -214,18 +212,7 @@ int waitconnect(curl_socket_t sockfd, /* socket */ #endif /* now select() until we get connect or timeout */ - FD_ZERO(&fd); - FD_SET(sockfd, &fd); - - FD_ZERO(&errfd); - FD_SET(sockfd, &errfd); - - interval.tv_sec = (int)(timeout_msec/1000); - timeout_msec -= interval.tv_sec*1000; - - interval.tv_usec = timeout_msec*1000; - - rc = select(sockfd+1, NULL, &fd, &errfd, &interval); + rc = Curl_select(CURL_SOCKET_BAD, sockfd, timeout_msec); if(-1 == rc) /* error, no connect here, try next */ return WAITCONN_SELECT_ERROR; @@ -234,7 +221,7 @@ int waitconnect(curl_socket_t sockfd, /* socket */ /* timeout, no connect today */ return WAITCONN_TIMEOUT; - if(FD_ISSET(sockfd, &errfd)) + if(rc & CSELECT_ERR) /* error condition caught */ return WAITCONN_FDSET_ERROR; -- cgit v1.2.1 From 8e34e75100d8eac74f5a0019c3b22fde53bc08d6 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 22 Nov 2004 13:28:44 +0000 Subject: Curl_select's timeout arg is an int --- lib/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index b8e1e7158..e982ddfaf 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -212,7 +212,7 @@ int waitconnect(curl_socket_t sockfd, /* socket */ #endif /* now select() until we get connect or timeout */ - rc = Curl_select(CURL_SOCKET_BAD, sockfd, timeout_msec); + rc = Curl_select(CURL_SOCKET_BAD, sockfd, (int)timeout_msec); if(-1 == rc) /* error, no connect here, try next */ return WAITCONN_SELECT_ERROR; -- cgit v1.2.1 From b96a0dba90780950ed7db4882349d99981714216 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 6 Dec 2004 22:45:45 +0000 Subject: Gisle Vanem's fix for better info messages when failing to connect using the multi interface --- lib/connect.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index e982ddfaf..141d9593f 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -523,10 +523,18 @@ CURLcode Curl_is_connected(struct connectdata *conn, } } else if(WAITCONN_TIMEOUT != rc) { + int error = 0; + /* nope, not connected */ + if (WAITCONN_FDSET_ERROR == rc) { + verifyconnect(sockfd, &error); + infof(data, "%s\n",Curl_strerror(conn,error)); + } + else infof(data, "Connection failed\n"); + if(trynextip(conn, sockindex, connected)) { - int error = Curl_ourerrno(); + error = Curl_ourerrno(); failf(data, "Failed connect to %s:%d; %s", conn->host.name, conn->port, Curl_strerror(conn,error)); code = CURLE_COULDNT_CONNECT; -- cgit v1.2.1 From 1dc15ec1bc034864cb11156af6f2ba9714ca95a1 Mon Sep 17 00:00:00 2001 From: Gisle Vanem Date: Mon, 13 Dec 2004 17:52:55 +0000 Subject: Set 'data->state.os_errno = error' in some places. Needed elsewhere too? --- lib/connect.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 141d9593f..3b40891ad 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -528,13 +528,15 @@ CURLcode Curl_is_connected(struct connectdata *conn, /* nope, not connected */ if (WAITCONN_FDSET_ERROR == rc) { verifyconnect(sockfd, &error); + data->state.os_errno = error; infof(data, "%s\n",Curl_strerror(conn,error)); } else - infof(data, "Connection failed\n"); + infof(data, "Connection failed\n"); if(trynextip(conn, sockindex, connected)) { error = Curl_ourerrno(); + data->state.os_errno = error; failf(data, "Failed connect to %s:%d; %s", conn->host.name, conn->port, Curl_strerror(conn,error)); code = CURLE_COULDNT_CONNECT; @@ -644,6 +646,7 @@ singleipconnect(struct connectdata *conn, /* unknown error, fallthrough and try another address! */ failf(data, "Failed to connect to %s: %s", addr_buf, Curl_strerror(conn,error)); + data->state.os_errno = error; break; } } -- cgit v1.2.1 From f661475962213123b5e640db9744b23ea361ac65 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 28 Jan 2005 23:21:24 +0000 Subject: Connect failures with the multi interface was often returned as "connect() timed out" even though the reason was different. Fixed this problem by not setting this timeout to zero when using multi. --- lib/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 3b40891ad..5cd4c0656 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -754,7 +754,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ if(data->state.used_interface == Curl_if_multi) /* don't hang when doing multi */ - timeout_per_addr = timeout_ms = 0; + timeout_per_addr = 0; /* * Connecting with a Curl_addrinfo chain -- cgit v1.2.1 From c4ff5eb0ca9322a6671d581e80e0c63085b21426 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 29 Jan 2005 13:07:16 +0000 Subject: conn->ip_addr MUST NOT be used on re-used connections --- lib/connect.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 5cd4c0656..104be2d42 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2004, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2005, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -429,6 +429,25 @@ static bool verifyconnect(curl_socket_t sockfd, int *error) return rc; } +CURLcode Curl_store_ip_addr(struct connectdata *conn) +{ + char addrbuf[256]; + Curl_printable_address(conn->ip_addr, addrbuf, sizeof(addrbuf)); + + /* save the string */ + Curl_safefree(conn->ip_addr_str); + conn->ip_addr_str = strdup(addrbuf); + if(!conn->ip_addr_str) + return CURLE_OUT_OF_MEMORY; /* FAIL */ + +#ifdef PF_INET6 + if(conn->ip_addr->ai_family == PF_INET6) + conn->bits.ipv6 = TRUE; +#endif + + return CURLE_OK; +} + /* Used within the multi interface. Try next IP address, return TRUE if no more address exists */ static bool trynextip(struct connectdata *conn, @@ -450,6 +469,8 @@ static bool trynextip(struct connectdata *conn, /* store the new socket descriptor */ conn->sock[sockindex] = sockfd; conn->ip_addr = ai; + + Curl_store_ip_addr(conn); return FALSE; } ai = ai->ai_next; -- cgit v1.2.1 From 9a820d7a987dab462fef32ca1b4ca5ecfd20c19a Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 29 Jan 2005 22:38:45 +0000 Subject: include "url.h" for the Curl_safefree() proto --- lib/connect.c | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 104be2d42..e59e6721e 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -98,6 +98,7 @@ #include "connect.h" #include "memory.h" #include "select.h" +#include "url.h" /* for Curl_safefree() */ /* The last #include file should be: */ #include "memdebug.h" -- cgit v1.2.1 From 176981b529bad6a61ad4a5439c87953ae5541a98 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 17 Feb 2005 14:45:03 +0000 Subject: close the socket properly when returning error due to failing localbind Bug report #1124588 by David --- lib/connect.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index e59e6721e..261ab08d8 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -640,8 +640,10 @@ singleipconnect(struct connectdata *conn, /* user selected to bind the outgoing socket to a specified "device" before doing connect */ CURLcode res = bindlocal(conn, sockfd); - if(res) + if(res) { + sclose(sockfd); /* close socket and bail out */ return res; + } } /* set socket non-blocking */ -- cgit v1.2.1 From 3916d1e6cbe8eb5cb4dbbc43690b44b0b8fe6cc1 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 14 Mar 2005 15:43:23 +0000 Subject: silence compiler warnings for mingw win32 builds --enable-debug --- lib/connect.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 261ab08d8..f402ede77 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -364,6 +364,9 @@ static CURLcode bindlocal(struct connectdata *conn, return CURLE_OK; } /* end of device selection support */ +#else + (void)conn; + (void)sockfd; #endif /* end of HAVE_INET_NTOA */ return CURLE_HTTP_PORT_FAILED; -- cgit v1.2.1 From 6b1220b61d5ed2481dbf31714a68be6ef6eed3da Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 26 Apr 2005 13:08:49 +0000 Subject: Cory Nelson's work on nuking compiler warnings when building on x64 with VS2005. --- lib/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index f402ede77..c7b3c51bb 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -652,7 +652,7 @@ singleipconnect(struct connectdata *conn, /* set socket non-blocking */ Curl_nonblock(sockfd, TRUE); - rc = connect(sockfd, ai->ai_addr, ai->ai_addrlen); + rc = connect(sockfd, ai->ai_addr, (socklen_t)ai->ai_addrlen); if(-1 == rc) { error = Curl_ourerrno(); -- cgit v1.2.1 From ae1d6f29d93ec987d829dd407cb8958c341edfe0 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 30 Apr 2005 15:16:39 +0000 Subject: singleipconnect() returns a socket descriptor, not a CURLcode (but perhaps we should make it do that...) --- lib/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index c7b3c51bb..17a2c94de 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -645,7 +645,7 @@ singleipconnect(struct connectdata *conn, CURLcode res = bindlocal(conn, sockfd); if(res) { sclose(sockfd); /* close socket and bail out */ - return res; + return CURL_SOCKET_BAD; } } -- cgit v1.2.1 From 44985e88845f4a931795fc1cfd41c3231fd3e73f Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 2 May 2005 22:53:55 +0000 Subject: improved failf() error messages --- lib/connect.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 17a2c94de..b603c12c8 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -345,7 +345,8 @@ static CURLcode bindlocal(struct connectdata *conn, if(!bindworked) { data->state.os_errno = Curl_ourerrno(); - failf(data, "%s", Curl_strerror(conn, data->state.os_errno)); + failf(data, "bind failure: %s", + Curl_strerror(conn, data->state.os_errno)); return CURLE_HTTP_PORT_FAILED; } -- cgit v1.2.1 From 0c96056a943ee73b95e32208c4f0d2ae9b6e1e48 Mon Sep 17 00:00:00 2001 From: Gisle Vanem Date: Sat, 14 May 2005 05:58:52 +0000 Subject: Change for systems with >1 ways of setting (non-)blocking mode. (djgpp/Watt-32 has 3 ways). Should rewrite this using "#elif ..", but maybe there is still broken cpp around? --- lib/connect.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index b603c12c8..4ab7af2bd 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -133,6 +133,7 @@ int Curl_nonblock(curl_socket_t sockfd, /* operate on this */ int nonblock /* TRUE or FALSE */) { #undef SETBLOCK +#define SETBLOCK 0 #ifdef HAVE_O_NONBLOCK /* most recent unix versions */ int flags; @@ -145,43 +146,48 @@ int Curl_nonblock(curl_socket_t sockfd, /* operate on this */ #define SETBLOCK 1 #endif -#ifdef HAVE_FIONBIO +#if defined(HAVE_FIONBIO) && (SETBLOCK == 0) /* older unix versions */ int flags; flags = nonblock; return ioctl(sockfd, FIONBIO, &flags); +#undef SETBLOCK #define SETBLOCK 2 #endif -#ifdef HAVE_IOCTLSOCKET +#if defined(HAVE_IOCTLSOCKET) && (SETBLOCK == 0) /* Windows? */ unsigned long flags; flags = nonblock; return ioctlsocket(sockfd, FIONBIO, &flags); +#undef SETBLOCK #define SETBLOCK 3 #endif -#ifdef HAVE_IOCTLSOCKET_CASE +#if defined(HAVE_IOCTLSOCKET_CASE) && (SETBLOCK == 0) /* presumably for Amiga */ return IoctlSocket(sockfd, FIONBIO, (long)nonblock); +#undef SETBLOCK #define SETBLOCK 4 #endif -#ifdef HAVE_SO_NONBLOCK +#if defined(HAVE_SO_NONBLOCK) && (SETBLOCK == 0) /* BeOS */ long b = nonblock ? 1 : 0; return setsockopt(sockfd, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b)); +#undef SETBLOCK #define SETBLOCK 5 #endif #ifdef HAVE_DISABLED_NONBLOCKING return 0; /* returns success */ +#undef SETBLOCK #define SETBLOCK 6 #endif -#ifndef SETBLOCK +#if (SETBLOCK == 0) #error "no non-blocking method was found/used/set" #endif } -- cgit v1.2.1 From 944af98be677d87999d3f8ccd3b8a322defb86ac Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 14 May 2005 21:15:36 +0000 Subject: fix warning about redefined symbol --- lib/connect.c | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 4ab7af2bd..8799ba2df 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -143,6 +143,7 @@ int Curl_nonblock(curl_socket_t sockfd, /* operate on this */ return fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); else return fcntl(sockfd, F_SETFL, flags & (~O_NONBLOCK)); +#undef SETBLOCK #define SETBLOCK 1 #endif -- cgit v1.2.1 From 6e87cf5b30ac44447315f66ffa164e8eec8df831 Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Thu, 21 Jul 2005 22:18:35 +0000 Subject: Fixed some typos in output messages. --- lib/connect.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 8799ba2df..50f6684b6 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -359,13 +359,13 @@ static CURLcode bindlocal(struct connectdata *conn, } /* end of if h */ else { - failf(data,"could't find my own IP address (%s)", myhost); + failf(data,"couldn't find my own IP address (%s)", myhost); return CURLE_HTTP_PORT_FAILED; } } /* end of inet_addr */ else { - failf(data, "could't find my own IP address (%s)", myhost); + failf(data, "couldn't find my own IP address (%s)", myhost); return CURLE_HTTP_PORT_FAILED; } -- cgit v1.2.1 From 56d9624b566ac15ffb4b4b6eef220a5000b767e0 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 2 Sep 2005 15:11:08 +0000 Subject: John Kelly added TFTP support to libcurl. A bunch of new error codes was added. TODO: add them to docs. add TFTP server to test suite. add TFTP to list of protocols whereever those are mentioned. --- lib/connect.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 50f6684b6..5d9cf65ef 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -660,8 +660,13 @@ singleipconnect(struct connectdata *conn, /* set socket non-blocking */ Curl_nonblock(sockfd, TRUE); - rc = connect(sockfd, ai->ai_addr, (socklen_t)ai->ai_addrlen); - + /* Connect TCP sockets, bind UDP */ + if(ai->ai_socktype==SOCK_STREAM) { + rc = connect(sockfd, ai->ai_addr, (socklen_t)ai->ai_addrlen); + } else { + rc = 0; + } + if(-1 == rc) { error = Curl_ourerrno(); -- cgit v1.2.1 From e7093b3ca8f54a9d67a078ce37afdc825c86fdf4 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 16 Sep 2005 21:30:08 +0000 Subject: keep 'socktype' in the connectdata struct and make sure we use that for all protocol sockets even if the resolved address may say otherwise --- lib/connect.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 5d9cf65ef..23c192c7d 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -631,8 +631,9 @@ singleipconnect(struct connectdata *conn, int error; bool conected; struct SessionHandle *data = conn->data; - curl_socket_t sockfd = socket(ai->ai_family, ai->ai_socktype, - ai->ai_protocol); + curl_socket_t sockfd; + + sockfd = socket(ai->ai_family, conn->socktype, ai->ai_protocol); if (sockfd == CURL_SOCKET_BAD) return CURL_SOCKET_BAD; @@ -661,12 +662,11 @@ singleipconnect(struct connectdata *conn, Curl_nonblock(sockfd, TRUE); /* Connect TCP sockets, bind UDP */ - if(ai->ai_socktype==SOCK_STREAM) { + if(conn->socktype == SOCK_STREAM) rc = connect(sockfd, ai->ai_addr, (socklen_t)ai->ai_addrlen); - } else { + else rc = 0; - } - + if(-1 == rc) { error = Curl_ourerrno(); -- cgit v1.2.1 From 9e0882ba98feff82f4ffa1f8701cdc139bbcd0f1 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 25 Oct 2005 13:15:11 +0000 Subject: close the existing socket when trying next IP, as otherwise we leak one! bug #1326306 --- lib/connect.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 23c192c7d..18c40f9ac 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -472,6 +472,9 @@ static bool trynextip(struct connectdata *conn, if(sockindex != FIRSTSOCKET) return TRUE; /* no next */ + /* first close the failed socket */ + sclose(conn->sock[sockindex]); + /* try the next address */ ai = conn->ip_addr->ai_next; -- cgit v1.2.1 From e2df946eee5cc05ff11d841fae8afdc9ad5d4852 Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Tue, 13 Dec 2005 18:54:31 +0000 Subject: Fixed some compiler warnings on lcc. --- lib/connect.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 18c40f9ac..42c0ea6e7 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -216,7 +216,7 @@ int waitconnect(curl_socket_t sockfd, /* socket */ /* Call this function once now, and ignore the results. We do this to "clear" the error state on the socket so that we can later read it reliably. This is reported necessary on the MPE/iX operating system. */ - verifyconnect(sockfd, NULL); + (void)verifyconnect(sockfd, NULL); #endif /* now select() until we get connect or timeout */ @@ -563,7 +563,7 @@ CURLcode Curl_is_connected(struct connectdata *conn, /* nope, not connected */ if (WAITCONN_FDSET_ERROR == rc) { - verifyconnect(sockfd, &error); + (void)verifyconnect(sockfd, &error); data->state.os_errno = error; infof(data, "%s\n",Curl_strerror(conn,error)); } @@ -632,7 +632,7 @@ singleipconnect(struct connectdata *conn, char addr_buf[128]; int rc; int error; - bool conected; + bool isconnected; struct SessionHandle *data = conn->data; curl_socket_t sockfd; @@ -702,9 +702,9 @@ singleipconnect(struct connectdata *conn, return sockfd; } - conected = verifyconnect(sockfd, &error); + isconnected = verifyconnect(sockfd, &error); - if(!rc && conected) { + if(!rc && isconnected) { /* we are connected, awesome! */ *connected = TRUE; /* this is a true connect */ infof(data, "connected\n"); -- cgit v1.2.1 From d6c5d24af3627ec12721e7d286d426ed12901b55 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Sun, 18 Dec 2005 15:36:14 +0000 Subject: Cleanup windows header includes. Where aplicable, inclusion of windows.h winsock.h winsock2.h ws2tcpip.h is done in setup.h --- lib/connect.c | 1 - 1 file changed, 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 42c0ea6e7..2fb08d628 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -83,7 +83,6 @@ #endif #ifdef WIN32 -#include #define EINPROGRESS WSAEINPROGRESS #define EWOULDBLOCK WSAEWOULDBLOCK #define EISCONN WSAEISCONN -- cgit v1.2.1 From 2fbf94b0f309de9bd9153274bb475abc744afb0a Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 30 Jan 2006 08:24:07 +0000 Subject: Added CURLOPT_LOCALPORT and CURLOPT_LOCALPORTRANGE to libcurl. Set with the curl tool with --local-port. Plain and simply set the range of ports to bind the local end of connections to. Implemented on to popular demand. Not extensively tested. Please let me know how it works. --- lib/connect.c | 147 ++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 87 insertions(+), 60 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 2fb08d628..902721c80 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2005, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2006, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -98,6 +98,7 @@ #include "memory.h" #include "select.h" #include "url.h" /* for Curl_safefree() */ +#include "sockaddr.h" /* required for Curl_sockaddr_storage */ /* The last #include file should be: */ #include "memdebug.h" @@ -239,16 +240,20 @@ int waitconnect(curl_socket_t sockfd, /* socket */ static CURLcode bindlocal(struct connectdata *conn, curl_socket_t sockfd) { -#ifdef HAVE_INET_NTOA - bool bindworked = FALSE; struct SessionHandle *data = conn->data; + struct sockaddr_in me; + struct sockaddr *sock = NULL; /* bind to this address */ + socklen_t socksize; /* size of the data sock points to */ + unsigned short port = data->set.localport; /* use this port number, 0 for + "random" */ + /* how many port numbers to try to bind to, increasing one at a time */ + int portnum = data->set.localportrange; /************************************************************* * Select device to bind socket to *************************************************************/ - if (strlen(data->set.device)<255) { + if (data->set.device && (strlen(data->set.device)<255) ) { struct Curl_dns_entry *h=NULL; - size_t size; char myhost[256] = ""; in_addr_t in; int rc; @@ -266,8 +271,10 @@ static CURLcode bindlocal(struct connectdata *conn, if(rc == CURLRESOLV_PENDING) (void)Curl_wait_for_resolv(conn, &h); - if(h) + if(h) { was_iface = TRUE; + Curl_resolv_unlock(data, h); + } } if(!was_iface) { @@ -279,9 +286,11 @@ static CURLcode bindlocal(struct connectdata *conn, if(rc == CURLRESOLV_PENDING) (void)Curl_wait_for_resolv(conn, &h); - if(h) + if(h) { /* we know data->set.device is shorter than the myhost array */ strcpy(myhost, data->set.device); + Curl_resolv_unlock(data, h); + } } if(! *myhost) { @@ -295,7 +304,7 @@ static CURLcode bindlocal(struct connectdata *conn, return CURLE_HTTP_PORT_FAILED; } - infof(data, "We bind local end to %s\n", myhost); + infof(data, "Bind local address to %s\n", myhost); #ifdef SO_BINDTODEVICE /* I am not sure any other OSs than Linux that provide this feature, and @@ -323,60 +332,79 @@ static CURLcode bindlocal(struct connectdata *conn, #endif in=inet_addr(myhost); - if (CURL_INADDR_NONE != in) { + if (CURL_INADDR_NONE == in) { + failf(data,"couldn't find my own IP address (%s)", myhost); + return CURLE_HTTP_PORT_FAILED; + } /* end of inet_addr */ - if ( h ) { - Curl_addrinfo *addr = h->addr; + if ( h ) { + Curl_addrinfo *addr = h->addr; + sock = addr->ai_addr; + socksize = addr->ai_addrlen; + } + else + return CURLE_HTTP_PORT_FAILED; - Curl_resolv_unlock(data, h); - /* we don't need it anymore after this function has returned */ + } + else if(port) { + /* if a local port number is requested but no local IP, extract the + address from the socket */ + memset(&me, 0, sizeof(struct sockaddr)); + me.sin_family = AF_INET; + me.sin_addr.s_addr = INADDR_ANY; - if( bind(sockfd, addr->ai_addr, (socklen_t)addr->ai_addrlen) >= 0) { - /* we succeeded to bind */ -#ifdef ENABLE_IPV6 - struct sockaddr_in6 add; -#else - struct sockaddr_in add; -#endif + sock = (struct sockaddr *)&me; + socksize = sizeof(struct sockaddr); - bindworked = TRUE; + } + else + /* no local kind of binding was requested */ + return CURLE_OK; - size = sizeof(add); - if(getsockname(sockfd, (struct sockaddr *) &add, - (socklen_t *)&size)<0) { - failf(data, "getsockname() failed"); - return CURLE_HTTP_PORT_FAILED; - } - } + do { - if(!bindworked) { - data->state.os_errno = Curl_ourerrno(); - failf(data, "bind failure: %s", - Curl_strerror(conn, data->state.os_errno)); - return CURLE_HTTP_PORT_FAILED; - } + /* Set port number to bind to, 0 makes the system pick one */ + if(sock->sa_family == AF_INET) + ((struct sockaddr_in *)sock)->sin_port = htons(port); +#ifdef ENABLE_IPV6 + else + ((struct sockaddr_in6 *)sock)->sin6_port = htons(port); +#endif - } /* end of if h */ - else { - failf(data,"couldn't find my own IP address (%s)", myhost); + if( bind(sockfd, sock, socksize) >= 0) { + /* we succeeded to bind */ + struct Curl_sockaddr_storage add; + unsigned short port; + size_t size; + + size = sizeof(add); + if(getsockname(sockfd, (struct sockaddr *) &add, + (socklen_t *)&size)<0) { + failf(data, "getsockname() failed"); return CURLE_HTTP_PORT_FAILED; } - } /* end of inet_addr */ - - else { - failf(data, "couldn't find my own IP address (%s)", myhost); - return CURLE_HTTP_PORT_FAILED; + if(((struct sockaddr *)&add)->sa_family == AF_INET) + port = ntohs(((struct sockaddr_in *)&add)->sin_port); +#ifdef ENABLE_IPV6 + else + port = ntohs(((struct sockaddr_in6 *)&add)->sin6_port); +#endif + infof(data, "Local port: %d\n", port); + return CURLE_OK; } + if(--portnum > 0) { + infof(data, "Bind to local port %d failed, trying next\n", port); + port++; /* try next port */ + } + else + break; + } while(1); - return CURLE_OK; - - } /* end of device selection support */ -#else - (void)conn; - (void)sockfd; -#endif /* end of HAVE_INET_NTOA */ - + data->state.os_errno = Curl_ourerrno(); + failf(data, "bind failure: %s", + Curl_strerror(conn, data->state.os_errno)); return CURLE_HTTP_PORT_FAILED; + } /* @@ -618,6 +646,8 @@ static void nosigpipe(struct connectdata *conn, infof(data, "Could not set SO_NOSIGPIPE: %s\n", Curl_strerror(conn, Curl_ourerrno())); } +#else +#define nosigpipe(x,y) #endif /* singleipconnect() connects to the given IP only, and it may return without @@ -634,6 +664,7 @@ singleipconnect(struct connectdata *conn, bool isconnected; struct SessionHandle *data = conn->data; curl_socket_t sockfd; + CURLcode res; sockfd = socket(ai->ai_family, conn->socktype, ai->ai_protocol); if (sockfd == CURL_SOCKET_BAD) @@ -647,17 +678,13 @@ singleipconnect(struct connectdata *conn, if(data->set.tcp_nodelay) tcpnodelay(conn, sockfd); -#ifdef SO_NOSIGPIPE nosigpipe(conn, sockfd); -#endif - if(conn->data->set.device) { - /* user selected to bind the outgoing socket to a specified "device" - before doing connect */ - CURLcode res = bindlocal(conn, sockfd); - if(res) { - sclose(sockfd); /* close socket and bail out */ - return CURL_SOCKET_BAD; - } + + /* possibly bind the local end to an IP, interface or port */ + res = bindlocal(conn, sockfd); + if(res) { + sclose(sockfd); /* close socket and bail out */ + return CURL_SOCKET_BAD; } /* set socket non-blocking */ -- cgit v1.2.1 From 5994b62930c004deccff61b7670ebf6debadfaa2 Mon Sep 17 00:00:00 2001 From: Gisle Vanem Date: Mon, 30 Jan 2006 18:57:02 +0000 Subject: Squelch the "warning: 'port' might be used uninitialized in this function". (occurs w/o ENABLE_IPV6). --- lib/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 902721c80..787951136 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -374,7 +374,7 @@ static CURLcode bindlocal(struct connectdata *conn, if( bind(sockfd, sock, socksize) >= 0) { /* we succeeded to bind */ struct Curl_sockaddr_storage add; - unsigned short port; + unsigned short port = 0; size_t size; size = sizeof(add); -- cgit v1.2.1 From 60b029869f3f21ba73350793f8f7355f13d538cc Mon Sep 17 00:00:00 2001 From: Gisle Vanem Date: Sun, 26 Feb 2006 17:08:33 +0000 Subject: Use getprotobyname() to retrieve protocol number for TCP (sorry, I don't know how to add this to the configure process). --- lib/connect.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 787951136..427a87431 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -619,7 +619,15 @@ static void tcpnodelay(struct connectdata *conn, #ifdef TCP_NODELAY struct SessionHandle *data= conn->data; socklen_t onoff = (socklen_t) data->set.tcp_nodelay; - if(setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (void *)&onoff, + int proto = IPPROTO_TCP; + +#ifdef HAVE_GETPROTOBYNAME + struct protoent *pe = getprotobyname("tcp"); + if (pe) + proto = p->p_proto; +#endif + + if(setsockopt(sockfd, proto, TCP_NODELAY, (void *)&onoff, sizeof(onoff)) < 0) infof(data, "Could not set TCP_NODELAY: %s\n", Curl_strerror(conn, Curl_ourerrno())); -- cgit v1.2.1 From dc4fbd2e97e5705ad4d93b05b2fff14e6b222320 Mon Sep 17 00:00:00 2001 From: Gisle Vanem Date: Sun, 26 Feb 2006 18:20:43 +0000 Subject: Small fix. --- lib/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 427a87431..b1186f267 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -624,7 +624,7 @@ static void tcpnodelay(struct connectdata *conn, #ifdef HAVE_GETPROTOBYNAME struct protoent *pe = getprotobyname("tcp"); if (pe) - proto = p->p_proto; + proto = pe->p_proto; #endif if(setsockopt(sockfd, proto, TCP_NODELAY, (void *)&onoff, -- cgit v1.2.1 From 686d90745be4417127050ad4b36d0a5403def200 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 10 Apr 2006 15:00:53 +0000 Subject: First curl_multi_socket() commit. Should primarily be considered as an internal code rearrange to fit the future better. --- lib/connect.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index b1186f267..8964ec551 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -98,6 +98,7 @@ #include "memory.h" #include "select.h" #include "url.h" /* for Curl_safefree() */ +#include "multiif.h" #include "sockaddr.h" /* required for Curl_sockaddr_storage */ /* The last #include file should be: */ @@ -534,6 +535,7 @@ CURLcode Curl_is_connected(struct connectdata *conn, CURLcode code = CURLE_OK; curl_socket_t sockfd = conn->sock[sockindex]; long allow = DEFAULT_CONNECT_TIMEOUT; + long allow_total = 0; long has_passed; curlassert(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET); @@ -546,12 +548,12 @@ CURLcode Curl_is_connected(struct connectdata *conn, /* subtract the most strict timeout of the ones */ if(data->set.timeout && data->set.connecttimeout) { if (data->set.timeout < data->set.connecttimeout) - allow = data->set.timeout*1000; + allow_total = allow = data->set.timeout*1000; else allow = data->set.connecttimeout*1000; } else if(data->set.timeout) { - allow = data->set.timeout*1000; + allow_total = allow = data->set.timeout*1000; } else if(data->set.connecttimeout) { allow = data->set.connecttimeout*1000; @@ -564,10 +566,13 @@ CURLcode Curl_is_connected(struct connectdata *conn, } if(conn->bits.tcpconnect) { /* we are connected already! */ + Curl_expire(data, allow_total); *connected = TRUE; return CURLE_OK; } + Curl_expire(data, allow); + /* check for connect without timeout as we want to return immediately */ rc = waitconnect(sockfd, 0); @@ -818,6 +823,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ return CURLE_OPERATION_TIMEOUTED; } } + Curl_expire(data, timeout_ms); /* Max time for each address */ num_addr = Curl_num_addresses(remotehost->addr); -- cgit v1.2.1 From 17bf5ac2fca38fc1f54a89a526a577ef0dea0295 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 18 Apr 2006 10:51:07 +0000 Subject: avoid a warning about declaring a variable that shadows an earlier declared one --- lib/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 8964ec551..f0865f47c 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -375,7 +375,6 @@ static CURLcode bindlocal(struct connectdata *conn, if( bind(sockfd, sock, socksize) >= 0) { /* we succeeded to bind */ struct Curl_sockaddr_storage add; - unsigned short port = 0; size_t size; size = sizeof(add); @@ -384,6 +383,7 @@ static CURLcode bindlocal(struct connectdata *conn, failf(data, "getsockname() failed"); return CURLE_HTTP_PORT_FAILED; } + /* We re-use/clobber the port variable here below */ if(((struct sockaddr *)&add)->sa_family == AF_INET) port = ntohs(((struct sockaddr_in *)&add)->sin_port); #ifdef ENABLE_IPV6 -- cgit v1.2.1 From db03d4bdd0aa5b2eaef8fb0987310fe5c0ff0570 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 21 Apr 2006 13:46:19 +0000 Subject: Ale Vesely fixed CURLOPT_INTERFACE when using a hostname --- lib/connect.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index f0865f47c..b3372f42a 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -100,6 +100,7 @@ #include "url.h" /* for Curl_safefree() */ #include "multiif.h" #include "sockaddr.h" /* required for Curl_sockaddr_storage */ +#include "inet_ntop.h" /* The last #include file should be: */ #include "memdebug.h" @@ -288,8 +289,14 @@ static CURLcode bindlocal(struct connectdata *conn, (void)Curl_wait_for_resolv(conn, &h); if(h) { - /* we know data->set.device is shorter than the myhost array */ - strcpy(myhost, data->set.device); + if(in == CURL_INADDR_NONE) + /* convert the resolved address, sizeof myhost >= INET_ADDRSTRLEN */ + Curl_inet_ntop(h->addr->ai_addr->sa_family, + &((struct sockaddr_in*)h->addr->ai_addr)->sin_addr, + myhost, sizeof myhost); + else + /* we know data->set.device is shorter than the myhost array */ + strcpy(myhost, data->set.device); Curl_resolv_unlock(data, h); } } -- cgit v1.2.1 From e85e30546c89e17b6fb0cf383de25b7ed7f3bf3d Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 4 May 2006 22:39:47 +0000 Subject: Roland Blom filed bug report #1481217 (http://curl.haxx.se/bug/view.cgi?id=1481217), with follow-ups by Michele Bini and David Byron. libcurl previously wrongly used GetLastError() on windows to get error details after socket-related function calls, when it really should use WSAGetLastError() instead. When changing to this, the former function Curl_ourerrno() is now instead called Curl_sockerrno() as it is necessary to only use it to get errno from socket-related functions as otherwise it won't work as intended on Windows. --- lib/connect.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index b3372f42a..1ba87099f 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -114,13 +114,13 @@ singleipconnect(struct connectdata *conn, bool *connected); /* - * Curl_ourerrno() returns the errno (or equivalent) on this platform to - * hide platform specific for the function that calls this. + * Curl_sockerrno() returns the *socket-related* errno (or equivalent) on this + * platform to hide platform specific for the function that calls this. */ -int Curl_ourerrno(void) +int Curl_sockerrno(void) { #ifdef WIN32 - return (int)GetLastError(); + return (int)WSAGetLastError(); #else return errno; #endif @@ -330,7 +330,7 @@ static CURLcode bindlocal(struct connectdata *conn, if (setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, data->set.device, strlen(data->set.device)+1) != 0) { /* printf("Failed to BINDTODEVICE, socket: %d device: %s error: %s\n", - sockfd, data->set.device, Curl_strerror(Curl_ourerrno())); */ + sockfd, data->set.device, Curl_strerror(Curl_sockerrno())); */ infof(data, "SO_BINDTODEVICE %s failed\n", data->set.device); /* This is typically "errno 1, error: Operation not permitted" if @@ -408,7 +408,7 @@ static CURLcode bindlocal(struct connectdata *conn, break; } while(1); - data->state.os_errno = Curl_ourerrno(); + data->state.os_errno = Curl_sockerrno(); failf(data, "bind failure: %s", Curl_strerror(conn, data->state.os_errno)); return CURLE_HTTP_PORT_FAILED; @@ -452,7 +452,7 @@ static bool verifyconnect(curl_socket_t sockfd, int *error) if( -1 == getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *)&err, &errSize)) - err = Curl_ourerrno(); + err = Curl_sockerrno(); #ifdef _WIN32_WCE /* Always returns this error, bug in CE? */ @@ -471,7 +471,7 @@ static bool verifyconnect(curl_socket_t sockfd, int *error) #else (void)sockfd; if (error) - *error = Curl_ourerrno(); + *error = Curl_sockerrno(); #endif return rc; } @@ -610,7 +610,7 @@ CURLcode Curl_is_connected(struct connectdata *conn, infof(data, "Connection failed\n"); if(trynextip(conn, sockindex, connected)) { - error = Curl_ourerrno(); + error = Curl_sockerrno(); data->state.os_errno = error; failf(data, "Failed connect to %s:%d; %s", conn->host.name, conn->port, Curl_strerror(conn,error)); @@ -642,7 +642,7 @@ static void tcpnodelay(struct connectdata *conn, if(setsockopt(sockfd, proto, TCP_NODELAY, (void *)&onoff, sizeof(onoff)) < 0) infof(data, "Could not set TCP_NODELAY: %s\n", - Curl_strerror(conn, Curl_ourerrno())); + Curl_strerror(conn, Curl_sockerrno())); else infof(data,"TCP_NODELAY set\n"); #else @@ -664,7 +664,7 @@ static void nosigpipe(struct connectdata *conn, if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff, sizeof(onoff)) < 0) infof(data, "Could not set SO_NOSIGPIPE: %s\n", - Curl_strerror(conn, Curl_ourerrno())); + Curl_strerror(conn, Curl_sockerrno())); } #else #define nosigpipe(x,y) @@ -717,7 +717,7 @@ singleipconnect(struct connectdata *conn, rc = 0; if(-1 == rc) { - error = Curl_ourerrno(); + error = Curl_sockerrno(); switch (error) { case EINPROGRESS: -- cgit v1.2.1 From dcc7900e7cf7c2611ab0f30ea8be0452e30bc199 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Tue, 11 Jul 2006 00:23:21 +0000 Subject: Socket must be set to CURL_SOCKET_BAD after closing it. --- lib/connect.c | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 1ba87099f..0b404aed7 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -509,6 +509,7 @@ static bool trynextip(struct connectdata *conn, /* first close the failed socket */ sclose(conn->sock[sockindex]); + conn->sock[sockindex] = CURL_SOCKET_BAD; /* try the next address */ ai = conn->ip_addr->ai_next; -- cgit v1.2.1 From d2cefc140a601c3028c16b23dae2d47cd95ac3c8 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Fri, 14 Jul 2006 10:30:44 +0000 Subject: Change the ai_addrlen type of struct addrinfo from size_t to socklen_t, per RFC 3493. --- lib/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 0b404aed7..b12cf8b84 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -713,7 +713,7 @@ singleipconnect(struct connectdata *conn, /* Connect TCP sockets, bind UDP */ if(conn->socktype == SOCK_STREAM) - rc = connect(sockfd, ai->ai_addr, (socklen_t)ai->ai_addrlen); + rc = connect(sockfd, ai->ai_addr, ai->ai_addrlen); else rc = 0; -- cgit v1.2.1 From ef82da93fb8e8409cb369598a3e22be6c50fb16b Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Mon, 17 Jul 2006 19:22:28 +0000 Subject: "*connected" must be set to FALSE if trynextip() fails. --- lib/connect.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index b12cf8b84..a24a12178 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -504,12 +504,13 @@ static bool trynextip(struct connectdata *conn, curl_socket_t sockfd; Curl_addrinfo *ai; - if(sockindex != FIRSTSOCKET) - return TRUE; /* no next */ - /* first close the failed socket */ sclose(conn->sock[sockindex]); conn->sock[sockindex] = CURL_SOCKET_BAD; + *connected = FALSE; + + if(sockindex != FIRSTSOCKET) + return TRUE; /* no next */ /* try the next address */ ai = conn->ip_addr->ai_next; -- cgit v1.2.1 From c4ad533300b5771b8b4885c51c3b0d3e0d59ef5c Mon Sep 17 00:00:00 2001 From: Gisle Vanem Date: Fri, 21 Jul 2006 06:50:39 +0000 Subject: Constify some arguments in Curl_connecthost() and singleipconnect(). --- lib/connect.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index a24a12178..95fdf8119 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -109,7 +109,7 @@ static bool verifyconnect(curl_socket_t sockfd, int *error); static curl_socket_t singleipconnect(struct connectdata *conn, - Curl_addrinfo *ai, /* start connecting to this */ + const Curl_addrinfo *ai, /* start connecting to this */ long timeout_ms, bool *connected); @@ -676,7 +676,7 @@ static void nosigpipe(struct connectdata *conn, having connected if used from the multi interface. */ static curl_socket_t singleipconnect(struct connectdata *conn, - Curl_addrinfo *ai, + const Curl_addrinfo *ai, long timeout_ms, bool *connected) { @@ -778,7 +778,7 @@ singleipconnect(struct connectdata *conn, */ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ - struct Curl_dns_entry *remotehost, /* use this one */ + const struct Curl_dns_entry *remotehost, /* use this one */ curl_socket_t *sockconn, /* the connected socket */ Curl_addrinfo **addr, /* the one we used */ bool *connected) /* really connected? */ -- cgit v1.2.1 From 5acadc9cd7a1ff40ffa8d57214c90d8c788b2b03 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 29 Aug 2006 14:39:33 +0000 Subject: David McCreedy added CURLOPT_SOCKOPTFUNCTION and CURLOPT_SOCKOPTDATA to allow applications to set their own socket options. --- lib/connect.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 95fdf8119..4e7f4f8ea 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -702,6 +702,17 @@ singleipconnect(struct connectdata *conn, nosigpipe(conn, sockfd); + if(data->set.fsockopt) { + /* activate callback for setting socket options */ + error = data->set.fsockopt(data->set.sockopt_client, + sockfd, + CURLSOCKTYPE_IPCXN); + if (error) { + sclose(sockfd); /* close the socket and bail out */ + return CURL_SOCKET_BAD; + } + } + /* possibly bind the local end to an IP, interface or port */ res = bindlocal(conn, sockfd); if(res) { -- cgit v1.2.1 From 59cf6fd4f058917839a407f5a206f5f1c1a004a6 Mon Sep 17 00:00:00 2001 From: Gisle Vanem Date: Tue, 29 Aug 2006 18:45:55 +0000 Subject: Watcom lacks . --- lib/connect.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 4e7f4f8ea..d28f1f094 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -25,7 +25,9 @@ #ifndef WIN32 /* headers for non-win32 */ +#ifndef __WATCOMC__ #include +#endif #ifdef HAVE_SYS_TYPES_H #include #endif -- cgit v1.2.1 From c7aae1030004da71c7c046fd6af259f91bbfa991 Mon Sep 17 00:00:00 2001 From: Gisle Vanem Date: Wed, 30 Aug 2006 16:17:06 +0000 Subject: Removed "#ifndef__WATCOMC__". Use "#ifdef HAVE_SYS_TIME_H" instead. --- lib/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index d28f1f094..17dddaf87 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -25,7 +25,7 @@ #ifndef WIN32 /* headers for non-win32 */ -#ifndef __WATCOMC__ +#ifdef HAVE_SYS_TIME_H #include #endif #ifdef HAVE_SYS_TYPES_H -- cgit v1.2.1 From 5df4be11657fc49d74e1e6b39c0003f7cf2f3772 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Wed, 18 Oct 2006 21:05:40 +0000 Subject: Check for USE_WINSOCK instead of WIN32 where the check was done to verify winsock API availability. --- lib/connect.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 17dddaf87..1ffb98b37 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -84,7 +84,7 @@ #define FALSE 0 #endif -#ifdef WIN32 +#ifdef USE_WINSOCK #define EINPROGRESS WSAEINPROGRESS #define EWOULDBLOCK WSAEWOULDBLOCK #define EISCONN WSAEISCONN @@ -121,7 +121,7 @@ singleipconnect(struct connectdata *conn, */ int Curl_sockerrno(void) { -#ifdef WIN32 +#ifdef USE_WINSOCK return (int)WSAGetLastError(); #else return errno; -- cgit v1.2.1 From ebee2e323d42e7ef4017fcf99e67e02b083d8002 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 22 Dec 2006 13:30:54 +0000 Subject: - David McCreedy fixed a bad call to getsockname() that wrongly used a size_t variable to point to when it should be a socklen_t. --- lib/connect.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 1ffb98b37..2b3897204 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -384,11 +384,10 @@ static CURLcode bindlocal(struct connectdata *conn, if( bind(sockfd, sock, socksize) >= 0) { /* we succeeded to bind */ struct Curl_sockaddr_storage add; - size_t size; + socklen_t size; size = sizeof(add); - if(getsockname(sockfd, (struct sockaddr *) &add, - (socklen_t *)&size)<0) { + if(getsockname(sockfd, (struct sockaddr *) &add, &size) < 0) { failf(data, "getsockname() failed"); return CURLE_HTTP_PORT_FAILED; } -- cgit v1.2.1 From 91386937ff120d11f7bf24dc487f00751362a61c Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 5 Feb 2007 22:51:32 +0000 Subject: - Michael Wallner provided a patch that adds support for CURLOPT_TIMEOUT_MS and CURLOPT_CONNECTTIMEOUT_MS that, as their names should hint, do the timeouts with millisecond resolution instead. The only restriction to that is the alarm() (sometimes) used to abort name resolves as that uses full seconds. I fixed the FTP response timeout part of the patch. Internally we now count and keep the timeouts in milliseconds but it also means we multiply set timeouts with 1000. The effect of this is that no timeout can be set to more than 2^31 milliseconds (on 32 bit systems), which equals 24.86 days. We probably couldn't before either since the code did *1000 on the timeout values on several places already. --- lib/connect.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 2b3897204..37db6e228 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2006, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2007, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -558,15 +558,15 @@ CURLcode Curl_is_connected(struct connectdata *conn, /* subtract the most strict timeout of the ones */ if(data->set.timeout && data->set.connecttimeout) { if (data->set.timeout < data->set.connecttimeout) - allow_total = allow = data->set.timeout*1000; + allow_total = allow = data->set.timeout; else - allow = data->set.connecttimeout*1000; + allow = data->set.connecttimeout; } else if(data->set.timeout) { - allow_total = allow = data->set.timeout*1000; + allow_total = allow = data->set.timeout; } else if(data->set.connecttimeout) { - allow = data->set.connecttimeout*1000; + allow = data->set.connecttimeout; } if(has_passed > allow ) { @@ -826,14 +826,14 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ /* get the most strict timeout of the ones converted to milliseconds */ if(data->set.timeout && data->set.connecttimeout) { if (data->set.timeout < data->set.connecttimeout) - timeout_ms = data->set.timeout*1000; + timeout_ms = data->set.timeout; else - timeout_ms = data->set.connecttimeout*1000; + timeout_ms = data->set.connecttimeout; } else if(data->set.timeout) - timeout_ms = data->set.timeout*1000; + timeout_ms = data->set.timeout; else - timeout_ms = data->set.connecttimeout*1000; + timeout_ms = data->set.connecttimeout; /* subtract the passed time */ timeout_ms -= has_passed; -- cgit v1.2.1 From a1d598399146984c99baa46db148e87c75261033 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Fri, 16 Feb 2007 18:19:35 +0000 Subject: use macros ERRNO, SET_ERRNO(), SOCKERRNO and SET_SOCKERRNO() for errno handling --- lib/connect.c | 29 ++++++++--------------------- 1 file changed, 8 insertions(+), 21 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 37db6e228..464b59098 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -115,19 +115,6 @@ singleipconnect(struct connectdata *conn, long timeout_ms, bool *connected); -/* - * Curl_sockerrno() returns the *socket-related* errno (or equivalent) on this - * platform to hide platform specific for the function that calls this. - */ -int Curl_sockerrno(void) -{ -#ifdef USE_WINSOCK - return (int)WSAGetLastError(); -#else - return errno; -#endif -} - /* * Curl_nonblock() set the given socket to either blocking or non-blocking * mode based on the 'nonblock' boolean argument. This function is highly @@ -332,7 +319,7 @@ static CURLcode bindlocal(struct connectdata *conn, if (setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, data->set.device, strlen(data->set.device)+1) != 0) { /* printf("Failed to BINDTODEVICE, socket: %d device: %s error: %s\n", - sockfd, data->set.device, Curl_strerror(Curl_sockerrno())); */ + sockfd, data->set.device, Curl_strerror(SOCKERRNO)); */ infof(data, "SO_BINDTODEVICE %s failed\n", data->set.device); /* This is typically "errno 1, error: Operation not permitted" if @@ -409,7 +396,7 @@ static CURLcode bindlocal(struct connectdata *conn, break; } while(1); - data->state.os_errno = Curl_sockerrno(); + data->state.os_errno = SOCKERRNO; failf(data, "bind failure: %s", Curl_strerror(conn, data->state.os_errno)); return CURLE_HTTP_PORT_FAILED; @@ -453,7 +440,7 @@ static bool verifyconnect(curl_socket_t sockfd, int *error) if( -1 == getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *)&err, &errSize)) - err = Curl_sockerrno(); + err = SOCKERRNO; #ifdef _WIN32_WCE /* Always returns this error, bug in CE? */ @@ -472,7 +459,7 @@ static bool verifyconnect(curl_socket_t sockfd, int *error) #else (void)sockfd; if (error) - *error = Curl_sockerrno(); + *error = SOCKERRNO; #endif return rc; } @@ -613,7 +600,7 @@ CURLcode Curl_is_connected(struct connectdata *conn, infof(data, "Connection failed\n"); if(trynextip(conn, sockindex, connected)) { - error = Curl_sockerrno(); + error = SOCKERRNO; data->state.os_errno = error; failf(data, "Failed connect to %s:%d; %s", conn->host.name, conn->port, Curl_strerror(conn,error)); @@ -645,7 +632,7 @@ static void tcpnodelay(struct connectdata *conn, if(setsockopt(sockfd, proto, TCP_NODELAY, (void *)&onoff, sizeof(onoff)) < 0) infof(data, "Could not set TCP_NODELAY: %s\n", - Curl_strerror(conn, Curl_sockerrno())); + Curl_strerror(conn, SOCKERRNO)); else infof(data,"TCP_NODELAY set\n"); #else @@ -667,7 +654,7 @@ static void nosigpipe(struct connectdata *conn, if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff, sizeof(onoff)) < 0) infof(data, "Could not set SO_NOSIGPIPE: %s\n", - Curl_strerror(conn, Curl_sockerrno())); + Curl_strerror(conn, SOCKERRNO)); } #else #define nosigpipe(x,y) @@ -731,7 +718,7 @@ singleipconnect(struct connectdata *conn, rc = 0; if(-1 == rc) { - error = Curl_sockerrno(); + error = SOCKERRNO; switch (error) { case EINPROGRESS: -- cgit v1.2.1 From d9bf55570b4abbe9ed0058091d567e99ebff0973 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Sat, 17 Feb 2007 13:51:24 +0000 Subject: Move portable error number symbolic name definitions to setup_once.h --- lib/connect.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 464b59098..5be0df27e 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -84,14 +84,6 @@ #define FALSE 0 #endif -#ifdef USE_WINSOCK -#define EINPROGRESS WSAEINPROGRESS -#define EWOULDBLOCK WSAEWOULDBLOCK -#define EISCONN WSAEISCONN -#define ENOTSOCK WSAENOTSOCK -#define ECONNREFUSED WSAECONNREFUSED -#endif - #include "urldata.h" #include "sendf.h" #include "if2ip.h" -- cgit v1.2.1 From 3a634a273a7bff3d219883f572db786e2c1004b1 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Wed, 21 Feb 2007 19:03:20 +0000 Subject: curlassert macro replaced with DEBUGASSERT macro defined in setup_once.h --- lib/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 5be0df27e..2b8e11ff8 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -527,7 +527,7 @@ CURLcode Curl_is_connected(struct connectdata *conn, long allow_total = 0; long has_passed; - curlassert(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET); + DEBUGASSERT(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET); *connected = FALSE; /* a very negative world view is best */ -- cgit v1.2.1 From 69565afab0be081211df57a245a222cbd3e43ed3 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Thu, 22 Feb 2007 02:51:54 +0000 Subject: Check for stdbool.h at configuration stage, and include it if available. Check for lowercase 'bool' type at configuration stage. If not available provide a suitable replacement with a type definition of 'unsigned char' in setup_once.h Move definitions of TRUE and FALSE to setup_once.h --- lib/connect.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 2b8e11ff8..14e2ff038 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -79,11 +79,6 @@ #include #include -#ifndef TRUE -#define TRUE 1 -#define FALSE 0 -#endif - #include "urldata.h" #include "sendf.h" #include "if2ip.h" @@ -122,7 +117,7 @@ int Curl_nonblock(curl_socket_t sockfd, /* operate on this */ int flags; flags = fcntl(sockfd, F_GETFL, 0); - if (TRUE == nonblock) + if (FALSE != nonblock) return fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); else return fcntl(sockfd, F_SETFL, flags & (~O_NONBLOCK)); -- cgit v1.2.1 From c514a2a89aa1c1e06b70405eedb4e1f70b27fd10 Mon Sep 17 00:00:00 2001 From: Gisle Vanem Date: Mon, 26 Feb 2007 04:24:26 +0000 Subject: Removed inclusion of and in .c-files since they're already included through "setup.h". --- lib/connect.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 14e2ff038..a18a335af 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -28,9 +28,6 @@ #ifdef HAVE_SYS_TIME_H #include #endif -#ifdef HAVE_SYS_TYPES_H -#include -#endif #ifdef HAVE_SYS_SOCKET_H #include #endif @@ -59,9 +56,9 @@ #include #endif #ifdef HAVE_STDLIB_H -#include /* required for free() prototype, without it, this crashes - on macos 68K */ -#endif +#include /* required for free() prototype, without it, this crashes */ +#endif /* on macos 68K */ + #if (defined(HAVE_FIONBIO) && defined(__NOVELL_LIBC__)) #include #endif @@ -74,7 +71,8 @@ #include #endif -#endif +#endif /* !WIN32 */ + #include #include #include -- cgit v1.2.1 From 1e55ed5c7d04c47fc931719fea05314f126aa974 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 9 Mar 2007 22:48:07 +0000 Subject: - Robert Iakobashvili fixed CURLOPT_INTERFACE for IPv6. --- lib/connect.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index a18a335af..d98569fce 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -233,7 +233,9 @@ static CURLcode bindlocal(struct connectdata *conn, char myhost[256] = ""; in_addr_t in; int rc; + char ipv6_addr[16]; bool was_iface = FALSE; + int in6 = -1; /* First check if the given name is an IP address */ in=inet_addr(data->set.device); @@ -314,7 +316,11 @@ static CURLcode bindlocal(struct connectdata *conn, #endif in=inet_addr(myhost); - if (CURL_INADDR_NONE == in) { + +#ifdef ENABLE_IPV6 + in6 = inet_pton (AF_INET6, myhost, (void *)&ipv6_addr); +#endif + if (CURL_INADDR_NONE == in && -1 == in6) { failf(data,"couldn't find my own IP address (%s)", myhost); return CURLE_HTTP_PORT_FAILED; } /* end of inet_addr */ -- cgit v1.2.1 From 40e9e40cb41f3755b7a07c7d73cac59a6633f121 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Sun, 11 Mar 2007 00:26:01 +0000 Subject: fix compiler warning: unused variable --- lib/connect.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index d98569fce..d105ee03d 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -216,6 +216,9 @@ int waitconnect(curl_socket_t sockfd, /* socket */ static CURLcode bindlocal(struct connectdata *conn, curl_socket_t sockfd) { +#ifdef ENABLE_IPV6 + char ipv6_addr[16]; +#endif struct SessionHandle *data = conn->data; struct sockaddr_in me; struct sockaddr *sock = NULL; /* bind to this address */ @@ -233,7 +236,6 @@ static CURLcode bindlocal(struct connectdata *conn, char myhost[256] = ""; in_addr_t in; int rc; - char ipv6_addr[16]; bool was_iface = FALSE; int in6 = -1; -- cgit v1.2.1 From 0188493d54711d61ba7227f37fe87afbdb4426c7 Mon Sep 17 00:00:00 2001 From: Gisle Vanem Date: Tue, 13 Mar 2007 12:52:28 +0000 Subject: Use Curl_inet_pton() instead of inet_pton(). --- lib/connect.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index d105ee03d..147b73eaa 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -88,6 +88,7 @@ #include "multiif.h" #include "sockaddr.h" /* required for Curl_sockaddr_storage */ #include "inet_ntop.h" +#include "inet_pton.h" /* The last #include file should be: */ #include "memdebug.h" @@ -320,7 +321,7 @@ static CURLcode bindlocal(struct connectdata *conn, in=inet_addr(myhost); #ifdef ENABLE_IPV6 - in6 = inet_pton (AF_INET6, myhost, (void *)&ipv6_addr); + in6 = Curl_inet_pton (AF_INET6, myhost, (void *)&ipv6_addr); #endif if (CURL_INADDR_NONE == in && -1 == in6) { failf(data,"couldn't find my own IP address (%s)", myhost); -- cgit v1.2.1 From fba4cd0e625cdba3561b3530317ba87ae348aeaf Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Mon, 26 Mar 2007 23:23:46 +0000 Subject: Internal function Curl_select() renamed to Curl_socket_ready() --- lib/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 147b73eaa..95791cf5d 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -197,7 +197,7 @@ int waitconnect(curl_socket_t sockfd, /* socket */ #endif /* now select() until we get connect or timeout */ - rc = Curl_select(CURL_SOCKET_BAD, sockfd, (int)timeout_msec); + rc = Curl_socket_ready(CURL_SOCKET_BAD, sockfd, (int)timeout_msec); if(-1 == rc) /* error, no connect here, try next */ return WAITCONN_SELECT_ERROR; -- cgit v1.2.1 From 76627b322e369c209c60863b9e1f05e3ce02953d Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 16 Apr 2007 16:34:08 +0000 Subject: - Robert Iakobashvil added curl_multi_socket_action() to libcurl, which is a function that deprecates the curl_multi_socket() function. Using the new function the application tell libcurl what action that was found in the socket that it passes in. This gives a significant performance boost as it allows libcurl to avoid a call to poll()/select() for every call to curl_multi_socket*(). --- lib/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 95791cf5d..dd67638ff 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -206,7 +206,7 @@ int waitconnect(curl_socket_t sockfd, /* socket */ /* timeout, no connect today */ return WAITCONN_TIMEOUT; - if(rc & CSELECT_ERR) + if(rc & CURL_CSELECT_ERR) /* error condition caught */ return WAITCONN_FDSET_ERROR; -- cgit v1.2.1 From b0e909329e63f7d4a6f50f536c41082ba8c1619d Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Thu, 19 Apr 2007 20:16:28 +0000 Subject: fix comment and line spacing --- lib/connect.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index dd67638ff..57e203657 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -432,16 +432,15 @@ static bool verifyconnect(curl_socket_t sockfd, int *error) #endif - if( -1 == getsockopt(sockfd, SOL_SOCKET, SO_ERROR, - (void *)&err, &errSize)) + if (0 != getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *)&err, &errSize)) err = SOCKERRNO; - #ifdef _WIN32_WCE - /* Always returns this error, bug in CE? */ - if(WSAENOPROTOOPT==err) - err=0; + /* Old WinCE versions don't support SO_ERROR */ + if (WSAENOPROTOOPT == err) { + SET_SOCKERRNO(0); + err = 0; + } #endif - if ((0 == err) || (EISCONN == err)) /* we are connected, awesome! */ rc = TRUE; -- cgit v1.2.1 From 3616912d227ad06512b44af67e38a62e1d968c7c Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Sun, 22 Apr 2007 18:17:46 +0000 Subject: Avoid an unnecessary call to gettimeofday() when using custom timeout values. --- lib/connect.c | 48 ++++++++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 22 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 57e203657..0aeaf7959 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -781,6 +781,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ int num_addr; Curl_addrinfo *ai; Curl_addrinfo *curr_addr; + int timeout_set = 0; struct timeval after; struct timeval before = Curl_tvnow(); @@ -788,36 +789,39 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ /************************************************************* * Figure out what maximum time we have left *************************************************************/ - long timeout_ms= DEFAULT_CONNECT_TIMEOUT; + long timeout_ms; long timeout_per_addr; *connected = FALSE; /* default to not connected */ - if(data->set.timeout || data->set.connecttimeout) { - long has_passed; - - /* Evaluate in milliseconds how much time that has passed */ - has_passed = Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle); - -#ifndef min -#define min(a, b) ((a) < (b) ? (a) : (b)) -#endif - - /* get the most strict timeout of the ones converted to milliseconds */ - if(data->set.timeout && data->set.connecttimeout) { - if (data->set.timeout < data->set.connecttimeout) - timeout_ms = data->set.timeout; - else - timeout_ms = data->set.connecttimeout; - } - else if(data->set.timeout) + /* if a timeout is set, use the most restrictive one */ + + if (data->set.timeout > 0) + timeout_set += 1; + if (data->set.connecttimeout > 0) + timeout_set += 2; + + switch (timeout_set) { + case 1: + timeout_ms = data->set.timeout; + break; + case 2: + timeout_ms = data->set.connecttimeout; + break; + case 3: + if (data->set.timeout < data->set.connecttimeout) timeout_ms = data->set.timeout; else timeout_ms = data->set.connecttimeout; + break; + default: + timeout_ms = DEFAULT_CONNECT_TIMEOUT; + break; + } - /* subtract the passed time */ - timeout_ms -= has_passed; - + if (timeout_set > 0) { + /* if a timeout was already set, substract elapsed time */ + timeout_ms -= Curl_tvdiff(before, data->progress.t_startsingle); if(timeout_ms < 0) { /* a precaution, no need to continue if time already is up */ failf(data, "Connection time-out"); -- cgit v1.2.1 From afdfa4bed24c9f937bc49807c6d547ac3a158525 Mon Sep 17 00:00:00 2001 From: Gunter Knauf Date: Sat, 30 Jun 2007 20:08:13 +0000 Subject: minor patches to enable building for NetWare CLIB. sent by Dmitry Mityugov. --- lib/connect.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 0aeaf7959..8fbdd8661 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -59,10 +59,13 @@ #include /* required for free() prototype, without it, this crashes */ #endif /* on macos 68K */ -#if (defined(HAVE_FIONBIO) && defined(__NOVELL_LIBC__)) +#if (defined(HAVE_FIONBIO) && defined(NETWARE)) #include #endif -#if (defined(NETWARE) && defined(__NOVELL_LIBC__)) +#ifdef NETWARE +#ifndef __NOVELL_LIBC__ +NETDB_DEFINE_CONTEXT +#endif #undef in_addr_t #define in_addr_t unsigned long #endif -- cgit v1.2.1 From c0095d6dd904c6ad82fe834cbef790ca4d231944 Mon Sep 17 00:00:00 2001 From: Gunter Knauf Date: Wed, 11 Jul 2007 21:47:31 +0000 Subject: removed now obsolete NETDB_DEFINE_CONTEXT macro calls. --- lib/connect.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 8fbdd8661..ffce3dad5 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -63,9 +63,6 @@ #include #endif #ifdef NETWARE -#ifndef __NOVELL_LIBC__ -NETDB_DEFINE_CONTEXT -#endif #undef in_addr_t #define in_addr_t unsigned long #endif -- cgit v1.2.1 From cf5378b366258ab7ec9cbd03eef26b852e454745 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 13 Jul 2007 20:04:53 +0000 Subject: Daniel Cater made libcurl build with CURL_NO_OLDIES defined (which doesn't define the symbols for backwards source compatibility) --- lib/connect.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index ffce3dad5..65b2878b3 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -288,7 +288,7 @@ static CURLcode bindlocal(struct connectdata *conn, sizeof(hostent_buf)); */ failf(data, "Couldn't bind to '%s'", data->set.device); - return CURLE_HTTP_PORT_FAILED; + return CURLE_INTERFACE_FAILED; } infof(data, "Bind local address to %s\n", myhost); @@ -325,7 +325,7 @@ static CURLcode bindlocal(struct connectdata *conn, #endif if (CURL_INADDR_NONE == in && -1 == in6) { failf(data,"couldn't find my own IP address (%s)", myhost); - return CURLE_HTTP_PORT_FAILED; + return CURLE_INTERFACE_FAILED; } /* end of inet_addr */ if ( h ) { @@ -334,7 +334,7 @@ static CURLcode bindlocal(struct connectdata *conn, socksize = addr->ai_addrlen; } else - return CURLE_HTTP_PORT_FAILED; + return CURLE_INTERFACE_FAILED; } else if(port) { @@ -370,7 +370,7 @@ static CURLcode bindlocal(struct connectdata *conn, size = sizeof(add); if(getsockname(sockfd, (struct sockaddr *) &add, &size) < 0) { failf(data, "getsockname() failed"); - return CURLE_HTTP_PORT_FAILED; + return CURLE_INTERFACE_FAILED; } /* We re-use/clobber the port variable here below */ if(((struct sockaddr *)&add)->sa_family == AF_INET) @@ -393,7 +393,7 @@ static CURLcode bindlocal(struct connectdata *conn, data->state.os_errno = SOCKERRNO; failf(data, "bind failure: %s", Curl_strerror(conn, data->state.os_errno)); - return CURLE_HTTP_PORT_FAILED; + return CURLE_INTERFACE_FAILED; } -- cgit v1.2.1 From 46c699c483f3e453fa6b0e8f69846ecce95a1a0f Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 13 Jul 2007 20:17:35 +0000 Subject: Colin Hogben filed bug report #1750274 (http://curl.haxx.se/bug/view.cgi?id=1750274) and submitted a patch for the case where libcurl did a connect attempt to a non-listening port and didn't provide a human readable error string back. --- lib/connect.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 65b2878b3..d608e1e2e 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -577,6 +577,8 @@ CURLcode Curl_is_connected(struct connectdata *conn, data->state.os_errno = error; infof(data, "Connection failed\n"); if(trynextip(conn, sockindex, connected)) { + failf(data, "Failed connect to %s:%d; %s", + conn->host.name, conn->port, Curl_strerror(conn, error)); code = CURLE_COULDNT_CONNECT; } } @@ -596,7 +598,7 @@ CURLcode Curl_is_connected(struct connectdata *conn, error = SOCKERRNO; data->state.os_errno = error; failf(data, "Failed connect to %s:%d; %s", - conn->host.name, conn->port, Curl_strerror(conn,error)); + conn->host.name, conn->port, Curl_strerror(conn, error)); code = CURLE_COULDNT_CONNECT; } } -- cgit v1.2.1 From 50c10aa5bf545eedfdbe561116656b6ec12654cd Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 1 Aug 2007 21:20:01 +0000 Subject: Patrick Monnerat and I modified libcurl so that now it *copies* all strings passed to it with curl_easy_setopt()! Previously it has always just refered to the data, forcing the user to keep the data around until libcurl is done with it. That is now history and libcurl will instead clone the given strings and keep private copies. --- lib/connect.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index d608e1e2e..634595766 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -228,11 +228,12 @@ static CURLcode bindlocal(struct connectdata *conn, "random" */ /* how many port numbers to try to bind to, increasing one at a time */ int portnum = data->set.localportrange; + const char *dev = data->set.str[STRING_DEVICE]; /************************************************************* * Select device to bind socket to *************************************************************/ - if (data->set.device && (strlen(data->set.device)<255) ) { + if (dev && (strlen(dev)<255) ) { struct Curl_dns_entry *h=NULL; char myhost[256] = ""; in_addr_t in; @@ -241,10 +242,10 @@ static CURLcode bindlocal(struct connectdata *conn, int in6 = -1; /* First check if the given name is an IP address */ - in=inet_addr(data->set.device); + in=inet_addr(dev); if((in == CURL_INADDR_NONE) && - Curl_if2ip(data->set.device, myhost, sizeof(myhost))) { + Curl_if2ip(dev, myhost, sizeof(myhost))) { /* * We now have the numerical IPv4-style x.y.z.w in the 'myhost' buffer */ @@ -263,7 +264,7 @@ static CURLcode bindlocal(struct connectdata *conn, * This was not an interface, resolve the name as a host name * or IP number */ - rc = Curl_resolv(conn, data->set.device, 0, &h); + rc = Curl_resolv(conn, dev, 0, &h); if(rc == CURLRESOLV_PENDING) (void)Curl_wait_for_resolv(conn, &h); @@ -275,7 +276,7 @@ static CURLcode bindlocal(struct connectdata *conn, myhost, sizeof myhost); else /* we know data->set.device is shorter than the myhost array */ - strcpy(myhost, data->set.device); + strcpy(myhost, dev); Curl_resolv_unlock(data, h); } } @@ -287,7 +288,7 @@ static CURLcode bindlocal(struct connectdata *conn, hostent_buf, sizeof(hostent_buf)); */ - failf(data, "Couldn't bind to '%s'", data->set.device); + failf(data, "Couldn't bind to '%s'", dev); return CURLE_INTERFACE_FAILED; } @@ -307,11 +308,10 @@ static CURLcode bindlocal(struct connectdata *conn, * hostname or ip address. */ if (setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, - data->set.device, strlen(data->set.device)+1) != 0) { + dev, strlen(dev)+1) != 0) { /* printf("Failed to BINDTODEVICE, socket: %d device: %s error: %s\n", - sockfd, data->set.device, Curl_strerror(SOCKERRNO)); */ - infof(data, "SO_BINDTODEVICE %s failed\n", - data->set.device); + sockfd, dev, Curl_strerror(SOCKERRNO)); */ + infof(data, "SO_BINDTODEVICE %s failed\n", dev); /* This is typically "errno 1, error: Operation not permitted" if you're not running as root or another suitable privileged user */ } -- cgit v1.2.1 From 188b08ca557a73aacf9b7b877ebb1e88aa06f8a9 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 2 Aug 2007 14:42:16 +0000 Subject: Patrick Monnerat's cleanup fix after my alloc-strings commit --- lib/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 634595766..9877ae8f4 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -242,7 +242,7 @@ static CURLcode bindlocal(struct connectdata *conn, int in6 = -1; /* First check if the given name is an IP address */ - in=inet_addr(dev); + in=inet_addr((char *) dev); if((in == CURL_INADDR_NONE) && Curl_if2ip(dev, myhost, sizeof(myhost))) { -- cgit v1.2.1 From 9f44a95522162c0f4a61093efe1bf1f58b087358 Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Thu, 30 Aug 2007 20:34:57 +0000 Subject: Renamed several libcurl error codes and options to make them more general and allow reuse by multiple protocols. Several unused error codes were removed. In all cases, macros were added to preserve source (and binary) compatibility with the old names. These macros are subject to removal at a future date, but probably not before 2009. An application can be tested to see if it is using any obsolete code by compiling it with the CURL_NO_OLDIES macro defined. Documented some newer error codes in libcurl-error(3) --- lib/connect.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 9877ae8f4..cfdf5680a 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -552,7 +552,7 @@ CURLcode Curl_is_connected(struct connectdata *conn, if(has_passed > allow ) { /* time-out, bail out, go home */ failf(data, "Connection time-out after %ld ms", has_passed); - return CURLE_OPERATION_TIMEOUTED; + return CURLE_OPERATION_TIMEDOUT; } if(conn->bits.tcpconnect) { /* we are connected already! */ @@ -827,7 +827,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ if(timeout_ms < 0) { /* a precaution, no need to continue if time already is up */ failf(data, "Connection time-out"); - return CURLE_OPERATION_TIMEOUTED; + return CURLE_OPERATION_TIMEDOUT; } } Curl_expire(data, timeout_ms); @@ -863,7 +863,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ timeout_ms -= Curl_tvdiff(after, before); if(timeout_ms < 0) { failf(data, "connect() timed out!"); - return CURLE_OPERATION_TIMEOUTED; + return CURLE_OPERATION_TIMEDOUT; } before = after; } /* end of connect-to-each-address loop */ -- cgit v1.2.1 From 8147c3659d427110fe7febccaa2f60d4ab1a5cc7 Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Wed, 5 Sep 2007 22:01:57 +0000 Subject: Minix doesn't support getsockopt on UDP sockets or send/recv on TCP sockets. --- lib/connect.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index cfdf5680a..c8c82a1b7 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -440,6 +440,13 @@ static bool verifyconnect(curl_socket_t sockfd, int *error) SET_SOCKERRNO(0); err = 0; } +#endif +#ifdef __minix + /* Minix 3.1.x doesn't support getsockopt on UDP sockets */ + if (EBADIOCTL == err) { + SET_SOCKERRNO(0); + err = 0; + } #endif if ((0 == err) || (EISCONN == err)) /* we are connected, awesome! */ -- cgit v1.2.1 From ce1cfcb7a6a0956c3101f5a6eb20961024e55d84 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 3 Oct 2007 08:45:00 +0000 Subject: Alexey Pesternikov introduced CURLOPT_OPENSOCKETFUNCTION and CURLOPT_OPENSOCKETDATA to set a callback that allows an application to replace the socket() call used by libcurl. It basically allows the app to change address, protocol or whatever of the socket. (I also did some whitespace indent/cleanups in lib/url.c which kind of hides some of these changes, sorry for mixing those in.) --- lib/connect.c | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index c8c82a1b7..b0615661f 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -677,14 +677,41 @@ singleipconnect(struct connectdata *conn, struct SessionHandle *data = conn->data; curl_socket_t sockfd; CURLcode res; - - sockfd = socket(ai->ai_family, conn->socktype, ai->ai_protocol); + /* + * Curl_sockaddr_storage, which is basically sockaddr_storage has a space + * for a largest possible struct sockaddr only. We should add some space for + * the other fields we are using. Hence the addr_storage size math. + */ + char addr_storage[sizeof(struct Curl_sockaddr)- + sizeof(struct sockaddr)+ + sizeof(struct Curl_sockaddr_storage)]; + struct Curl_sockaddr* addr=(struct Curl_sockaddr*)&addr_storage; + + addr->family=ai->ai_family; + addr->socktype=conn->socktype; + addr->protocol=ai->ai_protocol; + addr->addrlen=(ai->ai_addrlen<=sizeof(struct Curl_sockaddr_storage))? + ai->ai_addrlen:sizeof(struct Curl_sockaddr_storage); + memcpy(&addr->addr, ai->ai_addr, addr->addrlen); + + /* optionally use callback to get the socket */ + sockfd = (data->set.fopensocket)? + data->set.fopensocket(data->set.opensocket_client, CURLSOCKTYPE_IPCXN, + &addr): + socket(addr->family, addr->socktype, addr->protocol); if (sockfd == CURL_SOCKET_BAD) return CURL_SOCKET_BAD; *connected = FALSE; /* default is not connected */ - Curl_printable_address(ai, addr_buf, sizeof(addr_buf)); + /* FIXME: do we have Curl_printable_address-like with struct sockaddr* as + argument? */ + const void *iptoprint = &((const struct sockaddr_in*)(&addr->addr))->sin_addr; +#ifdef ENABLE_IPV6 + if(addr->family==AF_INET6) + iptoprint= &((const struct sockaddr_in6*)(&addr->addr))->sin6_addr; +#endif + Curl_inet_ntop(addr->family, iptoprint, addr_buf, sizeof(addr_buf)); infof(data, " Trying %s... ", addr_buf); if(data->set.tcp_nodelay) @@ -715,7 +742,7 @@ singleipconnect(struct connectdata *conn, /* Connect TCP sockets, bind UDP */ if(conn->socktype == SOCK_STREAM) - rc = connect(sockfd, ai->ai_addr, ai->ai_addrlen); + rc = connect(sockfd, &addr->addr, addr->addrlen); else rc = 0; @@ -779,7 +806,7 @@ singleipconnect(struct connectdata *conn, */ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ - const struct Curl_dns_entry *remotehost, /* use this one */ + const struct Curl_dns_entry *remotehost, curl_socket_t *sockconn, /* the connected socket */ Curl_addrinfo **addr, /* the one we used */ bool *connected) /* really connected? */ -- cgit v1.2.1 From 4bf28cb904212e37a31403a21c3d9db1f921367d Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 3 Oct 2007 08:58:40 +0000 Subject: exported symbols must use lowercase "curl_", and I also fixed two compiler warnings, one C99 thing and the bad pointer sent to the callback --- lib/connect.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index b0615661f..d386a1bc5 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -682,10 +682,11 @@ singleipconnect(struct connectdata *conn, * for a largest possible struct sockaddr only. We should add some space for * the other fields we are using. Hence the addr_storage size math. */ - char addr_storage[sizeof(struct Curl_sockaddr)- + char addr_storage[sizeof(struct curl_sockaddr)- sizeof(struct sockaddr)+ sizeof(struct Curl_sockaddr_storage)]; - struct Curl_sockaddr* addr=(struct Curl_sockaddr*)&addr_storage; + struct curl_sockaddr *addr=(struct curl_sockaddr*)&addr_storage; + const void *iptoprint; addr->family=ai->ai_family; addr->socktype=conn->socktype; @@ -697,7 +698,7 @@ singleipconnect(struct connectdata *conn, /* optionally use callback to get the socket */ sockfd = (data->set.fopensocket)? data->set.fopensocket(data->set.opensocket_client, CURLSOCKTYPE_IPCXN, - &addr): + addr): socket(addr->family, addr->socktype, addr->protocol); if (sockfd == CURL_SOCKET_BAD) return CURL_SOCKET_BAD; @@ -706,7 +707,7 @@ singleipconnect(struct connectdata *conn, /* FIXME: do we have Curl_printable_address-like with struct sockaddr* as argument? */ - const void *iptoprint = &((const struct sockaddr_in*)(&addr->addr))->sin_addr; + iptoprint = &((const struct sockaddr_in*)(&addr->addr))->sin_addr; #ifdef ENABLE_IPV6 if(addr->family==AF_INET6) iptoprint= &((const struct sockaddr_in6*)(&addr->addr))->sin6_addr; -- cgit v1.2.1 From 67d94514b0d1501832a52fd42db8f5a41151d7f5 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 4 Oct 2007 10:01:41 +0000 Subject: Kim Rinnewitz reported that --local-port didn't work with TFTP transfers. This happened because the tftp code always uncondionally did a bind() without caring if one already had been done and then it failed. I wrote a test case (1009) to verify this, but it is a bit error-prone since it will have to pick a fixed local port number and since the tests are run on so many different hosts in different situations I add it in disabled state. --- lib/connect.c | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index d386a1bc5..918602c2d 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -380,6 +380,7 @@ static CURLcode bindlocal(struct connectdata *conn, port = ntohs(((struct sockaddr_in6 *)&add)->sin6_port); #endif infof(data, "Local port: %d\n", port); + conn->bits.bound = TRUE; return CURLE_OK; } if(--portnum > 0) { -- cgit v1.2.1 From 85877dae9af9c47df2e3cd27c904013fe676b150 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Wed, 17 Oct 2007 00:10:00 +0000 Subject: Fix compiler warning: comparison between signed and unsigned --- lib/connect.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 918602c2d..1f4562a9a 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -692,8 +692,9 @@ singleipconnect(struct connectdata *conn, addr->family=ai->ai_family; addr->socktype=conn->socktype; addr->protocol=ai->ai_protocol; - addr->addrlen=(ai->ai_addrlen<=sizeof(struct Curl_sockaddr_storage))? - ai->ai_addrlen:sizeof(struct Curl_sockaddr_storage); + addr->addrlen = + (ai->ai_addrlen < (socklen_t)sizeof(struct Curl_sockaddr_storage)) ? + ai->ai_addrlen : (socklen_t)sizeof(struct Curl_sockaddr_storage); memcpy(&addr->addr, ai->ai_addr, addr->addrlen); /* optionally use callback to get the socket */ -- cgit v1.2.1 From 949073d44884203dcf0285a7c9f4ab477e6a0da9 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Wed, 17 Oct 2007 00:44:48 +0000 Subject: Fix compiler warning: signed and unsigned type in conditional expression --- lib/connect.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 1f4562a9a..2ab97eb8d 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -697,11 +697,12 @@ singleipconnect(struct connectdata *conn, ai->ai_addrlen : (socklen_t)sizeof(struct Curl_sockaddr_storage); memcpy(&addr->addr, ai->ai_addr, addr->addrlen); - /* optionally use callback to get the socket */ - sockfd = (data->set.fopensocket)? - data->set.fopensocket(data->set.opensocket_client, CURLSOCKTYPE_IPCXN, - addr): - socket(addr->family, addr->socktype, addr->protocol); + /* If set, use opensocket callback to get the socket */ + if(data->set.fopensocket) + sockfd = data->set.fopensocket(data->set.opensocket_client, + CURLSOCKTYPE_IPCXN, addr); + else + sockfd = socket(addr->family, addr->socktype, addr->protocol); if (sockfd == CURL_SOCKET_BAD) return CURL_SOCKET_BAD; -- cgit v1.2.1 From ad6e28073c985a42e8b15d2234baa7ef67ffcb35 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 5 Nov 2007 09:45:09 +0000 Subject: removed space after if and while before the parenthesis for better source code consistency --- lib/connect.c | 50 +++++++++++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 25 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 2ab97eb8d..fcfce7248 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -116,7 +116,7 @@ int Curl_nonblock(curl_socket_t sockfd, /* operate on this */ int flags; flags = fcntl(sockfd, F_GETFL, 0); - if (FALSE != nonblock) + if(FALSE != nonblock) return fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); else return fcntl(sockfd, F_SETFL, flags & (~O_NONBLOCK)); @@ -165,7 +165,7 @@ int Curl_nonblock(curl_socket_t sockfd, /* operate on this */ #define SETBLOCK 6 #endif -#if (SETBLOCK == 0) +#if(SETBLOCK == 0) #error "no non-blocking method was found/used/set" #endif } @@ -233,7 +233,7 @@ static CURLcode bindlocal(struct connectdata *conn, /************************************************************* * Select device to bind socket to *************************************************************/ - if (dev && (strlen(dev)<255) ) { + if(dev && (strlen(dev)<255) ) { struct Curl_dns_entry *h=NULL; char myhost[256] = ""; in_addr_t in; @@ -303,11 +303,11 @@ static CURLcode bindlocal(struct connectdata *conn, * interfaces to go out the external interface. * */ - if (was_iface) { + if(was_iface) { /* Only bind to the interface when specified as interface, not just as a * hostname or ip address. */ - if (setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, + if(setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, dev, strlen(dev)+1) != 0) { /* printf("Failed to BINDTODEVICE, socket: %d device: %s error: %s\n", sockfd, dev, Curl_strerror(SOCKERRNO)); */ @@ -323,12 +323,12 @@ static CURLcode bindlocal(struct connectdata *conn, #ifdef ENABLE_IPV6 in6 = Curl_inet_pton (AF_INET6, myhost, (void *)&ipv6_addr); #endif - if (CURL_INADDR_NONE == in && -1 == in6) { + if(CURL_INADDR_NONE == in && -1 == in6) { failf(data,"couldn't find my own IP address (%s)", myhost); return CURLE_INTERFACE_FAILED; } /* end of inet_addr */ - if ( h ) { + if( h ) { Curl_addrinfo *addr = h->addr; sock = addr->ai_addr; socksize = addr->ai_addrlen; @@ -433,33 +433,33 @@ static bool verifyconnect(curl_socket_t sockfd, int *error) #endif - if (0 != getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *)&err, &errSize)) + if(0 != getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *)&err, &errSize)) err = SOCKERRNO; #ifdef _WIN32_WCE /* Old WinCE versions don't support SO_ERROR */ - if (WSAENOPROTOOPT == err) { + if(WSAENOPROTOOPT == err) { SET_SOCKERRNO(0); err = 0; } #endif #ifdef __minix /* Minix 3.1.x doesn't support getsockopt on UDP sockets */ - if (EBADIOCTL == err) { + if(EBADIOCTL == err) { SET_SOCKERRNO(0); err = 0; } #endif - if ((0 == err) || (EISCONN == err)) + if((0 == err) || (EISCONN == err)) /* we are connected, awesome! */ rc = TRUE; else /* This wasn't a successful connect */ rc = FALSE; - if (error) + if(error) *error = err; #else (void)sockfd; - if (error) + if(error) *error = SOCKERRNO; #endif return rc; @@ -504,7 +504,7 @@ static bool trynextip(struct connectdata *conn, /* try the next address */ ai = conn->ip_addr->ai_next; - while (ai) { + while(ai) { sockfd = singleipconnect(conn, ai, 0L, connected); if(sockfd != CURL_SOCKET_BAD) { /* store the new socket descriptor */ @@ -545,7 +545,7 @@ CURLcode Curl_is_connected(struct connectdata *conn, /* subtract the most strict timeout of the ones */ if(data->set.timeout && data->set.connecttimeout) { - if (data->set.timeout < data->set.connecttimeout) + if(data->set.timeout < data->set.connecttimeout) allow_total = allow = data->set.timeout; else allow = data->set.connecttimeout; @@ -576,7 +576,7 @@ CURLcode Curl_is_connected(struct connectdata *conn, if(WAITCONN_CONNECTED == rc) { int error; - if (verifyconnect(sockfd, &error)) { + if(verifyconnect(sockfd, &error)) { /* we are connected, awesome! */ *connected = TRUE; return CURLE_OK; @@ -594,7 +594,7 @@ CURLcode Curl_is_connected(struct connectdata *conn, int error = 0; /* nope, not connected */ - if (WAITCONN_FDSET_ERROR == rc) { + if(WAITCONN_FDSET_ERROR == rc) { (void)verifyconnect(sockfd, &error); data->state.os_errno = error; infof(data, "%s\n",Curl_strerror(conn,error)); @@ -628,7 +628,7 @@ static void tcpnodelay(struct connectdata *conn, #ifdef HAVE_GETPROTOBYNAME struct protoent *pe = getprotobyname("tcp"); - if (pe) + if(pe) proto = pe->p_proto; #endif @@ -703,7 +703,7 @@ singleipconnect(struct connectdata *conn, CURLSOCKTYPE_IPCXN, addr); else sockfd = socket(addr->family, addr->socktype, addr->protocol); - if (sockfd == CURL_SOCKET_BAD) + if(sockfd == CURL_SOCKET_BAD) return CURL_SOCKET_BAD; *connected = FALSE; /* default is not connected */ @@ -728,7 +728,7 @@ singleipconnect(struct connectdata *conn, error = data->set.fsockopt(data->set.sockopt_client, sockfd, CURLSOCKTYPE_IPCXN); - if (error) { + if(error) { sclose(sockfd); /* close the socket and bail out */ return CURL_SOCKET_BAD; } @@ -836,9 +836,9 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ /* if a timeout is set, use the most restrictive one */ - if (data->set.timeout > 0) + if(data->set.timeout > 0) timeout_set += 1; - if (data->set.connecttimeout > 0) + if(data->set.connecttimeout > 0) timeout_set += 2; switch (timeout_set) { @@ -849,7 +849,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ timeout_ms = data->set.connecttimeout; break; case 3: - if (data->set.timeout < data->set.connecttimeout) + if(data->set.timeout < data->set.connecttimeout) timeout_ms = data->set.timeout; else timeout_ms = data->set.connecttimeout; @@ -859,7 +859,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ break; } - if (timeout_set > 0) { + if(timeout_set > 0) { /* if a timeout was already set, substract elapsed time */ timeout_ms -= Curl_tvdiff(before, data->progress.t_startsingle); if(timeout_ms < 0) { @@ -906,7 +906,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ before = after; } /* end of connect-to-each-address loop */ - if (sockfd == CURL_SOCKET_BAD) { + if(sockfd == CURL_SOCKET_BAD) { /* no good connect was made */ *sockconn = CURL_SOCKET_BAD; failf(data, "couldn't connect to host"); -- cgit v1.2.1 From 59b4bdf78d39b2fa9d13ca46f1c1de0e2b0bffe8 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Tue, 8 Jan 2008 01:05:50 +0000 Subject: Change typecast due to http://cool.haxx.se/cvs.cgi/curl/include/curl/curl.h.diff?r1=1.336&r2=1.337 --- lib/connect.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index fcfce7248..e9f9cf150 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2007, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2008, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -694,7 +694,7 @@ singleipconnect(struct connectdata *conn, addr->protocol=ai->ai_protocol; addr->addrlen = (ai->ai_addrlen < (socklen_t)sizeof(struct Curl_sockaddr_storage)) ? - ai->ai_addrlen : (socklen_t)sizeof(struct Curl_sockaddr_storage); + (unsigned int)ai->ai_addrlen : sizeof(struct Curl_sockaddr_storage); memcpy(&addr->addr, ai->ai_addr, addr->addrlen); /* If set, use opensocket callback to get the socket */ -- cgit v1.2.1 From 1b701c746f66b8fd5bf3017c36254dbde8456df2 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 7 Feb 2008 22:25:04 +0000 Subject: - Refactored a lot of timeout code into a few functions in an attempt to make them all use the same (hopefully correct) logic to make it less error-prone and easier to introduce library-wide where it should be used. --- lib/connect.c | 138 ++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 81 insertions(+), 57 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index e9f9cf150..393c85603 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -101,6 +101,66 @@ singleipconnect(struct connectdata *conn, long timeout_ms, bool *connected); +/* + * Curl_timeleft() returns the amount of milliseconds left allowed for the + * transfer/connection. If the value is negative, the timeout time has already + * elapsed. + * + * If 'nowp' is non-NULL, it points to the current time. + * 'duringconnect' is FALSE if not during a connect, as then of course the + * connect timeout is not taken into account! + */ +long Curl_timeleft(struct connectdata *conn, + struct timeval *nowp, + bool duringconnect) +{ + struct SessionHandle *data = conn->data; + int timeout_set = 0; + long timeout_ms = duringconnect?DEFAULT_CONNECT_TIMEOUT:0; + struct timeval now; + + /* if a timeout is set, use the most restrictive one */ + + if(data->set.timeout > 0) + timeout_set |= 1; + if(duringconnect && (data->set.connecttimeout > 0)) + timeout_set |= 2; + + switch (timeout_set) { + case 1: + timeout_ms = data->set.timeout; + break; + case 2: + timeout_ms = data->set.connecttimeout; + break; + case 3: + if(data->set.timeout < data->set.connecttimeout) + timeout_ms = data->set.timeout; + else + timeout_ms = data->set.connecttimeout; + break; + default: + /* use the default */ + if(!duringconnect) + /* if we're not during connect, there's no default timeout so if we're + at zero we better just return zero and not make it a negative number + by the math below */ + return 0; + break; + } + + if(!nowp) { + now = Curl_tvnow(); + nowp = &now; + } + + /* substract elapsed time */ + timeout_ms -= Curl_tvdiff(*nowp, data->progress.t_startsingle); + + return timeout_ms; +} + + /* * Curl_nonblock() set the given socket to either blocking or non-blocking * mode based on the 'nonblock' boolean argument. This function is highly @@ -533,42 +593,33 @@ CURLcode Curl_is_connected(struct connectdata *conn, CURLcode code = CURLE_OK; curl_socket_t sockfd = conn->sock[sockindex]; long allow = DEFAULT_CONNECT_TIMEOUT; - long allow_total = 0; - long has_passed; DEBUGASSERT(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET); *connected = FALSE; /* a very negative world view is best */ - /* Evaluate in milliseconds how much time that has passed */ - has_passed = Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle); - - /* subtract the most strict timeout of the ones */ - if(data->set.timeout && data->set.connecttimeout) { - if(data->set.timeout < data->set.connecttimeout) - allow_total = allow = data->set.timeout; - else - allow = data->set.connecttimeout; - } - else if(data->set.timeout) { - allow_total = allow = data->set.timeout; - } - else if(data->set.connecttimeout) { - allow = data->set.connecttimeout; - } - - if(has_passed > allow ) { - /* time-out, bail out, go home */ - failf(data, "Connection time-out after %ld ms", has_passed); - return CURLE_OPERATION_TIMEDOUT; - } if(conn->bits.tcpconnect) { /* we are connected already! */ + long allow_total = 0; + + /* subtract the most strict timeout of the ones */ + if(data->set.timeout) + allow_total = data->set.timeout; + Curl_expire(data, allow_total); *connected = TRUE; return CURLE_OK; } + /* figure out how long time we have left to connect */ + allow = Curl_timeleft(conn, NULL, TRUE); + + if(allow < 0) { + /* time-out, bail out, go home */ + failf(data, "Connection time-out"); + return CURLE_OPERATION_TIMEDOUT; + } + Curl_expire(data, allow); /* check for connect without timeout as we want to return immediately */ @@ -821,7 +872,6 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ int num_addr; Curl_addrinfo *ai; Curl_addrinfo *curr_addr; - int timeout_set = 0; struct timeval after; struct timeval before = Curl_tvnow(); @@ -834,39 +884,13 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ *connected = FALSE; /* default to not connected */ - /* if a timeout is set, use the most restrictive one */ - - if(data->set.timeout > 0) - timeout_set += 1; - if(data->set.connecttimeout > 0) - timeout_set += 2; - - switch (timeout_set) { - case 1: - timeout_ms = data->set.timeout; - break; - case 2: - timeout_ms = data->set.connecttimeout; - break; - case 3: - if(data->set.timeout < data->set.connecttimeout) - timeout_ms = data->set.timeout; - else - timeout_ms = data->set.connecttimeout; - break; - default: - timeout_ms = DEFAULT_CONNECT_TIMEOUT; - break; - } + /* get the timeout left */ + timeout_ms = Curl_timeleft(conn, &before, TRUE); - if(timeout_set > 0) { - /* if a timeout was already set, substract elapsed time */ - timeout_ms -= Curl_tvdiff(before, data->progress.t_startsingle); - if(timeout_ms < 0) { - /* a precaution, no need to continue if time already is up */ - failf(data, "Connection time-out"); - return CURLE_OPERATION_TIMEDOUT; - } + if(timeout_ms < 0) { + /* a precaution, no need to continue if time already is up */ + failf(data, "Connection time-out"); + return CURLE_OPERATION_TIMEDOUT; } Curl_expire(data, timeout_ms); -- cgit v1.2.1 From 1960eebc2d021ecf5ffc3f6d4e935d54aa592c72 Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Tue, 22 Apr 2008 22:53:53 +0000 Subject: Added support for running on Symbian OS. --- lib/connect.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 393c85603..063556315 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -93,6 +93,11 @@ /* The last #include file should be: */ #include "memdebug.h" +#ifdef __SYMBIAN32__ +/* This isn't actually supported under Symbian OS */ +#undef SO_NOSIGPIPE +#endif + static bool verifyconnect(curl_socket_t sockfd, int *error); static curl_socket_t -- cgit v1.2.1 From 3d29bda9f836d21b35110d6a005d56b6931bee6a Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 1 May 2008 21:34:34 +0000 Subject: - Bart Whiteley provided a patch that made libcurl work properly when an app uses the CURLOPT_OPENSOCKETFUNCTION callback to create a unix domain socket to a http server. --- lib/connect.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 063556315..dcccfe4d2 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -34,6 +34,9 @@ #ifdef HAVE_NETINET_IN_H #include /* may need it */ #endif +#ifdef HAVE_SYS_UN_H +#include /* for sockaddr_un */ +#endif #ifdef HAVE_NETINET_TCP_H #include /* for TCP_NODELAY */ #endif @@ -766,13 +769,24 @@ singleipconnect(struct connectdata *conn, /* FIXME: do we have Curl_printable_address-like with struct sockaddr* as argument? */ - iptoprint = &((const struct sockaddr_in*)(&addr->addr))->sin_addr; +#if defined(HAVE_SYS_UN_H) && defined(AF_UNIX) + if(addr->family==AF_UNIX) + infof(data, " Trying %s... ", + ((const struct sockaddr_un*)(&addr->addr))->sun_path); + else +#endif + { #ifdef ENABLE_IPV6 - if(addr->family==AF_INET6) - iptoprint= &((const struct sockaddr_in6*)(&addr->addr))->sin6_addr; + if(addr->family==AF_INET6) + iptoprint= &((const struct sockaddr_in6*)(&addr->addr))->sin6_addr; + else #endif - Curl_inet_ntop(addr->family, iptoprint, addr_buf, sizeof(addr_buf)); - infof(data, " Trying %s... ", addr_buf); + iptoprint = &((const struct sockaddr_in*)(&addr->addr))->sin_addr; + + if(Curl_inet_ntop(addr->family, iptoprint, addr_buf, + sizeof(addr_buf)) != NULL) + infof(data, " Trying %s... ", addr_buf); + } if(data->set.tcp_nodelay) tcpnodelay(conn, sockfd); -- cgit v1.2.1 From b84b71f5241e18ee3e6bde5bdb9d257c71b56d5f Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 3 May 2008 13:43:35 +0000 Subject: - Jean-Francois Bertrand reported a libcurl crash with CURLOPT_TCP_NODELAY since libcurl used getprotobyname() and that isn't thread-safe. We now switched to use IPPROTO_TCP unconditionally, but perhaps the proper fix is to detect the thread-safe version of the function and use that. http://curl.haxx.se/mail/lib-2008-05/0011.html --- lib/connect.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index dcccfe4d2..33e4e0777 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -685,7 +685,14 @@ static void tcpnodelay(struct connectdata *conn, socklen_t onoff = (socklen_t) data->set.tcp_nodelay; int proto = IPPROTO_TCP; -#ifdef HAVE_GETPROTOBYNAME +#if 0 + /* The use of getprotobyname() is disabled since it isn't thread-safe on + numerous systems. On these getprotobyname_r() should be used instead, but + that exists in at least one 4 arg version and one 5 arg version, and + since the proto number rarely changes anyway we now just use the hard + coded number. The "proper" fix would need a configure check for the + correct function much in the same style the gethostbyname_r versions are + detected. */ struct protoent *pe = getprotobyname("tcp"); if(pe) proto = pe->p_proto; -- cgit v1.2.1 From 514592b89207e83d13b5a4e79bc247aa6f74c4b7 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 12 May 2008 21:43:24 +0000 Subject: - Introducing curl_easy_send() and curl_easy_recv(). They can be used to send and receive data over a connection previously setup with curl_easy_perform() and its CURLOPT_CONNECT_ONLY option. The sendrecv.c example was added to show how they can be used. --- lib/connect.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 33e4e0777..74380da1e 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -92,6 +92,7 @@ #include "sockaddr.h" /* required for Curl_sockaddr_storage */ #include "inet_ntop.h" #include "inet_pton.h" +#include "sslgen.h" /* for Curl_ssl_check_cxn() */ /* The last #include file should be: */ #include "memdebug.h" @@ -977,3 +978,46 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ return CURLE_OK; } + +/* + * Used to extract socket and connectdata struct for the most recent + * transfer on the given SessionHandle. + * + * The socket 'long' will be -1 in case of failure! + */ +CURLcode Curl_getconnectinfo(struct SessionHandle *data, + long *param_longp, + struct connectdata **connp) +{ + if((data->state.lastconnect != -1) && + (data->state.connc->connects[data->state.lastconnect] != NULL)) { + struct connectdata *c = + data->state.connc->connects[data->state.lastconnect]; + if(connp) + /* only store this if the caller cares for it */ + *connp = c; + *param_longp = c->sock[FIRSTSOCKET]; + /* we have a socket connected, let's determine if the server shut down */ + /* determine if ssl */ + if(c->ssl[FIRSTSOCKET].use) { + /* use the SSL context */ + if(!Curl_ssl_check_cxn(c)) + *param_longp = -1; /* FIN received */ + } +/* Minix 3.1 doesn't support any flags on recv; just assume socket is OK */ +#ifdef MSG_PEEK + else { + /* use the socket */ + char buf; + if(recv((RECV_TYPE_ARG1)c->sock[FIRSTSOCKET], (RECV_TYPE_ARG2)&buf, + (RECV_TYPE_ARG3)1, (RECV_TYPE_ARG4)MSG_PEEK) == 0) { + *param_longp = -1; /* FIN received */ + } + } +#endif + } + else + *param_longp = -1; + + return CURLE_OK; +} -- cgit v1.2.1 From 100945694a5bfa8216eee63bff21e9dcea374234 Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Wed, 21 May 2008 21:08:31 +0000 Subject: Removed some duplicated #includes --- lib/connect.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 74380da1e..b3928ef1e 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -52,9 +52,6 @@ #ifdef HAVE_FCNTL_H #include #endif -#ifdef HAVE_NETINET_IN_H -#include -#endif #ifdef HAVE_ARPA_INET_H #include #endif -- cgit v1.2.1 From 930a45e7a93c964ec224bdddb59f97479b7e4a5d Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 6 Jun 2008 17:33:35 +0000 Subject: - Added CURLINFO_PRIMARY_IP as a new information retrievable with curl_easy_getinfo. It returns a pointer to a string with the most recently used IP address. Modified test case 500 to also verify this feature. The implementing of this feature was sponsored by Lenny Rachitsky at NeuStar. --- lib/connect.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index b3928ef1e..e398f61fb 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -775,9 +775,12 @@ singleipconnect(struct connectdata *conn, /* FIXME: do we have Curl_printable_address-like with struct sockaddr* as argument? */ #if defined(HAVE_SYS_UN_H) && defined(AF_UNIX) - if(addr->family==AF_UNIX) + if(addr->family==AF_UNIX) { infof(data, " Trying %s... ", ((const struct sockaddr_un*)(&addr->addr))->sun_path); + snprintf(data->info.ip, MAX_IPADR_LEN, "%s", + ((const struct sockaddr_un*)(&addr->addr))->sun_path); + } else #endif { @@ -789,8 +792,10 @@ singleipconnect(struct connectdata *conn, iptoprint = &((const struct sockaddr_in*)(&addr->addr))->sin_addr; if(Curl_inet_ntop(addr->family, iptoprint, addr_buf, - sizeof(addr_buf)) != NULL) + sizeof(addr_buf)) != NULL) { infof(data, " Trying %s... ", addr_buf); + snprintf(data->info.ip, MAX_IPADR_LEN, "%s", addr_buf); + } } if(data->set.tcp_nodelay) -- cgit v1.2.1 From d8bc4a0e9ab2407f235af3e8e3b37c135bcc76d8 Mon Sep 17 00:00:00 2001 From: Gunter Knauf Date: Sun, 8 Jun 2008 15:52:03 +0000 Subject: use our *printf functions only. --- lib/connect.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index e398f61fb..92538fc77 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -77,6 +77,9 @@ #include #include +#define _MPRINTF_REPLACE /* use our functions only */ +#include + #include "urldata.h" #include "sendf.h" #include "if2ip.h" -- cgit v1.2.1 From bc0ebfcdeb5a063f1753a82a6068871455adac76 Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Mon, 28 Jul 2008 18:35:34 +0000 Subject: Fixed display of the interface bind address in the trace output when it's an IPv6 address. --- lib/connect.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 92538fc77..6c736a42c 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -340,9 +340,7 @@ static CURLcode bindlocal(struct connectdata *conn, if(h) { if(in == CURL_INADDR_NONE) /* convert the resolved address, sizeof myhost >= INET_ADDRSTRLEN */ - Curl_inet_ntop(h->addr->ai_addr->sa_family, - &((struct sockaddr_in*)h->addr->ai_addr)->sin_addr, - myhost, sizeof myhost); + Curl_printable_address(h->addr, myhost, sizeof myhost); else /* we know data->set.device is shorter than the myhost array */ strcpy(myhost, dev); -- cgit v1.2.1 From 5aed78e183e843a6935679d3ebdafd0c10b41114 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 30 Jul 2008 21:55:26 +0000 Subject: - Phil Blundell added the CURLOPT_SCOPE option, as well as adjusted the URL parser to allow numerical IPv6-addresses to be specified with the scope given, as per RFC4007 - with a percent letter that itself needs to be URL escaped. For example, for an address of fe80::1234%1 the HTTP URL is: "http://[fe80::1234%251]/" --- lib/connect.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 6c736a42c..4018eb042 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -773,6 +773,13 @@ singleipconnect(struct connectdata *conn, *connected = FALSE; /* default is not connected */ +#ifdef CURLRES_IPV6 + if (conn->scope && (addr->family == AF_INET6)) { + struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)&addr->addr; + in6->sin6_scope_id = conn->scope; + } +#endif + /* FIXME: do we have Curl_printable_address-like with struct sockaddr* as argument? */ #if defined(HAVE_SYS_UN_H) && defined(AF_UNIX) -- cgit v1.2.1 From 4b01dfe369896a8a93a3c82228c755a03da731e9 Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Tue, 26 Aug 2008 21:28:57 +0000 Subject: Fixed out of memory problems that caused torture test failures in tests 1021 and 1067. --- lib/connect.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 4018eb042..860111f56 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -552,7 +552,7 @@ CURLcode Curl_store_ip_addr(struct connectdata *conn) } /* Used within the multi interface. Try next IP address, return TRUE if no - more address exists */ + more address exists or error */ static bool trynextip(struct connectdata *conn, int sockindex, bool *connected) @@ -578,8 +578,7 @@ static bool trynextip(struct connectdata *conn, conn->sock[sockindex] = sockfd; conn->ip_addr = ai; - Curl_store_ip_addr(conn); - return FALSE; + return Curl_store_ip_addr(conn) != CURLE_OK; } ai = ai->ai_next; } @@ -919,6 +918,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ long timeout_ms; long timeout_per_addr; + DEBUGASSERT(sockconn); *connected = FALSE; /* default to not connected */ /* get the timeout left */ @@ -967,9 +967,10 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ before = after; } /* end of connect-to-each-address loop */ + *sockconn = sockfd; /* the socket descriptor we've connected */ + if(sockfd == CURL_SOCKET_BAD) { /* no good connect was made */ - *sockconn = CURL_SOCKET_BAD; failf(data, "couldn't connect to host"); return CURLE_COULDNT_CONNECT; } @@ -980,10 +981,6 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ if(addr) *addr = curr_addr; - /* allow NULL-pointers to get passed in */ - if(sockconn) - *sockconn = sockfd; /* the socket descriptor we've connected */ - data->info.numconnects++; /* to track the number of connections made */ return CURLE_OK; -- cgit v1.2.1 From 2ef72f7abb0f955d08a7f26d1a65a21be26b1af9 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Mon, 8 Sep 2008 19:34:58 +0000 Subject: fix compiler warning --- lib/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 860111f56..3773b8280 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -578,7 +578,7 @@ static bool trynextip(struct connectdata *conn, conn->sock[sockindex] = sockfd; conn->ip_addr = ai; - return Curl_store_ip_addr(conn) != CURLE_OK; + return (bool)(Curl_store_ip_addr(conn) != CURLE_OK); } ai = ai->ai_next; } -- cgit v1.2.1 From fad3288d20fba6af71fa9bdfb851fe92c3aa2f04 Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Thu, 9 Oct 2008 19:23:50 +0000 Subject: Fixed the --interface option to work with IPv6 connections on glibc systems supporting getifaddrs(). Also fixed a problem where an IPv6 address could be chosen instead of an IPv4 one for --interface when it involved a name lookup. --- lib/connect.c | 111 ++++++++++++++++++++++++++++++---------------------------- 1 file changed, 58 insertions(+), 53 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 3773b8280..07d5f3887 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -284,15 +284,16 @@ int waitconnect(curl_socket_t sockfd, /* socket */ } static CURLcode bindlocal(struct connectdata *conn, - curl_socket_t sockfd) + curl_socket_t sockfd, int af) { -#ifdef ENABLE_IPV6 - char ipv6_addr[16]; -#endif struct SessionHandle *data = conn->data; struct sockaddr_in me; +#ifdef ENABLE_IPV6 + struct sockaddr_in6 me6; +#endif struct sockaddr *sock = NULL; /* bind to this address */ - socklen_t socksize; /* size of the data sock points to */ + socklen_t socksize = 0; /* size of the data sock points to */ + struct Curl_dns_entry *h=NULL; unsigned short port = data->set.localport; /* use this port number, 0 for "random" */ /* how many port numbers to try to bind to, increasing one at a time */ @@ -303,20 +304,13 @@ static CURLcode bindlocal(struct connectdata *conn, * Select device to bind socket to *************************************************************/ if(dev && (strlen(dev)<255) ) { - struct Curl_dns_entry *h=NULL; char myhost[256] = ""; - in_addr_t in; int rc; bool was_iface = FALSE; - int in6 = -1; - /* First check if the given name is an IP address */ - in=inet_addr((char *) dev); - - if((in == CURL_INADDR_NONE) && - Curl_if2ip(dev, myhost, sizeof(myhost))) { + if(Curl_if2ip(af, dev, myhost, sizeof(myhost))) { /* - * We now have the numerical IPv4-style x.y.z.w in the 'myhost' buffer + * We now have the numerical IP address in the 'myhost' buffer */ rc = Curl_resolv(conn, myhost, 0, &h); if(rc == CURLRESOLV_PENDING) @@ -324,7 +318,6 @@ static CURLcode bindlocal(struct connectdata *conn, if(h) { was_iface = TRUE; - Curl_resolv_unlock(data, h); } } @@ -333,22 +326,30 @@ static CURLcode bindlocal(struct connectdata *conn, * This was not an interface, resolve the name as a host name * or IP number */ + + /* + * Temporarily force name resolution to use only the address type + * of the connection. The resolve functions should really be changed + * to take a type parameter instead. + */ + long ipver = data->set.ip_version; + if (af == AF_INET) + data->set.ip_version = CURL_IPRESOLVE_V4; + else if (af == AF_INET6) + data->set.ip_version = CURL_IPRESOLVE_V6; + rc = Curl_resolv(conn, dev, 0, &h); if(rc == CURLRESOLV_PENDING) (void)Curl_wait_for_resolv(conn, &h); + data->set.ip_version = ipver; if(h) { - if(in == CURL_INADDR_NONE) - /* convert the resolved address, sizeof myhost >= INET_ADDRSTRLEN */ - Curl_printable_address(h->addr, myhost, sizeof myhost); - else - /* we know data->set.device is shorter than the myhost array */ - strcpy(myhost, dev); - Curl_resolv_unlock(data, h); + /* convert the resolved address, sizeof myhost >= INET_ADDRSTRLEN */ + Curl_printable_address(h->addr, myhost, sizeof myhost); } } - if(! *myhost) { + if(!*myhost || !h) { /* need to fix this h=Curl_gethost(data, getmyhost(*myhost,sizeof(myhost)), @@ -356,11 +357,16 @@ static CURLcode bindlocal(struct connectdata *conn, sizeof(hostent_buf)); */ failf(data, "Couldn't bind to '%s'", dev); + if(h) + Curl_resolv_unlock(data, h); return CURLE_INTERFACE_FAILED; } infof(data, "Bind local address to %s\n", myhost); + sock = h->addr->ai_addr; + socksize = h->addr->ai_addrlen; + #ifdef SO_BINDTODEVICE /* I am not sure any other OSs than Linux that provide this feature, and * at the least I cannot test. --Ben @@ -378,42 +384,37 @@ static CURLcode bindlocal(struct connectdata *conn, dev, strlen(dev)+1) != 0) { /* printf("Failed to BINDTODEVICE, socket: %d device: %s error: %s\n", sockfd, dev, Curl_strerror(SOCKERRNO)); */ - infof(data, "SO_BINDTODEVICE %s failed\n", dev); + int error = ERRNO; + infof(data, "SO_BINDTODEVICE %s failed with errno %d: %s; will do regular bind\n", + dev, error, Curl_strerror(conn, error)); /* This is typically "errno 1, error: Operation not permitted" if you're not running as root or another suitable privileged user */ } } #endif - - in=inet_addr(myhost); - -#ifdef ENABLE_IPV6 - in6 = Curl_inet_pton (AF_INET6, myhost, (void *)&ipv6_addr); -#endif - if(CURL_INADDR_NONE == in && -1 == in6) { - failf(data,"couldn't find my own IP address (%s)", myhost); - return CURLE_INTERFACE_FAILED; - } /* end of inet_addr */ - - if( h ) { - Curl_addrinfo *addr = h->addr; - sock = addr->ai_addr; - socksize = addr->ai_addrlen; - } - else - return CURLE_INTERFACE_FAILED; - } else if(port) { /* if a local port number is requested but no local IP, extract the address from the socket */ - memset(&me, 0, sizeof(struct sockaddr)); - me.sin_family = AF_INET; - me.sin_addr.s_addr = INADDR_ANY; + if(af == AF_INET) { + memset(&me, 0, sizeof(struct sockaddr)); + me.sin_family = AF_INET; + me.sin_addr.s_addr = INADDR_ANY; - sock = (struct sockaddr *)&me; - socksize = sizeof(struct sockaddr); + sock = (struct sockaddr *)&me; + socksize = sizeof(struct sockaddr); + } +#ifdef ENABLE_IPV6 + else { /* AF_INET6 */ + memset(&me6, 0, sizeof(struct sockaddr)); + me6.sin6_family = AF_INET6; + me6.sin6_addr = in6addr_any; + + sock = (struct sockaddr *)&me6; + socksize = sizeof(struct sockaddr); + } +#endif } else /* no local kind of binding was requested */ @@ -432,11 +433,11 @@ static CURLcode bindlocal(struct connectdata *conn, if( bind(sockfd, sock, socksize) >= 0) { /* we succeeded to bind */ struct Curl_sockaddr_storage add; - socklen_t size; - - size = sizeof(add); + socklen_t size = sizeof(add); if(getsockname(sockfd, (struct sockaddr *) &add, &size) < 0) { failf(data, "getsockname() failed"); + if(h) + Curl_resolv_unlock(data, h); return CURLE_INTERFACE_FAILED; } /* We re-use/clobber the port variable here below */ @@ -448,6 +449,8 @@ static CURLcode bindlocal(struct connectdata *conn, #endif infof(data, "Local port: %d\n", port); conn->bits.bound = TRUE; + if(h) + Curl_resolv_unlock(data, h); return CURLE_OK; } if(--portnum > 0) { @@ -461,8 +464,10 @@ static CURLcode bindlocal(struct connectdata *conn, data->state.os_errno = SOCKERRNO; failf(data, "bind failure: %s", Curl_strerror(conn, data->state.os_errno)); - return CURLE_INTERFACE_FAILED; + if(h) + Curl_resolv_unlock(data, h); + return CURLE_INTERFACE_FAILED; } /* @@ -822,7 +827,7 @@ singleipconnect(struct connectdata *conn, } /* possibly bind the local end to an IP, interface or port */ - res = bindlocal(conn, sockfd); + res = bindlocal(conn, sockfd, addr->family); if(res) { sclose(sockfd); /* close socket and bail out */ return CURL_SOCKET_BAD; -- cgit v1.2.1 From 8cd76d392133a0c8a52ff0cb9f56951e19657936 Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Fri, 10 Oct 2008 03:46:32 +0000 Subject: Allow compilation when no IPv6 stack is available. --- lib/connect.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 07d5f3887..3d3479218 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -335,8 +335,10 @@ static CURLcode bindlocal(struct connectdata *conn, long ipver = data->set.ip_version; if (af == AF_INET) data->set.ip_version = CURL_IPRESOLVE_V4; +#ifdef ENABLE_IPV6 else if (af == AF_INET6) data->set.ip_version = CURL_IPRESOLVE_V6; +#endif rc = Curl_resolv(conn, dev, 0, &h); if(rc == CURLRESOLV_PENDING) -- cgit v1.2.1 From a754ea1326ea7f6fa099fa5c0c10d06e6e28eda3 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Sat, 11 Oct 2008 15:32:32 +0000 Subject: fix compiler warning --- lib/connect.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 3d3479218..51857ec8d 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -299,6 +299,7 @@ static CURLcode bindlocal(struct connectdata *conn, /* how many port numbers to try to bind to, increasing one at a time */ int portnum = data->set.localportrange; const char *dev = data->set.str[STRING_DEVICE]; + int error; /************************************************************* * Select device to bind socket to @@ -358,7 +359,9 @@ static CURLcode bindlocal(struct connectdata *conn, hostent_buf, sizeof(hostent_buf)); */ - failf(data, "Couldn't bind to '%s'", dev); + data->state.os_errno = error = SOCKERRNO; + failf(data, "Couldn't bind to '%s', failed with errno %d: %s", + dev, error, Curl_strerror(conn, error)); if(h) Curl_resolv_unlock(data, h); return CURLE_INTERFACE_FAILED; @@ -384,9 +387,7 @@ static CURLcode bindlocal(struct connectdata *conn, */ if(setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, dev, strlen(dev)+1) != 0) { - /* printf("Failed to BINDTODEVICE, socket: %d device: %s error: %s\n", - sockfd, dev, Curl_strerror(SOCKERRNO)); */ - int error = ERRNO; + error = ERRNO; infof(data, "SO_BINDTODEVICE %s failed with errno %d: %s; will do regular bind\n", dev, error, Curl_strerror(conn, error)); /* This is typically "errno 1, error: Operation not permitted" if @@ -437,7 +438,9 @@ static CURLcode bindlocal(struct connectdata *conn, struct Curl_sockaddr_storage add; socklen_t size = sizeof(add); if(getsockname(sockfd, (struct sockaddr *) &add, &size) < 0) { - failf(data, "getsockname() failed"); + data->state.os_errno = error = SOCKERRNO; + failf(data, "getsockname() failed with errno %d: %s", + error, Curl_strerror(conn, error)); if(h) Curl_resolv_unlock(data, h); return CURLE_INTERFACE_FAILED; @@ -463,9 +466,9 @@ static CURLcode bindlocal(struct connectdata *conn, break; } while(1); - data->state.os_errno = SOCKERRNO; - failf(data, "bind failure: %s", - Curl_strerror(conn, data->state.os_errno)); + data->state.os_errno = error = SOCKERRNO; + failf(data, "bind failed with errno %d: %s", + error, Curl_strerror(conn, error)); if(h) Curl_resolv_unlock(data, h); -- cgit v1.2.1 From c3a959cc37d69f2634fa3b6a0a4775c7cf08ce27 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Mon, 13 Oct 2008 06:16:02 +0000 Subject: There's no guarantee that a socket was involved at this point, so avoid displaying any error code. And on the other hand a message after setsockopt() certainly must use SOCKERRNO. --- lib/connect.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 51857ec8d..3a90a65b0 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -359,9 +359,7 @@ static CURLcode bindlocal(struct connectdata *conn, hostent_buf, sizeof(hostent_buf)); */ - data->state.os_errno = error = SOCKERRNO; - failf(data, "Couldn't bind to '%s', failed with errno %d: %s", - dev, error, Curl_strerror(conn, error)); + failf(data, "Couldn't bind to '%s'", dev); if(h) Curl_resolv_unlock(data, h); return CURLE_INTERFACE_FAILED; @@ -387,7 +385,7 @@ static CURLcode bindlocal(struct connectdata *conn, */ if(setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, dev, strlen(dev)+1) != 0) { - error = ERRNO; + error = SOCKERRNO; infof(data, "SO_BINDTODEVICE %s failed with errno %d: %s; will do regular bind\n", dev, error, Curl_strerror(conn, error)); /* This is typically "errno 1, error: Operation not permitted" if -- cgit v1.2.1 From 29f09f71b4f8b8ab6df7b3ce13ae4794edb7158b Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Fri, 17 Oct 2008 03:38:36 +0000 Subject: portability fix to avoid memory alignment problems --- lib/connect.c | 88 +++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 55 insertions(+), 33 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 3a90a65b0..9003aba07 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -102,6 +102,18 @@ #undef SO_NOSIGPIPE #endif +struct Curl_sockaddr_ex { + int family; + int socktype; + int protocol; + unsigned int addrlen; + union { + struct sockaddr addr; + struct Curl_sockaddr_storage buff; + } _sa_ex_u; +}; +#define sa_addr _sa_ex_u.addr + static bool verifyconnect(curl_socket_t sockfd, int *error); static curl_socket_t @@ -743,6 +755,7 @@ singleipconnect(struct connectdata *conn, long timeout_ms, bool *connected) { + struct Curl_sockaddr_ex addr; char addr_buf[128]; int rc; int error; @@ -750,63 +763,72 @@ singleipconnect(struct connectdata *conn, struct SessionHandle *data = conn->data; curl_socket_t sockfd; CURLcode res; + const void *iptoprint; + /* - * Curl_sockaddr_storage, which is basically sockaddr_storage has a space - * for a largest possible struct sockaddr only. We should add some space for - * the other fields we are using. Hence the addr_storage size math. + * The Curl_sockaddr_ex structure is basically libcurl's external API + * curl_sockaddr structure with enough space available to directly hold + * any protocol-specific address structures. The variable declared here + * will be used to pass / receive data to/from the fopensocket callback + * if this has been set, before that, it is initialized from parameters. */ - char addr_storage[sizeof(struct curl_sockaddr)- - sizeof(struct sockaddr)+ - sizeof(struct Curl_sockaddr_storage)]; - struct curl_sockaddr *addr=(struct curl_sockaddr*)&addr_storage; - const void *iptoprint; - addr->family=ai->ai_family; - addr->socktype=conn->socktype; - addr->protocol=ai->ai_protocol; - addr->addrlen = - (ai->ai_addrlen < (socklen_t)sizeof(struct Curl_sockaddr_storage)) ? - (unsigned int)ai->ai_addrlen : sizeof(struct Curl_sockaddr_storage); - memcpy(&addr->addr, ai->ai_addr, addr->addrlen); + addr.family = ai->ai_family; + addr.socktype = conn->socktype; + addr.protocol = ai->ai_protocol; + addr.addrlen = ai->ai_addrlen; + + if(addr.addrlen > sizeof(struct Curl_sockaddr_storage)) + addr.addrlen = sizeof(struct Curl_sockaddr_storage); + memcpy(&addr.sa_addr, ai->ai_addr, addr.addrlen); + + *connected = FALSE; /* default is not connected */ - /* If set, use opensocket callback to get the socket */ if(data->set.fopensocket) + /* + * If the opensocket callback is set, all the destination address information + * is passed to the callback. Depending on this information the callback may + * opt to abort the connection, this is indicated returning CURL_SOCKET_BAD; + * otherwise it will return a not-connected socket. When the callback returns + * a valid socket the destination address information might have been changed + * and this 'new' address will actually be used here to connect. + */ sockfd = data->set.fopensocket(data->set.opensocket_client, - CURLSOCKTYPE_IPCXN, addr); + CURLSOCKTYPE_IPCXN, + (struct curl_sockaddr *)&addr); else - sockfd = socket(addr->family, addr->socktype, addr->protocol); + /* opensocket callback not set, so simply create the socket now */ + sockfd = socket(addr.family, addr.socktype, addr.protocol); + if(sockfd == CURL_SOCKET_BAD) + /* no socket, no connection */ return CURL_SOCKET_BAD; - *connected = FALSE; /* default is not connected */ - #ifdef CURLRES_IPV6 - if (conn->scope && (addr->family == AF_INET6)) { - struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)&addr->addr; - in6->sin6_scope_id = conn->scope; - } + if (conn->scope && (addr.family == AF_INET6)) + ((struct sockaddr_in6 *)(&addr.sa_addr))->sin6_scope_id = conn->scope; #endif /* FIXME: do we have Curl_printable_address-like with struct sockaddr* as argument? */ #if defined(HAVE_SYS_UN_H) && defined(AF_UNIX) - if(addr->family==AF_UNIX) { + if(addr.family == AF_UNIX) { infof(data, " Trying %s... ", - ((const struct sockaddr_un*)(&addr->addr))->sun_path); + ((const struct sockaddr_un*)(&addr.sa_addr))->sun_path); snprintf(data->info.ip, MAX_IPADR_LEN, "%s", - ((const struct sockaddr_un*)(&addr->addr))->sun_path); + ((const struct sockaddr_un*)(&addr.sa_addr))->sun_path); } else #endif { #ifdef ENABLE_IPV6 - if(addr->family==AF_INET6) - iptoprint= &((const struct sockaddr_in6*)(&addr->addr))->sin6_addr; + if(addr.family == AF_INET6) + iptoprint = &((const struct sockaddr_in6*)(&addr.sa_addr))->sin6_addr; else #endif - iptoprint = &((const struct sockaddr_in*)(&addr->addr))->sin_addr; + iptoprint = &((const struct sockaddr_in*)(&addr.sa_addr))->sin_addr; - if(Curl_inet_ntop(addr->family, iptoprint, addr_buf, + if(Curl_inet_ntop(addr.family, iptoprint, addr_buf, sizeof(addr_buf)) != NULL) { infof(data, " Trying %s... ", addr_buf); snprintf(data->info.ip, MAX_IPADR_LEN, "%s", addr_buf); @@ -830,7 +852,7 @@ singleipconnect(struct connectdata *conn, } /* possibly bind the local end to an IP, interface or port */ - res = bindlocal(conn, sockfd, addr->family); + res = bindlocal(conn, sockfd, addr.family); if(res) { sclose(sockfd); /* close socket and bail out */ return CURL_SOCKET_BAD; @@ -841,7 +863,7 @@ singleipconnect(struct connectdata *conn, /* Connect TCP sockets, bind UDP */ if(conn->socktype == SOCK_STREAM) - rc = connect(sockfd, &addr->addr, addr->addrlen); + rc = connect(sockfd, &addr.sa_addr, addr.addrlen); else rc = 0; -- cgit v1.2.1 From 10035c898b4c6c5dddb4d58ad495cdb1da085f45 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Fri, 24 Oct 2008 16:59:35 +0000 Subject: fix compiler warning --- lib/connect.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 9003aba07..1f6a262c8 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -410,22 +410,22 @@ static CURLcode bindlocal(struct connectdata *conn, /* if a local port number is requested but no local IP, extract the address from the socket */ if(af == AF_INET) { - memset(&me, 0, sizeof(struct sockaddr)); + memset(&me, 0, sizeof(me)); me.sin_family = AF_INET; me.sin_addr.s_addr = INADDR_ANY; sock = (struct sockaddr *)&me; - socksize = sizeof(struct sockaddr); + socksize = sizeof(me); } #ifdef ENABLE_IPV6 else { /* AF_INET6 */ - memset(&me6, 0, sizeof(struct sockaddr)); + memset(&me6, 0, sizeof(me6)); me6.sin6_family = AF_INET6; me6.sin6_addr = in6addr_any; sock = (struct sockaddr *)&me6; - socksize = sizeof(struct sockaddr); + socksize = sizeof(me6); } #endif } @@ -437,22 +437,23 @@ static CURLcode bindlocal(struct connectdata *conn, /* Set port number to bind to, 0 makes the system pick one */ if(sock->sa_family == AF_INET) - ((struct sockaddr_in *)sock)->sin_port = htons(port); + me.sin_port = htons(port); #ifdef ENABLE_IPV6 else - ((struct sockaddr_in6 *)sock)->sin6_port = htons(port); + me6.sin6_port = htons(port); #endif if( bind(sockfd, sock, socksize) >= 0) { /* we succeeded to bind */ struct Curl_sockaddr_storage add; socklen_t size = sizeof(add); + memset(&add, 0, sizeof(struct Curl_sockaddr_storage)); if(getsockname(sockfd, (struct sockaddr *) &add, &size) < 0) { data->state.os_errno = error = SOCKERRNO; failf(data, "getsockname() failed with errno %d: %s", error, Curl_strerror(conn, error)); - if(h) - Curl_resolv_unlock(data, h); + if(h) + Curl_resolv_unlock(data, h); return CURLE_INTERFACE_FAILED; } /* We re-use/clobber the port variable here below */ @@ -465,7 +466,7 @@ static CURLcode bindlocal(struct connectdata *conn, infof(data, "Local port: %d\n", port); conn->bits.bound = TRUE; if(h) - Curl_resolv_unlock(data, h); + Curl_resolv_unlock(data, h); return CURLE_OK; } if(--portnum > 0) { @@ -764,6 +765,10 @@ singleipconnect(struct connectdata *conn, curl_socket_t sockfd; CURLcode res; const void *iptoprint; + struct sockaddr_in * const sa4 = (void *)&addr.sa_addr; +#ifdef ENABLE_IPV6 + struct sockaddr_in6 * const sa6 = (void *)&addr.sa_addr; +#endif /* * The Curl_sockaddr_ex structure is basically libcurl's external API @@ -804,9 +809,9 @@ singleipconnect(struct connectdata *conn, /* no socket, no connection */ return CURL_SOCKET_BAD; -#ifdef CURLRES_IPV6 +#ifdef ENABLE_IPV6 if (conn->scope && (addr.family == AF_INET6)) - ((struct sockaddr_in6 *)(&addr.sa_addr))->sin6_scope_id = conn->scope; + sa6->sin6_scope_id = conn->scope; #endif /* FIXME: do we have Curl_printable_address-like with struct sockaddr* as @@ -823,10 +828,10 @@ singleipconnect(struct connectdata *conn, { #ifdef ENABLE_IPV6 if(addr.family == AF_INET6) - iptoprint = &((const struct sockaddr_in6*)(&addr.sa_addr))->sin6_addr; + iptoprint = &sa6->sin6_addr; else #endif - iptoprint = &((const struct sockaddr_in*)(&addr.sa_addr))->sin_addr; + iptoprint = &sa4->sin_addr; if(Curl_inet_ntop(addr.family, iptoprint, addr_buf, sizeof(addr_buf)) != NULL) { -- cgit v1.2.1 From 8693afdfea8eddc51c86f7bc93d1b9c1887276bc Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Fri, 24 Oct 2008 18:59:51 +0000 Subject: Stop using in6addr_any because it's not available everywhere (e.g. Symbian) and isn't strictly needed here. --- lib/connect.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 1f6a262c8..7fc808e86 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -422,7 +422,9 @@ static CURLcode bindlocal(struct connectdata *conn, else { /* AF_INET6 */ memset(&me6, 0, sizeof(me6)); me6.sin6_family = AF_INET6; - me6.sin6_addr = in6addr_any; + /* in6addr_any isn't always available and since me6 has just been + cleared, it's not strictly necessary to use it here */ + /*me6.sin6_addr = in6addr_any;*/ sock = (struct sockaddr *)&me6; socksize = sizeof(me6); -- cgit v1.2.1 From d0b8b5a1990a31f37fcab925cb8b59bee958d41d Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 3 Nov 2008 16:24:56 +0000 Subject: - Bug #2218480 (http://curl.haxx.se/bug/view.cgi?id=2218480) pointed out a problem with my CURLINFO_PRIMARY_IP fix from October 7th that caused a NULL pointer read. I also took the opportunity to clean up this logic (storing of the connection's IP address) somewhat as we had it stored in two different places and ways previously and they are now unified. --- lib/connect.c | 30 ++++++++---------------------- 1 file changed, 8 insertions(+), 22 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 7fc808e86..b602731fe 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -555,25 +555,6 @@ static bool verifyconnect(curl_socket_t sockfd, int *error) return rc; } -CURLcode Curl_store_ip_addr(struct connectdata *conn) -{ - char addrbuf[256]; - Curl_printable_address(conn->ip_addr, addrbuf, sizeof(addrbuf)); - - /* save the string */ - Curl_safefree(conn->ip_addr_str); - conn->ip_addr_str = strdup(addrbuf); - if(!conn->ip_addr_str) - return CURLE_OUT_OF_MEMORY; /* FAIL */ - -#ifdef PF_INET6 - if(conn->ip_addr->ai_family == PF_INET6) - conn->bits.ipv6 = TRUE; -#endif - - return CURLE_OK; -} - /* Used within the multi interface. Try next IP address, return TRUE if no more address exists or error */ static bool trynextip(struct connectdata *conn, @@ -600,8 +581,7 @@ static bool trynextip(struct connectdata *conn, /* store the new socket descriptor */ conn->sock[sockindex] = sockfd; conn->ip_addr = ai; - - return (bool)(Curl_store_ip_addr(conn) != CURLE_OK); + break; } ai = ai->ai_next; } @@ -824,21 +804,27 @@ singleipconnect(struct connectdata *conn, ((const struct sockaddr_un*)(&addr.sa_addr))->sun_path); snprintf(data->info.ip, MAX_IPADR_LEN, "%s", ((const struct sockaddr_un*)(&addr.sa_addr))->sun_path); + strcpy(conn->ip_addr_str, data->info.ip); } else #endif { #ifdef ENABLE_IPV6 - if(addr.family == AF_INET6) + if(addr.family == AF_INET6) { iptoprint = &sa6->sin6_addr; + conn->bits.ipv6 = TRUE; + } else #endif + { iptoprint = &sa4->sin_addr; + } if(Curl_inet_ntop(addr.family, iptoprint, addr_buf, sizeof(addr_buf)) != NULL) { infof(data, " Trying %s... ", addr_buf); snprintf(data->info.ip, MAX_IPADR_LEN, "%s", addr_buf); + strcpy(conn->ip_addr_str, data->info.ip); } } -- cgit v1.2.1 From a0ef686c542bee30be0b20cd4d3243bec6b4f059 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Thu, 6 Nov 2008 17:19:56 +0000 Subject: Merged existing IPv4 and IPv6 Curl_ip2addr functions into a single one which now also takes a protocol address family argument. --- lib/connect.c | 1 - 1 file changed, 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index b602731fe..65e9be4f4 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -91,7 +91,6 @@ #include "multiif.h" #include "sockaddr.h" /* required for Curl_sockaddr_storage */ #include "inet_ntop.h" -#include "inet_pton.h" #include "sslgen.h" /* for Curl_ssl_check_cxn() */ /* The last #include file should be: */ -- cgit v1.2.1 From 17d2a464ad42c47ec37870e4b01a18ef5593877f Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Thu, 13 Nov 2008 18:56:55 +0000 Subject: Refactor configure script detection of functions used to set sockets into non-blocking mode, and decouple function detection from function capability. --- lib/connect.c | 55 +++++++++++++++++++------------------------------------ 1 file changed, 19 insertions(+), 36 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 65e9be4f4..f2b15da82 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -59,7 +59,7 @@ #include /* required for free() prototype, without it, this crashes */ #endif /* on macos 68K */ -#if (defined(HAVE_FIONBIO) && defined(NETWARE)) +#if (defined(HAVE_IOCTL_FIONBIO) && defined(NETWARE)) #include #endif #ifdef NETWARE @@ -189,64 +189,47 @@ long Curl_timeleft(struct connectdata *conn, int Curl_nonblock(curl_socket_t sockfd, /* operate on this */ int nonblock /* TRUE or FALSE */) { -#undef SETBLOCK -#define SETBLOCK 0 -#ifdef HAVE_O_NONBLOCK +#if defined(USE_BLOCKING_SOCKETS) + + return 0; /* returns success */ + +#elif defined(HAVE_FCNTL_O_NONBLOCK) + /* most recent unix versions */ int flags; - flags = fcntl(sockfd, F_GETFL, 0); if(FALSE != nonblock) return fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); else return fcntl(sockfd, F_SETFL, flags & (~O_NONBLOCK)); -#undef SETBLOCK -#define SETBLOCK 1 -#endif -#if defined(HAVE_FIONBIO) && (SETBLOCK == 0) +#elif defined(HAVE_IOCTL_FIONBIO) + /* older unix versions */ int flags; - flags = nonblock; return ioctl(sockfd, FIONBIO, &flags); -#undef SETBLOCK -#define SETBLOCK 2 -#endif -#if defined(HAVE_IOCTLSOCKET) && (SETBLOCK == 0) - /* Windows? */ +#elif defined(HAVE_IOCTLSOCKET_FIONBIO) + + /* Windows */ unsigned long flags; flags = nonblock; - return ioctlsocket(sockfd, FIONBIO, &flags); -#undef SETBLOCK -#define SETBLOCK 3 -#endif -#if defined(HAVE_IOCTLSOCKET_CASE) && (SETBLOCK == 0) - /* presumably for Amiga */ +#elif defined(HAVE_IOCTLSOCKET_CAMEL_FIONBIO) + + /* Amiga */ return IoctlSocket(sockfd, FIONBIO, (long)nonblock); -#undef SETBLOCK -#define SETBLOCK 4 -#endif -#if defined(HAVE_SO_NONBLOCK) && (SETBLOCK == 0) +#elif defined(HAVE_SETSOCKOPT_SO_NONBLOCK) + /* BeOS */ long b = nonblock ? 1 : 0; return setsockopt(sockfd, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b)); -#undef SETBLOCK -#define SETBLOCK 5 -#endif -#ifdef HAVE_DISABLED_NONBLOCKING - return 0; /* returns success */ -#undef SETBLOCK -#define SETBLOCK 6 -#endif - -#if(SETBLOCK == 0) -#error "no non-blocking method was found/used/set" +#else +# error "no non-blocking method was found/used/set" #endif } -- cgit v1.2.1 From ea8fbb5233b24745177871a7e1e9105a137f94f9 Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Fri, 14 Nov 2008 23:17:32 +0000 Subject: Added some #ifdefs around header files and change the EAGAIN test to fix compilation on Cell (reported by Jeff Curley). --- lib/connect.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index f2b15da82..30cd1535b 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -848,12 +848,14 @@ singleipconnect(struct connectdata *conn, switch (error) { case EINPROGRESS: case EWOULDBLOCK: -#if defined(EAGAIN) && EAGAIN != EWOULDBLOCK +#if defined(EAGAIN) +#if (EAGAIN) != (EWOULDBLOCK) /* On some platforms EAGAIN and EWOULDBLOCK are the * same value, and on others they are different, hence * the odd #if */ case EAGAIN: +#endif #endif rc = waitconnect(sockfd, timeout_ms); break; -- cgit v1.2.1 From 418683f5377d7bcb751888345ba14a77fd68cdbd Mon Sep 17 00:00:00 2001 From: Gisle Vanem Date: Tue, 16 Dec 2008 08:25:55 +0000 Subject: Added the use of Watt-32 tcp/ip stack for Win32 targets. --- lib/connect.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 30cd1535b..569142d3e 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -23,8 +23,6 @@ #include "setup.h" -#ifndef WIN32 -/* headers for non-win32 */ #ifdef HAVE_SYS_TIME_H #include #endif @@ -71,8 +69,6 @@ #include #endif -#endif /* !WIN32 */ - #include #include #include -- cgit v1.2.1 From 1cc50d31f9962264fd78cdbe6a27dac10742dcd6 Mon Sep 17 00:00:00 2001 From: Gunter Knauf Date: Tue, 30 Dec 2008 08:05:38 +0000 Subject: changed HAVE_SIN6_SCOPE_ID define to HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID since just found that ares already uses this define. --- lib/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 569142d3e..47e8681c5 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -769,7 +769,7 @@ singleipconnect(struct connectdata *conn, /* no socket, no connection */ return CURL_SOCKET_BAD; -#ifdef ENABLE_IPV6 +#if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID) if (conn->scope && (addr.family == AF_INET6)) sa6->sin6_scope_id = conn->scope; #endif -- cgit v1.2.1 From 7b7db23633626d4ad60ab282e93ff28d029cd4e7 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 27 Feb 2009 12:07:14 +0000 Subject: - Senthil Raja Velu reported a problem when CURLOPT_INTERFACE and CURLOPT_LOCALPORT were used together (the local port bind failed), and Markus Koetter provided the fix! --- lib/connect.c | 208 ++++++++++++++++++++++++++++------------------------------ 1 file changed, 101 insertions(+), 107 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 47e8681c5..3b2b65c71 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2008, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -54,8 +54,8 @@ #include #endif #ifdef HAVE_STDLIB_H -#include /* required for free() prototype, without it, this crashes */ -#endif /* on macos 68K */ +#include +#endif #if (defined(HAVE_IOCTL_FIONBIO) && defined(NETWARE)) #include @@ -277,12 +277,15 @@ static CURLcode bindlocal(struct connectdata *conn, curl_socket_t sockfd, int af) { struct SessionHandle *data = conn->data; - struct sockaddr_in me; + + struct Curl_sockaddr_storage sa; + struct sockaddr *sock = (struct sockaddr *)&sa; /* bind to this address */ + socklen_t sizeof_sa = 0; /* size of the data sock points to */ + struct sockaddr_in *si4 = (struct sockaddr_in *)&sa; #ifdef ENABLE_IPV6 - struct sockaddr_in6 me6; + struct sockaddr_in6 *si6 = (struct sockaddr_in6 *)&sa; #endif - struct sockaddr *sock = NULL; /* bind to this address */ - socklen_t socksize = 0; /* size of the data sock points to */ + struct Curl_dns_entry *h=NULL; unsigned short port = data->set.localport; /* use this port number, 0 for "random" */ @@ -290,40 +293,64 @@ static CURLcode bindlocal(struct connectdata *conn, int portnum = data->set.localportrange; const char *dev = data->set.str[STRING_DEVICE]; int error; + char myhost[256] = ""; + int done = 0; /* -1 for error, 1 for address found */ /************************************************************* * Select device to bind socket to *************************************************************/ + if ( !dev && !port ) + /* no local kind of binding was requested */ + return CURLE_OK; + + memset(&sa, 0, sizeof(struct Curl_sockaddr_storage)); + if(dev && (strlen(dev)<255) ) { - char myhost[256] = ""; - int rc; - bool was_iface = FALSE; + /* interface */ if(Curl_if2ip(af, dev, myhost, sizeof(myhost))) { /* * We now have the numerical IP address in the 'myhost' buffer */ - rc = Curl_resolv(conn, myhost, 0, &h); - if(rc == CURLRESOLV_PENDING) - (void)Curl_wait_for_resolv(conn, &h); + infof(data, "Local Interface %s is ip %s using address family %i\n", + dev, myhost, af); + done = 1; - if(h) { - was_iface = TRUE; +#ifdef SO_BINDTODEVICE + /* I am not sure any other OSs than Linux that provide this feature, and + * at the least I cannot test. --Ben + * + * This feature allows one to tightly bind the local socket to a + * particular interface. This will force even requests to other local + * interfaces to go out the external interface. + * + * + * Only bind to the interface when specified as interface, not just as a + * hostname or ip address. + */ + if(setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, + dev, strlen(dev)+1) != 0) { + error = SOCKERRNO; + infof(data, "SO_BINDTODEVICE %s failed with errno %d: %s;" + " will do regular bind\n", + dev, error, Curl_strerror(conn, error)); + /* This is typically "errno 1, error: Operation not permitted" if + you're not running as root or another suitable privileged user */ } +#endif } - - if(!was_iface) { + else { /* * This was not an interface, resolve the name as a host name * or IP number - */ - - /* + * * Temporarily force name resolution to use only the address type * of the connection. The resolve functions should really be changed * to take a type parameter instead. */ long ipver = data->set.ip_version; + int rc; + if (af == AF_INET) data->set.ip_version = CURL_IPRESOLVE_V4; #ifdef ENABLE_IPV6 @@ -338,93 +365,65 @@ static CURLcode bindlocal(struct connectdata *conn, if(h) { /* convert the resolved address, sizeof myhost >= INET_ADDRSTRLEN */ - Curl_printable_address(h->addr, myhost, sizeof myhost); - } - } - - if(!*myhost || !h) { - /* need to fix this - h=Curl_gethost(data, - getmyhost(*myhost,sizeof(myhost)), - hostent_buf, - sizeof(hostent_buf)); - */ - failf(data, "Couldn't bind to '%s'", dev); - if(h) + Curl_printable_address(h->addr, myhost, sizeof(myhost)); + infof(data, "Name '%s' family %i resolved to '%s' family %i\n", + dev, af, myhost, h->addr->ai_family); Curl_resolv_unlock(data, h); - return CURLE_INTERFACE_FAILED; + done = 1; + } + else { + /* + * provided dev was no interface (or interfaces are not supported + * e.g. solaris) no ip address and no domain we fail here + */ + done = -1; + } } - infof(data, "Bind local address to %s\n", myhost); - - sock = h->addr->ai_addr; - socksize = h->addr->ai_addrlen; - -#ifdef SO_BINDTODEVICE - /* I am not sure any other OSs than Linux that provide this feature, and - * at the least I cannot test. --Ben - * - * This feature allows one to tightly bind the local socket to a - * particular interface. This will force even requests to other local - * interfaces to go out the external interface. - * - */ - if(was_iface) { - /* Only bind to the interface when specified as interface, not just as a - * hostname or ip address. - */ - if(setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, - dev, strlen(dev)+1) != 0) { - error = SOCKERRNO; - infof(data, "SO_BINDTODEVICE %s failed with errno %d: %s; will do regular bind\n", - dev, error, Curl_strerror(conn, error)); - /* This is typically "errno 1, error: Operation not permitted" if - you're not running as root or another suitable privileged user */ + if(done > 0) { +#ifdef ENABLE_IPV6 + /* ipv6 address */ + if ( (af == AF_INET6) && + inet_pton(AF_INET6, myhost, &si6->sin6_addr) > 0 ) { + si6->sin6_family = AF_INET6; + si6->sin6_port = htons(port); + sizeof_sa = sizeof(struct sockaddr_in6); } - } + else #endif - } - else if(port) { - /* if a local port number is requested but no local IP, extract the - address from the socket */ - if(af == AF_INET) { - memset(&me, 0, sizeof(me)); - me.sin_family = AF_INET; - me.sin_addr.s_addr = INADDR_ANY; - - sock = (struct sockaddr *)&me; - socksize = sizeof(me); + /* ipv4 address */ + if ( af == AF_INET && inet_pton(AF_INET, myhost, &si4->sin_addr) > 0 ) { + si4->sin_family = AF_INET; + si4->sin_port = htons(port); + sizeof_sa = sizeof(struct sockaddr_in); + } + } + if(done < 1) { + failf(data, "Couldn't bind to '%s'", dev); + return CURLE_INTERFACE_FAILED; } + } + else { + /* no device was given, prepare sa to match af's needs */ #ifdef ENABLE_IPV6 - else { /* AF_INET6 */ - memset(&me6, 0, sizeof(me6)); - me6.sin6_family = AF_INET6; - /* in6addr_any isn't always available and since me6 has just been - cleared, it's not strictly necessary to use it here */ - /*me6.sin6_addr = in6addr_any;*/ - - sock = (struct sockaddr *)&me6; - socksize = sizeof(me6); + if ( af == AF_INET6 ) { + si6->sin6_family = AF_INET6; + si6->sin6_port = htons(port); + sizeof_sa = sizeof(struct sockaddr_in6); } + else #endif + if ( af == AF_INET ) { + si4->sin_family = AF_INET; + si4->sin_port = htons(port); + sizeof_sa = sizeof(struct sockaddr_in); + } } - else - /* no local kind of binding was requested */ - return CURLE_OK; do { - - /* Set port number to bind to, 0 makes the system pick one */ - if(sock->sa_family == AF_INET) - me.sin_port = htons(port); -#ifdef ENABLE_IPV6 - else - me6.sin6_port = htons(port); -#endif - - if( bind(sockfd, sock, socksize) >= 0) { - /* we succeeded to bind */ + if( bind(sockfd, sock, sizeof_sa) >= 0) { + /* we succeeded to bind */ struct Curl_sockaddr_storage add; socklen_t size = sizeof(add); memset(&add, 0, sizeof(struct Curl_sockaddr_storage)); @@ -432,26 +431,23 @@ static CURLcode bindlocal(struct connectdata *conn, data->state.os_errno = error = SOCKERRNO; failf(data, "getsockname() failed with errno %d: %s", error, Curl_strerror(conn, error)); - if(h) - Curl_resolv_unlock(data, h); return CURLE_INTERFACE_FAILED; } - /* We re-use/clobber the port variable here below */ - if(((struct sockaddr *)&add)->sa_family == AF_INET) - port = ntohs(((struct sockaddr_in *)&add)->sin_port); -#ifdef ENABLE_IPV6 - else - port = ntohs(((struct sockaddr_in6 *)&add)->sin6_port); -#endif infof(data, "Local port: %d\n", port); conn->bits.bound = TRUE; - if(h) - Curl_resolv_unlock(data, h); return CURLE_OK; } + if(--portnum > 0) { infof(data, "Bind to local port %d failed, trying next\n", port); port++; /* try next port */ + /* We re-use/clobber the port variable here below */ + if(sock->sa_family == AF_INET) + si4->sin_port = ntohs(port); +#ifdef ENABLE_IPV6 + else + si6->sin6_port = ntohs(port); +#endif } else break; @@ -460,8 +456,6 @@ static CURLcode bindlocal(struct connectdata *conn, data->state.os_errno = error = SOCKERRNO; failf(data, "bind failed with errno %d: %s", error, Curl_strerror(conn, error)); - if(h) - Curl_resolv_unlock(data, h); return CURLE_INTERFACE_FAILED; } -- cgit v1.2.1 From 8d78a33e60e64ef92120652d01e0aa1c0da9216c Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Sat, 28 Feb 2009 01:35:53 +0000 Subject: for portability reasons: s/inet_pton/Curl_inet_pton/ --- lib/connect.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 3b2b65c71..ba337bc79 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -87,6 +87,7 @@ #include "multiif.h" #include "sockaddr.h" /* required for Curl_sockaddr_storage */ #include "inet_ntop.h" +#include "inet_pton.h" #include "sslgen.h" /* for Curl_ssl_check_cxn() */ /* The last #include file should be: */ @@ -383,8 +384,8 @@ static CURLcode bindlocal(struct connectdata *conn, if(done > 0) { #ifdef ENABLE_IPV6 /* ipv6 address */ - if ( (af == AF_INET6) && - inet_pton(AF_INET6, myhost, &si6->sin6_addr) > 0 ) { + if((af == AF_INET6) && + (Curl_inet_pton(AF_INET6, myhost, &si6->sin6_addr) > 0)) { si6->sin6_family = AF_INET6; si6->sin6_port = htons(port); sizeof_sa = sizeof(struct sockaddr_in6); @@ -392,7 +393,8 @@ static CURLcode bindlocal(struct connectdata *conn, else #endif /* ipv4 address */ - if ( af == AF_INET && inet_pton(AF_INET, myhost, &si4->sin_addr) > 0 ) { + if((af == AF_INET) && + (Curl_inet_pton(AF_INET, myhost, &si4->sin_addr) > 0)) { si4->sin_family = AF_INET; si4->sin_port = htons(port); sizeof_sa = sizeof(struct sockaddr_in); -- cgit v1.2.1 From 33a3753c3f41d546ebf3350685eb7201d25783f4 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Tue, 21 Apr 2009 11:46:16 +0000 Subject: libcurl's memory.h renamed to curl_memory.h --- lib/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index ba337bc79..c1206cee5 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -81,7 +81,7 @@ #include "if2ip.h" #include "strerror.h" #include "connect.h" -#include "memory.h" +#include "curl_memory.h" #include "select.h" #include "url.h" /* for Curl_safefree() */ #include "multiif.h" -- cgit v1.2.1 From d068001102519c01970808e1ec572016ee3d3408 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 28 Apr 2009 20:27:06 +0000 Subject: - Constantine Sapuntzakis filed bug report #2783090 (http://curl.haxx.se/bug/view.cgi?id=2783090) pointing out that on windows we need to grow the SO_SNDBUF buffer somewhat to get really good upload speeds. http://support.microsoft.com/kb/823764 has the details. Friends confirmed that simply adding 32 to CURL_MAX_WRITE_SIZE is enough. --- lib/connect.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index c1206cee5..7727bf017 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -704,6 +704,27 @@ static void nosigpipe(struct connectdata *conn, #define nosigpipe(x,y) #endif +#ifdef WIN32 +/* When you run a program that uses the Windows Sockets API, you may + experience slow performance when you copy data to a TCP server. + + http://support.microsoft.com/kb/823764 + + Work-around: Make the Socket Send Buffer Size Larger Than the Program Send + Buffer Size + +*/ +static void sndbufset(struct connectdata *conn, + curl_socket_t sockfd) +{ + int val = CURL_MAX_WRITE_SIZE + 32; + setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (const char *)&val, sizeof(val)); +} +#else +#define sndbufset(x,y) +#endif + + /* singleipconnect() connects to the given IP only, and it may return without having connected if used from the multi interface. */ static curl_socket_t @@ -807,6 +828,8 @@ singleipconnect(struct connectdata *conn, nosigpipe(conn, sockfd); + sndbufset(conn, sockfd); + if(data->set.fsockopt) { /* activate callback for setting socket options */ error = data->set.fsockopt(data->set.sockopt_client, -- cgit v1.2.1 From c174b13f8b8820d7fd8bc67a1da26e9697e5aff3 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Thu, 30 Apr 2009 09:32:02 +0000 Subject: fix compiler warning: unused parameter --- lib/connect.c | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 7727bf017..d4b621f33 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -718,6 +718,7 @@ static void sndbufset(struct connectdata *conn, curl_socket_t sockfd) { int val = CURL_MAX_WRITE_SIZE + 32; + (void)conn; setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (const char *)&val, sizeof(val)); } #else -- cgit v1.2.1 From 9137e717b04644592b9b527839470337fdd9f44d Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Sat, 2 May 2009 02:37:32 +0000 Subject: Use build-time configured curl_socklen_t instead of socklen_t --- lib/connect.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index d4b621f33..d7b2f7fc0 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -281,7 +281,7 @@ static CURLcode bindlocal(struct connectdata *conn, struct Curl_sockaddr_storage sa; struct sockaddr *sock = (struct sockaddr *)&sa; /* bind to this address */ - socklen_t sizeof_sa = 0; /* size of the data sock points to */ + curl_socklen_t sizeof_sa = 0; /* size of the data sock points to */ struct sockaddr_in *si4 = (struct sockaddr_in *)&sa; #ifdef ENABLE_IPV6 struct sockaddr_in6 *si6 = (struct sockaddr_in6 *)&sa; @@ -427,7 +427,7 @@ static CURLcode bindlocal(struct connectdata *conn, if( bind(sockfd, sock, sizeof_sa) >= 0) { /* we succeeded to bind */ struct Curl_sockaddr_storage add; - socklen_t size = sizeof(add); + curl_socklen_t size = sizeof(add); memset(&add, 0, sizeof(struct Curl_sockaddr_storage)); if(getsockname(sockfd, (struct sockaddr *) &add, &size) < 0) { data->state.os_errno = error = SOCKERRNO; @@ -470,7 +470,7 @@ static bool verifyconnect(curl_socket_t sockfd, int *error) bool rc = TRUE; #ifdef SO_ERROR int err = 0; - socklen_t errSize = sizeof(err); + curl_socklen_t errSize = sizeof(err); #ifdef WIN32 /* @@ -657,7 +657,7 @@ static void tcpnodelay(struct connectdata *conn, { #ifdef TCP_NODELAY struct SessionHandle *data= conn->data; - socklen_t onoff = (socklen_t) data->set.tcp_nodelay; + curl_socklen_t onoff = (curl_socklen_t) data->set.tcp_nodelay; int proto = IPPROTO_TCP; #if 0 -- cgit v1.2.1 From 9c788a529beb63e95de5be013bb4b0f26f8456a0 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 7 May 2009 20:00:44 +0000 Subject: - Made the SO_SNDBUF setting for the data connection socket for ftp uploads as well. See change 28 Apr 2009. --- lib/connect.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index d7b2f7fc0..930b2b039 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -714,15 +714,13 @@ static void nosigpipe(struct connectdata *conn, Buffer Size */ -static void sndbufset(struct connectdata *conn, - curl_socket_t sockfd) +void Curl_sndbufset(curl_socket_t sockfd) { int val = CURL_MAX_WRITE_SIZE + 32; - (void)conn; setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (const char *)&val, sizeof(val)); } #else -#define sndbufset(x,y) +#define Curl_sndbufset(y) #endif @@ -829,7 +827,7 @@ singleipconnect(struct connectdata *conn, nosigpipe(conn, sockfd); - sndbufset(conn, sockfd); + Curl_sndbufset(sockfd); if(data->set.fsockopt) { /* activate callback for setting socket options */ -- cgit v1.2.1 From 6ca321ca75c8f8ad6808bcfd786ad8e84c790aff Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 7 May 2009 20:02:51 +0000 Subject: Curl_sndbufset is (at times) defined in the header, no need to do it again here --- lib/connect.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 930b2b039..49914e82f 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -719,8 +719,6 @@ void Curl_sndbufset(curl_socket_t sockfd) int val = CURL_MAX_WRITE_SIZE + 32; setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (const char *)&val, sizeof(val)); } -#else -#define Curl_sndbufset(y) #endif -- cgit v1.2.1 From d709cb2ae37c9d9512fe3a9724dd95b0fe49d108 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 9 Jul 2009 21:47:24 +0000 Subject: - Eric Wong introduced curlx_nonblock() that the curl tool now (re-)uses for setting a file descriptor non-blocking. Used by the functionality Eric himself brough on June 15th. --- lib/connect.c | 55 +------------------------------------------------------ 1 file changed, 1 insertion(+), 54 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 49914e82f..7865216bd 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -177,59 +177,6 @@ long Curl_timeleft(struct connectdata *conn, return timeout_ms; } - -/* - * Curl_nonblock() set the given socket to either blocking or non-blocking - * mode based on the 'nonblock' boolean argument. This function is highly - * portable. - */ -int Curl_nonblock(curl_socket_t sockfd, /* operate on this */ - int nonblock /* TRUE or FALSE */) -{ -#if defined(USE_BLOCKING_SOCKETS) - - return 0; /* returns success */ - -#elif defined(HAVE_FCNTL_O_NONBLOCK) - - /* most recent unix versions */ - int flags; - flags = fcntl(sockfd, F_GETFL, 0); - if(FALSE != nonblock) - return fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); - else - return fcntl(sockfd, F_SETFL, flags & (~O_NONBLOCK)); - -#elif defined(HAVE_IOCTL_FIONBIO) - - /* older unix versions */ - int flags; - flags = nonblock; - return ioctl(sockfd, FIONBIO, &flags); - -#elif defined(HAVE_IOCTLSOCKET_FIONBIO) - - /* Windows */ - unsigned long flags; - flags = nonblock; - return ioctlsocket(sockfd, FIONBIO, &flags); - -#elif defined(HAVE_IOCTLSOCKET_CAMEL_FIONBIO) - - /* Amiga */ - return IoctlSocket(sockfd, FIONBIO, (long)nonblock); - -#elif defined(HAVE_SETSOCKOPT_SO_NONBLOCK) - - /* BeOS */ - long b = nonblock ? 1 : 0; - return setsockopt(sockfd, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b)); - -#else -# error "no non-blocking method was found/used/set" -#endif -} - /* * waitconnect() waits for a TCP connect on the given socket for the specified * number if milliseconds. It returns: @@ -846,7 +793,7 @@ singleipconnect(struct connectdata *conn, } /* set socket non-blocking */ - Curl_nonblock(sockfd, TRUE); + curlx_nonblock(sockfd, TRUE); /* Connect TCP sockets, bind UDP */ if(conn->socktype == SOCK_STREAM) -- cgit v1.2.1 From 39704bec3c2d8c9542d42bc22e539ad0615aeb84 Mon Sep 17 00:00:00 2001 From: Gunter Knauf Date: Sat, 29 Aug 2009 04:12:51 +0000 Subject: add cast to silent compiler warning with 64bit systems. --- lib/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 7865216bd..2a6b003e0 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -277,7 +277,7 @@ static CURLcode bindlocal(struct connectdata *conn, * hostname or ip address. */ if(setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, - dev, strlen(dev)+1) != 0) { + dev, (curl_socklen_t)strlen(dev)+1) != 0) { error = SOCKERRNO; infof(data, "SO_BINDTODEVICE %s failed with errno %d: %s;" " will do regular bind\n", -- cgit v1.2.1 From 5ed274d0b7483085d5d8642daddace93b41316e7 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 1 Oct 2009 07:05:07 +0000 Subject: - Constantine Sapuntzakis: The current implementation will always set SO_SNDBUF to CURL_WRITE_SIZE even if the SO_SNDBUF starts out larger. The patch doesn't do a setsockopt if SO_SNDBUF is already greater than CURL_WRITE_SIZE. This should help folks who have set up their computer with large send buffers. --- lib/connect.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 2a6b003e0..aaeee6762 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -664,6 +664,13 @@ static void nosigpipe(struct connectdata *conn, void Curl_sndbufset(curl_socket_t sockfd) { int val = CURL_MAX_WRITE_SIZE + 32; + int curval = 0; + int curlen = sizeof(curval); + + if (getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (char *)&curval, &curlen) == 0) + if (curval > val) + return; + setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (const char *)&val, sizeof(val)); } #endif -- cgit v1.2.1 From b2339578854c2a261f264997e4c94b676d6a723a Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 1 Oct 2009 07:59:45 +0000 Subject: - Tom Mueller correctly reported in bug report #2870221 (http://curl.haxx.se/bug/view.cgi?id=2870221) that libcurl returned an incorrect return code from the internal trynextip() function which caused him grief. This is a regression that was introduced in 7.19.1 and I find it strange it hasn't hit us harder, but I won't persue into figuring out exactly why. --- lib/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index aaeee6762..affb7fec5 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -502,7 +502,7 @@ static bool trynextip(struct connectdata *conn, /* store the new socket descriptor */ conn->sock[sockindex] = sockfd; conn->ip_addr = ai; - break; + return FALSE; } ai = ai->ai_next; } -- cgit v1.2.1 From 3184a91ec86b2f35f16a8e11e2daa03fac8e91b6 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Wed, 30 Dec 2009 17:59:56 +0000 Subject: VMS specific preprocessor symbol checking adjustments --- lib/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index affb7fec5..ec3e43bd5 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -64,7 +64,7 @@ #undef in_addr_t #define in_addr_t unsigned long #endif -#ifdef VMS +#ifdef __VMS #include #include #endif -- cgit v1.2.1 From 377b2db05b71c798b76ec2c0d2284be66f020eea Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 11 Jan 2010 21:38:13 +0000 Subject: - Made sure that the progress callback is repeatedly called at a regular interval even during very slow connects. --- lib/connect.c | 47 +++++++++++++++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 16 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index ec3e43bd5..cca960d87 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -89,6 +89,7 @@ #include "inet_ntop.h" #include "inet_pton.h" #include "sslgen.h" /* for Curl_ssl_check_cxn() */ +#include "progress.h" /* The last #include file should be: */ #include "memdebug.h" @@ -192,7 +193,8 @@ long Curl_timeleft(struct connectdata *conn, #define WAITCONN_FDSET_ERROR 2 static -int waitconnect(curl_socket_t sockfd, /* socket */ +int waitconnect(struct connectdata *conn, + curl_socket_t sockfd, /* socket */ long timeout_msec) { int rc; @@ -203,21 +205,34 @@ int waitconnect(curl_socket_t sockfd, /* socket */ (void)verifyconnect(sockfd, NULL); #endif - /* now select() until we get connect or timeout */ - rc = Curl_socket_ready(CURL_SOCKET_BAD, sockfd, (int)timeout_msec); - if(-1 == rc) - /* error, no connect here, try next */ - return WAITCONN_SELECT_ERROR; + while(1) { - else if(0 == rc) - /* timeout, no connect today */ - return WAITCONN_TIMEOUT; + /* now select() until we get connect or timeout */ + rc = Curl_socket_ready(CURL_SOCKET_BAD, sockfd, (int)(timeout_msec>1000? + 1000:timeout_msec)); - if(rc & CURL_CSELECT_ERR) - /* error condition caught */ - return WAITCONN_FDSET_ERROR; + if(Curl_pgrsUpdate(conn)) + return CURLE_ABORTED_BY_CALLBACK; - /* we have a connect! */ + if(-1 == rc) + /* error, no connect here, try next */ + return WAITCONN_SELECT_ERROR; + + else if(0 == rc) { + /* timeout */ + timeout_msec -= 1000; + if(timeout_msec <= 0) + return WAITCONN_TIMEOUT; + + continue; + } + + if(rc & CURL_CSELECT_ERR) + /* error condition caught */ + return WAITCONN_FDSET_ERROR; + + break; + } return WAITCONN_CONNECTED; } @@ -553,7 +568,7 @@ CURLcode Curl_is_connected(struct connectdata *conn, Curl_expire(data, allow); /* check for connect without timeout as we want to return immediately */ - rc = waitconnect(sockfd, 0); + rc = waitconnect(conn, sockfd, 0); if(WAITCONN_CONNECTED == rc) { int error; @@ -823,7 +838,7 @@ singleipconnect(struct connectdata *conn, case EAGAIN: #endif #endif - rc = waitconnect(sockfd, timeout_ms); + rc = waitconnect(conn, sockfd, timeout_ms); break; default: /* unknown error, fallthrough and try another address! */ -- cgit v1.2.1 From 33ce0ec1f1951bc1a8f4d475381c1b7c95d4a03a Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 22 Jan 2010 23:21:39 +0000 Subject: wrap long lines and do some indent policing --- lib/connect.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index cca960d87..3ae38c990 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -734,12 +734,13 @@ singleipconnect(struct connectdata *conn, if(data->set.fopensocket) /* - * If the opensocket callback is set, all the destination address information - * is passed to the callback. Depending on this information the callback may - * opt to abort the connection, this is indicated returning CURL_SOCKET_BAD; - * otherwise it will return a not-connected socket. When the callback returns - * a valid socket the destination address information might have been changed - * and this 'new' address will actually be used here to connect. + * If the opensocket callback is set, all the destination address + * information is passed to the callback. Depending on this information the + * callback may opt to abort the connection, this is indicated returning + * CURL_SOCKET_BAD; otherwise it will return a not-connected socket. When + * the callback returns a valid socket the destination address information + * might have been changed and this 'new' address will actually be used + * here to connect. */ sockfd = data->set.fopensocket(data->set.opensocket_client, CURLSOCKTYPE_IPCXN, -- cgit v1.2.1 From d65cf7889b4ce669876f9e05442fd09f6fe40e37 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Thu, 28 Jan 2010 15:34:18 +0000 Subject: fix printf-style format strings --- lib/connect.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 3ae38c990..35c3d4855 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -581,7 +581,7 @@ CURLcode Curl_is_connected(struct connectdata *conn, data->state.os_errno = error; infof(data, "Connection failed\n"); if(trynextip(conn, sockindex, connected)) { - failf(data, "Failed connect to %s:%d; %s", + failf(data, "Failed connect to %s:%ld; %s", conn->host.name, conn->port, Curl_strerror(conn, error)); code = CURLE_COULDNT_CONNECT; } @@ -601,7 +601,7 @@ CURLcode Curl_is_connected(struct connectdata *conn, if(trynextip(conn, sockindex, connected)) { error = SOCKERRNO; data->state.os_errno = error; - failf(data, "Failed connect to %s:%d; %s", + failf(data, "Failed connect to %s:%ld; %s", conn->host.name, conn->port, Curl_strerror(conn, error)); code = CURLE_COULDNT_CONNECT; } -- cgit v1.2.1 From d1717e7c9079a5f2b6291fa1fefe95d1348f8cc5 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Tue, 2 Feb 2010 16:25:07 +0000 Subject: Fix compiler warning: conditional expression is constant --- lib/connect.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 35c3d4855..1d2947488 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -205,7 +205,7 @@ int waitconnect(struct connectdata *conn, (void)verifyconnect(sockfd, NULL); #endif - while(1) { + for(;;) { /* now select() until we get connect or timeout */ rc = Curl_socket_ready(CURL_SOCKET_BAD, sockfd, (int)(timeout_msec>1000? @@ -385,7 +385,7 @@ static CURLcode bindlocal(struct connectdata *conn, } } - do { + for(;;) { if( bind(sockfd, sock, sizeof_sa) >= 0) { /* we succeeded to bind */ struct Curl_sockaddr_storage add; @@ -415,7 +415,7 @@ static CURLcode bindlocal(struct connectdata *conn, } else break; - } while(1); + } data->state.os_errno = error = SOCKERRNO; failf(data, "bind failed with errno %d: %s", -- cgit v1.2.1 From 7aef172a347a0422a0968fde9c487639ff673383 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Thu, 4 Feb 2010 19:44:31 +0000 Subject: fix printf-style format strings --- lib/connect.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 1d2947488..5e94b8673 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -397,13 +397,13 @@ static CURLcode bindlocal(struct connectdata *conn, error, Curl_strerror(conn, error)); return CURLE_INTERFACE_FAILED; } - infof(data, "Local port: %d\n", port); + infof(data, "Local port: %hu\n", port); conn->bits.bound = TRUE; return CURLE_OK; } if(--portnum > 0) { - infof(data, "Bind to local port %d failed, trying next\n", port); + infof(data, "Bind to local port %hu failed, trying next\n", port); port++; /* try next port */ /* We re-use/clobber the port variable here below */ if(sock->sa_family == AF_INET) -- cgit v1.2.1 From 4b351d018e3d6691191fd653a17f14f4a31e0b4c Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 23 Mar 2010 23:29:23 +0100 Subject: mark connection as connected Kenny To filed the bug report #2963679 with patch to fix a problem he experienced with doing multi interface HTTP POST over a proxy using PROXYTUNNEL. He found a case where it would connect fine but bits.tcpconnect was not set correct so libcurl didn't work properly. (http://curl.haxx.se/bug/view.cgi?id=2963679) --- lib/connect.c | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 5e94b8673..c0f2012a8 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -574,6 +574,7 @@ CURLcode Curl_is_connected(struct connectdata *conn, int error; if(verifyconnect(sockfd, &error)) { /* we are connected, awesome! */ + conn->bits.tcpconnect = TRUE; *connected = TRUE; return CURLE_OK; } -- cgit v1.2.1 From 2309b4e330b96bc2e1f8e36b6184015e59544037 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 24 Mar 2010 11:02:54 +0100 Subject: remove the CVSish $Id$ lines --- lib/connect.c | 1 - 1 file changed, 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index c0f2012a8..eb6df71d4 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -18,7 +18,6 @@ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * - * $Id$ ***************************************************************************/ #include "setup.h" -- cgit v1.2.1 From adaf87530dc561314a2261fa6d26c38ce999876f Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 7 May 2010 23:49:29 +0200 Subject: multi interface: missed storing connection time Dirk Manske reported a regression. When connecting with the multi interface, there were situations where libcurl wouldn't store connect time correctly as it used to (and is documented to) do. Using his fine sample program we could repeat it, and I wrote up test case 573 using that code. The problem does not easily show itself using the local test suite though. The fix, also as suggested by Dirk, is a bit on the ugly side as it adds yet another call to Curl_verboseconnect() and setting the TIMER_CONNECT time. That situation is subject for some closer inspection in the future. --- lib/connect.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index eb6df71d4..4adc7f35a 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -575,6 +575,8 @@ CURLcode Curl_is_connected(struct connectdata *conn, /* we are connected, awesome! */ conn->bits.tcpconnect = TRUE; *connected = TRUE; + Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */ + Curl_verboseconnect(conn); return CURLE_OK; } /* nope, not connected for real */ -- cgit v1.2.1 From 8098d9417c649272b9d6d2ad76abbde7dfbfcad1 Mon Sep 17 00:00:00 2001 From: Frank Meier Date: Sat, 5 Jun 2010 00:29:09 +0200 Subject: getinfo: added *_PRIMARY_PORT, *_LOCAL_IP and *_LOCAL_PORT --- lib/connect.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 4adc7f35a..43e17aa63 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -523,6 +523,50 @@ static bool trynextip(struct connectdata *conn, return TRUE; } +/* retrieves ip address and port from a sockaddr structure */ +static void getaddressinfo(struct sockaddr* sa, char* addr, + long* port) +{ + struct sockaddr_in* si = NULL; +#ifdef ENABLE_IPV6 + struct sockaddr_in6* si6 = NULL; +#endif + + switch (sa->sa_family) { + case AF_INET: + si = (struct sockaddr_in*) sa; + Curl_inet_ntop(sa->sa_family, &(si->sin_addr), addr, MAX_IPADR_LEN); + *port = ntohs(si->sin_port); + break; +#ifdef ENABLE_IPV6 + case AF_INET6: + si6 = (struct sockaddr_in6*)sa; + Curl_inet_ntop(sa->sa_family, &(si6->sin6_addr), addr, MAX_IPADR_LEN); + *port = ntohs(si6->sin6_port); + break; +#endif + default: + addr[0] = '\0'; + *port = 0; + } +} + +/* retrieves the start/end point information of a socket of an established + connection */ +void Curl_updateconninfo(curl_socket_t sockfd, struct PureInfo* info) +{ + struct Curl_sockaddr_storage ssrem; + struct Curl_sockaddr_storage ssloc; + + socklen_t len = sizeof(struct Curl_sockaddr_storage); + + getpeername(sockfd, (struct sockaddr*) &ssrem, &len); + getsockname(sockfd, (struct sockaddr*) &ssloc, &len); + + getaddressinfo((struct sockaddr*)&ssrem, info->ip, &info->port); + getaddressinfo((struct sockaddr*)&ssloc, info->localip, &info->localport); +} + /* * Curl_is_connected() is used from the multi interface to check if the * firstsocket has connected. @@ -577,6 +621,8 @@ CURLcode Curl_is_connected(struct connectdata *conn, *connected = TRUE; Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */ Curl_verboseconnect(conn); + Curl_updateconninfo(sockfd, &(data->info)); + return CURLE_OK; } /* nope, not connected for real */ @@ -866,6 +912,7 @@ singleipconnect(struct connectdata *conn, /* we are connected, awesome! */ *connected = TRUE; /* this is a true connect */ infof(data, "connected\n"); + Curl_updateconninfo(sockfd, &(data->info)); return sockfd; } else if(WAITCONN_TIMEOUT == rc) -- cgit v1.2.1 From 4724b9d966e0785a875018a33861076501a83929 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Sat, 5 Jun 2010 15:08:26 +0200 Subject: replace socklen_t with curl_socklen_t --- lib/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 43e17aa63..207956693 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -558,7 +558,7 @@ void Curl_updateconninfo(curl_socket_t sockfd, struct PureInfo* info) struct Curl_sockaddr_storage ssrem; struct Curl_sockaddr_storage ssloc; - socklen_t len = sizeof(struct Curl_sockaddr_storage); + curl_socklen_t len = sizeof(struct Curl_sockaddr_storage); getpeername(sockfd, (struct sockaddr*) &ssrem, &len); getsockname(sockfd, (struct sockaddr*) &ssloc, &len); -- cgit v1.2.1 From f737e94164fd33cbb03a559ff51d4b4db59902ea Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Mon, 7 Jun 2010 16:53:31 +0200 Subject: Curl_updateconninfo() error handling fix --- lib/connect.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 49 insertions(+), 13 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 207956693..51d117389 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -524,9 +524,10 @@ static bool trynextip(struct connectdata *conn, } /* retrieves ip address and port from a sockaddr structure */ -static void getaddressinfo(struct sockaddr* sa, char* addr, +static bool getaddressinfo(struct sockaddr* sa, char* addr, long* port) { + unsigned short us_port; struct sockaddr_in* si = NULL; #ifdef ENABLE_IPV6 struct sockaddr_in6* si6 = NULL; @@ -535,36 +536,71 @@ static void getaddressinfo(struct sockaddr* sa, char* addr, switch (sa->sa_family) { case AF_INET: si = (struct sockaddr_in*) sa; - Curl_inet_ntop(sa->sa_family, &(si->sin_addr), addr, MAX_IPADR_LEN); - *port = ntohs(si->sin_port); + if(Curl_inet_ntop(sa->sa_family, &si->sin_addr, + addr, MAX_IPADR_LEN) != 0) + return FALSE; + us_port = ntohs(si->sin_port); + *port = us_port; break; #ifdef ENABLE_IPV6 case AF_INET6: si6 = (struct sockaddr_in6*)sa; - Curl_inet_ntop(sa->sa_family, &(si6->sin6_addr), addr, MAX_IPADR_LEN); - *port = ntohs(si6->sin6_port); + if(Curl_inet_ntop(sa->sa_family, &si6->sin6_addr, + addr, MAX_IPADR_LEN) != 0) + return FALSE; + us_port = ntohs(si6->sin6_port); + *port = us_port; break; #endif default: addr[0] = '\0'; *port = 0; } + return TRUE; } /* retrieves the start/end point information of a socket of an established connection */ -void Curl_updateconninfo(curl_socket_t sockfd, struct PureInfo* info) +void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd) { + int error; + curl_socklen_t len; struct Curl_sockaddr_storage ssrem; struct Curl_sockaddr_storage ssloc; + struct SessionHandle *data = conn->data; + struct PureInfo *info = &conn->data->info; + + len = sizeof(struct Curl_sockaddr_storage); + if(getpeername(sockfd, (struct sockaddr*) &ssrem, &len)) { + error = SOCKERRNO; + failf(data, "getpeername() failed with errno %d: %s", + error, Curl_strerror(conn, error)); + return; + } - curl_socklen_t len = sizeof(struct Curl_sockaddr_storage); + len = sizeof(struct Curl_sockaddr_storage); + if(getsockname(sockfd, (struct sockaddr*) &ssloc, &len)) { + error = SOCKERRNO; + failf(data, "getsockname() failed with errno %d: %s", + error, Curl_strerror(conn, error)); + return; + } - getpeername(sockfd, (struct sockaddr*) &ssrem, &len); - getsockname(sockfd, (struct sockaddr*) &ssloc, &len); + if(!getaddressinfo((struct sockaddr*)&ssrem, + info->ip, &info->port)) { + error = ERRNO; + failf(data, "ssrem inet_ntop() failed with errno %d: %s", + error, Curl_strerror(conn, error)); + return; + } - getaddressinfo((struct sockaddr*)&ssrem, info->ip, &info->port); - getaddressinfo((struct sockaddr*)&ssloc, info->localip, &info->localport); + if(!getaddressinfo((struct sockaddr*)&ssloc, + info->localip, &info->localport)) { + error = ERRNO; + failf(data, "ssloc inet_ntop() failed with errno %d: %s", + error, Curl_strerror(conn, error)); + return; + } } /* @@ -621,7 +657,7 @@ CURLcode Curl_is_connected(struct connectdata *conn, *connected = TRUE; Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */ Curl_verboseconnect(conn); - Curl_updateconninfo(sockfd, &(data->info)); + Curl_updateconninfo(conn, sockfd); return CURLE_OK; } @@ -912,7 +948,7 @@ singleipconnect(struct connectdata *conn, /* we are connected, awesome! */ *connected = TRUE; /* this is a true connect */ infof(data, "connected\n"); - Curl_updateconninfo(sockfd, &(data->info)); + Curl_updateconninfo(conn, sockfd); return sockfd; } else if(WAITCONN_TIMEOUT == rc) -- cgit v1.2.1 From cbdd1cbcdee97b39a5940b61ba96ee32800f524f Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Tue, 8 Jun 2010 16:16:34 +0200 Subject: fix function result checking --- lib/connect.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 51d117389..3ca6aa3ce 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -537,7 +537,7 @@ static bool getaddressinfo(struct sockaddr* sa, char* addr, case AF_INET: si = (struct sockaddr_in*) sa; if(Curl_inet_ntop(sa->sa_family, &si->sin_addr, - addr, MAX_IPADR_LEN) != 0) + addr, MAX_IPADR_LEN) == NULL) return FALSE; us_port = ntohs(si->sin_port); *port = us_port; @@ -546,7 +546,7 @@ static bool getaddressinfo(struct sockaddr* sa, char* addr, case AF_INET6: si6 = (struct sockaddr_in6*)sa; if(Curl_inet_ntop(sa->sa_family, &si6->sin6_addr, - addr, MAX_IPADR_LEN) != 0) + addr, MAX_IPADR_LEN) == NULL) return FALSE; us_port = ntohs(si6->sin6_port); *port = us_port; -- cgit v1.2.1 From feecf63a9607cce4c9339ad9f1b5a550e6bd2d98 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Tue, 8 Jun 2010 19:29:20 +0200 Subject: avoid redundant work when reusing same connection --- lib/connect.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 3ca6aa3ce..f917ed595 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -570,6 +570,10 @@ void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd) struct SessionHandle *data = conn->data; struct PureInfo *info = &conn->data->info; + if(conn->bits.reuse) + /* reusing same connection */ + return; + len = sizeof(struct Curl_sockaddr_storage); if(getpeername(sockfd, (struct sockaddr*) &ssrem, &len)) { error = SOCKERRNO; -- cgit v1.2.1 From 8da56e12c6f8bc1306d1c5db8818933a6ef013d3 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 24 Jun 2010 23:19:27 +0200 Subject: multi_socket: re-use of same socket without notifying app When a hostname resolves to multiple IP addresses and the first one tried doesn't work, the socket for the second attempt may get dropped on the floor, causing the request to eventually time out. The issue is that when using kqueue (as on mac and bsd platforms) instead of select, the kernel removes the first fd from kqueue when it is closed (in trynextip, connect.c:503). Trynextip() then goes on to open a new socket, which gets assigned the same number as the one it just closed. Later in multi.c, socket_cb is not called because the fd is already in multi->sockhash, so the new socket is never added to kqueue. The correct fix is to ensure that socket_cb is called to remove the fd when trynextip() closes the socket, and again to re-add it after singleipsocket(). I'm not sure how to cleanly do that, but the attached patch works around the problem in an admittedly kludgy way by delaying the close to ensure that the newly-opened socket gets a different fd. Daniel's added comment: I didn't spot a way to easily do a nicer fix so I've proceeded with Ben's patch. Bug: http://curl.haxx.se/bug/view.cgi?id=3017819 Patch by: Ben Darnell --- lib/connect.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index f917ed595..12e71278e 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -499,13 +499,18 @@ static bool trynextip(struct connectdata *conn, curl_socket_t sockfd; Curl_addrinfo *ai; - /* first close the failed socket */ - sclose(conn->sock[sockindex]); + /* First clean up after the failed socket. + Don't close it yet to ensure that the next IP's socket gets a different + file descriptor, which can prevent bugs when the curl_multi_socket_action + interface is used with certain select() replacements such as kqueue. */ + curl_socket_t fd_to_close = conn->sock[sockindex]; conn->sock[sockindex] = CURL_SOCKET_BAD; *connected = FALSE; - if(sockindex != FIRSTSOCKET) + if(sockindex != FIRSTSOCKET) { + sclose(fd_to_close); return TRUE; /* no next */ + } /* try the next address */ ai = conn->ip_addr->ai_next; @@ -516,10 +521,12 @@ static bool trynextip(struct connectdata *conn, /* store the new socket descriptor */ conn->sock[sockindex] = sockfd; conn->ip_addr = ai; + sclose(fd_to_close); return FALSE; } ai = ai->ai_next; } + sclose(fd_to_close); return TRUE; } -- cgit v1.2.1 From 37201e3c36541a1a7f14424860e1f685eaa83e7c Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 10 Aug 2010 15:28:46 +0200 Subject: callbacks: acknowledge progress callback error returns When the progress callback is called during the TCP connection, an error return would accidentally not abort the operation as intended but would instead be counted as a failure to connect to that particular IP and libcurl would just continue to try the next. I made singleipconnect() and trynextip() return CURLcode properly. Added bonus: it corrected the error code for bad --interface usages, like tested in test 1084 and test 1085. Reported by: Adam Light Bug: http://curl.haxx.se/mail/lib-2010-08/0105.html --- lib/connect.c | 79 ++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 49 insertions(+), 30 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 12e71278e..0495887b0 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -112,10 +112,11 @@ struct Curl_sockaddr_ex { static bool verifyconnect(curl_socket_t sockfd, int *error); -static curl_socket_t +static CURLcode singleipconnect(struct connectdata *conn, const Curl_addrinfo *ai, /* start connecting to this */ long timeout_ms, + curl_socket_t *sock, bool *connected); /* @@ -180,16 +181,13 @@ long Curl_timeleft(struct connectdata *conn, /* * waitconnect() waits for a TCP connect on the given socket for the specified * number if milliseconds. It returns: - * 0 fine connect - * -1 select() error - * 1 select() timeout - * 2 select() returned with an error condition fd_set */ #define WAITCONN_CONNECTED 0 #define WAITCONN_SELECT_ERROR -1 #define WAITCONN_TIMEOUT 1 #define WAITCONN_FDSET_ERROR 2 +#define WAITCONN_ABORTED 3 static int waitconnect(struct connectdata *conn, @@ -209,9 +207,8 @@ int waitconnect(struct connectdata *conn, /* now select() until we get connect or timeout */ rc = Curl_socket_ready(CURL_SOCKET_BAD, sockfd, (int)(timeout_msec>1000? 1000:timeout_msec)); - if(Curl_pgrsUpdate(conn)) - return CURLE_ABORTED_BY_CALLBACK; + return WAITCONN_ABORTED; if(-1 == rc) /* error, no connect here, try next */ @@ -492,9 +489,9 @@ static bool verifyconnect(curl_socket_t sockfd, int *error) /* Used within the multi interface. Try next IP address, return TRUE if no more address exists or error */ -static bool trynextip(struct connectdata *conn, - int sockindex, - bool *connected) +static CURLcode trynextip(struct connectdata *conn, + int sockindex, + bool *connected) { curl_socket_t sockfd; Curl_addrinfo *ai; @@ -509,25 +506,27 @@ static bool trynextip(struct connectdata *conn, if(sockindex != FIRSTSOCKET) { sclose(fd_to_close); - return TRUE; /* no next */ + return CURLE_COULDNT_CONNECT; /* no next */ } /* try the next address */ ai = conn->ip_addr->ai_next; while(ai) { - sockfd = singleipconnect(conn, ai, 0L, connected); + CURLcode res = singleipconnect(conn, ai, 0L, &sockfd, connected); + if(res) + return res; if(sockfd != CURL_SOCKET_BAD) { /* store the new socket descriptor */ conn->sock[sockindex] = sockfd; conn->ip_addr = ai; sclose(fd_to_close); - return FALSE; + return CURLE_OK; } ai = ai->ai_next; } sclose(fd_to_close); - return TRUE; + return CURLE_COULDNT_CONNECT; } /* retrieves ip address and port from a sockaddr structure */ @@ -675,11 +674,10 @@ CURLcode Curl_is_connected(struct connectdata *conn, /* nope, not connected for real */ data->state.os_errno = error; infof(data, "Connection failed\n"); - if(trynextip(conn, sockindex, connected)) { + code = trynextip(conn, sockindex, connected); + if(code) failf(data, "Failed connect to %s:%ld; %s", conn->host.name, conn->port, Curl_strerror(conn, error)); - code = CURLE_COULDNT_CONNECT; - } } else if(WAITCONN_TIMEOUT != rc) { int error = 0; @@ -693,12 +691,13 @@ CURLcode Curl_is_connected(struct connectdata *conn, else infof(data, "Connection failed\n"); - if(trynextip(conn, sockindex, connected)) { + code = trynextip(conn, sockindex, connected); + + if(code) { error = SOCKERRNO; data->state.os_errno = error; failf(data, "Failed connect to %s:%ld; %s", conn->host.name, conn->port, Curl_strerror(conn, error)); - code = CURLE_COULDNT_CONNECT; } } /* @@ -786,12 +785,20 @@ void Curl_sndbufset(curl_socket_t sockfd) #endif -/* singleipconnect() connects to the given IP only, and it may return without - having connected if used from the multi interface. */ -static curl_socket_t +/* + * singleipconnect() + * + * Note that even on connect fail it returns CURLE_OK, but with 'sock' set to + * CURL_SOCKET_BAD. Other errors will however return proper errors. + * + * singleipconnect() connects to the given IP only, and it may return without + * having connected if used from the multi interface. + */ +static CURLcode singleipconnect(struct connectdata *conn, const Curl_addrinfo *ai, long timeout_ms, + curl_socket_t *sockp, bool *connected) { struct Curl_sockaddr_ex addr; @@ -801,13 +808,15 @@ singleipconnect(struct connectdata *conn, bool isconnected; struct SessionHandle *data = conn->data; curl_socket_t sockfd; - CURLcode res; + CURLcode res = CURLE_OK; const void *iptoprint; struct sockaddr_in * const sa4 = (void *)&addr.sa_addr; #ifdef ENABLE_IPV6 struct sockaddr_in6 * const sa6 = (void *)&addr.sa_addr; #endif + *sockp = CURL_SOCKET_BAD; + /* * The Curl_sockaddr_ex structure is basically libcurl's external API * curl_sockaddr structure with enough space available to directly hold @@ -846,7 +855,7 @@ singleipconnect(struct connectdata *conn, if(sockfd == CURL_SOCKET_BAD) /* no socket, no connection */ - return CURL_SOCKET_BAD; + return CURLE_OK; #if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID) if (conn->scope && (addr.family == AF_INET6)) @@ -899,7 +908,7 @@ singleipconnect(struct connectdata *conn, CURLSOCKTYPE_IPCXN); if(error) { sclose(sockfd); /* close the socket and bail out */ - return CURL_SOCKET_BAD; + return res; } } @@ -907,7 +916,7 @@ singleipconnect(struct connectdata *conn, res = bindlocal(conn, sockfd, addr.family); if(res) { sclose(sockfd); /* close socket and bail out */ - return CURL_SOCKET_BAD; + return res; } /* set socket non-blocking */ @@ -935,6 +944,10 @@ singleipconnect(struct connectdata *conn, #endif #endif rc = waitconnect(conn, sockfd, timeout_ms); + if(WAITCONN_ABORTED == rc) { + sclose(sockfd); + return CURLE_ABORTED_BY_CALLBACK; + } break; default: /* unknown error, fallthrough and try another address! */ @@ -950,7 +963,8 @@ singleipconnect(struct connectdata *conn, if((WAITCONN_TIMEOUT == rc) && (data->state.used_interface == Curl_if_multi)) { /* Timeout when running the multi interface */ - return sockfd; + *sockp = sockfd; + return CURLE_OK; } isconnected = verifyconnect(sockfd, &error); @@ -960,7 +974,8 @@ singleipconnect(struct connectdata *conn, *connected = TRUE; /* this is a true connect */ infof(data, "connected\n"); Curl_updateconninfo(conn, sockfd); - return sockfd; + *sockp = sockfd; + return CURLE_OK; } else if(WAITCONN_TIMEOUT == rc) infof(data, "Timeout\n"); @@ -972,7 +987,7 @@ singleipconnect(struct connectdata *conn, /* connect failed or timed out */ sclose(sockfd); - return CURL_SOCKET_BAD; + return CURLE_OK; } /* @@ -1037,7 +1052,11 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ curr_addr = curr_addr->ai_next, aliasindex++) { /* start connecting to the IP curr_addr points to */ - sockfd = singleipconnect(conn, curr_addr, timeout_per_addr, connected); + CURLcode res = + singleipconnect(conn, curr_addr, timeout_per_addr, &sockfd, connected); + + if(res) + return res; if(sockfd != CURL_SOCKET_BAD) break; -- cgit v1.2.1 From ab6681c2c89ad985984e964c5d121340be011a91 Mon Sep 17 00:00:00 2001 From: Dirk Manske Date: Sat, 21 Aug 2010 00:29:35 +0200 Subject: Curl_is_connected: use correct errno The correctly extracted errno contents were mistakenly overwritten by a newer value that wasn't the correct error value. Bug: http://curl.haxx.se/mail/lib-2010-08/0242.html --- lib/connect.c | 45 ++++++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 23 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 0495887b0..771129b5a 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -627,6 +627,7 @@ CURLcode Curl_is_connected(struct connectdata *conn, CURLcode code = CURLE_OK; curl_socket_t sockfd = conn->sock[sockindex]; long allow = DEFAULT_CONNECT_TIMEOUT; + int error = 0; DEBUGASSERT(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET); @@ -658,9 +659,11 @@ CURLcode Curl_is_connected(struct connectdata *conn, /* check for connect without timeout as we want to return immediately */ rc = waitconnect(conn, sockfd, 0); + if(WAITCONN_TIMEOUT == rc) + /* not an error, but also no connection yet */ + return code; if(WAITCONN_CONNECTED == rc) { - int error; if(verifyconnect(sockfd, &error)) { /* we are connected, awesome! */ conn->bits.tcpconnect = TRUE; @@ -672,38 +675,34 @@ CURLcode Curl_is_connected(struct connectdata *conn, return CURLE_OK; } /* nope, not connected for real */ - data->state.os_errno = error; - infof(data, "Connection failed\n"); - code = trynextip(conn, sockindex, connected); - if(code) - failf(data, "Failed connect to %s:%ld; %s", - conn->host.name, conn->port, Curl_strerror(conn, error)); } - else if(WAITCONN_TIMEOUT != rc) { - int error = 0; - + else { /* nope, not connected */ if(WAITCONN_FDSET_ERROR == rc) { (void)verifyconnect(sockfd, &error); - data->state.os_errno = error; - infof(data, "%s\n",Curl_strerror(conn,error)); + infof(data, "%s\n",Curl_strerror(conn, error)); } else infof(data, "Connection failed\n"); - - code = trynextip(conn, sockindex, connected); - - if(code) { - error = SOCKERRNO; - data->state.os_errno = error; - failf(data, "Failed connect to %s:%ld; %s", - conn->host.name, conn->port, Curl_strerror(conn, error)); - } } + /* - * If the connection failed here, we should attempt to connect to the "next - * address" for the given host. + * The connection failed here, we should attempt to connect to the "next + * address" for the given host. But first remember the latest error. */ + if(error) { + data->state.os_errno = error; + SET_SOCKERRNO(error); + } + + code = trynextip(conn, sockindex, connected); + + if(code) { + error = SOCKERRNO; + data->state.os_errno = error; + failf(data, "Failed connect to %s:%ld; %s", + conn->host.name, conn->port, Curl_strerror(conn, error)); + } return code; } -- cgit v1.2.1 From c6fa1952a14ba2fa14f4a3483f1f573560ef3133 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 6 Sep 2010 00:02:54 +0200 Subject: portabilty: use proper variable type to hold sockets Curl_getconnectinfo() is changed to return a proper curl_socket_t for the last socket so that it'll work more portably (and cause less compiler warnings). --- lib/connect.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 771129b5a..172ccbbbf 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -1093,12 +1093,12 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ * Used to extract socket and connectdata struct for the most recent * transfer on the given SessionHandle. * - * The socket 'long' will be -1 in case of failure! + * The returned socket will be CURL_SOCKET_BAD in case of failure! */ -CURLcode Curl_getconnectinfo(struct SessionHandle *data, - long *param_longp, - struct connectdata **connp) +curl_socket_t Curl_getconnectinfo(struct SessionHandle *data, + struct connectdata **connp) { + curl_socket_t sockfd; if((data->state.lastconnect != -1) && (data->state.connc->connects[data->state.lastconnect] != NULL)) { struct connectdata *c = @@ -1106,13 +1106,13 @@ CURLcode Curl_getconnectinfo(struct SessionHandle *data, if(connp) /* only store this if the caller cares for it */ *connp = c; - *param_longp = c->sock[FIRSTSOCKET]; + sockfd = c->sock[FIRSTSOCKET]; /* we have a socket connected, let's determine if the server shut down */ /* determine if ssl */ if(c->ssl[FIRSTSOCKET].use) { /* use the SSL context */ if(!Curl_ssl_check_cxn(c)) - *param_longp = -1; /* FIN received */ + return CURL_SOCKET_BAD; /* FIN received */ } /* Minix 3.1 doesn't support any flags on recv; just assume socket is OK */ #ifdef MSG_PEEK @@ -1121,13 +1121,13 @@ CURLcode Curl_getconnectinfo(struct SessionHandle *data, char buf; if(recv((RECV_TYPE_ARG1)c->sock[FIRSTSOCKET], (RECV_TYPE_ARG2)&buf, (RECV_TYPE_ARG3)1, (RECV_TYPE_ARG4)MSG_PEEK) == 0) { - *param_longp = -1; /* FIN received */ + return CURL_SOCKET_BAD; /* FIN received */ } } #endif } else - *param_longp = -1; + return CURL_SOCKET_BAD; - return CURLE_OK; + return sockfd; } -- cgit v1.2.1 From 296b246b9cd1da5d13c56254e1c68914f8756a2e Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 14 Sep 2010 22:40:05 +0200 Subject: multi: don't do extra expire calls for the connection The timeout is set for the connect phase already at the start of the request so we should not add a new one, and we MUST not set expire to 0 as that will remove any other potentially existing timeouts. --- lib/connect.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 172ccbbbf..e440913e9 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -635,13 +635,6 @@ CURLcode Curl_is_connected(struct connectdata *conn, if(conn->bits.tcpconnect) { /* we are connected already! */ - long allow_total = 0; - - /* subtract the most strict timeout of the ones */ - if(data->set.timeout) - allow_total = data->set.timeout; - - Curl_expire(data, allow_total); *connected = TRUE; return CURLE_OK; } @@ -655,8 +648,6 @@ CURLcode Curl_is_connected(struct connectdata *conn, return CURLE_OPERATION_TIMEDOUT; } - Curl_expire(data, allow); - /* check for connect without timeout as we want to return immediately */ rc = waitconnect(conn, sockfd, 0); if(WAITCONN_TIMEOUT == rc) @@ -1028,7 +1019,6 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ failf(data, "Connection time-out"); return CURLE_OPERATION_TIMEDOUT; } - Curl_expire(data, timeout_ms); /* Max time for each address */ num_addr = Curl_num_addresses(remotehost->addr); -- cgit v1.2.1 From 3880dd3741204965dde312643a18190a24c66ba9 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 17 Sep 2010 22:58:08 +0200 Subject: Curl_timeleft: avoid returning "no timeout" by mistake As this function uses return code 0 to mean that there is no timeout, it needs to check that it doesn't return a time left value that is exactly zero. It could lead to libcurl doing an extra 1000 ms select() call and thus not timing out as accurately as it should. I fell over this bug when working on the bug 3061535 but this fix does not correct that problem alone, although this is a problem that needs to be fixed. Reported by: Rodric Glaser Bug: http://curl.haxx.se/bug/view.cgi?id=3061535 --- lib/connect.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index e440913e9..e178633d8 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -174,6 +174,9 @@ long Curl_timeleft(struct connectdata *conn, /* substract elapsed time */ timeout_ms -= Curl_tvdiff(*nowp, data->progress.t_startsingle); + if(!timeout_ms) + /* avoid returning 0 as that means no timeout! */ + return -1; return timeout_ms; } -- cgit v1.2.1 From a1f32ffee540bcef046dc499938585c5da9d0aa8 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 11 Nov 2010 14:51:39 +0100 Subject: ip_version: moved to connection struct The IP version choice was previously only in the UserDefined struct within the SessionHandle, but since we sometimes alter that option during a request we need to have it on a per-connection basis. I also moved more "init conn" code into the allocate_conn() function which is designed for that purpose more or less. --- lib/connect.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index e178633d8..88fb7eb76 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -310,20 +310,20 @@ static CURLcode bindlocal(struct connectdata *conn, * of the connection. The resolve functions should really be changed * to take a type parameter instead. */ - long ipver = data->set.ip_version; + long ipver = conn->ip_version; int rc; if (af == AF_INET) - data->set.ip_version = CURL_IPRESOLVE_V4; + conn->ip_version = CURL_IPRESOLVE_V4; #ifdef ENABLE_IPV6 else if (af == AF_INET6) - data->set.ip_version = CURL_IPRESOLVE_V6; + conn->ip_version = CURL_IPRESOLVE_V6; #endif rc = Curl_resolv(conn, dev, 0, &h); if(rc == CURLRESOLV_PENDING) (void)Curl_wait_for_resolv(conn, &h); - data->set.ip_version = ipver; + conn->ip_version = ipver; if(h) { /* convert the resolved address, sizeof myhost >= INET_ADDRSTRLEN */ -- cgit v1.2.1 From f6f5d7874f6a890f2626195f169abcbfc785b220 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Tue, 30 Nov 2010 06:20:54 +0100 Subject: fix getinfo CURLINFO_LOCAL* for reused connections --- lib/connect.c | 58 +++++++++++++++++++++++----------------------------------- 1 file changed, 23 insertions(+), 35 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 88fb7eb76..95033fa81 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -541,6 +541,9 @@ static bool getaddressinfo(struct sockaddr* sa, char* addr, #ifdef ENABLE_IPV6 struct sockaddr_in6* si6 = NULL; #endif +#if defined(HAVE_SYS_UN_H) && defined(AF_UNIX) + struct sockaddr_un* su = NULL; +#endif switch (sa->sa_family) { case AF_INET: @@ -560,6 +563,13 @@ static bool getaddressinfo(struct sockaddr* sa, char* addr, us_port = ntohs(si6->sin6_port); *port = us_port; break; +#endif +#if defined(HAVE_SYS_UN_H) && defined(AF_UNIX) + case AF_UNIX: + su = (struct sockaddr_un*)sa; + snprintf(addr, MAX_IPADR_LEN, "%s", su->sun_path); + *port = 0; + break; #endif default: addr[0] = '\0'; @@ -600,7 +610,7 @@ void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd) } if(!getaddressinfo((struct sockaddr*)&ssrem, - info->ip, &info->port)) { + info->primary_ip, &info->primary_port)) { error = ERRNO; failf(data, "ssrem inet_ntop() failed with errno %d: %s", error, Curl_strerror(conn, error)); @@ -608,7 +618,7 @@ void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd) } if(!getaddressinfo((struct sockaddr*)&ssloc, - info->localip, &info->localport)) { + info->local_ip, &info->local_port)) { error = ERRNO; failf(data, "ssloc inet_ntop() failed with errno %d: %s", error, Curl_strerror(conn, error)); @@ -802,11 +812,6 @@ singleipconnect(struct connectdata *conn, struct SessionHandle *data = conn->data; curl_socket_t sockfd; CURLcode res = CURLE_OK; - const void *iptoprint; - struct sockaddr_in * const sa4 = (void *)&addr.sa_addr; -#ifdef ENABLE_IPV6 - struct sockaddr_in6 * const sa6 = (void *)&addr.sa_addr; -#endif *sockp = CURL_SOCKET_BAD; @@ -855,37 +860,20 @@ singleipconnect(struct connectdata *conn, sa6->sin6_scope_id = conn->scope; #endif - /* FIXME: do we have Curl_printable_address-like with struct sockaddr* as - argument? */ -#if defined(HAVE_SYS_UN_H) && defined(AF_UNIX) - if(addr.family == AF_UNIX) { - infof(data, " Trying %s... ", - ((const struct sockaddr_un*)(&addr.sa_addr))->sun_path); - snprintf(data->info.ip, MAX_IPADR_LEN, "%s", - ((const struct sockaddr_un*)(&addr.sa_addr))->sun_path); - strcpy(conn->ip_addr_str, data->info.ip); + /* store remote address and port used in this connection attempt */ + if(!getaddressinfo((struct sockaddr*)&addr.sa_addr, + data->info.primary_ip, &data->info.primary_port)) { + error = ERRNO; + failf(data, "sa_addr inet_ntop() failed with errno %d: %s", + error, Curl_strerror(conn, error)); } - else -#endif - { + strcpy(conn->ip_addr_str, data->info.primary_ip); + infof(data, " Trying %s... ", conn->ip_addr_str); + #ifdef ENABLE_IPV6 - if(addr.family == AF_INET6) { - iptoprint = &sa6->sin6_addr; - conn->bits.ipv6 = TRUE; - } - else + if(addr.family == AF_INET6) + conn->bits.ipv6 = TRUE; #endif - { - iptoprint = &sa4->sin_addr; - } - - if(Curl_inet_ntop(addr.family, iptoprint, addr_buf, - sizeof(addr_buf)) != NULL) { - infof(data, " Trying %s... ", addr_buf); - snprintf(data->info.ip, MAX_IPADR_LEN, "%s", addr_buf); - strcpy(conn->ip_addr_str, data->info.ip); - } - } if(data->set.tcp_nodelay) tcpnodelay(conn, sockfd); -- cgit v1.2.1 From 1b2b93e0746ed09daf62ffc55cff1dcaaa3dff09 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Tue, 30 Nov 2010 13:42:02 +0100 Subject: fix getinfo CURLINFO_LOCAL* for reused connections follow-up Reinstate IPV6 build variable that got removed. --- lib/connect.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 95033fa81..3d829f7b7 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -812,6 +812,9 @@ singleipconnect(struct connectdata *conn, struct SessionHandle *data = conn->data; curl_socket_t sockfd; CURLcode res = CURLE_OK; +#ifdef ENABLE_IPV6 + struct sockaddr_in6 * const sa6 = (void *)&addr.sa_addr; +#endif *sockp = CURL_SOCKET_BAD; -- cgit v1.2.1 From 11cddb68e0ff73c8297b85e51bebaf6f968a8d62 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Tue, 30 Nov 2010 22:14:37 +0100 Subject: fix getinfo CURLINFO_LOCAL* for reused connections (take 2) --- lib/connect.c | 80 +++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 47 insertions(+), 33 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 3d829f7b7..0e5a73cb0 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -532,6 +532,16 @@ static CURLcode trynextip(struct connectdata *conn, return CURLE_COULDNT_CONNECT; } +/* Copies connection info into the session handle to make it available + when the session handle is no longer associated with a connection. */ +void Curl_persistconninfo(struct connectdata *conn) +{ + memcpy(conn->data->info.conn_primary_ip, conn->primary_ip, MAX_IPADR_LEN); + memcpy(conn->data->info.conn_local_ip, conn->local_ip, MAX_IPADR_LEN); + conn->data->info.conn_primary_port = conn->primary_port; + conn->data->info.conn_local_port = conn->local_port; +} + /* retrieves ip address and port from a sockaddr structure */ static bool getaddressinfo(struct sockaddr* sa, char* addr, long* port) @@ -587,43 +597,45 @@ void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd) struct Curl_sockaddr_storage ssrem; struct Curl_sockaddr_storage ssloc; struct SessionHandle *data = conn->data; - struct PureInfo *info = &conn->data->info; - if(conn->bits.reuse) - /* reusing same connection */ - return; + if(!conn->bits.reuse) { - len = sizeof(struct Curl_sockaddr_storage); - if(getpeername(sockfd, (struct sockaddr*) &ssrem, &len)) { - error = SOCKERRNO; - failf(data, "getpeername() failed with errno %d: %s", - error, Curl_strerror(conn, error)); - return; - } + len = sizeof(struct Curl_sockaddr_storage); + if(getpeername(sockfd, (struct sockaddr*) &ssrem, &len)) { + error = SOCKERRNO; + failf(data, "getpeername() failed with errno %d: %s", + error, Curl_strerror(conn, error)); + return; + } - len = sizeof(struct Curl_sockaddr_storage); - if(getsockname(sockfd, (struct sockaddr*) &ssloc, &len)) { - error = SOCKERRNO; - failf(data, "getsockname() failed with errno %d: %s", - error, Curl_strerror(conn, error)); - return; - } + len = sizeof(struct Curl_sockaddr_storage); + if(getsockname(sockfd, (struct sockaddr*) &ssloc, &len)) { + error = SOCKERRNO; + failf(data, "getsockname() failed with errno %d: %s", + error, Curl_strerror(conn, error)); + return; + } - if(!getaddressinfo((struct sockaddr*)&ssrem, - info->primary_ip, &info->primary_port)) { - error = ERRNO; - failf(data, "ssrem inet_ntop() failed with errno %d: %s", - error, Curl_strerror(conn, error)); - return; - } + if(!getaddressinfo((struct sockaddr*)&ssrem, + conn->primary_ip, &conn->primary_port)) { + error = ERRNO; + failf(data, "ssrem inet_ntop() failed with errno %d: %s", + error, Curl_strerror(conn, error)); + return; + } + + if(!getaddressinfo((struct sockaddr*)&ssloc, + conn->local_ip, &conn->local_port)) { + error = ERRNO; + failf(data, "ssloc inet_ntop() failed with errno %d: %s", + error, Curl_strerror(conn, error)); + return; + } - if(!getaddressinfo((struct sockaddr*)&ssloc, - info->local_ip, &info->local_port)) { - error = ERRNO; - failf(data, "ssloc inet_ntop() failed with errno %d: %s", - error, Curl_strerror(conn, error)); - return; } + + /* persist connection info in session handle */ + Curl_persistconninfo(conn); } /* @@ -865,14 +877,16 @@ singleipconnect(struct connectdata *conn, /* store remote address and port used in this connection attempt */ if(!getaddressinfo((struct sockaddr*)&addr.sa_addr, - data->info.primary_ip, &data->info.primary_port)) { + conn->primary_ip, &conn->primary_port)) { error = ERRNO; failf(data, "sa_addr inet_ntop() failed with errno %d: %s", error, Curl_strerror(conn, error)); } - strcpy(conn->ip_addr_str, data->info.primary_ip); + memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN); infof(data, " Trying %s... ", conn->ip_addr_str); + Curl_persistconninfo(conn); + #ifdef ENABLE_IPV6 if(addr.family == AF_INET6) conn->bits.ipv6 = TRUE; -- cgit v1.2.1 From 5d47bf377668846d915c3d8a3f22cfdf66041512 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Wed, 1 Dec 2010 17:30:52 +0100 Subject: connect: fix compiler warning: unused variable --- lib/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 0e5a73cb0..dd7eb7276 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -824,7 +824,7 @@ singleipconnect(struct connectdata *conn, struct SessionHandle *data = conn->data; curl_socket_t sockfd; CURLcode res = CURLE_OK; -#ifdef ENABLE_IPV6 +#if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID) struct sockaddr_in6 * const sa6 = (void *)&addr.sa_addr; #endif -- cgit v1.2.1 From 46a0062dffca452142d6d91bc3ca07c018d93ec2 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Fri, 3 Dec 2010 14:29:06 +0100 Subject: fix getinfo CURLINFO_LOCAL* for reused connections (take 2) follow-up - Show address string from proper buffer in case of connection failure. - Try next address when inet_ntop() fails. --- lib/connect.c | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index dd7eb7276..7638854b3 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -559,19 +559,21 @@ static bool getaddressinfo(struct sockaddr* sa, char* addr, case AF_INET: si = (struct sockaddr_in*) sa; if(Curl_inet_ntop(sa->sa_family, &si->sin_addr, - addr, MAX_IPADR_LEN) == NULL) - return FALSE; - us_port = ntohs(si->sin_port); - *port = us_port; + addr, MAX_IPADR_LEN)) { + us_port = ntohs(si->sin_port); + *port = us_port; + return TRUE; + } break; #ifdef ENABLE_IPV6 case AF_INET6: si6 = (struct sockaddr_in6*)sa; if(Curl_inet_ntop(sa->sa_family, &si6->sin6_addr, - addr, MAX_IPADR_LEN) == NULL) - return FALSE; - us_port = ntohs(si6->sin6_port); - *port = us_port; + addr, MAX_IPADR_LEN)) { + us_port = ntohs(si6->sin6_port); + *port = us_port; + return TRUE; + } break; #endif #if defined(HAVE_SYS_UN_H) && defined(AF_UNIX) @@ -579,13 +581,16 @@ static bool getaddressinfo(struct sockaddr* sa, char* addr, su = (struct sockaddr_un*)sa; snprintf(addr, MAX_IPADR_LEN, "%s", su->sun_path); *port = 0; - break; + return TRUE; #endif default: - addr[0] = '\0'; - *port = 0; + break; } - return TRUE; + + addr[0] = '\0'; + *port = 0; + + return FALSE; } /* retrieves the start/end point information of a socket of an established @@ -817,7 +822,6 @@ singleipconnect(struct connectdata *conn, bool *connected) { struct Curl_sockaddr_ex addr; - char addr_buf[128]; int rc; int error; bool isconnected; @@ -878,9 +882,12 @@ singleipconnect(struct connectdata *conn, /* store remote address and port used in this connection attempt */ if(!getaddressinfo((struct sockaddr*)&addr.sa_addr, conn->primary_ip, &conn->primary_port)) { + /* malformed address or bug in inet_ntop, try next address */ error = ERRNO; failf(data, "sa_addr inet_ntop() failed with errno %d: %s", error, Curl_strerror(conn, error)); + sclose(sockfd); + return CURLE_OK; } memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN); infof(data, " Trying %s... ", conn->ip_addr_str); @@ -950,7 +957,7 @@ singleipconnect(struct connectdata *conn, default: /* unknown error, fallthrough and try another address! */ failf(data, "Failed to connect to %s: %s", - addr_buf, Curl_strerror(conn,error)); + conn->ip_addr_str, Curl_strerror(conn,error)); data->state.os_errno = error; break; } -- cgit v1.2.1 From 5825aa149dc74050bb329b4491b556c6095ac4a8 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 23 Dec 2010 22:19:25 +0100 Subject: multi: connect fail => use next IP address When using the multi interface and connecting to a host name that resolves to multiple IP addresses, there was no logic that made it continue to the next IP if connecting to the first address times out. This is now corrected. --- lib/connect.c | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 7638854b3..be87ed91c 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -658,6 +658,7 @@ CURLcode Curl_is_connected(struct connectdata *conn, curl_socket_t sockfd = conn->sock[sockindex]; long allow = DEFAULT_CONNECT_TIMEOUT; int error = 0; + struct timeval now; DEBUGASSERT(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET); @@ -669,8 +670,10 @@ CURLcode Curl_is_connected(struct connectdata *conn, return CURLE_OK; } + now = Curl_tvnow(); + /* figure out how long time we have left to connect */ - allow = Curl_timeleft(conn, NULL, TRUE); + allow = Curl_timeleft(conn, &now, TRUE); if(allow < 0) { /* time-out, bail out, go home */ @@ -680,9 +683,16 @@ CURLcode Curl_is_connected(struct connectdata *conn, /* check for connect without timeout as we want to return immediately */ rc = waitconnect(conn, sockfd, 0); - if(WAITCONN_TIMEOUT == rc) + if(WAITCONN_TIMEOUT == rc) { + if(curlx_tvdiff(now, conn->connecttime) >= conn->timeoutms_per_addr) { + infof(data, "After %ldms connect time, move on!\n", + conn->timeoutms_per_addr); + goto next; + } + /* not an error, but also no connection yet */ return code; + } if(WAITCONN_CONNECTED == rc) { if(verifyconnect(sockfd, &error)) { @@ -715,6 +725,7 @@ CURLcode Curl_is_connected(struct connectdata *conn, data->state.os_errno = error; SET_SOCKERRNO(error); } + next: code = trynextip(conn, sockindex, connected); @@ -928,8 +939,12 @@ singleipconnect(struct connectdata *conn, curlx_nonblock(sockfd, TRUE); /* Connect TCP sockets, bind UDP */ - if(conn->socktype == SOCK_STREAM) + if(conn->socktype == SOCK_STREAM) { rc = connect(sockfd, &addr.sa_addr, addr.addrlen); + conn->connecttime = Curl_tvnow(); + if(conn->num_addr > 1) + Curl_expire(data, conn->timeoutms_per_addr); + } else rc = 0; @@ -1010,7 +1025,6 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ struct SessionHandle *data = conn->data; curl_socket_t sockfd = CURL_SOCKET_BAD; int aliasindex; - int num_addr; Curl_addrinfo *ai; Curl_addrinfo *curr_addr; @@ -1021,7 +1035,6 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ * Figure out what maximum time we have left *************************************************************/ long timeout_ms; - long timeout_per_addr; DEBUGASSERT(sockconn); *connected = FALSE; /* default to not connected */ @@ -1036,8 +1049,8 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ } /* Max time for each address */ - num_addr = Curl_num_addresses(remotehost->addr); - timeout_per_addr = timeout_ms / num_addr; + conn->num_addr = Curl_num_addresses(remotehost->addr); + conn->timeoutms_per_addr = timeout_ms / conn->num_addr; ai = remotehost->addr; @@ -1045,10 +1058,6 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ * know for the given host. One by one until one IP succeeds. */ - if(data->state.used_interface == Curl_if_multi) - /* don't hang when doing multi */ - timeout_per_addr = 0; - /* * Connecting with a Curl_addrinfo chain */ @@ -1057,7 +1066,10 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ /* start connecting to the IP curr_addr points to */ CURLcode res = - singleipconnect(conn, curr_addr, timeout_per_addr, &sockfd, connected); + singleipconnect(conn, curr_addr, + /* don't hang when doing multi */ + (data->state.used_interface == Curl_if_multi)?0: + conn->timeoutms_per_addr, &sockfd, connected); if(res) return res; -- cgit v1.2.1 From adb49ad8bb280b586b387ba930c0681afee03923 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 4 Jan 2011 23:07:58 +0100 Subject: Curl_timeleft: s/conn/data in first argument As the function doesn't really use the connectdata struct but only the SessionHanadle struct I modified what argument it wants. --- lib/connect.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index be87ed91c..604bb2a1a 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -124,15 +124,17 @@ singleipconnect(struct connectdata *conn, * transfer/connection. If the value is negative, the timeout time has already * elapsed. * + * The start time is stored in progress.t_startsingle - as set with + * Curl_pgrsTime(..., TIMER_STARTSINGLE); + * * If 'nowp' is non-NULL, it points to the current time. * 'duringconnect' is FALSE if not during a connect, as then of course the * connect timeout is not taken into account! */ -long Curl_timeleft(struct connectdata *conn, +long Curl_timeleft(struct SessionHandle *data, struct timeval *nowp, bool duringconnect) { - struct SessionHandle *data = conn->data; int timeout_set = 0; long timeout_ms = duringconnect?DEFAULT_CONNECT_TIMEOUT:0; struct timeval now; @@ -673,7 +675,7 @@ CURLcode Curl_is_connected(struct connectdata *conn, now = Curl_tvnow(); /* figure out how long time we have left to connect */ - allow = Curl_timeleft(conn, &now, TRUE); + allow = Curl_timeleft(data, &now, TRUE); if(allow < 0) { /* time-out, bail out, go home */ @@ -1040,7 +1042,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ *connected = FALSE; /* default to not connected */ /* get the timeout left */ - timeout_ms = Curl_timeleft(conn, &before, TRUE); + timeout_ms = Curl_timeleft(data, &before, TRUE); if(timeout_ms < 0) { /* a precaution, no need to continue if time already is up */ -- cgit v1.2.1 From 08a65b10fbbee20926211a9deb99b1ce8328d91a Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 11 Jan 2011 00:14:36 +0100 Subject: connect: use UDP correctly The idea that the protocol and socktype is part of name resolving in the libc functions is nuts. We keep the name resolver functions assume TCP/STREAM and we make sure that when we want to connect to a UDP service we use the correct UDP/DGRAM set instead. This bug was because the ->protocol field was not always set correctly. This bug was only affecting ipv6-disabled non-cares non-threaded builds. Bug: http://curl.haxx.se/bug/view.cgi?id=3154436 Reported by: "dperham" --- lib/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 604bb2a1a..bcc1ed74a 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -857,7 +857,7 @@ singleipconnect(struct connectdata *conn, addr.family = ai->ai_family; addr.socktype = conn->socktype; - addr.protocol = ai->ai_protocol; + addr.protocol = conn->socktype==SOCK_DGRAM?IPPROTO_UDP:ai->ai_protocol; addr.addrlen = ai->ai_addrlen; if(addr.addrlen > sizeof(struct Curl_sockaddr_storage)) -- cgit v1.2.1 From b370fcd300902d1310696088decf53ee2a286b95 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 9 Feb 2011 15:36:36 +0100 Subject: CURLOPT_SOCKOPTFUNCTION: return proper error code When the callback returns an error, this function must make sure to return CURLE_ABORTED_BY_CALLBACK properly and not CURLE_OK as before to allow the callback to properly abort the operation. --- lib/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index bcc1ed74a..fb21fb7df 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -926,7 +926,7 @@ singleipconnect(struct connectdata *conn, CURLSOCKTYPE_IPCXN); if(error) { sclose(sockfd); /* close the socket and bail out */ - return res; + return CURLE_ABORTED_BY_CALLBACK; } } -- cgit v1.2.1 From 1c3c0162c62e2788373261a43f484ff401017d8a Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 9 Feb 2011 15:46:41 +0100 Subject: SOCKOPTFUNCTION: callback can say already-connected Introducing a few CURL_SOCKOPT* defines for conveniance. The new CURL_SOCKOPT_ALREADY_CONNECTED signals to libcurl that the socket is to be treated as already connected and thus it will skip the connect() call. --- lib/connect.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index fb21fb7df..261b2150e 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -837,7 +837,7 @@ singleipconnect(struct connectdata *conn, struct Curl_sockaddr_ex addr; int rc; int error; - bool isconnected; + bool isconnected = FALSE; struct SessionHandle *data = conn->data; curl_socket_t sockfd; CURLcode res = CURLE_OK; @@ -924,7 +924,10 @@ singleipconnect(struct connectdata *conn, error = data->set.fsockopt(data->set.sockopt_client, sockfd, CURLSOCKTYPE_IPCXN); - if(error) { + + if(error == CURL_SOCKOPT_ALREADY_CONNECTED) + isconnected = TRUE; + else if(error) { sclose(sockfd); /* close the socket and bail out */ return CURLE_ABORTED_BY_CALLBACK; } @@ -941,7 +944,7 @@ singleipconnect(struct connectdata *conn, curlx_nonblock(sockfd, TRUE); /* Connect TCP sockets, bind UDP */ - if(conn->socktype == SOCK_STREAM) { + if(!isconnected && (conn->socktype == SOCK_STREAM)) { rc = connect(sockfd, &addr.sa_addr, addr.addrlen); conn->connecttime = Curl_tvnow(); if(conn->num_addr > 1) @@ -989,7 +992,8 @@ singleipconnect(struct connectdata *conn, return CURLE_OK; } - isconnected = verifyconnect(sockfd, &error); + if(!isconnected) + isconnected = verifyconnect(sockfd, &error); if(!rc && isconnected) { /* we are connected, awesome! */ -- cgit v1.2.1 From f01df1979812a1870b54ec676688137f61ab36c0 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 11 Apr 2011 13:17:55 +0200 Subject: checkconnection: don't call with NULL pointer When checking if an existing RTSP connection is alive or not, the checkconnection function might be called with a SessionHandle pointer being NULL and then referenced causing a crash. This happened only using the multi interface. Reported by: Tinus van den Berg Bug: http://curl.haxx.se/bug/view.cgi?id=3280739 --- lib/connect.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 261b2150e..3cde1805e 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -1122,6 +1122,9 @@ curl_socket_t Curl_getconnectinfo(struct SessionHandle *data, struct connectdata **connp) { curl_socket_t sockfd; + + DEBUGASSERT(data); + if((data->state.lastconnect != -1) && (data->state.connc->connects[data->state.lastconnect] != NULL)) { struct connectdata *c = -- cgit v1.2.1 From 1702a2c08d3a0ed5945f34e6cd38436611f65164 Mon Sep 17 00:00:00 2001 From: Fabian Keil Date: Tue, 19 Apr 2011 15:54:13 +0200 Subject: Fix a couple of spelling errors in lib/ Found with codespell. --- lib/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 3cde1805e..69d84c359 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -174,7 +174,7 @@ long Curl_timeleft(struct SessionHandle *data, nowp = &now; } - /* substract elapsed time */ + /* subtract elapsed time */ timeout_ms -= Curl_tvdiff(*nowp, data->progress.t_startsingle); if(!timeout_ms) /* avoid returning 0 as that means no timeout! */ -- cgit v1.2.1 From 7de2f9271c68c10ee7057c10741b0406bca6c156 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 31 Jan 2011 00:10:35 +0100 Subject: async resolvers: further cleanups asyn-ares.c and asyn-thread.c are two separate backends that implement the same (internal) async resolver API for libcurl to use. Backend is specified at build time. The internal resolver API is defined in asyn.h for asynch resolvers. --- lib/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 69d84c359..e876e7641 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -324,7 +324,7 @@ static CURLcode bindlocal(struct connectdata *conn, rc = Curl_resolv(conn, dev, 0, &h); if(rc == CURLRESOLV_PENDING) - (void)Curl_wait_for_resolv(conn, &h); + (void)Curl_resolver_wait_resolv(conn, &h); conn->ip_version = ipver; if(h) { -- cgit v1.2.1 From b903186fa0189ff241d756d25d07fdfe9885ae49 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 20 Apr 2011 15:17:42 +0200 Subject: source cleanup: unify look, style and indent levels By the use of a the new lib/checksrc.pl script that checks that our basic source style rules are followed. --- lib/connect.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index e876e7641..f815d4363 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -263,7 +263,7 @@ static CURLcode bindlocal(struct connectdata *conn, /************************************************************* * Select device to bind socket to *************************************************************/ - if ( !dev && !port ) + if(!dev && !port) /* no local kind of binding was requested */ return CURLE_OK; @@ -315,10 +315,10 @@ static CURLcode bindlocal(struct connectdata *conn, long ipver = conn->ip_version; int rc; - if (af == AF_INET) + if(af == AF_INET) conn->ip_version = CURL_IPRESOLVE_V4; #ifdef ENABLE_IPV6 - else if (af == AF_INET6) + else if(af == AF_INET6) conn->ip_version = CURL_IPRESOLVE_V6; #endif @@ -372,14 +372,14 @@ static CURLcode bindlocal(struct connectdata *conn, else { /* no device was given, prepare sa to match af's needs */ #ifdef ENABLE_IPV6 - if ( af == AF_INET6 ) { + if( af == AF_INET6 ) { si6->sin6_family = AF_INET6; si6->sin6_port = htons(port); sizeof_sa = sizeof(struct sockaddr_in6); } else #endif - if ( af == AF_INET ) { + if( af == AF_INET ) { si4->sin_family = AF_INET; si4->sin_port = htons(port); sizeof_sa = sizeof(struct sockaddr_in); @@ -388,7 +388,7 @@ static CURLcode bindlocal(struct connectdata *conn, for(;;) { if( bind(sockfd, sock, sizeof_sa) >= 0) { - /* we succeeded to bind */ + /* we succeeded to bind */ struct Curl_sockaddr_storage add; curl_socklen_t size = sizeof(add); memset(&add, 0, sizeof(struct Curl_sockaddr_storage)); @@ -809,8 +809,8 @@ void Curl_sndbufset(curl_socket_t sockfd) int curval = 0; int curlen = sizeof(curval); - if (getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (char *)&curval, &curlen) == 0) - if (curval > val) + if(getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (char *)&curval, &curlen) == 0) + if(curval > val) return; setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (const char *)&val, sizeof(val)); @@ -888,7 +888,7 @@ singleipconnect(struct connectdata *conn, return CURLE_OK; #if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID) - if (conn->scope && (addr.family == AF_INET6)) + if(conn->scope && (addr.family == AF_INET6)) sa6->sin6_scope_id = conn->scope; #endif @@ -1067,8 +1067,8 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ /* * Connecting with a Curl_addrinfo chain */ - for (curr_addr = ai, aliasindex=0; curr_addr; - curr_addr = curr_addr->ai_next, aliasindex++) { + for(curr_addr = ai, aliasindex=0; curr_addr; + curr_addr = curr_addr->ai_next, aliasindex++) { /* start connecting to the IP curr_addr points to */ CURLcode res = -- cgit v1.2.1 From 889d1e973fb718a77c5000141d724ce03863af23 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 22 Apr 2011 23:01:30 +0200 Subject: whitespace cleanup: no space first in conditionals "if(a)" is our style, not "if( a )" --- lib/connect.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index f815d4363..2cd8cd39c 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -372,14 +372,14 @@ static CURLcode bindlocal(struct connectdata *conn, else { /* no device was given, prepare sa to match af's needs */ #ifdef ENABLE_IPV6 - if( af == AF_INET6 ) { + if(af == AF_INET6) { si6->sin6_family = AF_INET6; si6->sin6_port = htons(port); sizeof_sa = sizeof(struct sockaddr_in6); } else #endif - if( af == AF_INET ) { + if(af == AF_INET) { si4->sin_family = AF_INET; si4->sin_port = htons(port); sizeof_sa = sizeof(struct sockaddr_in); @@ -387,7 +387,7 @@ static CURLcode bindlocal(struct connectdata *conn, } for(;;) { - if( bind(sockfd, sock, sizeof_sa) >= 0) { + if(bind(sockfd, sock, sizeof_sa) >= 0) { /* we succeeded to bind */ struct Curl_sockaddr_storage add; curl_socklen_t size = sizeof(add); -- cgit v1.2.1 From 4a42e5cdaa344755c6bf5317908849619f61798b Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 28 Apr 2011 09:39:33 +0200 Subject: multi-socks: fix connect to proxy When connecting to a socks or similar proxy we do the proxy handshake at once when we know the TCP connect is completed and we only consider the "connection" complete after the proxy handshake. This fixes test 564 which is now no longer considered disabled. Reported by: Dmitri Shubin Bug: http://curl.haxx.se/mail/lib-2011-04/0127.html --- lib/connect.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 2cd8cd39c..732fc6721 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -698,7 +698,13 @@ CURLcode Curl_is_connected(struct connectdata *conn, if(WAITCONN_CONNECTED == rc) { if(verifyconnect(sockfd, &error)) { - /* we are connected, awesome! */ + /* we are connected with TCP, awesome! */ + + /* see if we need to do any proxy magic first once we connected */ + code = Curl_connected_proxy(conn); + if(code) + return code; + conn->bits.tcpconnect = TRUE; *connected = TRUE; Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */ -- cgit v1.2.1 From b5d170b55110bacc61a4aa8bf99df1afc303c5dc Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 16 May 2011 23:46:43 +0200 Subject: CLOSESOCKETFUNCTION: added Introduced the initial setup to allow closesocket callbacks by making sure sclose() is only ever called from one place in the libcurl source and still run all test cases fine. --- lib/connect.c | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 732fc6721..2802c5d61 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -510,7 +510,7 @@ static CURLcode trynextip(struct connectdata *conn, *connected = FALSE; if(sockindex != FIRSTSOCKET) { - sclose(fd_to_close); + Curl_closesocket(conn, fd_to_close); return CURLE_COULDNT_CONNECT; /* no next */ } @@ -525,12 +525,12 @@ static CURLcode trynextip(struct connectdata *conn, /* store the new socket descriptor */ conn->sock[sockindex] = sockfd; conn->ip_addr = ai; - sclose(fd_to_close); + Curl_closesocket(conn, fd_to_close); return CURLE_OK; } ai = ai->ai_next; } - sclose(fd_to_close); + Curl_closesocket(conn, fd_to_close); return CURLE_COULDNT_CONNECT; } @@ -905,7 +905,7 @@ singleipconnect(struct connectdata *conn, error = ERRNO; failf(data, "sa_addr inet_ntop() failed with errno %d: %s", error, Curl_strerror(conn, error)); - sclose(sockfd); + Curl_closesocket(conn, sockfd); return CURLE_OK; } memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN); @@ -934,7 +934,7 @@ singleipconnect(struct connectdata *conn, if(error == CURL_SOCKOPT_ALREADY_CONNECTED) isconnected = TRUE; else if(error) { - sclose(sockfd); /* close the socket and bail out */ + Curl_closesocket(conn, sockfd); /* close the socket and bail out */ return CURLE_ABORTED_BY_CALLBACK; } } @@ -942,7 +942,7 @@ singleipconnect(struct connectdata *conn, /* possibly bind the local end to an IP, interface or port */ res = bindlocal(conn, sockfd, addr.family); if(res) { - sclose(sockfd); /* close socket and bail out */ + Curl_closesocket(conn, sockfd); /* close socket and bail out */ return res; } @@ -976,7 +976,7 @@ singleipconnect(struct connectdata *conn, #endif rc = waitconnect(conn, sockfd, timeout_ms); if(WAITCONN_ABORTED == rc) { - sclose(sockfd); + Curl_closesocket(conn, sockfd); return CURLE_ABORTED_BY_CALLBACK; } break; @@ -1017,7 +1017,7 @@ singleipconnect(struct connectdata *conn, } /* connect failed or timed out */ - sclose(sockfd); + Curl_closesocket(conn, sockfd); return CURLE_OK; } @@ -1163,3 +1163,16 @@ curl_socket_t Curl_getconnectinfo(struct SessionHandle *data, return sockfd; } + +/* + * Close a socket. + * + * 'conn' can be NULL, beware! + */ +int Curl_closesocket(struct connectdata *conn, + curl_socket_t sock) +{ + (void)conn; + + return sclose(sock); +} -- cgit v1.2.1 From 60f0ebbdc9fbddccaa4e2fcd1dce3d3a05f234ed Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 16 May 2011 23:52:15 +0200 Subject: CLOSESOCKETFUNCTION: use the callback Fix the return type of the callback to match close() and make use of it. --- lib/connect.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 2802c5d61..2dcf122c1 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -1172,7 +1172,8 @@ curl_socket_t Curl_getconnectinfo(struct SessionHandle *data, int Curl_closesocket(struct connectdata *conn, curl_socket_t sock) { - (void)conn; - - return sclose(sock); + if(conn && conn->fclosesocket) + return conn->fclosesocket(conn->closesocket_client, sock); + else + return sclose(sock); } -- cgit v1.2.1 From 3c9ff41a1fef4b03571f5a7f905e5016cae55208 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Thu, 26 May 2011 15:44:53 +0200 Subject: compiler warning: fix Fix compiler warning: conversion may lose significant bits --- lib/connect.c | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 2dcf122c1..369ba053e 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -89,6 +89,7 @@ #include "inet_pton.h" #include "sslgen.h" /* for Curl_ssl_check_cxn() */ #include "progress.h" +#include "warnless.h" /* The last #include file should be: */ #include "memdebug.h" -- cgit v1.2.1 From 4f170ee8f9c1d067022300df2da331c30dcda9dd Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 4 Jun 2011 21:19:14 +0200 Subject: Curl_socket_ready: make timeout a 'long' It was mostly typecasted to int all over the code so switching to long instead all over should be a net gain. --- lib/connect.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 369ba053e..6d657eb5e 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -211,8 +211,8 @@ int waitconnect(struct connectdata *conn, for(;;) { /* now select() until we get connect or timeout */ - rc = Curl_socket_ready(CURL_SOCKET_BAD, sockfd, (int)(timeout_msec>1000? - 1000:timeout_msec)); + rc = Curl_socket_ready(CURL_SOCKET_BAD, sockfd, timeout_msec>1000? + 1000:timeout_msec); if(Curl_pgrsUpdate(conn)) return WAITCONN_ABORTED; -- cgit v1.2.1 From 0f7bea7c3a6ddb0bf43f890c764322faaa3ba561 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 10 Jun 2011 14:40:46 +0200 Subject: unittest: mark all unit tested functions With "@unittest: [num]" in the header comment for each tested function. Shows we have a log way to go still... --- lib/connect.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 6d657eb5e..a9185978c 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -131,6 +131,8 @@ singleipconnect(struct connectdata *conn, * If 'nowp' is non-NULL, it points to the current time. * 'duringconnect' is FALSE if not during a connect, as then of course the * connect timeout is not taken into account! + * + * @unittest: 1303 */ long Curl_timeleft(struct SessionHandle *data, struct timeval *nowp, -- cgit v1.2.1 From ef2176109fca302ed89193716b62c3a7113552a3 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Sun, 24 Jul 2011 04:39:43 +0200 Subject: errno.h inclusion conditionally done in setup_once.h --- lib/connect.c | 1 - 1 file changed, 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index a9185978c..b9b6c7589 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -69,7 +69,6 @@ #endif #include -#include #include #define _MPRINTF_REPLACE /* use our functions only */ -- cgit v1.2.1 From 0337b871975ab515c513d2c5d596feb9a489494d Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Mon, 25 Jul 2011 04:08:08 +0200 Subject: time.h and sys/time.h inclusion conditionally done in setup_once.h --- lib/connect.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index b9b6c7589..adfdd712d 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -22,9 +22,6 @@ #include "setup.h" -#ifdef HAVE_SYS_TIME_H -#include -#endif #ifdef HAVE_SYS_SOCKET_H #include #endif -- cgit v1.2.1 From f1586cb4775681810afd8e6626e7842d459f3b85 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Tue, 26 Jul 2011 17:23:27 +0200 Subject: stdio.h, stdlib.h, string.h, stdarg.h and ctype.h inclusion done in setup_once.h --- lib/connect.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index adfdd712d..1f802bda8 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -49,9 +49,6 @@ #ifdef HAVE_ARPA_INET_H #include #endif -#ifdef HAVE_STDLIB_H -#include -#endif #if (defined(HAVE_IOCTL_FIONBIO) && defined(NETWARE)) #include @@ -65,9 +62,6 @@ #include #endif -#include -#include - #define _MPRINTF_REPLACE /* use our functions only */ #include -- cgit v1.2.1 From f6272dd9b8ae8d188068aeb0df2af496a964e407 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Fri, 5 Aug 2011 15:42:05 +0200 Subject: BSD-style lwIP TCP/IP stack support - followup --- lib/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 1f802bda8..9301f0108 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -792,7 +792,7 @@ static void nosigpipe(struct connectdata *conn, #define nosigpipe(x,y) #endif -#ifdef WIN32 +#ifdef USE_WINSOCK /* When you run a program that uses the Windows Sockets API, you may experience slow performance when you copy data to a TCP server. -- cgit v1.2.1 From b998d95b4d6de388ddc59a48714a2a1d9a43dc43 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 18 Aug 2011 23:35:15 +0200 Subject: FTP: fix proxy connect race condition When using the multi interface, a SOCKS proxy, and a connection that wouldn't immediately consider itself connected (which my Linux tests do by default), libcurl would be tricked into doing _two_ connects to the SOCKS proxy when it setup the data connection and then of course the second attempt would fail miserably and cause error. This problem is a regression that was introduced by commit 4a42e5cdaa344755 that was introduced in the 7.21.7 release. Bug: http://curl.haxx.se/mail/lib-2011-08/0199.html Reported by: Fabian Keil --- lib/connect.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 9301f0108..230d1055a 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -659,7 +659,7 @@ CURLcode Curl_is_connected(struct connectdata *conn, *connected = FALSE; /* a very negative world view is best */ - if(conn->bits.tcpconnect) { + if(conn->bits.tcpconnect[sockindex]) { /* we are connected already! */ *connected = TRUE; return CURLE_OK; @@ -698,7 +698,7 @@ CURLcode Curl_is_connected(struct connectdata *conn, if(code) return code; - conn->bits.tcpconnect = TRUE; + conn->bits.tcpconnect[sockindex] = TRUE; *connected = TRUE; Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */ Curl_verboseconnect(conn); -- cgit v1.2.1 From 3af9ba166cfd456c943d2dbf92a1d4b4b893949c Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 19 Aug 2011 00:16:01 +0200 Subject: connect: set TIMER_CONNECT When connecting, make sure TIMER_CONNECT is set. --- lib/connect.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 230d1055a..7f7e16794 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -700,7 +700,8 @@ CURLcode Curl_is_connected(struct connectdata *conn, conn->bits.tcpconnect[sockindex] = TRUE; *connected = TRUE; - Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */ + if(sockindex == FIRSTSOCKET) + Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */ Curl_verboseconnect(conn); Curl_updateconninfo(conn, sockfd); -- cgit v1.2.1 From 6b75d2c2df7209919a70a29a4479625b62fb3c28 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Sat, 3 Sep 2011 16:06:10 +0200 Subject: fix a bunch of MSVC compiler warnings --- lib/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 7f7e16794..df304fc62 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -790,7 +790,7 @@ static void nosigpipe(struct connectdata *conn, Curl_strerror(conn, SOCKERRNO)); } #else -#define nosigpipe(x,y) +#define nosigpipe(x,y) Curl_nop_stmt #endif #ifdef USE_WINSOCK -- cgit v1.2.1 From 303c90074d4cfe1d79c7478838dc5fe01477af00 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 9 Sep 2011 15:20:31 +0200 Subject: tcpnodelay: rename variable Renamed the variable from 'proto' to 'level' simply because it is not protocol you set but level and that is the name of the argument used in man pages and the POSIX documentation of the setsockopt function. --- lib/connect.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index df304fc62..7f0171f46 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -747,7 +747,7 @@ static void tcpnodelay(struct connectdata *conn, #ifdef TCP_NODELAY struct SessionHandle *data= conn->data; curl_socklen_t onoff = (curl_socklen_t) data->set.tcp_nodelay; - int proto = IPPROTO_TCP; + int level = IPPROTO_TCP; #if 0 /* The use of getprotobyname() is disabled since it isn't thread-safe on @@ -759,10 +759,10 @@ static void tcpnodelay(struct connectdata *conn, detected. */ struct protoent *pe = getprotobyname("tcp"); if(pe) - proto = pe->p_proto; + level = pe->p_proto; #endif - if(setsockopt(sockfd, proto, TCP_NODELAY, (void *)&onoff, + if(setsockopt(sockfd, level, TCP_NODELAY, (void *)&onoff, sizeof(onoff)) < 0) infof(data, "Could not set TCP_NODELAY: %s\n", Curl_strerror(conn, SOCKERRNO)); -- cgit v1.2.1 From 1a416cd27a37dac23a36063ced06ecc99fcd41e2 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 15 Oct 2011 23:44:28 +0200 Subject: singleipconnect: don't clobber errno Save the errno value immediately after a connect() failure so that it won't get reset to something else before we read it. Bug: http://curl.haxx.se/mail/lib-2011-10/0066.html Reported by: Frank Van Uffelen and Fabian Hiernaux --- lib/connect.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 7f0171f46..309ba355a 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -836,7 +836,7 @@ singleipconnect(struct connectdata *conn, { struct Curl_sockaddr_ex addr; int rc; - int error; + int error = 0; bool isconnected = FALSE; struct SessionHandle *data = conn->data; curl_socket_t sockfd; @@ -946,6 +946,8 @@ singleipconnect(struct connectdata *conn, /* Connect TCP sockets, bind UDP */ if(!isconnected && (conn->socktype == SOCK_STREAM)) { rc = connect(sockfd, &addr.sa_addr, addr.addrlen); + if(-1 == rc) + error = SOCKERRNO; conn->connecttime = Curl_tvnow(); if(conn->num_addr > 1) Curl_expire(data, conn->timeoutms_per_addr); @@ -954,8 +956,6 @@ singleipconnect(struct connectdata *conn, rc = 0; if(-1 == rc) { - error = SOCKERRNO; - switch (error) { case EINPROGRESS: case EWOULDBLOCK: -- cgit v1.2.1 From ecbb08cea3cd67406c49572eeb4f456dfc94cca2 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 17 Oct 2011 22:01:09 +0200 Subject: singleipconnect: unstick the ipv6-connection boolean Previously the bit was set before the connection was found working so if it would first fail to an ipv6 address and then connect fine to a IPv4 address the variable would still be TRUE. Reported by: Thomas L. Shinnick Bug: http://curl.haxx.se/bug/view.cgi?id=3421912 --- lib/connect.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 309ba355a..2a1876e71 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -907,11 +907,6 @@ singleipconnect(struct connectdata *conn, Curl_persistconninfo(conn); -#ifdef ENABLE_IPV6 - if(addr.family == AF_INET6) - conn->bits.ipv6 = TRUE; -#endif - if(data->set.tcp_nodelay) tcpnodelay(conn, sockfd); @@ -999,6 +994,10 @@ singleipconnect(struct connectdata *conn, /* we are connected, awesome! */ *connected = TRUE; /* this is a true connect */ infof(data, "connected\n"); +#ifdef ENABLE_IPV6 + conn->bits.ipv6 = (addr.family == AF_INET6)?TRUE:FALSE; +#endif + Curl_updateconninfo(conn, sockfd); *sockp = sockfd; return CURLE_OK; -- cgit v1.2.1 From 9109cdec11ee5a19f132fd7bdf2e9ceefea4de41 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 5 Dec 2011 10:58:38 +0100 Subject: Curl_socket: internal replacement for socket() Moved out into a separate function to work as a "generic" socket() replacement. --- lib/connect.c | 125 +++++++++++++++++++++++++++++++--------------------------- 1 file changed, 67 insertions(+), 58 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 2a1876e71..2eef242d4 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -89,18 +89,6 @@ #undef SO_NOSIGPIPE #endif -struct Curl_sockaddr_ex { - int family; - int socktype; - int protocol; - unsigned int addrlen; - union { - struct sockaddr addr; - struct Curl_sockaddr_storage buff; - } _sa_ex_u; -}; -#define sa_addr _sa_ex_u.addr - static bool verifyconnect(curl_socket_t sockfd, int *error); static CURLcode @@ -841,56 +829,13 @@ singleipconnect(struct connectdata *conn, struct SessionHandle *data = conn->data; curl_socket_t sockfd; CURLcode res = CURLE_OK; -#if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID) - struct sockaddr_in6 * const sa6 = (void *)&addr.sa_addr; -#endif *sockp = CURL_SOCKET_BAD; - - /* - * The Curl_sockaddr_ex structure is basically libcurl's external API - * curl_sockaddr structure with enough space available to directly hold - * any protocol-specific address structures. The variable declared here - * will be used to pass / receive data to/from the fopensocket callback - * if this has been set, before that, it is initialized from parameters. - */ - - addr.family = ai->ai_family; - addr.socktype = conn->socktype; - addr.protocol = conn->socktype==SOCK_DGRAM?IPPROTO_UDP:ai->ai_protocol; - addr.addrlen = ai->ai_addrlen; - - if(addr.addrlen > sizeof(struct Curl_sockaddr_storage)) - addr.addrlen = sizeof(struct Curl_sockaddr_storage); - memcpy(&addr.sa_addr, ai->ai_addr, addr.addrlen); - *connected = FALSE; /* default is not connected */ - if(data->set.fopensocket) - /* - * If the opensocket callback is set, all the destination address - * information is passed to the callback. Depending on this information the - * callback may opt to abort the connection, this is indicated returning - * CURL_SOCKET_BAD; otherwise it will return a not-connected socket. When - * the callback returns a valid socket the destination address information - * might have been changed and this 'new' address will actually be used - * here to connect. - */ - sockfd = data->set.fopensocket(data->set.opensocket_client, - CURLSOCKTYPE_IPCXN, - (struct curl_sockaddr *)&addr); - else - /* opensocket callback not set, so simply create the socket now */ - sockfd = socket(addr.family, addr.socktype, addr.protocol); - - if(sockfd == CURL_SOCKET_BAD) - /* no socket, no connection */ - return CURLE_OK; - -#if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID) - if(conn->scope && (addr.family == AF_INET6)) - sa6->sin6_scope_id = conn->scope; -#endif + res = Curl_socket(conn, ai, &addr, &sockfd); + if(res) + return res; /* store remote address and port used in this connection attempt */ if(!getaddressinfo((struct sockaddr*)&addr.sa_addr, @@ -1170,3 +1115,67 @@ int Curl_closesocket(struct connectdata *conn, else return sclose(sock); } + +/* + * Create a socket based on info from 'conn' and 'ai'. + * + * Fill in 'addr' and 'sockfd' accordingly if OK is returned. If the open + * socket callback is set, used that! + * + */ +CURLcode Curl_socket(struct connectdata *conn, + const Curl_addrinfo *ai, + struct Curl_sockaddr_ex *addr, + curl_socket_t *sockfd) +{ + struct SessionHandle *data = conn->data; +#if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID) + struct sockaddr_in6 * const sa6 = (void *)&addr->sa_addr; +#endif + + /* + * The Curl_sockaddr_ex structure is basically libcurl's external API + * curl_sockaddr structure with enough space available to directly hold + * any protocol-specific address structures. The variable declared here + * will be used to pass / receive data to/from the fopensocket callback + * if this has been set, before that, it is initialized from parameters. + */ + + addr->family = ai->ai_family; + addr->socktype = conn->socktype; + addr->protocol = conn->socktype==SOCK_DGRAM?IPPROTO_UDP:ai->ai_protocol; + addr->addrlen = ai->ai_addrlen; + + if(addr->addrlen > sizeof(struct Curl_sockaddr_storage)) + addr->addrlen = sizeof(struct Curl_sockaddr_storage); + memcpy(&addr->sa_addr, ai->ai_addr, addr->addrlen); + + if(data->set.fopensocket) + /* + * If the opensocket callback is set, all the destination address + * information is passed to the callback. Depending on this information the + * callback may opt to abort the connection, this is indicated returning + * CURL_SOCKET_BAD; otherwise it will return a not-connected socket. When + * the callback returns a valid socket the destination address information + * might have been changed and this 'new' address will actually be used + * here to connect. + */ + *sockfd = data->set.fopensocket(data->set.opensocket_client, + CURLSOCKTYPE_IPCXN, + (struct curl_sockaddr *)addr); + else + /* opensocket callback not set, so simply create the socket now */ + *sockfd = socket(addr->family, addr->socktype, addr->protocol); + + if(*sockfd == CURL_SOCKET_BAD) + /* no socket, no connection */ + return CURLE_FAILED_INIT; + +#if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID) + if(conn->scope && (addr->family == AF_INET6)) + sa6->sin6_scope_id = conn->scope; +#endif + + return CURLE_OK; + +} -- cgit v1.2.1 From 088ba97a2471c97e90fe7153dff0ce119faab4ef Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 5 Dec 2011 11:42:10 +0100 Subject: FTP: call opensocket callback properly When the new socket is created for an active connection, it is now done using the open socket callback. Test case 596 was modified to run fine, although it hides the fact that the close callback is still called too many times, as it also gets called for closing sockets that were created with accept(). --- lib/connect.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 2eef242d4..445261754 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -1119,8 +1119,10 @@ int Curl_closesocket(struct connectdata *conn, /* * Create a socket based on info from 'conn' and 'ai'. * - * Fill in 'addr' and 'sockfd' accordingly if OK is returned. If the open - * socket callback is set, used that! + * 'addr' should be a pointer to the correct struct to get data back, or NULL. + * 'sockfd' must be a pointer to a socket descriptor. + * + * If the open socket callback is set, used that! * */ CURLcode Curl_socket(struct connectdata *conn, @@ -1129,9 +1131,11 @@ CURLcode Curl_socket(struct connectdata *conn, curl_socket_t *sockfd) { struct SessionHandle *data = conn->data; -#if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID) - struct sockaddr_in6 * const sa6 = (void *)&addr->sa_addr; -#endif + struct Curl_sockaddr_ex dummy; + + if(!addr) + /* if the caller doesn't want info back, use a local temp copy */ + addr = &dummy; /* * The Curl_sockaddr_ex structure is basically libcurl's external API @@ -1172,8 +1176,10 @@ CURLcode Curl_socket(struct connectdata *conn, return CURLE_FAILED_INIT; #if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID) - if(conn->scope && (addr->family == AF_INET6)) + if(conn->scope && (addr->family == AF_INET6)) { + struct sockaddr_in6 * const sa6 = (void *)&addr->sa_addr; sa6->sin6_scope_id = conn->scope; + } #endif return CURLE_OK; -- cgit v1.2.1 From d5b5f64bce3a86ae39361248da6b3b207cff2cd2 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 5 Dec 2011 12:34:27 +0100 Subject: FTP: close callback fix Keep track of which sockets that are the result of accept() calls and refuse to call the closesocket callback for those sockets. Test case 596 now verifies that the open socket callback is called the same number of times as the closed socket callback for active FTP connections. Bug: http://curl.haxx.se/mail/lib-2011-12/0018.html Reported by: Gokhan Sengun --- lib/connect.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 445261754..a560c4d3b 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -1110,10 +1110,14 @@ curl_socket_t Curl_getconnectinfo(struct SessionHandle *data, int Curl_closesocket(struct connectdata *conn, curl_socket_t sock) { - if(conn && conn->fclosesocket) - return conn->fclosesocket(conn->closesocket_client, sock); - else - return sclose(sock); + if(conn && conn->fclosesocket) { + if((sock != conn->sock[SECONDARYSOCKET]) || + !conn->sock_accepted[SECONDARYSOCKET]) + /* if this socket matches the second socket, and that was created with + accept, then we MUST NOT call the callback */ + return conn->fclosesocket(conn->closesocket_client, sock); + } + return sclose(sock); } /* -- cgit v1.2.1 From 1cacf853da30edb8a9f6b834df43ee639a1811f2 Mon Sep 17 00:00:00 2001 From: Gokhan Sengun Date: Wed, 7 Dec 2011 16:00:20 +0100 Subject: Curl_closesocket: clear sock_accepted on close As a follow-up from commit d5b5f64bce3a8, clear the sock_accepted status when such a socket is closed to avoid a re-used connection to retain the state wrongly. Bug: http://curl.haxx.se/mail/lib-2011-12/0079.html --- lib/connect.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index a560c4d3b..af225ab83 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -1111,10 +1111,13 @@ int Curl_closesocket(struct connectdata *conn, curl_socket_t sock) { if(conn && conn->fclosesocket) { - if((sock != conn->sock[SECONDARYSOCKET]) || - !conn->sock_accepted[SECONDARYSOCKET]) + if((sock == conn->sock[SECONDARYSOCKET]) && + conn->sock_accepted[SECONDARYSOCKET]) /* if this socket matches the second socket, and that was created with - accept, then we MUST NOT call the callback */ + accept, then we MUST NOT call the callback but clear the accepted + status */ + conn->sock_accepted[SECONDARYSOCKET] = FALSE; + else return conn->fclosesocket(conn->closesocket_client, sock); } return sclose(sock); -- cgit v1.2.1 From 6e4835c795996ee92ac1aa78733f23a089f310a5 Mon Sep 17 00:00:00 2001 From: Jason Glasgow Date: Fri, 4 Nov 2011 16:48:05 -0400 Subject: CURLOPT_INTERFACE: avoid resolving interfaces names Do not try to resolve interfaces names via DNS by recognizing interface names in a few ways. If the interface option argument has a prefix of "if!" then treat the argument as only an interface. Similarly, if the interface argument is the name of an interface (even if it does not have an IP address assigned), treat it as an interface name. Finally, if the interface argument is prefixed by "host!" treat it as a hostname that must be resolved by /etc/hosts or DNS. These changes allow a client using the multi interfaces to avoid blocking on name resolution if the interface loses its IP address or disappears. --- lib/connect.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index af225ab83..906fd9d18 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -240,6 +240,10 @@ static CURLcode bindlocal(struct connectdata *conn, int error; char myhost[256] = ""; int done = 0; /* -1 for error, 1 for address found */ + int is_interface = FALSE; + int is_host = FALSE; + static const char *if_prefix = "if!"; + static const char *host_prefix = "host!"; /************************************************************* * Select device to bind socket to @@ -251,9 +255,20 @@ static CURLcode bindlocal(struct connectdata *conn, memset(&sa, 0, sizeof(struct Curl_sockaddr_storage)); if(dev && (strlen(dev)<255) ) { + if(strncmp(if_prefix, dev, strlen(if_prefix)) == 0) { + dev += strlen(if_prefix); + is_interface = TRUE; + } + else if(strncmp(host_prefix, dev, strlen(host_prefix)) == 0) { + dev += strlen(host_prefix); + is_host = TRUE; + } /* interface */ - if(Curl_if2ip(af, dev, myhost, sizeof(myhost))) { + if(!is_host && (is_interface || Curl_if_is_interface_name(dev))) { + if(Curl_if2ip(af, dev, myhost, sizeof(myhost)) == NULL) + return CURLE_INTERFACE_FAILED; + /* * We now have the numerical IP address in the 'myhost' buffer */ -- cgit v1.2.1 From de6f4f356e4b35c17f55c3a2f98e9ea4adeb7fff Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Tue, 13 Dec 2011 16:18:08 +0100 Subject: connect.c: fix compiler warning 'enumerated type is mixed with another type' --- lib/connect.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 906fd9d18..bcd538406 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -240,8 +240,8 @@ static CURLcode bindlocal(struct connectdata *conn, int error; char myhost[256] = ""; int done = 0; /* -1 for error, 1 for address found */ - int is_interface = FALSE; - int is_host = FALSE; + bool is_interface = FALSE; + bool is_host = FALSE; static const char *if_prefix = "if!"; static const char *host_prefix = "host!"; -- cgit v1.2.1 From c834213ad52c52431e9ca597862dc81839cabe84 Mon Sep 17 00:00:00 2001 From: Gokhan Sengun Date: Mon, 19 Dec 2011 14:35:20 +0100 Subject: FTP: perform active connections non-blocking 1- Two new error codes are introduced. CURLE_FTP_ACCEPT_FAILED to be set whenever ACCEPTing fails because of FTP server connected. CURLE_FTP_ACCEPT_TIMEOUT to be set whenever ACCEPTing timeouts. Neither of these errors are considered fatal and control connection remains OK because it could just be a firewall blocking server to connect to the client. 2- One new setopt option was introduced. CURLOPT_ACCEPTTIMEOUT_MS It sets the maximum amount of time FTP client is going to wait for a server to connect. Internal default accept timeout is 60 seconds. --- lib/connect.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index bcd538406..cc835808b 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -98,6 +98,34 @@ singleipconnect(struct connectdata *conn, curl_socket_t *sock, bool *connected); +/* + * Curl_timeleft_accept() returns the amount of milliseconds left allowed for + * waiting server to connect. If the value is negative, the timeout time has + * already elapsed. + * + * The start time is stored in progress.t_acceptdata - as set with + * Curl_pgrsTime(..., TIMER_STARTACCEPT); + * + */ +long Curl_timeleft_accept(struct SessionHandle *data) +{ + long timeout_ms = DEFAULT_ACCEPT_TIMEOUT; + struct timeval now; + + if(data->set.accepttimeout > 0) + timeout_ms = data->set.accepttimeout; + + now = Curl_tvnow(); + + /* subtract elapsed time */ + timeout_ms -= Curl_tvdiff(now, data->progress.t_acceptdata); + if(!timeout_ms) + /* avoid returning 0 as that means no timeout! */ + return -1; + + return timeout_ms; +} + /* * Curl_timeleft() returns the amount of milliseconds left allowed for the * transfer/connection. If the value is negative, the timeout time has already -- cgit v1.2.1 From 130fac6c16c4fb8a7eeec116adc479aad1e3273d Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 20 Dec 2011 20:55:54 +0100 Subject: timeleft_accept: ack global timeout, moved to ftp.c First off the timeout for accepting a server connect back must of course respect a global timeout. Then the timeleft function is only used by ftp code so it was moved to ftp.c and made static. --- lib/connect.c | 28 ---------------------------- 1 file changed, 28 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index cc835808b..bcd538406 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -98,34 +98,6 @@ singleipconnect(struct connectdata *conn, curl_socket_t *sock, bool *connected); -/* - * Curl_timeleft_accept() returns the amount of milliseconds left allowed for - * waiting server to connect. If the value is negative, the timeout time has - * already elapsed. - * - * The start time is stored in progress.t_acceptdata - as set with - * Curl_pgrsTime(..., TIMER_STARTACCEPT); - * - */ -long Curl_timeleft_accept(struct SessionHandle *data) -{ - long timeout_ms = DEFAULT_ACCEPT_TIMEOUT; - struct timeval now; - - if(data->set.accepttimeout > 0) - timeout_ms = data->set.accepttimeout; - - now = Curl_tvnow(); - - /* subtract elapsed time */ - timeout_ms -= Curl_tvdiff(now, data->progress.t_acceptdata); - if(!timeout_ms) - /* avoid returning 0 as that means no timeout! */ - return -1; - - return timeout_ms; -} - /* * Curl_timeleft() returns the amount of milliseconds left allowed for the * transfer/connection. If the value is negative, the timeout time has already -- cgit v1.2.1 From 0ce2bca741ae596a346b2ab767dfbf5be9bc7dae Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Mon, 16 Jan 2012 21:14:05 +0100 Subject: add LF termination to infof() trace string --- lib/connect.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index bcd538406..f76ec0e0b 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2012, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -863,7 +863,7 @@ singleipconnect(struct connectdata *conn, return CURLE_OK; } memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN); - infof(data, " Trying %s... ", conn->ip_addr_str); + infof(data, " Trying %s...\n", conn->ip_addr_str); Curl_persistconninfo(conn); -- cgit v1.2.1 From 4d2737bcb2c6713d5eebba09343367b6b4d5580c Mon Sep 17 00:00:00 2001 From: Pierre Ynard Date: Mon, 23 Jan 2012 10:44:53 +0100 Subject: remove write-only variable --- lib/connect.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index f76ec0e0b..582782e5c 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -989,7 +989,6 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ { struct SessionHandle *data = conn->data; curl_socket_t sockfd = CURL_SOCKET_BAD; - int aliasindex; Curl_addrinfo *ai; Curl_addrinfo *curr_addr; @@ -1026,8 +1025,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ /* * Connecting with a Curl_addrinfo chain */ - for(curr_addr = ai, aliasindex=0; curr_addr; - curr_addr = curr_addr->ai_next, aliasindex++) { + for(curr_addr = ai; curr_addr; curr_addr = curr_addr->ai_next) { /* start connecting to the IP curr_addr points to */ CURLcode res = -- cgit v1.2.1 From f4d3c0cbfb648917a0b78d291ac9855fd12975a9 Mon Sep 17 00:00:00 2001 From: Pierre Ynard Date: Mon, 23 Jan 2012 10:45:24 +0100 Subject: more resilient connection times among IP addresses When connecting to a domain with multiple IP addresses, allow different, decreasing connection timeout values. This should guarantee some connections attempts with sufficiently long timeouts, while still providing fallback. --- lib/connect.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 582782e5c..b5082d896 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -732,6 +732,8 @@ CURLcode Curl_is_connected(struct connectdata *conn, } next: + conn->timeoutms_per_addr = conn->ip_addr->ai_next == NULL ? + allow : allow / 2; code = trynextip(conn, sockindex, connected); if(code) { @@ -1012,9 +1014,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ return CURLE_OPERATION_TIMEDOUT; } - /* Max time for each address */ conn->num_addr = Curl_num_addresses(remotehost->addr); - conn->timeoutms_per_addr = timeout_ms / conn->num_addr; ai = remotehost->addr; @@ -1026,14 +1026,17 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ * Connecting with a Curl_addrinfo chain */ for(curr_addr = ai; curr_addr; curr_addr = curr_addr->ai_next) { + CURLcode res; - /* start connecting to the IP curr_addr points to */ - CURLcode res = - singleipconnect(conn, curr_addr, - /* don't hang when doing multi */ - (data->state.used_interface == Curl_if_multi)?0: - conn->timeoutms_per_addr, &sockfd, connected); + /* Max time for the next address */ + conn->timeoutms_per_addr = curr_addr->ai_next == NULL ? + timeout_ms : timeout_ms / 2; + /* start connecting to the IP curr_addr points to */ + res = singleipconnect(conn, curr_addr, + /* don't hang when doing multi */ + (data->state.used_interface == Curl_if_multi)?0: + conn->timeoutms_per_addr, &sockfd, connected); if(res) return res; -- cgit v1.2.1 From 705f0f7a5b6120bb783d139c9266b285a4c8acd8 Mon Sep 17 00:00:00 2001 From: Dave Reisner Date: Tue, 24 Jan 2012 01:28:06 +0000 Subject: add library support for tuning TCP_KEEPALIVE This adds three new options to control the behavior of TCP keepalives: - CURLOPT_TCP_KEEPALIVE: enable/disable probes - CURLOPT_TCP_KEEPIDLE: idle time before sending first probe - CURLOPT_TCP_KEEPINTVL: delay between successive probes While not all operating systems support the TCP_KEEPIDLE and TCP_KEEPINTVL knobs, the library will still allow these options to be set by clients, silently ignoring the values. --- lib/connect.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index b5082d896..5747b0431 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -91,6 +91,35 @@ static bool verifyconnect(curl_socket_t sockfd, int *error); +static void +tcpkeepalive(struct SessionHandle *data, + int sockfd) +{ + int optval = data->set.tcp_keepalive; + + /* only set IDLE and INTVL if setting KEEPALIVE is successful */ + if(setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, + (void *)&optval, sizeof(optval)) < 0) { + infof(data, "Failed to set SO_KEEPALIVE on fd %d\n", sockfd); + } + else { +#ifdef TCP_KEEPIDLE + optval = data->set.tcp_keepidle; + if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE, + (void *)&optval, sizeof(optval)) < 0) { + infof(data, "Failed to set TCP_KEEPIDLE on fd %d\n", sockfd); + } +#endif +#ifdef TCP_KEEPINTVL + optval = data->set.tcp_keepintvl; + if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPINTVL, + (void *)&optval, sizeof(optval)) < 0) { + infof(data, "Failed to set TCP_KEEPINTVL on fd %d\n", sockfd); + } +#endif + } +} + static CURLcode singleipconnect(struct connectdata *conn, const Curl_addrinfo *ai, /* start connecting to this */ @@ -876,6 +905,9 @@ singleipconnect(struct connectdata *conn, Curl_sndbufset(sockfd); + if(data->set.tcp_keepalive) + tcpkeepalive(data, sockfd); + if(data->set.fsockopt) { /* activate callback for setting socket options */ error = data->set.fsockopt(data->set.sockopt_client, -- cgit v1.2.1 From 8af4b657d0f44bd6f2b1d672666c046e53af0e0c Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Fri, 16 Mar 2012 19:06:34 +0100 Subject: fix some compiler warnings --- lib/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 5747b0431..0affca288 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -95,7 +95,7 @@ static void tcpkeepalive(struct SessionHandle *data, int sockfd) { - int optval = data->set.tcp_keepalive; + int optval = data->set.tcp_keepalive?1:0; /* only set IDLE and INTVL if setting KEEPALIVE is successful */ if(setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, -- cgit v1.2.1 From c6825b7a6b5e8798bc861b3d280430e8149e7298 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Tue, 20 Mar 2012 18:28:24 +0100 Subject: fix several compiler warnings --- lib/connect.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 0affca288..38f68b428 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -93,7 +93,7 @@ static bool verifyconnect(curl_socket_t sockfd, int *error); static void tcpkeepalive(struct SessionHandle *data, - int sockfd) + curl_socket_t sockfd) { int optval = data->set.tcp_keepalive?1:0; @@ -104,14 +104,14 @@ tcpkeepalive(struct SessionHandle *data, } else { #ifdef TCP_KEEPIDLE - optval = data->set.tcp_keepidle; + optval = curlx_sltosi(data->set.tcp_keepidle); if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE, (void *)&optval, sizeof(optval)) < 0) { infof(data, "Failed to set TCP_KEEPIDLE on fd %d\n", sockfd); } #endif #ifdef TCP_KEEPINTVL - optval = data->set.tcp_keepintvl; + optval = curlx_sltosi(data->set.tcp_keepintvl); if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPINTVL, (void *)&optval, sizeof(optval)) < 0) { infof(data, "Failed to set TCP_KEEPINTVL on fd %d\n", sockfd); -- cgit v1.2.1 From 950b0b770ebc4736f7623b0bd3c038cf9e26ad6f Mon Sep 17 00:00:00 2001 From: Lijo Antony Date: Tue, 3 Apr 2012 02:45:25 +0400 Subject: connect.c: return changed to CURLE_COULDNT_CONNECT when opensocket fails Curl_socket returns CURLE_COULDNT_CONNECT when the opensocket callback returns CURL_SOCKET_BAD. Previous return value CURLE_FAILED_INIT conveys incorrect information to the user. --- lib/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 38f68b428..2d592291d 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -1228,7 +1228,7 @@ CURLcode Curl_socket(struct connectdata *conn, if(*sockfd == CURL_SOCKET_BAD) /* no socket, no connection */ - return CURLE_FAILED_INIT; + return CURLE_COULDNT_CONNECT; #if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID) if(conn->scope && (addr->family == AF_INET6)) { -- cgit v1.2.1 From 5cd524df187cbb2414d518f8933894399edbf572 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 19 Apr 2012 23:31:50 +0200 Subject: singleipconnect: return OK even when Curl_socket() fails Commit 9109cdec11ee5a brought this regression (shipped since 7.24.0). The singleipconnect() function must not return an error if Curl_socket() returns an error. It should then simply return OK and pass a SOCKET_BAD back simply because that is how the user of this function expects it to work and something else is not fine. Reported by: Blaise Potard Bug: http://curl.haxx.se/bug/view.cgi?id=3516508 --- lib/connect.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 2d592291d..42b626f1a 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -881,7 +881,10 @@ singleipconnect(struct connectdata *conn, res = Curl_socket(conn, ai, &addr, &sockfd); if(res) - return res; + /* Failed to create the socket, but still return OK since we signal the + lack of socket as well. This allows the parent function to keep looping + over alternative addresses/socket families etc. */ + return CURLE_OK; /* store remote address and port used in this connection attempt */ if(!getaddressinfo((struct sockaddr*)&addr.sa_addr, -- cgit v1.2.1 From 9c94236e6cc078a0dc5a78b6e2fefc1403e5375e Mon Sep 17 00:00:00 2001 From: Marc Hoersken Date: Mon, 11 Jun 2012 12:24:03 +0200 Subject: connect.c/ftp.c: Fixed dereferencing pointer breakin strict-aliasing Fixed warning: dereferencing pointer does break strict-aliasing rules by using a union instead of separate pointer variables. Internal union sockaddr_u could probably be moved to generic header. Thanks to Paul Howarth for the hint about using unions for this. Important for winbuild: Separate declaration of sockaddr_u pointer. The pointer variable *sock cannot be declared and initialized right after the union declaration. Therefore it has to be a separate statement. --- lib/connect.c | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 42b626f1a..28c101930 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -253,12 +253,16 @@ static CURLcode bindlocal(struct connectdata *conn, struct SessionHandle *data = conn->data; struct Curl_sockaddr_storage sa; - struct sockaddr *sock = (struct sockaddr *)&sa; /* bind to this address */ curl_socklen_t sizeof_sa = 0; /* size of the data sock points to */ - struct sockaddr_in *si4 = (struct sockaddr_in *)&sa; + + union sockaddr_u { + struct sockaddr sa; + struct sockaddr_in sa4; #ifdef ENABLE_IPV6 - struct sockaddr_in6 *si6 = (struct sockaddr_in6 *)&sa; + struct sockaddr_in6 sa6; #endif + }; + union sockaddr_u *sock = (union sockaddr_u *)&sa; /* bind to this address */ struct Curl_dns_entry *h=NULL; unsigned short port = data->set.localport; /* use this port number, 0 for @@ -373,18 +377,18 @@ static CURLcode bindlocal(struct connectdata *conn, #ifdef ENABLE_IPV6 /* ipv6 address */ if((af == AF_INET6) && - (Curl_inet_pton(AF_INET6, myhost, &si6->sin6_addr) > 0)) { - si6->sin6_family = AF_INET6; - si6->sin6_port = htons(port); + (Curl_inet_pton(AF_INET6, myhost, &sock->sa6.sin6_addr) > 0)) { + sock->sa6.sin6_family = AF_INET6; + sock->sa6.sin6_port = htons(port); sizeof_sa = sizeof(struct sockaddr_in6); } else #endif /* ipv4 address */ if((af == AF_INET) && - (Curl_inet_pton(AF_INET, myhost, &si4->sin_addr) > 0)) { - si4->sin_family = AF_INET; - si4->sin_port = htons(port); + (Curl_inet_pton(AF_INET, myhost, &sock->sa4.sin_addr) > 0)) { + sock->sa4.sin_family = AF_INET; + sock->sa4.sin_port = htons(port); sizeof_sa = sizeof(struct sockaddr_in); } } @@ -398,21 +402,21 @@ static CURLcode bindlocal(struct connectdata *conn, /* no device was given, prepare sa to match af's needs */ #ifdef ENABLE_IPV6 if(af == AF_INET6) { - si6->sin6_family = AF_INET6; - si6->sin6_port = htons(port); + sock->sa6.sin6_family = AF_INET6; + sock->sa6.sin6_port = htons(port); sizeof_sa = sizeof(struct sockaddr_in6); } else #endif if(af == AF_INET) { - si4->sin_family = AF_INET; - si4->sin_port = htons(port); + sock->sa4.sin_family = AF_INET; + sock->sa4.sin_port = htons(port); sizeof_sa = sizeof(struct sockaddr_in); } } for(;;) { - if(bind(sockfd, sock, sizeof_sa) >= 0) { + if(bind(sockfd, &sock->sa, sizeof_sa) >= 0) { /* we succeeded to bind */ struct Curl_sockaddr_storage add; curl_socklen_t size = sizeof(add); @@ -432,11 +436,11 @@ static CURLcode bindlocal(struct connectdata *conn, infof(data, "Bind to local port %hu failed, trying next\n", port); port++; /* try next port */ /* We re-use/clobber the port variable here below */ - if(sock->sa_family == AF_INET) - si4->sin_port = ntohs(port); + if(sock->sa.sa_family == AF_INET) + sock->sa4.sin_port = ntohs(port); #ifdef ENABLE_IPV6 else - si6->sin6_port = ntohs(port); + sock->sa6.sin6_port = ntohs(port); #endif } else -- cgit v1.2.1 From d95b8e0627d875f264fb37e78b36122e00a10472 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Tue, 12 Jun 2012 13:12:09 +0200 Subject: Revert "connect.c/ftp.c: Fixed dereferencing pointer breakin strict-aliasing" This reverts commit 9c94236e6cc078a0dc5a78b6e2fefc1403e5375e. It didn't server its purpose, so lets go back to long-time working code. --- lib/connect.c | 38 +++++++++++++++++--------------------- 1 file changed, 17 insertions(+), 21 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 28c101930..42b626f1a 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -253,16 +253,12 @@ static CURLcode bindlocal(struct connectdata *conn, struct SessionHandle *data = conn->data; struct Curl_sockaddr_storage sa; + struct sockaddr *sock = (struct sockaddr *)&sa; /* bind to this address */ curl_socklen_t sizeof_sa = 0; /* size of the data sock points to */ - - union sockaddr_u { - struct sockaddr sa; - struct sockaddr_in sa4; + struct sockaddr_in *si4 = (struct sockaddr_in *)&sa; #ifdef ENABLE_IPV6 - struct sockaddr_in6 sa6; + struct sockaddr_in6 *si6 = (struct sockaddr_in6 *)&sa; #endif - }; - union sockaddr_u *sock = (union sockaddr_u *)&sa; /* bind to this address */ struct Curl_dns_entry *h=NULL; unsigned short port = data->set.localport; /* use this port number, 0 for @@ -377,18 +373,18 @@ static CURLcode bindlocal(struct connectdata *conn, #ifdef ENABLE_IPV6 /* ipv6 address */ if((af == AF_INET6) && - (Curl_inet_pton(AF_INET6, myhost, &sock->sa6.sin6_addr) > 0)) { - sock->sa6.sin6_family = AF_INET6; - sock->sa6.sin6_port = htons(port); + (Curl_inet_pton(AF_INET6, myhost, &si6->sin6_addr) > 0)) { + si6->sin6_family = AF_INET6; + si6->sin6_port = htons(port); sizeof_sa = sizeof(struct sockaddr_in6); } else #endif /* ipv4 address */ if((af == AF_INET) && - (Curl_inet_pton(AF_INET, myhost, &sock->sa4.sin_addr) > 0)) { - sock->sa4.sin_family = AF_INET; - sock->sa4.sin_port = htons(port); + (Curl_inet_pton(AF_INET, myhost, &si4->sin_addr) > 0)) { + si4->sin_family = AF_INET; + si4->sin_port = htons(port); sizeof_sa = sizeof(struct sockaddr_in); } } @@ -402,21 +398,21 @@ static CURLcode bindlocal(struct connectdata *conn, /* no device was given, prepare sa to match af's needs */ #ifdef ENABLE_IPV6 if(af == AF_INET6) { - sock->sa6.sin6_family = AF_INET6; - sock->sa6.sin6_port = htons(port); + si6->sin6_family = AF_INET6; + si6->sin6_port = htons(port); sizeof_sa = sizeof(struct sockaddr_in6); } else #endif if(af == AF_INET) { - sock->sa4.sin_family = AF_INET; - sock->sa4.sin_port = htons(port); + si4->sin_family = AF_INET; + si4->sin_port = htons(port); sizeof_sa = sizeof(struct sockaddr_in); } } for(;;) { - if(bind(sockfd, &sock->sa, sizeof_sa) >= 0) { + if(bind(sockfd, sock, sizeof_sa) >= 0) { /* we succeeded to bind */ struct Curl_sockaddr_storage add; curl_socklen_t size = sizeof(add); @@ -436,11 +432,11 @@ static CURLcode bindlocal(struct connectdata *conn, infof(data, "Bind to local port %hu failed, trying next\n", port); port++; /* try next port */ /* We re-use/clobber the port variable here below */ - if(sock->sa.sa_family == AF_INET) - sock->sa4.sin_port = ntohs(port); + if(sock->sa_family == AF_INET) + si4->sin_port = ntohs(port); #ifdef ENABLE_IPV6 else - sock->sa6.sin6_port = ntohs(port); + si6->sin6_port = ntohs(port); #endif } else -- cgit v1.2.1 From c0f8340c7c5ead51ffc6c6297d465221181de4bd Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sun, 22 Jul 2012 22:38:38 +0200 Subject: keepalive: multiply value for OS-specific units DragonFly uses milliseconds, while our API and Linux use full seconds. Reported by: John Marino Bug: http://curl.haxx.se/bug/view.cgi?id=3546257 --- lib/connect.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 42b626f1a..dc6291bda 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -91,6 +91,13 @@ static bool verifyconnect(curl_socket_t sockfd, int *error); +#ifdef __DragonFly__ +/* DragonFlyBSD uses millisecond as KEEPIDLE and KEEPINTVL units */ +#define KEEPALIVE_FACTOR(x) (x *= 1000) +#else +#define KEEPALIVE_FACTOR(x) +#endif + static void tcpkeepalive(struct SessionHandle *data, curl_socket_t sockfd) @@ -105,6 +112,7 @@ tcpkeepalive(struct SessionHandle *data, else { #ifdef TCP_KEEPIDLE optval = curlx_sltosi(data->set.tcp_keepidle); + KEEPALIVE_FACTOR(optval); if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE, (void *)&optval, sizeof(optval)) < 0) { infof(data, "Failed to set TCP_KEEPIDLE on fd %d\n", sockfd); @@ -112,6 +120,7 @@ tcpkeepalive(struct SessionHandle *data, #endif #ifdef TCP_KEEPINTVL optval = curlx_sltosi(data->set.tcp_keepintvl); + KEEPALIVE_FACTOR(optval); if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPINTVL, (void *)&optval, sizeof(optval)) < 0) { infof(data, "Failed to set TCP_KEEPINTVL on fd %d\n", sockfd); -- cgit v1.2.1 From e1fa945e7e55bf0dd2cc0de482753e00c2f36116 Mon Sep 17 00:00:00 2001 From: Lars Buitinck Date: Wed, 31 Oct 2012 16:58:53 +0100 Subject: Curl_connecthost: friendlier "couldn't connect" message --- lib/connect.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index dc6291bda..1651e6e20 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -1101,7 +1101,9 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ if(sockfd == CURL_SOCKET_BAD) { /* no good connect was made */ - failf(data, "couldn't connect to host"); + failf(data, "couldn't connect to %s at %s:%d", + conn->bits.proxy?"proxy":"host", + conn->bits.proxy?conn->proxy.name:conn->host.name, conn->port); return CURLE_COULDNT_CONNECT; } -- cgit v1.2.1 From d021f2e8a0067fc769652f27afec9024c0d02b3d Mon Sep 17 00:00:00 2001 From: Linus Nielsen Feltzing Date: Thu, 6 Dec 2012 12:12:04 +0100 Subject: Introducing a new persistent connection caching system using "bundles". A bundle is a list of all persistent connections to the same host. The connection cache consists of a hash of bundles, with the hostname as the key. The benefits may not be obvious, but they are two: 1) Faster search for connections to reuse, since the hash lookup only finds connections to the host in question. 2) It lays out the groundworks for an upcoming patch, which will introduce multiple HTTP pipelines. This patch also removes the awkward list of "closure handles", which were needed to send QUIT commands to the FTP server when closing a connection. Now we allocate a separate closure handle and use that one to close all connections. This has been tested in a live system for a few weeks, and of course passes the test suite. --- lib/connect.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index 1651e6e20..f615d81e9 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -1131,10 +1131,8 @@ curl_socket_t Curl_getconnectinfo(struct SessionHandle *data, DEBUGASSERT(data); - if((data->state.lastconnect != -1) && - (data->state.connc->connects[data->state.lastconnect] != NULL)) { - struct connectdata *c = - data->state.connc->connects[data->state.lastconnect]; + if(data->state.lastconnect) { + struct connectdata *c = data->state.lastconnect; if(connp) /* only store this if the caller cares for it */ *connp = c; -- cgit v1.2.1 From 4deb52831a071bc83cefb4871764281a5c32f902 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 11 Dec 2012 22:49:11 +0100 Subject: Curl_getconnectinfo: fixed to work with always-multi To make sure CURLINFO_LASTSOCKET works and curl_easy_recv() etc when the connection cache is now always in the multi handle that the easy handle doesn't have a strong connection to anymore, the code now searches for the last used connection in the last used multi handle to see if it is still there and then gets the socket from there. This makes CURLINFO_LASTSOCKET only work if curl_easy_perform() has been used on an easy handle, but that was always how the feature was documented. As a result of this restructure, I've created multihandle.h which now has the multi handle struct and related stuff defined so that more files than multi.c can use it. --- lib/connect.c | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) (limited to 'lib/connect.c') diff --git a/lib/connect.c b/lib/connect.c index f615d81e9..9930d3c3d 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -79,6 +79,8 @@ #include "inet_pton.h" #include "sslgen.h" /* for Curl_ssl_check_cxn() */ #include "progress.h" +#include "conncache.h" +#include "multihandle.h" #include "warnless.h" /* The last #include file should be: */ @@ -1118,6 +1120,21 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ return CURLE_OK; } +struct connfind { + struct connectdata *tofind; + bool found; +}; + +static int conn_is_conn(struct connectdata *conn, void *param) +{ + struct connfind *f = (struct connfind *)param; + if(conn == f->tofind) { + f->found = TRUE; + return 1; + } + return 0; +} + /* * Used to extract socket and connectdata struct for the most recent * transfer on the given SessionHandle. @@ -1131,8 +1148,21 @@ curl_socket_t Curl_getconnectinfo(struct SessionHandle *data, DEBUGASSERT(data); - if(data->state.lastconnect) { + /* this only works for an easy handle that has been used for + curl_easy_perform()! */ + if(data->state.lastconnect && data->multi_easy) { struct connectdata *c = data->state.lastconnect; + struct connfind find; + find.tofind = data->state.lastconnect; + find.found = FALSE; + + Curl_conncache_foreach(data->multi_easy->conn_cache, &find, conn_is_conn); + + if(!find.found) { + data->state.lastconnect = NULL; + return CURL_SOCKET_BAD; + } + if(connp) /* only store this if the caller cares for it */ *connp = c; -- cgit v1.2.1