1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
12 * are also available at http://curl.haxx.se/docs/copyright.html.
14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
16 * furnished to do so, under the terms of the COPYING file.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 * $Id: connect.c,v 1.2 2007/03/15 19:22:13 andy Exp $
22 ***************************************************************************/
27 /* headers for non-win32 */
28 #ifdef HAVE_SYS_TIME_H
31 #ifdef HAVE_SYS_TYPES_H
32 #include <sys/types.h>
34 #ifdef HAVE_SYS_SOCKET_H
35 #include <sys/socket.h>
37 #ifdef HAVE_NETINET_IN_H
38 #include <netinet/in.h> /* <netinet/tcp.h> may need it */
40 #ifdef HAVE_NETINET_TCP_H
41 #include <netinet/tcp.h> /* for TCP_NODELAY */
43 #ifdef HAVE_SYS_IOCTL_H
44 #include <sys/ioctl.h>
55 #ifdef HAVE_NETINET_IN_H
56 #include <netinet/in.h>
58 #ifdef HAVE_ARPA_INET_H
59 #include <arpa/inet.h>
62 #include <stdlib.h> /* required for free() prototype, without it, this crashes
65 #if (defined(HAVE_FIONBIO) && defined(__NOVELL_LIBC__))
66 #include <sys/filio.h>
68 #if (defined(NETWARE) && defined(__NOVELL_LIBC__))
70 #define in_addr_t unsigned long
88 #define EINPROGRESS WSAEINPROGRESS
89 #define EWOULDBLOCK WSAEWOULDBLOCK
90 #define EISCONN WSAEISCONN
91 #define ENOTSOCK WSAENOTSOCK
92 #define ECONNREFUSED WSAECONNREFUSED
102 #include "url.h" /* for Curl_safefree() */
104 #include "sockaddr.h" /* required for Curl_sockaddr_storage */
105 #include "inet_ntop.h"
107 /* The last #include file should be: */
108 #include "memdebug.h"
110 static bool verifyconnect(curl_socket_t sockfd
, int *error
);
113 singleipconnect(struct connectdata
*conn
,
114 const Curl_addrinfo
*ai
, /* start connecting to this */
119 * Curl_sockerrno() returns the *socket-related* errno (or equivalent) on this
120 * platform to hide platform specific for the function that calls this.
122 int Curl_sockerrno(void)
125 return (int)WSAGetLastError();
132 * Curl_nonblock() set the given socket to either blocking or non-blocking
133 * mode based on the 'nonblock' boolean argument. This function is highly
136 int Curl_nonblock(curl_socket_t sockfd
, /* operate on this */
137 int nonblock
/* TRUE or FALSE */)
141 #ifdef HAVE_O_NONBLOCK
142 /* most recent unix versions */
145 flags
= fcntl(sockfd
, F_GETFL
, 0);
146 if (TRUE
== nonblock
)
147 return fcntl(sockfd
, F_SETFL
, flags
| O_NONBLOCK
);
149 return fcntl(sockfd
, F_SETFL
, flags
& (~O_NONBLOCK
));
154 #if defined(HAVE_FIONBIO) && (SETBLOCK == 0)
155 /* older unix versions */
159 return ioctl(sockfd
, FIONBIO
, &flags
);
164 #if defined(HAVE_IOCTLSOCKET) && (SETBLOCK == 0)
169 return ioctlsocket(sockfd
, FIONBIO
, &flags
);
174 #if defined(HAVE_IOCTLSOCKET_CASE) && (SETBLOCK == 0)
175 /* presumably for Amiga */
176 return IoctlSocket(sockfd
, FIONBIO
, (long)nonblock
);
181 #if defined(HAVE_SO_NONBLOCK) && (SETBLOCK == 0)
183 long b
= nonblock
? 1 : 0;
184 return setsockopt(sockfd
, SOL_SOCKET
, SO_NONBLOCK
, &b
, sizeof(b
));
189 #ifdef HAVE_DISABLED_NONBLOCKING
190 return 0; /* returns success */
196 #error "no non-blocking method was found/used/set"
201 * waitconnect() waits for a TCP connect on the given socket for the specified
202 * number if milliseconds. It returns:
206 * 2 select() returned with an error condition fd_set
209 #define WAITCONN_CONNECTED 0
210 #define WAITCONN_SELECT_ERROR -1
211 #define WAITCONN_TIMEOUT 1
212 #define WAITCONN_FDSET_ERROR 2
215 int waitconnect(curl_socket_t sockfd
, /* socket */
220 /* Call this function once now, and ignore the results. We do this to
221 "clear" the error state on the socket so that we can later read it
222 reliably. This is reported necessary on the MPE/iX operating system. */
223 (void)verifyconnect(sockfd
, NULL
);
226 /* now select() until we get connect or timeout */
227 rc
= Curl_select(CURL_SOCKET_BAD
, sockfd
, (int)timeout_msec
);
229 /* error, no connect here, try next */
230 return WAITCONN_SELECT_ERROR
;
233 /* timeout, no connect today */
234 return WAITCONN_TIMEOUT
;
237 /* error condition caught */
238 return WAITCONN_FDSET_ERROR
;
240 /* we have a connect! */
241 return WAITCONN_CONNECTED
;
244 static CURLcode
bindlocal(struct connectdata
*conn
,
245 curl_socket_t sockfd
)
247 struct SessionHandle
*data
= conn
->data
;
248 struct sockaddr_in me
;
249 struct sockaddr
*sock
= NULL
; /* bind to this address */
250 socklen_t socksize
; /* size of the data sock points to */
251 unsigned short port
= data
->set
.localport
; /* use this port number, 0 for
253 /* how many port numbers to try to bind to, increasing one at a time */
254 int portnum
= data
->set
.localportrange
;
256 /*************************************************************
257 * Select device to bind socket to
258 *************************************************************/
259 if (data
->set
.device
&& (strlen(data
->set
.device
)<255) ) {
260 struct Curl_dns_entry
*h
=NULL
;
261 char myhost
[256] = "";
264 bool was_iface
= FALSE
;
266 /* First check if the given name is an IP address */
267 in
=inet_addr(data
->set
.device
);
269 if((in
== CURL_INADDR_NONE
) &&
270 Curl_if2ip(data
->set
.device
, myhost
, sizeof(myhost
))) {
272 * We now have the numerical IPv4-style x.y.z.w in the 'myhost' buffer
274 rc
= Curl_resolv(conn
, myhost
, 0, &h
);
275 if(rc
== CURLRESOLV_PENDING
)
276 (void)Curl_wait_for_resolv(conn
, &h
);
280 Curl_resolv_unlock(data
, h
);
286 * This was not an interface, resolve the name as a host name
289 rc
= Curl_resolv(conn
, data
->set
.device
, 0, &h
);
290 if(rc
== CURLRESOLV_PENDING
)
291 (void)Curl_wait_for_resolv(conn
, &h
);
294 if(in
== CURL_INADDR_NONE
)
295 /* convert the resolved address, sizeof myhost >= INET_ADDRSTRLEN */
296 Curl_inet_ntop(h
->addr
->ai_addr
->sa_family
,
297 &((struct sockaddr_in
*)h
->addr
->ai_addr
)->sin_addr
,
298 myhost
, sizeof myhost
);
300 /* we know data->set.device is shorter than the myhost array */
301 strcpy(myhost
, data
->set
.device
);
302 Curl_resolv_unlock(data
, h
);
309 getmyhost(*myhost,sizeof(myhost)),
311 sizeof(hostent_buf));
313 failf(data
, "Couldn't bind to '%s'", data
->set
.device
);
314 return CURLE_HTTP_PORT_FAILED
;
317 infof(data
, "Bind local address to %s\n", myhost
);
319 #ifdef SO_BINDTODEVICE
320 /* I am not sure any other OSs than Linux that provide this feature, and
321 * at the least I cannot test. --Ben
323 * This feature allows one to tightly bind the local socket to a
324 * particular interface. This will force even requests to other local
325 * interfaces to go out the external interface.
329 /* Only bind to the interface when specified as interface, not just as a
330 * hostname or ip address.
332 if (setsockopt(sockfd
, SOL_SOCKET
, SO_BINDTODEVICE
,
333 data
->set
.device
, strlen(data
->set
.device
)+1) != 0) {
334 /* printf("Failed to BINDTODEVICE, socket: %d device: %s error: %s\n",
335 sockfd, data->set.device, Curl_strerror(Curl_sockerrno())); */
336 infof(data
, "SO_BINDTODEVICE %s failed\n",
338 /* This is typically "errno 1, error: Operation not permitted" if
339 you're not running as root or another suitable privileged user */
344 in
=inet_addr(myhost
);
345 if (CURL_INADDR_NONE
== in
) {
346 failf(data
,"couldn't find my own IP address (%s)", myhost
);
347 return CURLE_HTTP_PORT_FAILED
;
348 } /* end of inet_addr */
351 Curl_addrinfo
*addr
= h
->addr
;
352 sock
= addr
->ai_addr
;
353 socksize
= addr
->ai_addrlen
;
356 return CURLE_HTTP_PORT_FAILED
;
360 /* if a local port number is requested but no local IP, extract the
361 address from the socket */
362 memset(&me
, 0, sizeof(struct sockaddr
));
363 me
.sin_family
= AF_INET
;
364 me
.sin_addr
.s_addr
= INADDR_ANY
;
366 sock
= (struct sockaddr
*)&me
;
367 socksize
= sizeof(struct sockaddr
);
371 /* no local kind of binding was requested */
376 /* Set port number to bind to, 0 makes the system pick one */
377 if(sock
->sa_family
== AF_INET
)
378 ((struct sockaddr_in
*)sock
)->sin_port
= htons(port
);
381 ((struct sockaddr_in6
*)sock
)->sin6_port
= htons(port
);
384 if( bind(sockfd
, sock
, socksize
) >= 0) {
385 /* we succeeded to bind */
386 struct Curl_sockaddr_storage add
;
390 if(getsockname(sockfd
, (struct sockaddr
*) &add
, &size
) < 0) {
391 failf(data
, "getsockname() failed");
392 return CURLE_HTTP_PORT_FAILED
;
394 /* We re-use/clobber the port variable here below */
395 if(((struct sockaddr
*)&add
)->sa_family
== AF_INET
)
396 port
= ntohs(((struct sockaddr_in
*)&add
)->sin_port
);
399 port
= ntohs(((struct sockaddr_in6
*)&add
)->sin6_port
);
401 infof(data
, "Local port: %d\n", port
);
405 infof(data
, "Bind to local port %d failed, trying next\n", port
);
406 port
++; /* try next port */
412 data
->state
.os_errno
= Curl_sockerrno();
413 failf(data
, "bind failure: %s",
414 Curl_strerror(conn
, data
->state
.os_errno
));
415 return CURLE_HTTP_PORT_FAILED
;
420 * verifyconnect() returns TRUE if the connect really has happened.
422 static bool verifyconnect(curl_socket_t sockfd
, int *error
)
427 socklen_t errSize
= sizeof(err
);
431 * In October 2003 we effectively nullified this function on Windows due to
432 * problems with it using all CPU in multi-threaded cases.
434 * In May 2004, we bring it back to offer more info back on connect failures.
435 * Gisle Vanem could reproduce the former problems with this function, but
436 * could avoid them by adding this SleepEx() call below:
438 * "I don't have Rational Quantify, but the hint from his post was
439 * ntdll::NtRemoveIoCompletion(). So I'd assume the SleepEx (or maybe
440 * just Sleep(0) would be enough?) would release whatever
441 * mutex/critical-section the ntdll call is waiting on.
443 * Someone got to verify this on Win-NT 4.0, 2000."
454 if( -1 == getsockopt(sockfd
, SOL_SOCKET
, SO_ERROR
,
455 (void *)&err
, &errSize
))
456 err
= Curl_sockerrno();
459 /* Always returns this error, bug in CE? */
460 if(WSAENOPROTOOPT
==err
)
464 if ((0 == err
) || (EISCONN
== err
))
465 /* we are connected, awesome! */
468 /* This wasn't a successful connect */
475 *error
= Curl_sockerrno();
480 CURLcode
Curl_store_ip_addr(struct connectdata
*conn
)
483 Curl_printable_address(conn
->ip_addr
, addrbuf
, sizeof(addrbuf
));
485 /* save the string */
486 Curl_safefree(conn
->ip_addr_str
);
487 conn
->ip_addr_str
= strdup(addrbuf
);
488 if(!conn
->ip_addr_str
)
489 return CURLE_OUT_OF_MEMORY
; /* FAIL */
492 if(conn
->ip_addr
->ai_family
== PF_INET6
)
493 conn
->bits
.ipv6
= TRUE
;
499 /* Used within the multi interface. Try next IP address, return TRUE if no
500 more address exists */
501 static bool trynextip(struct connectdata
*conn
,
505 curl_socket_t sockfd
;
508 /* first close the failed socket */
509 sclose(conn
->sock
[sockindex
]);
510 conn
->sock
[sockindex
] = CURL_SOCKET_BAD
;
513 if(sockindex
!= FIRSTSOCKET
)
514 return TRUE
; /* no next */
516 /* try the next address */
517 ai
= conn
->ip_addr
->ai_next
;
520 sockfd
= singleipconnect(conn
, ai
, 0L, connected
);
521 if(sockfd
!= CURL_SOCKET_BAD
) {
522 /* store the new socket descriptor */
523 conn
->sock
[sockindex
] = sockfd
;
526 Curl_store_ip_addr(conn
);
535 * Curl_is_connected() is used from the multi interface to check if the
536 * firstsocket has connected.
539 CURLcode
Curl_is_connected(struct connectdata
*conn
,
544 struct SessionHandle
*data
= conn
->data
;
545 CURLcode code
= CURLE_OK
;
546 curl_socket_t sockfd
= conn
->sock
[sockindex
];
547 long allow
= DEFAULT_CONNECT_TIMEOUT
;
548 long allow_total
= 0;
551 curlassert(sockindex
>= FIRSTSOCKET
&& sockindex
<= SECONDARYSOCKET
);
553 *connected
= FALSE
; /* a very negative world view is best */
555 /* Evaluate in milliseconds how much time that has passed */
556 has_passed
= Curl_tvdiff(Curl_tvnow(), data
->progress
.t_startsingle
);
558 /* subtract the most strict timeout of the ones */
559 if(data
->set
.timeout
&& data
->set
.connecttimeout
) {
560 if (data
->set
.timeout
< data
->set
.connecttimeout
)
561 allow_total
= allow
= data
->set
.timeout
*1000;
563 allow
= data
->set
.connecttimeout
*1000;
565 else if(data
->set
.timeout
) {
566 allow_total
= allow
= data
->set
.timeout
*1000;
568 else if(data
->set
.connecttimeout
) {
569 allow
= data
->set
.connecttimeout
*1000;
572 if(has_passed
> allow
) {
573 /* time-out, bail out, go home */
574 failf(data
, "Connection time-out after %ld ms", has_passed
);
575 return CURLE_OPERATION_TIMEOUTED
;
577 if(conn
->bits
.tcpconnect
) {
578 /* we are connected already! */
579 Curl_expire(data
, allow_total
);
584 Curl_expire(data
, allow
);
586 /* check for connect without timeout as we want to return immediately */
587 rc
= waitconnect(sockfd
, 0);
589 if(WAITCONN_CONNECTED
== rc
) {
591 if (verifyconnect(sockfd
, &error
)) {
592 /* we are connected, awesome! */
596 /* nope, not connected for real */
597 data
->state
.os_errno
= error
;
598 infof(data
, "Connection failed\n");
599 if(trynextip(conn
, sockindex
, connected
)) {
600 code
= CURLE_COULDNT_CONNECT
;
603 else if(WAITCONN_TIMEOUT
!= rc
) {
606 /* nope, not connected */
607 if (WAITCONN_FDSET_ERROR
== rc
) {
608 (void)verifyconnect(sockfd
, &error
);
609 data
->state
.os_errno
= error
;
610 infof(data
, "%s\n",Curl_strerror(conn
,error
));
613 infof(data
, "Connection failed\n");
615 if(trynextip(conn
, sockindex
, connected
)) {
616 error
= Curl_sockerrno();
617 data
->state
.os_errno
= error
;
618 failf(data
, "Failed connect to %s:%d; %s",
619 conn
->host
.name
, conn
->port
, Curl_strerror(conn
,error
));
620 code
= CURLE_COULDNT_CONNECT
;
624 * If the connection failed here, we should attempt to connect to the "next
625 * address" for the given host.
631 static void tcpnodelay(struct connectdata
*conn
,
632 curl_socket_t sockfd
)
635 struct SessionHandle
*data
= conn
->data
;
636 socklen_t onoff
= (socklen_t
) data
->set
.tcp_nodelay
;
637 int proto
= IPPROTO_TCP
;
639 #ifdef HAVE_GETPROTOBYNAME
640 struct protoent
*pe
= getprotobyname("tcp");
645 if(setsockopt(sockfd
, proto
, TCP_NODELAY
, (void *)&onoff
,
647 infof(data
, "Could not set TCP_NODELAY: %s\n",
648 Curl_strerror(conn
, Curl_sockerrno()));
650 infof(data
,"TCP_NODELAY set\n");
658 /* The preferred method on Mac OS X (10.2 and later) to prevent SIGPIPEs when
659 sending data to a dead peer (instead of relying on the 4th argument to send
660 being MSG_NOSIGNAL). Possibly also existing and in use on other BSD
662 static void nosigpipe(struct connectdata
*conn
,
663 curl_socket_t sockfd
)
665 struct SessionHandle
*data
= conn
->data
;
667 if(setsockopt(sockfd
, SOL_SOCKET
, SO_NOSIGPIPE
, (void *)&onoff
,
669 infof(data
, "Could not set SO_NOSIGPIPE: %s\n",
670 Curl_strerror(conn
, Curl_sockerrno()));
673 #define nosigpipe(x,y)
676 /* singleipconnect() connects to the given IP only, and it may return without
677 having connected if used from the multi interface. */
679 singleipconnect(struct connectdata
*conn
,
680 const Curl_addrinfo
*ai
,
688 struct SessionHandle
*data
= conn
->data
;
689 curl_socket_t sockfd
;
692 sockfd
= socket(ai
->ai_family
, conn
->socktype
, ai
->ai_protocol
);
693 if (sockfd
== CURL_SOCKET_BAD
)
694 return CURL_SOCKET_BAD
;
696 *connected
= FALSE
; /* default is not connected */
698 Curl_printable_address(ai
, addr_buf
, sizeof(addr_buf
));
699 infof(data
, " Trying %s... ", addr_buf
);
701 if(data
->set
.tcp_nodelay
)
702 tcpnodelay(conn
, sockfd
);
704 nosigpipe(conn
, sockfd
);
706 if(data
->set
.fsockopt
) {
707 /* activate callback for setting socket options */
708 error
= data
->set
.fsockopt(data
->set
.sockopt_client
,
712 sclose(sockfd
); /* close the socket and bail out */
713 return CURL_SOCKET_BAD
;
717 /* possibly bind the local end to an IP, interface or port */
718 res
= bindlocal(conn
, sockfd
);
720 sclose(sockfd
); /* close socket and bail out */
721 return CURL_SOCKET_BAD
;
724 /* set socket non-blocking */
725 Curl_nonblock(sockfd
, TRUE
);
727 /* Connect TCP sockets, bind UDP */
728 if(conn
->socktype
== SOCK_STREAM
)
729 rc
= connect(sockfd
, ai
->ai_addr
, ai
->ai_addrlen
);
734 error
= Curl_sockerrno();
739 #if defined(EAGAIN) && EAGAIN != EWOULDBLOCK
740 /* On some platforms EAGAIN and EWOULDBLOCK are the
741 * same value, and on others they are different, hence
746 rc
= waitconnect(sockfd
, timeout_ms
);
749 /* unknown error, fallthrough and try another address! */
750 failf(data
, "Failed to connect to %s: %s",
751 addr_buf
, Curl_strerror(conn
,error
));
752 data
->state
.os_errno
= error
;
757 /* The 'WAITCONN_TIMEOUT == rc' comes from the waitconnect(), and not from
758 connect(). We can be sure of this since connect() cannot return 1. */
759 if((WAITCONN_TIMEOUT
== rc
) &&
760 (data
->state
.used_interface
== Curl_if_multi
)) {
761 /* Timeout when running the multi interface */
765 isconnected
= verifyconnect(sockfd
, &error
);
767 if(!rc
&& isconnected
) {
768 /* we are connected, awesome! */
769 *connected
= TRUE
; /* this is a true connect */
770 infof(data
, "connected\n");
773 else if(WAITCONN_TIMEOUT
== rc
)
774 infof(data
, "Timeout\n");
776 data
->state
.os_errno
= error
;
777 infof(data
, "%s\n", Curl_strerror(conn
, error
));
780 /* connect failed or timed out */
783 return CURL_SOCKET_BAD
;
787 * TCP connect to the given host with timeout, proxy or remote doesn't matter.
788 * There might be more than one IP address to try out. Fill in the passed
789 * pointer with the connected socket.
792 CURLcode
Curl_connecthost(struct connectdata
*conn
, /* context */
793 const struct Curl_dns_entry
*remotehost
, /* use this one */
794 curl_socket_t
*sockconn
, /* the connected socket */
795 Curl_addrinfo
**addr
, /* the one we used */
796 bool *connected
) /* really connected? */
798 struct SessionHandle
*data
= conn
->data
;
799 curl_socket_t sockfd
= CURL_SOCKET_BAD
;
803 Curl_addrinfo
*curr_addr
;
805 struct timeval after
;
806 struct timeval before
= Curl_tvnow();
808 /*************************************************************
809 * Figure out what maximum time we have left
810 *************************************************************/
811 long timeout_ms
= DEFAULT_CONNECT_TIMEOUT
;
812 long timeout_per_addr
;
814 *connected
= FALSE
; /* default to not connected */
816 if(data
->set
.timeout
|| data
->set
.connecttimeout
) {
819 /* Evaluate in milliseconds how much time that has passed */
820 has_passed
= Curl_tvdiff(Curl_tvnow(), data
->progress
.t_startsingle
);
823 #define min(a, b) ((a) < (b) ? (a) : (b))
826 /* get the most strict timeout of the ones converted to milliseconds */
827 if(data
->set
.timeout
&& data
->set
.connecttimeout
) {
828 if (data
->set
.timeout
< data
->set
.connecttimeout
)
829 timeout_ms
= data
->set
.timeout
*1000;
831 timeout_ms
= data
->set
.connecttimeout
*1000;
833 else if(data
->set
.timeout
)
834 timeout_ms
= data
->set
.timeout
*1000;
836 timeout_ms
= data
->set
.connecttimeout
*1000;
838 /* subtract the passed time */
839 timeout_ms
-= has_passed
;
842 /* a precaution, no need to continue if time already is up */
843 failf(data
, "Connection time-out");
844 return CURLE_OPERATION_TIMEOUTED
;
847 Curl_expire(data
, timeout_ms
);
849 /* Max time for each address */
850 num_addr
= Curl_num_addresses(remotehost
->addr
);
851 timeout_per_addr
= timeout_ms
/ num_addr
;
853 ai
= remotehost
->addr
;
855 /* Below is the loop that attempts to connect to all IP-addresses we
856 * know for the given host. One by one until one IP succeeds.
859 if(data
->state
.used_interface
== Curl_if_multi
)
860 /* don't hang when doing multi */
861 timeout_per_addr
= 0;
864 * Connecting with a Curl_addrinfo chain
866 for (curr_addr
= ai
, aliasindex
=0; curr_addr
;
867 curr_addr
= curr_addr
->ai_next
, aliasindex
++) {
869 /* start connecting to the IP curr_addr points to */
870 sockfd
= singleipconnect(conn
, curr_addr
, timeout_per_addr
, connected
);
872 if(sockfd
!= CURL_SOCKET_BAD
)
875 /* get a new timeout for next attempt */
876 after
= Curl_tvnow();
877 timeout_ms
-= Curl_tvdiff(after
, before
);
879 failf(data
, "connect() timed out!");
880 return CURLE_OPERATION_TIMEOUTED
;
883 } /* end of connect-to-each-address loop */
885 if (sockfd
== CURL_SOCKET_BAD
) {
886 /* no good connect was made */
887 *sockconn
= CURL_SOCKET_BAD
;
888 failf(data
, "couldn't connect to host");
889 return CURLE_COULDNT_CONNECT
;
892 /* leave the socket in non-blocking mode */
894 /* store the address we use */
898 /* allow NULL-pointers to get passed in */
900 *sockconn
= sockfd
; /* the socket descriptor we've connected */
902 data
->info
.numconnects
++; /* to track the number of connections made */