From e09969112fffec1e7862a8e82ed073777da849c8 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 26 Aug 2004 00:33:08 +0000 Subject: [PATCH] 2004-08-25 Dan Williams * panel-applet/* - Rework the panel applet to do all DBUS communication in a separate thread git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@70 4912f4e0-d625-0410-9fb7-b9a5a253dbdc --- ChangeLog | 52 +- panel-applet/Makefile.am | 6 +- panel-applet/NMWirelessApplet.c | 257 ++++++---- panel-applet/NMWirelessApplet.h | 56 ++- panel-applet/NMWirelessAppletDbus.c | 712 ++++++++++++++++++++-------- panel-applet/NMWirelessAppletDbus.h | 20 +- panel-applet/wireless-applet.glade | 156 ++++++ 7 files changed, 934 insertions(+), 325 deletions(-) create mode 100644 panel-applet/wireless-applet.glade diff --git a/ChangeLog b/ChangeLog index 6f25067ee..91c006c4a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,54 @@ +2004-08-25 Dan Williams + + * panel-applet/* + - Rework the panel applet to do all DBUS communication in a separate + thread + +2004-08-25 Dan Williams + + * info-daemon/NetworkManagerInfo.[ch] + - Remove "get_next_priority" function + + * info-daemon/NetworkManagerInfoDbus.[ch] + - Convert "priority" functions to "timestamp" + +2004-08-25 Dan Williams + + * src/NetworkManagerAP.[ch] + - Add a "enc_method_good" member and accessors to an Access Point + to signal when we've found the correct encryption method + for an access point + - Add a "timestamp" member and accessors, remove "priority" member + and accessors (use timestamps instead) + - Rename "wep_key"->"enc_key" + - (nm_ap_get_enc_key_hashed): new, return the correct mangled key + for a specified encryption method using the access points + source encryption key/passphrase + + * src/NetworkManagerAPList.c + - When updating a network with dbus, grab timestamp now instead of + priority + + * src/NetworkManagerDBus.[ch] + - Add signal for "DeviceActivating" + - Switch priority->timestamp + + * src/NetworkManagerDevice.c + - Change references of "wep_key" -> "enc_key" or "key" + - Signal DeviceActivating when starting activation + - When activating a wireless device, if the access point we are connecting + to is encrypted, and we have a source key, try to generate a mangled + key and use that (ie, generate real WEP key from a passphrase) + - Rework device activation to fallback to other encryption methods if + a previous one didn't work (ie, try mangling a key as a 104-bit passphrase + first, then if that doesn't work fall back to direct hex key). + - (nm_device_update_best_ap): fix a deadlock, and use timestamps instead of + priority. We now prefer the latest access point used, rather than using + a priority scheme + - (nm_device_do_normal_scan): make the encryption method "unknown" on access + points we've just discovered, and merge in correct info from the global + access point lists + 2004-08-25 Seth Nickell Patch from Matthew Garrett for adding @@ -33,7 +84,6 @@ - Refactored initscript code separately for each distribution - 2004-08-23 Dan Williams * configure.in diff --git a/panel-applet/Makefile.am b/panel-applet/Makefile.am index 08b66a822..27afb988b 100644 --- a/panel-applet/Makefile.am +++ b/panel-applet/Makefile.am @@ -1,5 +1,3 @@ -## Process this file with automake to produce Makefile.in - NULL= INCLUDES = \ @@ -41,6 +39,9 @@ $(server_DATA): $(srcdir)/$(server_in_files) uidir = $(datadir)/gnome-2.0/ui ui_DATA = NMWirelessApplet.xml +gladedir = $(datadir)/NMWirelessApplet +glade_DATA = wireless-applet.glade + pixmapdir = $(datadir)/pixmaps/NMWirelessApplet pixmap_DATA = no-link-0.png \ wired.png \ @@ -63,5 +64,6 @@ EXTRA_DIST = \ $(server_in_files) \ $(pixmap_DATA) \ $(ui_DATA) \ + $(glade_DATA) \ $(NULL) diff --git a/panel-applet/NMWirelessApplet.c b/panel-applet/NMWirelessApplet.c index c247ab332..05421e59a 100644 --- a/panel-applet/NMWirelessApplet.c +++ b/panel-applet/NMWirelessApplet.c @@ -42,13 +42,12 @@ #include #include -#include -#include - #include "NMWirelessApplet.h" #include "NMWirelessAppletDbus.h" #define CFG_UPDATE_INTERVAL 1 +#define NM_GCONF_TRUSTED_NETWORKS_PATH "/system/networking/wireless/trusted_networks" +#define NM_GCONF_PREFERRED_NETWORKS_PATH "/system/networking/wireless/preferred_networks" static char * pixmap_names[] = { @@ -66,14 +65,9 @@ static char * pixmap_names[] = static char *glade_file; -/* Represents an access point */ -typedef struct -{ - char * essid; - gboolean encrypted; -} AccessPoint; - -static void nmwa_about_cb (BonoboUIComponent *uic, NMWirelessApplet *applet); +static void nmwa_about_cb (BonoboUIComponent *uic, NMWirelessApplet *applet); +static GtkWidget * nmwa_populate_menu (NMWirelessApplet *applet); +static void nmwa_dispose_menu (NMWirelessApplet *applet); static const BonoboUIVerb nmwa_context_menu_verbs [] = { @@ -104,13 +98,13 @@ static GType nmwa_get_type (void) /* - * nmwa_draw + * nmwa_redraw * * Actually update the applet's pixmap so that our panel icon reflects * the state of the applet * */ -static void nmwa_draw (NMWirelessApplet *applet) +static void nmwa_redraw (NMWirelessApplet *applet) { const char *label_text; char *tmp; @@ -132,73 +126,72 @@ static void nmwa_draw (NMWirelessApplet *applet) */ static void nmwa_update_state (NMWirelessApplet *applet) { - if (applet->nm_active) +fprintf( stderr, "state (%d)\n", applet->applet_state); + switch (applet->applet_state) { - char *status = nmwa_dbus_get_nm_status (applet->connection); - char *active_device = nmwa_dbus_get_active_device (applet->connection); + case (APPLET_STATE_NO_NM): + break; - if (active_device && status) - { - int type = nmwa_dbus_get_device_type (applet->connection, active_device); + case (APPLET_STATE_NO_CONNECTION): - switch (type) - { - case (DEVICE_TYPE_WIRELESS_ETHERNET): - if (strcmp (status, "connected") == 0) - applet->pix_state = PIX_WIRELESS_SIGNAL_4; - else if (strcmp (status, "connecting") == 0) - { - if ( (applet->pix_state < PIX_WIRELESS_CONNECT_0) - || (applet->pix_state > PIX_WIRELESS_CONNECT_2)) - applet->pix_state = PIX_WIRELESS_CONNECT_0; - else - applet->pix_state++; - } - break; + case (APPLET_STATE_WIRED): + case (APPLET_STATE_WIRED_CONNECTING): + applet->pix_state = PIX_WIRED; + break; - case (DEVICE_TYPE_WIRED_ETHERNET): - default: - applet->pix_state = PIX_WIRED; - break; - } - } + case (APPLET_STATE_WIRELESS): + applet->pix_state = PIX_WIRELESS_SIGNAL_4; + break; - if (active_device) dbus_free (active_device); - if (status) dbus_free (status); + case (APPLET_STATE_WIRELESS_CONNECTING): + if (applet->pix_state < PIX_WIRELESS_CONNECT_0) + applet->pix_state = PIX_WIRELESS_CONNECT_0; + else if (applet->pix_state >= PIX_WIRELESS_CONNECT_3) + applet->pix_state = PIX_WIRELESS_CONNECT_0; + else + applet->pix_state++; + break; + + default: + break; } - - nmwa_draw (applet); } /* - * nmwa_timeout_handler + * nmwa_redraw_timeout * * Called regularly to update the applet's state and icon in the panel * */ -static int nmwa_timeout_handler (NMWirelessApplet *applet) +static int nmwa_redraw_timeout (NMWirelessApplet *applet) { - /* Try to get a connection to dbus if we don't already have one */ - if (!applet->connection) - applet->connection = nmwa_dbus_init (applet); - nmwa_update_state (applet); + nmwa_redraw (applet); + + if (applet->applet_state != applet->old_state) + { + if (applet->menu) + nmwa_dispose_menu (applet); + applet->menu = nmwa_populate_menu (applet); + applet->old_state = applet->applet_state; + } return (TRUE); } -static void nmwa_start_timeout (NMWirelessApplet *applet) +static void nmwa_start_redraw_timeout (NMWirelessApplet *applet) { - applet->timeout_handler_id = g_timeout_add (CFG_UPDATE_INTERVAL * 1000, - (GtkFunction)nmwa_timeout_handler, applet); + applet->redraw_timeout_id = g_timeout_add (CFG_UPDATE_INTERVAL * 1000, + (GtkFunction)nmwa_redraw_timeout, applet); } static void nmwa_cancel_timeout (NMWirelessApplet *applet) { - g_source_remove (applet->timeout_handler_id); - applet->timeout_handler_id = -1; + g_source_remove (applet->redraw_timeout_id); + applet->redraw_timeout_id = -1; nmwa_update_state (applet); + nmwa_redraw (applet); } @@ -314,10 +307,10 @@ static void nmwa_destroy (NMWirelessApplet *applet, gpointer user_data) if (applet->menu) nmwa_dispose_menu (applet); - if (applet->timeout_handler_id > 0) + if (applet->redraw_timeout_id > 0) { - gtk_timeout_remove (applet->timeout_handler_id); - applet->timeout_handler_id = 0; + gtk_timeout_remove (applet->redraw_timeout_id); + applet->redraw_timeout_id = 0; } for (i = 0; i < PIX_NUMBER; i++) @@ -384,11 +377,40 @@ static void nmwa_get_menu_pos (GtkMenu *menu, gint *x, gint *y, gboolean *push_i */ void nmwa_handle_network_choice (NMWirelessApplet *applet, char *network) { + GConfEntry *gconf_entry; + char *key; g_return_if_fail (applet != NULL); g_return_if_fail (network != NULL); -fprintf( stderr, "Forcing network '%s'\n", network); + /* Update GConf to set timestamp for this network, or add it if + * it doesn't already exist. + */ + key = g_strdup_printf ("%s/%s", NM_GCONF_TRUSTED_NETWORKS_PATH, network); + gconf_entry = gconf_client_get_entry (applet->gconf_client, key, NULL, TRUE, NULL); + g_free (key); + + if (gconf_entry) + { + /* Update timestamp on existing network in trusted networks */ + key = g_strdup_printf ("%s/%s/timestamp", NM_GCONF_TRUSTED_NETWORKS_PATH, network); + gconf_client_set_int (applet->gconf_client, key, time (NULL), NULL); + g_free (key); + } + else + { + /* If its not already in trusted networks, add the chosen network to preferred networks */ + key = g_strdup_printf ("%s/%s/timestamp", NM_GCONF_PREFERRED_NETWORKS_PATH, network); + gconf_client_set_int (applet->gconf_client, key, time (NULL), NULL); + g_free (key); + + /* Force-set the essid too so that we have a semi-complete network entry */ + key = g_strdup_printf ("%s/%s/essid", NM_GCONF_PREFERRED_NETWORKS_PATH, network); + gconf_client_set_string (applet->gconf_client, key, network, NULL); + g_free (key); + } + + fprintf (stderr, "Forcing network '%s'\n", network); nmwa_dbus_set_network (applet->connection, network); } @@ -424,14 +446,9 @@ static void nmwa_button_clicked (GtkWidget *button, NMWirelessApplet *applet) gtk_menu_popdown (GTK_MENU (applet->menu)); else { - if (applet->nm_active) - { - if (!applet->menu) - applet->menu = nmwa_populate_menu (applet); - - gtk_menu_popup (GTK_MENU (applet->menu), NULL, NULL, nmwa_get_menu_pos, - applet, 0, gtk_get_current_event_time()); - } + nmwa_redraw_timeout (applet); + gtk_menu_popup (GTK_MENU (applet->menu), NULL, NULL, nmwa_get_menu_pos, + applet, 0, gtk_get_current_event_time()); } } @@ -439,8 +456,7 @@ static void nmwa_button_clicked (GtkWidget *button, NMWirelessApplet *applet) /* * nmwa_add_menu_item * - * Callback from nmwa_dbus_add_networks_to_menu() during network enumeration. - * Given a network, add it to our networks menu. + * Add a menu item * */ void nmwa_add_menu_item (NMWirelessApplet *applet, GtkWidget *menu, char *text, char *tag, gboolean current, @@ -452,7 +468,7 @@ void nmwa_add_menu_item (NMWirelessApplet *applet, GtkWidget *menu, char *text, g_return_if_fail (text != NULL); g_return_if_fail (menu != NULL); -fprintf( stderr, "text = %s\n", text); + menu_item = gtk_menu_item_new (); hbox = gtk_hbox_new (FALSE, 5); gtk_container_add (GTK_CONTAINER (menu_item), hbox); @@ -461,7 +477,7 @@ fprintf( stderr, "text = %s\n", text); label = gtk_label_new (text); if (current) { - char *markup = g_strdup_printf ("%s", text); + char *markup = g_strdup_printf ("%s (active)", text); gtk_label_set_markup (GTK_LABEL (label), markup); g_free (markup); } @@ -534,11 +550,57 @@ GtkWidget * nmwa_populate_menu (NMWirelessApplet *applet) { GtkWidget *menu; - g_assert (applet->nm_active); g_return_if_fail (applet != NULL); menu = gtk_menu_new (); - nmwa_dbus_add_networks_to_menu (applet, menu); +fprintf( stderr, "populate_menu() state (%d)\n", applet->applet_state); + switch (applet->applet_state) + { + case (APPLET_STATE_NO_NM): + nmwa_add_menu_item (applet, menu, "NetworkManager is not running...", + NULL, FALSE, FALSE); + break; + + case (APPLET_STATE_NO_CONNECTION): + nmwa_add_menu_item (applet, menu, "No network connection is currently active...", + NULL, FALSE, FALSE); + break; + + case (APPLET_STATE_WIRED): + case (APPLET_STATE_WIRED_CONNECTING): + nmwa_add_menu_item (applet, menu, "A wired network connection is currently active...", + NULL, FALSE, FALSE); + break; + + case (APPLET_STATE_WIRELESS): + case (APPLET_STATE_WIRELESS_CONNECTING): + { + GSList *element = applet->networks; + g_mutex_lock (applet->networks_mutex); + if (!element) + nmwa_add_menu_item (applet, menu, "There are no wireless networks...", + NULL, FALSE, FALSE); + else + { + /* Add all networks in our network list to the menu */ + while (element) + { + WirelessNetwork *net = (WirelessNetwork *)(element->data); + + if (net) + nmwa_add_menu_item (applet, menu, net->essid, + net->essid, net->active, net->encrypted); + + element = g_slist_next (element); + } + } + g_mutex_unlock (applet->networks_mutex); + break; + } + + default: + break; + } return (menu); } @@ -608,21 +670,19 @@ static void nmwa_setup_widgets (NMWirelessApplet *applet) applet->current_pixbuf = NULL; applet->about_dialog = NULL; - - if (applet->nm_active) - applet->menu = nmwa_populate_menu (applet); + applet->menu = NULL; } static void change_size_cb(PanelApplet *pa, gint s, NMWirelessApplet *applet) { nmwa_setup_widgets (applet); - nmwa_timeout_handler (applet); + nmwa_redraw_timeout (applet); } static void change_orient_cb(PanelApplet *pa, gint s, NMWirelessApplet *applet) { nmwa_setup_widgets (applet); - nmwa_timeout_handler (applet); + nmwa_redraw_timeout (applet); } static gboolean do_not_eat_button_press (GtkWidget *widget, GdkEventButton *event) @@ -669,37 +729,47 @@ static void change_background_cb(PanelApplet *a, PanelAppletBackgroundType type, */ static GtkWidget * nmwa_new (NMWirelessApplet *applet) { - panel_applet_set_flags (PANEL_APPLET (applet), PANEL_APPLET_EXPAND_MINOR); + GError *error = NULL; + panel_applet_set_flags (PANEL_APPLET (applet), PANEL_APPLET_EXPAND_MINOR); gtk_widget_hide(GTK_WIDGET(applet)); applet->gconf_client = gconf_client_get_default (); if (!applet->gconf_client) return (NULL); -#if 0 - applet->net_dialog = glade_xml_new(GLADEDIR"/network_chocie.glade", NULL, NULL); - if (!applet->net_dialog) + applet->ui_resources = glade_xml_new(glade_file, NULL, NULL); + if (!applet->ui_resources) { - fprintf (stderr, "Could not open the network dialog glade file!\n"); + fprintf (stderr, "Could not get our UI resources from the glade file\n"); g_object_unref (G_OBJECT (applet->gconf_client)); return (NULL); } -#endif - applet->pix_state = PIX_WIRED; - applet->connection = nmwa_dbus_init(applet); - applet->nm_active = nmwa_dbus_nm_is_running(applet->connection); + applet->applet_state = APPLET_STATE_NO_NM; + /* Start our dbus thread */ + if (!(applet->networks_mutex = g_mutex_new ())) + { + g_object_unref (G_OBJECT (applet->gconf_client)); + /* FIXME: free glade file */ + return (NULL); + } + if (!(applet->dbus_thread = g_thread_create (nmwa_dbus_worker, applet, FALSE, &error))) + { + g_mutex_free (applet->networks_mutex); + g_object_unref (G_OBJECT (applet->gconf_client)); + /* FIXME: free glade file */ + return (NULL); + } + + /* Load pixmaps and create applet widgets */ nmwa_load_theme (applet); nmwa_setup_widgets (applet); g_signal_connect (applet,"destroy", G_CALLBACK (nmwa_destroy),NULL); g_signal_connect (applet->button, "button_press_event", G_CALLBACK (do_not_eat_button_press), NULL); - nmwa_timeout_handler (applet); - nmwa_start_timeout (applet); - panel_applet_setup_menu_from_file (PANEL_APPLET (applet), NULL, "NMWirelessApplet.xml", NULL, nmwa_context_menu_verbs, applet); @@ -715,6 +785,9 @@ static GtkWidget * nmwa_new (NMWirelessApplet *applet) g_signal_connect (G_OBJECT (applet), "change_orient", G_CALLBACK (change_orient_cb), applet); g_signal_connect (G_OBJECT (applet), "change_background", G_CALLBACK (change_background_cb), applet); + /* Start redraw timeout */ + nmwa_start_redraw_timeout (applet); + return (GTK_WIDGET (applet)); } @@ -725,6 +798,12 @@ static gboolean nmwa_fill (NMWirelessApplet *applet) glade_gnome_init (); glade_file = gnome_program_locate_file (NULL, GNOME_FILE_DOMAIN_DATADIR, "NMWirelessApplet/wireless-applet.glade", FALSE, NULL); + if (!glade_file) + { + show_warning_dialog (TRUE, "The NetworkManager Applet could not find some required" + "resources (the glade file was not found)."); + return (FALSE); + } gtk_widget_show (nmwa_new (applet)); return (TRUE); diff --git a/panel-applet/NMWirelessApplet.h b/panel-applet/NMWirelessApplet.h index 8ecb19c33..53b5a6944 100644 --- a/panel-applet/NMWirelessApplet.h +++ b/panel-applet/NMWirelessApplet.h @@ -27,6 +27,8 @@ #include #include #include +#include +#include typedef enum { @@ -40,42 +42,66 @@ typedef enum PIX_WIRELESS_CONNECT_1, PIX_WIRELESS_CONNECT_2, PIX_WIRELESS_CONNECT_3, - PIX_NUMBER, + PIX_NUMBER } PixmapState; +typedef enum +{ + APPLET_STATE_NO_NM, + APPLET_STATE_NO_CONNECTION, + APPLET_STATE_WIRED, + APPLET_STATE_WIRED_CONNECTING, + APPLET_STATE_WIRELESS, + APPLET_STATE_WIRELESS_CONNECTING, + APPLET_STATE_IGNORE +} AppletState; + + +/* + * Applet instance data + * + */ typedef struct { PanelApplet base; DBusConnection *connection; - gboolean nm_active; GConfClient *gconf_client; - GladeXML *net_dialog; + GladeXML *ui_resources; + guint redraw_timeout_id; + GThread *dbus_thread; + GMainContext *thread_context; - PixmapState pix_state; - /* contains pointers into the images GList. - * 0-100 are for link */ + PixmapState pix_state; // Index into pixmaps array GdkPixbuf *pixmaps[PIX_NUMBER]; - /* pointer to the current used file name */ GdkPixbuf *current_pixbuf; GdkPixbuf *key_pixbuf; + /* Data model elements */ + GMutex *networks_mutex; + GSList *networks; + AppletState applet_state; + AppletState old_state; + + /* Direct UI elements */ GtkWidget *pixmap; GtkWidget *button; GtkWidget *box; GtkWidget *about_dialog; GtkWidget *menu; - - guint timeout_handler_id; } NMWirelessApplet; -void nmwa_add_menu_item (NMWirelessApplet *applet, GtkWidget *menu, char *text, char *tag, - gboolean current, gboolean encrypted); - -GtkWidget * nmwa_populate_menu (NMWirelessApplet *applet); - -void nmwa_dispose_menu (NMWirelessApplet *applet); +/* + * Representation of a wireless network + * + */ +typedef struct +{ + char *essid; + gboolean encrypted; + gboolean active; +} WirelessNetwork; #endif diff --git a/panel-applet/NMWirelessAppletDbus.c b/panel-applet/NMWirelessAppletDbus.c index 8c5a7d9a8..195c28fce 100644 --- a/panel-applet/NMWirelessAppletDbus.c +++ b/panel-applet/NMWirelessAppletDbus.c @@ -35,153 +35,189 @@ #define NMI_DBUS_PATH "/org/freedesktop/NetworkManagerInfo" #define NMI_DBUS_INTERFACE "org.freedesktop.NetworkManagerInfo" +#define DBUS_NO_SERVICE_ERROR "org.freedesktop.DBus.Error.ServiceDoesNotExist" +#define NM_DBUS_NO_ACTIVE_NET_ERROR "org.freedesktop.NetworkManager.NoActiveNetwork" /* * nmwa_dbus_get_string * * NOTE: caller MUST free the returned string * + * Returns: RETURN_SUCCESS on success + * RETURN_FAILURE on failure + * RETURN_NO_NM if NetworkManager service no longer exists + * */ -char * nmwa_dbus_get_string (DBusConnection *connection, const char *path, const char *method) +int nmwa_dbus_get_string (DBusConnection *connection, const char *path, const char *method, char **string) { DBusMessage *message; DBusMessage *reply; DBusError error; - char *string = NULL; + char *dbus_string = NULL; - g_return_val_if_fail (connection != NULL, NULL); - g_return_val_if_fail (path != NULL, NULL); - g_return_val_if_fail (method != NULL, NULL); + g_return_val_if_fail (connection != NULL, RETURN_FAILURE); + g_return_val_if_fail (path != NULL, RETURN_FAILURE); + g_return_val_if_fail (method != NULL, RETURN_FAILURE); + g_return_val_if_fail (string != NULL, RETURN_FAILURE); + g_return_val_if_fail (*string == NULL, RETURN_FAILURE); if (!(message = dbus_message_new_method_call (NM_DBUS_SERVICE, path, NM_DBUS_INTERFACE, method))) { fprintf (stderr, "nmwa_dbus_get_string(): Couldn't allocate the dbus message\n"); - return (NULL); + return (RETURN_FAILURE); } dbus_error_init (&error); reply = dbus_connection_send_with_reply_and_block (connection, message, -1, &error); + dbus_message_unref (message); if (dbus_error_is_set (&error)) { + int ret = RETURN_FAILURE; + fprintf (stderr, "nmwa_dbus_get_string(): %s raised:\n %s\n\n", error.name, error.message); - dbus_message_unref (message); - return (NULL); + if (strcmp (error.name, DBUS_NO_SERVICE_ERROR) == 0) + ret = RETURN_NO_NM; + else if (strcmp (error.name, NM_DBUS_NO_ACTIVE_NET_ERROR) == 0) + ret = RETURN_SUCCESS; + + return (ret); } if (reply == NULL) { fprintf (stderr, "nmwa_dbus_get_string(): dbus reply message was NULL\n" ); - dbus_message_unref (message); - return (NULL); + return (RETURN_FAILURE); } dbus_error_init (&error); - if (!dbus_message_get_args (reply, &error, DBUS_TYPE_STRING, &string, DBUS_TYPE_INVALID)) + if (!dbus_message_get_args (reply, &error, DBUS_TYPE_STRING, &dbus_string, DBUS_TYPE_INVALID)) { fprintf (stderr, "nmwa_dbus_get_string(): error while getting args: name='%s' message='%s'\n", error.name, error.message); - string = NULL; + dbus_message_unref (reply); + return (RETURN_FAILURE); } - dbus_message_unref (reply); - dbus_message_unref (message); - return (string); + *string = dbus_string; + return (RETURN_SUCCESS); } /* * nmwa_dbus_get_int * + * Returns: RETURN_SUCCESS on success + * RETURN_FAILURE on failure + * RETURN_NO_NM if NetworkManager service no longer exists + * */ -gint32 nmwa_dbus_get_int (DBusConnection *connection, const char *path, const char *method) +int nmwa_dbus_get_int (DBusConnection *connection, const char *path, const char *method, gint32 *num) { DBusMessage *message; DBusMessage *reply; DBusError error; - gint32 num; + int dbus_num; - g_return_val_if_fail (connection != NULL, 0); - g_return_val_if_fail (path != NULL, 0); - g_return_val_if_fail (method != NULL, 0); + g_return_val_if_fail (connection != NULL, RETURN_FAILURE); + g_return_val_if_fail (path != NULL, RETURN_FAILURE); + g_return_val_if_fail (method != NULL, RETURN_FAILURE); + g_return_val_if_fail (num != NULL, RETURN_FAILURE); if (!(message = dbus_message_new_method_call (NM_DBUS_SERVICE, path, NM_DBUS_INTERFACE, method))) { fprintf (stderr, "nmwa_dbus_get_int(): Couldn't allocate the dbus message\n"); - return (0); + return (RETURN_FAILURE); } dbus_error_init (&error); reply = dbus_connection_send_with_reply_and_block (connection, message, -1, &error); + dbus_message_unref (message); if (dbus_error_is_set (&error)) { + int ret = RETURN_FAILURE; + fprintf (stderr, "nmwa_dbus_get_int(): %s raised:\n %s\n\n", error.name, error.message); - dbus_message_unref (message); - return (0); + if (strcmp (error.name, DBUS_NO_SERVICE_ERROR) == 0) + ret = RETURN_NO_NM; + + return (ret); } if (reply == NULL) { fprintf( stderr, "nmwa_dbus_get_int(): dbus reply message was NULL\n" ); - dbus_message_unref (message); - return (0); + return (RETURN_FAILURE); } dbus_error_init (&error); - if (!dbus_message_get_args (reply, &error, DBUS_TYPE_INT32, &num, DBUS_TYPE_INVALID)) - num = 0; + if (!dbus_message_get_args (reply, &error, DBUS_TYPE_INT32, &dbus_num, DBUS_TYPE_INVALID)) + { + dbus_message_unref (reply); + return (RETURN_FAILURE); + } dbus_message_unref (reply); - dbus_message_unref (message); - - return (num); + *num = dbus_num; + return (RETURN_SUCCESS); } /* * nmwa_dbus_get_bool * + * Returns: RETURN_SUCCESS on success + * RETURN_FAILURE on failure + * RETURN_NO_NM if NetworkManager service no longer exists + * */ -gboolean nmwa_dbus_get_bool (DBusConnection *connection, const char *path, const char *method) +int nmwa_dbus_get_bool (DBusConnection *connection, const char *path, const char *method, gboolean *val) { DBusMessage *message; DBusMessage *reply; DBusError error; - gboolean val; - g_return_val_if_fail (connection != NULL, 0); - g_return_val_if_fail (path != NULL, 0); - g_return_val_if_fail (method != NULL, 0); + g_return_val_if_fail (connection != NULL, RETURN_FAILURE); + g_return_val_if_fail (path != NULL, RETURN_FAILURE); + g_return_val_if_fail (method != NULL, RETURN_FAILURE); + g_return_val_if_fail (val != NULL, RETURN_FAILURE); if (!(message = dbus_message_new_method_call (NM_DBUS_SERVICE, path, NM_DBUS_INTERFACE, method))) { - fprintf (stderr, "nmwa_dbus_get_int(): Couldn't allocate the dbus message\n"); - return (0); + fprintf (stderr, "nmwa_dbus_get_bool(): Couldn't allocate the dbus message\n"); + return (RETURN_FAILURE); } dbus_error_init (&error); reply = dbus_connection_send_with_reply_and_block (connection, message, -1, &error); + dbus_message_unref (message); if (dbus_error_is_set (&error)) { - fprintf (stderr, "nmwa_dbus_get_int(): %s raised:\n %s\n\n", error.name, error.message); - dbus_message_unref (message); - return (0); + int ret = RETURN_FAILURE; + + fprintf (stderr, "nmwa_dbus_get_bool(): %s raised:\n %s\n\n", error.name, error.message); + if (strcmp (error.name, DBUS_NO_SERVICE_ERROR) == 0) + ret = RETURN_NO_NM; + + return (ret); } if (reply == NULL) { - fprintf( stderr, "nmwa_dbus_get_int(): dbus reply message was NULL\n" ); + fprintf( stderr, "nmwa_dbus_get_bool(): dbus reply message was NULL\n" ); dbus_message_unref (message); - return (0); + return (RETURN_FAILURE); } dbus_error_init (&error); - if (!dbus_message_get_args (reply, &error, DBUS_TYPE_BOOLEAN, &val, DBUS_TYPE_INVALID)) - val = FALSE; + if (!dbus_message_get_args (reply, &error, DBUS_TYPE_BOOLEAN, val, DBUS_TYPE_INVALID)) + { + dbus_message_unref (reply); + return (RETURN_FAILURE); + } dbus_message_unref (reply); - dbus_message_unref (message); - - return (val); + *val = FALSE; + return (RETURN_SUCCESS); } @@ -238,51 +274,71 @@ double nmwa_dbus_get_double (DBusConnection *connection, const char *path, const * * NOTE: caller MUST free the returned string array * + * Returns: RETURN_SUCCESS on success + * RETURN_FAILURE on failure + * RETURN_NO_NM if NetworkManager service no longer exists + * */ -char **nmwa_dbus_get_string_array (DBusConnection *connection, const char *path, const char *method, int *num_items) +int nmwa_dbus_get_string_array (DBusConnection *connection, const char *path, const char *method, + int *num_items, char ***string_array) { DBusMessage *message; DBusMessage *reply; DBusMessageIter iter; DBusError error; - char **array; + char **array = NULL; + int items = 0; - g_return_val_if_fail (connection != NULL, NULL); - g_return_val_if_fail (path != NULL, NULL); - g_return_val_if_fail (method != NULL, NULL); - g_return_val_if_fail (num_items != NULL, NULL); + g_return_val_if_fail (connection != NULL, RETURN_FAILURE); + g_return_val_if_fail (path != NULL, RETURN_FAILURE); + g_return_val_if_fail (method != NULL, RETURN_FAILURE); + g_return_val_if_fail (num_items != NULL, RETURN_FAILURE); + g_return_val_if_fail (string_array != NULL, RETURN_FAILURE); if (!(message = dbus_message_new_method_call (NM_DBUS_SERVICE, path, NM_DBUS_INTERFACE, method))) { fprintf (stderr, "nmwa_dbus_get_string_array(): Couldn't allocate the dbus message\n"); - return (NULL); + return (RETURN_FAILURE); } dbus_error_init (&error); reply = dbus_connection_send_with_reply_and_block (connection, message, -1, &error); + dbus_message_unref (message); if (dbus_error_is_set (&error)) { + int ret = RETURN_FAILURE; + fprintf (stderr, "nmwa_dbus_get_string_array(): %s raised:\n %s\n\n", error.name, error.message); - dbus_message_unref (message); - return (NULL); + if (strcmp (error.name, DBUS_NO_SERVICE_ERROR) == 0) + ret = RETURN_NO_NM; + else if (strcmp (error.name, "NoNetworks") == 0) + { + *string_array = NULL; + *num_items = 0; + ret = RETURN_SUCCESS; + } + + return (ret); } if (reply == NULL) { fprintf( stderr, "nmwa_dbus_get_string_array(): dbus reply message was NULL\n" ); - dbus_message_unref (message); - return (NULL); + return (RETURN_FAILURE); } /* now analyze reply */ dbus_message_iter_init (reply, &iter); - if (!dbus_message_iter_get_string_array (&iter, &array, num_items)) - array = NULL; + if (!dbus_message_iter_get_string_array (&iter, &array, &items)) + { + dbus_message_unref (reply); + return (RETURN_FAILURE); + } dbus_message_unref (reply); - dbus_message_unref (message); - - return (array); + *num_items = items; + *string_array = array; + return (RETURN_SUCCESS); } @@ -292,20 +348,22 @@ char **nmwa_dbus_get_string_array (DBusConnection *connection, const char *path, * Returns the object_path of the currently active device, if any. * */ -char * nmwa_dbus_get_active_device (DBusConnection *connection) +char * nmwa_dbus_get_active_device (NMWirelessApplet *applet, AppletState failure_state) { - char *active_device; + char *active_device = NULL; - if (!connection) - return (NULL); - - if ((active_device = nmwa_dbus_get_string (connection, NM_DBUS_PATH, "getActiveDevice"))) + switch (nmwa_dbus_get_string (applet->connection, NM_DBUS_PATH, "getActiveDevice", &active_device)) { - if (strlen (active_device) < 1) - { - dbus_free (active_device); - active_device = NULL; - } + case (RETURN_NO_NM): + applet->applet_state = APPLET_STATE_NO_NM; + break; + + case (RETURN_FAILURE): + applet->applet_state = failure_state; + break; + + default: + break; } return (active_device); @@ -318,20 +376,23 @@ char * nmwa_dbus_get_active_device (DBusConnection *connection) * Returns the object_path of the currently active network of the active device. * */ -char * nmwa_dbus_get_active_network (DBusConnection *connection, char *dev_path) +char * nmwa_dbus_get_active_network (NMWirelessApplet *applet, char *dev_path, AppletState failure_state) { - char *network; + char *network = NULL; - if (!connection) - return (NULL); - - if ((network = nmwa_dbus_get_string (connection, dev_path, "getActiveNetwork"))) + switch (nmwa_dbus_get_string (applet->connection, dev_path, "getActiveNetwork", &network)) { - if (strlen (network) < 1) - { - dbus_free (network); - network = NULL; - } + case (RETURN_NO_NM): + applet->applet_state = APPLET_STATE_NO_NM; + break; + + case (RETURN_FAILURE): + if (failure_state != APPLET_STATE_IGNORE) + applet->applet_state = failure_state; + break; + + default: + break; } return (network); @@ -341,15 +402,28 @@ char * nmwa_dbus_get_active_network (DBusConnection *connection, char *dev_path) /* * nmwa_dbus_get_device_type * - * Returns the object_path of the currently active device, if any. + * Returns the device type of the specified device. * */ -int nmwa_dbus_get_device_type (DBusConnection *connection, char *path) +int nmwa_dbus_get_device_type (NMWirelessApplet *applet, char *path, AppletState failure_state) { - if (!connection || !path) - return (0); + int type = -1; - return (nmwa_dbus_get_int (connection, path, "getType")); + switch (nmwa_dbus_get_int (applet->connection, path, "getType", &type)) + { + case (RETURN_NO_NM): + applet->applet_state = APPLET_STATE_NO_NM; + break; + + case (RETURN_FAILURE): + applet->applet_state = failure_state; + break; + + default: + break; + } + + return (type); } @@ -359,20 +433,22 @@ int nmwa_dbus_get_device_type (DBusConnection *connection, char *path) * Returns NetworkManager's status * */ -char * nmwa_dbus_get_nm_status (DBusConnection *connection) +char * nmwa_dbus_get_nm_status (NMWirelessApplet *applet, AppletState failure_state) { - char *status; + char *status = NULL; - if (!connection) - return (NULL); - - if ((status = nmwa_dbus_get_string (connection, NM_DBUS_PATH, "status"))) + switch (nmwa_dbus_get_string (applet->connection, NM_DBUS_PATH, "status", &status)) { - if (strlen (status) < 1) - { - dbus_free (status); - status = NULL; - } + case (RETURN_NO_NM): + applet->applet_state = APPLET_STATE_NO_NM; + break; + + case (RETURN_FAILURE): + applet->applet_state = failure_state; + break; + + default: + break; } return (status); @@ -380,101 +456,83 @@ char * nmwa_dbus_get_nm_status (DBusConnection *connection) /* - * nmwa_dbus_add_networks_to_menu + * nmwa_dbus_get_network_name * - * Query NetworkManager for networks and add any to the networks menu + * Returns the name of a specified wireless network * */ -void nmwa_dbus_add_networks_to_menu (NMWirelessApplet *applet, GtkWidget *menu) +char * nmwa_dbus_get_network_name (NMWirelessApplet *applet, char *net_path) { - char *active_device; - char *active_network; - char **networks; - int num_items = 0; - int i; + char *name = NULL; - g_return_if_fail (applet != NULL); - g_return_if_fail (applet->connection != NULL); - g_return_if_fail (menu != NULL); - - if (!applet->connection) + switch (nmwa_dbus_get_string (applet->connection, net_path, "getName", &name)) { - nmwa_add_menu_item (applet, menu, "No wireless networks found...", NULL, FALSE, FALSE); - return; - } - - if (!(active_device = nmwa_dbus_get_active_device (applet->connection))) - { - nmwa_add_menu_item (applet, menu, "No network connection is present.", NULL, FALSE, FALSE); - return; - } - - switch (nmwa_dbus_get_device_type (applet->connection, active_device)) - { - case (DEVICE_TYPE_WIRED_ETHERNET): - nmwa_add_menu_item (applet, menu, "A wired ethernet card is currently active.", NULL, FALSE, FALSE); - return; - - case (DEVICE_TYPE_WIRELESS_ETHERNET): + case (RETURN_NO_NM): + applet->applet_state = APPLET_STATE_NO_NM; break; default: - nmwa_add_menu_item (applet, menu, "Some other network device is currently active.", NULL, FALSE, FALSE); - return; + break; } - active_network = nmwa_dbus_get_active_network (applet->connection, active_device); + return (name); +} - /* Get each of the networks in turn and add them to the menu */ - if (!(networks = nmwa_dbus_get_string_array (applet->connection, active_device, "getNetworks", &num_items))) + +/* + * nmwa_dbus_get_network_encrypted + * + * Returns whether or not the specified network is encrypted + * + */ +gboolean nmwa_dbus_get_network_encrypted (NMWirelessApplet *applet, char *net_path) +{ + gboolean enc = FALSE; + + switch (nmwa_dbus_get_bool (applet->connection, net_path, "getName", &enc)) { - dbus_free (active_device); - if (active_network) - dbus_free (active_network); - return; + case (RETURN_NO_NM): + applet->applet_state = APPLET_STATE_NO_NM; + break; + + default: + break; } - if (strlen (networks[0]) == 0) + return (enc); +} + + +/* + * nmwa_dbus_get_device_networks + * + * Returns an array of wireless networks that the specified device knows about. + * + */ +char **nmwa_dbus_get_device_networks (NMWirelessApplet *applet, char *path, int *num_items, AppletState failure_state) +{ + char **array = NULL; + int items; + + switch (nmwa_dbus_get_string_array (applet->connection, path, "getNetworks", &items, &array)) { - nmwa_add_menu_item (applet, menu, "No wireless networks found...", NULL, FALSE, FALSE); - dbus_free (active_device); - if (active_network) - dbus_free (active_network); - return; + case (RETURN_NO_NM): + applet->applet_state = APPLET_STATE_NO_NM; + break; + + case (RETURN_FAILURE): + applet->applet_state = failure_state; + break; + + case (RETURN_SUCCESS): + *num_items = items; + break; + + default: + break; } - for (i = 0; i < num_items; i++) - { - char *name = nmwa_dbus_get_string (applet->connection, networks[i], "getName"); - - if (name && strlen (name)) - { - gboolean found = FALSE; - int j; - - /* Only show one menu item per network. NetworkManager really passes back a list - * of access points, and there may be more than one that have the same ESSID. Filter - * them here. - */ - for (j = 0; j < i; j++) - if (found = (networks[j] && (strcmp (networks[i], networks[j]) == 0))) - break; - - if (!found) - { - gboolean active = active_network ? (strcmp (networks[i], active_network) == 0) : FALSE; - gboolean encrypted = nmwa_dbus_get_bool (applet->connection, networks[i], "getEncrypted"); - - fprintf( stderr, "Adding '%s' active (%d), enc (%d)\n", name, active, encrypted); - nmwa_add_menu_item (applet, menu, name, name, active, encrypted); - } - } - dbus_free (name); - } - - dbus_free_string_array (networks); - dbus_free (active_network); - dbus_free (active_device); + return (array); } @@ -498,26 +556,174 @@ void nmwa_dbus_set_network (DBusConnection *connection, char *network) dbus_connection_send (connection, message, NULL); } else - fprintf (stderr, "nm_dbus_get_network_priority(): Couldn't allocate the dbus message\n"); + fprintf (stderr, "nm_dbus_set_network(): Couldn't allocate the dbus message\n"); } /* - * nmwa_dbus_nm_is_running + * wireless_network_free * - * Ask dbus whether or not NetworkManager is running + * Frees the representation of a wireless network * */ -gboolean nmwa_dbus_nm_is_running (DBusConnection *connection) +static void wireless_network_free (void *element, void *user_data) { - DBusError error; - gboolean exists; + WirelessNetwork *net = (WirelessNetwork *)(element); - g_return_val_if_fail (connection != NULL, FALSE); + if (net) g_free (net->essid); + g_free (net); +} - dbus_error_init (&error); - exists = dbus_bus_service_exists (connection, NM_DBUS_SERVICE, &error); - return (exists); + +/* + * nmwa_dbus_update_wireless_network_list + * + * Query NetworkManager for the wireless networks the active device + * knows about, if the active device is wireless. + * + */ +void nmwa_dbus_update_wireless_network_list (NMWirelessApplet *applet) +{ + char *active_device = NULL; + char *active_network = NULL; + int dev_type; + char **networks = NULL; + int num_items = 0; + int i; + + /* Grab the lock for the network list. */ + g_mutex_lock (applet->networks_mutex); + + /* Clear out existing entries in the list */ + if (applet->networks) + { + g_slist_foreach (applet->networks, wireless_network_free, NULL); + g_slist_free (applet->networks); + applet->networks = NULL; + } + g_mutex_unlock (applet->networks_mutex); + + if ( (applet->applet_state != APPLET_STATE_WIRELESS) + && (applet->applet_state != APPLET_STATE_WIRELESS_CONNECTING)) + return; + + if (!(active_device = nmwa_dbus_get_active_device (applet, APPLET_STATE_NO_CONNECTION))) + goto out; + + if ( ((dev_type = nmwa_dbus_get_device_type (applet, active_device, APPLET_STATE_NO_CONNECTION)) == -1) + || (dev_type != DEVICE_TYPE_WIRELESS_ETHERNET)) + goto out; + + active_network = nmwa_dbus_get_active_network (applet, active_device, APPLET_STATE_IGNORE); + if (applet->applet_state == APPLET_STATE_NO_NM) + goto out; /* Don't proceed if NetworkManager died during the call to get the active network */ + + /* Get each of the networks in turn and add them to the menu */ + networks = nmwa_dbus_get_device_networks (applet, active_device, &num_items, APPLET_STATE_NO_CONNECTION); + if ((applet->applet_state != APPLET_STATE_WIRELESS) && (applet->applet_state != APPLET_STATE_WIRELESS_CONNECTING)) + goto out; + + if (!networks) + goto out; + + g_mutex_lock (applet->networks_mutex); + + for (i = 0; i < num_items; i++) + { + char *name = NULL; + + if (!(name = nmwa_dbus_get_network_name (applet, networks[i]))) + break; + + if (name && strlen (name)) + { + gboolean found = FALSE; + int j; + WirelessNetwork *net = NULL; + + /* Only show one menu item per network. NetworkManager really passes back a list + * of access points, and there may be more than one that have the same ESSID. Filter + * them here. + */ + for (j = 0; j < i; j++) + if (found = (networks[j] && (strcmp (networks[i], networks[j]) == 0))) + break; + if (found) + continue; + + net = g_new0 (WirelessNetwork, 1); + net->essid = g_strdup (name); + net->active = active_network ? (strcmp (networks[i], active_network) == 0) : FALSE; + net->encrypted = nmwa_dbus_get_network_encrypted (applet, networks[i]); + + fprintf( stderr, "Adding '%s' active (%d), enc (%d)\n", name, net->active, net->encrypted); + applet->networks = g_slist_append (applet->networks, net); + } + dbus_free (name); + } + g_mutex_unlock (applet->networks_mutex); + +out: + dbus_free (active_device); + dbus_free (active_network); + dbus_free_string_array (networks); +} + + +/* + * nmwa_dbus_update_network_state + * + * Update our state based on what NetworkManager's network state is + * + */ +void nmwa_dbus_update_network_state (NMWirelessApplet *applet) +{ + char *active_device = NULL; + char *nm_status = NULL; + int dev_type = -1; + + g_return_if_fail (applet != NULL); + + /* Grab NetworkManager's status */ + if (!(nm_status = nmwa_dbus_get_nm_status (applet, APPLET_STATE_NO_CONNECTION))) + return; + + if (strcmp (nm_status, "disconnected") == 0) + { + applet->applet_state = APPLET_STATE_NO_CONNECTION; + goto out; + } + + if (!(active_device = nmwa_dbus_get_active_device (applet, APPLET_STATE_NO_CONNECTION))) + goto out; + + if ((dev_type = nmwa_dbus_get_device_type (applet, active_device, APPLET_STATE_NO_CONNECTION)) == -1) + goto out; + + /* If the device is not 802.x, we don't show state for it (yet) */ + if ((dev_type != DEVICE_TYPE_WIRED_ETHERNET) && (dev_type != DEVICE_TYPE_WIRELESS_ETHERNET)) + { + applet->applet_state = APPLET_STATE_NO_CONNECTION; + goto out; + } + else if (dev_type == DEVICE_TYPE_WIRED_ETHERNET) + { + if (strcmp (nm_status, "connecting") == 0) + applet->applet_state = APPLET_STATE_WIRED_CONNECTING; + else if (strcmp (nm_status, "connected") == 0) + applet->applet_state = APPLET_STATE_WIRED; + } + else if (dev_type == DEVICE_TYPE_WIRELESS_ETHERNET) + { + if (strcmp (nm_status, "connecting") == 0) + applet->applet_state = APPLET_STATE_WIRELESS_CONNECTING; + else if (strcmp (nm_status, "connected") == 0) + applet->applet_state = APPLET_STATE_WIRELESS; + } + +out: + dbus_free (nm_status); + dbus_free (active_device); } @@ -541,8 +747,11 @@ static DBusHandlerResult nmwa_dbus_filter (DBusConnection *connection, DBusMessa dbus_error_init (&error); if ( dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &service, DBUS_TYPE_INVALID) - && (strcmp (service, NM_DBUS_SERVICE) == 0)) - applet->nm_active = TRUE; + && (strcmp (service, NM_DBUS_SERVICE) == 0) && (applet->applet_state == APPLET_STATE_NO_NM)) +{ + applet->applet_state = APPLET_STATE_NO_CONNECTION; +fprintf( stderr, "ServiceCreate state = (%d)\n", applet->applet_state); +} } else if (dbus_message_is_signal (message, DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS, "ServiceDeleted")) { @@ -552,20 +761,23 @@ static DBusHandlerResult nmwa_dbus_filter (DBusConnection *connection, DBusMessa dbus_error_init (&error); if ( dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &service, DBUS_TYPE_INVALID) && (strcmp (service, NM_DBUS_SERVICE) == 0)) - applet->nm_active = FALSE; +{ + applet->applet_state = APPLET_STATE_NO_NM; +fprintf( stderr, "ServiceDeleted state = (%d)\n", applet->applet_state); +} } else if ( dbus_message_is_signal (message, NM_DBUS_INTERFACE, "WirelessNetworkAppeared") - || dbus_message_is_signal (message, NM_DBUS_INTERFACE, "WirelessNetworkDisappeared") - || dbus_message_is_signal (message, NM_DBUS_INTERFACE, "DeviceNowActive") - || dbus_message_is_signal (message, NM_DBUS_INTERFACE, "DeviceNoLongerActive")) + || dbus_message_is_signal (message, NM_DBUS_INTERFACE, "WirelessNetworkDisappeared")) { - if (applet->menu && !GTK_WIDGET_VISIBLE (applet->menu)) - { - nmwa_dispose_menu (applet); - applet->menu = nmwa_populate_menu (applet); - } - else if (!applet->menu) - applet->menu = nmwa_populate_menu (applet); +fprintf( stderr, "Updating wireless networks\n"); + nmwa_dbus_update_wireless_network_list (applet); + } + else if ( dbus_message_is_signal (message, NM_DBUS_INTERFACE, "DeviceNowActive") + || dbus_message_is_signal (message, NM_DBUS_INTERFACE, "DeviceNoLongerActive") + || dbus_message_is_signal (message, NM_DBUS_INTERFACE, "DeviceActivating")) + { +fprintf( stderr, "Updating network state\n"); + nmwa_dbus_update_network_state (applet); } else handled = FALSE; @@ -574,17 +786,38 @@ static DBusHandlerResult nmwa_dbus_filter (DBusConnection *connection, DBusMessa } +/* + * nmwa_dbus_nm_is_running + * + * Ask dbus whether or not NetworkManager is running + * + */ +gboolean nmwa_dbus_nm_is_running (DBusConnection *connection) +{ + DBusError error; + gboolean exists; + + g_return_val_if_fail (connection != NULL, FALSE); + + dbus_error_init (&error); + exists = dbus_bus_service_exists (connection, NM_DBUS_SERVICE, &error); + return (exists); +} + + /* * nmwa_dbus_init * * Initialize a connection to NetworkManager if we can get one * */ -DBusConnection * nmwa_dbus_init (gpointer user_data) +static DBusConnection * nmwa_dbus_init (NMWirelessApplet *applet, GMainContext *context) { - DBusConnection *connection; + DBusConnection *connection = NULL; DBusError error; + g_return_val_if_fail (applet != NULL, NULL); + dbus_error_init (&error); connection = dbus_bus_get (DBUS_BUS_SYSTEM, &error); @@ -594,13 +827,11 @@ DBusConnection * nmwa_dbus_init (gpointer user_data) return (NULL); } - g_assert(connection); - - if (!dbus_connection_add_filter (connection, nmwa_dbus_filter, user_data, NULL)) + if (!dbus_connection_add_filter (connection, nmwa_dbus_filter, applet, NULL)) return (NULL); dbus_connection_set_exit_on_disconnect (connection, FALSE); - dbus_connection_setup_with_g_main (connection, NULL); + dbus_connection_setup_with_g_main (connection, context); dbus_bus_add_match(connection, "type='signal'," @@ -615,6 +846,73 @@ DBusConnection * nmwa_dbus_init (gpointer user_data) "sender='" NM_DBUS_SERVICE "'", &error); +fprintf( stderr, "returning good DBUS connection\n"); return (connection); } + +/* + * nmwa_dbus_timeout_worker + * + * Timer to update our state from NetworkManager + * + */ +static gboolean nmwa_dbus_timeout_worker (gpointer user_data) +{ + NMWirelessApplet *applet = (NMWirelessApplet *)user_data; + + g_return_val_if_fail (applet != NULL, TRUE); + + if (!applet->connection) + { + /* After our first connection, update the state. After that, we listen + * for signals from NetworkManager to trigger state updates. + */ + if ((applet->connection = nmwa_dbus_init (applet, applet->thread_context))) + nmwa_dbus_update_network_state (applet); + } + + return (TRUE); +} + + +/* + * nmwa_dbus_worker + * + * Thread worker function that periodically grabs the NetworkManager state + * and updates our local applet state to reflect that. + * + */ +gpointer nmwa_dbus_worker (gpointer user_data) +{ + NMWirelessApplet *applet = (NMWirelessApplet *)user_data; + GMainLoop *thread_loop; + guint timeout_id; + GSource *timeout_source; + + g_return_val_if_fail (applet != NULL, NULL); + + if (!(applet->thread_context = g_main_context_new ())) + return (NULL); + if (!(thread_loop = g_main_loop_new (applet->thread_context, FALSE))) + return (NULL); + + applet->connection = nmwa_dbus_init (applet, applet->thread_context); + + timeout_source = g_timeout_source_new (2000); + g_source_set_callback (timeout_source, nmwa_dbus_timeout_worker, applet, NULL); + timeout_id = g_source_attach (timeout_source, applet->thread_context); + + if (applet->connection && nmwa_dbus_nm_is_running (applet->connection)) + { + nmwa_dbus_update_network_state (applet); + if ((applet->applet_state == APPLET_STATE_WIRELESS) || (applet->applet_state == APPLET_STATE_WIRELESS_CONNECTING)) + nmwa_dbus_update_wireless_network_list (applet); + } + else + applet->applet_state = APPLET_STATE_NO_NM; + + g_main_loop_run (thread_loop); + + g_source_destroy (timeout_source); +} diff --git a/panel-applet/NMWirelessAppletDbus.h b/panel-applet/NMWirelessAppletDbus.h index eaf4e8909..9de4ebf73 100644 --- a/panel-applet/NMWirelessAppletDbus.h +++ b/panel-applet/NMWirelessAppletDbus.h @@ -26,6 +26,14 @@ #include #include "NMWirelessApplet.h" +/* Return codes for functions that use dbus */ +enum +{ + RETURN_SUCCESS = 1, + RETURN_FAILURE = 0, + RETURN_NO_NM = -1 +}; + /* Must match NetworkManager device types */ enum { @@ -34,17 +42,7 @@ enum DEVICE_TYPE_WIRELESS_ETHERNET }; -DBusConnection * nmwa_dbus_init (gpointer user_data); - -gboolean nmwa_dbus_nm_is_running (DBusConnection *connection); - -void nmwa_dbus_add_networks_to_menu (NMWirelessApplet *applet, GtkWidget *menu); - -char * nmwa_dbus_get_active_device (DBusConnection *connection); - -int nmwa_dbus_get_device_type (DBusConnection *connection, char *path); - -char * nmwa_dbus_get_nm_status (DBusConnection *connection); +gpointer nmwa_dbus_worker (gpointer user_data); void nmwa_dbus_set_network (DBusConnection *connection, char *network); diff --git a/panel-applet/wireless-applet.glade b/panel-applet/wireless-applet.glade new file mode 100644 index 000000000..43dbdead3 --- /dev/null +++ b/panel-applet/wireless-applet.glade @@ -0,0 +1,156 @@ + + + + + + + 6 + + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER_ALWAYS + True + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_DIALOG + GDK_GRAVITY_NORTH_WEST + False + + + + True + False + 12 + + + + True + GTK_BUTTONBOX_END + + + + True + True + True + gtk-cancel + True + GTK_RELIEF_NORMAL + True + -6 + + + + + + True + True + True + True + _Login to Network + True + GTK_RELIEF_NORMAL + True + -5 + + + + + 0 + False + True + GTK_PACK_END + + + + + + 6 + True + False + 12 + + + + True + gtk-dialog-warning + 6 + 0.5 + 0 + 0 + 0 + + + 0 + False + True + + + + + + True + False + 12 + + + + True + <span weight="bold" size="larger">Wireless Network Login Confirmation</span> + +You have chosen log in to the wireless network '%s'. If you are sure this wireless network is secure, click the checkbox below and NetworkManager will no longer pester you with stupid questions when you connect to it. + False + True + GTK_JUSTIFY_LEFT + True + False + 0 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + True + Always Trust this Wireless Network + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + 0 + True + True + + + + + 0 + True + True + + + + + + +