diff libpurple/network.c @ 29832:2ab17571bf42

propagate from branch 'im.pidgin.pidgin' (head 7850267e7626c94b519fd5f1c959c79f0624d34e) to branch 'im.pidgin.cpw.malu.ft_thumbnails' (head 3845c5c2ec11e409fd1891793e73ab3d934001f9)
author Marcus Lundblad <ml@update.uu.se>
date Sat, 24 Apr 2010 14:59:13 +0000
parents 35a1cf247168
children c91976cf319c
line wrap: on
line diff
--- a/libpurple/network.c	Wed Mar 24 20:16:05 2010 +0000
+++ b/libpurple/network.c	Sat Apr 24 14:59:13 2010 +0000
@@ -394,7 +394,7 @@
 }
 
 static PurpleNetworkListenData *
-purple_network_do_listen(unsigned short port, int socket_type, PurpleNetworkListenCallback cb, gpointer cb_data)
+purple_network_do_listen(unsigned short port, int socket_family, int socket_type, PurpleNetworkListenCallback cb, gpointer cb_data)
 {
 	int listenfd = -1;
 	int flags;
@@ -412,7 +412,7 @@
 	g_snprintf(serv, sizeof(serv), "%hu", port);
 	memset(&hints, 0, sizeof(struct addrinfo));
 	hints.ai_flags = AI_PASSIVE;
-	hints.ai_family = AF_UNSPEC;
+	hints.ai_family = socket_family;
 	hints.ai_socktype = socket_type;
 	errnum = getaddrinfo(NULL /* any IP */, serv, &hints, &res);
 	if (errnum != 0) {
@@ -436,7 +436,7 @@
 		if (listenfd < 0)
 			continue;
 		if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) != 0)
-			purple_debug_warning("network", "setsockopt: %s\n", g_strerror(errno));
+			purple_debug_warning("network", "setsockopt(SO_REUSEADDR): %s\n", g_strerror(errno));
 		if (bind(listenfd, next->ai_addr, next->ai_addrlen) == 0)
 			break; /* success */
 		/* XXX - It is unclear to me (datallah) whether we need to be
@@ -451,6 +451,13 @@
 #else
 	struct sockaddr_in sockin;
 
+	if (socket_family != AF_INET && socket_family != AF_UNSPEC) {
+		purple_debug_warning("network", "Address family %d only "
+		                     "supported when built with getaddrinfo() "
+		                     "support\n", socket_family);
+		return NULL;
+	}
+
 	if ((listenfd = socket(AF_INET, socket_type, 0)) < 0) {
 		purple_debug_warning("network", "socket: %s\n", g_strerror(errno));
 		return NULL;
@@ -492,7 +499,8 @@
 	listen_data->cb_data = cb_data;
 	listen_data->socket_type = socket_type;
 
-	if (!listen_map_external || !purple_prefs_get_bool("/purple/network/map_ports"))
+	if (!purple_socket_speaks_ipv4(listenfd) || !listen_map_external ||
+			!purple_prefs_get_bool("/purple/network/map_ports"))
 	{
 		purple_debug_info("network", "Skipping external port mapping.\n");
 		/* The pmp_map_cb does what we want to do */
@@ -519,17 +527,29 @@
 }
 
 PurpleNetworkListenData *
-purple_network_listen(unsigned short port, int socket_type,
-		PurpleNetworkListenCallback cb, gpointer cb_data)
+purple_network_listen_family(unsigned short port, int socket_family,
+                             int socket_type, PurpleNetworkListenCallback cb,
+                             gpointer cb_data)
 {
 	g_return_val_if_fail(port != 0, NULL);
 
-	return purple_network_do_listen(port, socket_type, cb, cb_data);
+	return purple_network_do_listen(port, socket_family, socket_type,
+	                                cb, cb_data);
 }
 
 PurpleNetworkListenData *
-purple_network_listen_range(unsigned short start, unsigned short end,
-		int socket_type, PurpleNetworkListenCallback cb, gpointer cb_data)
+purple_network_listen(unsigned short port, int socket_type,
+		PurpleNetworkListenCallback cb, gpointer cb_data)
+{
+	return purple_network_listen_family(port, AF_UNSPEC, socket_type,
+	                                    cb, cb_data);
+}
+
+PurpleNetworkListenData *
+purple_network_listen_range_family(unsigned short start, unsigned short end,
+                                   int socket_family, int socket_type,
+                                   PurpleNetworkListenCallback cb,
+                                   gpointer cb_data)
 {
 	PurpleNetworkListenData *ret = NULL;
 
@@ -542,7 +562,7 @@
 	}
 
 	for (; start <= end; start++) {
-		ret = purple_network_do_listen(start, socket_type, cb, cb_data);
+		ret = purple_network_do_listen(start, AF_UNSPEC, socket_type, cb, cb_data);
 		if (ret != NULL)
 			break;
 	}
@@ -550,6 +570,15 @@
 	return ret;
 }
 
+PurpleNetworkListenData *
+purple_network_listen_range(unsigned short start, unsigned short end,
+                            int socket_type, PurpleNetworkListenCallback cb,
+                            gpointer cb_data)
+{
+	return purple_network_listen_range_family(start, end, AF_UNSPEC,
+	                                          socket_type, cb, cb_data);
+}
+
 void purple_network_listen_cancel(PurpleNetworkListenData *listen_data)
 {
 	if (listen_data->mapping_data != NULL)