diff options
Diffstat (limited to 'plugins/FTPFileYM/curl/lib/connect.c')
-rw-r--r-- | plugins/FTPFileYM/curl/lib/connect.c | 176 |
1 files changed, 136 insertions, 40 deletions
diff --git a/plugins/FTPFileYM/curl/lib/connect.c b/plugins/FTPFileYM/curl/lib/connect.c index 0afb1ee616..2b5719d123 100644 --- a/plugins/FTPFileYM/curl/lib/connect.c +++ b/plugins/FTPFileYM/curl/lib/connect.c @@ -87,13 +87,23 @@ static bool verifyconnect(curl_socket_t sockfd, int *error); -#ifdef __DragonFly__ -/* DragonFlyBSD uses millisecond as KEEPIDLE and KEEPINTVL units */ +#if defined(__DragonFly__) || defined(HAVE_WINSOCK_H) +/* DragonFlyBSD and Windows use millisecond units */ #define KEEPALIVE_FACTOR(x) (x *= 1000) #else #define KEEPALIVE_FACTOR(x) #endif +#if defined(HAVE_WINSOCK_H) && !defined(SIO_KEEPALIVE_VALS) +#define SIO_KEEPALIVE_VALS _WSAIOW(IOC_VENDOR,4) + +struct tcp_keepalive { + u_long onoff; + u_long keepalivetime; + u_long keepaliveinterval; +}; +#endif + static void tcpkeepalive(struct SessionHandle *data, curl_socket_t sockfd) @@ -106,6 +116,22 @@ tcpkeepalive(struct SessionHandle *data, infof(data, "Failed to set SO_KEEPALIVE on fd %d\n", sockfd); } else { +#if defined(SIO_KEEPALIVE_VALS) + struct tcp_keepalive vals; + DWORD dummy; + vals.onoff = 1; + optval = curlx_sltosi(data->set.tcp_keepidle); + KEEPALIVE_FACTOR(optval); + vals.keepalivetime = optval; + optval = curlx_sltosi(data->set.tcp_keepintvl); + KEEPALIVE_FACTOR(optval); + vals.keepaliveinterval = optval; + if(WSAIoctl(sockfd, SIO_KEEPALIVE_VALS, (LPVOID) &vals, sizeof(vals), + NULL, 0, &dummy, NULL, NULL) != 0) { + infof(data, "Failed to set SIO_KEEPALIVE_VALS on fd %d: %d\n", + (int)sockfd, WSAGetLastError()); + } +#else #ifdef TCP_KEEPIDLE optval = curlx_sltosi(data->set.tcp_keepidle); KEEPALIVE_FACTOR(optval); @@ -122,6 +148,16 @@ tcpkeepalive(struct SessionHandle *data, infof(data, "Failed to set TCP_KEEPINTVL on fd %d\n", sockfd); } #endif +#ifdef TCP_KEEPALIVE + /* Mac OS X style */ + optval = curlx_sltosi(data->set.tcp_keepidle); + KEEPALIVE_FACTOR(optval); + if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPALIVE, + (void *)&optval, sizeof(optval)) < 0) { + infof(data, "Failed to set TCP_KEEPALIVE on fd %d\n", sockfd); + } +#endif +#endif } } @@ -283,41 +319,54 @@ static CURLcode bindlocal(struct connectdata *conn, } /* interface */ - 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 - */ - infof(data, "Local Interface %s is ip %s using address family %i\n", - dev, myhost, af); - done = 1; + if(!is_host) { + switch(Curl_if2ip(af, conn->scope, dev, myhost, sizeof(myhost))) { + case IF2IP_NOT_FOUND: + if(is_interface) { + /* Do not fall back to treating it as a host name */ + failf(data, "Couldn't bind to interface '%s'", dev); + return CURLE_INTERFACE_FAILED; + } + break; + case IF2IP_AF_NOT_SUPPORTED: + /* Signal the caller to try another address family if available */ + return CURLE_UNSUPPORTED_PROTOCOL; + case IF2IP_FOUND: + is_interface = TRUE; + /* + * We now have the numerical IP address in the 'myhost' buffer + */ + infof(data, "Local Interface %s is ip %s using address family %i\n", + dev, myhost, af); + done = 1; #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, (curl_socklen_t)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 */ - } + /* 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, (curl_socklen_t)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 + break; + } } - else { + if(!is_interface) { /* * This was not an interface, resolve the name as a host name * or IP number @@ -361,10 +410,24 @@ static CURLcode bindlocal(struct connectdata *conn, if(done > 0) { #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); + if(af == AF_INET6) { +#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID + char *scope_ptr = strchr(myhost, '%'); + if(scope_ptr) + *(scope_ptr++) = 0; +#endif + if(Curl_inet_pton(AF_INET6, myhost, &si6->sin6_addr) > 0) { + si6->sin6_family = AF_INET6; + si6->sin6_port = htons(port); +#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID + if(scope_ptr) + /* The "myhost" string either comes from Curl_if2ip or from + Curl_printable_address. The latter returns only numeric scope + IDs and the former returns none at all. So the scope ID, if + present, is known to be numeric */ + si6->sin6_scope_id = atoi(scope_ptr); +#endif + } sizeof_sa = sizeof(struct sockaddr_in6); } else @@ -825,13 +888,35 @@ static void nosigpipe(struct connectdata *conn, Work-around: Make the Socket Send Buffer Size Larger Than the Program Send Buffer Size + The problem described in this knowledge-base is applied only to pre-Vista + Windows. Following function trying to detect OS version and skips + SO_SNDBUF adjustment for Windows Vista and above. */ +#define DETECT_OS_NONE 0 +#define DETECT_OS_PREVISTA 1 +#define DETECT_OS_VISTA_OR_LATER 2 + void Curl_sndbufset(curl_socket_t sockfd) { int val = CURL_MAX_WRITE_SIZE + 32; int curval = 0; int curlen = sizeof(curval); + OSVERSIONINFO osver; + static int detectOsState = DETECT_OS_NONE; + + if(detectOsState == DETECT_OS_NONE) { + memset(&osver, 0, sizeof(osver)); + osver.dwOSVersionInfoSize = sizeof(osver); + detectOsState = DETECT_OS_PREVISTA; + if(GetVersionEx(&osver)) { + if(osver.dwMajorVersion >= 6) + detectOsState = DETECT_OS_VISTA_OR_LATER; + } + } + if(detectOsState == DETECT_OS_VISTA_OR_LATER) + return; + if(getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (char *)&curval, &curlen) == 0) if(curval > val) return; @@ -917,6 +1002,11 @@ singleipconnect(struct connectdata *conn, res = bindlocal(conn, sockfd, addr.family); if(res) { Curl_closesocket(conn, sockfd); /* close socket and bail out */ + if(res == CURLE_UNSUPPORTED_PROTOCOL) { + /* The address family is not supported on this interface. + We can continue trying addresses */ + return CURLE_OK; + } return res; } @@ -1054,7 +1144,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ if(sockfd == CURL_SOCKET_BAD) { /* no good connect was made */ - failf(data, "couldn't connect to %s at %s:%d", + failf(data, "couldn't connect to %s at %s:%ld", conn->bits.proxy?"proxy":"host", conn->bits.proxy?conn->proxy.name:conn->host.name, conn->port); return CURLE_COULDNT_CONNECT; @@ -1149,7 +1239,7 @@ curl_socket_t Curl_getconnectinfo(struct SessionHandle *data, * 'conn' can be NULL, beware! */ int Curl_closesocket(struct connectdata *conn, - curl_socket_t sock) + curl_socket_t sock) { if(conn && conn->fclosesocket) { if((sock == conn->sock[SECONDARYSOCKET]) && @@ -1161,7 +1251,13 @@ int Curl_closesocket(struct connectdata *conn, else return conn->fclosesocket(conn->closesocket_client, sock); } - return sclose(sock); + sclose(sock); + + if(conn) + /* tell the multi-socket code about this */ + Curl_multi_closed(conn, sock); + + return 0; } /* |