summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorantirez <antirez@gmail.com>2015-06-11 12:55:58 +0200
committerantirez <antirez@gmail.com>2015-06-11 14:34:38 +0200
commita017b7ec0e68792fa79b611023f3065c4e0c9394 (patch)
tree2038eb7b19ae82f81ff847397e0d4eed0d8421de
parent8fa8b251a9766f987a7704f034e66c645f0c3afe (diff)
downloadredis-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.
-rw-r--r--src/anet.c24
-rw-r--r--src/anet.h1
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);