From 8339fd04204ff38f4fa5f5d79710fce1acfd2d83 Mon Sep 17 00:00:00 2001 From: Dmitry Podgorny Date: Sun, 11 Oct 2015 05:20:31 +0300 Subject: [PATCH] sock: socket should be non-blocking Event loop handles asynchronous connections. --- src/sock.c | 43 +++++++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/src/sock.c b/src/sock.c index ade501a..f4246cf 100644 --- a/src/sock.c +++ b/src/sock.c @@ -69,7 +69,7 @@ static int _in_progress(int error) #ifdef _WIN32 return (error == WSAEWOULDBLOCK || error == WSAEINPROGRESS); #else - return (errno == EINPROGRESS); + return (error == EINPROGRESS); #endif } @@ -79,8 +79,6 @@ sock_t sock_connect(const char * const host, const unsigned int port) char service[6]; struct addrinfo *res, *ainfo, hints; int err; - - sock = -1; snprintf(service, 6, "%u", port); @@ -101,18 +99,19 @@ sock_t sock_connect(const char * const host, const unsigned int port) if (sock < 0) continue; - err = connect(sock, ainfo->ai_addr, ainfo->ai_addrlen); - if (err < 0) { - close(sock); - continue; + err = sock_set_nonblocking(sock); + if (err == 0) { + err = connect(sock, ainfo->ai_addr, ainfo->ai_addrlen); + if (err == 0 || _in_progress(sock_error())) + break; } - /* Connection has been established. */ - break; + close(sock); } freeaddrinfo(res); + sock = ainfo == NULL ? -1 : sock; - return ainfo == NULL ? -1 : sock; + return sock; } int sock_close(const sock_t sock) @@ -130,7 +129,13 @@ int sock_set_blocking(const sock_t sock) u_long block = 0; return ioctlsocket(sock, FIONBIO, &block); #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 } @@ -140,7 +145,13 @@ int sock_set_nonblocking(const sock_t sock) u_long nonblock = 1; return ioctlsocket(sock, FIONBIO, &nonblock); #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 } @@ -158,7 +169,7 @@ int sock_is_recoverable(const int error) { #ifdef _WIN32 return (error == WSAEINTR || error == WSAEWOULDBLOCK || - error == WSAEINPROGRESS); + error == WSAEINPROGRESS); #else return (error == EAGAIN || error == EINTR); #endif @@ -167,18 +178,18 @@ int sock_is_recoverable(const int error) int sock_connect_error(const sock_t sock) { struct sockaddr sa; - unsigned len; + socklen_t len; char temp; + memset(&sa, 0, sizeof(sa)); sa.sa_family = AF_UNSPEC; - len = sizeof(sa); /* we don't actually care about the peer name, we're just checking if * we're connected or not */ if (getpeername(sock, &sa, &len) == 0) { - return 0; + return 0; } /* it's possible that the error wasn't ENOTCONN, so if it wasn't,