Add ability to bind source address on connect
Some environments require binding to specific source addresses instead of letting the system determine which IP a connection should originate from. Closes #233
This commit is contained in:
parent
61eeedbe77
commit
37d25a392c
8
async.c
8
async.c
@ -165,6 +165,14 @@ redisAsyncContext *redisAsyncConnect(const char *ip, int port) {
|
|||||||
return ac;
|
return ac;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
redisAsyncContext *redisAsyncConnectBind(const char *ip, int port,
|
||||||
|
char *source_addr) {
|
||||||
|
redisContext *c = redisConnectBindNonBlock(ip,port,source_addr);
|
||||||
|
redisAsyncContext *ac = redisAsyncInitialize(c);
|
||||||
|
__redisAsyncCopyError(ac);
|
||||||
|
return ac;
|
||||||
|
}
|
||||||
|
|
||||||
redisAsyncContext *redisAsyncConnectUnix(const char *path) {
|
redisAsyncContext *redisAsyncConnectUnix(const char *path) {
|
||||||
redisContext *c;
|
redisContext *c;
|
||||||
redisAsyncContext *ac;
|
redisAsyncContext *ac;
|
||||||
|
1
async.h
1
async.h
@ -102,6 +102,7 @@ typedef struct redisAsyncContext {
|
|||||||
|
|
||||||
/* Functions that proxy to hiredis */
|
/* Functions that proxy to hiredis */
|
||||||
redisAsyncContext *redisAsyncConnect(const char *ip, int port);
|
redisAsyncContext *redisAsyncConnect(const char *ip, int port);
|
||||||
|
redisAsyncContext *redisAsyncConnectBind(const char *ip, int port,char *source);
|
||||||
redisAsyncContext *redisAsyncConnectUnix(const char *path);
|
redisAsyncContext *redisAsyncConnectUnix(const char *path);
|
||||||
int redisAsyncSetConnectCallback(redisAsyncContext *ac, redisConnectCallback *fn);
|
int redisAsyncSetConnectCallback(redisAsyncContext *ac, redisConnectCallback *fn);
|
||||||
int redisAsyncSetDisconnectCallback(redisAsyncContext *ac, redisDisconnectCallback *fn);
|
int redisAsyncSetDisconnectCallback(redisAsyncContext *ac, redisDisconnectCallback *fn);
|
||||||
|
@ -1049,6 +1049,14 @@ redisContext *redisConnectNonBlock(const char *ip, int port) {
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
redisContext *redisConnectBindNonBlock(const char *ip, int port,
|
||||||
|
char *source_addr) {
|
||||||
|
redisContext *c = redisContextInit();
|
||||||
|
c->flags &= ~REDIS_BLOCK;
|
||||||
|
redisContextConnectBindTcp(c,ip,port,NULL,source_addr);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
redisContext *redisConnectUnix(const char *path) {
|
redisContext *redisConnectUnix(const char *path) {
|
||||||
redisContext *c;
|
redisContext *c;
|
||||||
|
|
||||||
|
@ -175,6 +175,7 @@ typedef struct redisContext {
|
|||||||
redisContext *redisConnect(const char *ip, int port);
|
redisContext *redisConnect(const char *ip, int port);
|
||||||
redisContext *redisConnectWithTimeout(const char *ip, int port, const struct timeval tv);
|
redisContext *redisConnectWithTimeout(const char *ip, int port, const struct timeval tv);
|
||||||
redisContext *redisConnectNonBlock(const char *ip, int port);
|
redisContext *redisConnectNonBlock(const char *ip, int port);
|
||||||
|
redisContext *redisConnectBindNonBlock(const char *ip, int port, char *source);
|
||||||
redisContext *redisConnectUnix(const char *path);
|
redisContext *redisConnectUnix(const char *path);
|
||||||
redisContext *redisConnectUnixWithTimeout(const char *path, const struct timeval tv);
|
redisContext *redisConnectUnixWithTimeout(const char *path, const struct timeval tv);
|
||||||
redisContext *redisConnectUnixNonBlock(const char *path);
|
redisContext *redisConnectUnixNonBlock(const char *path);
|
||||||
|
38
net.c
38
net.c
@ -250,10 +250,12 @@ int redisContextSetTimeout(redisContext *c, const struct timeval tv) {
|
|||||||
return REDIS_OK;
|
return REDIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int redisContextConnectTcp(redisContext *c, const char *addr, int port, const struct timeval *timeout) {
|
static int _redisContextConnectTcp(redisContext *c, const char *addr, int port,
|
||||||
|
const struct timeval *timeout,
|
||||||
|
char *source_addr) {
|
||||||
int s, rv;
|
int s, rv;
|
||||||
char _port[6]; /* strlen("65535"); */
|
char _port[6]; /* strlen("65535"); */
|
||||||
struct addrinfo hints, *servinfo, *p;
|
struct addrinfo hints, *servinfo, *bservinfo, *p, *b;
|
||||||
int blocking = (c->flags & REDIS_BLOCK);
|
int blocking = (c->flags & REDIS_BLOCK);
|
||||||
|
|
||||||
snprintf(_port, 6, "%d", port);
|
snprintf(_port, 6, "%d", port);
|
||||||
@ -280,6 +282,28 @@ int redisContextConnectTcp(redisContext *c, const char *addr, int port, const st
|
|||||||
c->fd = s;
|
c->fd = s;
|
||||||
if (redisSetBlocking(c,0) != REDIS_OK)
|
if (redisSetBlocking(c,0) != REDIS_OK)
|
||||||
goto error;
|
goto error;
|
||||||
|
if (source_addr) {
|
||||||
|
int bound = 0;
|
||||||
|
/* Using getaddrinfo saves us from self-determining IPv4 vs IPv6 */
|
||||||
|
if ((rv = getaddrinfo(source_addr, NULL, &hints, &bservinfo)) != 0) {
|
||||||
|
char buf[128];
|
||||||
|
snprintf(buf,sizeof(buf),"Can't get addr: %s",gai_strerror(rv));
|
||||||
|
__redisSetError(c,REDIS_ERR_OTHER,buf);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
for (b = bservinfo; b != NULL; b = b->ai_next) {
|
||||||
|
if (bind(s,b->ai_addr,b->ai_addrlen) != -1) {
|
||||||
|
bound = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!bound) {
|
||||||
|
char buf[128];
|
||||||
|
snprintf(buf,sizeof(buf),"Can't bind socket: %s",strerror(errno));
|
||||||
|
__redisSetError(c,REDIS_ERR_OTHER,buf);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (connect(s,p->ai_addr,p->ai_addrlen) == -1) {
|
if (connect(s,p->ai_addr,p->ai_addrlen) == -1) {
|
||||||
if (errno == EHOSTUNREACH) {
|
if (errno == EHOSTUNREACH) {
|
||||||
redisContextCloseFd(c);
|
redisContextCloseFd(c);
|
||||||
@ -314,6 +338,16 @@ end:
|
|||||||
return rv; // Need to return REDIS_OK if alright
|
return rv; // Need to return REDIS_OK if alright
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int redisContextConnectTcp(redisContext *c, const char *addr, int port,
|
||||||
|
const struct timeval *timeout) {
|
||||||
|
return _redisContextConnectTcp(c, addr, port, timeout, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int redisContextConnectBindTcp(redisContext *c, const char *addr, int port,
|
||||||
|
const struct timeval *timeout, char *source_addr) {
|
||||||
|
return _redisContextConnectTcp(c, addr, port, timeout, source_addr);
|
||||||
|
}
|
||||||
|
|
||||||
int redisContextConnectUnix(redisContext *c, const char *path, const struct timeval *timeout) {
|
int redisContextConnectUnix(redisContext *c, const char *path, const struct timeval *timeout) {
|
||||||
int blocking = (c->flags & REDIS_BLOCK);
|
int blocking = (c->flags & REDIS_BLOCK);
|
||||||
struct sockaddr_un sa;
|
struct sockaddr_un sa;
|
||||||
|
2
net.h
2
net.h
@ -42,6 +42,8 @@
|
|||||||
int redisCheckSocketError(redisContext *c);
|
int redisCheckSocketError(redisContext *c);
|
||||||
int redisContextSetTimeout(redisContext *c, const struct timeval tv);
|
int redisContextSetTimeout(redisContext *c, const struct timeval tv);
|
||||||
int redisContextConnectTcp(redisContext *c, const char *addr, int port, const struct timeval *timeout);
|
int redisContextConnectTcp(redisContext *c, const char *addr, int port, const struct timeval *timeout);
|
||||||
|
int redisContextConnectBindTcp(redisContext *c, const char *addr, int port,
|
||||||
|
const struct timeval *timeout, char *source_addr);
|
||||||
int redisContextConnectUnix(redisContext *c, const char *path, const struct timeval *timeout);
|
int redisContextConnectUnix(redisContext *c, const char *path, const struct timeval *timeout);
|
||||||
int redisKeepAlive(redisContext *c, int interval);
|
int redisKeepAlive(redisContext *c, int interval);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user