# HG changeset patch # User Richard Laager # Date 1210390155 0 # Node ID 790c606ff8a928533287b629c7db619529697198 # Parent e8a66e79c49c47835f1fbcfbd7d443abcb629106 A patch from QuLogic to replace the libnm_glib calls with straight DBus calls. This removes a library dependence and should be more stable, we hope. diff -r e8a66e79c49c -r 790c606ff8a9 libpurple/network.c --- a/libpurple/network.c Fri May 09 05:58:54 2008 +0000 +++ b/libpurple/network.c Sat May 10 03:29:15 2008 +0000 @@ -60,10 +60,12 @@ #endif #ifdef HAVE_LIBNM -#include +#include +#include -static libnm_glib_ctx *nm_context = NULL; -static guint nm_callback_idx = 0; +static DBusGConnection *nm_conn = NULL; +static DBusGProxy *nm_proxy = NULL; +static DBusGProxy *dbus_proxy = NULL; #elif defined _WIN32 static int current_network_count; @@ -80,7 +82,7 @@ }; #ifdef HAVE_LIBNM -static void nm_callback_func(libnm_glib_ctx* ctx, gpointer user_data); +static NMState nm_get_network_state(void); #endif const unsigned char * @@ -593,17 +595,12 @@ { #ifdef HAVE_LIBNM /* Try NetworkManager first, maybe we'll get lucky */ - int libnm_retval = -1; - - if (nm_context) + if (nm_get_network_state() != NM_STATE_CONNECTED) { - if ((libnm_retval = libnm_glib_get_network_state(nm_context)) == LIBNM_NO_NETWORK_CONNECTION) - { - purple_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; - } + purple_debug_warning("network", "NetworkManager not active or reports no connection\n"); + return FALSE; + } else + return TRUE; #elif defined _WIN32 return (current_network_count > 0); #endif @@ -612,40 +609,79 @@ #ifdef HAVE_LIBNM static void -nm_callback_func(libnm_glib_ctx* ctx, gpointer user_data) +nm_update_state(NMState state) { - static libnm_glib_state prev = LIBNM_NO_DBUS; - libnm_glib_state current; + static NMState prev = NM_STATE_UNKNOWN; PurpleConnectionUiOps *ui_ops = purple_connections_get_ui_ops(); - 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) + switch(state) { - case LIBNM_ACTIVE_NETWORK_CONNECTION: - /* Call res_init in case DNS servers have changed */ - res_init(); - if (ui_ops != NULL && ui_ops->network_connected != NULL) - ui_ops->network_connected(); - prev = current; - break; - case LIBNM_NO_NETWORK_CONNECTION: - if (prev != LIBNM_ACTIVE_NETWORK_CONNECTION) + case NM_STATE_CONNECTED: + /* Call res_init in case DNS servers have changed */ + res_init(); + if (ui_ops != NULL && ui_ops->network_connected != NULL) + ui_ops->network_connected(); + prev = state; break; - if (ui_ops != NULL && ui_ops->network_disconnected != NULL) - ui_ops->network_disconnected(); - prev = current; - break; - case LIBNM_NO_DBUS: - case LIBNM_NO_NETWORKMANAGER: - case LIBNM_INVALID_CONTEXT: - default: - break; + case NM_STATE_ASLEEP: + case NM_STATE_CONNECTING: + case NM_STATE_DISCONNECTED: + if (prev != NM_STATE_CONNECTED) + break; + if (ui_ops != NULL && ui_ops->network_disconnected != NULL) + ui_ops->network_disconnected(); + prev = state; + break; + case NM_STATE_UNKNOWN: + default: + break; } } + +static void +nm_state_change_cb(DBusGProxy *proxy, NMState state, gpointer user_data) +{ + purple_debug_info("network", "Got StateChange from NetworkManager: %d.\n", state); + nm_update_state(state); +} + +static NMState +nm_get_network_state(void) +{ + GError *err = NULL; + NMState state = NM_STATE_UNKNOWN; + + if (!nm_proxy) + return NM_STATE_UNKNOWN; + + if (!dbus_g_proxy_call(nm_proxy, "state", &err, G_TYPE_INVALID, G_TYPE_UINT, &state, G_TYPE_INVALID)) { + /* XXX: Print an error? */ + return NM_STATE_UNKNOWN; + } + + return state; +} + +static void +nm_dbus_name_owner_changed_cb(DBusGProxy *proxy, char *service, char *old_owner, char *new_owner, gpointer user_data) +{ + if (g_str_equal(service, NM_DBUS_SERVICE)) { + gboolean old_owner_good = old_owner && (old_owner[0] != '\0'); + gboolean new_owner_good = new_owner && (new_owner[0] != '\0'); + + purple_debug_info("network", "Got NameOwnerChanged signal, service = '%s', old_owner = '%s', new_owner = '%s'\n", service, old_owner, new_owner); + if (!old_owner_good && new_owner_good) { /* Equivalent to old ServiceCreated signal */ + purple_debug_info("network", "NetworkManager has started.\n"); + nm_update_state(nm_get_network_state()); + } else if (old_owner_good && !new_owner_good) { /* Equivalent to old ServiceDeleted signal */ + purple_debug_info("network", "NetworkManager has gone away.\n"); + nm_update_state(NM_STATE_UNKNOWN); + } + } +} + #endif void * @@ -659,6 +695,9 @@ void purple_network_init(void) { +#ifdef HAVE_LIBNM + GError *error = NULL; +#endif #ifdef _WIN32 GError *err = NULL; gint cnt = wpurple_get_connected_network_count(); @@ -686,9 +725,26 @@ purple_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()); + nm_conn = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error); + if (!nm_conn) { + purple_debug_warning("network", "Error connecting to DBus System service: %s.\n", error->message); + } else { + nm_proxy = dbus_g_proxy_new_for_name(nm_conn, + NM_DBUS_SERVICE, + NM_DBUS_PATH, + NM_DBUS_INTERFACE); + dbus_g_proxy_add_signal(nm_proxy, NM_DBUS_SIGNAL_STATE_CHANGE, G_TYPE_UINT, G_TYPE_INVALID); + dbus_g_proxy_connect_signal(nm_proxy, NM_DBUS_SIGNAL_STATE_CHANGE, + G_CALLBACK(nm_state_change_cb), NULL, NULL); + + dbus_proxy = dbus_g_proxy_new_for_name(nm_conn, + DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS); + dbus_g_proxy_add_signal(dbus_proxy, "NameOwnerChanged", G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID); + dbus_g_proxy_connect_signal(dbus_proxy, "NameOwnerChanged", + G_CALLBACK(nm_dbus_name_owner_changed_cb), NULL, NULL); + } #endif purple_signal_register(purple_network_get_handle(), "network-configuration-changed", @@ -702,13 +758,16 @@ purple_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); + if (nm_proxy) { + dbus_g_proxy_disconnect_signal(nm_proxy, NM_DBUS_SIGNAL_STATE_CHANGE, G_CALLBACK(nm_state_change_cb), NULL); + g_object_unref(G_OBJECT(nm_proxy)); + } + if (dbus_proxy) { + dbus_g_proxy_disconnect_signal(dbus_proxy, "NameOwnerChanged", G_CALLBACK(nm_dbus_name_owner_changed_cb), NULL); + g_object_unref(G_OBJECT(dbus_proxy)); + } + if (nm_conn) + dbus_g_connection_unref(nm_conn); #endif purple_signal_unregister(purple_network_get_handle(),