diff --git a/ChangeLog b/ChangeLog index f24ad3c49e..03298148d3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,36 @@ +Thu Aug 26 2004 Dan Williams + + * panel-applet/NMWirelessApplet.[ch] + - Rework menu code to add devices to menu, and to show + signal strength for each access point. Code cleanups + too. + + * panel-applet/NMWirelessAppletDbus.c + - Grab network devices from NetworkManager too + - Grab quality information from NM for wireless networks + + * src/NetworkManagerDbus.[ch] + - Add dbus methods for getting the HAL UDI from a device and + for getting its base quality, if its wireless + - Consolidate some functions (wireless network notifications, + device notifications) + - Add method for requesting NM to use a particular device + + * src/NetworkManager.c + - Change for function consolidations from NetworkManagerDbus.c + - Implement active device locking and user-requested devices + (ie, tell NM to use a particular device instead of the one + it autochose) + + * src/NetworkManagerDevice.c + - Add method for getting the base quality of a device, if its + wireless + - Grab device base quailty info from iwlib during scans + + * src/NetworkManagerPolicy.c + - Use a user-requested device rather than the auto-chosen device + if we are told to + Thu Aug 26 15:12:36 2004 Jonathan Blandford * Makefile.am: add po as a supdir diff --git a/info-daemon/NetworkManagerInfoDbus.c b/info-daemon/NetworkManagerInfoDbus.c index c90386cc68..0105429f01 100644 --- a/info-daemon/NetworkManagerInfoDbus.c +++ b/info-daemon/NetworkManagerInfoDbus.c @@ -100,6 +100,7 @@ static void nmi_dbus_get_key_for_network (NMIAppInfo *info, DBusMessage *message DBUS_TYPE_STRING, &network, DBUS_TYPE_INVALID)) { +fprintf( stderr, "getUserKey\n"); nmi_passphrase_dialog_show (device, network, info); dbus_free (device); diff --git a/panel-applet/Makefile.am b/panel-applet/Makefile.am index cc119760ac..0b33be9b00 100644 --- a/panel-applet/Makefile.am +++ b/panel-applet/Makefile.am @@ -46,6 +46,7 @@ glade_DATA = wireless-applet.glade pixmapdir = $(datadir)/pixmaps/NMWirelessApplet pixmap_DATA = no-link-0.png \ wired.png \ + wireless.png \ broken-0.png \ signal-1-40.png \ signal-41-60.png \ diff --git a/panel-applet/NMWirelessApplet.c b/panel-applet/NMWirelessApplet.c index 63b75651c6..1278379de4 100644 --- a/panel-applet/NMWirelessApplet.c +++ b/panel-applet/NMWirelessApplet.c @@ -211,6 +211,12 @@ static void nmwa_load_theme (NMWirelessApplet *applet) pixmapname = g_build_filename (G_DIR_SEPARATOR_S, pixmapdir, "keyring.png", NULL); applet->key_pixbuf = gdk_pixbuf_new_from_file_at_size (pixmapname, 16, 16, &error); g_free (pixmapname); + pixmapname = g_build_filename (G_DIR_SEPARATOR_S, pixmapdir, "wired.png", NULL); + applet->wired_icon = gdk_pixbuf_new_from_file_at_size (pixmapname, 16, 16, &error); + g_free (pixmapname); + pixmapname = g_build_filename (G_DIR_SEPARATOR_S, pixmapdir, "wireless.png", NULL); + applet->wireless_icon = gdk_pixbuf_new_from_file_at_size (pixmapname, 16, 16, &error); + g_free (pixmapname); g_free (pixmapdir); } @@ -454,17 +460,132 @@ static void nmwa_toplevel_menu_activate (GtkWidget *menu, NMWirelessApplet *appl /* - * nmwa_add_menu_item - * - * Add a menu item + * nmwa_menu_add_separator_item * */ -void nmwa_add_menu_item (NMWirelessApplet *applet, GtkWidget *menu, char *text, char *tag, gboolean current, - gboolean encrypted) +void nmwa_menu_add_separator_item (GtkWidget *menu) +{ + GtkWidget *menu_item; + + menu_item = gtk_separator_menu_item_new (); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); + gtk_widget_show (menu_item); +} + + +/* + * nmwa_menu_add_text_item + * + * Add a non-clickable text item to a menu + * + */ +void nmwa_menu_add_text_item (GtkWidget *menu, char *text) +{ + GtkWidget *menu_item; + GtkWidget *label; + + g_return_if_fail (text != NULL); + g_return_if_fail (menu != NULL); + + menu_item = gtk_menu_item_new_with_label (text); + gtk_widget_set_sensitive (menu_item, FALSE); + + gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); + gtk_widget_show (menu_item); +} + + +/* + * nmwa_menu_add_device_item + * + * Add a network device to the menu + * + */ +void nmwa_menu_add_device_item (GtkWidget *menu, GdkPixbuf *icon, char *name, char *nm_device, gpointer user_data) { GtkWidget *menu_item; GtkWidget *label; GtkWidget *hbox; + GtkWidget *image; + + g_return_if_fail (menu != NULL); + g_return_if_fail (icon != NULL); + g_return_if_fail (name != NULL); + g_return_if_fail (nm_device != NULL); + + menu_item = gtk_menu_item_new (); + hbox = gtk_hbox_new (FALSE, 5); + gtk_container_add (GTK_CONTAINER (menu_item), hbox); + gtk_widget_show (hbox); + + if ((image = gtk_image_new_from_pixbuf (icon))) + { + gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 2); + gtk_widget_show (image); + } + + label = gtk_label_new (name); + gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); + gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 2); + gtk_widget_show (label); + + g_object_set_data (G_OBJECT (menu_item), "device", g_strdup (nm_device)); + g_signal_connect(G_OBJECT (menu_item), "activate", G_CALLBACK(nmwa_menu_item_activate), user_data); + + gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); + gtk_widget_show (menu_item); +} + + +/* + * nmwa_menu_add_devices + * + */ +void nmwa_menu_add_devices (GtkWidget *menu, NMWirelessApplet *applet) +{ + GSList *element; + + g_return_if_fail (menu != NULL); + g_return_if_fail (applet != NULL); + + g_mutex_lock (applet->data_mutex); + element = applet->devices; + if (!element) + nmwa_menu_add_text_item (menu, _("There are no network devices...")); + else + { + /* Add all devices in our device list to the menu */ + while (element) + { + NetworkDevice *dev = (NetworkDevice *)(element->data); + + if (dev && ((dev->type == DEVICE_TYPE_WIRED_ETHERNET) || (dev->type == DEVICE_TYPE_WIRELESS_ETHERNET))) + { + GdkPixbuf *icon = (dev->type == DEVICE_TYPE_WIRED_ETHERNET) ? applet->wired_icon : applet->wireless_icon; + nmwa_menu_add_device_item (menu, icon, dev->name, dev->nm_device, applet); + } + + element = g_slist_next (element); + } + } + g_mutex_unlock (applet->data_mutex); +} + + +/* + * nmwa_menu_add_network + * + * Add a wireless network menu item + * + */ +void nmwa_menu_add_network (GtkWidget *menu, GdkPixbuf *key, char *text, char *network, gboolean current, + gboolean encrypted, guint8 quality, gpointer user_data) +{ + GtkWidget *menu_item; + GtkWidget *label; + GtkWidget *hbox; + GtkWidget *progress; + float percent; g_return_if_fail (text != NULL); g_return_if_fail (menu != NULL); @@ -485,25 +606,64 @@ void nmwa_add_menu_item (NMWirelessApplet *applet, GtkWidget *menu, char *text, gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 2); gtk_widget_show (label); + progress = gtk_progress_bar_new (); + percent = ((float)quality / (float)0x100); + percent = (percent < 0 ? 0 : (percent > 1.0 ? 1.0 : percent)); + gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (progress), percent); + gtk_box_pack_start (GTK_BOX (hbox), progress, TRUE, TRUE, 0); + gtk_widget_show (progress); + if (encrypted) { GtkWidget *image; - if ((image = gtk_image_new_from_pixbuf (applet->key_pixbuf))) + if ((image = gtk_image_new_from_pixbuf (key))) { gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 2); gtk_widget_show (image); } } - g_object_set_data (G_OBJECT (menu_item), "network", g_strdup (tag)); - g_signal_connect(G_OBJECT (menu_item), "activate", G_CALLBACK(nmwa_menu_item_activate), applet); + g_object_set_data (G_OBJECT (menu_item), "network", g_strdup (network)); + g_signal_connect(G_OBJECT (menu_item), "activate", G_CALLBACK(nmwa_menu_item_activate), user_data); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); gtk_widget_show (menu_item); } +/* + * nmwa_menu_add_networks + * + */ +void nmwa_menu_add_networks (GtkWidget *menu, NMWirelessApplet *applet) +{ + GSList *element; + + g_return_if_fail (menu != NULL); + g_return_if_fail (applet != NULL); + + g_mutex_lock (applet->data_mutex); + element = applet->networks; + if (!element) + nmwa_menu_add_text_item (menu, _("There are no wireless networks...")); + else + { + /* Add all networks in our network list to the menu */ + while (element) + { + WirelessNetwork *net = (WirelessNetwork *)(element->data); + + if (net) + nmwa_menu_add_network (menu, applet->key_pixbuf, net->essid, + net->essid, net->active, net->encrypted, net->quality, applet); + + element = g_slist_next (element); + } + } + g_mutex_unlock (applet->data_mutex); +} + /* * nmwa_menu_item_data_free * @@ -557,49 +717,30 @@ GtkWidget * nmwa_populate_menu (NMWirelessApplet *applet) g_return_if_fail (applet != NULL); fprintf( stderr, "populate_menu() state (%d)\n", applet->applet_state); + if (applet->applet_state == APPLET_STATE_NO_NM) + { + nmwa_menu_add_text_item (menu, _("NetworkManager is not running...")); + return; + } + + nmwa_menu_add_devices (menu, applet); + nmwa_menu_add_separator_item (menu); + 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); + nmwa_menu_add_text_item (menu, _("No network connection is currently active...")); 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); + nmwa_menu_add_text_item (menu, _("A wired network connection is currently active...")); 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); + nmwa_menu_add_networks (menu, applet); break; - } default: break; @@ -746,7 +887,7 @@ static GtkWidget * nmwa_new (NMWirelessApplet *applet) applet->applet_state = APPLET_STATE_NO_NM; /* Start our dbus thread */ - if (!(applet->networks_mutex = g_mutex_new ())) + if (!(applet->data_mutex = g_mutex_new ())) { g_object_unref (G_OBJECT (applet->gconf_client)); /* FIXME: free glade file */ @@ -754,7 +895,7 @@ static GtkWidget * nmwa_new (NMWirelessApplet *applet) } if (!(applet->dbus_thread = g_thread_create (nmwa_dbus_worker, applet, FALSE, &error))) { - g_mutex_free (applet->networks_mutex); + g_mutex_free (applet->data_mutex); g_object_unref (G_OBJECT (applet->gconf_client)); /* FIXME: free glade file */ return (NULL); diff --git a/panel-applet/NMWirelessApplet.h b/panel-applet/NMWirelessApplet.h index d89f134851..dc59a35a8a 100644 --- a/panel-applet/NMWirelessApplet.h +++ b/panel-applet/NMWirelessApplet.h @@ -77,9 +77,12 @@ typedef struct GdkPixbuf *pixmaps[PIX_NUMBER]; GdkPixbuf *current_pixbuf; GdkPixbuf *key_pixbuf; + GdkPixbuf *wired_icon; + GdkPixbuf *wireless_icon; /* Data model elements */ - GMutex *networks_mutex; + GMutex *data_mutex; + GSList *devices; GSList *networks; AppletState applet_state; @@ -101,6 +104,19 @@ typedef struct char *essid; gboolean encrypted; gboolean active; + guint8 quality; } WirelessNetwork; +/* + * Representation of network device + * + */ +typedef struct +{ + char *nm_device; + int type; + char *name; + char *udi; +} NetworkDevice; + #endif diff --git a/panel-applet/NMWirelessAppletDbus.c b/panel-applet/NMWirelessAppletDbus.c index 07ca9d0f0f..e84a24a0ca 100644 --- a/panel-applet/NMWirelessAppletDbus.c +++ b/panel-applet/NMWirelessAppletDbus.c @@ -426,6 +426,30 @@ int nmwa_dbus_get_device_type (NMWirelessApplet *applet, char *path, AppletState } +/* + * nmwa_dbus_get_network_quality + * + * Returns the quality of a given wireless network + * + */ +guint8 nmwa_dbus_get_network_quality (NMWirelessApplet *applet, char *path) +{ + int qual = 0; + + switch (nmwa_dbus_get_int (applet->connection, path, "getQuality", &qual)) + { + case (RETURN_NO_NM): + applet->applet_state = APPLET_STATE_NO_NM; + break; + + default: + break; + } + + return (qual); +} + + /* * nmwa_dbus_get_nm_status * @@ -478,6 +502,54 @@ char * nmwa_dbus_get_network_name (NMWirelessApplet *applet, char *net_path) } +/* + * nmwa_dbus_get_device_name + * + * Returns the name of a specified network device + * + */ +char * nmwa_dbus_get_device_name (NMWirelessApplet *applet, char *dev_path) +{ + char *name = NULL; + + switch (nmwa_dbus_get_string (applet->connection, dev_path, "getName", &name)) + { + case (RETURN_NO_NM): + applet->applet_state = APPLET_STATE_NO_NM; + break; + + default: + break; + } + + return (name); +} + + +/* + * nmwa_dbus_get_device_udi + * + * Returns the HAL udi of a network device + * + */ +char * nmwa_dbus_get_device_udi (NMWirelessApplet *applet, char *dev_path) +{ + char *udi = NULL; + + switch (nmwa_dbus_get_string (applet->connection, dev_path, "getHalUdi", &udi)) + { + case (RETURN_NO_NM): + applet->applet_state = APPLET_STATE_NO_NM; + break; + + default: + break; + } + + return (udi); +} + + /* * nmwa_dbus_get_network_encrypted * @@ -591,7 +663,7 @@ void nmwa_dbus_update_wireless_network_list (NMWirelessApplet *applet) int i; /* Grab the lock for the network list. */ - g_mutex_lock (applet->networks_mutex); + g_mutex_lock (applet->data_mutex); /* Clear out existing entries in the list */ if (applet->networks) @@ -600,7 +672,7 @@ void nmwa_dbus_update_wireless_network_list (NMWirelessApplet *applet) g_slist_free (applet->networks); applet->networks = NULL; } - g_mutex_unlock (applet->networks_mutex); + g_mutex_unlock (applet->data_mutex); if ( (applet->applet_state != APPLET_STATE_WIRELESS) && (applet->applet_state != APPLET_STATE_WIRELESS_CONNECTING)) @@ -625,7 +697,7 @@ void nmwa_dbus_update_wireless_network_list (NMWirelessApplet *applet) if (!networks) goto out; - g_mutex_lock (applet->networks_mutex); + g_mutex_lock (applet->data_mutex); for (i = 0; i < num_items; i++) { @@ -654,13 +726,14 @@ void nmwa_dbus_update_wireless_network_list (NMWirelessApplet *applet) 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]); - + net->quality = nmwa_dbus_get_network_quality (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); + g_mutex_unlock (applet->data_mutex); out: dbus_free (active_device); @@ -726,6 +799,92 @@ out: } +/* + * network_device_free + * + * Frees the representation of a network device + * + */ +static void network_device_free (void *element, void *user_data) +{ + NetworkDevice *dev = (NetworkDevice *)(element); + + if (dev) + { + g_free (dev->nm_device); + g_free (dev->name); + g_free (dev->udi); + } + g_free (dev); +} + + +/* + * nmwa_dbus_update_devices + * + * Get a device list from NetworkManager + * + */ +void nmwa_dbus_update_devices (NMWirelessApplet *applet) +{ + char **devices = NULL; + int num_items = 0; + int i; + + g_return_if_fail (applet->data_mutex != NULL); + + switch (nmwa_dbus_get_string_array (applet->connection, NM_DBUS_PATH, "getDevices", &num_items, &devices)) + { + case (RETURN_NO_NM): + applet->applet_state = APPLET_STATE_NO_NM; + break; + + default: + break; + } + + if (!devices) + return; + + /* Clear out existing device list */ + g_mutex_lock (applet->data_mutex); + g_slist_foreach (applet->devices, network_device_free, NULL); + g_slist_free (applet->devices); + applet->devices = NULL; + + for (i = 0; i < num_items; i++) + { + char *name = nmwa_dbus_get_device_name (applet, devices [i]); + + if (name && strlen (name)) + { + NetworkDevice *dev; + + if ((dev = g_new0 (NetworkDevice, 1))) + { + dev->nm_device = g_strdup (devices[i]); + dev->type = nmwa_dbus_get_device_type (applet, devices[i], APPLET_STATE_NO_CONNECTION); + dev->name = g_strdup (name); + dev->udi = nmwa_dbus_get_device_udi (applet, devices[i]); + + /* Ensure valid device information */ + if (!dev->nm_device || !dev->name || !dev->udi || (dev->type == -1)) + network_device_free (dev, NULL); + else + { + applet->devices = g_slist_append (applet->devices, dev); + fprintf( stderr, "Got device '%s', udi '%s'\n", dev->name, dev->udi); + } + } + } + dbus_free (name); + } + + g_mutex_unlock (applet->data_mutex); + dbus_free_string_array (devices); +} + + /* * nmwa_dbus_filter * @@ -773,6 +932,8 @@ fprintf( stderr, "ServiceCreate state = (%d)\n", applet->applet_state); { nmwa_dbus_update_network_state (applet); } + else if (dbus_message_is_signal (message, NM_DBUS_INTERFACE, "DevicesChanged")) + nmwa_dbus_update_devices (applet); else handled = FALSE; @@ -902,6 +1063,7 @@ gpointer nmwa_dbus_worker (gpointer user_data) 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); + nmwa_dbus_update_devices (applet); } else applet->applet_state = APPLET_STATE_NO_NM; diff --git a/src/NetworkManager.c b/src/NetworkManager.c index 2270349168..d5c7472411 100644 --- a/src/NetworkManager.c +++ b/src/NetworkManager.c @@ -106,7 +106,10 @@ NMDevice * nm_create_device_and_add_to_list (NMData *data, const char *udi) hal_free_string (iface_name); if (success) + { nm_data_set_state_modified (data, TRUE); + nm_dbus_signal_device_status_change (data->dbus_connection, dev, DEVICE_LIST_CHANGE); + } else { /* If we couldn't add the device to our list, free its data. */ @@ -143,24 +146,31 @@ void nm_remove_device_from_list (NMData *data, const char *udi) { NMDevice *dev = (NMDevice *)(element->data); - if (dev) + if (dev && (nm_null_safe_strcmp (nm_device_get_udi (dev), udi) == 0)) { - if (nm_null_safe_strcmp (nm_device_get_udi (dev), udi) == 0) + if (data->active_device && (dev == data->active_device)) { - if (data->active_device && (dev == data->active_device)) - data->active_device = NULL; - - nm_device_activation_cancel (dev); - nm_device_unref (dev); - - /* Remove the device entry from the device list and free its data */ - data->dev_list = g_slist_remove_link (data->dev_list, element); - nm_device_unref (element->data); - g_slist_free (element); - nm_data_set_state_modified (data, TRUE); - - break; + data->active_device = NULL; + data->active_device_locked = FALSE; } + + if (data->user_device && (dev == data->user_device)) + { + nm_device_unref (data->user_device); + data->user_device = NULL; + } + + nm_device_activation_cancel (dev); + nm_device_unref (dev); + + /* Remove the device entry from the device list and free its data */ + data->dev_list = g_slist_remove_link (data->dev_list, element); + nm_device_unref (element->data); + g_slist_free (element); + nm_data_set_state_modified (data, TRUE); + nm_dbus_signal_device_status_change (data->dbus_connection, dev, DEVICE_LIST_CHANGE); + + break; } element = g_slist_next (element); } @@ -386,19 +396,12 @@ static NMData *nm_data_new (void) /* Initialize the device list mutex to protect additions/deletions to it. */ data->dev_list_mutex = g_mutex_new (); - if (!data->dev_list_mutex) - { - nm_data_free (data); - syslog( LOG_ERR, "Could not create device list mutex. Whacky shit going on?"); - return (NULL); - } - - /* Initialize the state modified mutex. */ + data->user_device_mutex = g_mutex_new (); data->state_modified_mutex = g_mutex_new (); - if (!data->state_modified_mutex) + if (!data->dev_list_mutex || !data->user_device_mutex || !data->state_modified_mutex) { nm_data_free (data); - syslog( LOG_ERR, "Could not create state_modified mutex. Whacky stuff going on?"); + syslog( LOG_ERR, "Could not initialize data structure locks."); return (NULL); } @@ -420,19 +423,6 @@ static NMData *nm_data_new (void) } -/* - * nm_data_dev_list_element_free - * - * Frees each member of the device list before the list is - * disposed of. - * - */ -static void nm_data_dev_list_element_free (void *element, void *user_data) -{ - nm_device_unref (element); -} - - /* * nm_data_free * @@ -445,9 +435,12 @@ static void nm_data_free (NMData *data) nm_device_unref (data->active_device); - g_slist_foreach (data->dev_list, nm_data_dev_list_element_free, NULL); + g_slist_foreach (data->dev_list, nm_device_unref, NULL); g_slist_free (data->dev_list); + g_mutex_free (data->dev_list_mutex); + g_mutex_free (data->user_device_mutex); + g_mutex_free (data->state_modified_mutex); nm_ap_list_unref (data->trusted_ap_list); nm_ap_list_unref (data->preferred_ap_list); diff --git a/src/NetworkManager.h b/src/NetworkManager.h index 154d4ad56e..d72195210e 100644 --- a/src/NetworkManager.h +++ b/src/NetworkManager.h @@ -38,6 +38,10 @@ struct NMData GMutex *dev_list_mutex; struct NMDevice *active_device; + gboolean active_device_locked; + + struct NMDevice *user_device; /* Holds a device that the user requests NM to use. */ + GMutex *user_device_mutex; gboolean state_modified; GMutex *state_modified_mutex; diff --git a/src/NetworkManagerAPList.c b/src/NetworkManagerAPList.c index c57f938980..f03e0b689a 100644 --- a/src/NetworkManagerAPList.c +++ b/src/NetworkManagerAPList.c @@ -328,7 +328,7 @@ void nm_ap_list_diff (NMData *data, NMDevice *dev, NMAccessPointList *old, NMAcc nm_ap_set_enc_method (new_ap, nm_ap_get_enc_method (old_ap)); } else - nm_dbus_signal_wireless_network_disappeared (data->dbus_connection, dev, old_ap); + nm_dbus_signal_wireless_network_change (data->dbus_connection, dev, old_ap, TRUE); } nm_ap_list_iter_free (iter); } @@ -341,7 +341,7 @@ void nm_ap_list_diff (NMData *data, NMDevice *dev, NMAccessPointList *old, NMAcc while ((new_ap = nm_ap_list_iter_next (iter))) { if (!nm_ap_get_matched (new_ap)) - nm_dbus_signal_wireless_network_appeared (data->dbus_connection, dev, new_ap); + nm_dbus_signal_wireless_network_change (data->dbus_connection, dev, new_ap, FALSE); } nm_ap_list_iter_free (iter); } diff --git a/src/NetworkManagerDbus.c b/src/NetworkManagerDbus.c index 8024e81a05..caf0effc05 100644 --- a/src/NetworkManagerDbus.c +++ b/src/NetworkManagerDbus.c @@ -194,6 +194,61 @@ static DBusMessage *nm_dbus_nm_get_active_device (DBusConnection *connection, DB } +/* + * nm_dbus_nm_set_active_device + * + * Notify the state modification handler that we want to lock to a specific + * device. + * + */ +static DBusMessage *nm_dbus_nm_set_active_device (DBusConnection *connection, DBusMessage *message, NMData *data) +{ + NMDevice *dev = NULL; + DBusMessage *reply_message = NULL; + char *dev_path = NULL; + DBusError error; + + g_return_val_if_fail (connection != NULL, NULL); + g_return_val_if_fail (message != NULL, NULL); + g_return_val_if_fail (data != NULL, NULL); + + dbus_error_init (&error); + if (!dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &dev_path, DBUS_TYPE_INVALID)) + { + reply_message = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "InvalidArguments", + "NetworkManager::setActiveDevice called with invalid arguments."); + return (reply_message); + } + + dev = nm_dbus_get_device_from_object_path (data, dev_path); + dbus_free (dev_path); + if (!dev) + { + reply_message = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "DeviceNotFound", + "The requested network device does not exist."); + return (reply_message); + } + + if (!(reply_message = dbus_message_new_method_return (message))) + return (NULL); + + /* Notify the state modification handler that we'd like to lock on a specific device */ + if (nm_try_acquire_mutex (data->user_device_mutex, __FUNCTION__)) + { + if (data->user_device) + nm_device_unref (data->user_device); + + nm_device_ref (dev); + data->user_device = dev; + + nm_unlock_mutex (data->user_device_mutex, __FUNCTION__); + nm_data_set_state_modified (data, TRUE); + } + + return (reply_message); +} + + /* * nm_dbus_nm_get_devices * @@ -266,15 +321,17 @@ static DBusMessage *nm_dbus_nm_get_devices (DBusConnection *connection, DBusMess /* - * nm_dbus_signal_device_no_longer_active + * nm_dbus_signal_device_status_change * - * Notifies the bus that a particular device is no longer active. + * Notifies the bus that a particular device has had a status change, either + * active or no longer active * */ -void nm_dbus_signal_device_no_longer_active (DBusConnection *connection, NMDevice *dev) +void nm_dbus_signal_device_status_change (DBusConnection *connection, NMDevice *dev, DeviceStatus status) { DBusMessage *message; unsigned char *dev_path; + unsigned char *signal = NULL; g_return_if_fail (connection != NULL); g_return_if_fail (dev != NULL); @@ -282,10 +339,28 @@ void nm_dbus_signal_device_no_longer_active (DBusConnection *connection, NMDevic if (!(dev_path = nm_dbus_get_object_path_from_device (dev))) return; - message = dbus_message_new_signal (NM_DBUS_PATH, NM_DBUS_INTERFACE, "DeviceNoLongerActive"); - if (!message) + switch (status) { - syslog (LOG_ERR, "nm_dbus_signal_device_no_longer_active(): Not enough memory for new dbus message!"); + case (DEVICE_NO_LONGER_ACTIVE): + signal = "DeviceNoLongerActive"; + break; + case (DEVICE_NOW_ACTIVE): + signal = "DeviceNowActive"; + break; + case (DEVICE_ACTIVATING): + signal = "DeviceActivating"; + break; + case (DEVICE_LIST_CHANGE): + signal = "DevicesChanged"; + break; + default: + syslog (LOG_ERR, "nm_dbus_signal_device_status_change(): got a bad signal name"); + return; + } + + if (!(message = dbus_message_new_signal (NM_DBUS_PATH, NM_DBUS_INTERFACE, signal))) + { + syslog (LOG_ERR, "nm_dbus_signal_device_status_change(): Not enough memory for new dbus message!"); g_free (dev_path); return; } @@ -294,77 +369,7 @@ void nm_dbus_signal_device_no_longer_active (DBusConnection *connection, NMDevic g_free (dev_path); if (!dbus_connection_send (connection, message, NULL)) - syslog (LOG_WARNING, "nm_dbus_signal_device_no_longer_active(): Could not raise the DeviceNoLongerActive signal!"); - - dbus_message_unref (message); -} - - -/* - * nm_dbus_signal_device_now_active - * - * Notifies the bus that a particular device is newly active. - * - */ -void nm_dbus_signal_device_now_active (DBusConnection *connection, NMDevice *dev) -{ - DBusMessage *message; - unsigned char *dev_path; - - g_return_if_fail (connection != NULL); - g_return_if_fail (dev != NULL); - - if (!(dev_path = nm_dbus_get_object_path_from_device (dev))) - return; - - message = dbus_message_new_signal (NM_DBUS_PATH, NM_DBUS_INTERFACE, "DeviceNowActive"); - if (!message) - { - syslog (LOG_ERR, "nm_dbus_signal_device_now_active(): Not enough memory for new dbus message!"); - g_free (dev_path); - return; - } - - dbus_message_append_args (message, DBUS_TYPE_STRING, dev_path, DBUS_TYPE_INVALID); - g_free (dev_path); - - if (!dbus_connection_send (connection, message, NULL)) - syslog (LOG_WARNING, "nm_dbus_signal_device_now_active(): Could not raise the DeviceNowActive signal!"); - - dbus_message_unref (message); -} - - -/* - * nm_dbus_signal_device_now_active - * - * Notifies the bus that a particular device is newly active. - * - */ -void nm_dbus_signal_device_activating (DBusConnection *connection, NMDevice *dev) -{ - DBusMessage *message; - unsigned char *dev_path; - - g_return_if_fail (connection != NULL); - g_return_if_fail (dev != NULL); - - if (!(dev_path = nm_dbus_get_object_path_from_device (dev))) - return; - - message = dbus_message_new_signal (NM_DBUS_PATH, NM_DBUS_INTERFACE, "DeviceActivating"); - if (!message) - { - syslog (LOG_ERR, "nm_dbus_signal_device_activating(): Not enough memory for new dbus message!"); - g_free (dev_path); - return; - } - - dbus_message_append_args (message, DBUS_TYPE_STRING, dev_path, DBUS_TYPE_INVALID); - g_free (dev_path); - - if (!dbus_connection_send (connection, message, NULL)) - syslog (LOG_WARNING, "nm_dbus_signal_device_activating(): Could not raise the DeviceActivating signal!"); + syslog (LOG_WARNING, "nm_dbus_signal_device_status_change(): Could not raise the signal!"); dbus_message_unref (message); } @@ -406,12 +411,12 @@ void nm_dbus_signal_device_ip4_address_change (DBusConnection *connection, NMDev /* - * nm_dbus_signal_wireless_network_appeared + * nm_dbus_signal_wireless_network_change * * Notifies the bus that a new wireless network has come into range * */ -void nm_dbus_signal_wireless_network_appeared (DBusConnection *connection, NMDevice *dev, NMAccessPoint *ap) +void nm_dbus_signal_wireless_network_change (DBusConnection *connection, NMDevice *dev, NMAccessPoint *ap, gboolean gone) { DBusMessage *message; char *dev_path; @@ -430,7 +435,8 @@ void nm_dbus_signal_wireless_network_appeared (DBusConnection *connection, NMDev return; } - message = dbus_message_new_signal (NM_DBUS_PATH, NM_DBUS_INTERFACE, "WirelessNetworkAppeared"); + message = dbus_message_new_signal (NM_DBUS_PATH, NM_DBUS_INTERFACE, + (gone ? "WirelessNetworkDisappeared" : "WirelessNetworkAppeared")); if (!message) { syslog (LOG_ERR, "nm_dbus_signal_wireless_network_appeared(): Not enough memory for new dbus message!"); @@ -453,101 +459,6 @@ void nm_dbus_signal_wireless_network_appeared (DBusConnection *connection, NMDev } -/* - * nm_dbus_signal_wireless_network_disappeared - * - * Notifies the bus that a new wireless network is no longer in range - * - */ -void nm_dbus_signal_wireless_network_disappeared (DBusConnection *connection, NMDevice *dev, NMAccessPoint *ap) -{ - DBusMessage *message; - unsigned char *dev_path; - unsigned char *ap_path; - - g_return_if_fail (connection != NULL); - g_return_if_fail (dev != NULL); - g_return_if_fail (ap != NULL); - - if (!(dev_path = nm_dbus_get_object_path_from_device (dev))) - return; - - if (!(ap_path = nm_device_get_path_for_ap (dev, ap))) - { - g_free (dev_path); - return; - } - - message = dbus_message_new_signal (NM_DBUS_PATH, NM_DBUS_INTERFACE, "WirelessNetworkDisappeared"); - if (!message) - { - syslog (LOG_ERR, "nm_dbus_signal_wireless_network_disappeared(): Not enough memory for new dbus message!"); - g_free (dev_path); - g_free (ap_path); - return; - } - - dbus_message_append_args (message, - DBUS_TYPE_STRING, dev_path, - DBUS_TYPE_STRING, ap_path, - DBUS_TYPE_INVALID); - g_free (ap_path); - g_free (dev_path); - - if (!dbus_connection_send (connection, message, NULL)) - syslog (LOG_WARNING, "nnm_dbus_signal_wireless_network_disappeared(): Could not raise the WirelessNetworkDisappeared signal!"); - - dbus_message_unref (message); -} - - -#if 0 -/* - * nm_dbus_get_user_key_for_network_callback - * - * Called from the DBus Pending Call upon receipt of a reply - * message from NetworkManagerInfo. - * - */ -void nm_dbus_get_user_key_for_network_callback (DBusPendingCall *pending, void *user_data) -{ - char *key = NULL; - DBusMessage *reply; - NMDevice *dev = (NMDevice *)user_data; - - g_return_if_fail (dev != NULL); - - reply = dbus_pending_call_get_reply (pending); - if (reply && !dbus_message_is_error (reply, DBUS_ERROR_NO_REPLY)) - { - DBusError error; - - dbus_error_init (&error); - if (dbus_message_get_args (reply, &error, DBUS_TYPE_STRING, &key, DBUS_TYPE_INVALID)) - { - nm_device_pending_action_set_user_key (dev, key); - syslog (LOG_DEBUG, "dbus user key callback got key '%s'", key ); - dbus_free (key); - dbus_pending_call_unref (pending); - } - } -} - - -/* - * nm_dbus_get_user_key_for_network_data_free - * - * Frees data used during the user key pending action - * - */ -void nm_dbus_get_user_key_for_network_data_free (void *user_data) -{ - g_return_if_fail (user_data != NULL); - - nm_device_unref ((NMDevice *)user_data); -} -#endif - /* * nm_dbus_get_user_key_for_network * @@ -575,24 +486,10 @@ void nm_dbus_get_user_key_for_network (DBusConnection *connection, NMDevice *dev DBUS_TYPE_STRING, nm_ap_get_essid (ap), DBUS_TYPE_INVALID); +fprintf( stderr, "getUserKey\n"); if (!dbus_connection_send (connection, message, NULL)) syslog (LOG_WARNING, "nm_dbus_get_user_key_for_network(): could not send dbus message"); - /* For asynchronous replies, disabled for now */ -#if 0 - if (!dbus_connection_send_with_reply (connection, message, pending, -1)) - { - syslog (LOG_ERR, "%s raised: %s", error.name, error.message); - dbus_message_unref (message); - return; - } - - nm_device_ref (dev); - dbus_pending_call_ref (*pending); - dbus_pending_call_set_notify (*pending, &nm_dbus_get_user_key_for_network_callback, - (void *)dev, &nm_dbus_get_user_key_for_network_data_free); -#endif - dbus_message_unref (message); } @@ -1082,8 +979,12 @@ static DBusMessage *nm_dbus_devices_handle_request (DBusConnection *connection, dbus_message_append_args (reply_message, DBUS_TYPE_STRING, nm_device_get_iface (dev), DBUS_TYPE_INVALID); else if (strcmp ("getType", request) == 0) dbus_message_append_args (reply_message, DBUS_TYPE_INT32, nm_device_get_type (dev), DBUS_TYPE_INVALID); + else if (strcmp ("getHalUdi", request) == 0) + dbus_message_append_args (reply_message, DBUS_TYPE_STRING, nm_device_get_udi (dev), DBUS_TYPE_INVALID); else if (strcmp ("getIP4Address", request) == 0) dbus_message_append_args (reply_message, DBUS_TYPE_UINT32, nm_device_get_ip4_address (dev), DBUS_TYPE_INVALID); + else if (strcmp ("getMaxQuality", request) == 0) + dbus_message_append_args (reply_message, DBUS_TYPE_UINT32, nm_device_get_max_quality (dev), DBUS_TYPE_INVALID); else if (strcmp ("getActiveNetwork", request) == 0) { NMAccessPoint *ap; @@ -1198,6 +1099,8 @@ static DBusHandlerResult nm_dbus_nm_message_handler (DBusConnection *connection, reply_message = nm_dbus_nm_get_active_device (connection, message, data); else if (strcmp ("getDevices", method) == 0) reply_message = nm_dbus_nm_get_devices (connection, message, data); + else if (strcmp ("setActiveDevice", method) == 0) + nm_dbus_nm_set_active_device (connection, message, data); else if (strcmp ("setKeyForNetwork", method) == 0) nm_dbus_set_user_key_for_network (connection, message, data); else if (strcmp ("setNetwork", method) == 0) diff --git a/src/NetworkManagerDbus.h b/src/NetworkManagerDbus.h index 8f22ef87b0..23d96f797b 100644 --- a/src/NetworkManagerDbus.h +++ b/src/NetworkManagerDbus.h @@ -39,21 +39,26 @@ #define NMI_DBUS_INTERFACE "org.freedesktop.NetworkManagerInfo" +typedef enum +{ + DEVICE_NOW_ACTIVE, + DEVICE_NO_LONGER_ACTIVE, + DEVICE_ACTIVATING, + DEVICE_LIST_CHANGE +} DeviceStatus; + + DBusConnection *nm_dbus_init (NMData *data); gboolean nm_dbus_is_info_daemon_running (DBusConnection *connection); -void nm_dbus_signal_device_no_longer_active (DBusConnection *connection, NMDevice *dev); +void nm_dbus_signal_device_status_change (DBusConnection *connection, NMDevice *dev, DeviceStatus status); -void nm_dbus_signal_device_now_active (DBusConnection *connection, NMDevice *dev); - -void nm_dbus_signal_device_activating (DBusConnection *connection, NMDevice *dev); +void nm_dbus_signal_devices_changed (DBusConnection *connection); void nm_dbus_signal_device_ip4_address_change(DBusConnection *connection, NMDevice *dev); -void nm_dbus_signal_wireless_network_appeared (DBusConnection *connection, NMDevice *dev, NMAccessPoint *ap); - -void nm_dbus_signal_wireless_network_disappeared (DBusConnection *connection, NMDevice *dev, NMAccessPoint *ap); +void nm_dbus_signal_wireless_network_change (DBusConnection *connection, NMDevice *dev, NMAccessPoint *ap, gboolean gone); void nm_dbus_get_user_key_for_network (DBusConnection *connection, NMDevice *dev, NMAccessPoint *ap); diff --git a/src/NetworkManagerDevice.c b/src/NetworkManagerDevice.c index aabe5038a5..d914a46688 100644 --- a/src/NetworkManagerDevice.c +++ b/src/NetworkManagerDevice.c @@ -50,8 +50,9 @@ typedef struct NMDeviceWirelessOptions { gchar *cur_essid; gboolean supports_wireless_scan; - GMutex *scan_mutex; + guint8 max_quality; + GMutex *scan_mutex; NMAccessPointList *ap_list; NMAccessPoint *best_ap; @@ -657,6 +658,21 @@ void nm_device_set_enc_key (NMDevice *dev, const char *key) } +/* + * nm_device_get_max_quality + * + * Get the quality baseline of a wireless device. + * + */ +guint8 nm_device_get_max_quality (NMDevice *dev) +{ + g_return_val_if_fail (dev != NULL, 0); + g_return_val_if_fail (nm_device_is_wireless (dev), 0); + + return (dev->options.wireless.max_quality); +} + + /* * nm_device_get_ip4_address * @@ -835,7 +851,7 @@ gboolean nm_device_activation_begin (NMDevice *dev) return (FALSE); } - nm_dbus_signal_device_activating (data->dbus_connection, dev); + nm_dbus_signal_device_status_change (data->dbus_connection, dev, DEVICE_ACTIVATING); return (TRUE); } @@ -1156,7 +1172,7 @@ gboolean nm_device_deactivate (NMDevice *dev, gboolean just_added) dev->ip4_address = 0; if (!just_added) - nm_dbus_signal_device_no_longer_active (dev->app_data->dbus_connection, dev); + nm_dbus_signal_device_status_change (dev->app_data->dbus_connection, dev, DEVICE_NO_LONGER_ACTIVE); /* Clean up stuff, don't leave the card associated or up */ if (nm_device_is_wireless (dev)) @@ -1538,6 +1554,13 @@ static void nm_device_do_normal_scan (NMDevice *dev) wireless_scan *tmp_ap; int err; NMAccessPointList *old_ap_list = nm_device_ap_list_get (dev); + gboolean has_range; + iwrange range; + iwstats stats; + + has_range = (iw_get_range_info (iwlib_socket, nm_device_get_iface (dev), &range) < 0) ? FALSE : TRUE; + if (!iw_get_stats (iwlib_socket, nm_device_get_iface (dev), &stats, &range, has_range)) + dev->options.wireless.max_quality = range.max_qual.qual; err = iw_scan (iwlib_socket, nm_device_get_iface (dev), WIRELESS_EXT, &scan_results); if ((err == -1) && (errno == ENODATA)) diff --git a/src/NetworkManagerDevice.h b/src/NetworkManagerDevice.h index 325f81e851..930c7260f8 100644 --- a/src/NetworkManagerDevice.h +++ b/src/NetworkManagerDevice.h @@ -70,6 +70,7 @@ void nm_device_get_ip6_address (NMDevice *dev); gboolean nm_device_get_supports_wireless_scan (NMDevice *dev); void nm_device_do_wireless_scan (NMDevice *dev); +guint8 nm_device_get_max_quality (NMDevice *dev); NMAccessPoint *nm_device_get_best_ap (NMDevice *dev); void nm_device_set_best_ap (NMDevice *dev, NMAccessPoint *ap); diff --git a/src/NetworkManagerPolicy.c b/src/NetworkManagerPolicy.c index 7bb13799f3..113231d44a 100644 --- a/src/NetworkManagerPolicy.c +++ b/src/NetworkManagerPolicy.c @@ -40,13 +40,13 @@ extern gboolean debug; /* - * nm_policy_get_best_device + * nm_policy_auto_get_best_device * - * Filter all the devices and find the best device to use as the - * link. NOTE: caller must lock the device list if needed. + * Find the best device to use, regardless of whether we are + * "locked" on one device at this time. * */ -NMDevice * nm_policy_get_best_device (NMData *data) +static NMDevice * nm_policy_auto_get_best_device (NMData *data) { GSList *element; NMDevice *best_wired_dev = NULL; @@ -126,8 +126,8 @@ NMDevice * nm_policy_get_best_device (NMData *data) element = g_slist_next (element); } - syslog (LOG_NOTICE, "Best wired device = %s", best_wired_dev ? nm_device_get_iface (best_wired_dev) : "(null)"); - syslog (LOG_NOTICE, "Best wireless device = %s (%s)", best_wireless_dev ? nm_device_get_iface (best_wireless_dev) : "(null)", + syslog (LOG_NOTICE, "AUTO: Best wired device = %s", best_wired_dev ? nm_device_get_iface (best_wired_dev) : "(null)"); + syslog (LOG_NOTICE, "AUTO: Best wireless device = %s (%s)", best_wireless_dev ? nm_device_get_iface (best_wireless_dev) : "(null)", best_wireless_dev ? nm_device_get_essid (best_wireless_dev) : "null" ); if (best_wireless_dev || best_wired_dev) @@ -142,6 +142,73 @@ NMDevice * nm_policy_get_best_device (NMData *data) } +/* + * nm_policy_get_best_device + * + * Find the best device to use, taking into account if we are + * "locked" on one device or not. That lock may also be cleared + * under certain conditions. + * + */ +static NMDevice * nm_policy_get_best_device (NMData *data) +{ + NMDevice *best_dev = NULL; + + g_return_val_if_fail (data != NULL, NULL); + + /* Can't lock the active device if you don't have one */ + if (!data->active_device) + data->active_device_locked = FALSE; + + /* If the user told us to switch to a particular device, do it now */ + if (nm_try_acquire_mutex (data->user_device_mutex, __FUNCTION__)) + { + if (data->user_device) + { + best_dev = data->user_device; + + nm_device_unref (data->user_device); + data->user_device = NULL; + } + nm_unlock_mutex (data->user_device_mutex, __FUNCTION__); + } + + /* Determine whether we need to clear the active device and unlock it. */ + if (!best_dev && data->active_device_locked) + { + switch (nm_device_get_type (data->active_device)) + { + /* If the active device was a wired device, and it no + * longer has a link, switch to auto mode. + */ + case (DEVICE_TYPE_WIRED_ETHERNET): + if (nm_device_get_link_active (data->active_device)) + best_dev = data->active_device; + break; + + /* For wireless devices, we only "unlock" them if they are + * removed from the system. + */ + case (DEVICE_TYPE_WIRELESS_ETHERNET): + best_dev = data->active_device; + break; + + default: + break; + } + } + + /* Fall back to automatic device picking */ + if (!best_dev) + { + data->active_device_locked = FALSE; + best_dev = nm_policy_auto_get_best_device (data); + } + + return (best_dev); +} + + /* * nm_state_modification_monitor * @@ -232,7 +299,7 @@ gboolean nm_state_modification_monitor (gpointer user_data) } else if (data->active_device && nm_device_just_activated (data->active_device)) { - nm_dbus_signal_device_now_active (data->dbus_connection, data->active_device); + nm_dbus_signal_device_status_change (data->dbus_connection, data->active_device, DEVICE_NOW_ACTIVE); syslog (LOG_INFO, "nm_state_modification_monitor() activated device %s", nm_device_get_iface (data->active_device)); }