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;
struct sockaddr_in6 addr;
int err;
#if defined(LC_DARWIN) || defined(FIONBIO)
int val;
struct fd_set writefds, exceptfds;
struct timeval tv;
#endif
s = socket(dstaddr->ss_family, SOCK_STREAM, IPPROTO_TCP);
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));
#endif
#ifdef FIONBIO
// Enable non-blocking I/O for connect timeout support
val = 1;
ioctlsocket(s, FIONBIO, &val);
#endif
// Start async connection
// Start connection
memcpy(&addr, dstaddr, sizeof(addr));
addr.sin6_port = htons(port);
connect(s, (struct sockaddr*) &addr, addrlen);
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;
if (connect(s, (struct sockaddr*) &addr, addrlen) < 0) {
err = (int)LastSocketError();
}
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)) {
err = (err != 0) ? err : LastSocketFail();
Limelog("connect() failed: %d\n", err);
#ifdef FIONBIO
{
struct fd_set writefds, exceptfds;
struct timeval tv;
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
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
val = 0;
ioctlsocket(s, FIONBIO, &val);
if (err != 0) {
Limelog("connect() failed: %d\n", err);
closeSocket(s);
SetLastSocketError(err);
return INVALID_SOCKET;
}
return s;
}