pidgin: 47f25059: Add a function to remove a port mapping ...

malu at pidgin.im malu at pidgin.im
Mon Jun 15 17:45:32 EDT 2009


-----------------------------------------------------------------
Revision: 47f25059666d286ddfefc874f5486360935d8c2a
Ancestor: caf1ac283a4ee4be662ae40717b7d7104f76296d
Author: malu at pidgin.im
Date: 2009-06-15T21:43:25
Branch: im.pidgin.pidgin
URL: http://d.pidgin.im/viewmtn/revision/info/47f25059666d286ddfefc874f5486360935d8c2a

Modified files:
        ChangeLog.API libpurple/network.c libpurple/network.h
        libpurple/protocols/jabber/si.c

ChangeLog: 

Add a function to remove a port mapping (UPnP or NAT-PMP) given a file
descriptor.
Adapt the XMPP PRPL to use this to remove port mappings when a file transfer
is done.
There is still no support for removing left-over mappings at exit, since I've
found no good way of calling purple_upnp_remove_port_mapping (which relies on
callbacks) from purple_network_uninit (since the main thread terminates after
the _uninit functions have finished)...


-------------- next part --------------
============================================================
--- ChangeLog.API	7aec22e5459331b097b4c1e62b74192b4ff5c58b
+++ ChangeLog.API	64c38b7abdb448eea7c84eb4afe9dc530debdfa0
@@ -39,6 +39,7 @@ version 2.6.0 (??/??/2009):
 		* purple_network_set_turn_server
 		* purple_network_get_stun_ip
 		* purple_network_get_turn_ip
+		* purple_network_remove_port_mapping
 		* purple_proxy_connect_udp
 		* purple_prpl_get_media_caps
 		* purple_prpl_got_account_actions
============================================================
--- libpurple/network.c	4b70424840eba4e3105b0edd31ab608783da7f2e
+++ libpurple/network.c	2a904f7c2e877f1dbc295fd3d64cceba6d19036a
@@ -105,6 +105,10 @@ static gchar *turn_ip = NULL;
 static gchar *stun_ip = NULL;
 static gchar *turn_ip = NULL;
 
+/* Keep track of port mappings done with UPnP and NAT-PMP */
+static GHashTable *upnp_port_mappings = NULL;
+static GHashTable *nat_pmp_port_mappings = NULL;
+
 const unsigned char *
 purple_network_ip_atoi(const char *ip)
 {
@@ -257,6 +261,15 @@ purple_network_set_upnp_port_mapping_cb(
 		return;
 	}
 
+	if (success) {
+		/* add port mapping to hash table */
+		gint *key = g_new(gint, 1);
+		gint *value = g_new(gint, 1);
+		*key = purple_network_get_port_from_fd(listen_data->listenfd);
+		*value = listen_data->socket_type;
+		g_hash_table_insert(upnp_port_mappings, key, value);
+	}
+
 	if (listen_data->cb)
 		listen_data->cb(listen_data->listenfd, listen_data->cb_data);
 
@@ -892,7 +905,60 @@ purple_network_get_handle(void)
 	return &handle;
 }
 
+static void
+purple_network_upnp_mapping_remove_cb(gboolean sucess, gpointer data)
+{
+	purple_debug_info("network", "done removing UPnP port mapping\n");
+}
+
+/* the reason for these functions to have these signatures is to be able to
+ use them for g_hash_table_foreach to clean remaining port mappings, which is
+ not yet done */
+static void
+purple_network_upnp_mapping_remove(gpointer key, gpointer value,
+	gpointer user_data)
+{
+	gint port = (gint) *((gint *) key);
+	gint protocol = (gint) *((gint *) value);
+	purple_debug_info("network", "removing UPnP port mapping for port %d\n",
+		port);
+	purple_upnp_remove_port_mapping(port, 
+		protocol == SOCK_STREAM ? "TCP" : "UDP", 
+		purple_network_upnp_mapping_remove_cb, NULL);
+}
+
+static void
+purple_network_nat_pmp_mapping_remove(gpointer key, gpointer value,
+	gpointer user_data)
+{
+	gint port = (gint) *((gint *) key);
+	gint protocol = (gint) *((gint *) value);
+	purple_debug_info("network", "removing NAT-PMP port mapping for port %d\n",
+		port);
+	purple_pmp_destroy_map(
+		protocol == SOCK_STREAM ? PURPLE_PMP_TYPE_TCP : PURPLE_PMP_TYPE_UDP, 
+		port);
+}
+
 void
