Re: [PATCH] ipv6 rework in udp_establish_listener
Samuel Thibault <[email protected]> Wed, 17 Aug 2005 15:31:58 +0200
| Newsgroups | gmane.comp.multimedia.xmms.devel |
|---|---|
| Message-ID | <[email protected]> |
Pascal Terjan, le Wed 17 Aug 2005 14:36:37 +0200, a écrit :
> (talking only for my patch, not the other ipv6 patches that I did not
> yet really read but I think it uses getaddrinfo so will be more tricky
> to have working...)
No, it's _much_ easier to make working than using AF_INET6 & co by
hand. getaddrinfo gives you every information you need: address family,
protocol, address, ... You just need a HAVE_GETADDRINFO, and then you
can use a loop like:
int sock;
struct addrinfo hints, *res, *cur;
memset(&hints,0,sizeof(hints));
hints.ai_flags = AI_PASSIVE;
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
if (getaddrinfo(NULL, listen_port, &hints, &res) != 0) {
/* handle error */
} else {
for (cur = res; cur; cur = cur->ai_next) {
if ((sock = socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol)) <0) {
if (errno != EAFNOSUPPORT) {
/* warn about error */
}
continue;
}
if (bind(sock, cur->ai_addr, cur->ai_addrlen)) {
/* warn about error */
close(sock);
continue;
}
if (listen(sock, 1)) {
/* warn about error */
close(sock);
continue;
}
/* did it */
break;
}
freeaddrinfo(res);
if (cur)
return sock;
else {
/* print error: failed to find a way to establish server
*/
return -1;
}
}
This will correctly look through all adress families and protocols that
can provide a "passive" "stream" service, and establish a listening
socket for the first that succeeds (when both libc _and_ kernel support
ipv6).
No #ifdef foo6 or #ifdef HAVE_GETNAMEINFO... Just #ifdef
HAVE_GETADDRINFO, and you've got fully IPv4 _and_ IPv6 working code.
Note that this loop is just about the same for establishing a
connection. And it will correctly try the different IPs that could be
associated with a dns name, in case the first ones don't work.
This really _is_ the preferred way to implement things nowadays.
Regards,
Samuel