Re: [PATCH] ipv6 rework in udp_establish_listener

Pascal Terjan <[email protected]> Wed, 17 Aug 2005 00:06:02 +0200
Newsgroups gmane.comp.multimedia.xmms.devel
Organization Mandriva
Message-ID <1124229962.7132.5.camel@plop>
Le dimanche 14 août 2005 à 22:13 +0200, Samuel Thibault a écrit : 
> Hi,
> 
> Pascal Terjan, le Fri 12 Aug 2005 17:13:43 +0200, a écrit :
> > This especially occurs when xmms is built with ipv6 support and run on a
> > system with ipv6 disabled.
> 
> Actually, the current ipv6 implementation needs rewriting: just using
> getaddrinfo() _is_ the good solution, I don't understand why people are
> still using the old interface...

Here is a new version, also changing udp_check_for_data so that no
USE_IPV6 remain in the code (considering patch from the email "Patch re:
the "IPv6" connection code" is applied).

I currently tested it in ipv4 and ipv6 but only on ipv6 enabled host.

BTW, I noticed that current xmms with both DEBUG_UDP and USE_IPV6 won't
build due to unblanced { in udp_check_for_data.

_______________________________________________
xmms-devel mailing list
[email protected]
http://lists.xmms.org/mailman/listinfo/xmms-devel
xmms-1.2.10-ipv6.patch (text/x-patch, 3.6 KB)
--- Input/mpg123/http.c	2005-08-16 23:55:18.000000000 +0200
+++ Input/mpg123/http.c.new	2005-08-16 23:55:41.000000000 +0200
@@ -720,23 +720,17 @@
 /* Find a good local udp port and bind udp_sock to it, return the port */
 static int udp_establish_listener(int *sock)
 {
-#ifdef USE_IPV6
-	struct sockaddr_in6 sin;
-	socklen_t sinlen = sizeof (struct sockaddr_in6);
-#else
-	struct sockaddr_in sin;
-	socklen_t sinlen = sizeof (struct sockaddr_in);
-#endif
+	struct sockaddr_storage ss;
+	char hostname[INET6_ADDRSTRLEN], port_s[10];
+	int res, sockfd, port;
+	unsigned int ss_len;
 	
 #ifdef DEBUG_UDP
 	fprintf (stderr,"Establishing udp listener\n");
 #endif
 	
-#ifdef USE_IPV6
-	if ((*sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
-#else
-	if ((*sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
-#endif
+	if ((*sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) 
+	if ((*sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
 	{
 		g_log(NULL, G_LOG_LEVEL_CRITICAL,
 		      "udp_establish_listener(): unable to create socket: %s",
@@ -744,21 +738,15 @@
 		return -1;
 	}
 
-	memset(&sin, 0, sinlen);
-#ifdef USE_IPV6
-	sin.sin6_family = AF_INET6;
-#else
-	sin.sin_family = AF_INET;
-	sin.sin_addr.s_addr = g_htonl(INADDR_ANY);
-#endif
-			
-	if (bind(*sock, (struct sockaddr *)&sin, sinlen) < 0)
+	ss_len = sizeof(struct sockaddr_storage);
+	if (bind(*sock, (struct sockaddr *)&ss, ss_len) < 0)
 	{
 		g_log(NULL, G_LOG_LEVEL_CRITICAL,
 		      "udp_establish_listener():  Failed to bind socket to localhost: %s", strerror(errno));
 		close(*sock);
 		return -1;
 	}
+	
 	if (fcntl(*sock, F_SETFL, O_NONBLOCK) < 0)
 	{
 		g_log(NULL, G_LOG_LEVEL_CRITICAL,
@@ -767,8 +755,7 @@
 		return -1;
 	}
 
-	memset(&sin, 0, sinlen);
-	if (getsockname(*sock, (struct sockaddr *)&sin, &sinlen) < 0)
+	if (getsockname(*sock, (struct sockaddr *)&ss, &ss_len) < 0)
 	{
 		g_log(NULL, G_LOG_LEVEL_CRITICAL,
 		      "udp_establish_listener():  Failed to retrieve socket info: %s", strerror(errno));
@@ -776,15 +763,21 @@
 		return -1;
 	}
 
+	if (getnameinfo((struct sockaddr *)&ss, ss_len, hostname, INET6_ADDRSTRLEN, port_s, 10, NI_NUMERICSERV|NI_NUMERICHOST) != 0)
+	{
+		g_log(NULL, G_LOG_LEVEL_CRITICAL,
+			"udp_establish_listener():  Failed to retrieve hostname and port : %s", strerror(errno));
+		close(*sock);
+		return -1;
+	}
+
+	port = atoi(port_s);
+
 #ifdef DEBUG_UDP
-	fprintf (stderr,"Listening on local %s:%d\n", inet_ntoa(sin.sin_addr), g_ntohs(sin.sin_port));
+	fprintf (stderr,"Listening on local %s:%d\n", hostname, port);
 #endif
 	
-#ifdef USE_IPV6
-	return g_ntohs(sin.sin6_port);
-#else
-	return g_ntohs(sin.sin_port);
-#endif
+	return port;
 }
 
 static int udp_check_for_data(int sock)
@@ -793,11 +786,7 @@
 	char *valptr;
 	gchar *title;
 	gint len, i;
-#ifdef USE_IPV6
-	struct sockaddr_in6 from;
-#else
-	struct sockaddr_in from;
-#endif
+	struct sockaddr_storage from;
 	socklen_t fromlen;
 
 	fromlen = sizeof(from);
@@ -885,14 +874,16 @@
 #ifdef DEBUG_UDP
 			else
 				fprintf(stderr,"Sent ack: %s", obuf);
-#ifdef USE_IPV6
 {
-			char adr[INET6_ADDRSTRLEN];
-			inet_ntop(AF_INET6, &from.sin6_addr, adr, INET6_ADDRSTRLEN);
-			fprintf (stderr,"Remote: [%s]:%d\n", adr, g_ntohs(from.sin6_port));
-#else
-			fprintf (stderr,"Remote: %s:%d\n", inet_ntoa(from.sin_addr), g_ntohs(from.sin_port));
-#endif
+	char hostname[INET6_ADDRSTRLEN], port[10];
+	if (getnameinfo((struct sockaddr *)&ss, ss_len, hostname, 256, port, 10, NI_NUMERICSERV|NI_NUMERICHOST) != 0)
+	{
+		g_log(NULL, G_LOG_LEVEL_WARNING,
+			"udp_check_for_data():  Failed to retrieve address and port : %s", strerror(errno));
+	}
+       	else
+		fprintf (stderr,"Remote: [%s]:%s\n", hostname, port);
+}
 #endif
 		}
 	}