Make tcp_server_create IPv6 aware

This commit is contained in:
BtbN 2013-01-15 02:18:13 +01:00
parent 71b09488a1
commit 294b8d92c2

View file

@ -478,21 +478,55 @@ tcp_server_create(int port, tcp_server_callback_t *start, void *opaque)
int fd, x;
struct epoll_event e;
tcp_server_t *ts;
struct sockaddr_in s;
struct addrinfo hints, *res, *ressave, *use = NULL;
char *portBuf = (char*)malloc(6);
int one = 1;
int zero = 0;
memset(&e, 0, sizeof(e));
fd = tvh_socket(AF_INET, SOCK_STREAM, 0);
snprintf(portBuf, 6, "%d", port);
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_flags = AI_PASSIVE;
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
x = getaddrinfo(NULL, portBuf, &hints, &res);
free(portBuf);
if(x != 0)
return NULL;
ressave = res;
while(res)
{
if(res->ai_family == AF_INET6)
{
use = res;
break;
}
else if(use == NULL)
{
use = res;
}
res = res->ai_next;
}
fd = tvh_socket(use->ai_family, use->ai_socktype, use->ai_protocol);
if(fd == -1)
return NULL;
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(int));
if(use->ai_family == AF_INET6)
setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &zero, sizeof(int));
memset(&s, 0, sizeof(s));
s.sin_family = AF_INET;
s.sin_port = htons(port);
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(int));
x = bind(fd, (struct sockaddr *)&s, sizeof(s));
if(x < 0) {
x = bind(fd, use->ai_addr, use->ai_addrlen);
freeaddrinfo(ressave);
if(x != 0)
{
close(fd);
return NULL;
}
@ -504,11 +538,10 @@ tcp_server_create(int port, tcp_server_callback_t *start, void *opaque)
ts->start = start;
ts->opaque = opaque;
e.events = EPOLLIN;
e.data.ptr = ts;
epoll_ctl(tcp_server_epoll_fd, EPOLL_CTL_ADD, fd, &e);
return ts;
}