1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
12 * are also available at http://curl.haxx.se/docs/copyright.html.
14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
16 * furnished to do so, under the terms of the COPYING file.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ***************************************************************************/
23 #include "curl_setup.h"
25 #ifdef HAVE_NETINET_IN_H
26 #include <netinet/in.h> /* <netinet/tcp.h> may need it */
29 #include <sys/un.h> /* for sockaddr_un */
31 #ifdef HAVE_NETINET_TCP_H
32 #include <netinet/tcp.h> /* for TCP_NODELAY */
34 #ifdef HAVE_SYS_IOCTL_H
35 #include <sys/ioctl.h>
43 #ifdef HAVE_ARPA_INET_H
44 #include <arpa/inet.h>
47 #if (defined(HAVE_IOCTL_FIONBIO) && defined(NETWARE))
48 #include <sys/filio.h>
52 #define in_addr_t unsigned long
59 #define _MPRINTF_REPLACE /* use our functions only */
60 #include <curl/mprintf.h>
67 #include "curl_memory.h"
69 #include "url.h" /* for Curl_safefree() */
71 #include "sockaddr.h" /* required for Curl_sockaddr_storage */
72 #include "inet_ntop.h"
73 #include "inet_pton.h"
74 #include "vtls/vtls.h" /* for Curl_ssl_check_cxn() */
77 #include "conncache.h"
78 #include "multihandle.h"
80 /* The last #include file should be: */
84 /* This isn't actually supported under Symbian OS */
88 static bool verifyconnect(curl_socket_t sockfd, int *error);
90 #if defined(__DragonFly__) || defined(HAVE_WINSOCK_H)
91 /* DragonFlyBSD and Windows use millisecond units */
92 #define KEEPALIVE_FACTOR(x) (x *= 1000)
94 #define KEEPALIVE_FACTOR(x)
97 #if defined(HAVE_WINSOCK_H) && !defined(SIO_KEEPALIVE_VALS)
98 #define SIO_KEEPALIVE_VALS _WSAIOW(IOC_VENDOR,4)
100 struct tcp_keepalive {
102 u_long keepalivetime;
103 u_long keepaliveinterval;
108 tcpkeepalive(struct SessionHandle *data,
109 curl_socket_t sockfd)
111 int optval = data->set.tcp_keepalive?1:0;
113 /* only set IDLE and INTVL if setting KEEPALIVE is successful */
114 if(setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE,
115 (void *)&optval, sizeof(optval)) < 0) {
116 infof(data, "Failed to set SO_KEEPALIVE on fd %d\n", sockfd);
119 #if defined(SIO_KEEPALIVE_VALS)
120 struct tcp_keepalive vals;
123 optval = curlx_sltosi(data->set.tcp_keepidle);
124 KEEPALIVE_FACTOR(optval);
125 vals.keepalivetime = optval;
126 optval = curlx_sltosi(data->set.tcp_keepintvl);
127 KEEPALIVE_FACTOR(optval);
128 vals.keepaliveinterval = optval;
129 if(WSAIoctl(sockfd, SIO_KEEPALIVE_VALS, (LPVOID) &vals, sizeof(vals),
130 NULL, 0, &dummy, NULL, NULL) != 0) {
131 infof(data, "Failed to set SIO_KEEPALIVE_VALS on fd %d: %d\n",
132 (int)sockfd, WSAGetLastError());
136 optval = curlx_sltosi(data->set.tcp_keepidle);
137 KEEPALIVE_FACTOR(optval);
138 if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE,
139 (void *)&optval, sizeof(optval)) < 0) {
140 infof(data, "Failed to set TCP_KEEPIDLE on fd %d\n", sockfd);
144 optval = curlx_sltosi(data->set.tcp_keepintvl);
145 KEEPALIVE_FACTOR(optval);
146 if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPINTVL,
147 (void *)&optval, sizeof(optval)) < 0) {
148 infof(data, "Failed to set TCP_KEEPINTVL on fd %d\n", sockfd);
153 optval = curlx_sltosi(data->set.tcp_keepidle);
154 KEEPALIVE_FACTOR(optval);
155 if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPALIVE,
156 (void *)&optval, sizeof(optval)) < 0) {
157 infof(data, "Failed to set TCP_KEEPALIVE on fd %d\n", sockfd);
165 singleipconnect(struct connectdata *conn,
166 const Curl_addrinfo *ai, /* start connecting to this */
167 curl_socket_t *sock);
170 * Curl_timeleft() returns the amount of milliseconds left allowed for the
171 * transfer/connection. If the value is negative, the timeout time has already
174 * The start time is stored in progress.t_startsingle - as set with
175 * Curl_pgrsTime(..., TIMER_STARTSINGLE);
177 * If 'nowp' is non-NULL, it points to the current time.
178 * 'duringconnect' is FALSE if not during a connect, as then of course the
179 * connect timeout is not taken into account!
183 long Curl_timeleft(struct SessionHandle *data,
184 struct timeval *nowp,
188 long timeout_ms = duringconnect?DEFAULT_CONNECT_TIMEOUT:0;
191 /* if a timeout is set, use the most restrictive one */
193 if(data->set.timeout > 0)
195 if(duringconnect && (data->set.connecttimeout > 0))
198 switch (timeout_set) {
200 timeout_ms = data->set.timeout;
203 timeout_ms = data->set.connecttimeout;
206 if(data->set.timeout < data->set.connecttimeout)
207 timeout_ms = data->set.timeout;
209 timeout_ms = data->set.connecttimeout;
212 /* use the default */
214 /* if we're not during connect, there's no default timeout so if we're
215 at zero we better just return zero and not make it a negative number
226 /* subtract elapsed time */
228 /* since this most recent connect started */
229 timeout_ms -= Curl_tvdiff(*nowp, data->progress.t_startsingle);
231 /* since the entire operation started */
232 timeout_ms -= Curl_tvdiff(*nowp, data->progress.t_startop);
234 /* avoid returning 0 as that means no timeout! */
240 static CURLcode bindlocal(struct connectdata *conn,
241 curl_socket_t sockfd, int af)
243 struct SessionHandle *data = conn->data;
245 struct Curl_sockaddr_storage sa;
246 struct sockaddr *sock = (struct sockaddr *)&sa; /* bind to this address */
247 curl_socklen_t sizeof_sa = 0; /* size of the data sock points to */
248 struct sockaddr_in *si4 = (struct sockaddr_in *)&sa;
250 struct sockaddr_in6 *si6 = (struct sockaddr_in6 *)&sa;
253 struct Curl_dns_entry *h=NULL;
254 unsigned short port = data->set.localport; /* use this port number, 0 for
256 /* how many port numbers to try to bind to, increasing one at a time */
257 int portnum = data->set.localportrange;
258 const char *dev = data->set.str[STRING_DEVICE];
260 char myhost[256] = "";
261 int done = 0; /* -1 for error, 1 for address found */
262 bool is_interface = FALSE;
263 bool is_host = FALSE;
264 static const char *if_prefix = "if!";
265 static const char *host_prefix = "host!";
267 /*************************************************************
268 * Select device to bind socket to
269 *************************************************************/
271 /* no local kind of binding was requested */
274 memset(&sa, 0, sizeof(struct Curl_sockaddr_storage));
276 if(dev && (strlen(dev)<255) ) {
277 if(strncmp(if_prefix, dev, strlen(if_prefix)) == 0) {
278 dev += strlen(if_prefix);
281 else if(strncmp(host_prefix, dev, strlen(host_prefix)) == 0) {
282 dev += strlen(host_prefix);
288 switch(Curl_if2ip(af, conn->scope, dev, myhost, sizeof(myhost))) {
289 case IF2IP_NOT_FOUND:
291 /* Do not fall back to treating it as a host name */
292 failf(data, "Couldn't bind to interface '%s'", dev);
293 return CURLE_INTERFACE_FAILED;
296 case IF2IP_AF_NOT_SUPPORTED:
297 /* Signal the caller to try another address family if available */
298 return CURLE_UNSUPPORTED_PROTOCOL;
302 * We now have the numerical IP address in the 'myhost' buffer
304 infof(data, "Local Interface %s is ip %s using address family %i\n",
308 #ifdef SO_BINDTODEVICE
309 /* I am not sure any other OSs than Linux that provide this feature,
310 * and at the least I cannot test. --Ben
312 * This feature allows one to tightly bind the local socket to a
313 * particular interface. This will force even requests to other
314 * local interfaces to go out the external interface.
317 * Only bind to the interface when specified as interface, not just
318 * as a hostname or ip address.
320 if(setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE,
321 dev, (curl_socklen_t)strlen(dev)+1) != 0) {
323 infof(data, "SO_BINDTODEVICE %s failed with errno %d: %s;"
324 " will do regular bind\n",
325 dev, error, Curl_strerror(conn, error));
326 /* This is typically "errno 1, error: Operation not permitted" if
327 you're not running as root or another suitable privileged
336 * This was not an interface, resolve the name as a host name
339 * Temporarily force name resolution to use only the address type
340 * of the connection. The resolve functions should really be changed
341 * to take a type parameter instead.
343 long ipver = conn->ip_version;
347 conn->ip_version = CURL_IPRESOLVE_V4;
349 else if(af == AF_INET6)
350 conn->ip_version = CURL_IPRESOLVE_V6;
353 rc = Curl_resolv(conn, dev, 0, &h);
354 if(rc == CURLRESOLV_PENDING)
355 (void)Curl_resolver_wait_resolv(conn, &h);
356 conn->ip_version = ipver;
359 /* convert the resolved address, sizeof myhost >= INET_ADDRSTRLEN */
360 Curl_printable_address(h->addr, myhost, sizeof(myhost));
361 infof(data, "Name '%s' family %i resolved to '%s' family %i\n",
362 dev, af, myhost, h->addr->ai_family);
363 Curl_resolv_unlock(data, h);
368 * provided dev was no interface (or interfaces are not supported
369 * e.g. solaris) no ip address and no domain we fail here
379 #ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
380 char *scope_ptr = strchr(myhost, '%');
384 if(Curl_inet_pton(AF_INET6, myhost, &si6->sin6_addr) > 0) {
385 si6->sin6_family = AF_INET6;
386 si6->sin6_port = htons(port);
387 #ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
389 /* The "myhost" string either comes from Curl_if2ip or from
390 Curl_printable_address. The latter returns only numeric scope
391 IDs and the former returns none at all. So the scope ID, if
392 present, is known to be numeric */
393 si6->sin6_scope_id = atoi(scope_ptr);
396 sizeof_sa = sizeof(struct sockaddr_in6);
401 if((af == AF_INET) &&
402 (Curl_inet_pton(AF_INET, myhost, &si4->sin_addr) > 0)) {
403 si4->sin_family = AF_INET;
404 si4->sin_port = htons(port);
405 sizeof_sa = sizeof(struct sockaddr_in);
410 failf(data, "Couldn't bind to '%s'", dev);
411 return CURLE_INTERFACE_FAILED;
415 /* no device was given, prepare sa to match af's needs */
418 si6->sin6_family = AF_INET6;
419 si6->sin6_port = htons(port);
420 sizeof_sa = sizeof(struct sockaddr_in6);
425 si4->sin_family = AF_INET;
426 si4->sin_port = htons(port);
427 sizeof_sa = sizeof(struct sockaddr_in);
432 if(bind(sockfd, sock, sizeof_sa) >= 0) {
433 /* we succeeded to bind */
434 struct Curl_sockaddr_storage add;
435 curl_socklen_t size = sizeof(add);
436 memset(&add, 0, sizeof(struct Curl_sockaddr_storage));
437 if(getsockname(sockfd, (struct sockaddr *) &add, &size) < 0) {
438 data->state.os_errno = error = SOCKERRNO;
439 failf(data, "getsockname() failed with errno %d: %s",
440 error, Curl_strerror(conn, error));
441 return CURLE_INTERFACE_FAILED;
443 infof(data, "Local port: %hu\n", port);
444 conn->bits.bound = TRUE;
449 infof(data, "Bind to local port %hu failed, trying next\n", port);
450 port++; /* try next port */
451 /* We re-use/clobber the port variable here below */
452 if(sock->sa_family == AF_INET)
453 si4->sin_port = ntohs(port);
456 si6->sin6_port = ntohs(port);
463 data->state.os_errno = error = SOCKERRNO;
464 failf(data, "bind failed with errno %d: %s",
465 error, Curl_strerror(conn, error));
467 return CURLE_INTERFACE_FAILED;
471 * verifyconnect() returns TRUE if the connect really has happened.
473 static bool verifyconnect(curl_socket_t sockfd, int *error)
478 curl_socklen_t errSize = sizeof(err);
482 * In October 2003 we effectively nullified this function on Windows due to
483 * problems with it using all CPU in multi-threaded cases.
485 * In May 2004, we bring it back to offer more info back on connect failures.
486 * Gisle Vanem could reproduce the former problems with this function, but
487 * could avoid them by adding this SleepEx() call below:
489 * "I don't have Rational Quantify, but the hint from his post was
490 * ntdll::NtRemoveIoCompletion(). So I'd assume the SleepEx (or maybe
491 * just Sleep(0) would be enough?) would release whatever
492 * mutex/critical-section the ntdll call is waiting on.
494 * Someone got to verify this on Win-NT 4.0, 2000."
505 if(0 != getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *)&err, &errSize))
508 /* Old WinCE versions don't support SO_ERROR */
509 if(WSAENOPROTOOPT == err) {
515 /* Minix 3.1.x doesn't support getsockopt on UDP sockets */
516 if(EBADIOCTL == err) {
521 if((0 == err) || (EISCONN == err))
522 /* we are connected, awesome! */
525 /* This wasn't a successful connect */
537 /* Used within the multi interface. Try next IP address, return TRUE if no
538 more address exists or error */
539 static CURLcode trynextip(struct connectdata *conn,
543 CURLcode rc = CURLE_COULDNT_CONNECT;
545 /* First clean up after the failed socket.
546 Don't close it yet to ensure that the next IP's socket gets a different
547 file descriptor, which can prevent bugs when the curl_multi_socket_action
548 interface is used with certain select() replacements such as kqueue. */
549 curl_socket_t fd_to_close = conn->tempsock[tempindex];
550 conn->tempsock[tempindex] = CURL_SOCKET_BAD;
552 if(sockindex == FIRSTSOCKET) {
553 Curl_addrinfo *ai = NULL;
554 int family = AF_UNSPEC;
556 if(conn->tempaddr[tempindex]) {
557 /* find next address in the same protocol family */
558 family = conn->tempaddr[tempindex]->ai_family;
559 ai = conn->tempaddr[tempindex]->ai_next;
561 else if(conn->tempaddr[0]) {
562 /* happy eyeballs - try the other protocol family */
563 int firstfamily = conn->tempaddr[0]->ai_family;
565 family = (firstfamily == AF_INET) ? AF_INET6 : AF_INET;
567 family = firstfamily;
569 ai = conn->tempaddr[0]->ai_next;
573 while(ai && ai->ai_family != family)
577 rc = singleipconnect(conn, ai, &conn->tempsock[tempindex]);
578 if(rc == CURLE_COULDNT_CONNECT) {
582 conn->tempaddr[tempindex] = ai;
588 if(fd_to_close != CURL_SOCKET_BAD)
589 Curl_closesocket(conn, fd_to_close);
594 /* Copies connection info into the session handle to make it available
595 when the session handle is no longer associated with a connection. */
596 void Curl_persistconninfo(struct connectdata *conn)
598 memcpy(conn->data->info.conn_primary_ip, conn->primary_ip, MAX_IPADR_LEN);
599 memcpy(conn->data->info.conn_local_ip, conn->local_ip, MAX_IPADR_LEN);
600 conn->data->info.conn_primary_port = conn->primary_port;
601 conn->data->info.conn_local_port = conn->local_port;
604 /* retrieves ip address and port from a sockaddr structure */
605 static bool getaddressinfo(struct sockaddr* sa, char* addr,
608 unsigned short us_port;
609 struct sockaddr_in* si = NULL;
611 struct sockaddr_in6* si6 = NULL;
613 #if defined(HAVE_SYS_UN_H) && defined(AF_UNIX)
614 struct sockaddr_un* su = NULL;
617 switch (sa->sa_family) {
619 si = (struct sockaddr_in*) sa;
620 if(Curl_inet_ntop(sa->sa_family, &si->sin_addr,
621 addr, MAX_IPADR_LEN)) {
622 us_port = ntohs(si->sin_port);
629 si6 = (struct sockaddr_in6*)sa;
630 if(Curl_inet_ntop(sa->sa_family, &si6->sin6_addr,
631 addr, MAX_IPADR_LEN)) {
632 us_port = ntohs(si6->sin6_port);
638 #if defined(HAVE_SYS_UN_H) && defined(AF_UNIX)
640 su = (struct sockaddr_un*)sa;
641 snprintf(addr, MAX_IPADR_LEN, "%s", su->sun_path);
655 /* retrieves the start/end point information of a socket of an established
657 void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
661 struct Curl_sockaddr_storage ssrem;
662 struct Curl_sockaddr_storage ssloc;
663 struct SessionHandle *data = conn->data;
665 if(conn->socktype == SOCK_DGRAM)
666 /* there's no connection! */
669 if(!conn->bits.reuse) {
671 len = sizeof(struct Curl_sockaddr_storage);
672 if(getpeername(sockfd, (struct sockaddr*) &ssrem, &len)) {
674 failf(data, "getpeername() failed with errno %d: %s",
675 error, Curl_strerror(conn, error));
679 len = sizeof(struct Curl_sockaddr_storage);
680 if(getsockname(sockfd, (struct sockaddr*) &ssloc, &len)) {
682 failf(data, "getsockname() failed with errno %d: %s",
683 error, Curl_strerror(conn, error));
687 if(!getaddressinfo((struct sockaddr*)&ssrem,
688 conn->primary_ip, &conn->primary_port)) {
690 failf(data, "ssrem inet_ntop() failed with errno %d: %s",
691 error, Curl_strerror(conn, error));
694 memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN);
696 if(!getaddressinfo((struct sockaddr*)&ssloc,
697 conn->local_ip, &conn->local_port)) {
699 failf(data, "ssloc inet_ntop() failed with errno %d: %s",
700 error, Curl_strerror(conn, error));
706 /* persist connection info in session handle */
707 Curl_persistconninfo(conn);
711 * Curl_is_connected() checks if the socket has connected.
714 CURLcode Curl_is_connected(struct connectdata *conn,
718 struct SessionHandle *data = conn->data;
719 CURLcode code = CURLE_OK;
726 DEBUGASSERT(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET);
728 *connected = FALSE; /* a very negative world view is best */
730 if(conn->bits.tcpconnect[sockindex]) {
731 /* we are connected already! */
738 /* figure out how long time we have left to connect */
739 allow = Curl_timeleft(data, &now, TRUE);
742 /* time-out, bail out, go home */
743 failf(data, "Connection time-out");
744 return CURLE_OPERATION_TIMEDOUT;
748 if(conn->tempsock[i] == CURL_SOCKET_BAD)
752 /* Call this function once now, and ignore the results. We do this to
753 "clear" the error state on the socket so that we can later read it
754 reliably. This is reported necessary on the MPE/iX operating system. */
755 (void)verifyconnect(conn->tempsock[i], NULL);
758 /* check socket for connect */
759 result = Curl_socket_ready(CURL_SOCKET_BAD, conn->tempsock[i], 0);
761 if(result == 0) { /* no connection yet */
762 if(curlx_tvdiff(now, conn->connecttime) >= conn->timeoutms_per_addr) {
763 infof(data, "After %ldms connect time, move on!\n",
764 conn->timeoutms_per_addr);
768 /* should we try another protocol family? */
769 if(i == 0 && conn->tempaddr[1] == NULL &&
770 curlx_tvdiff(now, conn->connecttime) >= HAPPY_EYEBALLS_TIMEOUT) {
771 trynextip(conn, sockindex, 1);
774 else if(result == CURL_CSELECT_OUT) {
775 if(verifyconnect(conn->tempsock[i], &error)) {
776 /* we are connected with TCP, awesome! */
779 /* use this socket from now on */
780 conn->sock[sockindex] = conn->tempsock[i];
781 conn->ip_addr = conn->tempaddr[i];
782 conn->tempsock[i] = CURL_SOCKET_BAD;
784 /* close the other socket, if open */
785 if(conn->tempsock[other] != CURL_SOCKET_BAD) {
786 Curl_closesocket(conn, conn->tempsock[other]);
787 conn->tempsock[other] = CURL_SOCKET_BAD;
790 /* see if we need to do any proxy magic first once we connected */
791 code = Curl_connected_proxy(conn, sockindex);
795 conn->bits.tcpconnect[sockindex] = TRUE;
798 if(sockindex == FIRSTSOCKET)
799 Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */
800 Curl_updateconninfo(conn, conn->sock[sockindex]);
801 Curl_verboseconnect(conn);
806 infof(data, "Connection failed\n");
808 else if(result & CURL_CSELECT_ERR)
809 (void)verifyconnect(conn->tempsock[i], &error);
812 * The connection failed here, we should attempt to connect to the "next
813 * address" for the given host. But first remember the latest error.
816 char ipaddress[MAX_IPADR_LEN];
817 data->state.os_errno = error;
818 SET_SOCKERRNO(error);
819 if(conn->tempaddr[i]) {
820 Curl_printable_address(conn->tempaddr[i], ipaddress, MAX_IPADR_LEN);
821 infof(data, "connect to %s port %ld failed: %s\n",
822 ipaddress, conn->port, Curl_strerror(conn, error));
824 conn->timeoutms_per_addr = conn->tempaddr[i]->ai_next == NULL ?
827 code = trynextip(conn, sockindex, i);
833 /* no more addresses to try */
835 /* if the first address family runs out of addresses to try before
836 the happy eyeball timeout, go ahead and try the next family now */
837 if(conn->tempaddr[1] == NULL) {
839 rc = trynextip(conn, sockindex, 1);
844 failf(data, "Failed to connect to %s port %ld: %s",
845 conn->bits.proxy?conn->proxy.name:conn->host.name,
846 conn->port, Curl_strerror(conn, error));
852 static void tcpnodelay(struct connectdata *conn,
853 curl_socket_t sockfd)
856 struct SessionHandle *data= conn->data;
857 curl_socklen_t onoff = (curl_socklen_t) data->set.tcp_nodelay;
858 int level = IPPROTO_TCP;
861 /* The use of getprotobyname() is disabled since it isn't thread-safe on
862 numerous systems. On these getprotobyname_r() should be used instead, but
863 that exists in at least one 4 arg version and one 5 arg version, and
864 since the proto number rarely changes anyway we now just use the hard
865 coded number. The "proper" fix would need a configure check for the
866 correct function much in the same style the gethostbyname_r versions are
868 struct protoent *pe = getprotobyname("tcp");
873 if(setsockopt(sockfd, level, TCP_NODELAY, (void *)&onoff,
875 infof(data, "Could not set TCP_NODELAY: %s\n",
876 Curl_strerror(conn, SOCKERRNO));
878 infof(data,"TCP_NODELAY set\n");
886 /* The preferred method on Mac OS X (10.2 and later) to prevent SIGPIPEs when
887 sending data to a dead peer (instead of relying on the 4th argument to send
888 being MSG_NOSIGNAL). Possibly also existing and in use on other BSD
890 static void nosigpipe(struct connectdata *conn,
891 curl_socket_t sockfd)
893 struct SessionHandle *data= conn->data;
895 if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff,
897 infof(data, "Could not set SO_NOSIGPIPE: %s\n",
898 Curl_strerror(conn, SOCKERRNO));
901 #define nosigpipe(x,y) Curl_nop_stmt
905 /* When you run a program that uses the Windows Sockets API, you may
906 experience slow performance when you copy data to a TCP server.
908 http://support.microsoft.com/kb/823764
910 Work-around: Make the Socket Send Buffer Size Larger Than the Program Send
913 The problem described in this knowledge-base is applied only to pre-Vista
914 Windows. Following function trying to detect OS version and skips
915 SO_SNDBUF adjustment for Windows Vista and above.
917 #define DETECT_OS_NONE 0
918 #define DETECT_OS_PREVISTA 1
919 #define DETECT_OS_VISTA_OR_LATER 2
921 void Curl_sndbufset(curl_socket_t sockfd)
923 int val = CURL_MAX_WRITE_SIZE + 32;
925 int curlen = sizeof(curval);
926 DWORD majorVersion = 6;
928 static int detectOsState = DETECT_OS_NONE;
930 if(detectOsState == DETECT_OS_NONE) {
931 #if !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_WIN2K) || \
932 (_WIN32_WINNT < _WIN32_WINNT_WIN2K)
935 memset(&osver, 0, sizeof(osver));
936 osver.dwOSVersionInfoSize = sizeof(osver);
938 detectOsState = DETECT_OS_PREVISTA;
939 if(GetVersionEx(&osver)) {
940 if(osver.dwMajorVersion >= majorVersion)
941 detectOsState = DETECT_OS_VISTA_OR_LATER;
944 ULONGLONG majorVersionMask;
945 OSVERSIONINFOEX osver;
947 memset(&osver, 0, sizeof(osver));
948 osver.dwOSVersionInfoSize = sizeof(osver);
949 osver.dwMajorVersion = majorVersion;
950 majorVersionMask = VerSetConditionMask(0, VER_MAJORVERSION,
953 if(VerifyVersionInfo(&osver, VER_MAJORVERSION, majorVersionMask))
954 detectOsState = DETECT_OS_VISTA_OR_LATER;
956 detectOsState = DETECT_OS_PREVISTA;
960 if(detectOsState == DETECT_OS_VISTA_OR_LATER)
963 if(getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (char *)&curval, &curlen) == 0)
967 setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (const char *)&val, sizeof(val));
974 * Note that even on connect fail it returns CURLE_OK, but with 'sock' set to
975 * CURL_SOCKET_BAD. Other errors will however return proper errors.
977 * singleipconnect() connects to the given IP only, and it may return without
981 singleipconnect(struct connectdata *conn,
982 const Curl_addrinfo *ai,
983 curl_socket_t *sockp)
985 struct Curl_sockaddr_ex addr;
988 bool isconnected = FALSE;
989 struct SessionHandle *data = conn->data;
990 curl_socket_t sockfd;
991 CURLcode res = CURLE_OK;
992 char ipaddress[MAX_IPADR_LEN];
995 *sockp = CURL_SOCKET_BAD;
997 res = Curl_socket(conn, ai, &addr, &sockfd);
999 /* Failed to create the socket, but still return OK since we signal the
1000 lack of socket as well. This allows the parent function to keep looping
1001 over alternative addresses/socket families etc. */
1004 /* store remote address and port used in this connection attempt */
1005 if(!getaddressinfo((struct sockaddr*)&addr.sa_addr,
1006 ipaddress, &port)) {
1007 /* malformed address or bug in inet_ntop, try next address */
1009 failf(data, "sa_addr inet_ntop() failed with errno %d: %s",
1010 error, Curl_strerror(conn, error));
1011 Curl_closesocket(conn, sockfd);
1014 infof(data, " Trying %s...\n", ipaddress);
1016 if(data->set.tcp_nodelay)
1017 tcpnodelay(conn, sockfd);
1019 nosigpipe(conn, sockfd);
1021 Curl_sndbufset(sockfd);
1023 if(data->set.tcp_keepalive)
1024 tcpkeepalive(data, sockfd);
1026 if(data->set.fsockopt) {
1027 /* activate callback for setting socket options */
1028 error = data->set.fsockopt(data->set.sockopt_client,
1030 CURLSOCKTYPE_IPCXN);
1032 if(error == CURL_SOCKOPT_ALREADY_CONNECTED)
1035 Curl_closesocket(conn, sockfd); /* close the socket and bail out */
1036 return CURLE_ABORTED_BY_CALLBACK;
1040 /* possibly bind the local end to an IP, interface or port */
1041 res = bindlocal(conn, sockfd, addr.family);
1043 Curl_closesocket(conn, sockfd); /* close socket and bail out */
1044 if(res == CURLE_UNSUPPORTED_PROTOCOL) {
1045 /* The address family is not supported on this interface.
1046 We can continue trying addresses */
1052 /* set socket non-blocking */
1053 curlx_nonblock(sockfd, TRUE);
1055 conn->connecttime = Curl_tvnow();
1056 if(conn->num_addr > 1)
1057 Curl_expire(data, conn->timeoutms_per_addr);
1059 /* Connect TCP sockets, bind UDP */
1060 if(!isconnected && (conn->socktype == SOCK_STREAM)) {
1061 rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
1071 conn->bits.ipv6 = (addr.family == AF_INET6)?TRUE:FALSE;
1079 #if (EAGAIN) != (EWOULDBLOCK)
1080 /* On some platforms EAGAIN and EWOULDBLOCK are the
1081 * same value, and on others they are different, hence
1091 /* unknown error, fallthrough and try another address! */
1092 infof(data, "Immediate connect fail for %s: %s\n",
1093 ipaddress, Curl_strerror(conn,error));
1094 data->state.os_errno = error;
1096 /* connect failed */
1097 Curl_closesocket(conn, sockfd);
1098 res = CURLE_COULDNT_CONNECT;
1109 * TCP connect to the given host with timeout, proxy or remote doesn't matter.
1110 * There might be more than one IP address to try out. Fill in the passed
1111 * pointer with the connected socket.
1114 CURLcode Curl_connecthost(struct connectdata *conn, /* context */
1115 const struct Curl_dns_entry *remotehost)
1117 struct SessionHandle *data = conn->data;
1118 struct timeval before = Curl_tvnow();
1119 CURLcode res = CURLE_COULDNT_CONNECT;
1121 long timeout_ms = Curl_timeleft(data, &before, TRUE);
1123 if(timeout_ms < 0) {
1124 /* a precaution, no need to continue if time already is up */
1125 failf(data, "Connection time-out");
1126 return CURLE_OPERATION_TIMEDOUT;
1129 conn->num_addr = Curl_num_addresses(remotehost->addr);
1130 conn->tempaddr[0] = remotehost->addr;
1131 conn->tempaddr[1] = NULL;
1132 conn->tempsock[0] = CURL_SOCKET_BAD;
1133 conn->tempsock[1] = CURL_SOCKET_BAD;
1134 Curl_expire(conn->data, HAPPY_EYEBALLS_TIMEOUT);
1136 /* Max time for the next connection attempt */
1137 conn->timeoutms_per_addr =
1138 conn->tempaddr[0]->ai_next == NULL ? timeout_ms : timeout_ms / 2;
1140 /* start connecting to first IP */
1141 while(conn->tempaddr[0]) {
1142 res = singleipconnect(conn, conn->tempaddr[0], &(conn->tempsock[0]));
1145 conn->tempaddr[0] = conn->tempaddr[0]->ai_next;
1148 if(conn->tempsock[0] == CURL_SOCKET_BAD)
1151 data->info.numconnects++; /* to track the number of connections made */
1157 struct connectdata *tofind;
1161 static int conn_is_conn(struct connectdata *conn, void *param)
1163 struct connfind *f = (struct connfind *)param;
1164 if(conn == f->tofind) {
1172 * Used to extract socket and connectdata struct for the most recent
1173 * transfer on the given SessionHandle.
1175 * The returned socket will be CURL_SOCKET_BAD in case of failure!
1177 curl_socket_t Curl_getconnectinfo(struct SessionHandle *data,
1178 struct connectdata **connp)
1180 curl_socket_t sockfd;
1184 /* this only works for an easy handle that has been used for
1185 curl_easy_perform()! */
1186 if(data->state.lastconnect && data->multi_easy) {
1187 struct connectdata *c = data->state.lastconnect;
1188 struct connfind find;
1189 find.tofind = data->state.lastconnect;
1192 Curl_conncache_foreach(data->multi_easy->conn_cache, &find, conn_is_conn);
1195 data->state.lastconnect = NULL;
1196 return CURL_SOCKET_BAD;
1200 /* only store this if the caller cares for it */
1202 sockfd = c->sock[FIRSTSOCKET];
1203 /* we have a socket connected, let's determine if the server shut down */
1204 /* determine if ssl */
1205 if(c->ssl[FIRSTSOCKET].use) {
1206 /* use the SSL context */
1207 if(!Curl_ssl_check_cxn(c))
1208 return CURL_SOCKET_BAD; /* FIN received */
1210 /* Minix 3.1 doesn't support any flags on recv; just assume socket is OK */
1213 /* use the socket */
1215 if(recv((RECV_TYPE_ARG1)c->sock[FIRSTSOCKET], (RECV_TYPE_ARG2)&buf,
1216 (RECV_TYPE_ARG3)1, (RECV_TYPE_ARG4)MSG_PEEK) == 0) {
1217 return CURL_SOCKET_BAD; /* FIN received */
1223 return CURL_SOCKET_BAD;
1231 * 'conn' can be NULL, beware!
1233 int Curl_closesocket(struct connectdata *conn,
1236 if(conn && conn->fclosesocket) {
1237 if((sock == conn->sock[SECONDARYSOCKET]) &&
1238 conn->sock_accepted[SECONDARYSOCKET])
1239 /* if this socket matches the second socket, and that was created with
1240 accept, then we MUST NOT call the callback but clear the accepted
1242 conn->sock_accepted[SECONDARYSOCKET] = FALSE;
1244 return conn->fclosesocket(conn->closesocket_client, sock);
1249 /* tell the multi-socket code about this */
1250 Curl_multi_closed(conn, sock);
1256 * Create a socket based on info from 'conn' and 'ai'.
1258 * 'addr' should be a pointer to the correct struct to get data back, or NULL.
1259 * 'sockfd' must be a pointer to a socket descriptor.
1261 * If the open socket callback is set, used that!
1264 CURLcode Curl_socket(struct connectdata *conn,
1265 const Curl_addrinfo *ai,
1266 struct Curl_sockaddr_ex *addr,
1267 curl_socket_t *sockfd)
1269 struct SessionHandle *data = conn->data;
1270 struct Curl_sockaddr_ex dummy;
1273 /* if the caller doesn't want info back, use a local temp copy */
1277 * The Curl_sockaddr_ex structure is basically libcurl's external API
1278 * curl_sockaddr structure with enough space available to directly hold
1279 * any protocol-specific address structures. The variable declared here
1280 * will be used to pass / receive data to/from the fopensocket callback
1281 * if this has been set, before that, it is initialized from parameters.
1284 addr->family = ai->ai_family;
1285 addr->socktype = conn->socktype;
1286 addr->protocol = conn->socktype==SOCK_DGRAM?IPPROTO_UDP:ai->ai_protocol;
1287 addr->addrlen = ai->ai_addrlen;
1289 if(addr->addrlen > sizeof(struct Curl_sockaddr_storage))
1290 addr->addrlen = sizeof(struct Curl_sockaddr_storage);
1291 memcpy(&addr->sa_addr, ai->ai_addr, addr->addrlen);
1293 if(data->set.fopensocket)
1295 * If the opensocket callback is set, all the destination address
1296 * information is passed to the callback. Depending on this information the
1297 * callback may opt to abort the connection, this is indicated returning
1298 * CURL_SOCKET_BAD; otherwise it will return a not-connected socket. When
1299 * the callback returns a valid socket the destination address information
1300 * might have been changed and this 'new' address will actually be used
1303 *sockfd = data->set.fopensocket(data->set.opensocket_client,
1305 (struct curl_sockaddr *)addr);
1307 /* opensocket callback not set, so simply create the socket now */
1308 *sockfd = socket(addr->family, addr->socktype, addr->protocol);
1310 if(*sockfd == CURL_SOCKET_BAD)
1311 /* no socket, no connection */
1312 return CURLE_COULDNT_CONNECT;
1314 #if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID)
1315 if(conn->scope && (addr->family == AF_INET6)) {
1316 struct sockaddr_in6 * const sa6 = (void *)&addr->sa_addr;
1317 sa6->sin6_scope_id = conn->scope;
1327 * Curl_conncontrol() is used to set the conn->bits.close bit on or off. It
1328 * MUST be called with the connclose() or connclose() macros with a stated
1329 * reason. The reason is only shown in debug builds but helps to figure out
1330 * decision paths when connections are or aren't re-used as expected.
1332 void Curl_conncontrol(struct connectdata *conn, bool closeit,
1335 infof(conn->data, "Marked for [%s]: %s\n", closeit?"closure":"keep alive",
1337 conn->bits.close = closeit; /* the only place in the source code that should