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_WINSOCK2_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, unsigned int scope)
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];
261 /*************************************************************
262 * Select device to bind socket to
263 *************************************************************/
265 /* no local kind of binding was requested */
268 memset(&sa, 0, sizeof(struct Curl_sockaddr_storage));
270 if(dev && (strlen(dev)<255) ) {
271 char myhost[256] = "";
272 int done = 0; /* -1 for error, 1 for address found */
273 bool is_interface = FALSE;
274 bool is_host = FALSE;
275 static const char *if_prefix = "if!";
276 static const char *host_prefix = "host!";
278 if(strncmp(if_prefix, dev, strlen(if_prefix)) == 0) {
279 dev += strlen(if_prefix);
282 else if(strncmp(host_prefix, dev, strlen(host_prefix)) == 0) {
283 dev += strlen(host_prefix);
289 switch(Curl_if2ip(af, scope, conn->scope_id, dev,
290 myhost, sizeof(myhost))) {
291 case IF2IP_NOT_FOUND:
293 /* Do not fall back to treating it as a host name */
294 failf(data, "Couldn't bind to interface '%s'", dev);
295 return CURLE_INTERFACE_FAILED;
298 case IF2IP_AF_NOT_SUPPORTED:
299 /* Signal the caller to try another address family if available */
300 return CURLE_UNSUPPORTED_PROTOCOL;
304 * We now have the numerical IP address in the 'myhost' buffer
306 infof(data, "Local Interface %s is ip %s using address family %i\n",
310 #ifdef SO_BINDTODEVICE
311 /* I am not sure any other OSs than Linux that provide this feature,
312 * and at the least I cannot test. --Ben
314 * This feature allows one to tightly bind the local socket to a
315 * particular interface. This will force even requests to other
316 * local interfaces to go out the external interface.
319 * Only bind to the interface when specified as interface, not just
320 * as a hostname or ip address.
322 if(setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE,
323 dev, (curl_socklen_t)strlen(dev)+1) != 0) {
325 infof(data, "SO_BINDTODEVICE %s failed with errno %d: %s;"
326 " will do regular bind\n",
327 dev, error, Curl_strerror(conn, error));
328 /* This is typically "errno 1, error: Operation not permitted" if
329 you're not running as root or another suitable privileged
338 * This was not an interface, resolve the name as a host name
341 * Temporarily force name resolution to use only the address type
342 * of the connection. The resolve functions should really be changed
343 * to take a type parameter instead.
345 long ipver = conn->ip_version;
349 conn->ip_version = CURL_IPRESOLVE_V4;
351 else if(af == AF_INET6)
352 conn->ip_version = CURL_IPRESOLVE_V6;
355 rc = Curl_resolv(conn, dev, 0, &h);
356 if(rc == CURLRESOLV_PENDING)
357 (void)Curl_resolver_wait_resolv(conn, &h);
358 conn->ip_version = ipver;
361 /* convert the resolved address, sizeof myhost >= INET_ADDRSTRLEN */
362 Curl_printable_address(h->addr, myhost, sizeof(myhost));
363 infof(data, "Name '%s' family %i resolved to '%s' family %i\n",
364 dev, af, myhost, h->addr->ai_family);
365 Curl_resolv_unlock(data, h);
370 * provided dev was no interface (or interfaces are not supported
371 * e.g. solaris) no ip address and no domain we fail here
381 #ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
382 char *scope_ptr = strchr(myhost, '%');
386 if(Curl_inet_pton(AF_INET6, myhost, &si6->sin6_addr) > 0) {
387 si6->sin6_family = AF_INET6;
388 si6->sin6_port = htons(port);
389 #ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
391 /* The "myhost" string either comes from Curl_if2ip or from
392 Curl_printable_address. The latter returns only numeric scope
393 IDs and the former returns none at all. So the scope ID, if
394 present, is known to be numeric */
395 si6->sin6_scope_id = atoi(scope_ptr);
398 sizeof_sa = sizeof(struct sockaddr_in6);
403 if((af == AF_INET) &&
404 (Curl_inet_pton(AF_INET, myhost, &si4->sin_addr) > 0)) {
405 si4->sin_family = AF_INET;
406 si4->sin_port = htons(port);
407 sizeof_sa = sizeof(struct sockaddr_in);
412 failf(data, "Couldn't bind to '%s'", dev);
413 return CURLE_INTERFACE_FAILED;
417 /* no device was given, prepare sa to match af's needs */
420 si6->sin6_family = AF_INET6;
421 si6->sin6_port = htons(port);
422 sizeof_sa = sizeof(struct sockaddr_in6);
427 si4->sin_family = AF_INET;
428 si4->sin_port = htons(port);
429 sizeof_sa = sizeof(struct sockaddr_in);
434 if(bind(sockfd, sock, sizeof_sa) >= 0) {
435 /* we succeeded to bind */
436 struct Curl_sockaddr_storage add;
437 curl_socklen_t size = sizeof(add);
438 memset(&add, 0, sizeof(struct Curl_sockaddr_storage));
439 if(getsockname(sockfd, (struct sockaddr *) &add, &size) < 0) {
440 data->state.os_errno = error = SOCKERRNO;
441 failf(data, "getsockname() failed with errno %d: %s",
442 error, Curl_strerror(conn, error));
443 return CURLE_INTERFACE_FAILED;
445 infof(data, "Local port: %hu\n", port);
446 conn->bits.bound = TRUE;
451 infof(data, "Bind to local port %hu failed, trying next\n", port);
452 port++; /* try next port */
453 /* We re-use/clobber the port variable here below */
454 if(sock->sa_family == AF_INET)
455 si4->sin_port = ntohs(port);
458 si6->sin6_port = ntohs(port);
465 data->state.os_errno = error = SOCKERRNO;
466 failf(data, "bind failed with errno %d: %s",
467 error, Curl_strerror(conn, error));
469 return CURLE_INTERFACE_FAILED;
473 * verifyconnect() returns TRUE if the connect really has happened.
475 static bool verifyconnect(curl_socket_t sockfd, int *error)
480 curl_socklen_t errSize = sizeof(err);
484 * In October 2003 we effectively nullified this function on Windows due to
485 * problems with it using all CPU in multi-threaded cases.
487 * In May 2004, we bring it back to offer more info back on connect failures.
488 * Gisle Vanem could reproduce the former problems with this function, but
489 * could avoid them by adding this SleepEx() call below:
491 * "I don't have Rational Quantify, but the hint from his post was
492 * ntdll::NtRemoveIoCompletion(). So I'd assume the SleepEx (or maybe
493 * just Sleep(0) would be enough?) would release whatever
494 * mutex/critical-section the ntdll call is waiting on.
496 * Someone got to verify this on Win-NT 4.0, 2000."
507 if(0 != getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *)&err, &errSize))
510 /* Old WinCE versions don't support SO_ERROR */
511 if(WSAENOPROTOOPT == err) {
517 /* Minix 3.1.x doesn't support getsockopt on UDP sockets */
518 if(EBADIOCTL == err) {
523 if((0 == err) || (EISCONN == err))
524 /* we are connected, awesome! */
527 /* This wasn't a successful connect */
539 /* Used within the multi interface. Try next IP address, return TRUE if no
540 more address exists or error */
541 static CURLcode trynextip(struct connectdata *conn,
545 CURLcode result = CURLE_COULDNT_CONNECT;
547 /* First clean up after the failed socket.
548 Don't close it yet to ensure that the next IP's socket gets a different
549 file descriptor, which can prevent bugs when the curl_multi_socket_action
550 interface is used with certain select() replacements such as kqueue. */
551 curl_socket_t fd_to_close = conn->tempsock[tempindex];
552 conn->tempsock[tempindex] = CURL_SOCKET_BAD;
554 if(sockindex == FIRSTSOCKET) {
555 Curl_addrinfo *ai = NULL;
556 int family = AF_UNSPEC;
558 if(conn->tempaddr[tempindex]) {
559 /* find next address in the same protocol family */
560 family = conn->tempaddr[tempindex]->ai_family;
561 ai = conn->tempaddr[tempindex]->ai_next;
563 else if(conn->tempaddr[0]) {
564 /* happy eyeballs - try the other protocol family */
565 int firstfamily = conn->tempaddr[0]->ai_family;
567 family = (firstfamily == AF_INET) ? AF_INET6 : AF_INET;
569 family = firstfamily;
571 ai = conn->tempaddr[0]->ai_next;
575 while(ai && ai->ai_family != family)
579 result = singleipconnect(conn, ai, &conn->tempsock[tempindex]);
580 if(result == CURLE_COULDNT_CONNECT) {
585 conn->tempaddr[tempindex] = ai;
591 if(fd_to_close != CURL_SOCKET_BAD)
592 Curl_closesocket(conn, fd_to_close);
597 /* Copies connection info into the session handle to make it available
598 when the session handle is no longer associated with a connection. */
599 void Curl_persistconninfo(struct connectdata *conn)
601 memcpy(conn->data->info.conn_primary_ip, conn->primary_ip, MAX_IPADR_LEN);
602 memcpy(conn->data->info.conn_local_ip, conn->local_ip, MAX_IPADR_LEN);
603 conn->data->info.conn_primary_port = conn->primary_port;
604 conn->data->info.conn_local_port = conn->local_port;
607 /* retrieves ip address and port from a sockaddr structure */
608 static bool getaddressinfo(struct sockaddr* sa, char* addr,
611 unsigned short us_port;
612 struct sockaddr_in* si = NULL;
614 struct sockaddr_in6* si6 = NULL;
616 #if defined(HAVE_SYS_UN_H) && defined(AF_UNIX)
617 struct sockaddr_un* su = NULL;
620 switch (sa->sa_family) {
622 si = (struct sockaddr_in*) sa;
623 if(Curl_inet_ntop(sa->sa_family, &si->sin_addr,
624 addr, MAX_IPADR_LEN)) {
625 us_port = ntohs(si->sin_port);
632 si6 = (struct sockaddr_in6*)sa;
633 if(Curl_inet_ntop(sa->sa_family, &si6->sin6_addr,
634 addr, MAX_IPADR_LEN)) {
635 us_port = ntohs(si6->sin6_port);
641 #if defined(HAVE_SYS_UN_H) && defined(AF_UNIX)
643 su = (struct sockaddr_un*)sa;
644 snprintf(addr, MAX_IPADR_LEN, "%s", su->sun_path);
658 /* retrieves the start/end point information of a socket of an established
660 void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
663 struct Curl_sockaddr_storage ssrem;
664 struct Curl_sockaddr_storage ssloc;
665 struct SessionHandle *data = conn->data;
667 if(conn->socktype == SOCK_DGRAM)
668 /* there's no connection! */
671 if(!conn->bits.reuse) {
674 len = sizeof(struct Curl_sockaddr_storage);
675 if(getpeername(sockfd, (struct sockaddr*) &ssrem, &len)) {
677 failf(data, "getpeername() failed with errno %d: %s",
678 error, Curl_strerror(conn, error));
682 len = sizeof(struct Curl_sockaddr_storage);
683 memset(&ssloc, 0, sizeof(ssloc));
684 if(getsockname(sockfd, (struct sockaddr*) &ssloc, &len)) {
686 failf(data, "getsockname() failed with errno %d: %s",
687 error, Curl_strerror(conn, error));
691 if(!getaddressinfo((struct sockaddr*)&ssrem,
692 conn->primary_ip, &conn->primary_port)) {
694 failf(data, "ssrem inet_ntop() failed with errno %d: %s",
695 error, Curl_strerror(conn, error));
698 memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN);
700 if(!getaddressinfo((struct sockaddr*)&ssloc,
701 conn->local_ip, &conn->local_port)) {
703 failf(data, "ssloc inet_ntop() failed with errno %d: %s",
704 error, Curl_strerror(conn, error));
710 /* persist connection info in session handle */
711 Curl_persistconninfo(conn);
715 * Curl_is_connected() checks if the socket has connected.
718 CURLcode Curl_is_connected(struct connectdata *conn,
722 struct SessionHandle *data = conn->data;
723 CURLcode result = CURLE_OK;
730 DEBUGASSERT(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET);
732 *connected = FALSE; /* a very negative world view is best */
734 if(conn->bits.tcpconnect[sockindex]) {
735 /* we are connected already! */
742 /* figure out how long time we have left to connect */
743 allow = Curl_timeleft(data, &now, TRUE);
746 /* time-out, bail out, go home */
747 failf(data, "Connection time-out");
748 return CURLE_OPERATION_TIMEDOUT;
752 if(conn->tempsock[i] == CURL_SOCKET_BAD)
756 /* Call this function once now, and ignore the results. We do this to
757 "clear" the error state on the socket so that we can later read it
758 reliably. This is reported necessary on the MPE/iX operating system. */
759 (void)verifyconnect(conn->tempsock[i], NULL);
762 /* check socket for connect */
763 rc = Curl_socket_ready(CURL_SOCKET_BAD, conn->tempsock[i], 0);
765 if(rc == 0) { /* no connection yet */
766 if(curlx_tvdiff(now, conn->connecttime) >= conn->timeoutms_per_addr) {
767 infof(data, "After %ldms connect time, move on!\n",
768 conn->timeoutms_per_addr);
772 /* should we try another protocol family? */
773 if(i == 0 && conn->tempaddr[1] == NULL &&
774 curlx_tvdiff(now, conn->connecttime) >= HAPPY_EYEBALLS_TIMEOUT) {
775 trynextip(conn, sockindex, 1);
778 else if(rc == CURL_CSELECT_OUT) {
779 if(verifyconnect(conn->tempsock[i], &error)) {
780 /* we are connected with TCP, awesome! */
783 /* use this socket from now on */
784 conn->sock[sockindex] = conn->tempsock[i];
785 conn->ip_addr = conn->tempaddr[i];
786 conn->tempsock[i] = CURL_SOCKET_BAD;
788 /* close the other socket, if open */
789 if(conn->tempsock[other] != CURL_SOCKET_BAD) {
790 Curl_closesocket(conn, conn->tempsock[other]);
791 conn->tempsock[other] = CURL_SOCKET_BAD;
794 /* see if we need to do any proxy magic first once we connected */
795 result = Curl_connected_proxy(conn, sockindex);
799 conn->bits.tcpconnect[sockindex] = TRUE;
802 if(sockindex == FIRSTSOCKET)
803 Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */
804 Curl_updateconninfo(conn, conn->sock[sockindex]);
805 Curl_verboseconnect(conn);
810 infof(data, "Connection failed\n");
812 else if(rc & CURL_CSELECT_ERR)
813 (void)verifyconnect(conn->tempsock[i], &error);
816 * The connection failed here, we should attempt to connect to the "next
817 * address" for the given host. But first remember the latest error.
820 data->state.os_errno = error;
821 SET_SOCKERRNO(error);
822 if(conn->tempaddr[i]) {
823 char ipaddress[MAX_IPADR_LEN];
824 Curl_printable_address(conn->tempaddr[i], ipaddress, MAX_IPADR_LEN);
825 infof(data, "connect to %s port %ld failed: %s\n",
826 ipaddress, conn->port, Curl_strerror(conn, error));
828 conn->timeoutms_per_addr = conn->tempaddr[i]->ai_next == NULL ?
831 result = trynextip(conn, sockindex, i);
837 /* no more addresses to try */
839 /* if the first address family runs out of addresses to try before
840 the happy eyeball timeout, go ahead and try the next family now */
841 if(conn->tempaddr[1] == NULL) {
842 result = trynextip(conn, sockindex, 1);
847 failf(data, "Failed to connect to %s port %ld: %s",
848 conn->bits.proxy?conn->proxy.name:conn->host.name,
849 conn->port, Curl_strerror(conn, error));
855 static void tcpnodelay(struct connectdata *conn,
856 curl_socket_t sockfd)
859 struct SessionHandle *data= conn->data;
860 curl_socklen_t onoff = (curl_socklen_t) data->set.tcp_nodelay;
861 int level = IPPROTO_TCP;
864 /* The use of getprotobyname() is disabled since it isn't thread-safe on
865 numerous systems. On these getprotobyname_r() should be used instead, but
866 that exists in at least one 4 arg version and one 5 arg version, and
867 since the proto number rarely changes anyway we now just use the hard
868 coded number. The "proper" fix would need a configure check for the
869 correct function much in the same style the gethostbyname_r versions are
871 struct protoent *pe = getprotobyname("tcp");
876 if(setsockopt(sockfd, level, TCP_NODELAY, (void *)&onoff,
878 infof(data, "Could not set TCP_NODELAY: %s\n",
879 Curl_strerror(conn, SOCKERRNO));
881 infof(data,"TCP_NODELAY set\n");
889 /* The preferred method on Mac OS X (10.2 and later) to prevent SIGPIPEs when
890 sending data to a dead peer (instead of relying on the 4th argument to send
891 being MSG_NOSIGNAL). Possibly also existing and in use on other BSD
893 static void nosigpipe(struct connectdata *conn,
894 curl_socket_t sockfd)
896 struct SessionHandle *data= conn->data;
898 if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff,
900 infof(data, "Could not set SO_NOSIGPIPE: %s\n",
901 Curl_strerror(conn, SOCKERRNO));
904 #define nosigpipe(x,y) Curl_nop_stmt
908 /* When you run a program that uses the Windows Sockets API, you may
909 experience slow performance when you copy data to a TCP server.
911 http://support.microsoft.com/kb/823764
913 Work-around: Make the Socket Send Buffer Size Larger Than the Program Send
916 The problem described in this knowledge-base is applied only to pre-Vista
917 Windows. Following function trying to detect OS version and skips
918 SO_SNDBUF adjustment for Windows Vista and above.
920 #define DETECT_OS_NONE 0
921 #define DETECT_OS_PREVISTA 1
922 #define DETECT_OS_VISTA_OR_LATER 2
924 void Curl_sndbufset(curl_socket_t sockfd)
926 int val = CURL_MAX_WRITE_SIZE + 32;
928 int curlen = sizeof(curval);
929 DWORD majorVersion = 6;
931 static int detectOsState = DETECT_OS_NONE;
933 if(detectOsState == DETECT_OS_NONE) {
934 #if !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_WIN2K) || \
935 (_WIN32_WINNT < _WIN32_WINNT_WIN2K)
938 memset(&osver, 0, sizeof(osver));
939 osver.dwOSVersionInfoSize = sizeof(osver);
941 detectOsState = DETECT_OS_PREVISTA;
942 if(GetVersionEx(&osver)) {
943 if(osver.dwMajorVersion >= majorVersion)
944 detectOsState = DETECT_OS_VISTA_OR_LATER;
947 ULONGLONG majorVersionMask;
948 OSVERSIONINFOEX osver;
950 memset(&osver, 0, sizeof(osver));
951 osver.dwOSVersionInfoSize = sizeof(osver);
952 osver.dwMajorVersion = majorVersion;
953 majorVersionMask = VerSetConditionMask(0, VER_MAJORVERSION,
956 if(VerifyVersionInfo(&osver, VER_MAJORVERSION, majorVersionMask))
957 detectOsState = DETECT_OS_VISTA_OR_LATER;
959 detectOsState = DETECT_OS_PREVISTA;
963 if(detectOsState == DETECT_OS_VISTA_OR_LATER)
966 if(getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (char *)&curval, &curlen) == 0)
970 setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (const char *)&val, sizeof(val));
977 * Note that even on connect fail it returns CURLE_OK, but with 'sock' set to
978 * CURL_SOCKET_BAD. Other errors will however return proper errors.
980 * singleipconnect() connects to the given IP only, and it may return without
983 static CURLcode singleipconnect(struct connectdata *conn,
984 const Curl_addrinfo *ai,
985 curl_socket_t *sockp)
987 struct Curl_sockaddr_ex addr;
990 bool isconnected = FALSE;
991 struct SessionHandle *data = conn->data;
992 curl_socket_t sockfd;
994 char ipaddress[MAX_IPADR_LEN];
998 *sockp = CURL_SOCKET_BAD;
1000 result = Curl_socket(conn, ai, &addr, &sockfd);
1002 /* Failed to create the socket, but still return OK since we signal the
1003 lack of socket as well. This allows the parent function to keep looping
1004 over alternative addresses/socket families etc. */
1007 /* store remote address and port used in this connection attempt */
1008 if(!getaddressinfo((struct sockaddr*)&addr.sa_addr,
1009 ipaddress, &port)) {
1010 /* malformed address or bug in inet_ntop, try next address */
1012 failf(data, "sa_addr inet_ntop() failed with errno %d: %s",
1013 error, Curl_strerror(conn, error));
1014 Curl_closesocket(conn, sockfd);
1017 infof(data, " Trying %s...\n", ipaddress);
1019 is_tcp = (addr.family == AF_INET || addr.family == AF_INET6) &&
1020 addr.socktype == SOCK_STREAM;
1021 if(is_tcp && data->set.tcp_nodelay)
1022 tcpnodelay(conn, sockfd);
1024 nosigpipe(conn, sockfd);
1026 Curl_sndbufset(sockfd);
1028 if(is_tcp && data->set.tcp_keepalive)
1029 tcpkeepalive(data, sockfd);
1031 if(data->set.fsockopt) {
1032 /* activate callback for setting socket options */
1033 error = data->set.fsockopt(data->set.sockopt_client,
1035 CURLSOCKTYPE_IPCXN);
1037 if(error == CURL_SOCKOPT_ALREADY_CONNECTED)
1040 Curl_closesocket(conn, sockfd); /* close the socket and bail out */
1041 return CURLE_ABORTED_BY_CALLBACK;
1045 /* possibly bind the local end to an IP, interface or port */
1046 if(addr.family == AF_INET || addr.family == AF_INET6) {
1047 result = bindlocal(conn, sockfd, addr.family,
1048 Curl_ipv6_scope((struct sockaddr*)&addr.sa_addr));
1050 Curl_closesocket(conn, sockfd); /* close socket and bail out */
1051 if(result == CURLE_UNSUPPORTED_PROTOCOL) {
1052 /* The address family is not supported on this interface.
1053 We can continue trying addresses */
1054 return CURLE_COULDNT_CONNECT;
1060 /* set socket non-blocking */
1061 (void)curlx_nonblock(sockfd, TRUE);
1063 conn->connecttime = Curl_tvnow();
1064 if(conn->num_addr > 1)
1065 Curl_expire_latest(data, conn->timeoutms_per_addr);
1067 /* Connect TCP sockets, bind UDP */
1068 if(!isconnected && (conn->socktype == SOCK_STREAM)) {
1069 rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
1079 conn->bits.ipv6 = (addr.family == AF_INET6)?TRUE:FALSE;
1087 #if (EAGAIN) != (EWOULDBLOCK)
1088 /* On some platforms EAGAIN and EWOULDBLOCK are the
1089 * same value, and on others they are different, hence
1099 /* unknown error, fallthrough and try another address! */
1100 infof(data, "Immediate connect fail for %s: %s\n",
1101 ipaddress, Curl_strerror(conn,error));
1102 data->state.os_errno = error;
1104 /* connect failed */
1105 Curl_closesocket(conn, sockfd);
1106 result = CURLE_COULDNT_CONNECT;
1117 * TCP connect to the given host with timeout, proxy or remote doesn't matter.
1118 * There might be more than one IP address to try out. Fill in the passed
1119 * pointer with the connected socket.
1122 CURLcode Curl_connecthost(struct connectdata *conn, /* context */
1123 const struct Curl_dns_entry *remotehost)
1125 struct SessionHandle *data = conn->data;
1126 struct timeval before = Curl_tvnow();
1127 CURLcode result = CURLE_COULDNT_CONNECT;
1129 long timeout_ms = Curl_timeleft(data, &before, TRUE);
1131 if(timeout_ms < 0) {
1132 /* a precaution, no need to continue if time already is up */
1133 failf(data, "Connection time-out");
1134 return CURLE_OPERATION_TIMEDOUT;
1137 conn->num_addr = Curl_num_addresses(remotehost->addr);
1138 conn->tempaddr[0] = remotehost->addr;
1139 conn->tempaddr[1] = NULL;
1140 conn->tempsock[0] = CURL_SOCKET_BAD;
1141 conn->tempsock[1] = CURL_SOCKET_BAD;
1142 Curl_expire(conn->data, HAPPY_EYEBALLS_TIMEOUT);
1144 /* Max time for the next connection attempt */
1145 conn->timeoutms_per_addr =
1146 conn->tempaddr[0]->ai_next == NULL ? timeout_ms : timeout_ms / 2;
1148 /* start connecting to first IP */
1149 while(conn->tempaddr[0]) {
1150 result = singleipconnect(conn, conn->tempaddr[0], &(conn->tempsock[0]));
1153 conn->tempaddr[0] = conn->tempaddr[0]->ai_next;
1156 if(conn->tempsock[0] == CURL_SOCKET_BAD)
1159 data->info.numconnects++; /* to track the number of connections made */
1165 struct connectdata *tofind;
1169 static int conn_is_conn(struct connectdata *conn, void *param)
1171 struct connfind *f = (struct connfind *)param;
1172 if(conn == f->tofind) {
1180 * Used to extract socket and connectdata struct for the most recent
1181 * transfer on the given SessionHandle.
1183 * The returned socket will be CURL_SOCKET_BAD in case of failure!
1185 curl_socket_t Curl_getconnectinfo(struct SessionHandle *data,
1186 struct connectdata **connp)
1188 curl_socket_t sockfd;
1192 /* this only works for an easy handle that has been used for
1193 curl_easy_perform()! */
1194 if(data->state.lastconnect && data->multi_easy) {
1195 struct connectdata *c = data->state.lastconnect;
1196 struct connfind find;
1197 find.tofind = data->state.lastconnect;
1200 Curl_conncache_foreach(data->multi_easy->conn_cache, &find, conn_is_conn);
1203 data->state.lastconnect = NULL;
1204 return CURL_SOCKET_BAD;
1208 /* only store this if the caller cares for it */
1210 sockfd = c->sock[FIRSTSOCKET];
1211 /* we have a socket connected, let's determine if the server shut down */
1212 /* determine if ssl */
1213 if(c->ssl[FIRSTSOCKET].use) {
1214 /* use the SSL context */
1215 if(!Curl_ssl_check_cxn(c))
1216 return CURL_SOCKET_BAD; /* FIN received */
1218 /* Minix 3.1 doesn't support any flags on recv; just assume socket is OK */
1221 /* use the socket */
1223 if(recv((RECV_TYPE_ARG1)c->sock[FIRSTSOCKET], (RECV_TYPE_ARG2)&buf,
1224 (RECV_TYPE_ARG3)1, (RECV_TYPE_ARG4)MSG_PEEK) == 0) {
1225 return CURL_SOCKET_BAD; /* FIN received */
1231 return CURL_SOCKET_BAD;
1239 * 'conn' can be NULL, beware!
1241 int Curl_closesocket(struct connectdata *conn,
1244 if(conn && conn->fclosesocket) {
1245 if((sock == conn->sock[SECONDARYSOCKET]) &&
1246 conn->sock_accepted[SECONDARYSOCKET])
1247 /* if this socket matches the second socket, and that was created with
1248 accept, then we MUST NOT call the callback but clear the accepted
1250 conn->sock_accepted[SECONDARYSOCKET] = FALSE;
1252 return conn->fclosesocket(conn->closesocket_client, sock);
1256 /* tell the multi-socket code about this */
1257 Curl_multi_closed(conn, sock);
1265 * Create a socket based on info from 'conn' and 'ai'.
1267 * 'addr' should be a pointer to the correct struct to get data back, or NULL.
1268 * 'sockfd' must be a pointer to a socket descriptor.
1270 * If the open socket callback is set, used that!
1273 CURLcode Curl_socket(struct connectdata *conn,
1274 const Curl_addrinfo *ai,
1275 struct Curl_sockaddr_ex *addr,
1276 curl_socket_t *sockfd)
1278 struct SessionHandle *data = conn->data;
1279 struct Curl_sockaddr_ex dummy;
1282 /* if the caller doesn't want info back, use a local temp copy */
1286 * The Curl_sockaddr_ex structure is basically libcurl's external API
1287 * curl_sockaddr structure with enough space available to directly hold
1288 * any protocol-specific address structures. The variable declared here
1289 * will be used to pass / receive data to/from the fopensocket callback
1290 * if this has been set, before that, it is initialized from parameters.
1293 addr->family = ai->ai_family;
1294 addr->socktype = conn->socktype;
1295 addr->protocol = conn->socktype==SOCK_DGRAM?IPPROTO_UDP:ai->ai_protocol;
1296 addr->addrlen = ai->ai_addrlen;
1298 if(addr->addrlen > sizeof(struct Curl_sockaddr_storage))
1299 addr->addrlen = sizeof(struct Curl_sockaddr_storage);
1300 memcpy(&addr->sa_addr, ai->ai_addr, addr->addrlen);
1302 if(data->set.fopensocket)
1304 * If the opensocket callback is set, all the destination address
1305 * information is passed to the callback. Depending on this information the
1306 * callback may opt to abort the connection, this is indicated returning
1307 * CURL_SOCKET_BAD; otherwise it will return a not-connected socket. When
1308 * the callback returns a valid socket the destination address information
1309 * might have been changed and this 'new' address will actually be used
1312 *sockfd = data->set.fopensocket(data->set.opensocket_client,
1314 (struct curl_sockaddr *)addr);
1316 /* opensocket callback not set, so simply create the socket now */
1317 *sockfd = socket(addr->family, addr->socktype, addr->protocol);
1319 if(*sockfd == CURL_SOCKET_BAD)
1320 /* no socket, no connection */
1321 return CURLE_COULDNT_CONNECT;
1323 #if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID)
1324 if(conn->scope_id && (addr->family == AF_INET6)) {
1325 struct sockaddr_in6 * const sa6 = (void *)&addr->sa_addr;
1326 sa6->sin6_scope_id = conn->scope_id;
1336 * Curl_conncontrol() is used to set the conn->bits.close bit on or off. It
1337 * MUST be called with the connclose() or connkeep() macros with a stated
1338 * reason. The reason is only shown in debug builds but helps to figure out
1339 * decision paths when connections are or aren't re-used as expected.
1341 void Curl_conncontrol(struct connectdata *conn, bool closeit,
1344 #if defined(CURL_DISABLE_VERBOSE_STRINGS)
1348 infof(conn->data, "Marked for [%s]: %s\n", closeit?"closure":"keep alive",
1351 conn->bits.close = closeit; /* the only place in the source code that should