changeset 15446:910f4be8fc73

merge of '9425adf9514855b6d4a3c79a57ad0cbea1f48a82' and '9bd03762a44c1606ac1dcfa7b7eebc9eb51ea73c'
author Ethan Blanton <elb@pidgin.im>
date Sun, 28 Jan 2007 17:01:22 +0000
parents 8721df7d419f (current diff) 56a2a0bb290a (diff)
children 8c81db398f56
files
diffstat 3 files changed, 87 insertions(+), 35 deletions(-) [+]
line wrap: on
line diff
--- a/libpurple/network.c	Sun Jan 28 09:02:20 2007 +0000
+++ b/libpurple/network.c	Sun Jan 28 17:01:22 2007 +0000
@@ -74,6 +74,7 @@
 	gboolean adding;
 	GaimNetworkListenCallback cb;
 	gpointer cb_data;
+	UPnPMappingAddRemove *mapping_data;
 };
 
 #ifdef HAVE_LIBNM
@@ -210,28 +211,29 @@
 		if (listen_data->retry) {
 			listen_data->retry = FALSE;
 			listen_data->adding = FALSE;
-			/* TODO: Need to keep track of this return value! */
-			gaim_upnp_remove_port_mapping(
-				gaim_network_get_port_from_fd(listen_data->listenfd),
-				(listen_data->socket_type == SOCK_STREAM) ? "TCP" : "UDP",
-				gaim_network_set_upnp_port_mapping_cb, listen_data);
+			listen_data->mapping_data = gaim_upnp_remove_port_mapping(
+						gaim_network_get_port_from_fd(listen_data->listenfd),
+						(listen_data->socket_type == SOCK_STREAM) ? "TCP" : "UDP",
+						gaim_network_set_upnp_port_mapping_cb, listen_data);
 			return;
 		}
 	} else if (!listen_data->adding) {
 		/* We've tried successfully to remove the port mapping.
 		 * Try to add it again */
 		listen_data->adding = TRUE;
-		/* TODO: Need to keep track of this return value! */
-		gaim_upnp_set_port_mapping(
-			gaim_network_get_port_from_fd(listen_data->listenfd),
-			(listen_data->socket_type == SOCK_STREAM) ? "TCP" : "UDP",
-			gaim_network_set_upnp_port_mapping_cb, listen_data);
+		listen_data->mapping_data = gaim_upnp_set_port_mapping(
+					gaim_network_get_port_from_fd(listen_data->listenfd),
+					(listen_data->socket_type == SOCK_STREAM) ? "TCP" : "UDP",
+					gaim_network_set_upnp_port_mapping_cb, listen_data);
 		return;
 	}
 
 	if (listen_data->cb)
 		listen_data->cb(listen_data->listenfd, listen_data->cb_data);
 
+	/* Clear the UPnP mapping data, since it's complete and gaim_netweork_listen_cancel() will try to cancel
+	 * it otherwise. */
+	listen_data->mapping_data = NULL;
 	gaim_network_listen_cancel(listen_data);
 }
 
@@ -327,11 +329,10 @@
 	listen_data->cb = cb;
 	listen_data->cb_data = cb_data;
 
-	/* TODO: Need to keep track of this return value! */
-	gaim_upnp_set_port_mapping(
-			gaim_network_get_port_from_fd(listenfd),
-			(socket_type == SOCK_STREAM) ? "TCP" : "UDP",
-			gaim_network_set_upnp_port_mapping_cb, listen_data);
+	listen_data->mapping_data = gaim_upnp_set_port_mapping(
+					gaim_network_get_port_from_fd(listenfd),
+					(socket_type == SOCK_STREAM) ? "TCP" : "UDP",
+					gaim_network_set_upnp_port_mapping_cb, listen_data);
 
 	return listen_data;
 }
@@ -370,6 +371,9 @@
 
 void gaim_network_listen_cancel(GaimNetworkListenData *listen_data)
 {
+	if (listen_data->mapping_data != NULL)
+		gaim_upnp_cancel_port_mapping(listen_data->mapping_data);
+
 	g_free(listen_data);
 }
 