+purple_network_remove_port_mapping(gint fd)
+{
+	int port = purple_network_get_port_from_fd(fd);
+	gint *protocol = g_hash_table_lookup(upnp_port_mappings, &port);
+
+	if (protocol) {
+		purple_network_upnp_mapping_remove(&port, protocol, NULL);
+		g_hash_table_remove(upnp_port_mappings, protocol);
+	} else {
+		protocol = g_hash_table_lookup(nat_pmp_port_mappings, &port);
+		if (protocol) {
+			purple_network_nat_pmp_mapping_remove(&port, protocol, NULL);
+			g_hash_table_remove(nat_pmp_port_mappings, protocol);
+		}
+	}
+}
+	
+void
 purple_network_init(void)
 {
 #ifdef HAVE_NETWORKMANAGER
@@ -964,8 +1030,15 @@ purple_network_init(void)
 		purple_prefs_get_string("/purple/network/stun_server"));
 	purple_network_set_turn_server(
 		purple_prefs_get_string("/purple/network/turn_server"));
+
+	upnp_port_mappings = 
+		g_hash_table_new_full(g_int_hash, g_int_equal, g_free, g_free);
+	nat_pmp_port_mappings =
+		g_hash_table_new_full(g_int_hash, g_int_equal, g_free, g_free);
 }
 
+
+
 void
 purple_network_uninit(void)
 {
@@ -1008,4 +1081,10 @@ purple_network_uninit(void)
 	
 	if (stun_ip)
 		g_free(stun_ip);
+
+	g_hash_table_destroy(upnp_port_mappings);
+	g_hash_table_destroy(nat_pmp_port_mappings);
+
+	/* TODO: clean up remaining port mappings, note calling 
+	 purple_upnp_remove_port_mapping from here doesn't quite work... */
 }
============================================================
--- libpurple/network.h	5f7237ba0a0f2a69ebed06c61aa132945b796237
+++ libpurple/network.h	aaf931aba84bad7a6058d6a52498d0702043eaf8
@@ -259,8 +259,15 @@ const gchar *purple_network_get_turn_ip(
  */
 const gchar *purple_network_get_turn_ip(void);
 		
-	
 /**
+ * Remove a port mapping (UPnP or NAT-PMP) associated with listening socket
+ *
+ * @param fd Socket to remove the port mapping for
+ * @since 2.6.0
+ */
+void purple_network_remove_port_mapping(gint fd);	
+
+/**
  * Initializes the network subsystem.
  */
 void purple_network_init(void);
============================================================
--- libpurple/protocols/jabber/si.c	047237caa692752a8453c10c225a1ee7a79540aa
+++ libpurple/protocols/jabber/si.c	d84149e9c34f10d65b45b45bf56e50ee3819ada0
@@ -1321,6 +1321,11 @@ static void jabber_si_xfer_free(PurpleXf
 			jabber_iq_remove_callback_by_id(js, jsx->iq_id);
 		if (jsx->local_streamhost_fd >= 0)
 			close(jsx->local_streamhost_fd);
+		if (purple_xfer_get_type(xfer) == PURPLE_XFER_SEND &&
+			xfer->fd >= 0) {
+			purple_debug_info("jabber", "remove port mapping\n");
+			purple_network_remove_port_mapping(xfer->fd);
+		}
 		if (jsx->connect_timeout > 0)
 			purple_timeout_remove(jsx->connect_timeout);
 		if (jsx->ibb_timeout_handle > 0)


More information about the Commits mailing list