changeset 14696:34083fe39891

[gaim-migrate @ 17448] From Paul Betts, NetworkManager integration. This will smartly disconnect and reconnect accounts according to network availability. Probably needs some more tweaking. committer: Tailor Script <tailor@pidgin.im>
author Sean Egan <seanegan@gmail.com>
date Sun, 08 Oct 2006 08:40:09 +0000
parents fa0c8fa2b5a7
children 1136736fdd2c
files COPYRIGHT configure.ac gtk/gtkconn.c libgaim/Makefile.am libgaim/account.c libgaim/connection.h libgaim/network.c libgaim/network.h
diffstat 8 files changed, 150 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/COPYRIGHT	Sun Oct 08 04:31:39 2006 +0000
+++ b/COPYRIGHT	Sun Oct 08 08:40:09 2006 +0000
@@ -22,6 +22,7 @@
 Curtis Beattie
 Dave Bell
 Igor Belyi
+Paul Betts
 Brian Bernas
 Jonas Birmé
 Eric Blade
--- a/configure.ac	Sun Oct 08 04:31:39 2006 +0000
+++ b/configure.ac	Sun Oct 08 08:40:09 2006 +0000
@@ -887,6 +887,14 @@
 		AC_MSG_RESULT(no)
 		enable_dbus=no
 	])
+
+dnl     Check for libnm_glib; if we don't have it, oh well
+	PKG_CHECK_MODULES(LIBNM, libnm_glib,
+	[
+    		AC_DEFINE(HAVE_LIBNM, 1, [Check to see if we have NetworkManager])
+	])
+	AC_SUBST(LIBNM_CFLAGS)
+	AC_SUBST(LIBNM_LIBS)
 fi
 
 dnl #######################################################################
--- a/gtk/gtkconn.c	Sun Oct 08 04:31:39 2006 +0000
+++ b/gtk/gtkconn.c	Sun Oct 08 08:40:09 2006 +0000
@@ -101,13 +101,6 @@
 }
 
 static void
-gaim_gtk_connection_notice(GaimConnection *gc,
-		const char *text)
-{
-}
-
-
-static void
 free_auto_recon(gpointer data)
 {
 	GaimAutoRecon *info = data;
@@ -201,6 +194,32 @@
 	}
 }
 
+static void gaim_gtk_connection_network_connected () 
+{
+	GList *list = gaim_accounts_get_all_active();
+	while (list) {
+		GaimAccount *account = (GaimAccount*)list->data;
+		GaimAutoRecon *info = g_hash_table_lookup(hash, account);
+		if (info)
+			free_auto_recon(info);
+		do_signon(account);
+		list = list->next;
+ 	}
+}
+
+static void gaim_gtk_connection_network_disconnected () 
+{
+	GList *l = gaim_accounts_get_all_active();
+	while (l) {
+		GaimAccount *a = (GaimAccount*)l->data;
+		gaim_account_disconnect(a);
+		l = l->next;
+	}
+}
+
+static void gaim_gtk_connection_notice(GaimConnection *gc, const char *text)
+{ }
+
 static GaimConnectionUiOps conn_ui_ops =
 {
 	gaim_gtk_connection_connect_progress,
@@ -208,6 +227,8 @@
 	gaim_gtk_connection_disconnected,
 	gaim_gtk_connection_notice,
 	gaim_gtk_connection_report_disconnect,
+	gaim_gtk_connection_network_connected,
+	gaim_gtk_connection_network_disconnected
 };
 
 GaimConnectionUiOps *
--- a/libgaim/Makefile.am	Sun Oct 08 04:31:39 2006 +0000
+++ b/libgaim/Makefile.am	Sun Oct 08 08:40:09 2006 +0000
@@ -218,6 +218,7 @@
 	$(DBUS_LIBS) \
 	$(GLIB_LIBS) \
 	$(LIBXML_LIBS) \
+	$(LIBNM_LIBS) \
 	$(STATIC_LINK_LIBS) \
 	$(INTLLIBS) \
 	-lm
@@ -231,4 +232,5 @@
 	$(GLIB_CFLAGS) \
 	$(DEBUG_CFLAGS) \
 	$(DBUS_CFLAGS) \
-	$(LIBXML_CFLAGS)
+	$(LIBXML_CFLAGS) \
+	$(LIBNM_CFLAGS)
--- a/libgaim/account.c	Sun Oct 08 04:31:39 2006 +0000
+++ b/libgaim/account.c	Sun Oct 08 08:40:09 2006 +0000
@@ -27,6 +27,7 @@
 #include "core.h"
 #include "dbus-maybe.h"
 #include "debug.h"
+#include "network.h"
 #include "notify.h"
 #include "pounce.h"
 #include "prefs.h"
@@ -2242,6 +2243,13 @@
 	GList *l;
 	GaimAccount *account;
 
