summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPieter Noordhuis <pcnoordhuis@gmail.com>2011-07-20 05:02:08 -0700
committerPieter Noordhuis <pcnoordhuis@gmail.com>2011-07-20 05:02:08 -0700
commit7bc9f5413447af9c920b9aaba85fa39d9496fe1a (patch)
treec731a30101ed8fad488feba9678889f4adb1e400
parent6bde974927ffce4f6d7acd8370c8a60b51454004 (diff)
parentc4ed06d90c2d25ccbb709b3d7c9c848aa732de66 (diff)
Merge pull request #47 from geoffgarside/addrinfo
Use getaddrinfo
-rw-r--r--net.c99
1 files changed, 58 insertions, 41 deletions
diff --git a/net.c b/net.c
index d967e5b..158e1dd 100644
--- a/net.c
+++ b/net.c
@@ -62,16 +62,24 @@ static void __redisSetErrorFromErrno(redisContext *c, int type, const char *pref
__redisSetError(c,type,buf);
}
+static int redisSetReuseAddr(redisContext *c, int fd) {
+ int on = 1;
+ if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) {
+ __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
+ close(fd);
+ return REDIS_ERR;
+ }
+ return REDIS_OK;
+}
+
static int redisCreateSocket(redisContext *c, int type) {
- int s, on = 1;
+ int s;
if ((s = socket(type, SOCK_STREAM, 0)) == -1) {
__redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
return REDIS_ERR;
}
if (type == AF_INET) {
- if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) {
- __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
- close(s);
+ if (redisSetReuseAddr(c,s) == REDIS_ERR) {
return REDIS_ERR;
}
}
@@ -185,50 +193,59 @@ 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 == EHOSTUNREACH) {
+ close(s);
+ continue;
+ } else 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) {