Revision 92eebaf666f2e1fc850e295152612d773e764f2c
evands at pidgin.im
evands at pidgin.im
Sat Mar 31 16:34:15 EDT 2007
o -----------------------------------------------------------------
| Revision: 92eebaf666f2e1fc850e295152612d773e764f2c
| Ancestor: 5c8fc9e8be1747485235f4be52a2ed3acf9dc62e
| Author: evands at pidgin.im
| Date: 2007-03-31T20:33:54
| Branch: im.pidgin.pidgin
|
| Modified files:
| ChangeLog.API libpurple/Makefile.am libpurple/nat-pmp.c
| libpurple/nat-pmp.h libpurple/network.c libpurple/network.h
| libpurple/upnp.c libpurple/upnp.h
|
| ChangeLog:
|
| The network module now registers the signal 'network-configuration-changed' and emits it when a network change is detected via libnm or the win32 network monitor. The UI could also emit this signal if it knows something network.c doesn't. UPnP and NAT-PMP respond to the signal by clearing their IP address caches; changing networks without quitting/relaunching will now lead to the new IP address being (lazily) determined. This commit also enables nat-pmp and adds nat-pmp.[h|c] to the build process; please let me know if there are any problems building, as I only have OS X test machines.
|
| ============================================================
| --- ChangeLog.API 7d5b4a3e76e446081d5930f73284b1973e3a7a45
| +++ ChangeLog.API c39013970ce25d0a576e86272b2ae8fea8af2bf5
| @@ -416,6 +416,7 @@ version 2.0.0:
| * "gtkblist-hiding"
| * "gtkblist-unhiding"
| * "log-displaying"
| + * "network-configuration-changed"
| * "savedstatus-changed"
| * "sendto-extended-menu"
| * "uri-handler"
| ============================================================
| --- libpurple/Makefile.am 02143704a0dd9f1a16d987b4c722b762c2fb58e6
| +++ libpurple/Makefile.am 532f08086b6418786f8eb71439ffacf79862f3fa
| @@ -49,6 +49,7 @@ purple_coresources = \
| imgstore.c \
| log.c \
| mime.c \
| + nat-pmp.c \
| network.c \
| ntlm.c \
| notify.c \
| @@ -99,6 +100,7 @@ purple_coreheaders = \
| imgstore.h \
| log.h \
| mime.h \
| + nat-pmp.h \
| network.h \
| notify.h \
| ntlm.h \
| ============================================================
| --- libpurple/nat-pmp.c 0cc6b65d22e43ee71a150d303771e55a580a794a
| +++ libpurple/nat-pmp.c 01a2138d2a57a096d3a42d30395b878476a183f0
| @@ -30,6 +30,8 @@
|
| #include "nat-pmp.h"
| #include "debug.h"
| +#include "signals.h"
| +#include "network.h"
|
| #include <arpa/inet.h>
| #include <netinet/in.h>
| @@ -87,6 +89,20 @@ typedef struct _PurplePmpMapResponse Pur
|
| 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 +256,32 @@ purple_pmp_get_public_ip()
| 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 +289,6 @@ purple_pmp_get_public_ip()
| 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 +305,19 @@ purple_pmp_get_public_ip()
| * 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 +325,19 @@ purple_pmp_get_public_ip()
| {
| 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 +348,15 @@ purple_pmp_get_public_ip()
| {
| 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 +375,10 @@ purple_pmp_get_public_ip()
|
| 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 +499,30 @@ purple_pmp_destroy_map(PurplePmpType typ
|
| 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 +541,10 @@ purple_pmp_destroy_map(PurplePmpType typ
| {
| return FALSE;
| }
| +
| +void
| +purple_pmp_init()
| +{
| +
| +}
| #endif /* #ifndef NET_RT_DUMP */
| ============================================================
| --- libpurple/nat-pmp.h 5f2cac238513429f0a46ff2bcf9374b5f61270c3
| +++ libpurple/nat-pmp.h b2dd434326438e746912ec2093af768d5d0f40e9
| @@ -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
| ============================================================
| --- libpurple/network.c 60335f4bd92f820defa3407a93d944941ae7dc91
| +++ libpurple/network.c eb2bd60ce146f635283a73a30a8f825238c68211
| @@ -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 @@ purple_network_get_my_ip(int fd)
| 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_set_upnp_port_mapping_cb(
| purple_network_listen_cancel(listen_data);
| }
|
| -#ifdef ENABLE_NAT_PMP
| static gboolean
| purple_network_finish_pmp_map_cb(gpointer data)
| {
| @@ -265,7 +257,6 @@ purple_network_finish_pmp_map_cb(gpointe
|
| return FALSE;
| }
| -#endif
|
| static PurpleNetworkListenData *
| purple_network_do_listen(unsigned short port, int socket_type, PurpleNetworkListenCallback cb, gpointer cb_data)
| @@ -361,7 +352,6 @@ purple_network_do_listen(unsigned short
| 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_network_do_listen(unsigned short
| 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 @@ static gboolean wpurple_network_change_t
|
| 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 @@ nm_callback_func(libnm_glib_ctx* ctx, gp
| 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 @@ nm_callback_func(libnm_glib_ctx* ctx, gp
| }
| #endif
|
| +void *
| +purple_network_get_handle(void)
| +{
| + static int handle;
| +
| + return &handle;
| +}
| +
| void
| purple_network_init(void)
| {
| @@ -673,6 +674,12 @@ purple_network_init(void)
| 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
| ============================================================
| --- libpurple/network.h 6f8979bf0ba8b30e517d718148b5365ac3d09700
| +++ libpurple/network.h 858b42c7c54f71c5f2008e9a66f1c9b6387de90f
| @@ -197,6 +197,13 @@ gboolean purple_network_is_available(voi
| 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);
| ============================================================
| --- libpurple/upnp.c 96621a5920d0f7ffc49169a7327f4dc3345d3acc
| +++ libpurple/upnp.c f425a77b17efb304f7aa61c8d638d4d575282bb8
| @@ -24,15 +24,16 @@
| */
| #include "internal.h"
|
| +#include "upnp.h"
| +
| #include "debug.h"
| -#include "util.h"
| +#include "eventloop.h"
| +#include "network.h"
| #include "proxy.h"
| +#include "signals.h"
| +#include "util.h"
| #include "xmlnode.h"
| -#include "network.h"
| -#include "eventloop.h"
| -#include "upnp.h"
|
| -
| /***************************************************************
| ** General Defines *
| ****************************************************************/
| @@ -1026,3 +1027,32 @@ purple_upnp_remove_port_mapping(unsigned
| 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));
| +}
| ============================================================
| --- libpurple/upnp.h 528c77de4eda81ff204682df262574a00c3dfec1
| +++ libpurple/upnp.h 7fc0680c51662700ad6ff20b2b618736c1f0aebe
| @@ -41,7 +41,14 @@ typedef void (*PurpleUPnPCallback) (gboo
|
| 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
| * public IP address of the IGD, and control it for forwarding ports.
To get the patch for this revision, please do this:
mtn log --last 1 --diffs --from 92eebaf666f2e1fc850e295152612d773e764f2c
More information about the Commits
mailing list