connect.c
Go to the documentation of this file.
1 /***************************************************************************
2  * _ _ ____ _
3  * Project ___| | | | _ \| |
4  * / __| | | | |_) | |
5  * | (__| |_| | _ <| |___
6  * \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
9  *
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 https://curl.haxx.se/docs/copyright.html.
13  *
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.
17  *
18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19  * KIND, either express or implied.
20  *
21  ***************************************************************************/
22 
23 #include "curl_setup.h"
24 
25 #ifdef HAVE_NETINET_IN_H
26 #include <netinet/in.h> /* <netinet/tcp.h> may need it */
27 #endif
28 #ifdef HAVE_SYS_UN_H
29 #include <sys/un.h> /* for sockaddr_un */
30 #endif
31 #ifdef HAVE_NETINET_TCP_H
32 #include <netinet/tcp.h> /* for TCP_NODELAY */
33 #endif
34 #ifdef HAVE_SYS_IOCTL_H
35 #include <sys/ioctl.h>
36 #endif
37 #ifdef HAVE_NETDB_H
38 #include <netdb.h>
39 #endif
40 #ifdef HAVE_FCNTL_H
41 #include <fcntl.h>
42 #endif
43 #ifdef HAVE_ARPA_INET_H
44 #include <arpa/inet.h>
45 #endif
46 
47 #if (defined(HAVE_IOCTL_FIONBIO) && defined(NETWARE))
48 #include <sys/filio.h>
49 #endif
50 #ifdef NETWARE
51 #undef in_addr_t
52 #define in_addr_t unsigned long
53 #endif
54 #ifdef __VMS
55 #include <in.h>
56 #include <inet.h>
57 #endif
58 
59 #include "urldata.h"
60 #include "sendf.h"
61 #include "if2ip.h"
62 #include "strerror.h"
63 #include "connect.h"
64 #include "select.h"
65 #include "url.h" /* for Curl_safefree() */
66 #include "multiif.h"
67 #include "sockaddr.h" /* required for Curl_sockaddr_storage */
68 #include "inet_ntop.h"
69 #include "inet_pton.h"
70 #include "vtls/vtls.h" /* for Curl_ssl_check_cxn() */
71 #include "progress.h"
72 #include "warnless.h"
73 #include "conncache.h"
74 #include "multihandle.h"
75 #include "system_win32.h"
76 
77 /* The last 3 #include files should be in this order */
78 #include "curl_printf.h"
79 #include "curl_memory.h"
80 #include "memdebug.h"
81 
82 #ifdef __SYMBIAN32__
83 /* This isn't actually supported under Symbian OS */
84 #undef SO_NOSIGPIPE
85 #endif
86 
87 static bool verifyconnect(curl_socket_t sockfd, int *error);
88 
89 #if defined(__DragonFly__) || defined(HAVE_WINSOCK_H)
90 /* DragonFlyBSD and Windows use millisecond units */
91 #define KEEPALIVE_FACTOR(x) (x *= 1000)
92 #else
93 #define KEEPALIVE_FACTOR(x)
94 #endif
95 
96 #if defined(HAVE_WINSOCK2_H) && !defined(SIO_KEEPALIVE_VALS)
97 #define SIO_KEEPALIVE_VALS _WSAIOW(IOC_VENDOR,4)
98 
99 struct tcp_keepalive {
100  u_long onoff;
101  u_long keepalivetime;
102  u_long keepaliveinterval;
103 };
104 #endif
105 
106 static void
108  curl_socket_t sockfd)
109 {
110  int optval = data->set.tcp_keepalive?1:0;
111 
112  /* only set IDLE and INTVL if setting KEEPALIVE is successful */
113  if(setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE,
114  (void *)&optval, sizeof(optval)) < 0) {
115  infof(data, "Failed to set SO_KEEPALIVE on fd %d\n", sockfd);
116  }
117  else {
118 #if defined(SIO_KEEPALIVE_VALS)
119  struct tcp_keepalive vals;
120  DWORD dummy;
121  vals.onoff = 1;
122  optval = curlx_sltosi(data->set.tcp_keepidle);
123  KEEPALIVE_FACTOR(optval);
124  vals.keepalivetime = optval;
125  optval = curlx_sltosi(data->set.tcp_keepintvl);
126  KEEPALIVE_FACTOR(optval);
127  vals.keepaliveinterval = optval;
128  if(WSAIoctl(sockfd, SIO_KEEPALIVE_VALS, (LPVOID) &vals, sizeof(vals),
129  NULL, 0, &dummy, NULL, NULL) != 0) {
130  infof(data, "Failed to set SIO_KEEPALIVE_VALS on fd %d: %d\n",
131  (int)sockfd, WSAGetLastError());
132  }
133 #else
134 #ifdef TCP_KEEPIDLE
135  optval = curlx_sltosi(data->set.tcp_keepidle);
136  KEEPALIVE_FACTOR(optval);
137  if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE,
138  (void *)&optval, sizeof(optval)) < 0) {
139  infof(data, "Failed to set TCP_KEEPIDLE on fd %d\n", sockfd);
140  }
141 #endif
142 #ifdef TCP_KEEPINTVL
143  optval = curlx_sltosi(data->set.tcp_keepintvl);
144  KEEPALIVE_FACTOR(optval);
145  if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPINTVL,
146  (void *)&optval, sizeof(optval)) < 0) {
147  infof(data, "Failed to set TCP_KEEPINTVL on fd %d\n", sockfd);
148  }
149 #endif
150 #ifdef TCP_KEEPALIVE
151  /* Mac OS X style */
152  optval = curlx_sltosi(data->set.tcp_keepidle);
153  KEEPALIVE_FACTOR(optval);
154  if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPALIVE,
155  (void *)&optval, sizeof(optval)) < 0) {
156  infof(data, "Failed to set TCP_KEEPALIVE on fd %d\n", sockfd);
157  }
158 #endif
159 #endif
160  }
161 }
162 
163 static CURLcode
164 singleipconnect(struct connectdata *conn,
165  const Curl_addrinfo *ai, /* start connecting to this */
166  curl_socket_t *sock);
167 
168 /*
169  * Curl_timeleft() returns the amount of milliseconds left allowed for the
170  * transfer/connection. If the value is negative, the timeout time has already
171  * elapsed.
172  *
173  * The start time is stored in progress.t_startsingle - as set with
174  * Curl_pgrsTime(..., TIMER_STARTSINGLE);
175  *
176  * If 'nowp' is non-NULL, it points to the current time.
177  * 'duringconnect' is FALSE if not during a connect, as then of course the
178  * connect timeout is not taken into account!
179  *
180  * @unittest: 1303
181  */
182 time_t Curl_timeleft(struct Curl_easy *data,
183  struct curltime *nowp,
184  bool duringconnect)
185 {
186  int timeout_set = 0;
187  time_t timeout_ms = duringconnect?DEFAULT_CONNECT_TIMEOUT:0;
188  struct curltime now;
189 
190  /* if a timeout is set, use the most restrictive one */
191 
192  if(data->set.timeout > 0)
193  timeout_set |= 1;
194  if(duringconnect && (data->set.connecttimeout > 0))
195  timeout_set |= 2;
196 
197  switch(timeout_set) {
198  case 1:
199  timeout_ms = data->set.timeout;
200  break;
201  case 2:
202  timeout_ms = data->set.connecttimeout;
203  break;
204  case 3:
205  if(data->set.timeout < data->set.connecttimeout)
206  timeout_ms = data->set.timeout;
207  else
208  timeout_ms = data->set.connecttimeout;
209  break;
210  default:
211  /* use the default */
212  if(!duringconnect)
213  /* if we're not during connect, there's no default timeout so if we're
214  at zero we better just return zero and not make it a negative number
215  by the math below */
216  return 0;
217  break;
218  }
219 
220  if(!nowp) {
221  now = Curl_tvnow();
222  nowp = &now;
223  }
224 
225  /* subtract elapsed time */
226  if(duringconnect)
227  /* since this most recent connect started */
228  timeout_ms -= Curl_tvdiff(*nowp, data->progress.t_startsingle);
229  else
230  /* since the entire operation started */
231  timeout_ms -= Curl_tvdiff(*nowp, data->progress.t_startop);
232  if(!timeout_ms)
233  /* avoid returning 0 as that means no timeout! */
234  return -1;
235 
236  return timeout_ms;
237 }
238 
239 static CURLcode bindlocal(struct connectdata *conn,
240  curl_socket_t sockfd, int af, unsigned int scope)
241 {
242  struct Curl_easy *data = conn->data;
243 
244  struct Curl_sockaddr_storage sa;
245  struct sockaddr *sock = (struct sockaddr *)&sa; /* bind to this address */
246  curl_socklen_t sizeof_sa = 0; /* size of the data sock points to */
247  struct sockaddr_in *si4 = (struct sockaddr_in *)&sa;
248 #ifdef ENABLE_IPV6
249  struct sockaddr_in6 *si6 = (struct sockaddr_in6 *)&sa;
250 #endif
251 
252  struct Curl_dns_entry *h = NULL;
253  unsigned short port = data->set.localport; /* use this port number, 0 for
254  "random" */
255  /* how many port numbers to try to bind to, increasing one at a time */
256  int portnum = data->set.localportrange;
257  const char *dev = data->set.str[STRING_DEVICE];
258  int error;
259 
260  /*************************************************************
261  * Select device to bind socket to
262  *************************************************************/
263  if(!dev && !port)
264  /* no local kind of binding was requested */
265  return CURLE_OK;
266 
267  memset(&sa, 0, sizeof(struct Curl_sockaddr_storage));
268 
269  if(dev && (strlen(dev)<255) ) {
270  char myhost[256] = "";
271  int done = 0; /* -1 for error, 1 for address found */
272  bool is_interface = FALSE;
273  bool is_host = FALSE;
274  static const char *if_prefix = "if!";
275  static const char *host_prefix = "host!";
276 
277  if(strncmp(if_prefix, dev, strlen(if_prefix)) == 0) {
278  dev += strlen(if_prefix);
279  is_interface = TRUE;
280  }
281  else if(strncmp(host_prefix, dev, strlen(host_prefix)) == 0) {
282  dev += strlen(host_prefix);
283  is_host = TRUE;
284  }
285 
286  /* interface */
287  if(!is_host) {
288  switch(Curl_if2ip(af, scope, conn->scope_id, dev,
289  myhost, sizeof(myhost))) {
290  case IF2IP_NOT_FOUND:
291  if(is_interface) {
292  /* Do not fall back to treating it as a host name */
293  failf(data, "Couldn't bind to interface '%s'", dev);
294  return CURLE_INTERFACE_FAILED;
295  }
296  break;
298  /* Signal the caller to try another address family if available */
300  case IF2IP_FOUND:
301  is_interface = TRUE;
302  /*
303  * We now have the numerical IP address in the 'myhost' buffer
304  */
305  infof(data, "Local Interface %s is ip %s using address family %i\n",
306  dev, myhost, af);
307  done = 1;
308 
309 #ifdef SO_BINDTODEVICE
310  /* I am not sure any other OSs than Linux that provide this feature,
311  * and at the least I cannot test. --Ben
312  *
313  * This feature allows one to tightly bind the local socket to a
314  * particular interface. This will force even requests to other
315  * local interfaces to go out the external interface.
316  *
317  *
318  * Only bind to the interface when specified as interface, not just
319  * as a hostname or ip address.
320  */
321  if(setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE,
322  dev, (curl_socklen_t)strlen(dev) + 1) != 0) {
323  error = SOCKERRNO;
324  infof(data, "SO_BINDTODEVICE %s failed with errno %d: %s;"
325  " will do regular bind\n",
326  dev, error, Curl_strerror(conn, error));
327  /* This is typically "errno 1, error: Operation not permitted" if
328  you're not running as root or another suitable privileged
329  user */
330  }
331 #endif
332  break;
333  }
334  }
335  if(!is_interface) {
336  /*
337  * This was not an interface, resolve the name as a host name
338  * or IP number
339  *
340  * Temporarily force name resolution to use only the address type
341  * of the connection. The resolve functions should really be changed
342  * to take a type parameter instead.
343  */
344  long ipver = conn->ip_version;
345  int rc;
346 
347  if(af == AF_INET)
349 #ifdef ENABLE_IPV6
350  else if(af == AF_INET6)
352 #endif
353 
354  rc = Curl_resolv(conn, dev, 0, &h);
355  if(rc == CURLRESOLV_PENDING)
356  (void)Curl_resolver_wait_resolv(conn, &h);
357  conn->ip_version = ipver;
358 
359  if(h) {
360  /* convert the resolved address, sizeof myhost >= INET_ADDRSTRLEN */
361  Curl_printable_address(h->addr, myhost, sizeof(myhost));
362  infof(data, "Name '%s' family %i resolved to '%s' family %i\n",
363  dev, af, myhost, h->addr->ai_family);
364  Curl_resolv_unlock(data, h);
365  done = 1;
366  }
367  else {
368  /*
369  * provided dev was no interface (or interfaces are not supported
370  * e.g. solaris) no ip address and no domain we fail here
371  */
372  done = -1;
373  }
374  }
375 
376  if(done > 0) {
377 #ifdef ENABLE_IPV6
378  /* IPv6 address */
379  if(af == AF_INET6) {
380 #ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
381  char *scope_ptr = strchr(myhost, '%');
382  if(scope_ptr)
383  *(scope_ptr++) = 0;
384 #endif
385  if(Curl_inet_pton(AF_INET6, myhost, &si6->sin6_addr) > 0) {
386  si6->sin6_family = AF_INET6;
387  si6->sin6_port = htons(port);
388 #ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
389  if(scope_ptr)
390  /* The "myhost" string either comes from Curl_if2ip or from
391  Curl_printable_address. The latter returns only numeric scope
392  IDs and the former returns none at all. So the scope ID, if
393  present, is known to be numeric */
394  si6->sin6_scope_id = atoi(scope_ptr);
395 #endif
396  }
397  sizeof_sa = sizeof(struct sockaddr_in6);
398  }
399  else
400 #endif
401  /* IPv4 address */
402  if((af == AF_INET) &&
403  (Curl_inet_pton(AF_INET, myhost, &si4->sin_addr) > 0)) {
404  si4->sin_family = AF_INET;
405  si4->sin_port = htons(port);
406  sizeof_sa = sizeof(struct sockaddr_in);
407  }
408  }
409 
410  if(done < 1) {
411  failf(data, "Couldn't bind to '%s'", dev);
412  return CURLE_INTERFACE_FAILED;
413  }
414  }
415  else {
416  /* no device was given, prepare sa to match af's needs */
417 #ifdef ENABLE_IPV6
418  if(af == AF_INET6) {
419  si6->sin6_family = AF_INET6;
420  si6->sin6_port = htons(port);
421  sizeof_sa = sizeof(struct sockaddr_in6);
422  }
423  else
424 #endif
425  if(af == AF_INET) {
426  si4->sin_family = AF_INET;
427  si4->sin_port = htons(port);
428  sizeof_sa = sizeof(struct sockaddr_in);
429  }
430  }
431 
432  for(;;) {
433  if(bind(sockfd, sock, sizeof_sa) >= 0) {
434  /* we succeeded to bind */
435  struct Curl_sockaddr_storage add;
436  curl_socklen_t size = sizeof(add);
437  memset(&add, 0, sizeof(struct Curl_sockaddr_storage));
438  if(getsockname(sockfd, (struct sockaddr *) &add, &size) < 0) {
439  data->state.os_errno = error = SOCKERRNO;
440  failf(data, "getsockname() failed with errno %d: %s",
441  error, Curl_strerror(conn, error));
442  return CURLE_INTERFACE_FAILED;
443  }
444  infof(data, "Local port: %hu\n", port);
445  conn->bits.bound = TRUE;
446  return CURLE_OK;
447  }
448 
449  if(--portnum > 0) {
450  infof(data, "Bind to local port %hu failed, trying next\n", port);
451  port++; /* try next port */
452  /* We re-use/clobber the port variable here below */
453  if(sock->sa_family == AF_INET)
454  si4->sin_port = ntohs(port);
455 #ifdef ENABLE_IPV6
456  else
457  si6->sin6_port = ntohs(port);
458 #endif
459  }
460  else
461  break;
462  }
463 
464  data->state.os_errno = error = SOCKERRNO;
465  failf(data, "bind failed with errno %d: %s",
466  error, Curl_strerror(conn, error));
467 
468  return CURLE_INTERFACE_FAILED;
469 }
470 
471 /*
472  * verifyconnect() returns TRUE if the connect really has happened.
473  */
474 static bool verifyconnect(curl_socket_t sockfd, int *error)
475 {
476  bool rc = TRUE;
477 #ifdef SO_ERROR
478  int err = 0;
479  curl_socklen_t errSize = sizeof(err);
480 
481 #ifdef WIN32
482  /*
483  * In October 2003 we effectively nullified this function on Windows due to
484  * problems with it using all CPU in multi-threaded cases.
485  *
486  * In May 2004, we bring it back to offer more info back on connect failures.
487  * Gisle Vanem could reproduce the former problems with this function, but
488  * could avoid them by adding this SleepEx() call below:
489  *
490  * "I don't have Rational Quantify, but the hint from his post was
491  * ntdll::NtRemoveIoCompletion(). So I'd assume the SleepEx (or maybe
492  * just Sleep(0) would be enough?) would release whatever
493  * mutex/critical-section the ntdll call is waiting on.
494  *
495  * Someone got to verify this on Win-NT 4.0, 2000."
496  */
497 
498 #ifdef _WIN32_WCE
499  Sleep(0);
500 #else
501  SleepEx(0, FALSE);
502 #endif
503 
504 #endif
505 
506  if(0 != getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *)&err, &errSize))
507  err = SOCKERRNO;
508 #ifdef _WIN32_WCE
509  /* Old WinCE versions don't support SO_ERROR */
510  if(WSAENOPROTOOPT == err) {
511  SET_SOCKERRNO(0);
512  err = 0;
513  }
514 #endif
515 #ifdef __minix
516  /* Minix 3.1.x doesn't support getsockopt on UDP sockets */
517  if(EBADIOCTL == err) {
518  SET_SOCKERRNO(0);
519  err = 0;
520  }
521 #endif
522  if((0 == err) || (EISCONN == err))
523  /* we are connected, awesome! */
524  rc = TRUE;
525  else
526  /* This wasn't a successful connect */
527  rc = FALSE;
528  if(error)
529  *error = err;
530 #else
531  (void)sockfd;
532  if(error)
533  *error = SOCKERRNO;
534 #endif
535  return rc;
536 }
537 
538 /* Used within the multi interface. Try next IP address, return TRUE if no
539  more address exists or error */
540 static CURLcode trynextip(struct connectdata *conn,
541  int sockindex,
542  int tempindex)
543 {
544  const int other = tempindex ^ 1;
546 
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;
553 
554  if(sockindex == FIRSTSOCKET) {
555  Curl_addrinfo *ai = NULL;
556  int family = AF_UNSPEC;
557 
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;
562  }
563 #ifdef ENABLE_IPV6
564  else if(conn->tempaddr[0]) {
565  /* happy eyeballs - try the other protocol family */
566  int firstfamily = conn->tempaddr[0]->ai_family;
567  family = (firstfamily == AF_INET) ? AF_INET6 : AF_INET;
568  ai = conn->tempaddr[0]->ai_next;
569  }
570 #endif
571 
572  while(ai) {
573  if(conn->tempaddr[other]) {
574  /* we can safely skip addresses of the other protocol family */
575  while(ai && ai->ai_family != family)
576  ai = ai->ai_next;
577  }
578 
579  if(ai) {
580  result = singleipconnect(conn, ai, &conn->tempsock[tempindex]);
581  if(result == CURLE_COULDNT_CONNECT) {
582  ai = ai->ai_next;
583  continue;
584  }
585 
586  conn->tempaddr[tempindex] = ai;
587  }
588  break;
589  }
590  }
591 
592  if(fd_to_close != CURL_SOCKET_BAD)
593  Curl_closesocket(conn, fd_to_close);
594 
595  return result;
596 }
597 
598 /* Copies connection info into the session handle to make it available
599  when the session handle is no longer associated with a connection. */
601 {
604  conn->data->info.conn_scheme = conn->handler->scheme;
605  conn->data->info.conn_protocol = conn->handler->protocol;
606  conn->data->info.conn_primary_port = conn->primary_port;
607  conn->data->info.conn_local_port = conn->local_port;
608 }
609 
610 /* retrieves ip address and port from a sockaddr structure.
611  note it calls Curl_inet_ntop which sets errno on fail, not SOCKERRNO. */
612 static bool getaddressinfo(struct sockaddr *sa, char *addr,
613  long *port)
614 {
615  unsigned short us_port;
616  struct sockaddr_in *si = NULL;
617 #ifdef ENABLE_IPV6
618  struct sockaddr_in6 *si6 = NULL;
619 #endif
620 #if defined(HAVE_SYS_UN_H) && defined(AF_UNIX)
621  struct sockaddr_un *su = NULL;
622 #endif
623 
624  switch(sa->sa_family) {
625  case AF_INET:
626  si = (struct sockaddr_in *)(void *) sa;
627  if(Curl_inet_ntop(sa->sa_family, &si->sin_addr,
628  addr, MAX_IPADR_LEN)) {
629  us_port = ntohs(si->sin_port);
630  *port = us_port;
631  return TRUE;
632  }
633  break;
634 #ifdef ENABLE_IPV6
635  case AF_INET6:
636  si6 = (struct sockaddr_in6 *)(void *) sa;
637  if(Curl_inet_ntop(sa->sa_family, &si6->sin6_addr,
638  addr, MAX_IPADR_LEN)) {
639  us_port = ntohs(si6->sin6_port);
640  *port = us_port;
641  return TRUE;
642  }
643  break;
644 #endif
645 #if defined(HAVE_SYS_UN_H) && defined(AF_UNIX)
646  case AF_UNIX:
647  su = (struct sockaddr_un*)sa;
648  snprintf(addr, MAX_IPADR_LEN, "%s", su->sun_path);
649  *port = 0;
650  return TRUE;
651 #endif
652  default:
653  break;
654  }
655 
656  addr[0] = '\0';
657  *port = 0;
658  errno = EAFNOSUPPORT;
659  return FALSE;
660 }
661 
662 /* retrieves the start/end point information of a socket of an established
663  connection */
665 {
667  struct Curl_sockaddr_storage ssrem;
668  struct Curl_sockaddr_storage ssloc;
669  struct Curl_easy *data = conn->data;
670 
671  if(conn->socktype == SOCK_DGRAM)
672  /* there's no connection! */
673  return;
674 
675  if(!conn->bits.reuse && !conn->bits.tcp_fastopen) {
676  len = sizeof(struct Curl_sockaddr_storage);
677  if(getpeername(sockfd, (struct sockaddr*) &ssrem, &len)) {
678  int error = SOCKERRNO;
679  failf(data, "getpeername() failed with errno %d: %s",
680  error, Curl_strerror(conn, error));
681  return;
682  }
683 
684  len = sizeof(struct Curl_sockaddr_storage);
685  memset(&ssloc, 0, sizeof(ssloc));
686  if(getsockname(sockfd, (struct sockaddr*) &ssloc, &len)) {
687  int error = SOCKERRNO;
688  failf(data, "getsockname() failed with errno %d: %s",
689  error, Curl_strerror(conn, error));
690  return;
691  }
692 
693  if(!getaddressinfo((struct sockaddr*)&ssrem,
694  conn->primary_ip, &conn->primary_port)) {
695  failf(data, "ssrem inet_ntop() failed with errno %d: %s",
696  errno, Curl_strerror(conn, errno));
697  return;
698  }
700 
701  if(!getaddressinfo((struct sockaddr*)&ssloc,
702  conn->local_ip, &conn->local_port)) {
703  failf(data, "ssloc inet_ntop() failed with errno %d: %s",
704  errno, Curl_strerror(conn, errno));
705  return;
706  }
707 
708  }
709 
710  /* persist connection info in session handle */
711  Curl_persistconninfo(conn);
712 }
713 
714 /*
715  * Curl_is_connected() checks if the socket has connected.
716  */
717 
719  int sockindex,
720  bool *connected)
721 {
722  struct Curl_easy *data = conn->data;
724  time_t allow;
725  int error = 0;
726  struct curltime now;
727  int rc;
728  int i;
729 
730  DEBUGASSERT(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET);
731 
732  *connected = FALSE; /* a very negative world view is best */
733 
734  if(conn->bits.tcpconnect[sockindex]) {
735  /* we are connected already! */
736  *connected = TRUE;
737  return CURLE_OK;
738  }
739 
740  now = Curl_tvnow();
741 
742  /* figure out how long time we have left to connect */
743  allow = Curl_timeleft(data, &now, TRUE);
744 
745  if(allow < 0) {
746  /* time-out, bail out, go home */
747  failf(data, "Connection time-out");
749  }
750 
751  for(i = 0; i<2; i++) {
752  const int other = i ^ 1;
753  if(conn->tempsock[i] == CURL_SOCKET_BAD)
754  continue;
755 
756 #ifdef mpeix
757  /* Call this function once now, and ignore the results. We do this to
758  "clear" the error state on the socket so that we can later read it
759  reliably. This is reported necessary on the MPE/iX operating system. */
760  (void)verifyconnect(conn->tempsock[i], NULL);
761 #endif
762 
763  /* check socket for connect */
764  rc = SOCKET_WRITABLE(conn->tempsock[i], 0);
765 
766  if(rc == 0) { /* no connection yet */
767  error = 0;
768  if(curlx_tvdiff(now, conn->connecttime) >= conn->timeoutms_per_addr) {
769  infof(data, "After %ldms connect time, move on!\n",
770  conn->timeoutms_per_addr);
771  error = ETIMEDOUT;
772  }
773 
774  /* should we try another protocol family? */
775  if(i == 0 && conn->tempaddr[1] == NULL &&
777  trynextip(conn, sockindex, 1);
778  }
779  }
780  else if(rc == CURL_CSELECT_OUT || conn->bits.tcp_fastopen) {
781  if(verifyconnect(conn->tempsock[i], &error)) {
782  /* we are connected with TCP, awesome! */
783 
784  /* use this socket from now on */
785  conn->sock[sockindex] = conn->tempsock[i];
786  conn->ip_addr = conn->tempaddr[i];
787  conn->tempsock[i] = CURL_SOCKET_BAD;
788 
789  /* close the other socket, if open */
790  if(conn->tempsock[other] != CURL_SOCKET_BAD) {
791  Curl_closesocket(conn, conn->tempsock[other]);
792  conn->tempsock[other] = CURL_SOCKET_BAD;
793  }
794 
795  /* see if we need to do any proxy magic first once we connected */
796  result = Curl_connected_proxy(conn, sockindex);
797  if(result)
798  return result;
799 
800  conn->bits.tcpconnect[sockindex] = TRUE;
801 
802  *connected = TRUE;
803  if(sockindex == FIRSTSOCKET)
804  Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */
805  Curl_updateconninfo(conn, conn->sock[sockindex]);
806  Curl_verboseconnect(conn);
807 
808  return CURLE_OK;
809  }
810  infof(data, "Connection failed\n");
811  }
812  else if(rc & CURL_CSELECT_ERR)
813  (void)verifyconnect(conn->tempsock[i], &error);
814 
815  /*
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.
818  */
819  if(error) {
820  data->state.os_errno = error;
821  SET_SOCKERRNO(error);
822  if(conn->tempaddr[i]) {
823  CURLcode status;
824  char ipaddress[MAX_IPADR_LEN];
825  Curl_printable_address(conn->tempaddr[i], ipaddress, MAX_IPADR_LEN);
826  infof(data, "connect to %s port %ld failed: %s\n",
827  ipaddress, conn->port, Curl_strerror(conn, error));
828 
829  conn->timeoutms_per_addr = conn->tempaddr[i]->ai_next == NULL ?
830  allow : allow / 2;
831 
832  status = trynextip(conn, sockindex, i);
833  if(status != CURLE_COULDNT_CONNECT
834  || conn->tempsock[other] == CURL_SOCKET_BAD)
835  /* the last attempt failed and no other sockets remain open */
836  result = status;
837  }
838  }
839  }
840 
841  if(result) {
842  /* no more addresses to try */
843 
844  const char *hostname;
845 
846  /* if the first address family runs out of addresses to try before
847  the happy eyeball timeout, go ahead and try the next family now */
848  if(conn->tempaddr[1] == NULL) {
849  result = trynextip(conn, sockindex, 1);
850  if(!result)
851  return result;
852  }
853 
854  if(conn->bits.socksproxy)
855  hostname = conn->socks_proxy.host.name;
856  else if(conn->bits.httpproxy)
857  hostname = conn->http_proxy.host.name;
858  else if(conn->bits.conn_to_host)
859  hostname = conn->conn_to_host.name;
860  else
861  hostname = conn->host.name;
862 
863  failf(data, "Failed to connect to %s port %ld: %s",
864  hostname, conn->port, Curl_strerror(conn, error));
865  }
866 
867  return result;
868 }
869 
870 void Curl_tcpnodelay(struct connectdata *conn, curl_socket_t sockfd)
871 {
872 #if defined(TCP_NODELAY)
873 #if !defined(CURL_DISABLE_VERBOSE_STRINGS)
874  struct Curl_easy *data = conn->data;
875 #endif
876  curl_socklen_t onoff = (curl_socklen_t) 1;
877  int level = IPPROTO_TCP;
878 
879 #if defined(CURL_DISABLE_VERBOSE_STRINGS)
880  (void) conn;
881 #endif
882 
883  if(setsockopt(sockfd, level, TCP_NODELAY, (void *)&onoff,
884  sizeof(onoff)) < 0)
885  infof(data, "Could not set TCP_NODELAY: %s\n",
886  Curl_strerror(conn, SOCKERRNO));
887  else
888  infof(data, "TCP_NODELAY set\n");
889 #else
890  (void)conn;
891  (void)sockfd;
892 #endif
893 }
894 
895 #ifdef SO_NOSIGPIPE
896 /* The preferred method on Mac OS X (10.2 and later) to prevent SIGPIPEs when
897  sending data to a dead peer (instead of relying on the 4th argument to send
898  being MSG_NOSIGNAL). Possibly also existing and in use on other BSD
899  systems? */
900 static void nosigpipe(struct connectdata *conn,
901  curl_socket_t sockfd)
902 {
903  struct Curl_easy *data = conn->data;
904  int onoff = 1;
905  if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff,
906  sizeof(onoff)) < 0)
907  infof(data, "Could not set SO_NOSIGPIPE: %s\n",
908  Curl_strerror(conn, SOCKERRNO));
909 }
910 #else
911 #define nosigpipe(x,y) Curl_nop_stmt
912 #endif
913 
914 #ifdef USE_WINSOCK
915 /* When you run a program that uses the Windows Sockets API, you may
916  experience slow performance when you copy data to a TCP server.
917 
918  https://support.microsoft.com/kb/823764
919 
920  Work-around: Make the Socket Send Buffer Size Larger Than the Program Send
921  Buffer Size
922 
923  The problem described in this knowledge-base is applied only to pre-Vista
924  Windows. Following function trying to detect OS version and skips
925  SO_SNDBUF adjustment for Windows Vista and above.
926 */
927 #define DETECT_OS_NONE 0
928 #define DETECT_OS_PREVISTA 1
929 #define DETECT_OS_VISTA_OR_LATER 2
930 
931 void Curl_sndbufset(curl_socket_t sockfd)
932 {
933  int val = CURL_MAX_WRITE_SIZE + 32;
934  int curval = 0;
935  int curlen = sizeof(curval);
936 
937  static int detectOsState = DETECT_OS_NONE;
938 
939  if(detectOsState == DETECT_OS_NONE) {
940  if(Curl_verify_windows_version(6, 0, PLATFORM_WINNT,
941  VERSION_GREATER_THAN_EQUAL))
942  detectOsState = DETECT_OS_VISTA_OR_LATER;
943  else
944  detectOsState = DETECT_OS_PREVISTA;
945  }
946 
947  if(detectOsState == DETECT_OS_VISTA_OR_LATER)
948  return;
949 
950  if(getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (char *)&curval, &curlen) == 0)
951  if(curval > val)
952  return;
953 
954  setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (const char *)&val, sizeof(val));
955 }
956 #endif
957 
958 /*
959  * singleipconnect()
960  *
961  * Note that even on connect fail it returns CURLE_OK, but with 'sock' set to
962  * CURL_SOCKET_BAD. Other errors will however return proper errors.
963  *
964  * singleipconnect() connects to the given IP only, and it may return without
965  * having connected.
966  */
968  const Curl_addrinfo *ai,
969  curl_socket_t *sockp)
970 {
971  struct Curl_sockaddr_ex addr;
972  int rc = -1;
973  int error = 0;
974  bool isconnected = FALSE;
975  struct Curl_easy *data = conn->data;
976  curl_socket_t sockfd;
978  char ipaddress[MAX_IPADR_LEN];
979  long port;
980  bool is_tcp;
981 
982  *sockp = CURL_SOCKET_BAD;
983 
984  result = Curl_socket(conn, ai, &addr, &sockfd);
985  if(result)
986  /* Failed to create the socket, but still return OK since we signal the
987  lack of socket as well. This allows the parent function to keep looping
988  over alternative addresses/socket families etc. */
989  return CURLE_OK;
990 
991  /* store remote address and port used in this connection attempt */
992  if(!getaddressinfo((struct sockaddr*)&addr.sa_addr,
993  ipaddress, &port)) {
994  /* malformed address or bug in inet_ntop, try next address */
995  failf(data, "sa_addr inet_ntop() failed with errno %d: %s",
996  errno, Curl_strerror(conn, errno));
997  Curl_closesocket(conn, sockfd);
998  return CURLE_OK;
999  }
1000  infof(data, " Trying %s...\n", ipaddress);
1001 
1002 #ifdef ENABLE_IPV6
1003  is_tcp = (addr.family == AF_INET || addr.family == AF_INET6) &&
1004  addr.socktype == SOCK_STREAM;
1005 #else
1006  is_tcp = (addr.family == AF_INET) && addr.socktype == SOCK_STREAM;
1007 #endif
1008  if(is_tcp && data->set.tcp_nodelay)
1009  Curl_tcpnodelay(conn, sockfd);
1010 
1011  nosigpipe(conn, sockfd);
1012 
1013  Curl_sndbufset(sockfd);
1014 
1015  if(is_tcp && data->set.tcp_keepalive)
1016  tcpkeepalive(data, sockfd);
1017 
1018  if(data->set.fsockopt) {
1019  /* activate callback for setting socket options */
1020  error = data->set.fsockopt(data->set.sockopt_client,
1021  sockfd,
1023 
1024  if(error == CURL_SOCKOPT_ALREADY_CONNECTED)
1025  isconnected = TRUE;
1026  else if(error) {
1027  Curl_closesocket(conn, sockfd); /* close the socket and bail out */
1029  }
1030  }
1031 
1032  /* possibly bind the local end to an IP, interface or port */
1033  if(addr.family == AF_INET
1034 #ifdef ENABLE_IPV6
1035  || addr.family == AF_INET6
1036 #endif
1037  ) {
1038  result = bindlocal(conn, sockfd, addr.family,
1039  Curl_ipv6_scope((struct sockaddr*)&addr.sa_addr));
1040  if(result) {
1041  Curl_closesocket(conn, sockfd); /* close socket and bail out */
1042  if(result == CURLE_UNSUPPORTED_PROTOCOL) {
1043  /* The address family is not supported on this interface.
1044  We can continue trying addresses */
1045  return CURLE_COULDNT_CONNECT;
1046  }
1047  return result;
1048  }
1049  }
1050 
1051  /* set socket non-blocking */
1052  (void)curlx_nonblock(sockfd, TRUE);
1053 
1054  conn->connecttime = Curl_tvnow();
1055  if(conn->num_addr > 1)
1057 
1058  /* Connect TCP sockets, bind UDP */
1059  if(!isconnected && (conn->socktype == SOCK_STREAM)) {
1060  if(conn->bits.tcp_fastopen) {
1061 #if defined(CONNECT_DATA_IDEMPOTENT) /* OS X */
1062 #ifdef HAVE_BUILTIN_AVAILABLE
1063  if(__builtin_available(macOS 10.11, iOS 9.0, tvOS 9.0, watchOS 2.0, *)) {
1064 #endif /* HAVE_BUILTIN_AVAILABLE */
1065  sa_endpoints_t endpoints;
1066  endpoints.sae_srcif = 0;
1067  endpoints.sae_srcaddr = NULL;
1068  endpoints.sae_srcaddrlen = 0;
1069  endpoints.sae_dstaddr = &addr.sa_addr;
1070  endpoints.sae_dstaddrlen = addr.addrlen;
1071 
1072  rc = connectx(sockfd, &endpoints, SAE_ASSOCID_ANY,
1073  CONNECT_RESUME_ON_READ_WRITE | CONNECT_DATA_IDEMPOTENT,
1074  NULL, 0, NULL, NULL);
1075 #ifdef HAVE_BUILTIN_AVAILABLE
1076  }
1077  else {
1078  rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
1079  }
1080 #endif /* HAVE_BUILTIN_AVAILABLE */
1081 #elif defined(MSG_FASTOPEN) /* Linux */
1082  if(conn->given->flags & PROTOPT_SSL)
1083  rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
1084  else
1085  rc = 0; /* Do nothing */
1086 #endif
1087  }
1088  else {
1089  rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
1090  }
1091 
1092  if(-1 == rc)
1093  error = SOCKERRNO;
1094  }
1095  else {
1096  *sockp = sockfd;
1097  return CURLE_OK;
1098  }
1099 
1100 #ifdef ENABLE_IPV6
1101  conn->bits.ipv6 = (addr.family == AF_INET6)?TRUE:FALSE;
1102 #endif
1103 
1104  if(-1 == rc) {
1105  switch(error) {
1106  case EINPROGRESS:
1107  case EWOULDBLOCK:
1108 #if defined(EAGAIN)
1109 #if (EAGAIN) != (EWOULDBLOCK)
1110  /* On some platforms EAGAIN and EWOULDBLOCK are the
1111  * same value, and on others they are different, hence
1112  * the odd #if
1113  */
1114  case EAGAIN:
1115 #endif
1116 #endif
1117  result = CURLE_OK;
1118  break;
1119 
1120  default:
1121  /* unknown error, fallthrough and try another address! */
1122  infof(data, "Immediate connect fail for %s: %s\n",
1123  ipaddress, Curl_strerror(conn, error));
1124  data->state.os_errno = error;
1125 
1126  /* connect failed */
1127  Curl_closesocket(conn, sockfd);
1128  result = CURLE_COULDNT_CONNECT;
1129  }
1130  }
1131 
1132  if(!result)
1133  *sockp = sockfd;
1134 
1135  return result;
1136 }
1137 
1138 /*
1139  * TCP connect to the given host with timeout, proxy or remote doesn't matter.
1140  * There might be more than one IP address to try out. Fill in the passed
1141  * pointer with the connected socket.
1142  */
1143 
1144 CURLcode Curl_connecthost(struct connectdata *conn, /* context */
1145  const struct Curl_dns_entry *remotehost)
1146 {
1147  struct Curl_easy *data = conn->data;
1148  struct curltime before = Curl_tvnow();
1150 
1151  time_t timeout_ms = Curl_timeleft(data, &before, TRUE);
1152 
1153  if(timeout_ms < 0) {
1154  /* a precaution, no need to continue if time already is up */
1155  failf(data, "Connection time-out");
1156  return CURLE_OPERATION_TIMEDOUT;
1157  }
1158 
1159  conn->num_addr = Curl_num_addresses(remotehost->addr);
1160  conn->tempaddr[0] = remotehost->addr;
1161  conn->tempaddr[1] = NULL;
1162  conn->tempsock[0] = CURL_SOCKET_BAD;
1163  conn->tempsock[1] = CURL_SOCKET_BAD;
1164 
1165  /* Max time for the next connection attempt */
1166  conn->timeoutms_per_addr =
1167  conn->tempaddr[0]->ai_next == NULL ? timeout_ms : timeout_ms / 2;
1168 
1169  /* start connecting to first IP */
1170  while(conn->tempaddr[0]) {
1171  result = singleipconnect(conn, conn->tempaddr[0], &(conn->tempsock[0]));
1172  if(!result)
1173  break;
1174  conn->tempaddr[0] = conn->tempaddr[0]->ai_next;
1175  }
1176 
1177  if(conn->tempsock[0] == CURL_SOCKET_BAD) {
1178  if(!result)
1179  result = CURLE_COULDNT_CONNECT;
1180  return result;
1181  }
1182 
1183  data->info.numconnects++; /* to track the number of connections made */
1185 
1186  return CURLE_OK;
1187 }
1188 
1189 struct connfind {
1191  bool found;
1192 };
1193 
1194 static int conn_is_conn(struct connectdata *conn, void *param)
1195 {
1196  struct connfind *f = (struct connfind *)param;
1197  if(conn == f->tofind) {
1198  f->found = TRUE;
1199  return 1;
1200  }
1201  return 0;
1202 }
1203 
1204 /*
1205  * Used to extract socket and connectdata struct for the most recent
1206  * transfer on the given Curl_easy.
1207  *
1208  * The returned socket will be CURL_SOCKET_BAD in case of failure!
1209  */
1211  struct connectdata **connp)
1212 {
1213  curl_socket_t sockfd;
1214 
1215  DEBUGASSERT(data);
1216 
1217  /* this works for an easy handle:
1218  * - that has been used for curl_easy_perform()
1219  * - that is associated with a multi handle, and whose connection
1220  * was detached with CURLOPT_CONNECT_ONLY
1221  */
1222  if(data->state.lastconnect && (data->multi_easy || data->multi)) {
1223  struct connectdata *c = data->state.lastconnect;
1224  struct connfind find;
1225  find.tofind = data->state.lastconnect;
1226  find.found = FALSE;
1227 
1229  &data->multi_easy->conn_cache:
1230  &data->multi->conn_cache, &find, conn_is_conn);
1231 
1232  if(!find.found) {
1233  data->state.lastconnect = NULL;
1234  return CURL_SOCKET_BAD;
1235  }
1236 
1237  if(connp)
1238  /* only store this if the caller cares for it */
1239  *connp = c;
1240  sockfd = c->sock[FIRSTSOCKET];
1241  }
1242  else
1243  return CURL_SOCKET_BAD;
1244 
1245  return sockfd;
1246 }
1247 
1248 /*
1249  * Check if a connection seems to be alive.
1250  */
1251 bool Curl_connalive(struct connectdata *conn)
1252 {
1253  /* First determine if ssl */
1254  if(conn->ssl[FIRSTSOCKET].use) {
1255  /* use the SSL context */
1256  if(!Curl_ssl_check_cxn(conn))
1257  return false; /* FIN received */
1258  }
1259 /* Minix 3.1 doesn't support any flags on recv; just assume socket is OK */
1260 #ifdef MSG_PEEK
1261  else if(conn->sock[FIRSTSOCKET] == CURL_SOCKET_BAD)
1262  return false;
1263  else {
1264  /* use the socket */
1265  char buf;
1266  if(recv((RECV_TYPE_ARG1)conn->sock[FIRSTSOCKET], (RECV_TYPE_ARG2)&buf,
1267  (RECV_TYPE_ARG3)1, (RECV_TYPE_ARG4)MSG_PEEK) == 0) {
1268  return false; /* FIN received */
1269  }
1270  }
1271 #endif
1272  return true;
1273 }
1274 
1275 /*
1276  * Close a socket.
1277  *
1278  * 'conn' can be NULL, beware!
1279  */
1281  curl_socket_t sock)
1282 {
1283  if(conn && conn->fclosesocket) {
1284  if((sock == conn->sock[SECONDARYSOCKET]) &&
1286  /* if this socket matches the second socket, and that was created with
1287  accept, then we MUST NOT call the callback but clear the accepted
1288  status */
1290  else {
1291  Curl_multi_closed(conn, sock);
1292  return conn->fclosesocket(conn->closesocket_client, sock);
1293  }
1294  }
1295 
1296  if(conn)
1297  /* tell the multi-socket code about this */
1298  Curl_multi_closed(conn, sock);
1299 
1300  sclose(sock);
1301 
1302  return 0;
1303 }
1304 
1305 /*
1306  * Create a socket based on info from 'conn' and 'ai'.
1307  *
1308  * 'addr' should be a pointer to the correct struct to get data back, or NULL.
1309  * 'sockfd' must be a pointer to a socket descriptor.
1310  *
1311  * If the open socket callback is set, used that!
1312  *
1313  */
1315  const Curl_addrinfo *ai,
1316  struct Curl_sockaddr_ex *addr,
1317  curl_socket_t *sockfd)
1318 {
1319  struct Curl_easy *data = conn->data;
1320  struct Curl_sockaddr_ex dummy;
1321 
1322  if(!addr)
1323  /* if the caller doesn't want info back, use a local temp copy */
1324  addr = &dummy;
1325 
1326  /*
1327  * The Curl_sockaddr_ex structure is basically libcurl's external API
1328  * curl_sockaddr structure with enough space available to directly hold
1329  * any protocol-specific address structures. The variable declared here
1330  * will be used to pass / receive data to/from the fopensocket callback
1331  * if this has been set, before that, it is initialized from parameters.
1332  */
1333 
1334  addr->family = ai->ai_family;
1335  addr->socktype = conn->socktype;
1336  addr->protocol = conn->socktype == SOCK_DGRAM?IPPROTO_UDP:ai->ai_protocol;
1337  addr->addrlen = ai->ai_addrlen;
1338 
1339  if(addr->addrlen > sizeof(struct Curl_sockaddr_storage))
1340  addr->addrlen = sizeof(struct Curl_sockaddr_storage);
1341  memcpy(&addr->sa_addr, ai->ai_addr, addr->addrlen);
1342 
1343  if(data->set.fopensocket)
1344  /*
1345  * If the opensocket callback is set, all the destination address
1346  * information is passed to the callback. Depending on this information the
1347  * callback may opt to abort the connection, this is indicated returning
1348  * CURL_SOCKET_BAD; otherwise it will return a not-connected socket. When
1349  * the callback returns a valid socket the destination address information
1350  * might have been changed and this 'new' address will actually be used
1351  * here to connect.
1352  */
1353  *sockfd = data->set.fopensocket(data->set.opensocket_client,
1355  (struct curl_sockaddr *)addr);
1356  else
1357  /* opensocket callback not set, so simply create the socket now */
1358  *sockfd = socket(addr->family, addr->socktype, addr->protocol);
1359 
1360  if(*sockfd == CURL_SOCKET_BAD)
1361  /* no socket, no connection */
1362  return CURLE_COULDNT_CONNECT;
1363 
1364 #if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID)
1365  if(conn->scope_id && (addr->family == AF_INET6)) {
1366  struct sockaddr_in6 * const sa6 = (void *)&addr->sa_addr;
1367  sa6->sin6_scope_id = conn->scope_id;
1368  }
1369 #endif
1370 
1371  return CURLE_OK;
1372 
1373 }
1374 
1375 /*
1376  * Curl_conncontrol() marks streams or connection for closure.
1377  */
1378 void Curl_conncontrol(struct connectdata *conn,
1379  int ctrl /* see defines in header */
1380 #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
1381  , const char *reason
1382 #endif
1383  )
1384 {
1385  /* close if a connection, or a stream that isn't multiplexed */
1386  bool closeit = (ctrl == CONNCTRL_CONNECTION) ||
1387  ((ctrl == CONNCTRL_STREAM) && !(conn->handler->flags & PROTOPT_STREAM));
1388  if((ctrl == CONNCTRL_STREAM) &&
1389  (conn->handler->flags & PROTOPT_STREAM))
1390  DEBUGF(infof(conn->data, "Kill stream: %s\n", reason));
1391  else if(closeit != conn->bits.close) {
1392  DEBUGF(infof(conn->data, "Marked for [%s]: %s\n",
1393  closeit?"closure":"keep alive", reason));
1394  conn->bits.close = closeit; /* the only place in the source code that
1395  should assign this bit */
1396  }
1397 }
1398 
1399 /* Data received can be cached at various levels, so check them all here. */
1400 bool Curl_conn_data_pending(struct connectdata *conn, int sockindex)
1401 {
1402  int readable;
1403 
1404  if(Curl_ssl_data_pending(conn, sockindex) ||
1405  Curl_recv_has_postponed_data(conn, sockindex))
1406  return true;
1407 
1408  readable = SOCKET_READABLE(conn->sock[sockindex], 0);
1409  return (readable > 0 && (readable & CURL_CSELECT_IN));
1410 }
long timeout
Definition: urldata.h:1547
void * opensocket_client
Definition: urldata.h:1531
struct ssl_connect_data ssl[2]
Definition: urldata.h:887
#define CURL_IPRESOLVE_V6
Definition: curl.h:1856
struct connectdata * lastconnect
Definition: urldata.h:1248
bool tcp_fastopen
Definition: urldata.h:433
bool tcp_nodelay
Definition: urldata.h:1649
struct ConnectBits bits
Definition: urldata.h:893
bool bound
Definition: urldata.h:428
bool Curl_conn_data_pending(struct connectdata *conn, int sockindex)
Definition: connect.c:1400
bool close
Definition: urldata.h:376
#define bind
Definition: setup-os400.h:211
struct UserDefined set
Definition: urldata.h:1762
#define RECV_TYPE_ARG2
Definition: config-dos.h:108
char primary_ip[MAX_IPADR_LEN]
Definition: urldata.h:855
#define sclose(x)
#define Curl_sndbufset(y)
Definition: connect.h:72
curl_opensocket_callback fopensocket
Definition: urldata.h:1528
#define CURL_CSELECT_OUT
Definition: multi.h:265
struct curltime connecttime
Definition: urldata.h:898
long numconnects
Definition: urldata.h:1065
int curlx_sltosi(long slnum)
Definition: warnless.c:264
static void tcpkeepalive(struct Curl_easy *data, curl_socket_t sockfd)
Definition: connect.c:107
void Curl_conncache_foreach(struct conncache *connc, void *param, int(*func)(struct connectdata *conn, void *param))
Definition: conncache.c:264
struct hostname host
Definition: urldata.h:758
void Curl_pgrsTime(struct Curl_easy *data, timerid timer)
Definition: progress.c:162
#define FIRSTSOCKET
Definition: urldata.h:487
long connecttimeout
Definition: urldata.h:1548
struct Curl_multi * multi_easy
Definition: urldata.h:1757
f
unsigned int addrlen
Definition: connect.h:90
void Curl_conncontrol(struct connectdata *conn, int ctrl)
Definition: connect.c:1378
#define CURL_SOCKET_BAD
Definition: curl.h:131
const char * conn_scheme
Definition: urldata.h:1083
unsigned int Curl_ipv6_scope(const struct sockaddr *sa)
Definition: if2ip.c:64
#define failf
Definition: sendf.h:48
static bool getaddressinfo(struct sockaddr *sa, char *addr, long *port)
Definition: connect.c:612
#define CURL_IPRESOLVE_V4
Definition: curl.h:1855
#define SOCKERRNO
Definition: hostip.h:66
const struct Curl_handler * handler
Definition: urldata.h:904
curl_socket_t sockfd
Definition: urldata.h:911
#define CURL_MAX_WRITE_SIZE
Definition: curl.h:229
#define DEBUGASSERT(x)
struct Curl_multi * multi
Definition: urldata.h:1754
#define CURLRESOLV_PENDING
Definition: hostip.h:85
CURLcode
Definition: curl.h:454
long conn_primary_port
Definition: urldata.h:1078
struct curltime now
Definition: unit1399.c:83
int Curl_closesocket(struct connectdata *conn, curl_socket_t sock)
Definition: connect.c:1280
curl_socket_t tempsock[2]
Definition: urldata.h:878
#define HAPPY_EYEBALLS_TIMEOUT
Definition: connect.h:43
#define ENABLE_IPV6
Definition: config-os400.h:71
#define SECONDARYSOCKET
Definition: urldata.h:488
CURLcode Curl_socket(struct connectdata *conn, const Curl_addrinfo *ai, struct Curl_sockaddr_ex *addr, curl_socket_t *sockfd)
Definition: connect.c:1314
struct hostname host
Definition: urldata.h:833
struct curltime t_startop
Definition: urldata.h:1120
char * name
Definition: urldata.h:444
UNITTEST_START int result
Definition: unit1304.c:49
long conn_local_port
Definition: urldata.h:1081
char ip_addr_str[MAX_IPADR_LEN]
Definition: urldata.h:827
unsigned int i
Definition: unit1303.c:79
CURLcode Curl_connecthost(struct connectdata *conn, const struct Curl_dns_entry *remotehost)
Definition: connect.c:1144
#define RECV_TYPE_ARG3
Definition: config-dos.h:109
char * Curl_inet_ntop(int af, const void *src, char *buf, size_t size)
Definition: inet_ntop.c:183
int curlx_nonblock(curl_socket_t sockfd, int nonblock)
Definition: nonblock.c:47
void Curl_verboseconnect(struct connectdata *conn)
Definition: url.c:3961
struct sockaddr * ai_addr
Definition: curl_addrinfo.h:58
size_t len
Definition: curl_sasl.c:55
struct proxy_info http_proxy
Definition: urldata.h:839
#define PROTOPT_SSL
Definition: urldata.h:700
unsigned int protocol
Definition: urldata.h:694
const char * scheme
Definition: urldata.h:623
curl_sockopt_callback fsockopt
Definition: urldata.h:1526
#define MAX_IPADR_LEN
Definition: urldata.h:75
static CURLcode singleipconnect(struct connectdata *conn, const Curl_addrinfo *ai, curl_socket_t *sock)
Definition: connect.c:967
memcpy(filename, filename1, strlen(filename1))
CURLcode Curl_connected_proxy(struct connectdata *conn, int sockindex)
Definition: url.c:3911
unsigned int conn_protocol
Definition: urldata.h:1084
curl_socket_t Curl_getconnectinfo(struct Curl_easy *data, struct connectdata **connp)
Definition: connect.c:1210
#define CURL_CSELECT_ERR
Definition: multi.h:266
Curl_addrinfo * ip_addr
Definition: urldata.h:821
#define Curl_ssl_data_pending(x, y)
Definition: vtls.h:264
CURL_TYPEOF_CURL_SOCKLEN_T curl_socklen_t
Definition: system.h:414
#define CONNCTRL_STREAM
Definition: connect.h:126
bool ipv6
Definition: urldata.h:389
bool found
Definition: connect.c:1191
#define FALSE
time_t Curl_timeleft(struct Curl_easy *data, struct curltime *nowp, bool duringconnect)
Definition: connect.c:182
#define RECV_TYPE_ARG4
Definition: config-dos.h:110
unsigned int flags
Definition: urldata.h:696
#define CURL_CSELECT_IN
Definition: multi.h:264
UNITTEST_START int rc
Definition: unit1301.c:31
const char * Curl_strerror(struct connectdata *conn, int err)
Definition: strerror.c:646
#define EAGAIN
#define SOCKET_READABLE(x, z)
Definition: select.h:79
struct sockaddr sa
Definition: sockaddr.h:29
void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
Definition: connect.c:664
#define Curl_ssl_check_cxn(x)
Definition: vtls.h:265
bool httpproxy
Definition: urldata.h:383
const char * Curl_printable_address(const Curl_addrinfo *ai, char *buf, size_t bufsize)
Definition: hostip.c:166
#define SOCKET_WRITABLE(x, z)
Definition: select.h:81
CURLcode Curl_is_connected(struct connectdata *conn, int sockindex, bool *connected)
Definition: connect.c:718
bool tcp_keepalive
Definition: urldata.h:1687
#define connect
Definition: setup-os400.h:210
struct connectdata * tofind
Definition: connect.c:1190
if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope, unsigned int remote_scope_id, const char *interf, char *buf, int buf_size)
Definition: if2ip.c:261
int Curl_resolv(struct connectdata *conn, const char *hostname, int port, struct Curl_dns_entry **entry)
Definition: hostip.c:444
static CURLcode bindlocal(struct connectdata *conn, curl_socket_t sockfd, int af, unsigned int scope)
Definition: connect.c:239
#define Curl_tvnow()
Definition: timeval.h:57
void Curl_resolv_unlock(struct Curl_easy *data, struct Curl_dns_entry *dns)
Definition: hostip.c:722
int socktype
Definition: urldata.h:831
struct Progress progress
Definition: urldata.h:1768
#define nosigpipe(x, y)
Definition: connect.c:911
struct conncache conn_cache
Definition: multihandle.h:115
const struct Curl_handler * given
Definition: urldata.h:905
int os_errno
Definition: urldata.h:1274
Definition: curl.h:455
struct proxy_info socks_proxy
Definition: urldata.h:838
bool conn_to_host
Definition: urldata.h:378
int Curl_inet_pton(int af, const char *src, void *dst)
Definition: inet_pton.c:66
static unsigned short port
Definition: sockfilt.c:137
struct Curl_addrinfo * ai_next
Definition: curl_addrinfo.h:59
Curl_addrinfo * addr
Definition: hostip.h:67
bool Curl_connalive(struct connectdata *conn)
Definition: connect.c:1251
void * closesocket_client
Definition: urldata.h:801
struct UrlState state
Definition: urldata.h:1769
time_t timeoutms_per_addr
Definition: urldata.h:901
int localportrange
Definition: urldata.h:1514
char conn_local_ip[MAX_IPADR_LEN]
Definition: urldata.h:1080
time_t curlx_tvdiff(struct curltime newer, struct curltime older)
Definition: timeval.c:128
#define DEFAULT_CONNECT_TIMEOUT
Definition: connect.h:42
struct PureInfo info
Definition: urldata.h:1772
long ip_version
Definition: urldata.h:907
void Curl_tcpnodelay(struct connectdata *conn, curl_socket_t sockfd)
Definition: connect.c:870
curl_socket_t sock[2]
Definition: urldata.h:876
void Curl_multi_closed(struct connectdata *conn, curl_socket_t s)
Definition: multi.c:2467
bool reuse
Definition: urldata.h:377
int num_addr
Definition: urldata.h:900
curl_closesocket_callback fclosesocket
Definition: urldata.h:800
struct curltime t_startsingle
Definition: urldata.h:1119
#define SET_SOCKERRNO(x)
int Curl_num_addresses(const Curl_addrinfo *addr)
Definition: hostip.c:148
bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex)
Definition: sendf.c:212
long local_port
Definition: urldata.h:863
struct hostname conn_to_host
Definition: urldata.h:835
void Curl_persistconninfo(struct connectdata *conn)
Definition: connect.c:600
unsigned int scope_id
Definition: urldata.h:829
char local_ip[MAX_IPADR_LEN]
Definition: urldata.h:862
char buf[3]
Definition: unit1398.c:32
char conn_primary_ip[MAX_IPADR_LEN]
Definition: urldata.h:1077
static int conn_is_conn(struct connectdata *conn, void *param)
Definition: connect.c:1194
#define infof
Definition: sendf.h:44
static CURLcode trynextip(struct connectdata *conn, int sockindex, int tempindex)
Definition: connect.c:540
#define Curl_tvdiff(x, y)
Definition: timeval.h:58
long tcp_keepidle
Definition: urldata.h:1688
curl_socklen_t ai_addrlen
Definition: curl_addrinfo.h:56
char * str[STRING_LAST]
Definition: urldata.h:1663
bool sock_accepted[2]
Definition: urldata.h:879
#define CONNCTRL_CONNECTION
Definition: connect.h:125
long port
Definition: urldata.h:841
#define KEEPALIVE_FACTOR(x)
Definition: connect.c:93
size_t size
Definition: unit1302.c:52
#define snprintf
Definition: curl_printf.h:42
CURLcode Curl_resolver_wait_resolv(struct connectdata *conn, struct Curl_dns_entry **dnsentry)
void Curl_expire(struct Curl_easy *data, time_t milli, expire_id id)
Definition: multi.c:2930
#define TRUE
long primary_port
Definition: urldata.h:856
Curl_addrinfo * tempaddr[2]
Definition: urldata.h:822
#define PROTOPT_STREAM
Definition: urldata.h:716
bool socksproxy
Definition: urldata.h:384
#define RECV_TYPE_ARG1
Definition: config-dos.h:107
int curl_socket_t
Definition: curl.h:130
static bool verifyconnect(curl_socket_t sockfd, int *error)
Definition: connect.c:474
#define CURL_SOCKOPT_ALREADY_CONNECTED
Definition: curl.h:371
long tcp_keepintvl
Definition: urldata.h:1689
void * sockopt_client
Definition: urldata.h:1527
Definition: debug.c:29
bool tcpconnect[2]
Definition: urldata.h:393
unsigned short localport
Definition: urldata.h:1513
#define DEBUGF(x)
struct Curl_easy * data
Definition: urldata.h:791


rc_tagdetect_client
Author(s): Monika Florek-Jasinska , Raphael Schaller
autogenerated on Sat Feb 13 2021 03:42:08