+	/* If we're not connected to the Internet right now, we bail on this */
+	if (!gaim_network_is_available())
+	{
+		fprintf(stderr, "Network not connected; skipping reconnect\n");
+		return;
+	}
+
 	for (l = gaim_accounts_get_all(); l != NULL; l = l->next)
 	{
 		account = (GaimAccount *)l->data;
--- a/libgaim/connection.h	Sun Oct 08 04:31:39 2006 +0000
+++ b/libgaim/connection.h	Sun Oct 08 08:40:09 2006 +0000
@@ -68,6 +68,8 @@
 	void (*disconnected)(GaimConnection *gc);
 	void (*notice)(GaimConnection *gc, const char *text);
 	void (*report_disconnect)(GaimConnection *gc, const char *text);
+	void (*network_connected)();
+	void (*network_disconnected)();
 
 } GaimConnectionUiOps;
 
--- a/libgaim/network.c	Sun Oct 08 04:31:39 2006 +0000
+++ b/libgaim/network.c	Sun Oct 08 08:40:09 2006 +0000
@@ -42,6 +42,14 @@
 #include "stun.h"
 #include "upnp.h"
 
+#ifdef HAVE_LIBNM
+#include <libnm_glib.h>
+
+libnm_glib_ctx *nm_context = NULL;
+guint nm_callback_idx = 0;
+
+#endif
+
 struct _GaimNetworkListenData {
 	int listenfd;
 	int socket_type;
@@ -51,6 +59,10 @@
 	gpointer cb_data;
 };
 
+#ifdef HAVE_LIBNM
+void nm_callback_func(libnm_glib_ctx* ctx, gpointer user_data);
+#endif
+
 const unsigned char *
 gaim_network_ip_atoi(const char *ip)
 {
@@ -360,6 +372,60 @@
 	return ntohs(addr.sin_port);
 }
 
+gboolean
+gaim_network_is_available(void)
+{
+#ifdef HAVE_LIBNM
+	/* Try NetworkManager first, maybe we'll get lucky */
+	int libnm_retval = -1;
+
+	if (nm_context)
+	{
+		if ((libnm_retval = libnm_glib_get_network_state(nm_context)) == LIBNM_NO_NETWORK_CONNECTION)
+		{
+			gaim_debug_warning("network", "NetworkManager not active or reports no connection (retval = %i)\n", libnm_retval);
+			return FALSE;
+		}
+		if (libnm_retval == LIBNM_ACTIVE_NETWORK_CONNECTION)	return TRUE;
+	}
+#endif
+	return TRUE;
+}
+
+#ifdef HAVE_LIBNM
+void
+nm_callback_func(libnm_glib_ctx* ctx, gpointer user_data)
+{
+	GList *l;
+	GaimAccount *account;
+	static libnm_glib_state prev = LIBNM_NO_DBUS;
+	libnm_glib_state current;
+	GaimConnectionUiOps *ui_ops = gaim_connections_get_ui_ops();
+
+	current = libnm_glib_get_network_state(ctx);
+	gaim_debug_info("network","Entering nm_callback_func!\n");
+
+	switch(current)
+	{
+	case LIBNM_ACTIVE_NETWORK_CONNECTION:
+		ui_ops->network_connected();
+		prev = current;
+		break;
+	case LIBNM_NO_NETWORK_CONNECTION:
+		if (prev != LIBNM_ACTIVE_NETWORK_CONNECTION)
+			break;
+		ui_ops->network_disconnected();
+		prev = current;
+		break;
+	case LIBNM_NO_DBUS:
+	case LIBNM_NO_NETWORKMANAGER:
+	case LIBNM_INVALID_CONTEXT:
+	default:
+		break;
+	}
+}
+#endif
+
 void
 gaim_network_init(void)
 {
@@ -371,4 +437,24 @@
 	gaim_prefs_add_int   ("/core/network/ports_range_end", 2048);
 
 	gaim_upnp_discover(NULL, NULL);
+
+#ifdef HAVE_LIBNM
+	nm_context = libnm_glib_init();
+	if(nm_context)
+		nm_callback_idx = libnm_glib_register_callback(nm_context, nm_callback_func, NULL, g_main_context_default());
+#endif
 }
+
+void
+gaim_network_uninit(void)
+{
+#ifdef HAVE_LIBNM
+	/* FIXME: If anyone can think of a more clever way to shut down libnm without
+	 * using a global variable + this function, please do. */
+	if(nm_context && nm_callback_idx)
+		libnm_glib_unregister_callback(nm_context, nm_callback_idx);
+
+	if(nm_context)
+		libnm_glib_shutdown(nm_context);
+#endif
+}
--- a/libgaim/network.h	Sun Oct 08 04:31:39 2006 +0000
+++ b/libgaim/network.h	Sun Oct 08 08:40:09 2006 +0000
@@ -188,10 +188,24 @@
 unsigned short gaim_network_get_port_from_fd(int fd);
 
 /**
+ * Detects if there is an available Internet connection. Note that this call
+ * could block for the amount of time specified in inet_detect_timeout, so
+ * using it in a UI thread may cause uncomfortableness
+ *
+ * @return TRUE if the Internet is available
+ */
+gboolean gaim_network_is_available(void);
+
+/**
  * Initializes the network subsystem.
  */
 void gaim_network_init(void);
 
+/**
+ * Shuts down the network subsystem.
+ */
+void gaim_network_uninit(void);
+
 /*@}*/
 
 #ifdef __cplusplus