summaryrefslogtreecommitdiffstats
path: root/Utilities/cmcurl/lib/connect.c
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2015-08-12 19:43:52 (GMT)
committerBrad King <brad.king@kitware.com>2015-08-12 19:43:52 (GMT)
commit91e8d35ab8ec2d62478a42eff10af88713497fad (patch)
treeff8cd1bd1ce3c42ef56c76b5ab471831a80c4665 /Utilities/cmcurl/lib/connect.c
parent602cdc06a01b7c5c0eb444111382b09040f677ee (diff)
parent706542615828488a5ad197d0ef3dd5e42eb739c4 (diff)
downloadCMake-91e8d35ab8ec2d62478a42eff10af88713497fad.zip
CMake-91e8d35ab8ec2d62478a42eff10af88713497fad.tar.gz
CMake-91e8d35ab8ec2d62478a42eff10af88713497fad.tar.bz2
Merge branch 'curl-upstream' into update-curl
Resolve conflicts by taking upstream side when possible and otherwise integrating the changes from both sides. Be carful in CMakeLists.txt where the OPENSSL code block that we modified previously has moved, and preserve our previous modifications in the new location.
Diffstat (limited to 'Utilities/cmcurl/lib/connect.c')
-rw-r--r--Utilities/cmcurl/lib/connect.c227
1 files changed, 135 insertions, 92 deletions
diff --git a/Utilities/cmcurl/lib/connect.c b/Utilities/cmcurl/lib/connect.c
index fb315fc..18ac32c 100644
--- a/Utilities/cmcurl/lib/connect.c
+++ b/Utilities/cmcurl/lib/connect.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -56,15 +56,12 @@
#include <inet.h>
#endif
-#define _MPRINTF_REPLACE /* use our functions only */
-#include <curl/mprintf.h>
-
+#include "curl_printf.h"
#include "urldata.h"
#include "sendf.h"
#include "if2ip.h"
#include "strerror.h"
#include "connect.h"
-#include "curl_memory.h"
#include "select.h"
#include "url.h" /* for Curl_safefree() */
#include "multiif.h"
@@ -77,7 +74,8 @@
#include "conncache.h"
#include "multihandle.h"
-/* The last #include file should be: */
+/* The last #include files should be: */
+#include "curl_memory.h"
#include "memdebug.h"
#ifdef __SYMBIAN32__
@@ -238,7 +236,7 @@ long Curl_timeleft(struct SessionHandle *data,
}
static CURLcode bindlocal(struct connectdata *conn,
- curl_socket_t sockfd, int af)
+ curl_socket_t sockfd, int af, unsigned int scope)
{
struct SessionHandle *data = conn->data;
@@ -257,12 +255,6 @@ 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 */
- bool is_interface = FALSE;
- bool is_host = FALSE;
- static const char *if_prefix = "if!";
- static const char *host_prefix = "host!";
/*************************************************************
* Select device to bind socket to
@@ -274,6 +266,13 @@ static CURLcode bindlocal(struct connectdata *conn,
memset(&sa, 0, sizeof(struct Curl_sockaddr_storage));
if(dev && (strlen(dev)<255) ) {
+ char myhost[256] = "";
+ int done = 0; /* -1 for error, 1 for address found */
+ bool is_interface = FALSE;
+ bool is_host = FALSE;
+ static const char *if_prefix = "if!";
+ static const char *host_prefix = "host!";
+
if(strncmp(if_prefix, dev, strlen(if_prefix)) == 0) {
dev += strlen(if_prefix);
is_interface = TRUE;
@@ -285,7 +284,8 @@ static CURLcode bindlocal(struct connectdata *conn,
/* interface */
if(!is_host) {
- switch(Curl_if2ip(af, conn->scope, dev, myhost, sizeof(myhost))) {
+ switch(Curl_if2ip(af, scope, conn->scope_id, dev,
+ myhost, sizeof(myhost))) {
case IF2IP_NOT_FOUND:
if(is_interface) {
/* Do not fall back to treating it as a host name */
@@ -374,7 +374,7 @@ static CURLcode bindlocal(struct connectdata *conn,
if(done > 0) {
#ifdef ENABLE_IPV6
- /* ipv6 address */
+ /* IPv6 address */
if(af == AF_INET6) {
#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
char *scope_ptr = strchr(myhost, '%');
@@ -397,7 +397,7 @@ static CURLcode bindlocal(struct connectdata *conn,
}
else
#endif
- /* ipv4 address */
+ /* IPv4 address */
if((af == AF_INET) &&
(Curl_inet_pton(AF_INET, myhost, &si4->sin_addr) > 0)) {
si4->sin_family = AF_INET;
@@ -540,7 +540,8 @@ static CURLcode trynextip(struct connectdata *conn,
int sockindex,
int tempindex)
{
- CURLcode rc = CURLE_COULDNT_CONNECT;
+ const int other = tempindex ^ 1;
+ CURLcode result = CURLE_COULDNT_CONNECT;
/* First clean up after the failed socket.
Don't close it yet to ensure that the next IP's socket gets a different
@@ -558,27 +559,29 @@ static CURLcode trynextip(struct connectdata *conn,
family = conn->tempaddr[tempindex]->ai_family;
ai = conn->tempaddr[tempindex]->ai_next;
}
+#ifdef ENABLE_IPV6
else if(conn->tempaddr[0]) {
/* happy eyeballs - try the other protocol family */
int firstfamily = conn->tempaddr[0]->ai_family;
-#ifdef ENABLE_IPV6
family = (firstfamily == AF_INET) ? AF_INET6 : AF_INET;
-#else
- family = firstfamily;
-#endif
ai = conn->tempaddr[0]->ai_next;
}
+#endif
while(ai) {
- while(ai && ai->ai_family != family)
- ai = ai->ai_next;
+ if(conn->tempaddr[other]) {
+ /* we can safely skip addresses of the other protocol family */
+ while(ai && ai->ai_family != family)
+ ai = ai->ai_next;
+ }
if(ai) {
- rc = singleipconnect(conn, ai, &conn->tempsock[tempindex]);
- if(rc == CURLE_COULDNT_CONNECT) {
+ result = singleipconnect(conn, ai, &conn->tempsock[tempindex]);
+ if(result == CURLE_COULDNT_CONNECT) {
ai = ai->ai_next;
continue;
}
+
conn->tempaddr[tempindex] = ai;
}
break;
@@ -588,7 +591,7 @@ static CURLcode trynextip(struct connectdata *conn,
if(fd_to_close != CURL_SOCKET_BAD)
Curl_closesocket(conn, fd_to_close);
- return rc;
+ return result;
}
/* Copies connection info into the session handle to make it available
@@ -656,7 +659,6 @@ static bool getaddressinfo(struct sockaddr* sa, char* addr,
connection */
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;
@@ -667,6 +669,7 @@ void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
return;
if(!conn->bits.reuse) {
+ int error;
len = sizeof(struct Curl_sockaddr_storage);
if(getpeername(sockfd, (struct sockaddr*) &ssrem, &len)) {
@@ -677,6 +680,7 @@ void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
}
len = sizeof(struct Curl_sockaddr_storage);
+ memset(&ssloc, 0, sizeof(ssloc));
if(getsockname(sockfd, (struct sockaddr*) &ssloc, &len)) {
error = SOCKERRNO;
failf(data, "getsockname() failed with errno %d: %s",
@@ -716,11 +720,11 @@ CURLcode Curl_is_connected(struct connectdata *conn,
bool *connected)
{
struct SessionHandle *data = conn->data;
- CURLcode code = CURLE_OK;
+ CURLcode result = CURLE_OK;
long allow;
int error = 0;
struct timeval now;
- int result;
+ int rc;
int i;
DEBUGASSERT(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET);
@@ -745,6 +749,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
}
for(i=0; i<2; i++) {
+ const int other = i ^ 1;
if(conn->tempsock[i] == CURL_SOCKET_BAD)
continue;
@@ -756,9 +761,9 @@ CURLcode Curl_is_connected(struct connectdata *conn,
#endif
/* check socket for connect */
- result = Curl_socket_ready(CURL_SOCKET_BAD, conn->tempsock[i], 0);
+ rc = Curl_socket_ready(CURL_SOCKET_BAD, conn->tempsock[i], 0);
- if(result == 0) { /* no connection yet */
+ if(rc == 0) { /* no connection yet */
if(curlx_tvdiff(now, conn->connecttime) >= conn->timeoutms_per_addr) {
infof(data, "After %ldms connect time, move on!\n",
conn->timeoutms_per_addr);
@@ -771,10 +776,9 @@ CURLcode Curl_is_connected(struct connectdata *conn,
trynextip(conn, sockindex, 1);
}
}
- else if(result == CURL_CSELECT_OUT) {
+ else if(rc == CURL_CSELECT_OUT) {
if(verifyconnect(conn->tempsock[i], &error)) {
/* we are connected with TCP, awesome! */
- int other = i ^ 1;
/* use this socket from now on */
conn->sock[sockindex] = conn->tempsock[i];
@@ -788,9 +792,9 @@ CURLcode Curl_is_connected(struct connectdata *conn,
}
/* see if we need to do any proxy magic first once we connected */
- code = Curl_connected_proxy(conn, sockindex);
- if(code)
- return code;
+ result = Curl_connected_proxy(conn, sockindex);
+ if(result)
+ return result;
conn->bits.tcpconnect[sockindex] = TRUE;
@@ -805,7 +809,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
else
infof(data, "Connection failed\n");
}
- else if(result & CURL_CSELECT_ERR)
+ else if(rc & CURL_CSELECT_ERR)
(void)verifyconnect(conn->tempsock[i], &error);
/*
@@ -813,10 +817,11 @@ CURLcode Curl_is_connected(struct connectdata *conn,
* address" for the given host. But first remember the latest error.
*/
if(error) {
- char ipaddress[MAX_IPADR_LEN];
data->state.os_errno = error;
SET_SOCKERRNO(error);
if(conn->tempaddr[i]) {
+ CURLcode status;
+ char ipaddress[MAX_IPADR_LEN];
Curl_printable_address(conn->tempaddr[i], ipaddress, MAX_IPADR_LEN);
infof(data, "connect to %s port %ld failed: %s\n",
ipaddress, conn->port, Curl_strerror(conn, error));
@@ -824,21 +829,24 @@ CURLcode Curl_is_connected(struct connectdata *conn,
conn->timeoutms_per_addr = conn->tempaddr[i]->ai_next == NULL ?
allow : allow / 2;
- code = trynextip(conn, sockindex, i);
+ status = trynextip(conn, sockindex, i);
+ if(status != CURLE_COULDNT_CONNECT
+ || conn->tempsock[other] == CURL_SOCKET_BAD)
+ /* the last attempt failed and no other sockets remain open */
+ result = status;
}
}
}
- if(code) {
+ if(result) {
/* no more addresses to try */
/* if the first address family runs out of addresses to try before
the happy eyeball timeout, go ahead and try the next family now */
if(conn->tempaddr[1] == NULL) {
- int rc;
- rc = trynextip(conn, sockindex, 1);
- if(rc == CURLE_OK)
- return CURLE_OK;
+ result = trynextip(conn, sockindex, 1);
+ if(!result)
+ return result;
}
failf(data, "Failed to connect to %s port %ld: %s",
@@ -846,7 +854,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
conn->port, Curl_strerror(conn, error));
}
- return code;
+ return result;
}
static void tcpnodelay(struct connectdata *conn,
@@ -875,7 +883,7 @@ static void tcpnodelay(struct connectdata *conn,
infof(data, "Could not set TCP_NODELAY: %s\n",
Curl_strerror(conn, SOCKERRNO));
else
- infof(data,"TCP_NODELAY set\n");
+ infof(data, "TCP_NODELAY set\n");
#else
(void)conn;
(void)sockfd;
@@ -941,16 +949,21 @@ void Curl_sndbufset(curl_socket_t sockfd)
detectOsState = DETECT_OS_VISTA_OR_LATER;
}
#else
- ULONGLONG majorVersionMask;
+ ULONGLONG cm;
OSVERSIONINFOEX osver;
memset(&osver, 0, sizeof(osver));
osver.dwOSVersionInfoSize = sizeof(osver);
osver.dwMajorVersion = majorVersion;
- majorVersionMask = VerSetConditionMask(0, VER_MAJORVERSION,
- VER_GREATER_EQUAL);
- if(VerifyVersionInfo(&osver, VER_MAJORVERSION, majorVersionMask))
+ cm = VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL);
+ cm = VerSetConditionMask(cm, VER_MINORVERSION, VER_GREATER_EQUAL);
+ cm = VerSetConditionMask(cm, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
+ cm = VerSetConditionMask(cm, VER_SERVICEPACKMINOR, VER_GREATER_EQUAL);
+
+ if(VerifyVersionInfo(&osver, (VER_MAJORVERSION | VER_MINORVERSION |
+ VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR),
+ cm))
detectOsState = DETECT_OS_VISTA_OR_LATER;
else
detectOsState = DETECT_OS_PREVISTA;
@@ -977,10 +990,9 @@ void Curl_sndbufset(curl_socket_t sockfd)
* singleipconnect() connects to the given IP only, and it may return without
* having connected.
*/
-static CURLcode
-singleipconnect(struct connectdata *conn,
- const Curl_addrinfo *ai,
- curl_socket_t *sockp)
+static CURLcode singleipconnect(struct connectdata *conn,
+ const Curl_addrinfo *ai,
+ curl_socket_t *sockp)
{
struct Curl_sockaddr_ex addr;
int rc;
@@ -988,14 +1000,15 @@ singleipconnect(struct connectdata *conn,
bool isconnected = FALSE;
struct SessionHandle *data = conn->data;
curl_socket_t sockfd;
- CURLcode res = CURLE_OK;
+ CURLcode result;
char ipaddress[MAX_IPADR_LEN];
long port;
+ bool is_tcp;
*sockp = CURL_SOCKET_BAD;
- res = Curl_socket(conn, ai, &addr, &sockfd);
- if(res)
+ result = Curl_socket(conn, ai, &addr, &sockfd);
+ if(result)
/* 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. */
@@ -1013,14 +1026,20 @@ singleipconnect(struct connectdata *conn,
}
infof(data, " Trying %s...\n", ipaddress);
- if(data->set.tcp_nodelay)
+#ifdef ENABLE_IPV6
+ is_tcp = (addr.family == AF_INET || addr.family == AF_INET6) &&
+ addr.socktype == SOCK_STREAM;
+#else
+ is_tcp = (addr.family == AF_INET) && addr.socktype == SOCK_STREAM;
+#endif
+ if(is_tcp && data->set.tcp_nodelay)
tcpnodelay(conn, sockfd);
nosigpipe(conn, sockfd);
Curl_sndbufset(sockfd);
- if(data->set.tcp_keepalive)
+ if(is_tcp && data->set.tcp_keepalive)
tcpkeepalive(data, sockfd);
if(data->set.fsockopt) {
@@ -1038,19 +1057,26 @@ singleipconnect(struct connectdata *conn,
}
/* possibly bind the local end to an IP, interface or port */
- 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;
+ if(addr.family == AF_INET
+#ifdef ENABLE_IPV6
+ || addr.family == AF_INET6
+#endif
+ ) {
+ result = bindlocal(conn, sockfd, addr.family,
+ Curl_ipv6_scope((struct sockaddr*)&addr.sa_addr));
+ if(result) {
+ Curl_closesocket(conn, sockfd); /* close socket and bail out */
+ if(result == CURLE_UNSUPPORTED_PROTOCOL) {
+ /* The address family is not supported on this interface.
+ We can continue trying addresses */
+ return CURLE_COULDNT_CONNECT;
+ }
+ return result;
}
- return res;
}
/* set socket non-blocking */
- curlx_nonblock(sockfd, TRUE);
+ (void)curlx_nonblock(sockfd, TRUE);
conn->connecttime = Curl_tvnow();
if(conn->num_addr > 1)
@@ -1084,25 +1110,25 @@ singleipconnect(struct connectdata *conn,
case EAGAIN:
#endif
#endif
- res = CURLE_OK;
+ result = CURLE_OK;
break;
default:
/* unknown error, fallthrough and try another address! */
infof(data, "Immediate connect fail for %s: %s\n",
- ipaddress, Curl_strerror(conn,error));
+ ipaddress, Curl_strerror(conn, error));
data->state.os_errno = error;
/* connect failed */
Curl_closesocket(conn, sockfd);
- res = CURLE_COULDNT_CONNECT;
+ result = CURLE_COULDNT_CONNECT;
}
}
- if(!res)
+ if(!result)
*sockp = sockfd;
- return res;
+ return result;
}
/*
@@ -1116,7 +1142,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
{
struct SessionHandle *data = conn->data;
struct timeval before = Curl_tvnow();
- CURLcode res = CURLE_COULDNT_CONNECT;
+ CURLcode result = CURLE_COULDNT_CONNECT;
long timeout_ms = Curl_timeleft(data, &before, TRUE);
@@ -1139,14 +1165,17 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
/* start connecting to first IP */
while(conn->tempaddr[0]) {
- res = singleipconnect(conn, conn->tempaddr[0], &(conn->tempsock[0]));
- if(res == CURLE_OK)
- break;
+ result = singleipconnect(conn, conn->tempaddr[0], &(conn->tempsock[0]));
+ if(!result)
+ break;
conn->tempaddr[0] = conn->tempaddr[0]->ai_next;
}
- if(conn->tempsock[0] == CURL_SOCKET_BAD)
- return res;
+ if(conn->tempsock[0] == CURL_SOCKET_BAD) {
+ if(!result)
+ result = CURLE_COULDNT_CONNECT;
+ return result;
+ }
data->info.numconnects++; /* to track the number of connections made */
@@ -1181,15 +1210,20 @@ curl_socket_t Curl_getconnectinfo(struct SessionHandle *data,
DEBUGASSERT(data);
- /* this only works for an easy handle that has been used for
- curl_easy_perform()! */
- if(data->state.lastconnect && data->multi_easy) {
+ /* this works for an easy handle:
+ * - that has been used for curl_easy_perform()
+ * - that is associated with a multi handle, and whose connection
+ * was detached with CURLOPT_CONNECT_ONLY
+ */
+ if(data->state.lastconnect && (data->multi_easy || data->multi)) {
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);
+ Curl_conncache_foreach(data->multi_easy?
+ &data->multi_easy->conn_cache:
+ &data->multi->conn_cache, &find, conn_is_conn);
if(!find.found) {
data->state.lastconnect = NULL;
@@ -1240,15 +1274,18 @@ int Curl_closesocket(struct connectdata *conn,
accept, then we MUST NOT call the callback but clear the accepted
status */
conn->sock_accepted[SECONDARYSOCKET] = FALSE;
- else
+ else {
+ Curl_multi_closed(conn, sock);
return conn->fclosesocket(conn->closesocket_client, sock);
+ }
}
- sclose(sock);
if(conn)
/* tell the multi-socket code about this */
Curl_multi_closed(conn, sock);
+ sclose(sock);
+
return 0;
}
@@ -1312,9 +1349,9 @@ CURLcode Curl_socket(struct connectdata *conn,
return CURLE_COULDNT_CONNECT;
#if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID)
- if(conn->scope && (addr->family == AF_INET6)) {
+ if(conn->scope_id && (addr->family == AF_INET6)) {
struct sockaddr_in6 * const sa6 = (void *)&addr->sa_addr;
- sa6->sin6_scope_id = conn->scope;
+ sa6->sin6_scope_id = conn->scope_id;
}
#endif
@@ -1325,16 +1362,22 @@ CURLcode Curl_socket(struct connectdata *conn,
#ifdef CURLDEBUG
/*
* Curl_conncontrol() is used to set the conn->bits.close bit on or off. It
- * MUST be called with the connclose() or connclose() macros with a stated
+ * MUST be called with the connclose() or connkeep() macros with a stated
* reason. The reason is only shown in debug builds but helps to figure out
* decision paths when connections are or aren't re-used as expected.
*/
void Curl_conncontrol(struct connectdata *conn, bool closeit,
const char *reason)
{
- infof(conn->data, "Marked for [%s]: %s\n", closeit?"closure":"keep alive",
- reason);
- conn->bits.close = closeit; /* the only place in the source code that should
- assign this bit */
+#if defined(CURL_DISABLE_VERBOSE_STRINGS)
+ (void) reason;
+#endif
+ if(closeit != conn->bits.close) {
+ infof(conn->data, "Marked for [%s]: %s\n", closeit?"closure":"keep alive",
+ reason);
+
+ conn->bits.close = closeit; /* the only place in the source code that
+ should assign this bit */
+ }
}
#endif