#include "setup.h"
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef HAVE_SYS_UN_H
#include <sys/un.h>
#endif
#ifdef HAVE_NETINET_TCP_H
#include <netinet/tcp.h>
#endif
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#if (defined(HAVE_IOCTL_FIONBIO) && defined(NETWARE))
#include <sys/filio.h>
#endif
#ifdef NETWARE
#undef in_addr_t
#define in_addr_t unsigned long
#endif
#ifdef __VMS
#include <in.h>
#include <inet.h>
#endif
#include <stdio.h>
#include <errno.h>
#include <string.h>
#define _MPRINTF_REPLACE
#include <curl/mprintf.h>
#include "urldata.h"
#include "sendf.h"
#include "if2ip.h"
#include "strerror.h"
#include "connect.h"
#include "curl_memory.h"
#include "select.h"
#include "url.h"
#include "multiif.h"
#include "sockaddr.h"
#include "inet_ntop.h"
#include "inet_pton.h"
#include "sslgen.h"
#include "progress.h"
#include "memdebug.h"
#ifdef __SYMBIAN32__
#undef SO_NOSIGPIPE
#endif
struct Curl_sockaddr_ex {
int family;
int socktype;
int protocol;
unsigned int addrlen;
union {
struct sockaddr addr;
struct Curl_sockaddr_storage buff;
} _sa_ex_u;
};
#define sa_addr _sa_ex_u.addr
static bool verifyconnect(curl_socket_t sockfd, int *error);
static CURLcode
singleipconnect(struct connectdata *conn,
const Curl_addrinfo *ai,
long timeout_ms,
curl_socket_t *sock,
bool *connected);
long Curl_timeleft(struct SessionHandle *data,
struct timeval *nowp,
bool duringconnect)
{
int timeout_set = 0;
long timeout_ms = duringconnect?DEFAULT_CONNECT_TIMEOUT:0;
struct timeval now;
if(data->set.timeout > 0)
timeout_set |= 1;
if(duringconnect && (data->set.connecttimeout > 0))
timeout_set |= 2;
switch (timeout_set) {
case 1:
timeout_ms = data->set.timeout;
break;
case 2:
timeout_ms = data->set.connecttimeout;
break;
case 3:
if(data->set.timeout < data->set.connecttimeout)
timeout_ms = data->set.timeout;
else
timeout_ms = data->set.connecttimeout;
break;
default:
if(!duringconnect)
return 0;
break;
}
if(!nowp) {
now = Curl_tvnow();
nowp = &now;
}
timeout_ms -= Curl_tvdiff(*nowp, data->progress.t_startsingle);
if(!timeout_ms)
return -1;
return timeout_ms;
}
#define WAITCONN_CONNECTED 0
#define WAITCONN_SELECT_ERROR -1
#define WAITCONN_TIMEOUT 1
#define WAITCONN_FDSET_ERROR 2
#define WAITCONN_ABORTED 3
static
int waitconnect(struct connectdata *conn,
curl_socket_t sockfd,
long timeout_msec)
{
int rc;
#ifdef mpeix
(void)verifyconnect(sockfd, NULL);
#endif
for(;;) {
rc = Curl_socket_ready(CURL_SOCKET_BAD, sockfd, (int)(timeout_msec>1000?
1000:timeout_msec));
if(Curl_pgrsUpdate(conn))
return WAITCONN_ABORTED;
if(-1 == rc)
return WAITCONN_SELECT_ERROR;
else if(0 == rc) {
timeout_msec -= 1000;
if(timeout_msec <= 0)
return WAITCONN_TIMEOUT;
continue;
}
if(rc & CURL_CSELECT_ERR)
return WAITCONN_FDSET_ERROR;
break;
}
return WAITCONN_CONNECTED;
}
static CURLcode bindlocal(struct connectdata *conn,
curl_socket_t sockfd, int af)
{
struct SessionHandle *data = conn->data;
struct Curl_sockaddr_storage sa;
struct sockaddr *sock = (struct sockaddr *)&sa;
curl_socklen_t sizeof_sa = 0;
struct sockaddr_in *si4 = (struct sockaddr_in *)&sa;
#ifdef ENABLE_IPV6
struct sockaddr_in6 *si6 = (struct sockaddr_in6 *)&sa;
#endif
struct Curl_dns_entry *h=NULL;
unsigned short port = data->set.localport;
int portnum = data->set.localportrange;
const char *dev = data->set.str[STRING_DEVICE];
int error;
char myhost[256] = "";
int done = 0;
if ( !dev && !port )
return CURLE_OK;
memset(&sa, 0, sizeof(struct Curl_sockaddr_storage));
if(dev && (strlen(dev)<255) ) {
if(Curl_if2ip(af, dev, myhost, sizeof(myhost))) {
infof(data, "Local Interface %s is ip %s using address family %i\n",
dev, myhost, af);
done = 1;
#ifdef SO_BINDTODEVICE
if(setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE,
dev, (curl_socklen_t)strlen(dev)+1) != 0) {
error = SOCKERRNO;
infof(data, "SO_BINDTODEVICE %s failed with errno %d: %s;"
" will do regular bind\n",
dev, error, Curl_strerror(conn, error));
}
#endif
}
else {
long ipver = conn->ip_version;
int rc;
if (af == AF_INET)
conn->ip_version = CURL_IPRESOLVE_V4;
#ifdef ENABLE_IPV6
else if (af == AF_INET6)
conn->ip_version = CURL_IPRESOLVE_V6;
#endif
rc = Curl_resolv(conn, dev, 0, &h);
if(rc == CURLRESOLV_PENDING)
(void)Curl_wait_for_resolv(conn, &h);
conn->ip_version = ipver;
if(h) {
Curl_printable_address(h->addr, myhost, sizeof(myhost));
infof(data, "Name '%s' family %i resolved to '%s' family %i\n",
dev, af, myhost, h->addr->ai_family);
Curl_resolv_unlock(data, h);
done = 1;
}
else {
done = -1;
}
}
if(done > 0) {
#ifdef ENABLE_IPV6
if((af == AF_INET6) &&
(Curl_inet_pton(AF_INET6, myhost, &si6->sin6_addr) > 0)) {
si6->sin6_family = AF_INET6;
si6->sin6_port = htons(port);
sizeof_sa = sizeof(struct sockaddr_in6);
}
else
#endif
if((af == AF_INET) &&
(Curl_inet_pton(AF_INET, myhost, &si4->sin_addr) > 0)) {
si4->sin_family = AF_INET;
si4->sin_port = htons(port);
sizeof_sa = sizeof(struct sockaddr_in);
}
}
if(done < 1) {
failf(data, "Couldn't bind to '%s'", dev);
return CURLE_INTERFACE_FAILED;
}
}
else {
#ifdef ENABLE_IPV6
if ( af == AF_INET6 ) {
si6->sin6_family = AF_INET6;
si6->sin6_port = htons(port);
sizeof_sa = sizeof(struct sockaddr_in6);
}
else
#endif
if ( af == AF_INET ) {
si4->sin_family = AF_INET;
si4->sin_port = htons(port);
sizeof_sa = sizeof(struct sockaddr_in);
}
}
for(;;) {
if( bind(sockfd, sock, sizeof_sa) >= 0) {
struct Curl_sockaddr_storage add;
curl_socklen_t size = sizeof(add);
memset(&add, 0, sizeof(struct Curl_sockaddr_storage));
if(getsockname(sockfd, (struct sockaddr *) &add, &size) < 0) {
data->state.os_errno = error = SOCKERRNO;
failf(data, "getsockname() failed with errno %d: %s",
error, Curl_strerror(conn, error));
return CURLE_INTERFACE_FAILED;
}
infof(data, "Local port: %hu\n", port);
conn->bits.bound = TRUE;
return CURLE_OK;
}
if(--portnum > 0) {
infof(data, "Bind to local port %hu failed, trying next\n", port);
port++;
if(sock->sa_family == AF_INET)
si4->sin_port = ntohs(port);
#ifdef ENABLE_IPV6
else
si6->sin6_port = ntohs(port);
#endif
}
else
break;
}
data->state.os_errno = error = SOCKERRNO;
failf(data, "bind failed with errno %d: %s",
error, Curl_strerror(conn, error));
return CURLE_INTERFACE_FAILED;
}
static bool verifyconnect(curl_socket_t sockfd, int *error)
{
bool rc = TRUE;
#ifdef SO_ERROR
int err = 0;
curl_socklen_t errSize = sizeof(err);
#ifdef WIN32
#ifdef _WIN32_WCE
Sleep(0);
#else
SleepEx(0, FALSE);
#endif
#endif
if(0 != getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *)&err, &errSize))
err = SOCKERRNO;
#ifdef _WIN32_WCE
if(WSAENOPROTOOPT == err) {
SET_SOCKERRNO(0);
err = 0;
}
#endif
#ifdef __minix
if(EBADIOCTL == err) {
SET_SOCKERRNO(0);
err = 0;
}
#endif
if((0 == err) || (EISCONN == err))
rc = TRUE;
else
rc = FALSE;
if(error)
*error = err;
#else
(void)sockfd;
if(error)
*error = SOCKERRNO;
#endif
return rc;
}
static CURLcode trynextip(struct connectdata *conn,
int sockindex,
bool *connected)
{
curl_socket_t sockfd;
Curl_addrinfo *ai;
curl_socket_t fd_to_close = conn->sock[sockindex];
conn->sock[sockindex] = CURL_SOCKET_BAD;
*connected = FALSE;
if(sockindex != FIRSTSOCKET) {
sclose(fd_to_close);
return CURLE_COULDNT_CONNECT;
}
ai = conn->ip_addr->ai_next;
while(ai) {
CURLcode res = singleipconnect(conn, ai, 0L, &sockfd, connected);
if(res)
return res;
if(sockfd != CURL_SOCKET_BAD) {
conn->sock[sockindex] = sockfd;
conn->ip_addr = ai;
sclose(fd_to_close);
return CURLE_OK;
}
ai = ai->ai_next;
}
sclose(fd_to_close);
return CURLE_COULDNT_CONNECT;
}
void Curl_persistconninfo(struct connectdata *conn)
{
memcpy(conn->data->info.conn_primary_ip, conn->primary_ip, MAX_IPADR_LEN);
memcpy(conn->data->info.conn_local_ip, conn->local_ip, MAX_IPADR_LEN);
conn->data->info.conn_primary_port = conn->primary_port;
conn->data->info.conn_local_port = conn->local_port;
}
static bool getaddressinfo(struct sockaddr* sa, char* addr,
long* port)
{
unsigned short us_port;
struct sockaddr_in* si = NULL;
#ifdef ENABLE_IPV6
struct sockaddr_in6* si6 = NULL;
#endif
#if defined(HAVE_SYS_UN_H) && defined(AF_UNIX)
struct sockaddr_un* su = NULL;
#endif
switch (sa->sa_family) {
case AF_INET:
si = (struct sockaddr_in*) sa;
if(Curl_inet_ntop(sa->sa_family, &si->sin_addr,
addr, MAX_IPADR_LEN)) {
us_port = ntohs(si->sin_port);
*port = us_port;
return TRUE;
}
break;
#ifdef ENABLE_IPV6
case AF_INET6:
si6 = (struct sockaddr_in6*)sa;
if(Curl_inet_ntop(sa->sa_family, &si6->sin6_addr,
addr, MAX_IPADR_LEN)) {
us_port = ntohs(si6->sin6_port);
*port = us_port;
return TRUE;
}
break;
#endif
#if defined(HAVE_SYS_UN_H) && defined(AF_UNIX)
case AF_UNIX:
su = (struct sockaddr_un*)sa;
snprintf(addr, MAX_IPADR_LEN, "%s", su->sun_path);
*port = 0;
return TRUE;
#endif
default:
break;
}
addr[0] = '\0';
*port = 0;
return FALSE;
}
void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
{
int error;
curl_socklen_t len;
struct Curl_sockaddr_storage ssrem;
struct Curl_sockaddr_storage ssloc;
struct SessionHandle *data = conn->data;
if(!conn->bits.reuse) {
len = sizeof(struct Curl_sockaddr_storage);
if(getpeername(sockfd, (struct sockaddr*) &ssrem, &len)) {
error = SOCKERRNO;
failf(data, "getpeername() failed with errno %d: %s",
error, Curl_strerror(conn, error));
return;
}
len = sizeof(struct Curl_sockaddr_storage);
if(getsockname(sockfd, (struct sockaddr*) &ssloc, &len)) {
error = SOCKERRNO;
failf(data, "getsockname() failed with errno %d: %s",
error, Curl_strerror(conn, error));
return;
}
if(!getaddressinfo((struct sockaddr*)&ssrem,
conn->primary_ip, &conn->primary_port)) {
error = ERRNO;
failf(data, "ssrem inet_ntop() failed with errno %d: %s",
error, Curl_strerror(conn, error));
return;
}
if(!getaddressinfo((struct sockaddr*)&ssloc,
conn->local_ip, &conn->local_port)) {
error = ERRNO;
failf(data, "ssloc inet_ntop() failed with errno %d: %s",
error, Curl_strerror(conn, error));
return;
}
}
Curl_persistconninfo(conn);
}
CURLcode Curl_is_connected(struct connectdata *conn,
int sockindex,
bool *connected)
{
int rc;
struct SessionHandle *data = conn->data;
CURLcode code = CURLE_OK;
curl_socket_t sockfd = conn->sock[sockindex];
long allow = DEFAULT_CONNECT_TIMEOUT;
int error = 0;
struct timeval now;
DEBUGASSERT(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET);
*connected = FALSE;
if(conn->bits.tcpconnect) {
*connected = TRUE;
return CURLE_OK;
}
now = Curl_tvnow();
allow = Curl_timeleft(data, &now, TRUE);
if(allow < 0) {
failf(data, "Connection time-out");
return CURLE_OPERATION_TIMEDOUT;
}
rc = waitconnect(conn, sockfd, 0);
if(WAITCONN_TIMEOUT == rc) {
if(curlx_tvdiff(now, conn->connecttime) >= conn->timeoutms_per_addr) {
infof(data, "After %ldms connect time, move on!\n",
conn->timeoutms_per_addr);
goto next;
}
return code;
}
if(WAITCONN_CONNECTED == rc) {
if(verifyconnect(sockfd, &error)) {
conn->bits.tcpconnect = TRUE;
*connected = TRUE;
Curl_pgrsTime(data, TIMER_CONNECT);
Curl_verboseconnect(conn);
Curl_updateconninfo(conn, sockfd);
return CURLE_OK;
}
}
else {
if(WAITCONN_FDSET_ERROR == rc) {
(void)verifyconnect(sockfd, &error);
infof(data, "%s\n",Curl_strerror(conn, error));
}
else
infof(data, "Connection failed\n");
}
if(error) {
data->state.os_errno = error;
SET_SOCKERRNO(error);
}
next:
code = trynextip(conn, sockindex, connected);
if(code) {
error = SOCKERRNO;
data->state.os_errno = error;
failf(data, "Failed connect to %s:%ld; %s",
conn->host.name, conn->port, Curl_strerror(conn, error));
}
return code;
}
static void tcpnodelay(struct connectdata *conn,
curl_socket_t sockfd)
{
#ifdef TCP_NODELAY
struct SessionHandle *data= conn->data;
curl_socklen_t onoff = (curl_socklen_t) data->set.tcp_nodelay;
int proto = IPPROTO_TCP;
#if 0
struct protoent *pe = getprotobyname("tcp");
if(pe)
proto = pe->p_proto;
#endif
if(setsockopt(sockfd, proto, TCP_NODELAY, (void *)&onoff,
sizeof(onoff)) < 0)
infof(data, "Could not set TCP_NODELAY: %s\n",
Curl_strerror(conn, SOCKERRNO));
else
infof(data,"TCP_NODELAY set\n");
#else
(void)conn;
(void)sockfd;
#endif
}
#ifdef SO_NOSIGPIPE
static void nosigpipe(struct connectdata *conn,
curl_socket_t sockfd)
{
struct SessionHandle *data= conn->data;
int onoff = 1;
if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff,
sizeof(onoff)) < 0)
infof(data, "Could not set SO_NOSIGPIPE: %s\n",
Curl_strerror(conn, SOCKERRNO));
}
#else
#define nosigpipe(x,y)
#endif
#ifdef WIN32
void Curl_sndbufset(curl_socket_t sockfd)
{
int val = CURL_MAX_WRITE_SIZE + 32;
int curval = 0;
int curlen = sizeof(curval);
if (getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (char *)&curval, &curlen) == 0)
if (curval > val)
return;
setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (const char *)&val, sizeof(val));
}
#endif
static CURLcode
singleipconnect(struct connectdata *conn,
const Curl_addrinfo *ai,
long timeout_ms,
curl_socket_t *sockp,
bool *connected)
{
struct Curl_sockaddr_ex addr;
int rc;
int error;
bool isconnected;
struct SessionHandle *data = conn->data;
curl_socket_t sockfd;
CURLcode res = CURLE_OK;
#if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID)
struct sockaddr_in6 * const sa6 = (void *)&addr.sa_addr;
#endif
*sockp = CURL_SOCKET_BAD;
addr.family = ai->ai_family;
addr.socktype = conn->socktype;
addr.protocol = conn->socktype==SOCK_DGRAM?IPPROTO_UDP:ai->ai_protocol;
addr.addrlen = ai->ai_addrlen;
if(addr.addrlen > sizeof(struct Curl_sockaddr_storage))
addr.addrlen = sizeof(struct Curl_sockaddr_storage);
memcpy(&addr.sa_addr, ai->ai_addr, addr.addrlen);
*connected = FALSE;
if(data->set.fopensocket)
sockfd = data->set.fopensocket(data->set.opensocket_client,
CURLSOCKTYPE_IPCXN,
(struct curl_sockaddr *)&addr);
else
sockfd = socket(addr.family, addr.socktype, addr.protocol);
if(sockfd == CURL_SOCKET_BAD)
return CURLE_OK;
#if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID)
if (conn->scope && (addr.family == AF_INET6))
sa6->sin6_scope_id = conn->scope;
#endif
if(!getaddressinfo((struct sockaddr*)&addr.sa_addr,
conn->primary_ip, &conn->primary_port)) {
error = ERRNO;
failf(data, "sa_addr inet_ntop() failed with errno %d: %s",
error, Curl_strerror(conn, error));
sclose(sockfd);
return CURLE_OK;
}
memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN);
infof(data, " Trying %s... ", conn->ip_addr_str);
Curl_persistconninfo(conn);
#ifdef ENABLE_IPV6
if(addr.family == AF_INET6)
conn->bits.ipv6 = TRUE;
#endif
if(data->set.tcp_nodelay)
tcpnodelay(conn, sockfd);
nosigpipe(conn, sockfd);
Curl_sndbufset(sockfd);
if(data->set.fsockopt) {
error = data->set.fsockopt(data->set.sockopt_client,
sockfd,
CURLSOCKTYPE_IPCXN);
if(error) {
sclose(sockfd);
return CURLE_ABORTED_BY_CALLBACK;
}
}
res = bindlocal(conn, sockfd, addr.family);
if(res) {
sclose(sockfd);
return res;
}
curlx_nonblock(sockfd, TRUE);
if(conn->socktype == SOCK_STREAM) {
rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
conn->connecttime = Curl_tvnow();
if(conn->num_addr > 1)
Curl_expire(data, conn->timeoutms_per_addr);
}
else
rc = 0;
if(-1 == rc) {
error = SOCKERRNO;
switch (error) {
case EINPROGRESS:
case EWOULDBLOCK:
#if defined(EAGAIN)
#if (EAGAIN) != (EWOULDBLOCK)
case EAGAIN:
#endif
#endif
rc = waitconnect(conn, sockfd, timeout_ms);
if(WAITCONN_ABORTED == rc) {
sclose(sockfd);
return CURLE_ABORTED_BY_CALLBACK;
}
break;
default:
failf(data, "Failed to connect to %s: %s",
conn->ip_addr_str, Curl_strerror(conn,error));
data->state.os_errno = error;
break;
}
}
if((WAITCONN_TIMEOUT == rc) &&
(data->state.used_interface == Curl_if_multi)) {
*sockp = sockfd;
return CURLE_OK;
}
isconnected = verifyconnect(sockfd, &error);
if(!rc && isconnected) {
*connected = TRUE;
infof(data, "connected\n");
Curl_updateconninfo(conn, sockfd);
*sockp = sockfd;
return CURLE_OK;
}
else if(WAITCONN_TIMEOUT == rc)
infof(data, "Timeout\n");
else {
data->state.os_errno = error;
infof(data, "%s\n", Curl_strerror(conn, error));
}
sclose(sockfd);
return CURLE_OK;
}
CURLcode Curl_connecthost(struct connectdata *conn,
const struct Curl_dns_entry *remotehost,
curl_socket_t *sockconn,
Curl_addrinfo **addr,
bool *connected)
{
struct SessionHandle *data = conn->data;
curl_socket_t sockfd = CURL_SOCKET_BAD;
int aliasindex;
Curl_addrinfo *ai;
Curl_addrinfo *curr_addr;
struct timeval after;
struct timeval before = Curl_tvnow();
long timeout_ms;
DEBUGASSERT(sockconn);
*connected = FALSE;
timeout_ms = Curl_timeleft(data, &before, TRUE);
if(timeout_ms < 0) {
failf(data, "Connection time-out");
return CURLE_OPERATION_TIMEDOUT;
}
conn->num_addr = Curl_num_addresses(remotehost->addr);
conn->timeoutms_per_addr = timeout_ms / conn->num_addr;
ai = remotehost->addr;
for (curr_addr = ai, aliasindex=0; curr_addr;
curr_addr = curr_addr->ai_next, aliasindex++) {
CURLcode res =
singleipconnect(conn, curr_addr,
(data->state.used_interface == Curl_if_multi)?0:
conn->timeoutms_per_addr, &sockfd, connected);
if(res)
return res;
if(sockfd != CURL_SOCKET_BAD)
break;
after = Curl_tvnow();
timeout_ms -= Curl_tvdiff(after, before);
if(timeout_ms < 0) {
failf(data, "connect() timed out!");
return CURLE_OPERATION_TIMEDOUT;
}
before = after;
}
*sockconn = sockfd;
if(sockfd == CURL_SOCKET_BAD) {
failf(data, "couldn't connect to host");
return CURLE_COULDNT_CONNECT;
}
if(addr)
*addr = curr_addr;
data->info.numconnects++;
return CURLE_OK;
}
curl_socket_t Curl_getconnectinfo(struct SessionHandle *data,
struct connectdata **connp)
{
curl_socket_t sockfd;
if((data->state.lastconnect != -1) &&
(data->state.connc->connects[data->state.lastconnect] != NULL)) {
struct connectdata *c =
data->state.connc->connects[data->state.lastconnect];
if(connp)
*connp = c;
sockfd = c->sock[FIRSTSOCKET];
if(c->ssl[FIRSTSOCKET].use) {
if(!Curl_ssl_check_cxn(c))
return CURL_SOCKET_BAD;
}
#ifdef MSG_PEEK
else {
char buf;
if(recv((RECV_TYPE_ARG1)c->sock[FIRSTSOCKET], (RECV_TYPE_ARG2)&buf,
(RECV_TYPE_ARG3)1, (RECV_TYPE_ARG4)MSG_PEEK) == 0) {
return CURL_SOCKET_BAD;
}
}
#endif
}
else
return CURL_SOCKET_BAD;
return sockfd;
}