--- a/libpurple/upnp.c	Sun Jan 28 09:02:20 2007 +0000
+++ b/libpurple/upnp.c	Sun Jan 28 17:01:22 2007 +0000
@@ -131,13 +131,16 @@
 	gchar *full_url;
 } UPnPDiscoveryData;
 
-typedef struct {
+struct _UPnPMappingAddRemove
+{
 	unsigned short portmap;
 	gchar protocol[4];
 	gboolean add;
 	GaimUPnPCallback cb;
 	gpointer cb_data;
-} UPnPMappingAddRemove;
+	guint tima; /* gaim_timeout_add handle */
+	GaimUtilFetchUrlData *gfud;
+};
 
 static GaimUPnPControlInfo control_info = {
 	GAIM_UPNP_STATUS_UNDISCOVERED,
@@ -666,12 +669,12 @@
 	gaim_upnp_discover_send_broadcast(dd);
 }
 
-static void
+static GaimUtilFetchUrlData*
 gaim_upnp_generate_action_message_and_send(const gchar* actionName,
 		const gchar* actionParams, GaimUtilFetchUrlCallback cb,
 		gpointer cb_data)
 {
-
+	GaimUtilFetchUrlData* gfud;
 	gchar* soapMessage;
 	gchar* totalSendMessage;
 	gchar* pathOfControl;
@@ -703,11 +706,13 @@
 	g_free(pathOfControl);
 	g_free(soapMessage);
 
-	gaim_util_fetch_url_request(control_info.control_url, FALSE, NULL, TRUE,
-			totalSendMessage, TRUE, cb, cb_data);
+	gfud = gaim_util_fetch_url_request(control_info.control_url, FALSE, NULL, TRUE,
+				totalSendMessage, TRUE, cb, cb_data);
 
 	g_free(totalSendMessage);
 	g_free(addressOfControl);
+	
+	return gfud;
 }
 
 const gchar *
@@ -884,8 +889,8 @@
 				ar->portmap, ar->protocol);
 		}
 
-		gaim_upnp_generate_action_message_and_send(action_name,
-				action_params, done_port_mapping_cb, ar);
+		ar->gfud = gaim_upnp_generate_action_message_and_send(action_name,
+						action_params, done_port_mapping_cb, ar);
 
 		g_free(action_params);
 		return;
@@ -904,7 +909,33 @@
 	return FALSE;
 }
 
-void
+void gaim_upnp_cancel_port_mapping(UPnPMappingAddRemove *ar)
+{
+	GSList *l;
+
+	/* Remove ar from discovery_callbacks if present; it was inserted after a cb.
+	 * The same cb may be in the list multple times, so be careful to remove the one assocaited with ar. */
+	l  = discovery_callbacks;
+	while (l)
+	{
+		if (l->next && (l->next->data == ar)) {
+			discovery_callbacks = g_slist_delete_link(discovery_callbacks, l->next);
+			discovery_callbacks = g_slist_delete_link(discovery_callbacks, l);
+		}
+
+		l = l->next;
+	}
+
+	if (ar->tima > 0)
+		gaim_timeout_remove(ar->tima);
+
+	if (ar->gfud)
+		gaim_util_fetch_url_cancel(ar->gfud);
+
+	g_free(ar);
+}
+
+UPnPMappingAddRemove *
 gaim_upnp_set_port_mapping(unsigned short portmap, const gchar* protocol,
 		GaimUPnPCallback cb, gpointer cb_data)
 {
@@ -925,7 +956,7 @@
 				discovery_callbacks, do_port_mapping_cb);
 		discovery_callbacks = g_slist_append(
 				discovery_callbacks, ar);
-		return;
+		return ar;
 	}
 
 	/* If we haven't had a successful UPnP discovery, check if 5 minutes has
@@ -934,22 +965,24 @@
 			(control_info.status == GAIM_UPNP_STATUS_UNABLE_TO_DISCOVER
 			 && (time(NULL) - control_info.lookup_time) > 300)) {
 		gaim_upnp_discover(do_port_mapping_cb, ar);
-		return;
+		return ar;
 	} else if(control_info.status == GAIM_UPNP_STATUS_UNABLE_TO_DISCOVER) {
 		if (cb) {
 			/* Asynchronously trigger a failed response */
