]> rtime.felk.cvut.cz Git - hornmich/skoda-qr-demo.git/blob - QRScanner/mobile/jni/thirdparty/curl/lib/connect.c
Add MuPDF native source codes
[hornmich/skoda-qr-demo.git] / QRScanner / mobile / jni / thirdparty / curl / lib / connect.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2013, 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 http://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 #define _MPRINTF_REPLACE /* use our functions only */
60 #include <curl/mprintf.h>
61
62 #include "urldata.h"
63 #include "sendf.h"
64 #include "if2ip.h"
65 #include "strerror.h"
66 #include "connect.h"
67 #include "curl_memory.h"
68 #include "select.h"
69 #include "url.h" /* for Curl_safefree() */
70 #include "multiif.h"
71 #include "sockaddr.h" /* required for Curl_sockaddr_storage */
72 #include "inet_ntop.h"
73 #include "inet_pton.h"
74 #include "sslgen.h" /* for Curl_ssl_check_cxn() */
75 #include "progress.h"
76 #include "warnless.h"
77 #include "conncache.h"
78 #include "multihandle.h"
79
80 /* The last #include file should be: */
81 #include "memdebug.h"
82
83 #ifdef __SYMBIAN32__
84 /* This isn't actually supported under Symbian OS */
85 #undef SO_NOSIGPIPE
86 #endif
87
88 static bool verifyconnect(curl_socket_t sockfd, int *error);
89
90 #if defined(__DragonFly__) || defined(HAVE_WINSOCK_H)
91 /* DragonFlyBSD and Windows use millisecond units */
92 #define KEEPALIVE_FACTOR(x) (x *= 1000)
93 #else
94 #define KEEPALIVE_FACTOR(x)
95 #endif
96
97 #if defined(HAVE_WINSOCK_H) && !defined(SIO_KEEPALIVE_VALS)
98 #define SIO_KEEPALIVE_VALS    _WSAIOW(IOC_VENDOR,4)
99
100 struct tcp_keepalive {
101   u_long onoff;
102   u_long keepalivetime;
103   u_long keepaliveinterval;
104 };
105 #endif
106
107 static void
108 tcpkeepalive(struct SessionHandle *data,
109              curl_socket_t sockfd)
110 {
111   int optval = data->set.tcp_keepalive?1:0;
112
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);
117   }
118   else {
119 #if defined(SIO_KEEPALIVE_VALS)
120     struct tcp_keepalive vals;
121     DWORD dummy;
122     vals.onoff = 1;
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());
133     }
134 #else
135 #ifdef TCP_KEEPIDLE
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);
141     }
142 #endif
143 #ifdef TCP_KEEPINTVL
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);
149     }
150 #endif
151 #ifdef TCP_KEEPALIVE
152     /* Mac OS X style */
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);
158     }
159 #endif
160 #endif
161   }
162 }
163
164 static CURLcode
165 singleipconnect(struct connectdata *conn,
166                 const Curl_addrinfo *ai, /* start connecting to this */
167                 curl_socket_t *sock,
168                 bool *connected);
169
170 /*
171  * Curl_timeleft() returns the amount of milliseconds left allowed for the
172  * transfer/connection. If the value is negative, the timeout time has already
173  * elapsed.
174  *
175  * The start time is stored in progress.t_startsingle - as set with
176  * Curl_pgrsTime(..., TIMER_STARTSINGLE);
177  *
178  * If 'nowp' is non-NULL, it points to the current time.
179  * 'duringconnect' is FALSE if not during a connect, as then of course the
180  * connect timeout is not taken into account!
181  *
182  * @unittest: 1303
183  */
184 long Curl_timeleft(struct SessionHandle *data,
185                    struct timeval *nowp,
186                    bool duringconnect)
187 {
188   int timeout_set = 0;
189   long timeout_ms = duringconnect?DEFAULT_CONNECT_TIMEOUT:0;
190   struct timeval now;
191
192   /* if a timeout is set, use the most restrictive one */
193
194   if(data->set.timeout > 0)
195     timeout_set |= 1;
196   if(duringconnect && (data->set.connecttimeout > 0))
197     timeout_set |= 2;
198
199   switch (timeout_set) {
200   case 1:
201     timeout_ms = data->set.timeout;
202     break;
203   case 2:
204     timeout_ms = data->set.connecttimeout;
205     break;
206   case 3:
207     if(data->set.timeout < data->set.connecttimeout)
208       timeout_ms = data->set.timeout;
209     else
210       timeout_ms = data->set.connecttimeout;
211     break;
212   default:
213     /* use the default */
214     if(!duringconnect)
215       /* if we're not during connect, there's no default timeout so if we're
216          at zero we better just return zero and not make it a negative number
217          by the math below */
218       return 0;
219     break;
220   }
221
222   if(!nowp) {
223     now = Curl_tvnow();
224     nowp = &now;
225   }
226
227   /* subtract elapsed time */
228   timeout_ms -= Curl_tvdiff(*nowp, data->progress.t_startsingle);
229   if(!timeout_ms)
230     /* avoid returning 0 as that means no timeout! */
231     return -1;
232
233   return timeout_ms;
234 }
235
236 /*
237  * checkconnect() checks for a TCP connect on the given socket.
238  * It returns:
239  */
240
241 enum chkconn_t {
242   CHKCONN_SELECT_ERROR = -1,
243   CHKCONN_CONNECTED    = 0,
244   CHKCONN_IDLE         = 1,
245   CHKCONN_FDSET_ERROR  = 2
246 };
247
248 static enum chkconn_t
249 checkconnect(curl_socket_t sockfd)
250 {
251   int rc;
252 #ifdef mpeix
253   /* Call this function once now, and ignore the results. We do this to
254      "clear" the error state on the socket so that we can later read it
255      reliably. This is reported necessary on the MPE/iX operating system. */
256   (void)verifyconnect(sockfd, NULL);
257 #endif
258
259   rc = Curl_socket_ready(CURL_SOCKET_BAD, sockfd, 0);
260
261   if(-1 == rc)
262     /* error, no connect here, try next */
263     return CHKCONN_SELECT_ERROR;
264
265   else if(rc & CURL_CSELECT_ERR)
266     /* error condition caught */
267     return CHKCONN_FDSET_ERROR;
268
269   else if(rc)
270     return CHKCONN_CONNECTED;
271
272   return CHKCONN_IDLE;
273 }
274
275 static CURLcode bindlocal(struct connectdata *conn,
276                           curl_socket_t sockfd, int af)
277 {
278   struct SessionHandle *data = conn->data;
279
280   struct Curl_sockaddr_storage sa;
281   struct sockaddr *sock = (struct sockaddr *)&sa;  /* bind to this address */
282   curl_socklen_t sizeof_sa = 0; /* size of the data sock points to */
283   struct sockaddr_in *si4 = (struct sockaddr_in *)&sa;
284 #ifdef ENABLE_IPV6
285   struct sockaddr_in6 *si6 = (struct sockaddr_in6 *)&sa;
286 #endif
287
288   struct Curl_dns_entry *h=NULL;
289   unsigned short port = data->set.localport; /* use this port number, 0 for
290                                                 "random" */
291   /* how many port numbers to try to bind to, increasing one at a time */
292   int portnum = data->set.localportrange;
293   const char *dev = data->set.str[STRING_DEVICE];
294   int error;
295   char myhost[256] = "";
296   int done = 0; /* -1 for error, 1 for address found */
297   bool is_interface = FALSE;
298   bool is_host = FALSE;
299   static const char *if_prefix = "if!";
300   static const char *host_prefix = "host!";
301
302   /*************************************************************
303    * Select device to bind socket to
304    *************************************************************/
305   if(!dev && !port)
306     /* no local kind of binding was requested */
307     return CURLE_OK;
308
309   memset(&sa, 0, sizeof(struct Curl_sockaddr_storage));
310
311   if(dev && (strlen(dev)<255) ) {
312     if(strncmp(if_prefix, dev, strlen(if_prefix)) == 0) {
313       dev += strlen(if_prefix);
314       is_interface = TRUE;
315     }
316     else if(strncmp(host_prefix, dev, strlen(host_prefix)) == 0) {
317       dev += strlen(host_prefix);
318       is_host = TRUE;
319     }
320
321     /* interface */
322     if(!is_host) {
323       switch(Curl_if2ip(af, conn->scope, dev, myhost, sizeof(myhost))) {
324         case IF2IP_NOT_FOUND:
325           if(is_interface) {
326             /* Do not fall back to treating it as a host name */
327             failf(data, "Couldn't bind to interface '%s'", dev);
328             return CURLE_INTERFACE_FAILED;
329           }
330           break;
331         case IF2IP_AF_NOT_SUPPORTED:
332           /* Signal the caller to try another address family if available */
333           return CURLE_UNSUPPORTED_PROTOCOL;
334         case IF2IP_FOUND:
335           is_interface = TRUE;
336           /*
337            * We now have the numerical IP address in the 'myhost' buffer
338            */
339           infof(data, "Local Interface %s is ip %s using address family %i\n",
340                 dev, myhost, af);
341           done = 1;
342
343 #ifdef SO_BINDTODEVICE
344           /* I am not sure any other OSs than Linux that provide this feature,
345            * and at the least I cannot test. --Ben
346            *
347            * This feature allows one to tightly bind the local socket to a
348            * particular interface.  This will force even requests to other
349            * local interfaces to go out the external interface.
350            *
351            *
352            * Only bind to the interface when specified as interface, not just
353            * as a hostname or ip address.
354            */
355           if(setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE,
356                         dev, (curl_socklen_t)strlen(dev)+1) != 0) {
357             error = SOCKERRNO;
358             infof(data, "SO_BINDTODEVICE %s failed with errno %d: %s;"
359                   " will do regular bind\n",
360                   dev, error, Curl_strerror(conn, error));
361             /* This is typically "errno 1, error: Operation not permitted" if
362                you're not running as root or another suitable privileged
363                user */
364           }
365 #endif
366           break;
367       }
368     }
369     if(!is_interface) {
370       /*
371        * This was not an interface, resolve the name as a host name
372        * or IP number
373        *
374        * Temporarily force name resolution to use only the address type
375        * of the connection. The resolve functions should really be changed
376        * to take a type parameter instead.
377        */
378       long ipver = conn->ip_version;
379       int rc;
380
381       if(af == AF_INET)
382         conn->ip_version = CURL_IPRESOLVE_V4;
383 #ifdef ENABLE_IPV6
384       else if(af == AF_INET6)
385         conn->ip_version = CURL_IPRESOLVE_V6;
386 #endif
387
388       rc = Curl_resolv(conn, dev, 0, &h);
389       if(rc == CURLRESOLV_PENDING)
390         (void)Curl_resolver_wait_resolv(conn, &h);
391       conn->ip_version = ipver;
392
393       if(h) {
394         /* convert the resolved address, sizeof myhost >= INET_ADDRSTRLEN */
395         Curl_printable_address(h->addr, myhost, sizeof(myhost));
396         infof(data, "Name '%s' family %i resolved to '%s' family %i\n",
397               dev, af, myhost, h->addr->ai_family);
398         Curl_resolv_unlock(data, h);
399         done = 1;
400       }
401       else {
402         /*
403          * provided dev was no interface (or interfaces are not supported
404          * e.g. solaris) no ip address and no domain we fail here
405          */
406         done = -1;
407       }
408     }
409
410     if(done > 0) {
411 #ifdef ENABLE_IPV6
412       /* ipv6 address */
413       if(af == AF_INET6) {
414 #ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
415         char *scope_ptr = strchr(myhost, '%');
416         if(scope_ptr)
417           *(scope_ptr++) = 0;
418 #endif
419         if(Curl_inet_pton(AF_INET6, myhost, &si6->sin6_addr) > 0) {
420           si6->sin6_family = AF_INET6;
421           si6->sin6_port = htons(port);
422 #ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
423           if(scope_ptr)
424             /* The "myhost" string either comes from Curl_if2ip or from
425                Curl_printable_address. The latter returns only numeric scope
426                IDs and the former returns none at all.  So the scope ID, if
427                present, is known to be numeric */
428             si6->sin6_scope_id = atoi(scope_ptr);
429 #endif
430         }
431         sizeof_sa = sizeof(struct sockaddr_in6);
432       }
433       else
434 #endif
435       /* ipv4 address */
436       if((af == AF_INET) &&
437          (Curl_inet_pton(AF_INET, myhost, &si4->sin_addr) > 0)) {
438         si4->sin_family = AF_INET;
439         si4->sin_port = htons(port);
440         sizeof_sa = sizeof(struct sockaddr_in);
441       }
442     }
443
444     if(done < 1) {
445       failf(data, "Couldn't bind to '%s'", dev);
446       return CURLE_INTERFACE_FAILED;
447     }
448   }
449   else {
450     /* no device was given, prepare sa to match af's needs */
451 #ifdef ENABLE_IPV6
452     if(af == AF_INET6) {
453       si6->sin6_family = AF_INET6;
454       si6->sin6_port = htons(port);
455       sizeof_sa = sizeof(struct sockaddr_in6);
456     }
457     else
458 #endif
459     if(af == AF_INET) {
460       si4->sin_family = AF_INET;
461       si4->sin_port = htons(port);
462       sizeof_sa = sizeof(struct sockaddr_in);
463     }
464   }
465
466   for(;;) {
467     if(bind(sockfd, sock, sizeof_sa) >= 0) {
468       /* we succeeded to bind */
469       struct Curl_sockaddr_storage add;
470       curl_socklen_t size = sizeof(add);
471       memset(&add, 0, sizeof(struct Curl_sockaddr_storage));
472       if(getsockname(sockfd, (struct sockaddr *) &add, &size) < 0) {
473         data->state.os_errno = error = SOCKERRNO;
474         failf(data, "getsockname() failed with errno %d: %s",
475               error, Curl_strerror(conn, error));
476         return CURLE_INTERFACE_FAILED;
477       }
478       infof(data, "Local port: %hu\n", port);
479       conn->bits.bound = TRUE;
480       return CURLE_OK;
481     }
482
483     if(--portnum > 0) {
484       infof(data, "Bind to local port %hu failed, trying next\n", port);
485       port++; /* try next port */
486       /* We re-use/clobber the port variable here below */
487       if(sock->sa_family == AF_INET)
488         si4->sin_port = ntohs(port);
489 #ifdef ENABLE_IPV6
490       else
491         si6->sin6_port = ntohs(port);
492 #endif
493     }
494     else
495       break;
496   }
497
498   data->state.os_errno = error = SOCKERRNO;
499   failf(data, "bind failed with errno %d: %s",
500         error, Curl_strerror(conn, error));
501
502   return CURLE_INTERFACE_FAILED;
503 }
504
505 /*
506  * verifyconnect() returns TRUE if the connect really has happened.
507  */
508 static bool verifyconnect(curl_socket_t sockfd, int *error)
509 {
510   bool rc = TRUE;
511 #ifdef SO_ERROR
512   int err = 0;
513   curl_socklen_t errSize = sizeof(err);
514
515 #ifdef WIN32
516   /*
517    * In October 2003 we effectively nullified this function on Windows due to
518    * problems with it using all CPU in multi-threaded cases.
519    *
520    * In May 2004, we bring it back to offer more info back on connect failures.
521    * Gisle Vanem could reproduce the former problems with this function, but
522    * could avoid them by adding this SleepEx() call below:
523    *
524    *    "I don't have Rational Quantify, but the hint from his post was
525    *    ntdll::NtRemoveIoCompletion(). So I'd assume the SleepEx (or maybe
526    *    just Sleep(0) would be enough?) would release whatever
527    *    mutex/critical-section the ntdll call is waiting on.
528    *
529    *    Someone got to verify this on Win-NT 4.0, 2000."
530    */
531
532 #ifdef _WIN32_WCE
533   Sleep(0);
534 #else
535   SleepEx(0, FALSE);
536 #endif
537
538 #endif
539
540   if(0 != getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *)&err, &errSize))
541     err = SOCKERRNO;
542 #ifdef _WIN32_WCE
543   /* Old WinCE versions don't support SO_ERROR */
544   if(WSAENOPROTOOPT == err) {
545     SET_SOCKERRNO(0);
546     err = 0;
547   }
548 #endif
549 #ifdef __minix
550   /* Minix 3.1.x doesn't support getsockopt on UDP sockets */
551   if(EBADIOCTL == err) {
552     SET_SOCKERRNO(0);
553     err = 0;
554   }
555 #endif
556   if((0 == err) || (EISCONN == err))
557     /* we are connected, awesome! */
558     rc = TRUE;
559   else
560     /* This wasn't a successful connect */
561     rc = FALSE;
562   if(error)
563     *error = err;
564 #else
565   (void)sockfd;
566   if(error)
567     *error = SOCKERRNO;
568 #endif
569   return rc;
570 }
571
572 /* Used within the multi interface. Try next IP address, return TRUE if no
573    more address exists or error */
574 static CURLcode trynextip(struct connectdata *conn,
575                           int sockindex,
576                           bool *connected)
577 {
578   curl_socket_t sockfd;
579   Curl_addrinfo *ai;
580
581   /* First clean up after the failed socket.
582      Don't close it yet to ensure that the next IP's socket gets a different
583      file descriptor, which can prevent bugs when the curl_multi_socket_action
584      interface is used with certain select() replacements such as kqueue. */
585   curl_socket_t fd_to_close = conn->sock[sockindex];
586   conn->sock[sockindex] = CURL_SOCKET_BAD;
587   *connected = FALSE;
588
589   if(sockindex != FIRSTSOCKET) {
590     Curl_closesocket(conn, fd_to_close);
591     return CURLE_COULDNT_CONNECT; /* no next */
592   }
593
594   /* try the next address */
595   ai = conn->ip_addr->ai_next;
596
597   while(ai) {
598     CURLcode res = singleipconnect(conn, ai, &sockfd, connected);
599     if(res)
600       return res;
601     if(sockfd != CURL_SOCKET_BAD) {
602       /* store the new socket descriptor */
603       conn->sock[sockindex] = sockfd;
604       conn->ip_addr = ai;
605       Curl_closesocket(conn, fd_to_close);
606       return CURLE_OK;
607     }
608     ai = ai->ai_next;
609   }
610   Curl_closesocket(conn, fd_to_close);
611   return CURLE_COULDNT_CONNECT;
612 }
613
614 /* Copies connection info into the session handle to make it available
615    when the session handle is no longer associated with a connection. */
616 void Curl_persistconninfo(struct connectdata *conn)
617 {
618   memcpy(conn->data->info.conn_primary_ip, conn->primary_ip, MAX_IPADR_LEN);
619   memcpy(conn->data->info.conn_local_ip, conn->local_ip, MAX_IPADR_LEN);
620   conn->data->info.conn_primary_port = conn->primary_port;
621   conn->data->info.conn_local_port = conn->local_port;
622 }
623
624 /* retrieves ip address and port from a sockaddr structure */
625 static bool getaddressinfo(struct sockaddr* sa, char* addr,
626                            long* port)
627 {
628   unsigned short us_port;
629   struct sockaddr_in* si = NULL;
630 #ifdef ENABLE_IPV6
631   struct sockaddr_in6* si6 = NULL;
632 #endif
633 #if defined(HAVE_SYS_UN_H) && defined(AF_UNIX)
634   struct sockaddr_un* su = NULL;
635 #endif
636
637   switch (sa->sa_family) {
638     case AF_INET:
639       si = (struct sockaddr_in*) sa;
640       if(Curl_inet_ntop(sa->sa_family, &si->sin_addr,
641                         addr, MAX_IPADR_LEN)) {
642         us_port = ntohs(si->sin_port);
643         *port = us_port;
644         return TRUE;
645       }
646       break;
647 #ifdef ENABLE_IPV6
648     case AF_INET6:
649       si6 = (struct sockaddr_in6*)sa;
650       if(Curl_inet_ntop(sa->sa_family, &si6->sin6_addr,
651                         addr, MAX_IPADR_LEN)) {
652         us_port = ntohs(si6->sin6_port);
653         *port = us_port;
654         return TRUE;
655       }
656       break;
657 #endif
658 #if defined(HAVE_SYS_UN_H) && defined(AF_UNIX)
659     case AF_UNIX:
660       su = (struct sockaddr_un*)sa;
661       snprintf(addr, MAX_IPADR_LEN, "%s", su->sun_path);
662       *port = 0;
663       return TRUE;
664 #endif
665     default:
666       break;
667   }
668
669   addr[0] = '\0';
670   *port = 0;
671
672   return FALSE;
673 }
674
675 /* retrieves the start/end point information of a socket of an established
676    connection */
677 void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
678 {
679   int error;
680   curl_socklen_t len;
681   struct Curl_sockaddr_storage ssrem;
682   struct Curl_sockaddr_storage ssloc;
683   struct SessionHandle *data = conn->data;
684
685   if(!conn->bits.reuse) {
686
687     len = sizeof(struct Curl_sockaddr_storage);
688     if(getpeername(sockfd, (struct sockaddr*) &ssrem, &len)) {
689       error = SOCKERRNO;
690       failf(data, "getpeername() failed with errno %d: %s",
691             error, Curl_strerror(conn, error));
692       return;
693     }
694
695     len = sizeof(struct Curl_sockaddr_storage);
696     if(getsockname(sockfd, (struct sockaddr*) &ssloc, &len)) {
697       error = SOCKERRNO;
698       failf(data, "getsockname() failed with errno %d: %s",
699             error, Curl_strerror(conn, error));
700       return;
701     }
702
703     if(!getaddressinfo((struct sockaddr*)&ssrem,
704                         conn->primary_ip, &conn->primary_port)) {
705       error = ERRNO;
706       failf(data, "ssrem inet_ntop() failed with errno %d: %s",
707             error, Curl_strerror(conn, error));
708       return;
709     }
710
711     if(!getaddressinfo((struct sockaddr*)&ssloc,
712                        conn->local_ip, &conn->local_port)) {
713       error = ERRNO;
714       failf(data, "ssloc inet_ntop() failed with errno %d: %s",
715             error, Curl_strerror(conn, error));
716       return;
717     }
718
719   }
720
721   /* persist connection info in session handle */
722   Curl_persistconninfo(conn);
723 }
724
725 /*
726  * Curl_is_connected() checks if the socket has connected.
727  */
728
729 CURLcode Curl_is_connected(struct connectdata *conn,
730                            int sockindex,
731                            bool *connected)
732 {
733   struct SessionHandle *data = conn->data;
734   CURLcode code = CURLE_OK;
735   curl_socket_t sockfd = conn->sock[sockindex];
736   long allow = DEFAULT_CONNECT_TIMEOUT;
737   int error = 0;
738   struct timeval now;
739   enum chkconn_t chk;
740
741   DEBUGASSERT(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET);
742
743   *connected = FALSE; /* a very negative world view is best */
744
745   if(conn->bits.tcpconnect[sockindex]) {
746     /* we are connected already! */
747     *connected = TRUE;
748     return CURLE_OK;
749   }
750
751   now = Curl_tvnow();
752
753   /* figure out how long time we have left to connect */
754   allow = Curl_timeleft(data, &now, TRUE);
755
756   if(allow < 0) {
757     /* time-out, bail out, go home */
758     failf(data, "Connection time-out");
759     return CURLE_OPERATION_TIMEDOUT;
760   }
761
762   /* check socket for connect */
763   chk = checkconnect(sockfd);
764   if(CHKCONN_IDLE == chk) {
765     if(curlx_tvdiff(now, conn->connecttime) >= conn->timeoutms_per_addr) {
766       infof(data, "After %ldms connect time, move on!\n",
767             conn->timeoutms_per_addr);
768       goto next;
769     }
770
771     /* not an error, but also no connection yet */
772     return code;
773   }
774
775   if(CHKCONN_CONNECTED == chk) {
776     if(verifyconnect(sockfd, &error)) {
777       /* we are connected with TCP, awesome! */
778
779       /* see if we need to do any proxy magic first once we connected */
780       code = Curl_connected_proxy(conn);
781       if(code)
782         return code;
783
784       conn->bits.tcpconnect[sockindex] = TRUE;
785
786       *connected = TRUE;
787       if(sockindex == FIRSTSOCKET)
788         Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */
789       Curl_verboseconnect(conn);
790       Curl_updateconninfo(conn, sockfd);
791
792       return CURLE_OK;
793     }
794     /* nope, not connected for real */
795   }
796   else {
797     /* nope, not connected  */
798     if(CHKCONN_FDSET_ERROR == chk) {
799       (void)verifyconnect(sockfd, &error);
800       infof(data, "%s\n",Curl_strerror(conn, error));
801     }
802     else
803       infof(data, "Connection failed\n");
804   }
805
806   /*
807    * The connection failed here, we should attempt to connect to the "next
808    * address" for the given host. But first remember the latest error.
809    */
810   if(error) {
811     data->state.os_errno = error;
812     SET_SOCKERRNO(error);
813   }
814   next:
815
816   conn->timeoutms_per_addr = conn->ip_addr->ai_next == NULL ?
817                              allow : allow / 2;
818   code = trynextip(conn, sockindex, connected);
819
820   if(code) {
821     error = SOCKERRNO;
822     data->state.os_errno = error;
823     failf(data, "Failed connect to %s:%ld; %s",
824           conn->host.name, conn->port, Curl_strerror(conn, error));
825   }
826
827   return code;
828 }
829
830 static void tcpnodelay(struct connectdata *conn,
831                        curl_socket_t sockfd)
832 {
833 #ifdef TCP_NODELAY
834   struct SessionHandle *data= conn->data;
835   curl_socklen_t onoff = (curl_socklen_t) data->set.tcp_nodelay;
836   int level = IPPROTO_TCP;
837
838 #if 0
839   /* The use of getprotobyname() is disabled since it isn't thread-safe on
840      numerous systems. On these getprotobyname_r() should be used instead, but
841      that exists in at least one 4 arg version and one 5 arg version, and
842      since the proto number rarely changes anyway we now just use the hard
843      coded number. The "proper" fix would need a configure check for the
844      correct function much in the same style the gethostbyname_r versions are
845      detected. */
846   struct protoent *pe = getprotobyname("tcp");
847   if(pe)
848     level = pe->p_proto;
849 #endif
850
851   if(setsockopt(sockfd, level, TCP_NODELAY, (void *)&onoff,
852                 sizeof(onoff)) < 0)
853     infof(data, "Could not set TCP_NODELAY: %s\n",
854           Curl_strerror(conn, SOCKERRNO));
855   else
856     infof(data,"TCP_NODELAY set\n");
857 #else
858   (void)conn;
859   (void)sockfd;
860 #endif
861 }
862
863 #ifdef SO_NOSIGPIPE
864 /* The preferred method on Mac OS X (10.2 and later) to prevent SIGPIPEs when
865    sending data to a dead peer (instead of relying on the 4th argument to send
866    being MSG_NOSIGNAL). Possibly also existing and in use on other BSD
867    systems? */
868 static void nosigpipe(struct connectdata *conn,
869                       curl_socket_t sockfd)
870 {
871   struct SessionHandle *data= conn->data;
872   int onoff = 1;
873   if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff,
874                 sizeof(onoff)) < 0)
875     infof(data, "Could not set SO_NOSIGPIPE: %s\n",
876           Curl_strerror(conn, SOCKERRNO));
877 }
878 #else
879 #define nosigpipe(x,y) Curl_nop_stmt
880 #endif
881
882 #ifdef USE_WINSOCK
883 /* When you run a program that uses the Windows Sockets API, you may
884    experience slow performance when you copy data to a TCP server.
885
886    http://support.microsoft.com/kb/823764
887
888    Work-around: Make the Socket Send Buffer Size Larger Than the Program Send
889    Buffer Size
890
891    The problem described in this knowledge-base is applied only to pre-Vista
892    Windows.  Following function trying to detect OS version and skips
893    SO_SNDBUF adjustment for Windows Vista and above.
894 */
895 #define DETECT_OS_NONE 0
896 #define DETECT_OS_PREVISTA 1
897 #define DETECT_OS_VISTA_OR_LATER 2
898
899 void Curl_sndbufset(curl_socket_t sockfd)
900 {
901   int val = CURL_MAX_WRITE_SIZE + 32;
902   int curval = 0;
903   int curlen = sizeof(curval);
904
905   OSVERSIONINFO osver;
906   static int detectOsState = DETECT_OS_NONE;
907
908   if(detectOsState == DETECT_OS_NONE) {
909     memset(&osver, 0, sizeof(osver));
910     osver.dwOSVersionInfoSize = sizeof(osver);
911     detectOsState = DETECT_OS_PREVISTA;
912     if(GetVersionEx(&osver)) {
913       if(osver.dwMajorVersion >= 6)
914         detectOsState = DETECT_OS_VISTA_OR_LATER;
915     }
916   }
917   if(detectOsState == DETECT_OS_VISTA_OR_LATER)
918     return;
919
920   if(getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (char *)&curval, &curlen) == 0)
921     if(curval > val)
922       return;
923
924   setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (const char *)&val, sizeof(val));
925 }
926 #endif
927
928
929 /*
930  * singleipconnect()
931  *
932  * Note that even on connect fail it returns CURLE_OK, but with 'sock' set to
933  * CURL_SOCKET_BAD. Other errors will however return proper errors.
934  *
935  * singleipconnect() connects to the given IP only, and it may return without
936  * having connected.
937  */
938 static CURLcode
939 singleipconnect(struct connectdata *conn,
940                 const Curl_addrinfo *ai,
941                 curl_socket_t *sockp,
942                 bool *connected)
943 {
944   struct Curl_sockaddr_ex addr;
945   int rc;
946   int error = 0;
947   bool isconnected = FALSE;
948   struct SessionHandle *data = conn->data;
949   curl_socket_t sockfd;
950   CURLcode res = CURLE_OK;
951
952   *sockp = CURL_SOCKET_BAD;
953   *connected = FALSE; /* default is not connected */
954
955   res = Curl_socket(conn, ai, &addr, &sockfd);
956   if(res)
957     /* Failed to create the socket, but still return OK since we signal the
958        lack of socket as well. This allows the parent function to keep looping
959        over alternative addresses/socket families etc. */
960     return CURLE_OK;
961
962   /* store remote address and port used in this connection attempt */
963   if(!getaddressinfo((struct sockaddr*)&addr.sa_addr,
964                      conn->primary_ip, &conn->primary_port)) {
965     /* malformed address or bug in inet_ntop, try next address */
966     error = ERRNO;
967     failf(data, "sa_addr inet_ntop() failed with errno %d: %s",
968           error, Curl_strerror(conn, error));
969     Curl_closesocket(conn, sockfd);
970     return CURLE_OK;
971   }
972   memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN);
973   infof(data, "  Trying %s...\n", conn->ip_addr_str);
974
975   Curl_persistconninfo(conn);
976
977   if(data->set.tcp_nodelay)
978     tcpnodelay(conn, sockfd);
979
980   nosigpipe(conn, sockfd);
981
982   Curl_sndbufset(sockfd);
983
984   if(data->set.tcp_keepalive)
985     tcpkeepalive(data, sockfd);
986
987   if(data->set.fsockopt) {
988     /* activate callback for setting socket options */
989     error = data->set.fsockopt(data->set.sockopt_client,
990                                sockfd,
991                                CURLSOCKTYPE_IPCXN);
992
993     if(error == CURL_SOCKOPT_ALREADY_CONNECTED)
994       isconnected = TRUE;
995     else if(error) {
996       Curl_closesocket(conn, sockfd); /* close the socket and bail out */
997       return CURLE_ABORTED_BY_CALLBACK;
998     }
999   }
1000
1001   /* possibly bind the local end to an IP, interface or port */
1002   res = bindlocal(conn, sockfd, addr.family);
1003   if(res) {
1004     Curl_closesocket(conn, sockfd); /* close socket and bail out */
1005     if(res == CURLE_UNSUPPORTED_PROTOCOL) {
1006       /* The address family is not supported on this interface.
1007          We can continue trying addresses */
1008       return CURLE_OK;
1009     }
1010     return res;
1011   }
1012
1013   /* set socket non-blocking */
1014   curlx_nonblock(sockfd, TRUE);
1015
1016   conn->connecttime = Curl_tvnow();
1017   if(conn->num_addr > 1)
1018     Curl_expire(data, conn->timeoutms_per_addr);
1019
1020   /* Connect TCP sockets, bind UDP */
1021   if(!isconnected && (conn->socktype == SOCK_STREAM)) {
1022     rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
1023     if(-1 == rc)
1024       error = SOCKERRNO;
1025   }
1026   else {
1027     *sockp = sockfd;
1028     return CURLE_OK;
1029   }
1030
1031 #ifdef ENABLE_IPV6
1032   conn->bits.ipv6 = (addr.family == AF_INET6)?TRUE:FALSE;
1033 #endif
1034
1035   if(-1 == rc) {
1036     switch (error) {
1037     case EINPROGRESS:
1038     case EWOULDBLOCK:
1039 #if defined(EAGAIN)
1040 #if (EAGAIN) != (EWOULDBLOCK)
1041       /* On some platforms EAGAIN and EWOULDBLOCK are the
1042        * same value, and on others they are different, hence
1043        * the odd #if
1044        */
1045     case EAGAIN:
1046 #endif
1047 #endif
1048       *sockp = sockfd;
1049       return CURLE_OK;
1050
1051     default:
1052       /* unknown error, fallthrough and try another address! */
1053       failf(data, "Failed to connect to %s: %s",
1054             conn->ip_addr_str, Curl_strerror(conn,error));
1055       data->state.os_errno = error;
1056
1057       /* connect failed */
1058       Curl_closesocket(conn, sockfd);
1059
1060       break;
1061     }
1062   }
1063   else
1064     *sockp = sockfd;
1065
1066   return CURLE_OK;
1067 }
1068
1069 /*
1070  * TCP connect to the given host with timeout, proxy or remote doesn't matter.
1071  * There might be more than one IP address to try out. Fill in the passed
1072  * pointer with the connected socket.
1073  */
1074
1075 CURLcode Curl_connecthost(struct connectdata *conn,  /* context */
1076                           const struct Curl_dns_entry *remotehost,
1077                           curl_socket_t *sockconn,   /* the connected socket */
1078                           Curl_addrinfo **addr,      /* the one we used */
1079                           bool *connected)           /* really connected? */
1080 {
1081   struct SessionHandle *data = conn->data;
1082   curl_socket_t sockfd = CURL_SOCKET_BAD;
1083   Curl_addrinfo *ai;
1084   Curl_addrinfo *curr_addr;
1085
1086   struct timeval after;
1087   struct timeval before = Curl_tvnow();
1088
1089   /*************************************************************
1090    * Figure out what maximum time we have left
1091    *************************************************************/
1092   long timeout_ms;
1093
1094   DEBUGASSERT(sockconn);
1095   *connected = FALSE; /* default to not connected */
1096
1097   /* get the timeout left */
1098   timeout_ms = Curl_timeleft(data, &before, TRUE);
1099
1100   if(timeout_ms < 0) {
1101     /* a precaution, no need to continue if time already is up */
1102     failf(data, "Connection time-out");
1103     return CURLE_OPERATION_TIMEDOUT;
1104   }
1105
1106   conn->num_addr = Curl_num_addresses(remotehost->addr);
1107
1108   ai = remotehost->addr;
1109
1110   /* Below is the loop that attempts to connect to all IP-addresses we
1111    * know for the given host. One by one until one IP succeeds.
1112    */
1113
1114   /*
1115    * Connecting with a Curl_addrinfo chain
1116    */
1117   for(curr_addr = ai; curr_addr; curr_addr = curr_addr->ai_next) {
1118     CURLcode res;
1119
1120     /* Max time for the next address */
1121     conn->timeoutms_per_addr = curr_addr->ai_next == NULL ?
1122                                timeout_ms : timeout_ms / 2;
1123
1124     /* start connecting to the IP curr_addr points to */
1125     res = singleipconnect(conn, curr_addr,
1126                           &sockfd, connected);
1127     if(res)
1128       return res;
1129
1130     if(sockfd != CURL_SOCKET_BAD)
1131       break;
1132
1133     /* get a new timeout for next attempt */
1134     after = Curl_tvnow();
1135     timeout_ms -= Curl_tvdiff(after, before);
1136     if(timeout_ms < 0) {
1137       failf(data, "connect() timed out!");
1138       return CURLE_OPERATION_TIMEDOUT;
1139     }
1140     before = after;
1141   }  /* end of connect-to-each-address loop */
1142
1143   *sockconn = sockfd;    /* the socket descriptor we've connected */
1144
1145   if(sockfd == CURL_SOCKET_BAD) {
1146     /* no good connect was made */
1147     failf(data, "couldn't connect to %s at %s:%d",
1148           conn->bits.proxy?"proxy":"host",
1149           conn->bits.proxy?conn->proxy.name:conn->host.name, conn->port);
1150     return CURLE_COULDNT_CONNECT;
1151   }
1152
1153   /* leave the socket in non-blocking mode */
1154
1155   /* store the address we use */
1156   if(addr)
1157     *addr = curr_addr;
1158
1159   data->info.numconnects++; /* to track the number of connections made */
1160
1161   return CURLE_OK;
1162 }
1163
1164 struct connfind {
1165   struct connectdata *tofind;
1166   bool found;
1167 };
1168
1169 static int conn_is_conn(struct connectdata *conn, void *param)
1170 {
1171   struct connfind *f = (struct connfind *)param;
1172   if(conn == f->tofind) {
1173     f->found = TRUE;
1174     return 1;
1175   }
1176   return 0;
1177 }
1178
1179 /*
1180  * Used to extract socket and connectdata struct for the most recent
1181  * transfer on the given SessionHandle.
1182  *
1183  * The returned socket will be CURL_SOCKET_BAD in case of failure!
1184  */
1185 curl_socket_t Curl_getconnectinfo(struct SessionHandle *data,
1186                                   struct connectdata **connp)
1187 {
1188   curl_socket_t sockfd;
1189
1190   DEBUGASSERT(data);
1191
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;
1198     find.found = FALSE;
1199
1200     Curl_conncache_foreach(data->multi_easy->conn_cache, &find, conn_is_conn);
1201
1202     if(!find.found) {
1203       data->state.lastconnect = NULL;
1204       return CURL_SOCKET_BAD;
1205     }
1206
1207     if(connp)
1208       /* only store this if the caller cares for it */
1209       *connp = c;
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 */
1217     }
1218 /* Minix 3.1 doesn't support any flags on recv; just assume socket is OK */
1219 #ifdef MSG_PEEK
1220     else {
1221       /* use the socket */
1222       char buf;
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 */
1226       }
1227     }
1228 #endif
1229   }
1230   else
1231     return CURL_SOCKET_BAD;
1232
1233   return sockfd;
1234 }
1235
1236 /*
1237  * Close a socket.
1238  *
1239  * 'conn' can be NULL, beware!
1240  */
1241 int Curl_closesocket(struct connectdata *conn,
1242                       curl_socket_t sock)
1243 {
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
1249          status */
1250       conn->sock_accepted[SECONDARYSOCKET] = FALSE;
1251     else
1252       return conn->fclosesocket(conn->closesocket_client, sock);
1253   }
1254   sclose(sock);
1255
1256   if(conn)
1257     /* tell the multi-socket code about this */
1258     Curl_multi_closed(conn, sock);
1259
1260   return 0;
1261 }
1262
1263 /*
1264  * Create a socket based on info from 'conn' and 'ai'.
1265  *
1266  * 'addr' should be a pointer to the correct struct to get data back, or NULL.
1267  * 'sockfd' must be a pointer to a socket descriptor.
1268  *
1269  * If the open socket callback is set, used that!
1270  *
1271  */
1272 CURLcode Curl_socket(struct connectdata *conn,
1273                      const Curl_addrinfo *ai,
1274                      struct Curl_sockaddr_ex *addr,
1275                      curl_socket_t *sockfd)
1276 {
1277   struct SessionHandle *data = conn->data;
1278   struct Curl_sockaddr_ex dummy;
1279
1280   if(!addr)
1281     /* if the caller doesn't want info back, use a local temp copy */
1282     addr = &dummy;
1283
1284   /*
1285    * The Curl_sockaddr_ex structure is basically libcurl's external API
1286    * curl_sockaddr structure with enough space available to directly hold
1287    * any protocol-specific address structures. The variable declared here
1288    * will be used to pass / receive data to/from the fopensocket callback
1289    * if this has been set, before that, it is initialized from parameters.
1290    */
1291
1292   addr->family = ai->ai_family;
1293   addr->socktype = conn->socktype;
1294   addr->protocol = conn->socktype==SOCK_DGRAM?IPPROTO_UDP:ai->ai_protocol;
1295   addr->addrlen = ai->ai_addrlen;
1296
1297   if(addr->addrlen > sizeof(struct Curl_sockaddr_storage))
1298      addr->addrlen = sizeof(struct Curl_sockaddr_storage);
1299   memcpy(&addr->sa_addr, ai->ai_addr, addr->addrlen);
1300
1301   if(data->set.fopensocket)
1302    /*
1303     * If the opensocket callback is set, all the destination address
1304     * information is passed to the callback. Depending on this information the
1305     * callback may opt to abort the connection, this is indicated returning
1306     * CURL_SOCKET_BAD; otherwise it will return a not-connected socket. When
1307     * the callback returns a valid socket the destination address information
1308     * might have been changed and this 'new' address will actually be used
1309     * here to connect.
1310     */
1311     *sockfd = data->set.fopensocket(data->set.opensocket_client,
1312                                     CURLSOCKTYPE_IPCXN,
1313                                     (struct curl_sockaddr *)addr);
1314   else
1315     /* opensocket callback not set, so simply create the socket now */
1316     *sockfd = socket(addr->family, addr->socktype, addr->protocol);
1317
1318   if(*sockfd == CURL_SOCKET_BAD)
1319     /* no socket, no connection */
1320     return CURLE_COULDNT_CONNECT;
1321
1322 #if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID)
1323   if(conn->scope && (addr->family == AF_INET6)) {
1324     struct sockaddr_in6 * const sa6 = (void *)&addr->sa_addr;
1325     sa6->sin6_scope_id = conn->scope;
1326   }
1327 #endif
1328
1329   return CURLE_OK;
1330
1331 }