summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeoff Garside <geoff@geoffgarside.co.uk>2011-06-17 19:26:46 +0100
committerGeoff Garside <geoff@geoffgarside.co.uk>2011-06-17 19:26:46 +0100
commit3afe2585de94e82fd83c2b6a5534cf1e008dd083 (patch)
tree155fd460d58e4cc17186643527c906262d898701
parentb4664b41c71fbcd7cda8644fd5e26ebf479d5df0 (diff)
Use getaddrinfo(3) in redisContextConnectTcp.
Change redisContextConnectTcp() function to use getaddrinfo(3) to perform address resolution, socket creation and connection. Resolved addresses are limited to those reachable by the AF_INET family.
-rw-r--r--net.c80
1 files changed, 43 insertions, 37 deletions
diff --git a/net.c b/net.c
index 9364851..9298d2d 100644
--- a/net.c
+++ b/net.c
@@ -187,50 +187,56 @@ int redisContextSetTimeout(redisContext *c, struct timeval tv) {
}
int redisContextConnectTcp(redisContext *c, const char *addr, int port, struct timeval *timeout) {
- int s;
+ int s, rv;
+ char _port[6]; /* strlen("65535"); */
+ struct addrinfo hints, *servinfo, *p;
int blocking = (c->flags & REDIS_BLOCK);
- struct sockaddr_in sa;
- if ((s = redisCreateSocket(c,AF_INET)) < 0)
- return REDIS_ERR;
- if (redisSetBlocking(c,s,0) != REDIS_OK)
- return REDIS_ERR;
+ snprintf(_port, 6, "%d", port);
+ memset(&hints,0,sizeof(hints));
+ hints.ai_family = AF_INET;
+ hints.ai_socktype = SOCK_STREAM;
- sa.sin_family = AF_INET;
- sa.sin_port = htons(port);
- if (inet_aton(addr, &sa.sin_addr) == 0) {
- struct hostent *he;
-
- he = gethostbyname(addr);
- if (he == NULL) {
- char buf[128];
- snprintf(buf,sizeof(buf),"Can't resolve: %s", addr);
- __redisSetError(c,REDIS_ERR_OTHER,buf);
- close(s);
- return REDIS_ERR;
- }
- memcpy(&sa.sin_addr, he->h_addr, sizeof(struct in_addr));
+ if ((rv = getaddrinfo(addr,_port,&hints,&servinfo)) != 0) {
+ __redisSetError(c,REDIS_ERR_OTHER,gai_strerror(rv));
+ return REDIS_ERR;
}
-
- if (connect(s, (struct sockaddr*)&sa, sizeof(sa)) == -1) {
- if (errno == EINPROGRESS && !blocking) {
- /* This is ok. */
- } else {
- if (redisContextWaitReady(c,s,timeout) != REDIS_OK)
- return REDIS_ERR;
+ for (p = servinfo; p != NULL; p = p->ai_next) {
+ if ((s = socket(p->ai_family,p->ai_socktype,p->ai_protocol)) == -1)
+ continue;
+
+ if (redisSetBlocking(c,s,0) != REDIS_OK)
+ goto error;
+ if (connect(s,p->ai_addr,p->ai_addrlen) == -1) {
+ if (errno == EINPROGRESS && !blocking) {
+ /* This is ok. */
+ } else {
+ if (redisContextWaitReady(c,s,timeout) != REDIS_OK)
+ goto error;
+ }
}
+ if (blocking && redisSetBlocking(c,s,1) != REDIS_OK)
+ goto error;
+ if (redisSetTcpNoDelay(c,s) != REDIS_OK)
+ goto error;
+
+ c->fd = s;
+ c->flags |= REDIS_CONNECTED;
+ rv = REDIS_OK;
+ goto end;
+ }
+ if (p == NULL) {
+ char buf[128];
+ snprintf(buf,sizeof(buf),"Can't create socket: %s",strerror(errno));
+ __redisSetError(c,REDIS_ERR_OTHER,buf);
+ goto error;
}
- /* Reset socket to be blocking after connect(2). */
- if (blocking && redisSetBlocking(c,s,1) != REDIS_OK)
- return REDIS_ERR;
-
- if (redisSetTcpNoDelay(c,s) != REDIS_OK)
- return REDIS_ERR;
-
- c->fd = s;
- c->flags |= REDIS_CONNECTED;
- return REDIS_OK;
+error:
+ rv = REDIS_ERR;
+end:
+ freeaddrinfo(servinfo);
+ return rv; // Need to return REDIS_OK if alright
}
int redisContextConnectUnix(redisContext *c, const char *path, struct timeval *timeout) {