sock: socket should be non-blocking

Event loop handles asynchronous connections.
This commit is contained in:
Dmitry Podgorny
2015-10-11 05:20:31 +03:00
parent 63946ff7ef
commit 8339fd0420

View File

@@ -69,7 +69,7 @@ static int _in_progress(int error)
#ifdef _WIN32 #ifdef _WIN32
return (error == WSAEWOULDBLOCK || error == WSAEINPROGRESS); return (error == WSAEWOULDBLOCK || error == WSAEINPROGRESS);
#else #else
return (errno == EINPROGRESS); return (error == EINPROGRESS);
#endif #endif
} }
@@ -80,8 +80,6 @@ sock_t sock_connect(const char * const host, const unsigned int port)
struct addrinfo *res, *ainfo, hints; struct addrinfo *res, *ainfo, hints;
int err; int err;
sock = -1;
snprintf(service, 6, "%u", port); snprintf(service, 6, "%u", port);
memset(&hints, 0, sizeof(struct addrinfo)); memset(&hints, 0, sizeof(struct addrinfo));
@@ -101,18 +99,19 @@ sock_t sock_connect(const char * const host, const unsigned int port)
if (sock < 0) if (sock < 0)
continue; continue;
err = connect(sock, ainfo->ai_addr, ainfo->ai_addrlen); err = sock_set_nonblocking(sock);
if (err < 0) { if (err == 0) {
close(sock); err = connect(sock, ainfo->ai_addr, ainfo->ai_addrlen);
continue; if (err == 0 || _in_progress(sock_error()))
break;
} }
/* Connection has been established. */ close(sock);
break;
} }
freeaddrinfo(res); freeaddrinfo(res);
sock = ainfo == NULL ? -1 : sock;
return ainfo == NULL ? -1 : sock; return sock;
} }
int sock_close(const sock_t sock) int sock_close(const sock_t sock)
@@ -130,7 +129,13 @@ int sock_set_blocking(const sock_t sock)
u_long block = 0; u_long block = 0;
return ioctlsocket(sock, FIONBIO, &block); return ioctlsocket(sock, FIONBIO, &block);
#else #else
return fcntl(sock, F_SETFL, 0); int rc;
rc = fcntl(sock, F_GETFL, NULL);
if (rc >= 0) {
rc = fcntl(sock, F_SETFL, rc & (~O_NONBLOCK));
}
return rc;
#endif #endif
} }
@@ -140,7 +145,13 @@ int sock_set_nonblocking(const sock_t sock)
u_long nonblock = 1; u_long nonblock = 1;
return ioctlsocket(sock, FIONBIO, &nonblock); return ioctlsocket(sock, FIONBIO, &nonblock);
#else #else
return fcntl(sock, F_SETFL, O_NONBLOCK); int rc;
rc = fcntl(sock, F_GETFL, NULL);
if (rc >= 0) {
rc = fcntl(sock, F_SETFL, rc | O_NONBLOCK);
}
return rc;
#endif #endif
} }
@@ -158,7 +169,7 @@ int sock_is_recoverable(const int error)
{ {
#ifdef _WIN32 #ifdef _WIN32
return (error == WSAEINTR || error == WSAEWOULDBLOCK || return (error == WSAEINTR || error == WSAEWOULDBLOCK ||
error == WSAEINPROGRESS); error == WSAEINPROGRESS);
#else #else
return (error == EAGAIN || error == EINTR); return (error == EAGAIN || error == EINTR);
#endif #endif
@@ -167,18 +178,18 @@ int sock_is_recoverable(const int error)
int sock_connect_error(const sock_t sock) int sock_connect_error(const sock_t sock)
{ {
struct sockaddr sa; struct sockaddr sa;
unsigned len; socklen_t len;
char temp; char temp;
memset(&sa, 0, sizeof(sa));
sa.sa_family = AF_UNSPEC; sa.sa_family = AF_UNSPEC;
len = sizeof(sa); len = sizeof(sa);
/* we don't actually care about the peer name, we're just checking if /* we don't actually care about the peer name, we're just checking if
* we're connected or not */ * we're connected or not */
if (getpeername(sock, &sa, &len) == 0) if (getpeername(sock, &sa, &len) == 0)
{ {
return 0; return 0;
} }
/* it's possible that the error wasn't ENOTCONN, so if it wasn't, /* it's possible that the error wasn't ENOTCONN, so if it wasn't,