-			gaim_timeout_add(10, fire_port_mapping_failure_cb, ar);
+			ar->tima = gaim_timeout_add(10, fire_port_mapping_failure_cb, ar);
 		} else {
 			/* No need to do anything if nobody expects a response*/
 			g_free(ar);
+			ar = NULL;
 		}
-		return;
+		return ar;
 	}
 
 	do_port_mapping_cb(TRUE, ar);
+	return ar;
 }
 
-void
+UPnPMappingAddRemove *
 gaim_upnp_remove_port_mapping(unsigned short portmap, const char* protocol,
 		GaimUPnPCallback cb, gpointer cb_data)
 {
@@ -968,7 +1001,7 @@
 				discovery_callbacks, do_port_mapping_cb);
 		discovery_callbacks = g_slist_append(
 				discovery_callbacks, ar);
-		return;
+		return ar;
 	}
 
 	/* If we haven't had a successful UPnP discovery, check if 5 minutes has
@@ -977,17 +1010,19 @@
 			(control_info.status == GAIM_UPNP_STATUS_UNABLE_TO_DISCOVER
 			 && (time(NULL) - control_info.lookup_time) > 300)) {
 		gaim_upnp_discover(do_port_mapping_cb, ar);
-		return;
+		return ar;
 	} else if(control_info.status == GAIM_UPNP_STATUS_UNABLE_TO_DISCOVER) {
 		if (cb) {
 			/* Asynchronously trigger a failed response */
-			gaim_timeout_add(10, fire_port_mapping_failure_cb, ar);
+			ar->tima = gaim_timeout_add(10, fire_port_mapping_failure_cb, ar);
 		} else {
 			/* No need to do anything if nobody expects a response*/
 			g_free(ar);
+			ar = NULL;
 		}
-		return;
+		return ar;
 	}
 
 	do_port_mapping_cb(TRUE, ar);
+	return ar;
 }
--- a/libpurple/upnp.h	Sun Jan 28 09:02:20 2007 +0000
+++ b/libpurple/upnp.h	Sun Jan 28 17:01:22 2007 +0000
@@ -26,6 +26,7 @@
 #ifndef _GAIM_UPNP_H_
 #define _GAIM_UPNP_H_
 
+typedef struct _UPnPMappingAddRemove UPnPMappingAddRemove;
 
 #ifdef __cplusplus
 extern "C" {
@@ -74,6 +75,14 @@
 const gchar* gaim_upnp_get_public_ip(void);
 
 /**
+ * Cancel a pending port mapping request initiated with either
+ * gaim_upnp_set_port_mapping() or gaim_upnp_remove_port_mapping().
+ *
+ * @param mapping_data The data returned when you initiated the UPnP mapping request.
+ */
+void gaim_upnp_cancel_port_mapping(UPnPMappingAddRemove *mapping_data);
+
+/**
  * Maps Ports in a UPnP enabled IGD that sits on the local network to
  * this gaim client. Essentially, this function takes care of the port
  * forwarding so things like file transfers can work behind NAT firewalls
@@ -83,8 +92,10 @@
  * @param cb an optional callback function to be notified when the mapping
  *           addition is complete
  * @param cb_data Extra data to be passed to the callback
+ *
+ * @return Data which can be passed to gaim_upnp_port_mapping_cancel() to cancel
  */
-void gaim_upnp_set_port_mapping(unsigned short portmap, const gchar* protocol,
+UPnPMappingAddRemove *gaim_upnp_set_port_mapping(unsigned short portmap, const gchar* protocol,
 		GaimUPnPCallback cb, gpointer cb_data);
 
 /**
@@ -98,8 +109,10 @@
  * @param cb an optional callback function to be notified when the mapping
  *           removal is complete
  * @param cb_data Extra data to be passed to the callback
+ *
+ * @return Data which can be passed to gaim_upnp_port_mapping_cancel() to cancel
  */
-void gaim_upnp_remove_port_mapping(unsigned short portmap,
+UPnPMappingAddRemove *gaim_upnp_remove_port_mapping(unsigned short portmap,
 		const gchar* protocol, GaimUPnPCallback cb, gpointer cb_data);
 
 /*@}*/