sock: socket should be non-blocking
Event loop handles asynchronous connections.
This commit is contained in:
43
src/sock.c
43
src/sock.c
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,8 +79,6 @@ sock_t sock_connect(const char * const host, const unsigned int port)
|
|||||||
char service[6];
|
char service[6];
|
||||||
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);
|
||||||
|
|
||||||
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user