From 491f68108868baed5b60045b75099b5475eddd35 Mon Sep 17 00:00:00 2001 From: antirez Date: Wed, 25 Dec 2013 18:13:27 +0100 Subject: [PATCH] anetTcpGenericConnect() code improved + 1 bug fix. Now the socket is closed if anetNonBlock() fails, and in general the code structure makes it harder to introduce this kind of bugs in the future. Reference: pull request #1059. --- src/anet.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/anet.c b/src/anet.c index 257b491e..45b31e78 100644 --- a/src/anet.c +++ b/src/anet.c @@ -219,11 +219,11 @@ static int anetCreateSocket(char *err, int domain) { #define ANET_CONNECT_NONBLOCK 1 static int anetTcpGenericConnect(char *err, char *addr, int port, int flags) { - int s, rv; - char _port[6]; /* strlen("65535"); */ + int s = ANET_ERR, rv; + char _port[6]; /* strlen("65535") + 1; */ struct addrinfo hints, *servinfo, *p; - snprintf(_port,6,"%d",port); + snprintf(_port,sizeof(port),"%d",port); memset(&hints,0,sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; @@ -233,20 +233,26 @@ static int anetTcpGenericConnect(char *err, char *addr, int port, int flags) return ANET_ERR; } for (p = servinfo; p != NULL; p = p->ai_next) { + /* Try to create the socket and to connect it. + * If we fail in the socket() call, or on connect(), we retry with + * the next entry in servinfo. */ if ((s = socket(p->ai_family,p->ai_socktype,p->ai_protocol)) == -1) continue; - - /* if we set err then goto cleanup, otherwise next */ if (anetSetReuseAddr(err,s) == ANET_ERR) goto error; if (flags & ANET_CONNECT_NONBLOCK && anetNonBlock(err,s) != ANET_OK) goto error; if (connect(s,p->ai_addr,p->ai_addrlen) == -1) { - if (errno == EINPROGRESS && flags & ANET_CONNECT_NONBLOCK) goto end; + /* If the socket is non-blocking, it is ok for connect() to + * return an EINPROGRESS error here. */ + if (errno == EINPROGRESS && flags & ANET_CONNECT_NONBLOCK) + goto end; close(s); + s = ANET_ERR; continue; } - /* break with the socket */ + /* If we ended an iteration of the for loop without errors, we + * have a connected socket. Let's return to the caller. */ goto end; } if (p == NULL) { @@ -255,7 +261,10 @@ static int anetTcpGenericConnect(char *err, char *addr, int port, int flags) } error: - s = ANET_ERR; + if (s != ANET_ERR) { + close(s); + s = ANET_ERR; + } end: freeaddrinfo(servinfo); return s;