Commit 3afe2585 authored by Geoff Garside's avatar Geoff Garside
Browse files

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.
parent b4664b41
...@@ -187,50 +187,56 @@ int redisContextSetTimeout(redisContext *c, struct timeval tv) { ...@@ -187,50 +187,56 @@ int redisContextSetTimeout(redisContext *c, struct timeval tv) {
} }
int redisContextConnectTcp(redisContext *c, const char *addr, int port, struct timeval *timeout) { 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); 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;
sa.sin_family = AF_INET; snprintf(_port, 6, "%d", port);
sa.sin_port = htons(port); memset(&hints,0,sizeof(hints));
if (inet_aton(addr, &sa.sin_addr) == 0) { hints.ai_family = AF_INET;
struct hostent *he; hints.ai_socktype = SOCK_STREAM;
he = gethostbyname(addr); if ((rv = getaddrinfo(addr,_port,&hints,&servinfo)) != 0) {
if (he == NULL) { __redisSetError(c,REDIS_ERR_OTHER,gai_strerror(rv));
char buf[128];
snprintf(buf,sizeof(buf),"Can't resolve: %s", addr);
__redisSetError(c,REDIS_ERR_OTHER,buf);
close(s);
return REDIS_ERR; return REDIS_ERR;
} }
memcpy(&sa.sin_addr, he->h_addr, sizeof(struct in_addr)); for (p = servinfo; p != NULL; p = p->ai_next) {
} if ((s = socket(p->ai_family,p->ai_socktype,p->ai_protocol)) == -1)
continue;
if (connect(s, (struct sockaddr*)&sa, sizeof(sa)) == -1) { if (redisSetBlocking(c,s,0) != REDIS_OK)
goto error;
if (connect(s,p->ai_addr,p->ai_addrlen) == -1) {
if (errno == EINPROGRESS && !blocking) { if (errno == EINPROGRESS && !blocking) {
/* This is ok. */ /* This is ok. */
} else { } else {
if (redisContextWaitReady(c,s,timeout) != REDIS_OK) if (redisContextWaitReady(c,s,timeout) != REDIS_OK)
return REDIS_ERR; goto error;
} }
} }
/* Reset socket to be blocking after connect(2). */
if (blocking && redisSetBlocking(c,s,1) != REDIS_OK) if (blocking && redisSetBlocking(c,s,1) != REDIS_OK)
return REDIS_ERR; goto error;
if (redisSetTcpNoDelay(c,s) != REDIS_OK) if (redisSetTcpNoDelay(c,s) != REDIS_OK)
return REDIS_ERR; goto error;
c->fd = s; c->fd = s;
c->flags |= REDIS_CONNECTED; c->flags |= REDIS_CONNECTED;
return REDIS_OK; 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;
}
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) { int redisContextConnectUnix(redisContext *c, const char *path, struct timeval *timeout) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment