changeset 15977:499ed587543a

merge of 'e23bc35af900cf0925d85813b5896e19f73645d2' and 'ed972b3dfab31a2b23f4b191bfe7d4dcab7cc765'
author Sadrul Habib Chowdhury <imadil@gmail.com>
date Sun, 01 Apr 2007 03:47:50 +0000
parents 5eb0621e0760 (current diff) a6a79b8616bf (diff)
children 2a82bc8d57f7
files
diffstat 11 files changed, 181 insertions(+), 49 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog.API	Sun Apr 01 03:46:58 2007 +0000
+++ b/ChangeLog.API	Sun Apr 01 03:47:50 2007 +0000
@@ -416,6 +416,7 @@
 	* "gtkblist-hiding"
 	* "gtkblist-unhiding"
 	* "log-displaying"
+	* "network-configuration-changed"
 	* "savedstatus-changed"
 	* "sendto-extended-menu"
 	* "uri-handler"
--- a/libpurple/Makefile.am	Sun Apr 01 03:46:58 2007 +0000
+++ b/libpurple/Makefile.am	Sun Apr 01 03:47:50 2007 +0000
@@ -49,6 +49,7 @@
 	imgstore.c \
 	log.c \
 	mime.c \
+	nat-pmp.c \
 	network.c \
 	ntlm.c \
 	notify.c \
@@ -99,6 +100,7 @@
 	imgstore.h \
 	log.h \
 	mime.h \
+	nat-pmp.h \
 	network.h \
 	notify.h \
 	ntlm.h \
--- a/libpurple/Makefile.mingw	Sun Apr 01 03:46:58 2007 +0000
+++ b/libpurple/Makefile.mingw	Sun Apr 01 03:47:50 2007 +0000
@@ -48,6 +48,7 @@
 			imgstore.c \
 			log.c \
 			mime.c \
+			nat-pmp.c \
 			network.c \
 			notify.c \
 			ntlm.c \
--- a/libpurple/nat-pmp.c	Sun Apr 01 03:46:58 2007 +0000
+++ b/libpurple/nat-pmp.c	Sun Apr 01 03:47:50 2007 +0000
@@ -30,24 +30,28 @@
 
 #include "nat-pmp.h"
 #include "debug.h"
+#include "signals.h"
+#include "network.h"
 
+#include <sys/types.h>
+#ifndef _WIN32
 #include <arpa/inet.h>
 #include <netinet/in.h>
-#include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/sysctl.h>
 
+#include <net/if.h>
 #include <net/route.h>
 
 #include <netdb.h>
+#include <err.h>
+#endif
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <err.h>
 
 #include <errno.h>
-#include <sys/types.h>
-#include <net/if.h>
 
 #ifdef NET_RT_DUMP
 
@@ -87,6 +91,20 @@
 
 typedef struct _PurplePmpMapResponse PurplePmpMapResponse;
 
+typedef enum {
+	PURPLE_PMP_STATUS_UNDISCOVERED = -1,
+	PURPLE_PMP_STATUS_UNABLE_TO_DISCOVER,
+	PURPLE_PMP_STATUS_DISCOVERING,
+	PURPLE_PMP_STATUS_DISCOVERED
+} PurpleUPnPStatus;
+
+typedef struct {
+	PurpleUPnPStatus status;
+	gchar *publicip;
+} PurplePmpInfo;
+
+static PurplePmpInfo pmp_info = {PURPLE_PMP_STATUS_UNDISCOVERED, NULL};
+
 /*
  *	Thanks to R. Matthew Emerson for the fixes on this
  */
@@ -240,11 +258,32 @@
 char *
 purple_pmp_get_public_ip()
 {
-	struct sockaddr_in *gateway = default_gw();
+	struct sockaddr_in addr, *gateway, *publicsockaddr = NULL;
+	struct timeval req_timeout;
+	socklen_t len;
+
+	PurplePmpIpRequest req;
+	PurplePmpIpResponse resp;
+	int sendfd;
+	
+	if (pmp_info.status == PURPLE_PMP_STATUS_UNABLE_TO_DISCOVER)
+		return NULL;
+	
+	if ((pmp_info.status == PURPLE_PMP_STATUS_DISCOVERED) && (pmp_info.publicip != NULL))
+	{
+#ifdef PMP_DEBUG
+		purple_debug_info("nat-pmp", "Returning cached publicip %s",pmp_info.publicip);
+#endif
+		return pmp_info.publicip;
+	}
+
+	gateway = default_gw();
 
 	if (!gateway)
 	{
 		purple_debug_info("nat-pmp", "Cannot request public IP from a NULL gateway!\n");
+		/* If we get a NULL gateway, don't try again next time */
+		pmp_info.status = PURPLE_PMP_STATUS_UNABLE_TO_DISCOVER;
 		return NULL;
 	}
 
@@ -252,12 +291,6 @@
 	if (gateway->sin_port != PMP_PORT)
 		gateway->sin_port = htons(PMP_PORT);
 
-	int sendfd;
-	struct timeval req_timeout;
-	PurplePmpIpRequest req;
-	PurplePmpIpResponse resp;
-	struct sockaddr_in *publicsockaddr = NULL;
-
 	req_timeout.tv_sec = 0;
 	req_timeout.tv_usec = PMP_TIMEOUT;
 
@@ -274,20 +307,19 @@
 	 * With the recommended timeout of 0.25 seconds, we're talking 511.5 seconds (8.5 minutes).
 	 * 
 	 * This seems really silly... if this were nonblocking, a couple retries might be in order, but it's not at present.
-	 * XXX Make this nonblocking.
 	 */
 #ifdef PMP_DEBUG
 	purple_debug_info("nat-pmp", "Attempting to retrieve the public ip address for the NAT device at: %s\n", inet_ntoa(gateway->sin_addr));
 	purple_debug_info("nat-pmp", "\tTimeout: %ds %dus\n", req_timeout.tv_sec, req_timeout.tv_usec);
 #endif
-	struct sockaddr_in addr;
-	socklen_t len = sizeof(struct sockaddr_in);
 
 	/* TODO: Non-blocking! */
+	
 	if (sendto(sendfd, &req, sizeof(req), 0, (struct sockaddr *)(gateway), sizeof(struct sockaddr)) < 0)
 	{
 		purple_debug_info("nat-pmp", "There was an error sending the NAT-PMP public IP request! (%s)\n", strerror(errno));
 		g_free(gateway);
+		pmp_info.status = PURPLE_PMP_STATUS_UNABLE_TO_DISCOVER;
 		return NULL;
 	}
 
@@ -295,16 +327,19 @@
 	{
 		purple_debug_info("nat-pmp", "There was an error setting the socket's options! (%s)\n", strerror(errno));
 		g_free(gateway);
+		pmp_info.status = PURPLE_PMP_STATUS_UNABLE_TO_DISCOVER;
 		return NULL;
 	}		
 
 	/* TODO: Non-blocking! */
+	len = sizeof(struct sockaddr_in);
 	if (recvfrom(sendfd, &resp, sizeof(PurplePmpIpResponse), 0, (struct sockaddr *)(&addr), &len) < 0)
 	{			
 		if (errno != EAGAIN)
 		{
 			purple_debug_info("nat-pmp", "There was an error receiving the response from the NAT-PMP device! (%s)\n", strerror(errno));
 			g_free(gateway);
+			pmp_info.status = PURPLE_PMP_STATUS_UNABLE_TO_DISCOVER;
 			return NULL;
 		}
 	}
@@ -315,11 +350,15 @@
 	{
 		purple_debug_info("nat-pmp", "Response was not received from our gateway! Instead from: %s\n", inet_ntoa(addr.sin_addr));
 		g_free(gateway);
+
+		pmp_info.status = PURPLE_PMP_STATUS_UNABLE_TO_DISCOVER;
 		return NULL;
 	}
 
 	if (!publicsockaddr) {
 		g_free(gateway);
+		
+		pmp_info.status = PURPLE_PMP_STATUS_UNABLE_TO_DISCOVER;
 		return NULL;
 	}
 
@@ -338,6 +377,10 @@
 
 	g_free(gateway);
 
+	g_free(pmp_info.publicip);
+	pmp_info.publicip = g_strdup(inet_ntoa(publicsockaddr->sin_addr));
+	pmp_info.status = PURPLE_PMP_STATUS_DISCOVERED;
+
 	return inet_ntoa(publicsockaddr->sin_addr);
 }
 
@@ -458,6 +501,30 @@
 
 	return success;
 }
+
+static void
+purple_pmp_network_config_changed_cb(void *data)
+{
+	pmp_info.status = PURPLE_PMP_STATUS_UNDISCOVERED;
+	g_free(pmp_info.publicip);
+	pmp_info.publicip = NULL;
+}
+
+static void*
+purple_pmp_get_handle(void)
+{
+	static int handle;
+
+	return &handle;	
+}
+
+void
+purple_pmp_init()
+{
+	purple_signal_connect(purple_network_get_handle(), "network-configuration-changed",
+		  purple_pmp_get_handle(), PURPLE_CALLBACK(purple_pmp_network_config_changed_cb),
+		  GINT_TO_POINTER(0));	
+}
 #else /* #ifdef NET_RT_DUMP */
 char *
 purple_pmp_get_public_ip()
@@ -476,4 +543,10 @@
 {
 	return FALSE;
 }
+
+void
+purple_pmp_init()
+{
+
+}
 #endif /* #ifndef NET_RT_DUMP */
--- a/libpurple/nat-pmp.h	Sun Apr 01 03:46:58 2007 +0000
+++ b/libpurple/nat-pmp.h	Sun Apr 01 03:47:50 2007 +0000
@@ -36,27 +36,20 @@
 
 #define PURPLE_PMP_LIFETIME	3600	/* 3600 seconds */
 
-/*
- *	uint8_t:	version, opcodes
- *	uint16_t:	resultcode
- *	unint32_t:	epoch (seconds since mappings reset)
- */
-
 typedef enum {
 	PURPLE_PMP_TYPE_UDP,
 	PURPLE_PMP_TYPE_TCP
 } PurplePmpType;
 
 /**
+ * Initialize nat-pmp
+ */
+void purple_pmp_init(void);
+
+/**
  *
  */
-
-/*
- * TODO: This should probably cache the result of this lookup requests
- *       so that subsequent calls to this function do not require a
- *       round-trip exchange with the local router.
- */
-char *purple_pmp_get_public_ip();
+char *purple_pmp_get_public_ip(void);
 
 /**
  * Remove the NAT-PMP mapping for a specified type on a specified port
@@ -79,5 +72,6 @@
  * @returns TRUE if succesful; FALSE if unsuccessful
  */
 gboolean purple_pmp_destroy_map(PurplePmpType type, unsigned short privateport);
-	
-#endif
\ No newline at end of file
+
+#endif
+
--- a/libpurple/network.c	Sun Apr 01 03:46:58 2007 +0000
+++ b/libpurple/network.c	Sun Apr 01 03:47:50 2007 +0000
@@ -42,17 +42,12 @@
 
 #include "debug.h"
 #include "account.h"
+#include "nat-pmp.h"
 #include "network.h"
 #include "prefs.h"
 #include "stun.h"
 #include "upnp.h"
 
-/* #define ENABLE_NAT_PMP 1 */
-
-#ifdef ENABLE_NAT_PMP
-#include "nat-pmp.h"
-#endif
-
 /*
  * Calling sizeof(struct ifreq) isn't always correct on
  * Mac OS X (and maybe others).
@@ -198,12 +193,10 @@
 	if (ip != NULL)
 	  return ip;
 
-#ifdef ENABLE_NAT_PMP
 	/* Attempt to get the IP from a NAT device using NAT-PMP */
 	ip = purple_pmp_get_public_ip();
 	if (ip != NULL)
 		return ip;
-#endif
 
 	/* Just fetch the IP of the local system */
 	return purple_network_get_local_system_ip(fd);
@@ -250,7 +243,6 @@
 	purple_network_listen_cancel(listen_data);
 }
 
-#ifdef ENABLE_NAT_PMP
 static gboolean
 purple_network_finish_pmp_map_cb(gpointer data)
 {
@@ -265,7 +257,6 @@
 
 	return FALSE;
 }
-#endif
 
 static PurpleNetworkListenData *
 purple_network_do_listen(unsigned short port, int socket_type, PurpleNetworkListenCallback cb, gpointer cb_data)
@@ -361,7 +352,6 @@
 	listen_data->cb = cb;
 	listen_data->cb_data = cb_data;
 
-#ifdef ENABLE_NAT_PMP
 	/* Attempt a NAT-PMP Mapping, which will return immediately */
 	if (purple_pmp_create_map(((socket_type == SOCK_STREAM) ? PURPLE_PMP_TYPE_TCP : PURPLE_PMP_TYPE_UDP),
 							  actual_port, actual_port, PURPLE_PMP_LIFETIME))
@@ -371,7 +361,6 @@
 		purple_timeout_add(0, purple_network_finish_pmp_map_cb, listen_data);
 	}
 	else
-#endif
 	{
 		/* Attempt a UPnP Mapping */
 		listen_data->mapping_data = purple_upnp_set_port_mapping(
@@ -508,6 +497,8 @@
 
 	purple_debug_info("network", "Received Network Change Notification. Current network count is %d, previous count was %d.\n", new_count, current_network_count);
 
+	purple_signal_emit(purple_network_get_handle(), "network-configuration-changed", NULL);
+
 	if (new_count > 0 && ui_ops != NULL && ui_ops->network_connected != NULL) {
 		ui_ops->network_connected();
 	} else if (new_count == 0 && current_network_count > 0 &&
@@ -616,6 +607,8 @@
 	current = libnm_glib_get_network_state(ctx);
 	purple_debug_info("network","Entering nm_callback_func!\n");
 
+	purple_signal_emit(purple_network_get_handle(), "network-configuration-changed", NULL);
+
 	switch(current)
 	{
 	case LIBNM_ACTIVE_NETWORK_CONNECTION:
@@ -641,6 +634,14 @@
 }
 #endif
 
+void *
+purple_network_get_handle(void)
+{
+	static int handle;
+	
+	return &handle;
+}
+
 void
 purple_network_init(void)
 {
@@ -673,6 +674,12 @@
 	if(nm_context)
 		nm_callback_idx = libnm_glib_register_callback(nm_context, nm_callback_func, NULL, g_main_context_default());
 #endif
+
+	purple_signal_register(purple_network_get_handle(), "network-configuration-changed",
+						   purple_marshal_VOID, NULL, 0);
+	
+	purple_pmp_init();
+	purple_upnp_init();
 }
 
 void
--- a/libpurple/network.h	Sun Apr 01 03:46:58 2007 +0000
+++ b/libpurple/network.h	Sun Apr 01 03:47:50 2007 +0000
@@ -197,6 +197,13 @@
 gboolean purple_network_is_available(void);
 
 /**
+ * Get the handle for the network system
+ *
+ * @return the handle to the network system
+ */
+void *purple_network_get_handle(void);
+
+/**
  * Initializes the network subsystem.
  */
 void purple_network_init(void);
--- a/libpurple/protocols/silc/util.c	Sun Apr 01 03:46:58 2007 +0000
+++ b/libpurple/protocols/silc/util.c	Sun Apr 01 03:47:50 2007 +0000
@@ -444,8 +444,6 @@
 		strcat(buf, "[private] ");
 	if (mode & SILC_CHANNEL_MODE_SECRET)
 		strcat(buf, "[secret] ");
-	if (mode & SILC_CHANNEL_MODE_SECRET)
-		strcat(buf, "[secret] ");
 	if (mode & SILC_CHANNEL_MODE_PRIVKEY)
 		strcat(buf, "[private key] ");
 	if (mode & SILC_CHANNEL_MODE_INVITE)
--- a/libpurple/proxy.c	Sun Apr 01 03:46:58 2007 +0000
+++ b/libpurple/proxy.c	Sun Apr 01 03:47:50 2007 +0000
@@ -87,6 +87,12 @@
 
 static void try_connect(PurpleProxyConnectData *connect_data);
 
+/*
+ * TODO: Eventually (GObjectification) this bad boy will be removed, because it is
+ *       a gross fix for a crashy problem.
+ */
+#define PURPLE_PROXY_CONNECT_DATA_IS_VALID(connect_data) g_slist_find(handles, connect_data)
+
 /**************************************************************************
  * Proxy structure API
  **************************************************************************/
@@ -389,6 +395,12 @@
 	int error = 0;
 	int ret;
 
+	/* If the socket-connected message had already been triggered when connect_data
+ 	 * was destroyed via purple_proxy_connect_cancel(), we may get here with a freed connect_data.
+ 	 */
+	if (!PURPLE_PROXY_CONNECT_DATA_IS_VALID(connect_data))
+		return;
+	
 	purple_debug_info("proxy", "Connected to %s:%d.\n",
 					connect_data->host, connect_data->port);
 
--- a/libpurple/upnp.c	Sun Apr 01 03:46:58 2007 +0000
+++ b/libpurple/upnp.c	Sun Apr 01 03:47:50 2007 +0000
@@ -24,14 +24,15 @@
  */
 #include "internal.h"
 
-#include "debug.h"
-#include "util.h"
-#include "proxy.h"
-#include "xmlnode.h"
-#include "network.h"
-#include "eventloop.h"
 #include "upnp.h"
 
+#include "debug.h"
+#include "eventloop.h"
+#include "network.h"
+#include "proxy.h"
+#include "signals.h"
+#include "util.h"
+#include "xmlnode.h"
 
 /***************************************************************
 ** General Defines                                             *
@@ -1026,3 +1027,32 @@
 	do_port_mapping_cb(TRUE, ar);
 	return ar;
 }
+
+static void
+purple_upnp_network_config_changed_cb(void *data)
+{
+	/* Reset the control_info to default values */
+	control_info.status = PURPLE_UPNP_STATUS_UNDISCOVERED;
+	g_free(control_info.control_url);
+	control_info.control_url = NULL;
+	control_info.service_type[0] = '\0';
+	control_info.publicip[0] = '\0';
+	control_info.internalip[0] = '\0';
+	control_info.lookup_time = 0;
+}
+
+static void*
+purple_upnp_get_handle(void)
+{
+	static int handle;
+	
+	return &handle;	
+}
+
+void
+purple_upnp_init()
+{
+	purple_signal_connect(purple_network_get_handle(), "network-configuration-changed",
+						  purple_upnp_get_handle(), PURPLE_CALLBACK(purple_upnp_network_config_changed_cb),
+						  GINT_TO_POINTER(0));		
+}
--- a/libpurple/upnp.h	Sun Apr 01 03:46:58 2007 +0000
+++ b/libpurple/upnp.h	Sun Apr 01 03:47:50 2007 +0000
@@ -41,6 +41,13 @@
 
 typedef void (*PurpleUPnPCallback) (gboolean success, gpointer data);
 
+
+/**
+ * Initialize UPnP
+ */
+void purple_upnp_init(void);
+
+
 /**
  * Sends a discovery request to search for a UPnP enabled IGD that
  * contains the WANIPConnection service that will allow us to recieve the