diff options
author | antirez <antirez@gmail.com> | 2015-06-11 12:55:58 +0200 |
---|---|---|
committer | antirez <antirez@gmail.com> | 2015-06-11 14:34:38 +0200 |
commit | a017b7ec0e68792fa79b611023f3065c4e0c9394 (patch) | |
tree | 2038eb7b19ae82f81ff847397e0d4eed0d8421de /src | |
parent | 8fa8b251a9766f987a7704f034e66c645f0c3afe (diff) | |
download | redis-a017b7ec0e68792fa79b611023f3065c4e0c9394.tar.gz |
anet.c: new API anetTcpNonBlockBestEffortBindConnect()
This performs a best effort source address binding attempt. If it is
possible to bind the local address and still have a successful
connect(), then this socket is returned. Otherwise the call is retried
without source address binding attempt.
Related to issues #2609 and #2612.
Diffstat (limited to 'src')
-rw-r--r-- | src/anet.c | 24 | ||||
-rw-r--r-- | src/anet.h | 1 |
2 files changed, 22 insertions, 3 deletions
diff --git a/src/anet.c b/src/anet.c index bdaba8b0f..1728f3eb9 100644 --- a/src/anet.c +++ b/src/anet.c @@ -264,6 +264,7 @@ static int anetCreateSocket(char *err, int domain) { #define ANET_CONNECT_NONE 0 #define ANET_CONNECT_NONBLOCK 1 +#define ANET_CONNECT_BE_BINDING 2 /* Best effort binding. */ static int anetTcpGenericConnect(char *err, char *addr, int port, char *source_addr, int flags) { @@ -331,9 +332,17 @@ error: close(s); s = ANET_ERR; } + end: freeaddrinfo(servinfo); - return s; + + /* Handle best effort binding: if a binding address was used, but it is + * not possible to create a socket, try again without a binding address. */ + if (s == ANET_ERR && source_addr && (flags & ANET_CONNECT_BE_BINDING)) { + return anetTcpGenericConnect(err,addr,port,NULL,flags); + } else { + return s; + } } int anetTcpConnect(char *err, char *addr, int port) @@ -346,9 +355,18 @@ int anetTcpNonBlockConnect(char *err, char *addr, int port) return anetTcpGenericConnect(err,addr,port,NULL,ANET_CONNECT_NONBLOCK); } -int anetTcpNonBlockBindConnect(char *err, char *addr, int port, char *source_addr) +int anetTcpNonBlockBindConnect(char *err, char *addr, int port, + char *source_addr) +{ + return anetTcpGenericConnect(err,addr,port,source_addr, + ANET_CONNECT_NONBLOCK); +} + +int anetTcpNonBlockBestEffortBindConnect(char *err, char *addr, int port, + char *source_addr) { - return anetTcpGenericConnect(err,addr,port,source_addr,ANET_CONNECT_NONBLOCK); + return anetTcpGenericConnect(err,addr,port,source_addr, + ANET_CONNECT_NONBLOCK|ANET_CONNECT_BE_BINDING); } int anetUnixGenericConnect(char *err, char *path, int flags) diff --git a/src/anet.h b/src/anet.h index ea9c77f2e..8740a95d0 100644 --- a/src/anet.h +++ b/src/anet.h @@ -50,6 +50,7 @@ int anetTcpConnect(char *err, char *addr, int port); int anetTcpNonBlockConnect(char *err, char *addr, int port); int anetTcpNonBlockBindConnect(char *err, char *addr, int port, char *source_addr); +int anetTcpNonBlockBestEffortBindConnect(char *err, char *addr, int port, char *source_addr); int anetUnixConnect(char *err, char *path); int anetUnixNonBlockConnect(char *err, char *path); int anetRead(int fd, char *buf, int count); |