diff options
Diffstat (limited to 'net.c')
-rw-r--r-- | net.c | 66 |
1 files changed, 61 insertions, 5 deletions
@@ -47,6 +47,7 @@ #include <stdio.h> #include <poll.h> #include <limits.h> +#include <stdlib.h> #include "net.h" #include "sds.h" @@ -263,6 +264,44 @@ static int _redisContextConnectTcp(redisContext *c, const char *addr, int port, int reuseaddr = (c->flags & REDIS_REUSEADDR); int reuses = 0; + c->connection_type = REDIS_CONN_TCP; + c->tcp.port = port; + + /* We need to take possession of the passed parameters + * to make them reusable for a reconnect. + * We also carefully check we don't free data we already own, + * as in the case of the reconnect method. + * + * This is a bit ugly, but atleast it works and doesn't leak memory. + **/ + if (c->tcp.host != addr) { + if (c->tcp.host) + free(c->tcp.host); + + c->tcp.host = strdup(addr); + } + + if (timeout) { + if (c->timeout != timeout) { + if (c->timeout == NULL) + c->timeout = malloc(sizeof(struct timeval)); + + memcpy(c->timeout, timeout, sizeof(struct timeval)); + } + } else { + if (c->timeout) + free(c->timeout); + c->timeout = NULL; + } + + if (source_addr == NULL) { + free(c->tcp.source_addr); + c->tcp.source_addr = NULL; + } else if (c->tcp.source_addr != source_addr) { + free(c->tcp.source_addr); + c->tcp.source_addr = strdup(source_addr); + } + snprintf(_port, 6, "%d", port); memset(&hints,0,sizeof(hints)); hints.ai_family = AF_INET; @@ -273,7 +312,7 @@ static int _redisContextConnectTcp(redisContext *c, const char *addr, int port, * as this would add latency to every connect. Otherwise a more sensible * route could be: Use IPv6 if both addresses are available and there is IPv6 * connectivity. */ - if ((rv = getaddrinfo(addr,_port,&hints,&servinfo)) != 0) { + if ((rv = getaddrinfo(c->tcp.host,_port,&hints,&servinfo)) != 0) { hints.ai_family = AF_INET6; if ((rv = getaddrinfo(addr,_port,&hints,&servinfo)) != 0) { __redisSetError(c,REDIS_ERR_OTHER,gai_strerror(rv)); @@ -288,10 +327,10 @@ addrretry: c->fd = s; if (redisSetBlocking(c,0) != REDIS_OK) goto error; - if (source_addr) { + if (c->tcp.source_addr) { int bound = 0; /* Using getaddrinfo saves us from self-determining IPv4 vs IPv6 */ - if ((rv = getaddrinfo(source_addr, NULL, &hints, &bservinfo)) != 0) { + if ((rv = getaddrinfo(c->tcp.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); @@ -333,7 +372,7 @@ addrretry: goto addrretry; } } else { - if (redisContextWaitReady(c,timeout) != REDIS_OK) + if (redisContextWaitReady(c,c->timeout) != REDIS_OK) goto error; } } @@ -380,13 +419,30 @@ int redisContextConnectUnix(redisContext *c, const char *path, const struct time if (redisSetBlocking(c,0) != REDIS_OK) return REDIS_ERR; + c->connection_type = REDIS_CONN_UNIX; + if (c->unix.path != path) + c->unix.path = strdup(path); + + if (timeout) { + if (c->timeout != timeout) { + if (c->timeout == NULL) + c->timeout = malloc(sizeof(struct timeval)); + + memcpy(c->timeout, timeout, sizeof(struct timeval)); + } + } else { + if (c->timeout) + free(c->timeout); + c->timeout = NULL; + } + sa.sun_family = AF_LOCAL; strncpy(sa.sun_path,path,sizeof(sa.sun_path)-1); if (connect(c->fd, (struct sockaddr*)&sa, sizeof(sa)) == -1) { if (errno == EINPROGRESS && !blocking) { /* This is ok. */ } else { - if (redisContextWaitReady(c,timeout) != REDIS_OK) + if (redisContextWaitReady(c,c->timeout) != REDIS_OK) return REDIS_ERR; } } |