00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "setup.h"
00025
00026 #ifndef WIN32
00027
00028 #ifdef HAVE_SYS_TIME_H
00029 #include <sys/time.h>
00030 #endif
00031 #ifdef HAVE_SYS_SOCKET_H
00032 #include <sys/socket.h>
00033 #endif
00034 #ifdef HAVE_NETINET_IN_H
00035 #include <netinet/in.h>
00036 #endif
00037 #ifdef HAVE_NETINET_TCP_H
00038 #include <netinet/tcp.h>
00039 #endif
00040 #ifdef HAVE_SYS_IOCTL_H
00041 #include <sys/ioctl.h>
00042 #endif
00043 #ifdef HAVE_UNISTD_H
00044 #include <unistd.h>
00045 #endif
00046 #ifdef HAVE_NETDB_H
00047 #include <netdb.h>
00048 #endif
00049 #ifdef HAVE_FCNTL_H
00050 #include <fcntl.h>
00051 #endif
00052 #ifdef HAVE_NETINET_IN_H
00053 #include <netinet/in.h>
00054 #endif
00055 #ifdef HAVE_ARPA_INET_H
00056 #include <arpa/inet.h>
00057 #endif
00058 #ifdef HAVE_STDLIB_H
00059 #include <stdlib.h>
00060 #endif
00061
00062 #if (defined(HAVE_FIONBIO) && defined(NETWARE))
00063 #include <sys/filio.h>
00064 #endif
00065 #ifdef NETWARE
00066 #ifndef __NOVELL_LIBC__
00067 NETDB_DEFINE_CONTEXT
00068 #endif
00069 #undef in_addr_t
00070 #define in_addr_t unsigned long
00071 #endif
00072 #ifdef VMS
00073 #include <in.h>
00074 #include <inet.h>
00075 #endif
00076
00077 #endif
00078
00079 #include <stdio.h>
00080 #include <errno.h>
00081 #include <string.h>
00082
00083 #include "urldata.h"
00084 #include "sendf.h"
00085 #include "if2ip.h"
00086 #include "strerror.h"
00087 #include "connect.h"
00088 #include "memory.h"
00089 #include "select.h"
00090 #include "url.h"
00091 #include "multiif.h"
00092 #include "sockaddr.h"
00093 #include "inet_ntop.h"
00094 #include "inet_pton.h"
00095
00096
00097 #include "memdebug.h"
00098
00099 static bool verifyconnect(curl_socket_t sockfd, int *error);
00100
00101 static curl_socket_t
00102 singleipconnect(struct connectdata *conn,
00103 const Curl_addrinfo *ai,
00104 long timeout_ms,
00105 bool *connected);
00106
00107
00108
00109
00110
00111
00112 int Curl_nonblock(curl_socket_t sockfd,
00113 int nonblock )
00114 {
00115 #undef SETBLOCK
00116 #define SETBLOCK 0
00117 #ifdef HAVE_O_NONBLOCK
00118
00119 int flags;
00120
00121 flags = fcntl(sockfd, F_GETFL, 0);
00122 if (FALSE != nonblock)
00123 return fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
00124 else
00125 return fcntl(sockfd, F_SETFL, flags & (~O_NONBLOCK));
00126 #undef SETBLOCK
00127 #define SETBLOCK 1
00128 #endif
00129
00130 #if defined(HAVE_FIONBIO) && (SETBLOCK == 0)
00131
00132 int flags;
00133
00134 flags = nonblock;
00135 return ioctl(sockfd, FIONBIO, &flags);
00136 #undef SETBLOCK
00137 #define SETBLOCK 2
00138 #endif
00139
00140 #if defined(HAVE_IOCTLSOCKET) && (SETBLOCK == 0)
00141
00142 unsigned long flags;
00143 flags = nonblock;
00144
00145 return ioctlsocket(sockfd, FIONBIO, &flags);
00146 #undef SETBLOCK
00147 #define SETBLOCK 3
00148 #endif
00149
00150 #if defined(HAVE_IOCTLSOCKET_CASE) && (SETBLOCK == 0)
00151
00152 return IoctlSocket(sockfd, FIONBIO, (long)nonblock);
00153 #undef SETBLOCK
00154 #define SETBLOCK 4
00155 #endif
00156
00157 #if defined(HAVE_SO_NONBLOCK) && (SETBLOCK == 0)
00158
00159 long b = nonblock ? 1 : 0;
00160 return setsockopt(sockfd, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b));
00161 #undef SETBLOCK
00162 #define SETBLOCK 5
00163 #endif
00164
00165 #ifdef HAVE_DISABLED_NONBLOCKING
00166 return 0;
00167 #undef SETBLOCK
00168 #define SETBLOCK 6
00169 #endif
00170
00171 #if (SETBLOCK == 0)
00172 #error "no non-blocking method was found/used/set"
00173 #endif
00174 }
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185 #define WAITCONN_CONNECTED 0
00186 #define WAITCONN_SELECT_ERROR -1
00187 #define WAITCONN_TIMEOUT 1
00188 #define WAITCONN_FDSET_ERROR 2
00189
00190 static
00191 int waitconnect(curl_socket_t sockfd,
00192 long timeout_msec)
00193 {
00194 int rc;
00195 #ifdef mpeix
00196
00197
00198
00199 (void)verifyconnect(sockfd, NULL);
00200 #endif
00201
00202
00203 rc = Curl_socket_ready(CURL_SOCKET_BAD, sockfd, (int)timeout_msec);
00204 if(-1 == rc)
00205
00206 return WAITCONN_SELECT_ERROR;
00207
00208 else if(0 == rc)
00209
00210 return WAITCONN_TIMEOUT;
00211
00212 if(rc & CURL_CSELECT_ERR)
00213
00214 return WAITCONN_FDSET_ERROR;
00215
00216
00217 return WAITCONN_CONNECTED;
00218 }
00219
00220 static CURLcode bindlocal(struct connectdata *conn,
00221 curl_socket_t sockfd)
00222 {
00223 #ifdef ENABLE_IPV6
00224 char ipv6_addr[16];
00225 #endif
00226 struct SessionHandle *data = conn->data;
00227 struct sockaddr_in me;
00228 struct sockaddr *sock = NULL;
00229 socklen_t socksize;
00230 unsigned short port = data->set.localport;
00231
00232
00233 int portnum = data->set.localportrange;
00234
00235
00236
00237
00238 if (data->set.device && (strlen(data->set.device)<255) ) {
00239 struct Curl_dns_entry *h=NULL;
00240 char myhost[256] = "";
00241 in_addr_t in;
00242 int rc;
00243 bool was_iface = FALSE;
00244 int in6 = -1;
00245
00246
00247 in=inet_addr(data->set.device);
00248
00249 if((in == CURL_INADDR_NONE) &&
00250 Curl_if2ip(data->set.device, myhost, sizeof(myhost))) {
00251
00252
00253
00254 rc = Curl_resolv(conn, myhost, 0, &h);
00255 if(rc == CURLRESOLV_PENDING)
00256 (void)Curl_wait_for_resolv(conn, &h);
00257
00258 if(h) {
00259 was_iface = TRUE;
00260 Curl_resolv_unlock(data, h);
00261 }
00262 }
00263
00264 if(!was_iface) {
00265
00266
00267
00268
00269 rc = Curl_resolv(conn, data->set.device, 0, &h);
00270 if(rc == CURLRESOLV_PENDING)
00271 (void)Curl_wait_for_resolv(conn, &h);
00272
00273 if(h) {
00274 if(in == CURL_INADDR_NONE)
00275
00276 Curl_inet_ntop(h->addr->ai_addr->sa_family,
00277 &((struct sockaddr_in*)h->addr->ai_addr)->sin_addr,
00278 myhost, sizeof myhost);
00279 else
00280
00281 strcpy(myhost, data->set.device);
00282 Curl_resolv_unlock(data, h);
00283 }
00284 }
00285
00286 if(! *myhost) {
00287
00288
00289
00290
00291
00292
00293 failf(data, "Couldn't bind to '%s'", data->set.device);
00294 return CURLE_HTTP_PORT_FAILED;
00295 }
00296
00297 infof(data, "Bind local address to %s\n", myhost);
00298
00299 #ifdef SO_BINDTODEVICE
00300
00301
00302
00303
00304
00305
00306
00307
00308 if (was_iface) {
00309
00310
00311
00312 if (setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE,
00313 data->set.device, strlen(data->set.device)+1) != 0) {
00314
00315
00316 infof(data, "SO_BINDTODEVICE %s failed\n",
00317 data->set.device);
00318
00319
00320 }
00321 }
00322 #endif
00323
00324 in=inet_addr(myhost);
00325
00326 #ifdef ENABLE_IPV6
00327 in6 = Curl_inet_pton (AF_INET6, myhost, (void *)&ipv6_addr);
00328 #endif
00329 if (CURL_INADDR_NONE == in && -1 == in6) {
00330 failf(data,"couldn't find my own IP address (%s)", myhost);
00331 return CURLE_HTTP_PORT_FAILED;
00332 }
00333
00334 if ( h ) {
00335 Curl_addrinfo *addr = h->addr;
00336 sock = addr->ai_addr;
00337 socksize = addr->ai_addrlen;
00338 }
00339 else
00340 return CURLE_HTTP_PORT_FAILED;
00341
00342 }
00343 else if(port) {
00344
00345
00346 memset(&me, 0, sizeof(struct sockaddr));
00347 me.sin_family = AF_INET;
00348 me.sin_addr.s_addr = INADDR_ANY;
00349
00350 sock = (struct sockaddr *)&me;
00351 socksize = sizeof(struct sockaddr);
00352
00353 }
00354 else
00355
00356 return CURLE_OK;
00357
00358 do {
00359
00360
00361 if(sock->sa_family == AF_INET)
00362 ((struct sockaddr_in *)sock)->sin_port = htons(port);
00363 #ifdef ENABLE_IPV6
00364 else
00365 ((struct sockaddr_in6 *)sock)->sin6_port = htons(port);
00366 #endif
00367
00368 if( bind(sockfd, sock, socksize) >= 0) {
00369
00370 struct Curl_sockaddr_storage add;
00371 socklen_t size;
00372
00373 size = sizeof(add);
00374 if(getsockname(sockfd, (struct sockaddr *) &add, &size) < 0) {
00375 failf(data, "getsockname() failed");
00376 return CURLE_HTTP_PORT_FAILED;
00377 }
00378
00379 if(((struct sockaddr *)&add)->sa_family == AF_INET)
00380 port = ntohs(((struct sockaddr_in *)&add)->sin_port);
00381 #ifdef ENABLE_IPV6
00382 else
00383 port = ntohs(((struct sockaddr_in6 *)&add)->sin6_port);
00384 #endif
00385 infof(data, "Local port: %d\n", port);
00386 return CURLE_OK;
00387 }
00388 if(--portnum > 0) {
00389 infof(data, "Bind to local port %d failed, trying next\n", port);
00390 port++;
00391 }
00392 else
00393 break;
00394 } while(1);
00395
00396 data->state.os_errno = SOCKERRNO;
00397 failf(data, "bind failure: %s",
00398 Curl_strerror(conn, data->state.os_errno));
00399 return CURLE_HTTP_PORT_FAILED;
00400
00401 }
00402
00403
00404
00405
00406 static bool verifyconnect(curl_socket_t sockfd, int *error)
00407 {
00408 bool rc = TRUE;
00409 #ifdef SO_ERROR
00410 int err = 0;
00411 socklen_t errSize = sizeof(err);
00412
00413 #ifdef WIN32
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430 #ifdef _WIN32_WCE
00431 Sleep(0);
00432 #else
00433 SleepEx(0, FALSE);
00434 #endif
00435
00436 #endif
00437
00438 if (0 != getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *)&err, &errSize))
00439 err = SOCKERRNO;
00440 #ifdef _WIN32_WCE
00441
00442 if (WSAENOPROTOOPT == err) {
00443 SET_SOCKERRNO(0);
00444 err = 0;
00445 }
00446 #endif
00447 if ((0 == err) || (EISCONN == err))
00448
00449 rc = TRUE;
00450 else
00451
00452 rc = FALSE;
00453 if (error)
00454 *error = err;
00455 #else
00456 (void)sockfd;
00457 if (error)
00458 *error = SOCKERRNO;
00459 #endif
00460 return rc;
00461 }
00462
00463 CURLcode Curl_store_ip_addr(struct connectdata *conn)
00464 {
00465 char addrbuf[256];
00466 Curl_printable_address(conn->ip_addr, addrbuf, sizeof(addrbuf));
00467
00468
00469 Curl_safefree(conn->ip_addr_str);
00470 conn->ip_addr_str = strdup(addrbuf);
00471 if(!conn->ip_addr_str)
00472 return CURLE_OUT_OF_MEMORY;
00473
00474 #ifdef PF_INET6
00475 if(conn->ip_addr->ai_family == PF_INET6)
00476 conn->bits.ipv6 = TRUE;
00477 #endif
00478
00479 return CURLE_OK;
00480 }
00481
00482
00483
00484 static bool trynextip(struct connectdata *conn,
00485 int sockindex,
00486 bool *connected)
00487 {
00488 curl_socket_t sockfd;
00489 Curl_addrinfo *ai;
00490
00491
00492 sclose(conn->sock[sockindex]);
00493 conn->sock[sockindex] = CURL_SOCKET_BAD;
00494 *connected = FALSE;
00495
00496 if(sockindex != FIRSTSOCKET)
00497 return TRUE;
00498
00499
00500 ai = conn->ip_addr->ai_next;
00501
00502 while (ai) {
00503 sockfd = singleipconnect(conn, ai, 0L, connected);
00504 if(sockfd != CURL_SOCKET_BAD) {
00505
00506 conn->sock[sockindex] = sockfd;
00507 conn->ip_addr = ai;
00508
00509 Curl_store_ip_addr(conn);
00510 return FALSE;
00511 }
00512 ai = ai->ai_next;
00513 }
00514 return TRUE;
00515 }
00516
00517
00518
00519
00520
00521
00522 CURLcode Curl_is_connected(struct connectdata *conn,
00523 int sockindex,
00524 bool *connected)
00525 {
00526 int rc;
00527 struct SessionHandle *data = conn->data;
00528 CURLcode code = CURLE_OK;
00529 curl_socket_t sockfd = conn->sock[sockindex];
00530 long allow = DEFAULT_CONNECT_TIMEOUT;
00531 long allow_total = 0;
00532 long has_passed;
00533
00534 DEBUGASSERT(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET);
00535
00536 *connected = FALSE;
00537
00538
00539 has_passed = Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle);
00540
00541
00542 if(data->set.timeout && data->set.connecttimeout) {
00543 if (data->set.timeout < data->set.connecttimeout)
00544 allow_total = allow = data->set.timeout;
00545 else
00546 allow = data->set.connecttimeout;
00547 }
00548 else if(data->set.timeout) {
00549 allow_total = allow = data->set.timeout;
00550 }
00551 else if(data->set.connecttimeout) {
00552 allow = data->set.connecttimeout;
00553 }
00554
00555 if(has_passed > allow ) {
00556
00557 failf(data, "Connection time-out after %ld ms", has_passed);
00558 return CURLE_OPERATION_TIMEOUTED;
00559 }
00560 if(conn->bits.tcpconnect) {
00561
00562 Curl_expire(data, allow_total);
00563 *connected = TRUE;
00564 return CURLE_OK;
00565 }
00566
00567 Curl_expire(data, allow);
00568
00569
00570 rc = waitconnect(sockfd, 0);
00571
00572 if(WAITCONN_CONNECTED == rc) {
00573 int error;
00574 if (verifyconnect(sockfd, &error)) {
00575
00576 *connected = TRUE;
00577 return CURLE_OK;
00578 }
00579
00580 data->state.os_errno = error;
00581 infof(data, "Connection failed\n");
00582 if(trynextip(conn, sockindex, connected)) {
00583 code = CURLE_COULDNT_CONNECT;
00584 }
00585 }
00586 else if(WAITCONN_TIMEOUT != rc) {
00587 int error = 0;
00588
00589
00590 if (WAITCONN_FDSET_ERROR == rc) {
00591 (void)verifyconnect(sockfd, &error);
00592 data->state.os_errno = error;
00593 infof(data, "%s\n",Curl_strerror(conn,error));
00594 }
00595 else
00596 infof(data, "Connection failed\n");
00597
00598 if(trynextip(conn, sockindex, connected)) {
00599 error = SOCKERRNO;
00600 data->state.os_errno = error;
00601 failf(data, "Failed connect to %s:%d; %s",
00602 conn->host.name, conn->port, Curl_strerror(conn,error));
00603 code = CURLE_COULDNT_CONNECT;
00604 }
00605 }
00606
00607
00608
00609
00610
00611 return code;
00612 }
00613
00614 static void tcpnodelay(struct connectdata *conn,
00615 curl_socket_t sockfd)
00616 {
00617 #ifdef TCP_NODELAY
00618 struct SessionHandle *data= conn->data;
00619 socklen_t onoff = (socklen_t) data->set.tcp_nodelay;
00620 int proto = IPPROTO_TCP;
00621
00622 #ifdef HAVE_GETPROTOBYNAME
00623 struct protoent *pe = getprotobyname("tcp");
00624 if (pe)
00625 proto = pe->p_proto;
00626 #endif
00627
00628 if(setsockopt(sockfd, proto, TCP_NODELAY, (void *)&onoff,
00629 sizeof(onoff)) < 0)
00630 infof(data, "Could not set TCP_NODELAY: %s\n",
00631 Curl_strerror(conn, SOCKERRNO));
00632 else
00633 infof(data,"TCP_NODELAY set\n");
00634 #else
00635 (void)conn;
00636 (void)sockfd;
00637 #endif
00638 }
00639
00640 #ifdef SO_NOSIGPIPE
00641
00642
00643
00644
00645 static void nosigpipe(struct connectdata *conn,
00646 curl_socket_t sockfd)
00647 {
00648 struct SessionHandle *data= conn->data;
00649 int onoff = 1;
00650 if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff,
00651 sizeof(onoff)) < 0)
00652 infof(data, "Could not set SO_NOSIGPIPE: %s\n",
00653 Curl_strerror(conn, SOCKERRNO));
00654 }
00655 #else
00656 #define nosigpipe(x,y)
00657 #endif
00658
00659
00660
00661 static curl_socket_t
00662 singleipconnect(struct connectdata *conn,
00663 const Curl_addrinfo *ai,
00664 long timeout_ms,
00665 bool *connected)
00666 {
00667 char addr_buf[128];
00668 int rc;
00669 int error;
00670 bool isconnected;
00671 struct SessionHandle *data = conn->data;
00672 curl_socket_t sockfd;
00673 CURLcode res;
00674
00675 sockfd = socket(ai->ai_family, conn->socktype, ai->ai_protocol);
00676 if (sockfd == CURL_SOCKET_BAD)
00677 return CURL_SOCKET_BAD;
00678
00679 *connected = FALSE;
00680
00681 Curl_printable_address(ai, addr_buf, sizeof(addr_buf));
00682 infof(data, " Trying %s... ", addr_buf);
00683
00684 if(data->set.tcp_nodelay)
00685 tcpnodelay(conn, sockfd);
00686
00687 nosigpipe(conn, sockfd);
00688
00689 if(data->set.fsockopt) {
00690
00691 error = data->set.fsockopt(data->set.sockopt_client,
00692 sockfd,
00693 CURLSOCKTYPE_IPCXN);
00694 if (error) {
00695 sclose(sockfd);
00696 return CURL_SOCKET_BAD;
00697 }
00698 }
00699
00700
00701 res = bindlocal(conn, sockfd);
00702 if(res) {
00703 sclose(sockfd);
00704 return CURL_SOCKET_BAD;
00705 }
00706
00707
00708 Curl_nonblock(sockfd, TRUE);
00709
00710
00711 if(conn->socktype == SOCK_STREAM)
00712 rc = connect(sockfd, ai->ai_addr, ai->ai_addrlen);
00713 else
00714 rc = 0;
00715
00716 if(-1 == rc) {
00717 error = SOCKERRNO;
00718
00719 switch (error) {
00720 case EINPROGRESS:
00721 case EWOULDBLOCK:
00722 #if defined(EAGAIN) && EAGAIN != EWOULDBLOCK
00723
00724
00725
00726
00727 case EAGAIN:
00728 #endif
00729 rc = waitconnect(sockfd, timeout_ms);
00730 break;
00731 default:
00732
00733 failf(data, "Failed to connect to %s: %s",
00734 addr_buf, Curl_strerror(conn,error));
00735 data->state.os_errno = error;
00736 break;
00737 }
00738 }
00739
00740
00741
00742 if((WAITCONN_TIMEOUT == rc) &&
00743 (data->state.used_interface == Curl_if_multi)) {
00744
00745 return sockfd;
00746 }
00747
00748 isconnected = verifyconnect(sockfd, &error);
00749
00750 if(!rc && isconnected) {
00751
00752 *connected = TRUE;
00753 infof(data, "connected\n");
00754 return sockfd;
00755 }
00756 else if(WAITCONN_TIMEOUT == rc)
00757 infof(data, "Timeout\n");
00758 else {
00759 data->state.os_errno = error;
00760 infof(data, "%s\n", Curl_strerror(conn, error));
00761 }
00762
00763
00764 sclose(sockfd);
00765
00766 return CURL_SOCKET_BAD;
00767 }
00768
00769
00770
00771
00772
00773
00774
00775 CURLcode Curl_connecthost(struct connectdata *conn,
00776 const struct Curl_dns_entry *remotehost,
00777 curl_socket_t *sockconn,
00778 Curl_addrinfo **addr,
00779 bool *connected)
00780 {
00781 struct SessionHandle *data = conn->data;
00782 curl_socket_t sockfd = CURL_SOCKET_BAD;
00783 int aliasindex;
00784 int num_addr;
00785 Curl_addrinfo *ai;
00786 Curl_addrinfo *curr_addr;
00787 int timeout_set = 0;
00788
00789 struct timeval after;
00790 struct timeval before = Curl_tvnow();
00791
00792
00793
00794
00795 long timeout_ms;
00796 long timeout_per_addr;
00797
00798 *connected = FALSE;
00799
00800
00801
00802 if (data->set.timeout > 0)
00803 timeout_set += 1;
00804 if (data->set.connecttimeout > 0)
00805 timeout_set += 2;
00806
00807 switch (timeout_set) {
00808 case 1:
00809 timeout_ms = data->set.timeout;
00810 break;
00811 case 2:
00812 timeout_ms = data->set.connecttimeout;
00813 break;
00814 case 3:
00815 if (data->set.timeout < data->set.connecttimeout)
00816 timeout_ms = data->set.timeout;
00817 else
00818 timeout_ms = data->set.connecttimeout;
00819 break;
00820 default:
00821 timeout_ms = DEFAULT_CONNECT_TIMEOUT;
00822 break;
00823 }
00824
00825 if (timeout_set > 0) {
00826
00827 timeout_ms -= Curl_tvdiff(before, data->progress.t_startsingle);
00828 if(timeout_ms < 0) {
00829
00830 failf(data, "Connection time-out");
00831 return CURLE_OPERATION_TIMEOUTED;
00832 }
00833 }
00834 Curl_expire(data, timeout_ms);
00835
00836
00837 num_addr = Curl_num_addresses(remotehost->addr);
00838 timeout_per_addr = timeout_ms / num_addr;
00839
00840 ai = remotehost->addr;
00841
00842
00843
00844
00845
00846 if(data->state.used_interface == Curl_if_multi)
00847
00848 timeout_per_addr = 0;
00849
00850
00851
00852
00853 for (curr_addr = ai, aliasindex=0; curr_addr;
00854 curr_addr = curr_addr->ai_next, aliasindex++) {
00855
00856
00857 sockfd = singleipconnect(conn, curr_addr, timeout_per_addr, connected);
00858
00859 if(sockfd != CURL_SOCKET_BAD)
00860 break;
00861
00862
00863 after = Curl_tvnow();
00864 timeout_ms -= Curl_tvdiff(after, before);
00865 if(timeout_ms < 0) {
00866 failf(data, "connect() timed out!");
00867 return CURLE_OPERATION_TIMEOUTED;
00868 }
00869 before = after;
00870 }
00871
00872 if (sockfd == CURL_SOCKET_BAD) {
00873
00874 *sockconn = CURL_SOCKET_BAD;
00875 failf(data, "couldn't connect to host");
00876 return CURLE_COULDNT_CONNECT;
00877 }
00878
00879
00880
00881
00882 if(addr)
00883 *addr = curr_addr;
00884
00885
00886 if(sockconn)
00887 *sockconn = sockfd;
00888
00889 data->info.numconnects++;
00890
00891 return CURLE_OK;
00892 }