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