diff --git a/ChangeLog b/ChangeLog index ae5c3105ed..fd1c968236 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,41 @@ +2005-02-27 Dan Williams + + * panel-applet/NMWirelessApplet.[ch] + panel-applet/NMWirelessAppletDbus.[ch] + - Move to incremental network updates. Instead of blowing away our list + of devices every time we get a signal from NetworkManager, we now + incrementally add/remove networks when NetworkManager notifies us that + a new network has appeared or disappered. Strength updates now happen + on-the-fly for each access point as well. There are now two copies of + data from NetworkManager: one for the dbus side, and one for the gui side. + When the dbus side data is modified, it is copied over to the gui side + so we don't have to hold the data_mutex for long periods of time (and + therefore block animation of the applet's icon). + - Clean up some memleaks too + + * panel-applet/NMWirelessAppletOtherNetworkDialog.c + - Minor code beautification + + * src/NetworkManagerAPList.c + - (nm_ap_list_merge_scanned_ap): return whether or not the access point is + completely new and whether or not an existing one's strength was updated. + Try to fix multiple access points and signal strength by using the highest + signal strength in each scan for any given ESSID. + + * src/NetworkManagerDbus.[ch] + - (nm_dbus_signal_wireless_network_change): consolidate signals that deal with + wireless networks; now we have only WirelessNetworkUpdate which includes + a UINT32 for Appeared, Disappeared, or StrengthChanged (see NetworkManager.h). + - Kill usage of DbusMessageIter + + * src/NetworkManagerDevice.c + - (nm_device_wireless_process_scan_results): Use the same timestamp for all APs + in the same scan result list. Copy ESSIDs-by-address earlier on, for each + AP rather than all-at-once. Also don't ever remove the AP a card is + currently associated with from the network list. + - Update for new signals during scan, send out Appeared, Disappeared, or + StrengthChanged when necessary. + 2005-02-25 Dan Williams * README diff --git a/panel-applet/NMWirelessApplet.c b/panel-applet/NMWirelessApplet.c index 2287ce5490..d44bde44b7 100644 --- a/panel-applet/NMWirelessApplet.c +++ b/panel-applet/NMWirelessApplet.c @@ -69,6 +69,7 @@ static GObject * nmwa_constructor (GType type, guint n_props, GObjectConstructParam *construct_props); static void setup_stock (void); static void nmwa_icons_init (NMWirelessApplet *applet); +static void nmwa_icons_free (NMWirelessApplet *applet); static gboolean nmwa_fill (NMWirelessApplet *applet); static void nmwa_about_cb (NMWirelessApplet *applet); static void nmwa_context_menu_update (NMWirelessApplet *applet); @@ -190,48 +191,48 @@ static void nmwa_update_network_state (NMWirelessApplet *applet) if (applet->applet_state == APPLET_STATE_NO_NM) goto out; - if (!applet->nm_status) + if (!applet->gui_nm_status) { applet->applet_state = APPLET_STATE_NO_CONNECTION; goto out; } - if (strcmp (applet->nm_status, "scanning") == 0) + if (strcmp (applet->gui_nm_status, "scanning") == 0) { applet->applet_state = APPLET_STATE_WIRELESS_SCANNING; goto out; } - if (strcmp (applet->nm_status, "disconnected") == 0) + if (strcmp (applet->gui_nm_status, "disconnected") == 0) { applet->applet_state = APPLET_STATE_NO_CONNECTION; goto out; } - if (!applet->active_device) + if (!applet->gui_active_device) { applet->applet_state = APPLET_STATE_NO_CONNECTION; goto out; } /* If the device is not 802.x, we don't show state for it (yet) */ - if ( (applet->active_device->type != DEVICE_TYPE_WIRED_ETHERNET) - && (applet->active_device->type != DEVICE_TYPE_WIRELESS_ETHERNET)) + if ( (applet->gui_active_device->type != DEVICE_TYPE_WIRED_ETHERNET) + && (applet->gui_active_device->type != DEVICE_TYPE_WIRELESS_ETHERNET)) { applet->applet_state = APPLET_STATE_NO_CONNECTION; } - else if (applet->active_device->type == DEVICE_TYPE_WIRED_ETHERNET) + else if (applet->gui_active_device->type == DEVICE_TYPE_WIRED_ETHERNET) { - if (strcmp (applet->nm_status, "connecting") == 0) + if (strcmp (applet->gui_nm_status, "connecting") == 0) applet->applet_state = APPLET_STATE_WIRED_CONNECTING; - else if (strcmp (applet->nm_status, "connected") == 0) + else if (strcmp (applet->gui_nm_status, "connected") == 0) applet->applet_state = APPLET_STATE_WIRED; } - else if (applet->active_device->type == DEVICE_TYPE_WIRELESS_ETHERNET) + else if (applet->gui_active_device->type == DEVICE_TYPE_WIRELESS_ETHERNET) { - if (strcmp (applet->nm_status, "connecting") == 0) + if (strcmp (applet->gui_nm_status, "connecting") == 0) applet->applet_state = APPLET_STATE_WIRELESS_CONNECTING; - else if (strcmp (applet->nm_status, "connected") == 0) + else if (strcmp (applet->gui_nm_status, "connected") == 0) applet->applet_state = APPLET_STATE_WIRELESS; } @@ -244,8 +245,8 @@ out: /* We can only do this because we are called with * the applet->data_mutex locked. */ - g_free (applet->nm_status); - applet->nm_status = NULL; + g_free (applet->gui_nm_status); + applet->gui_nm_status = NULL; } old_state = applet->applet_state; } @@ -342,13 +343,13 @@ nmwa_update_state (NMWirelessApplet *applet) WirelessNetwork *active_network = NULL; g_mutex_lock (applet->data_mutex); - if (applet->active_device - && (applet->active_device->type == DEVICE_TYPE_WIRELESS_ETHERNET)) + if (applet->gui_active_device + && (applet->gui_active_device->type == DEVICE_TYPE_WIRELESS_ETHERNET)) { GSList *list; /* Grab a pointer the active network (for ESSID) */ - for (list = applet->active_device->networks; list; list = list->next) + for (list = applet->gui_active_device->networks; list; list = list->next) { WirelessNetwork *network = (WirelessNetwork *) list->data; @@ -356,14 +357,14 @@ nmwa_update_state (NMWirelessApplet *applet) active_network = network; } - strength = CLAMP ((int)applet->active_device->strength, 0, 100); + strength = CLAMP ((int)applet->gui_active_device->strength, 0, 100); } #if 0 /* Only show icon if there's more than one device and at least one is wireless */ - if (g_slist_length (applet->device_list) == 1 && applet->applet_state != APPLET_STATE_NO_NM) + if (g_slist_length (applet->gui_device_list) == 1 && applet->applet_state != APPLET_STATE_NO_NM) { - if (((NetworkDevice *)applet->device_list->data)->type == DEVICE_TYPE_WIRED_ETHERNET) + if (((NetworkDevice *)applet->gui_device_list->data)->type == DEVICE_TYPE_WIRED_ETHERNET) show_applet = FALSE; } #endif @@ -389,7 +390,7 @@ nmwa_update_state (NMWirelessApplet *applet) break; case (APPLET_STATE_WIRELESS): - if (applet->active_device) + if (applet->gui_active_device) { if (applet->is_adhoc) { @@ -574,33 +575,86 @@ WirelessNetwork *nmwa_get_device_network_for_essid (NMWirelessApplet *applet, Ne * NetworkManager ID given. * */ -NetworkDevice *nmwa_get_device_for_nm_device (NMWirelessApplet *applet, const char *nm_dev) +NetworkDevice *nmwa_get_device_for_nm_device (GSList *dev_list, const char *nm_dev) { NetworkDevice *found_dev = NULL; - GSList *element; + GSList *elt; - g_return_val_if_fail (applet != NULL, NULL); g_return_val_if_fail (nm_dev != NULL, NULL); g_return_val_if_fail (strlen (nm_dev), NULL); - g_mutex_lock (applet->data_mutex); - element = applet->device_list; - while (element) + for (elt = dev_list; elt; elt = g_slist_next (elt)) { - NetworkDevice *dev = (NetworkDevice *)(element->data); + NetworkDevice *dev = (NetworkDevice *)(elt->data); if (dev && (strcmp (dev->nm_device, nm_dev) == 0)) { found_dev = dev; break; } - element = g_slist_next (element); } - g_mutex_unlock (applet->data_mutex); return (found_dev); } +/* + * nmwa_get_net_for_nm_net + * + * Searches the network list of a device for a particular network + * + */ +WirelessNetwork *nmwa_get_net_for_nm_net (NetworkDevice *dev, const char *net_path) +{ + WirelessNetwork *found_net = NULL; + GSList *elt; + + g_return_val_if_fail (dev != NULL, NULL); + g_return_val_if_fail (net_path != NULL, NULL); + g_return_val_if_fail (strlen (net_path), NULL); + + for (elt = dev->networks; elt; elt = g_slist_next (elt)) + { + WirelessNetwork *net = (WirelessNetwork *)(elt->data); + if (net && (strcmp (net->nm_name, net_path) == 0)) + { + found_net = net; + break; + } + } + + return (found_net); +} + + +/* + * nmwa_get_net_by_essid + * + * Searches the network list of a device for a particular network + * + */ +WirelessNetwork *nmwa_get_net_by_essid (NetworkDevice *dev, const char *essid) +{ + WirelessNetwork *found_net = NULL; + GSList *elt; + + g_return_val_if_fail (dev != NULL, NULL); + g_return_val_if_fail (essid != NULL, NULL); + g_return_val_if_fail (strlen (essid), NULL); + + for (elt = dev->networks; elt; elt = g_slist_next (elt)) + { + WirelessNetwork *net = (WirelessNetwork *)(elt->data); + if (net && (strcmp (net->essid, essid) == 0)) + { + found_net = net; + break; + } + } + + return (found_net); +} + + /* * nmwa_menu_item_activate * @@ -621,15 +675,30 @@ static void nmwa_menu_item_activate (GtkMenuItem *item, gpointer user_data) { char *item_dev = g_object_get_data (G_OBJECT (item), "nm_device"); - if (item_dev && (dev = nmwa_get_device_for_nm_device (applet, item_dev))) + g_mutex_lock (applet->data_mutex); + if (item_dev && (dev = nmwa_get_device_for_nm_device (applet->gui_device_list, item_dev))) + { + network_device_ref (dev); + g_mutex_unlock (applet->data_mutex); if ((net = nmwa_get_device_network_for_essid (applet, dev, tag))) nmwa_update_network_timestamp (applet, net); + } + else + g_mutex_unlock (applet->data_mutex); } else if ((tag = g_object_get_data (G_OBJECT (item), "device"))) - dev = nmwa_get_device_for_nm_device (applet, tag); + { + g_mutex_lock (applet->data_mutex); + dev = nmwa_get_device_for_nm_device (applet->gui_device_list, tag); + network_device_ref (dev); + g_mutex_unlock (applet->data_mutex); + } if (dev) + { nmwa_dbus_set_device (applet->connection, dev, net, -1, NULL); + network_device_unref (dev); + } } @@ -686,7 +755,7 @@ static void nmwa_menu_add_device_item (GtkWidget *menu, NetworkDevice *device, g gtk_item = wired_menu_item_get_check_item (item); wired_menu_item_update (item, device, n_devices); - if (applet->active_device == device) + if (applet->gui_active_device == device) gtk_check_menu_item_set_active (gtk_item, TRUE); g_object_set_data (G_OBJECT (gtk_item), "device", g_strdup (device->nm_device)); @@ -793,7 +862,7 @@ static void nmwa_menu_device_add_networks (GtkWidget *menu, NetworkDevice *dev, gtk_item = network_menu_item_get_check_item (item); gtk_menu_shell_append (GTK_MENU_SHELL (menu), GTK_WIDGET (gtk_item)); - if (applet->active_device == dev && net->active) + if (applet->gui_active_device == dev && net->active) gtk_check_menu_item_set_active (gtk_item, TRUE); network_menu_item_update (item, net, has_encrypted); @@ -806,44 +875,6 @@ static void nmwa_menu_device_add_networks (GtkWidget *menu, NetworkDevice *dev, } } -static int -sort_networks_function (gconstpointer a, gconstpointer b) -{ - NetworkDevice *dev_a = (NetworkDevice *) a; - NetworkDevice *dev_b = (NetworkDevice *) b; - char *name_a; - char *name_b; - - if (dev_a->hal_name) - name_a = dev_a->hal_name; - else if (dev_a->nm_name) - name_a = dev_a->nm_name; - else - name_a = ""; - - if (dev_b->hal_name) - name_b = dev_b->hal_name; - else if (dev_b->nm_name) - name_b = dev_b->nm_name; - else - name_b = ""; - - if (dev_a->type == dev_b->type) - { - return strcmp (name_a, name_b); - } - if (dev_a->type == DEVICE_TYPE_WIRED_ETHERNET) - return -1; - if (dev_b->type == DEVICE_TYPE_WIRED_ETHERNET) - return 1; - if (dev_a->type == DEVICE_TYPE_WIRELESS_ETHERNET) - return -1; - if (dev_b->type == DEVICE_TYPE_WIRELESS_ETHERNET) - return 1; - - /* Unknown device types. Sort by name only at this point. */ - return strcmp (name_a, name_b); -} /* * nmwa_menu_add_devices @@ -859,16 +890,14 @@ static void nmwa_menu_add_devices (GtkWidget *menu, NMWirelessApplet *applet) g_return_if_fail (applet != NULL); g_mutex_lock (applet->data_mutex); - if (! applet->device_list) + if (! applet->gui_device_list) { nmwa_menu_add_text_item (menu, _("No network devices have been found")); g_mutex_unlock (applet->data_mutex); return; } - applet->device_list = g_slist_sort (applet->device_list, sort_networks_function); - - for (element = applet->device_list; element; element = element->next) + for (element = applet->gui_device_list; element; element = element->next) { NetworkDevice *dev = (NetworkDevice *)(element->data); @@ -888,13 +917,13 @@ static void nmwa_menu_add_devices (GtkWidget *menu, NMWirelessApplet *applet) } /* Add all devices in our device list to the menu */ - for (element = applet->device_list; element; element = element->next) + for (element = applet->gui_device_list; element; element = element->next) { NetworkDevice *dev = (NetworkDevice *)(element->data); if (dev && ((dev->type == DEVICE_TYPE_WIRED_ETHERNET) || (dev->type == DEVICE_TYPE_WIRELESS_ETHERNET))) { - gboolean current = (dev == applet->active_device); + gboolean current = (dev == applet->gui_active_device); gint n_devices = 0; if (dev->type == DEVICE_TYPE_WIRED_ETHERNET) @@ -968,6 +997,12 @@ static void nmwa_menu_item_data_free (GtkWidget *menu_item, gpointer data) g_free (tag); } + if ((tag = g_object_get_data (G_OBJECT (menu_item), "device"))) + { + g_object_set_data (G_OBJECT (menu_item), "device", NULL); + g_free (tag); + } + gtk_widget_destroy (menu_item); } @@ -1251,14 +1286,23 @@ static void nmwa_destroy (NMWirelessApplet *applet, gpointer user_data) if (applet->top_menu_item) gtk_menu_item_remove_submenu (GTK_MENU_ITEM (applet->top_menu_item)); + nmwa_icons_free (applet); + if (applet->redraw_timeout_id > 0) { gtk_timeout_remove (applet->redraw_timeout_id); applet->redraw_timeout_id = 0; } + g_main_loop_quit (applet->thread_loop); + while (applet->thread_done != TRUE) + g_usleep (G_USEC_PER_SEC / 4); + if (applet->gconf_client) g_object_unref (G_OBJECT (applet->gconf_client)); + + nmwa_free_gui_data_model (applet); + nmwa_free_gui_data_model (applet); } @@ -1279,10 +1323,13 @@ static GtkWidget * nmwa_get_instance (NMWirelessApplet *applet) return (NULL); applet->applet_state = APPLET_STATE_NO_NM; - applet->device_list = NULL; - applet->active_device = NULL; - applet->nm_status = NULL; + applet->gui_device_list = NULL; + applet->gui_active_device = NULL; + applet->gui_nm_status = NULL; applet->tooltips = NULL; + applet->thread_context = NULL; + applet->thread_loop = NULL; + applet->thread_done = FALSE; /* Start our dbus thread */ if (!(applet->data_mutex = g_mutex_new ())) diff --git a/panel-applet/NMWirelessApplet.h b/panel-applet/NMWirelessApplet.h index 23d904ef94..f039bb96e4 100644 --- a/panel-applet/NMWirelessApplet.h +++ b/panel-applet/NMWirelessApplet.h @@ -111,18 +111,24 @@ typedef struct guint redraw_timeout_id; GThread *dbus_thread; GMainContext *thread_context; + GMainLoop *thread_loop; + gboolean thread_done; /* Data model elements */ GMutex *data_mutex; AppletState applet_state; gboolean is_adhoc; - GSList *device_list; - NetworkDevice *active_device; - char *nm_status; - NetworkDevice *dbus_active_device; gboolean scanning_enabled; gboolean wireless_enabled; + GSList *gui_device_list; + NetworkDevice *gui_active_device; + char *gui_nm_status; + + GSList *dbus_device_list; + NetworkDevice *dbus_active_device; + char *dbus_nm_status; + GdkPixbuf *no_nm_icon; GdkPixbuf *wired_icon; GdkPixbuf *adhoc_icon; @@ -157,7 +163,9 @@ typedef struct } NMWirelessApplet; -NetworkDevice *nmwa_get_device_for_nm_device (NMWirelessApplet *applet, const char *nm_dev); +NetworkDevice *nmwa_get_device_for_nm_device (GSList *dev_list, const char *nm_dev); +WirelessNetwork *nmwa_get_net_for_nm_net (NetworkDevice *dev, const char *net_path); +WirelessNetwork *nmwa_get_net_by_essid (NetworkDevice *dev, const char *essid); NMWirelessApplet *nmwa_new (void); void show_warning_dialog (gboolean error, gchar *mesg, ...); diff --git a/panel-applet/NMWirelessAppletDbus.c b/panel-applet/NMWirelessAppletDbus.c index dbf4f3a475..12ea53dd75 100644 --- a/panel-applet/NMWirelessAppletDbus.c +++ b/panel-applet/NMWirelessAppletDbus.c @@ -57,7 +57,6 @@ static int nmwa_dbus_call_nm_method (DBusConnection *con, const char *path, cons char **dbus_string_array = NULL; int num_items = 0; dbus_bool_t ret = TRUE; - DBusMessageIter iter; g_return_val_if_fail (con != NULL, RETURN_FAILURE); g_return_val_if_fail (path != NULL, RETURN_FAILURE); @@ -117,8 +116,7 @@ static int nmwa_dbus_call_nm_method (DBusConnection *con, const char *path, cons ret = dbus_message_get_args (reply, &error, DBUS_TYPE_STRING, &dbus_string, DBUS_TYPE_INVALID); break; case DBUS_TYPE_STRING_ARRAY: - dbus_message_iter_init (reply, &iter); - ret = dbus_message_iter_get_string_array (&iter, &dbus_string_array, &num_items); + ret = dbus_message_get_args (reply, &error, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &dbus_string_array, &num_items, DBUS_TYPE_INVALID); break; case DBUS_TYPE_INT32: ret = dbus_message_get_args (reply, &error, DBUS_TYPE_INT32, &dbus_int, DBUS_TYPE_INVALID); @@ -143,15 +141,14 @@ static int nmwa_dbus_call_nm_method (DBusConnection *con, const char *path, cons dbus_message_unref (reply); return (RETURN_FAILURE); } - dbus_message_unref (reply); switch (arg_type) { case DBUS_TYPE_STRING: - *((char **)(arg)) = dbus_string; + *((char **)(arg)) = g_strdup (dbus_string); break; case DBUS_TYPE_STRING_ARRAY: - *((char ***)(arg)) = dbus_string_array; + *((char ***)(arg)) = g_strdupv (dbus_string_array); *item_count = num_items; break; case DBUS_TYPE_INT32: @@ -166,6 +163,7 @@ static int nmwa_dbus_call_nm_method (DBusConnection *con, const char *path, cons break; } + dbus_message_unref (reply); return (RETURN_SUCCESS); } @@ -352,7 +350,6 @@ static char * nmwa_dbus_get_nm_status (NMWirelessApplet *applet, AppletState fai default: break; } - return (status); } @@ -363,7 +360,7 @@ static char * nmwa_dbus_get_nm_status (NMWirelessApplet *applet, AppletState fai * Returns the name of a specified object (wireless network, device, etc) * */ -static char * nmwa_dbus_get_object_name (NMWirelessApplet *applet, char *path) +static char * nmwa_dbus_get_object_name (NMWirelessApplet *applet, const char *path) { char *name = NULL; @@ -538,6 +535,7 @@ static char *nmwa_dbus_get_hal_device_string_property (DBusConnection *connectio DBusError error; DBusMessage *message; DBusMessage *reply; + char *dbus_property = NULL; char *property = NULL; g_return_val_if_fail (connection != NULL, NULL); @@ -565,12 +563,14 @@ static char *nmwa_dbus_get_hal_device_string_property (DBusConnection *connectio } dbus_error_init (&error); - if (!dbus_message_get_args (reply, &error, DBUS_TYPE_STRING, &property, DBUS_TYPE_INVALID)) + if (!dbus_message_get_args (reply, &error, DBUS_TYPE_STRING, &dbus_property, DBUS_TYPE_INVALID)) { if (dbus_error_is_set (&error)) dbus_error_free (&error); - property = NULL; + dbus_property = NULL; } + else + property = g_strdup (dbus_property); dbus_message_unref (reply); return (property); @@ -857,6 +857,31 @@ static void network_device_free_wireless_network_list (NetworkDevice *dev) } +/* + * network_device_remove_wireless_network + * + * Remove one wireless network from the wireless network list + * + */ +void network_device_remove_wireless_network (NetworkDevice *dev, WirelessNetwork *net) +{ + GSList *elt; + + g_return_if_fail (dev != NULL); + g_return_if_fail (net != NULL); + + for (elt = dev->networks; elt; elt = g_slist_next (elt)) + { + if (elt->data == net) + { + dev->networks = g_slist_remove_link (dev->networks, elt); + wireless_network_unref ((WirelessNetwork *)elt->data); + g_slist_free (elt); + break; + } + } +} + /* * network_device_ref * @@ -887,9 +912,10 @@ void network_device_unref (NetworkDevice *dev) network_device_free_wireless_network_list (dev); g_free (dev->nm_device); g_free (dev->nm_name); - dbus_free (dev->udi); - dbus_free (dev->hal_name); + g_free (dev->udi); + g_free (dev->hal_name); g_free (dev); + memset (dev, 0, sizeof (NetworkDevice)); } } @@ -904,7 +930,7 @@ NetworkDevice *network_device_new (void) { NetworkDevice *dev = NULL; - if ((dev = g_new0 (NetworkDevice, 1))) + if ((dev = g_malloc0 (sizeof (NetworkDevice)))) network_device_ref (dev); return (dev); @@ -925,29 +951,28 @@ NetworkDevice *network_device_copy (NetworkDevice *src) g_return_val_if_fail (src != NULL, NULL); - if ((dev = g_new0 (NetworkDevice, 1))) + if ((dev = g_malloc0 (sizeof (NetworkDevice)))) { - GSList *elem; + GSList *elt; network_device_ref (dev); dev->nm_device = g_strdup (src->nm_device); dev->type = src->type; + dev->link = src->link; + dev->supports_carrier_detect = src->supports_carrier_detect; dev->nm_name = g_strdup (src->nm_name); dev->hal_name = g_strdup (src->hal_name); dev->udi = g_strdup (src->udi); dev->strength = src->strength; - elem = src->networks; - while (elem) + for (elt = src->networks; elt; elt = g_slist_next (elt)) { - WirelessNetwork *net = (WirelessNetwork *)elem->data; + WirelessNetwork *net = (WirelessNetwork *)elt->data; if (net) { WirelessNetwork *copy = wireless_network_copy (net); dev->networks = g_slist_append (dev->networks, copy); } - - elem = g_slist_next (elem); } } @@ -956,7 +981,59 @@ NetworkDevice *network_device_copy (NetworkDevice *src) /* - * nmwa_dbus_update_device_wireless_networks + * network_device_add_wireless_network + * + * Adds a wireless network to the network device's network list + * + */ +void network_device_add_wireless_network (NetworkDevice *dev, WirelessNetwork *net) +{ + g_return_if_fail (dev != NULL); + g_return_if_fail (net != NULL); + + wireless_network_ref (net); + dev->networks = g_slist_append (dev->networks, net); +} + + +/* + * nmwa_dbus_get_one_wireless_network + * + * Returns a new wireless network filled with info from NM + * + */ +WirelessNetwork *nmwa_dbus_get_one_wireless_network (NMWirelessApplet *applet, NetworkDevice *dev, + const char *net_path, const char *active_network) +{ + char *name = NULL; + WirelessNetwork *net = NULL; + + g_return_val_if_fail (applet != NULL, NULL); + g_return_val_if_fail (dev != NULL, NULL); + g_return_val_if_fail (net_path != NULL, NULL); + + if (!(name = nmwa_dbus_get_object_name (applet, net_path))) + goto out; + + if (strlen (name)) + { + if (!(net = wireless_network_new ())) + goto out; + net->nm_name = g_strdup (net_path); + net->essid = g_strdup (name); + net->active = active_network ? (strcmp (net->nm_name, active_network) == 0) : FALSE; + net->encrypted = nmwa_dbus_get_network_encrypted (applet, net->nm_name); + net->strength = nmwa_dbus_get_object_strength (applet, net->nm_name); + } + +out: + g_free (name); + return net; +} + + +/* + * nmwa_dbus_device_update_all_networks * * Query NetworkManager for the wireless networks a particular device * knows about, if the active device is wireless. @@ -964,7 +1041,7 @@ NetworkDevice *network_device_copy (NetworkDevice *src) * NOTE: caller must lock device list if necessary * */ -static void nmwa_dbus_update_device_wireless_networks (NetworkDevice *dev, gboolean active_dev, NMWirelessApplet *applet) +static void nmwa_dbus_device_update_all_networks (NetworkDevice *dev, NMWirelessApplet *applet) { char *active_network = NULL; char **networks = NULL; @@ -979,56 +1056,235 @@ static void nmwa_dbus_update_device_wireless_networks (NetworkDevice *dev, gbool if (dev->type != DEVICE_TYPE_WIRELESS_ETHERNET) goto out; - if (active_dev) + if (dev == applet->dbus_active_device) active_network = nmwa_dbus_get_active_network (applet, dev->nm_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, dev->nm_device, &num_items, APPLET_STATE_NO_CONNECTION); if (!networks || (applet->applet_state == APPLET_STATE_NO_NM)) goto out; for (i = 0; i < num_items; i++) { - char *name = NULL; + WirelessNetwork *tmp_net = nmwa_get_net_for_nm_net (dev, networks[i]); - if (!(name = nmwa_dbus_get_object_name (applet, networks[i]))) - break; - - if (strlen (name)) + /* Only add the network if its not already in the device's network list. We + * don't want duplicates. + */ + if (!tmp_net) { - gboolean found = FALSE; - int j; - WirelessNetwork *net = NULL; + WirelessNetwork *net; - /* 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 = wireless_network_new (); - /* FIXME: what if net == NULL? */ - net->nm_name = g_strdup (networks[i]); - net->essid = g_strdup (name); - net->active = active_network ? (strcmp (net->nm_name, active_network) == 0) : FALSE; - net->encrypted = nmwa_dbus_get_network_encrypted (applet, net->nm_name); - net->strength = nmwa_dbus_get_object_strength (applet, net->nm_name); - - dev->networks = g_slist_append (dev->networks, net); + if ((net = nmwa_dbus_get_one_wireless_network (applet, dev, networks[i], active_network))) + { + network_device_add_wireless_network (dev, net); + wireless_network_unref (net); + } } - dbus_free (name); } out: - dbus_free (active_network); - dbus_free_string_array (networks); + g_free (active_network); + g_strfreev (networks); +} + + + +void nmwa_free_gui_data_model (NMWirelessApplet *applet) +{ + g_return_if_fail (applet != NULL); + + if (applet->gui_device_list) + { + g_slist_foreach (applet->gui_device_list, (GFunc) network_device_unref, NULL); + g_slist_free (applet->gui_device_list); + applet->gui_device_list = NULL; + } + if (applet->gui_active_device) + { + network_device_unref (applet->gui_active_device); + applet->gui_active_device = NULL; + } + if (applet->gui_nm_status) + { + g_free (applet->gui_nm_status); + applet->gui_nm_status = NULL; + } +} + + +void nmwa_free_dbus_data_model (NMWirelessApplet *applet) +{ + g_return_if_fail (applet != NULL); + + if (applet->dbus_device_list) + { + g_slist_foreach (applet->dbus_device_list, (GFunc) network_device_unref, NULL); + g_slist_free (applet->dbus_device_list); + applet->dbus_device_list = NULL; + } + if (applet->dbus_active_device) + { + network_device_unref (applet->dbus_active_device); + applet->dbus_active_device = NULL; + } + if (applet->dbus_nm_status) + { + g_free (applet->dbus_nm_status); + applet->dbus_nm_status = NULL; + } +} + + +/* + * nmwa_copy_data_model + * + * Copy the dbus data model over to the gui data model + * + */ +void nmwa_copy_data_model (NMWirelessApplet *applet) +{ + GSList *elt; + NetworkDevice *act_dev = NULL; + + g_return_if_fail (applet != NULL); + + /* Free the existing GUI data model. */ + nmwa_free_gui_data_model (applet); + + /* Deep-copy network devices to GUI data model */ + for (elt = applet->dbus_device_list; elt; elt = g_slist_next (elt)) + { + NetworkDevice *src = (NetworkDevice *)(elt->data); + NetworkDevice *dst = network_device_copy (src); + + if (dst) + { + /* Transfer ownership of device to list, don't need to unref it */ + applet->gui_device_list = g_slist_append (applet->gui_device_list, dst); + + /* Make sure we get the right active device for the gui data model */ + if (applet->dbus_active_device == src) + { + network_device_ref (dst); + act_dev = dst; + } + } + } + + /* active_device is just a pointer into the device list, no need to deep-copy it */ + applet->gui_active_device = act_dev; + applet->gui_nm_status = g_strdup (applet->dbus_nm_status); +} + + +/* + * nmwa_dbus_device_update_one_network + * + * Update one wireless network + * + */ +static void nmwa_dbus_device_update_one_network (NMWirelessApplet *applet, DBusMessage *message) +{ + char *dev_path = NULL; + char *net_path = NULL; + NMNetworkStatus status; + guint8 strength = -1; + DBusError error; + gboolean success = TRUE; + + g_return_if_fail (applet != NULL); + g_return_if_fail (message != NULL); + + dbus_error_init (&error); + /* Try first time with strength, which is only passed for NETWORK_STATUS_STRENGTH_CHANGED */ + if (!dbus_message_get_args (message, &error, + DBUS_TYPE_STRING, &dev_path, + DBUS_TYPE_STRING, &net_path, + DBUS_TYPE_UINT32, &status, + DBUS_TYPE_INT32, &strength, + DBUS_TYPE_INVALID)) + { + if (dbus_error_is_set (&error)) + dbus_error_free (&error); + dbus_error_init (&error); + + /* Try without strength */ + if (!dbus_message_get_args (message, &error, + DBUS_TYPE_STRING, &dev_path, + DBUS_TYPE_STRING, &net_path, + DBUS_TYPE_UINT32, &status, + DBUS_TYPE_INVALID)) + { + if (dbus_error_is_set (&error)) + dbus_error_free (&error); + success = FALSE; + } + /* If the signal is NETWORK_STATUS_STRENGTH_CHANGED but we didn't get passed + * a strength in the arguments, we can't use the signal. + */ + if (status == NETWORK_STATUS_STRENGTH_CHANGED) + success = FALSE; + } + + if (success) + { + NetworkDevice *dev = nmwa_get_device_for_nm_device (applet->dbus_device_list, dev_path); + WirelessNetwork *net = dev ? nmwa_get_net_for_nm_net (dev, net_path) : NULL; + gboolean changed = FALSE; + + switch (status) + { + case NETWORK_STATUS_DISAPPEARED: + if (!dev || !net) + break; + network_device_remove_wireless_network (dev, net); + changed = TRUE; + break; + + case NETWORK_STATUS_APPEARED: + if (!dev) + break; + /* Add it if it doesn't already exist in the device's network list */ + if (!net) + { + WirelessNetwork *tmp_net; + char *active_network = NULL; + + if (dev == applet->dbus_active_device) + active_network = nmwa_dbus_get_active_network (applet, dev->nm_device, APPLET_STATE_IGNORE); + if (applet->applet_state == APPLET_STATE_NO_NM) + break; + + if ((tmp_net = nmwa_dbus_get_one_wireless_network (applet, dev, net_path, active_network))) + { + network_device_add_wireless_network (dev, tmp_net); + wireless_network_unref (tmp_net); + changed = TRUE; + } + g_free (active_network); + } + break; + + case NETWORK_STATUS_STRENGTH_CHANGED: + g_return_if_fail (net != NULL); + net->strength = strength; + changed = TRUE; + break; + + default: + break; + } + + if (changed) + { + /* Now move the data over to the GUI side */ + g_mutex_lock (applet->data_mutex); + nmwa_copy_data_model (applet); + g_mutex_unlock (applet->data_mutex); + } + } } @@ -1045,13 +1301,65 @@ static gboolean nmwa_dbus_update_active_device_strength (gpointer user_data) g_return_val_if_fail (user_data != NULL, FALSE); applet = (NMWirelessApplet *)user_data; - if (applet->dbus_active_device && (applet->active_device->type == DEVICE_TYPE_WIRELESS_ETHERNET)) - applet->dbus_active_device->strength = nmwa_dbus_get_object_strength (applet, applet->dbus_active_device->nm_device); + if (applet->gui_active_device && (applet->gui_active_device->type == DEVICE_TYPE_WIRELESS_ETHERNET)) + { + guint8 strength = nmwa_dbus_get_object_strength (applet, applet->gui_active_device->nm_device); + + applet->gui_active_device->strength = strength; + if (applet->gui_active_device == applet->dbus_active_device) + applet->dbus_active_device->strength = strength; + } return (TRUE); } +/* + * sort_devices_function + * + * Sort the devices for display... Wired devices at the top. + * + */ +static int +sort_devices_function (gconstpointer a, gconstpointer b) +{ + NetworkDevice *dev_a = (NetworkDevice *) a; + NetworkDevice *dev_b = (NetworkDevice *) b; + char *name_a; + char *name_b; + + if (dev_a->hal_name) + name_a = dev_a->hal_name; + else if (dev_a->nm_name) + name_a = dev_a->nm_name; + else + name_a = ""; + + if (dev_b->hal_name) + name_b = dev_b->hal_name; + else if (dev_b->nm_name) + name_b = dev_b->nm_name; + else + name_b = ""; + + if (dev_a->type == dev_b->type) + { + return strcmp (name_a, name_b); + } + if (dev_a->type == DEVICE_TYPE_WIRED_ETHERNET) + return -1; + if (dev_b->type == DEVICE_TYPE_WIRED_ETHERNET) + return 1; + if (dev_a->type == DEVICE_TYPE_WIRELESS_ETHERNET) + return -1; + if (dev_b->type == DEVICE_TYPE_WIRELESS_ETHERNET) + return 1; + + /* Unknown device types. Sort by name only at this point. */ + return strcmp (name_a, name_b); +} + + /* * nmwa_dbus_update_devices * @@ -1063,10 +1371,9 @@ static void nmwa_dbus_update_devices (NMWirelessApplet *applet) char **devices = NULL; int num_items = 0; int i; - char *nm_act_dev = NULL; - GSList *device_list = NULL; - char *nm_status = NULL; gboolean adhoc = FALSE; + char *nm_act_dev; + char *nm_status; g_return_if_fail (applet->data_mutex != NULL); @@ -1084,11 +1391,13 @@ static void nmwa_dbus_update_devices (NMWirelessApplet *applet) } if (!devices) + { + dbus_free (nm_status); return; + } - if (applet->dbus_active_device) - network_device_unref (applet->dbus_active_device); - applet->dbus_active_device = NULL; + nmwa_free_dbus_data_model (applet); + applet->dbus_nm_status = nm_status; nm_act_dev = nmwa_dbus_get_active_device (applet, APPLET_STATE_IGNORE); @@ -1116,45 +1425,32 @@ static void nmwa_dbus_update_devices (NMWirelessApplet *applet) network_device_unref (dev); else { - device_list = g_slist_append (device_list, dev); - if (nm_act_dev && !strcmp (nm_act_dev, devices[i])) + applet->dbus_device_list = g_slist_append (applet->dbus_device_list, dev); + if (nm_act_dev && (strcmp (nm_act_dev, devices[i]) == 0)) { + /* ref the current active device */ network_device_ref (dev); applet->dbus_active_device = dev; - network_device_ref (dev); if (dev->type == DEVICE_TYPE_WIRELESS_ETHERNET) - { adhoc = (nmwa_dbus_get_object_mode (applet, nm_act_dev) == NETWORK_MODE_ADHOC); - nmwa_dbus_update_device_wireless_networks (dev, TRUE, applet); - } } - else - nmwa_dbus_update_device_wireless_networks (dev, FALSE, applet); + nmwa_dbus_device_update_all_networks (dev, applet); } } } dbus_free (name); } - dbus_free (nm_act_dev); - dbus_free_string_array (devices); + g_free (nm_act_dev); + g_strfreev (devices); - /* Now move the data over to the GUI side */ + /* Sort the devices for display */ + applet->dbus_device_list = g_slist_sort (applet->dbus_device_list, sort_devices_function); + + /* Now copy the data over to the GUI side */ g_mutex_lock (applet->data_mutex); - if (applet->device_list) - { - g_slist_foreach (applet->device_list, (GFunc) network_device_unref, NULL); - g_slist_free (applet->device_list); - } - if (applet->active_device) - network_device_unref (applet->active_device); - if (applet->nm_status) - g_free (applet->nm_status); - applet->device_list = device_list; - applet->active_device = applet->dbus_active_device; - applet->nm_status = nm_status; + nmwa_copy_data_model (applet); applet->is_adhoc = adhoc; - applet->scanning_enabled = nmwa_dbus_get_scanning_enabled (applet); applet->wireless_enabled = nmwa_dbus_get_wireless_enabled (applet); @@ -1236,11 +1532,8 @@ static DBusHandlerResult nmwa_dbus_filter (DBusConnection *connection, DBusMessa #else #error "Unrecognized version of DBUS." #endif - else if ( dbus_message_is_signal (message, NM_DBUS_INTERFACE, "WirelessNetworkAppeared") - || dbus_message_is_signal (message, NM_DBUS_INTERFACE, "WirelessNetworkDisappeared")) - { - nmwa_dbus_update_devices (applet); - } + else if (dbus_message_is_signal (message, NM_DBUS_INTERFACE, "WirelessNetworkUpdate")) + nmwa_dbus_device_update_one_network (applet, message); 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") @@ -1368,7 +1661,6 @@ static gboolean nmwa_dbus_timeout_worker (gpointer user_data) gpointer nmwa_dbus_worker (gpointer user_data) { NMWirelessApplet *applet = (NMWirelessApplet *)user_data; - GMainLoop *thread_loop; guint timeout_id; GSource *timeout_source; guint strength_id; @@ -1380,7 +1672,7 @@ gpointer nmwa_dbus_worker (gpointer user_data) if (!(applet->thread_context = g_main_context_new ())) return (NULL); - if (!(thread_loop = g_main_loop_new (applet->thread_context, FALSE))) + if (!(applet->thread_loop = g_main_loop_new (applet->thread_context, FALSE))) return (NULL); applet->connection = nmwa_dbus_init (applet, applet->thread_context); @@ -1401,7 +1693,7 @@ gpointer nmwa_dbus_worker (gpointer user_data) else applet->applet_state = APPLET_STATE_NO_NM; - g_main_loop_run (thread_loop); + g_main_loop_run (applet->thread_loop); g_source_destroy (timeout_source); g_source_destroy (strength_source); diff --git a/panel-applet/NMWirelessAppletDbus.h b/panel-applet/NMWirelessAppletDbus.h index dc29c2f027..14a90386c1 100644 --- a/panel-applet/NMWirelessAppletDbus.h +++ b/panel-applet/NMWirelessAppletDbus.h @@ -56,4 +56,8 @@ void wireless_network_unref (WirelessNetwork *net); void network_device_ref (NetworkDevice *dev); void network_device_unref (NetworkDevice *dev); +void nmwa_free_gui_data_model (NMWirelessApplet *applet); +void nmwa_free_dbus_data_model (NMWirelessApplet *applet); + + #endif diff --git a/panel-applet/NMWirelessAppletOtherNetworkDialog.c b/panel-applet/NMWirelessAppletOtherNetworkDialog.c index 532a5d0318..a6ebea9ed9 100644 --- a/panel-applet/NMWirelessAppletOtherNetworkDialog.c +++ b/panel-applet/NMWirelessAppletOtherNetworkDialog.c @@ -104,7 +104,8 @@ static GtkTreeModel *create_wireless_adapter_model (NMWirelessApplet *applet) GSList *element; retval = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_POINTER); - for (element = applet->device_list; element; element = element->next) + /* We should have already locked applet->data_mutex */ + for (element = applet->gui_device_list; element; element = element->next) { NetworkDevice *network = (NetworkDevice *)(element->data); @@ -238,7 +239,7 @@ static GtkDialog *nmwa_other_network_dialog_init (GladeXML *xml, NMWirelessApple /* Do we have multiple Network cards? */ g_mutex_lock (applet->data_mutex); - for (element = applet->device_list; element; element = element->next) + for (element = applet->gui_device_list; element; element = element->next) { NetworkDevice *dev = (NetworkDevice *)(element->data); diff --git a/src/NetworkManagerAPList.c b/src/NetworkManagerAPList.c index 1ca6f3e34e..f641eed6af 100644 --- a/src/NetworkManagerAPList.c +++ b/src/NetworkManagerAPList.c @@ -377,32 +377,53 @@ void nm_ap_list_populate_from_nmi (NMAccessPointList *list, NMData *data) * TRUE if the ap was completely new * */ -gboolean nm_ap_list_merge_scanned_ap (NMAccessPointList *list, NMAccessPoint *merge_ap) +gboolean nm_ap_list_merge_scanned_ap (NMAccessPointList *list, NMAccessPoint *merge_ap, + gboolean *new, gboolean *strength_changed) { NMAccessPoint *list_ap; - gboolean new = FALSE; + gboolean success = FALSE; + g_return_val_if_fail (list != NULL, FALSE); g_return_val_if_fail (merge_ap != NULL, FALSE); + g_return_val_if_fail (new != NULL, FALSE); + g_return_val_if_fail (strength_changed != NULL, FALSE); if (!(list_ap = nm_ap_list_get_ap_by_address (list, nm_ap_get_address (merge_ap)))) list_ap = nm_ap_list_get_ap_by_essid (list, nm_ap_get_essid (merge_ap)); if (list_ap) { + const GTimeVal *merge_ap_seen = nm_ap_get_last_seen (merge_ap); + const GTimeVal *list_ap_seen = nm_ap_get_last_seen (list_ap); + /* Merge some properties on the AP that are new from scan to scan. */ nm_ap_set_encrypted (list_ap, nm_ap_get_encrypted (merge_ap)); nm_ap_set_auth_method (list_ap, nm_ap_get_auth_method (merge_ap)); - nm_ap_set_last_seen (list_ap, nm_ap_get_last_seen (merge_ap)); - nm_ap_set_strength (list_ap, nm_ap_get_strength (merge_ap)); + + /* Don't update the strength on the existing AP if the timestamp is + * the same as the AP we're going to merge (which means that they were + * found in the same scan, have the same ESSID, but are different APs) + * and the existing AP's strength is greater than the one we're about + * to merge. This helps keep the ESSID's reported strength that of the + * strongest AP we can see. + */ + if (!( (list_ap_seen->tv_sec == merge_ap_seen->tv_sec) + && (nm_ap_get_strength (list_ap) > nm_ap_get_strength (merge_ap)))) + { + nm_ap_set_strength (list_ap, nm_ap_get_strength (merge_ap)); + *strength_changed = TRUE; + } + + nm_ap_set_last_seen (list_ap, merge_ap_seen); } else { /* Add the whole AP, list takes ownership. */ nm_ap_list_append_ap (list, merge_ap); - new = TRUE; + *new = TRUE; } - return new; + return TRUE; } @@ -450,6 +471,29 @@ void nm_ap_list_copy_properties (NMAccessPointList *dest, NMAccessPointList *sou } +/* + * nm_ap_list_copy_one_essid_by_address + * + * If the access point doesn't have an ESSID, search through a list of access points + * and find one (if any) that has the MAC address of the access point we're looking for. + * If one is found, copy the essid over to the original access point. + * + */ +void nm_ap_list_copy_one_essid_by_address (NMAccessPoint *ap, NMAccessPointList *search_list) +{ + NMAccessPoint *found_ap; + + if (!ap || !search_list) + return; + + if (!nm_ap_get_essid (ap) && (found_ap = nm_ap_list_get_ap_by_address (search_list, nm_ap_get_address (ap)))) + { + if (nm_ap_get_essid (found_ap)) + nm_ap_set_essid (ap, nm_ap_get_essid (found_ap)); + } +} + + /* * nm_ap_list_copy_essids_by_address * @@ -469,15 +513,8 @@ void nm_ap_list_copy_essids_by_address (NMAccessPointList *dest, NMAccessPointLi if ((iter = nm_ap_list_iter_new (dest))) { while ((dest_ap = nm_ap_list_iter_next (iter))) - { - NMAccessPoint *src_ap = NULL; + nm_ap_list_copy_one_essid_by_address (dest_ap, source); - if (!nm_ap_get_essid (dest_ap) && (src_ap = nm_ap_list_get_ap_by_address (source, nm_ap_get_address (dest_ap)))) - { - if (nm_ap_get_essid (src_ap)) - nm_ap_set_essid (dest_ap, nm_ap_get_essid (src_ap)); - } - } nm_ap_list_iter_free (iter); } } @@ -523,7 +560,7 @@ void nm_ap_list_diff (NMData *data, NMDevice *dev, NMAccessPointList *old, NMAcc nm_ap_set_matched (new_ap, TRUE); } else - nm_dbus_signal_wireless_network_change (data->dbus_connection, dev, old_ap, TRUE); + nm_dbus_signal_wireless_network_change (data->dbus_connection, dev, old_ap, NETWORK_STATUS_DISAPPEARED, -1); } } nm_ap_list_iter_free (iter); @@ -537,7 +574,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_ap_get_essid (new_ap)) - nm_dbus_signal_wireless_network_change (data->dbus_connection, dev, new_ap, FALSE); + nm_dbus_signal_wireless_network_change (data->dbus_connection, dev, new_ap, NETWORK_STATUS_APPEARED, -1); } nm_ap_list_iter_free (iter); } diff --git a/src/NetworkManagerAPList.h b/src/NetworkManagerAPList.h index e8de7b7e62..2a8add99c8 100644 --- a/src/NetworkManagerAPList.h +++ b/src/NetworkManagerAPList.h @@ -48,9 +48,10 @@ void nm_ap_list_populate_from_nmi (NMAccessPointList *list, NMData *data); void nm_ap_list_copy_properties (NMAccessPointList *dest, NMAccessPointList *source); void nm_ap_list_copy_essids_by_address (NMAccessPointList *dest, NMAccessPointList *source); +void nm_ap_list_copy_one_essid_by_address (NMAccessPoint *ap, NMAccessPointList *search_list); void nm_ap_list_diff (NMData *data, NMDevice *dev, NMAccessPointList *old, NMAccessPointList *new); -gboolean nm_ap_list_merge_scanned_ap (NMAccessPointList *list, NMAccessPoint *merge_ap); +gboolean nm_ap_list_merge_scanned_ap (NMAccessPointList *list, NMAccessPoint *merge_ap, gboolean *new, gboolean *strength_changed); gboolean nm_ap_list_lock (NMAccessPointList *list); void nm_ap_list_unlock (NMAccessPointList *list); diff --git a/src/NetworkManagerDbus.c b/src/NetworkManagerDbus.c index 2f883529d5..639086437c 100644 --- a/src/NetworkManagerDbus.c +++ b/src/NetworkManagerDbus.c @@ -417,11 +417,12 @@ void nm_dbus_signal_device_ip4_address_change (DBusConnection *connection, NMDev * Notifies the bus that a new wireless network has come into range * */ -void nm_dbus_signal_wireless_network_change (DBusConnection *connection, NMDevice *dev, NMAccessPoint *ap, gboolean gone) +void nm_dbus_signal_wireless_network_change (DBusConnection *connection, NMDevice *dev, NMAccessPoint *ap, NMNetworkStatus status, gint8 strength) { DBusMessage *message; char *dev_path; char *ap_path; + const char *signal; g_return_if_fail (connection != NULL); g_return_if_fail (dev != NULL); @@ -436,8 +437,7 @@ void nm_dbus_signal_wireless_network_change (DBusConnection *connection, NMDevic return; } - message = dbus_message_new_signal (NM_DBUS_PATH, NM_DBUS_INTERFACE, - (gone ? "WirelessNetworkDisappeared" : "WirelessNetworkAppeared")); + message = dbus_message_new_signal (NM_DBUS_PATH, NM_DBUS_INTERFACE, "WirelessNetworkUpdate"); if (!message) { syslog (LOG_ERR, "nm_dbus_signal_wireless_network_appeared(): Not enough memory for new dbus message!"); @@ -449,10 +449,15 @@ void nm_dbus_signal_wireless_network_change (DBusConnection *connection, NMDevic dbus_message_append_args (message, DBUS_TYPE_STRING, dev_path, DBUS_TYPE_STRING, ap_path, + DBUS_TYPE_UINT32, status, DBUS_TYPE_INVALID); g_free (ap_path); g_free (dev_path); + /* Append signal-specific data */ + if (status == NETWORK_STATUS_STRENGTH_CHANGED) + dbus_message_append_args (message, DBUS_TYPE_INT32, strength, DBUS_TYPE_INVALID); + if (!dbus_connection_send (connection, message, NULL)) syslog (LOG_WARNING, "nnm_dbus_signal_wireless_network_appeared(): Could not raise the WirelessNetworkAppeared signal!"); @@ -768,19 +773,20 @@ char ** nm_dbus_get_networks (DBusConnection *connection, NMNetworkType type, in /* Send message and get essid back from NetworkManagerInfo */ 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)) syslog (LOG_ERR, "nm_dbus_get_networks(): %s raised %s", error.name, error.message); else if (!reply) syslog (LOG_NOTICE, "nm_dbus_get_networks(): reply was NULL."); else { - DBusMessageIter iter; - - dbus_message_iter_init (reply, &iter); - dbus_message_iter_get_string_array (&iter, &networks, num_networks); + dbus_error_init (&error); + dbus_message_get_args (reply, &error, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, + &networks, num_networks, DBUS_TYPE_INVALID); + if (dbus_error_is_set (&error)) + dbus_error_free (&error); } - dbus_message_unref (message); if (reply) dbus_message_unref (reply); diff --git a/src/NetworkManagerDbus.h b/src/NetworkManagerDbus.h index c30fb9aa80..9d7805b569 100644 --- a/src/NetworkManagerDbus.h +++ b/src/NetworkManagerDbus.h @@ -54,7 +54,7 @@ void nm_dbus_signal_network_status_change (DBusConnection *connection, NMData void nm_dbus_signal_device_ip4_address_change(DBusConnection *connection, NMDevice *dev); -void nm_dbus_signal_wireless_network_change (DBusConnection *connection, NMDevice *dev, NMAccessPoint *ap, gboolean gone); +void nm_dbus_signal_wireless_network_change (DBusConnection *connection, NMDevice *dev, NMAccessPoint *ap, NMNetworkStatus status, gint8 strength); void nm_dbus_get_user_key_for_network (DBusConnection *connection, NMDevice *dev, NMAccessPoint *ap, int attempt); diff --git a/src/NetworkManagerDevice.c b/src/NetworkManagerDevice.c index 27d6341af4..b3d6f2576d 100644 --- a/src/NetworkManagerDevice.c +++ b/src/NetworkManagerDevice.c @@ -3264,6 +3264,8 @@ static gboolean nm_device_wireless_process_scan_results (gpointer user_data) return FALSE; } + g_get_current_time (&cur_time); + /* Translate iwlib scan results to NM access point list */ for (tmp_ap = results->scan_head.result; tmp_ap; tmp_ap = tmp_ap->next) { @@ -3272,6 +3274,9 @@ static gboolean nm_device_wireless_process_scan_results (gpointer user_data) { NMAccessPoint *nm_ap = nm_ap_new (); int percent; + gboolean new = FALSE; + gboolean strength_changed = FALSE; + gboolean success = FALSE; /* Copy over info from scan to local structure */ @@ -3280,11 +3285,8 @@ static gboolean nm_device_wireless_process_scan_results (gpointer user_data) */ if ( !tmp_ap->b.has_essid || (tmp_ap->b.essid && !strlen (tmp_ap->b.essid)) - || (tmp_ap->b.essid && !strcmp (tmp_ap->b.essid, ""))) - { + || (tmp_ap->b.essid && !strcmp (tmp_ap->b.essid, ""))) /* Stupid ipw drivers use */ nm_ap_set_essid (nm_ap, NULL); - have_blank_essids = TRUE; - } else nm_ap_set_essid (nm_ap, tmp_ap->b.essid); @@ -3330,29 +3332,41 @@ static gboolean nm_device_wireless_process_scan_results (gpointer user_data) if (tmp_ap->b.has_freq) nm_ap_set_freq (nm_ap, tmp_ap->b.freq); - g_get_current_time (&cur_time); nm_ap_set_last_seen (nm_ap, &cur_time); + /* If the AP is not broadcasting its ESSID, try to fill it in here from our + * allowed list where we cache known MAC->ESSID associations. + */ + if (!nm_ap_get_essid (nm_ap)) + nm_ap_list_copy_one_essid_by_address (nm_ap, dev->app_data->allowed_ap_list); + /* Add the AP to the device's AP list */ - if (nm_ap_list_merge_scanned_ap (nm_device_ap_list_get (dev), nm_ap)) + success = nm_ap_list_merge_scanned_ap (nm_device_ap_list_get (dev), nm_ap, &new, &strength_changed); + if (success) { - nm_dbus_signal_wireless_network_change (dev->app_data->dbus_connection, dev, nm_ap, FALSE); - list_changed = TRUE; + /* Handle dbus signals that we need to broadcast when the AP is added to the list or changes + * strength. + */ + if (new) + { + nm_dbus_signal_wireless_network_change (dev->app_data->dbus_connection, dev, nm_ap, + NETWORK_STATUS_APPEARED, -1); + list_changed = TRUE; + } + else if (strength_changed) + { + nm_dbus_signal_wireless_network_change (dev->app_data->dbus_connection, dev, nm_ap, + NETWORK_STATUS_STRENGTH_CHANGED, nm_ap_get_strength (nm_ap)); + } } nm_ap_unref (nm_ap); } } - /* If we detected any blank-ESSID access points (ie don't broadcast their ESSID), then try to - * merge in ESSIDs that we have addresses for from user preferences/NetworkManagerInfo. - */ - if (have_blank_essids) - nm_ap_list_copy_essids_by_address (nm_device_ap_list_get (dev), dev->app_data->allowed_ap_list); - /* Once we have the list, copy in any relevant information from our Allowed list. */ nm_ap_list_copy_properties (nm_device_ap_list_get (dev), dev->app_data->allowed_ap_list); - /* Walk the access point list and remove any access points older than 60s */ + /* Walk the access point list and remove any access points older than 120s */ g_get_current_time (&cur_time); if (nm_device_ap_list_get (dev) && (iter = nm_ap_list_iter_new (nm_device_ap_list_get (dev)))) { @@ -3366,18 +3380,12 @@ static gboolean nm_device_wireless_process_scan_results (gpointer user_data) const GTimeVal *ap_time = nm_ap_get_last_seen (outdated_ap); gboolean keep_around = FALSE; - /* We don't add "artifical" APs to the outdated list if it is the - * one the card is currently associated with. - * Some Cisco cards don't report non-ESSID-broadcasting access points - * in their scans even though the card associates with that AP just fine. - */ + /* Don't ever get prune the AP we're currently associated with */ if ( nm_ap_get_essid (outdated_ap) - && (best_ap && (nm_null_safe_strcmp (nm_ap_get_essid (best_ap), nm_ap_get_essid (outdated_ap))) == 0) - && nm_ap_get_artificial (outdated_ap)) + && (best_ap && (nm_null_safe_strcmp (nm_ap_get_essid (best_ap), nm_ap_get_essid (outdated_ap))) == 0)) keep_around = TRUE; - /* Eh, we don't care about sub-second time resolution. */ - if ((ap_time->tv_sec + 120 < cur_time.tv_sec) && !keep_around) + if (!keep_around && (ap_time->tv_sec + 120 < cur_time.tv_sec)) outdated_list = g_slist_append (outdated_list, outdated_ap); } nm_ap_list_iter_free (iter); @@ -3393,7 +3401,7 @@ static gboolean nm_device_wireless_process_scan_results (gpointer user_data) { if ((outdated_ap = (NMAccessPoint *)(elt->data))) { - nm_dbus_signal_wireless_network_change (dev->app_data->dbus_connection, dev, outdated_ap, TRUE); + nm_dbus_signal_wireless_network_change (dev->app_data->dbus_connection, dev, outdated_ap, NETWORK_STATUS_DISAPPEARED, -1); nm_ap_list_remove_ap (nm_device_ap_list_get (dev), outdated_ap); list_changed = TRUE; }