FIONBIO is not supported under NaCl so only use non-blocking connect if available

This commit is contained in:
Cameron Gutman 2016-02-16 10:54:24 -05:00
parent 1662ce1ee8
commit 1bb1e47e8a

View File

@ -114,9 +114,9 @@ SOCKET connectTcpSocket(struct sockaddr_storage* dstaddr, SOCKADDR_LEN addrlen,
SOCKET s; SOCKET s;
struct sockaddr_in6 addr; struct sockaddr_in6 addr;
int err; int err;
#if defined(LC_DARWIN) || defined(FIONBIO)
int val; int val;
struct fd_set writefds, exceptfds; #endif
struct timeval tv;
s = socket(dstaddr->ss_family, SOCK_STREAM, IPPROTO_TCP); s = socket(dstaddr->ss_family, SOCK_STREAM, IPPROTO_TCP);
if (s == INVALID_SOCKET) { if (s == INVALID_SOCKET) {
@ -130,60 +130,75 @@ SOCKET connectTcpSocket(struct sockaddr_storage* dstaddr, SOCKADDR_LEN addrlen,
setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE, (char*)&val, sizeof(val)); setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE, (char*)&val, sizeof(val));
#endif #endif
#ifdef FIONBIO
// Enable non-blocking I/O for connect timeout support // Enable non-blocking I/O for connect timeout support
val = 1; val = 1;
ioctlsocket(s, FIONBIO, &val); ioctlsocket(s, FIONBIO, &val);
#endif
// Start async connection // Start connection
memcpy(&addr, dstaddr, sizeof(addr)); memcpy(&addr, dstaddr, sizeof(addr));
addr.sin6_port = htons(port); addr.sin6_port = htons(port);
connect(s, (struct sockaddr*) &addr, addrlen); if (connect(s, (struct sockaddr*) &addr, addrlen) < 0) {
err = (int)LastSocketError();
FD_ZERO(&writefds);
FD_ZERO(&exceptfds);
FD_SET(s, &writefds);
FD_SET(s, &exceptfds);
tv.tv_sec = timeoutSec;
tv.tv_usec = 0;
// Wait for the connection to complete or the timeout to elapse
err = select(s + 1, NULL, &writefds, &exceptfds, &tv);
if (err < 0) {
// select() failed
err = LastSocketError();
Limelog("select() failed: %d\n", err);
closeSocket(s);
SetLastSocketError(err);
return INVALID_SOCKET;
} }
else if (err == 0) {
// select() timed out #ifdef FIONBIO
Limelog("select() timed out after %d seconds\n", timeoutSec); {
closeSocket(s); struct fd_set writefds, exceptfds;
#if defined(LC_WINDOWS) struct timeval tv;
SetLastSocketError(WSAEWOULDBLOCK);
#else FD_ZERO(&writefds);
SetLastSocketError(EWOULDBLOCK); FD_ZERO(&exceptfds);
#endif FD_SET(s, &writefds);
return INVALID_SOCKET; FD_SET(s, &exceptfds);
}
else if (FD_ISSET(s, &writefds) || FD_ISSET(s, &exceptfds)) { tv.tv_sec = timeoutSec;
// The socket was signalled tv.tv_usec = 0;
SOCKADDR_LEN len = sizeof(err);
getsockopt(s, SOL_SOCKET, SO_ERROR, (char*)&err, &len); // Wait for the connection to complete or the timeout to elapse
if (err != 0 || FD_ISSET(s, &exceptfds)) { err = select(s + 1, NULL, &writefds, &exceptfds, &tv);
err = (err != 0) ? err : LastSocketFail(); if (err < 0) {
Limelog("connect() failed: %d\n", err); // select() failed
err = LastSocketError();
Limelog("select() failed: %d\n", err);
closeSocket(s); closeSocket(s);
SetLastSocketError(err); SetLastSocketError(err);
return INVALID_SOCKET; return INVALID_SOCKET;
} }
else if (err == 0) {
// select() timed out
Limelog("select() timed out after %d seconds\n", timeoutSec);
closeSocket(s);
#if defined(LC_WINDOWS)
SetLastSocketError(WSAEWOULDBLOCK);
#else
SetLastSocketError(EWOULDBLOCK);
#endif
return INVALID_SOCKET;
}
else if (FD_ISSET(s, &writefds) || FD_ISSET(s, &exceptfds)) {
// The socket was signalled
SOCKADDR_LEN len = sizeof(err);
getsockopt(s, SOL_SOCKET, SO_ERROR, (char*)&err, &len);
if (err != 0 || FD_ISSET(s, &exceptfds)) {
// Get the error code
err = (err != 0) ? err : LastSocketFail();
}
}
// Disable non-blocking I/O now that the connection is established
val = 0;
ioctlsocket(s, FIONBIO, &val);
} }
#endif
// Disable non-blocking I/O now that the connection is established if (err != 0) {
val = 0; Limelog("connect() failed: %d\n", err);
ioctlsocket(s, FIONBIO, &val); closeSocket(s);
SetLastSocketError(err);
return INVALID_SOCKET;
}
return s; return s;
} }