summaryrefslogtreecommitdiff
path: root/plugins/FTPFileYM/curl/lib/connect.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/FTPFileYM/curl/lib/connect.c')
-rw-r--r--plugins/FTPFileYM/curl/lib/connect.c176
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;
}
/*