Use getaddrinfo(3) in anetTcpGenericConnect.

Change anetTcpGenericConnect() 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.
This commit is contained in:
Geoff Garside 2011-06-17 01:06:19 +01:00 committed by antirez
parent 580b7dce9b
commit 0e01ce1b13

View File

@ -217,38 +217,52 @@ static int anetCreateSocket(char *err, int domain) {
#define ANET_CONNECT_NONBLOCK 1 #define ANET_CONNECT_NONBLOCK 1
static int anetTcpGenericConnect(char *err, char *addr, int port, int flags) static int anetTcpGenericConnect(char *err, char *addr, int port, int flags)
{ {
int s; int s, rv;
struct sockaddr_in sa; char _port[6]; /* strlen("65535"); */
struct addrinfo hints, *servinfo, *p;
if ((s = anetCreateSocket(err,AF_INET)) == ANET_ERR) snprintf(_port,6,"%d",port);
memset(&hints,0,sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
if ((rv = getaddrinfo(addr,_port,&hints,&servinfo)) != 0) {
anetSetError(err, "%s", gai_strerror(rv));
return ANET_ERR; return ANET_ERR;
}
for (p = servinfo; p != NULL; p = p->ai_next) {
if ((s = socket(p->ai_family,p->ai_socktype,p->ai_protocol)) == -1)
continue;
sa.sin_family = AF_INET; /* if we set err then goto cleanup, otherwise next */
sa.sin_port = htons(port); if (anetSetReuseAddr(err,s) == ANET_ERR) {
if (inet_aton(addr, &sa.sin_addr) == 0) { goto error;
struct hostent *he;
he = gethostbyname(addr);
if (he == NULL) {
anetSetError(err, "can't resolve: %s", addr);
close(s);
return ANET_ERR;
} }
memcpy(&sa.sin_addr, he->h_addr, sizeof(struct in_addr)); if (flags & ANET_CONNECT_NONBLOCK) {
} if (anetNonBlock(err,s) != ANET_OK)
if (flags & ANET_CONNECT_NONBLOCK) { goto error;
if (anetNonBlock(err,s) != ANET_OK) }
return ANET_ERR; if (connect(s,p->ai_addr,p->ai_addrlen) == -1) {
} if (errno == EINPROGRESS &&
if (connect(s, (struct sockaddr*)&sa, sizeof(sa)) == -1) { flags & ANET_CONNECT_NONBLOCK)
if (errno == EINPROGRESS && goto end;
flags & ANET_CONNECT_NONBLOCK)
return s;
anetSetError(err, "connect: %s", strerror(errno)); close(s);
close(s); continue;
return ANET_ERR; }
/* break with the socket */
goto end;
} }
if (p == NULL) {
anetSetError(err, "creating socket: %s", strerror(errno));
goto error;
}
error:
s = ANET_ERR;
end:
freeaddrinfo(servinfo);
return s; return s;
} }