summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2018-03-24 23:51:39 +0100
committerThomas Haller <thaller@redhat.com>2018-03-27 09:58:00 +0200
commitd7b1a911d913a2b6f5b26bcab01965e3a533081d (patch)
treea93583818f152ecc413ee6b562b9e6ead97512f7
parent9fafd26f68c551499d6da8f1621a2ff5354cae55 (diff)
downloadNetworkManager-d7b1a911d913a2b6f5b26bcab01965e3a533081d.tar.gz
wifi: rework tracking of wifi-aps to use CList
- no longer track APs in a hash table with their exported path as key. The exported path is already tracked by NMDBusManager's lookup index, so we can reuse that for fast lookup by path. Otherwise, track the APs in a CList per device. - as we now track APs in a CList, their order is well defined. We no longer need to sort APs and obsoletes nm_wifi_aps_get_sorted() and simplifies nm_wifi_aps_find_first_compatible().
-rw-r--r--src/devices/wifi/nm-device-iwd.c178
-rw-r--r--src/devices/wifi/nm-device-iwd.h2
-rw-r--r--src/devices/wifi/nm-device-wifi.c110
-rw-r--r--src/devices/wifi/nm-device-wifi.h2
-rw-r--r--src/devices/wifi/nm-wifi-ap.c155
-rw-r--r--src/devices/wifi/nm-wifi-ap.h25
-rw-r--r--src/devices/wifi/nm-wifi-common.c31
-rw-r--r--src/devices/wifi/nm-wifi-common.h5
8 files changed, 219 insertions, 289 deletions
diff --git a/src/devices/wifi/nm-device-iwd.c b/src/devices/wifi/nm-device-iwd.c
index 40980b06f0..eeff5bd32d 100644
--- a/src/devices/wifi/nm-device-iwd.c
+++ b/src/devices/wifi/nm-device-iwd.c
@@ -40,6 +40,7 @@
#include "nm-core-internal.h"
#include "nm-config.h"
#include "nm-iwd-manager.h"
+#include "nm-dbus-manager.h"
#include "devices/nm-device-logging.h"
_LOG_DECLARE_SELF(NMDeviceIwd);
@@ -66,8 +67,7 @@ static guint signals[LAST_SIGNAL] = { 0 };
typedef struct {
GDBusObject * dbus_obj;
GDBusProxy * dbus_proxy;
- GHashTable * aps;
- GHashTable * new_aps;
+ CList aps_lst_head;
NMWifiAP * current_ap;
GCancellable * cancellable;
NMDeviceWifiCapabilities capabilities;
@@ -104,6 +104,8 @@ G_DEFINE_TYPE (NMDeviceIwd, nm_device_iwd, NM_TYPE_DEVICE)
static void schedule_periodic_scan (NMDeviceIwd *self,
NMDeviceState current_state);
+/*****************************************************************************/
+
static void
_ap_dump (NMDeviceIwd *self,
NMLogLevel log_level,
@@ -119,20 +121,6 @@ _ap_dump (NMDeviceIwd *self,
nm_wifi_ap_to_string (ap, buf, sizeof (buf), now_s));
}
-static void
-_emit_access_point_added_removed (NMDeviceIwd *self,
- NMWifiAP *ap,
- gboolean is_added /* or else is removed */)
-{
- nm_dbus_object_emit_signal (NM_DBUS_OBJECT (self),
- &nm_interface_info_device_wireless,
- is_added
- ? &nm_signal_info_wireless_access_point_added
- : &nm_signal_info_wireless_access_point_removed,
- "(o)",
- nm_dbus_object_get_path (NM_DBUS_OBJECT (ap)));
-}
-
/* Callers ensure we're not removing current_ap */
static void
ap_add_remove (NMDeviceIwd *self,
@@ -143,23 +131,25 @@ ap_add_remove (NMDeviceIwd *self,
NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self);
if (is_adding) {
- g_hash_table_insert (priv->aps,
- (gpointer) nm_dbus_object_export (NM_DBUS_OBJECT (ap)),
- g_object_ref (ap));
+ g_object_ref (ap);
+ ap->wifi_device = NM_DEVICE (self);
+ c_list_link_tail (&priv->aps_lst_head, &ap->aps_lst);
+ nm_dbus_object_export (NM_DBUS_OBJECT (ap));
_ap_dump (self, LOGL_DEBUG, ap, "added", 0);
- } else
+ nm_device_wifi_emit_signal_access_point (NM_DEVICE (self), ap, TRUE);
+ } else {
+ ap->wifi_device = NULL;
+ c_list_unlink (&ap->aps_lst);
_ap_dump (self, LOGL_DEBUG, ap, "removed", 0);
+ }
- _emit_access_point_added_removed (self, ap, is_adding);
+ _notify (self, PROP_ACCESS_POINTS);
if (!is_adding) {
- g_hash_table_remove (priv->aps, nm_dbus_object_get_path (NM_DBUS_OBJECT (ap)));
- nm_dbus_object_unexport (NM_DBUS_OBJECT (ap));
- g_object_unref (ap);
+ nm_device_wifi_emit_signal_access_point (NM_DEVICE (self), ap, FALSE);
+ nm_dbus_object_clear_and_unexport (&ap);
}
- _notify (self, PROP_ACCESS_POINTS);
-
nm_device_emit_recheck_auto_activate (NM_DEVICE (self));
if (recheck_available_connections)
nm_device_recheck_available_connections (NM_DEVICE (self));
@@ -194,59 +184,20 @@ set_current_ap (NMDeviceIwd *self, NMWifiAP *new_ap, gboolean recheck_available_
_notify (self, PROP_MODE);
}
-static gboolean
-update_ap_func (gpointer key, gpointer value, gpointer user_data)
-{
- NMWifiAP *ap = value;
- NMDeviceIwd *self = user_data;
- NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self);
- NMWifiAP *new_ap = NULL;
-
- if (priv->new_aps)
- new_ap = g_hash_table_lookup (priv->new_aps,
- nm_wifi_ap_get_supplicant_path (ap));
-
- if (new_ap) {
- g_hash_table_steal (priv->new_aps,
- nm_wifi_ap_get_supplicant_path (ap));
-
- if (nm_wifi_ap_set_strength (ap, nm_wifi_ap_get_strength (new_ap)))
- _ap_dump (self, LOGL_TRACE, ap, "updated", 0);
-
- g_object_unref (new_ap);
- return FALSE;
- }
-
- if (ap == priv->current_ap)
- /* Normally IWD will prevent the current AP from being
- * removed from the list and set a low signal strength,
- * but just making sure.
- */
- return FALSE;
-
- _ap_dump (self, LOGL_DEBUG, ap, "removed", 0);
-
- _emit_access_point_added_removed (self, ap, FALSE);
-
- nm_dbus_object_unexport (NM_DBUS_OBJECT (ap));
- g_object_unref (ap);
-
- return TRUE;
-}
-
static void
remove_all_aps (NMDeviceIwd *self)
{
NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self);
+ NMWifiAP *ap, *ap_safe;
- if (!g_hash_table_size (priv->aps))
+ if (c_list_is_empty (&priv->aps_lst_head))
return;
set_current_ap (self, NULL, FALSE);
- g_hash_table_foreach_remove (priv->aps, update_ap_func, self);
+ c_list_for_each_entry_safe (ap, ap_safe, &priv->aps_lst_head, aps_lst)
+ ap_add_remove (self, FALSE, ap, FALSE);
- _notify (self, PROP_ACCESS_POINTS);
nm_device_emit_recheck_auto_activate (NM_DEVICE (self));
nm_device_recheck_available_connections (NM_DEVICE (self));
}
@@ -285,9 +236,10 @@ get_ordered_networks_cb (GObject *source, GAsyncResult *res, gpointer user_data)
GVariantIter *networks;
const gchar *path, *name, *type;
int16_t signal;
- NMWifiAP *ap;
+ NMWifiAP *ap, *ap_safe;
gboolean changed = FALSE;
GHashTableIter ap_iter;
+ gs_unref_hashtable GHashTable *new_aps = NULL;
variant = _nm_dbus_proxy_call_finish (G_DBUS_PROXY (source), res,
G_VARIANT_TYPE ("(a(osns))"),
@@ -298,7 +250,7 @@ get_ordered_networks_cb (GObject *source, GAsyncResult *res, gpointer user_data)
return;
}
- priv->new_aps = g_hash_table_new (nm_str_hash, g_str_equal);
+ new_aps = g_hash_table_new_full (nm_str_hash, g_str_equal, NULL, g_object_unref);
g_variant_get (variant, "(a(osns))", &networks);
@@ -348,27 +300,47 @@ get_ordered_networks_cb (GObject *source, GAsyncResult *res, gpointer user_data)
nm_wifi_ap_set_strength (ap, nm_wifi_utils_level_to_quality (signal / 100));
nm_wifi_ap_set_freq (ap, 2417);
nm_wifi_ap_set_max_bitrate (ap, 65000);
- g_hash_table_insert (priv->new_aps,
+ g_hash_table_insert (new_aps,
(gpointer) nm_wifi_ap_get_supplicant_path (ap),
ap);
}
g_variant_iter_free (networks);
- if (g_hash_table_foreach_remove (priv->aps, update_ap_func, self))
+ c_list_for_each_entry_safe (ap, ap_safe, &priv->aps_lst_head, aps_lst) {
+
+ ap = g_hash_table_lookup (new_aps,
+ nm_wifi_ap_get_supplicant_path (ap));
+ if (ap) {
+ if (nm_wifi_ap_set_strength (ap, nm_wifi_ap_get_strength (ap))) {
+ _ap_dump (self, LOGL_TRACE, ap, "updated", 0);
+ changed = TRUE;
+ }
+ g_hash_table_remove (new_aps,
+ nm_wifi_ap_get_supplicant_path (ap));
+ continue;
+ }
+
+ if (ap == priv->current_ap) {
+ /* Normally IWD will prevent the current AP from being
+ * removed from the list and set a low signal strength,
+ * but just making sure.
+ */
+ continue;
+ }
+
+ ap_add_remove (self, FALSE, ap, FALSE);
changed = TRUE;
+ }
- g_hash_table_iter_init (&ap_iter, priv->new_aps);
+ g_hash_table_iter_init (&ap_iter, new_aps);
while (g_hash_table_iter_next (&ap_iter, NULL, (gpointer) &ap)) {
ap_add_remove (self, TRUE, ap, FALSE);
+ g_hash_table_iter_remove (&ap_iter);
changed = TRUE;
}
- g_hash_table_destroy (priv->new_aps);
- priv->new_aps = NULL;
-
if (changed) {
- _notify (self, PROP_ACCESS_POINTS);
nm_device_emit_recheck_auto_activate (NM_DEVICE (self));
nm_device_recheck_available_connections (NM_DEVICE (self));
}
@@ -585,13 +557,6 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
return TRUE;
}
-static NMWifiAP *
-get_ap_by_path (NMDeviceIwd *self, const char *path)
-{
- g_return_val_if_fail (path != NULL, NULL);
- return g_hash_table_lookup (NM_DEVICE_IWD_GET_PRIVATE (self)->aps, path);
-}
-
static gboolean
check_connection_available (NMDevice *device,
NMConnection *connection,
@@ -629,7 +594,7 @@ check_connection_available (NMDevice *device,
if (specific_object) {
NMWifiAP *ap;
- ap = get_ap_by_path (self, specific_object);
+ ap = nm_wifi_ap_lookup_for_device (NM_DEVICE (self), specific_object);
return ap ? nm_wifi_ap_check_compatible (ap, connection) : FALSE;
}
@@ -637,7 +602,7 @@ check_connection_available (NMDevice *device,
return TRUE;
/* Check at least one AP is compatible with this connection */
- return !!nm_wifi_aps_find_first_compatible (priv->aps, connection, TRUE);
+ return !!nm_wifi_aps_find_first_compatible (&priv->aps_lst_head, connection);
}
static gboolean
@@ -691,7 +656,7 @@ complete_connection (NMDevice *device,
}
/* Find a compatible AP in the scan list */
- ap = nm_wifi_aps_find_first_compatible (priv->aps, connection, FALSE);
+ ap = nm_wifi_aps_find_first_compatible (&priv->aps_lst_head, connection);
if (!ap) {
g_set_error_literal (error,
NM_DEVICE_ERROR,
@@ -700,7 +665,7 @@ complete_connection (NMDevice *device,
return FALSE;
}
} else {
- ap = get_ap_by_path (self, specific_object);
+ ap = nm_wifi_ap_lookup_for_device (NM_DEVICE (self), specific_object);
if (!ap) {
g_set_error (error,
NM_DEVICE_ERROR,
@@ -859,7 +824,7 @@ can_auto_connect (NMDevice *device,
return FALSE;
}
- ap = nm_wifi_aps_find_first_compatible (priv->aps, connection, FALSE);
+ ap = nm_wifi_aps_find_first_compatible (&priv->aps_lst_head, connection);
if (ap) {
/* All good; connection is usable */
NM_SET_OUT (specific_object, g_strdup (nm_dbus_object_get_path (NM_DBUS_OBJECT (ap))));
@@ -869,10 +834,10 @@ can_auto_connect (NMDevice *device,
return FALSE;
}
-GHashTable *
+const CList *
_nm_device_iwd_get_aps (NMDeviceIwd *self)
{
- return NM_DEVICE_IWD_GET_PRIVATE (self)->aps;
+ return &NM_DEVICE_IWD_GET_PRIVATE (self)->aps_lst_head;
}
static gboolean
@@ -1247,9 +1212,9 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason)
g_return_val_if_fail (s_wireless, NM_ACT_STAGE_RETURN_FAILURE);
ap_path = nm_active_connection_get_specific_object (NM_ACTIVE_CONNECTION (req));
- ap = ap_path ? get_ap_by_path (self, ap_path) : NULL;
+ ap = ap_path ? nm_wifi_ap_lookup_for_device (NM_DEVICE (self), ap_path) : NULL;
if (!ap) {
- ap = nm_wifi_aps_find_first_compatible (priv->aps, connection, FALSE);
+ ap = nm_wifi_aps_find_first_compatible (&priv->aps_lst_head, connection);
/* TODO: assuming hidden networks aren't supported do we need
* to consider the case of APs that are not in the scan list
@@ -1540,8 +1505,7 @@ get_property (GObject *object, guint prop_id,
{
NMDeviceIwd *self = NM_DEVICE_IWD (object);
NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self);
- gsize i;
- char **list;
+ const char **list;
switch (prop_id) {
case PROP_MODE:
@@ -1557,10 +1521,8 @@ get_property (GObject *object, guint prop_id,
g_value_set_uint (value, priv->capabilities);
break;
case PROP_ACCESS_POINTS:
- list = (char **) nm_wifi_aps_get_sorted_paths (priv->aps, TRUE);
- for (i = 0; list[i]; i++)
- list[i] = g_strdup (list[i]);
- g_value_take_boxed (value, list);
+ list = nm_wifi_aps_get_paths (&priv->aps_lst_head, TRUE);
+ g_value_take_boxed (value, nm_utils_strv_make_deep_copied (list));
break;
case PROP_ACTIVE_ACCESS_POINT:
nm_dbus_utils_g_value_set_object_path (value, priv->current_ap);
@@ -1830,7 +1792,7 @@ nm_device_iwd_init (NMDeviceIwd *self)
{
NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self);
- priv->aps = g_hash_table_new (nm_str_hash, g_str_equal);
+ c_list_init (&priv->aps_lst_head);
/* Make sure the manager is running */
(void) nm_iwd_manager_get ();
@@ -1867,19 +1829,8 @@ dispose (GObject *object)
remove_all_aps (self);
G_OBJECT_CLASS (nm_device_iwd_parent_class)->dispose (object);
-}
-
-static void
-finalize (GObject *object)
-{
- NMDeviceIwd *self = NM_DEVICE_IWD (object);
- NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self);
-
- nm_assert (g_hash_table_size (priv->aps) == 0);
-
- g_hash_table_unref (priv->aps);
- G_OBJECT_CLASS (nm_device_iwd_parent_class)->finalize (object);
+ nm_assert (c_list_is_empty (&priv->aps_lst_head));
}
static void
@@ -1894,7 +1845,6 @@ nm_device_iwd_class_init (NMDeviceIwdClass *klass)
object_class->get_property = get_property;
object_class->set_property = set_property;
object_class->dispose = dispose;
- object_class->finalize = finalize;
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&nm_interface_info_device_wireless);
diff --git a/src/devices/wifi/nm-device-iwd.h b/src/devices/wifi/nm-device-iwd.h
index 6d4ff06bfc..699ba1bb2b 100644
--- a/src/devices/wifi/nm-device-iwd.h
+++ b/src/devices/wifi/nm-device-iwd.h
@@ -53,7 +53,7 @@ void nm_device_iwd_set_dbus_object (NMDeviceIwd *device, GDBusObject *object);
gboolean nm_device_iwd_agent_psk_query (NMDeviceIwd *device,
GDBusMethodInvocation *invocation);
-GHashTable *_nm_device_iwd_get_aps (NMDeviceIwd *self);
+const CList *_nm_device_iwd_get_aps (NMDeviceIwd *self);
void _nm_device_iwd_request_scan (NMDeviceIwd *self,
GVariant *options,
diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c
index 7c64d594b7..de4af42cfc 100644
--- a/src/devices/wifi/nm-device-wifi.c
+++ b/src/devices/wifi/nm-device-wifi.c
@@ -32,6 +32,7 @@
#include "nm-common-macros.h"
#include "devices/nm-device.h"
#include "devices/nm-device-private.h"
+#include "nm-dbus-manager.h"
#include "nm-utils.h"
#include "NetworkManagerUtils.h"
#include "nm-act-request.h"
@@ -86,7 +87,8 @@ static guint signals[LAST_SIGNAL] = { 0 };
typedef struct {
gint8 invalid_strength_counter;
- GHashTable * aps;
+ CList aps_lst_head;
+
NMWifiAP * current_ap;
guint32 rate;
bool enabled:1; /* rfkilled or not */
@@ -344,30 +346,6 @@ supplicant_interface_release (NMDeviceWifi *self)
_notify_scanning (self);
}
-static NMWifiAP *
-get_ap_by_path (NMDeviceWifi *self, const char *path)
-{
- g_return_val_if_fail (path != NULL, NULL);
- return g_hash_table_lookup (NM_DEVICE_WIFI_GET_PRIVATE (self)->aps, path);
-
-}
-
-static NMWifiAP *
-get_ap_by_supplicant_path (NMDeviceWifi *self, const char *path)
-{
- GHashTableIter iter;
- NMWifiAP *ap;
-
- g_return_val_if_fail (path != NULL, NULL);
-
- g_hash_table_iter_init (&iter, NM_DEVICE_WIFI_GET_PRIVATE (self)->aps);
- while (g_hash_table_iter_next (&iter, NULL, (gpointer) &ap)) {
- if (g_strcmp0 (path, nm_wifi_ap_get_supplicant_path (ap)) == 0)
- return ap;
- }
- return NULL;
-}
-
static void
update_seen_bssids_cache (NMDeviceWifi *self, NMWifiAP *ap)
{
@@ -488,28 +466,25 @@ ap_add_remove (NMDeviceWifi *self,
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
if (is_adding) {
- g_hash_table_insert (priv->aps,
- (gpointer) nm_dbus_object_export (NM_DBUS_OBJECT (ap)),
- g_object_ref (ap));
+ g_object_ref (ap);
+ ap->wifi_device = NM_DEVICE (self);
+ c_list_link_tail (&priv->aps_lst_head, &ap->aps_lst);
+ nm_dbus_object_export (NM_DBUS_OBJECT (ap));
_ap_dump (self, LOGL_DEBUG, ap, "added", 0);
- } else
+ nm_device_wifi_emit_signal_access_point (NM_DEVICE (self), ap, TRUE);
+ } else {
+ ap->wifi_device = NULL;
+ c_list_unlink (&ap->aps_lst);
_ap_dump (self, LOGL_DEBUG, ap, "removed", 0);
+ }
- nm_dbus_object_emit_signal (NM_DBUS_OBJECT (self),
- &nm_interface_info_device_wireless,
- is_adding
- ? &nm_signal_info_wireless_access_point_added
- : &nm_signal_info_wireless_access_point_removed,
- "(o)",
- nm_dbus_object_get_path (NM_DBUS_OBJECT (ap)));
+ _notify (self, PROP_ACCESS_POINTS);
if (!is_adding) {
- g_hash_table_remove (priv->aps, nm_dbus_object_get_path (NM_DBUS_OBJECT (ap)));
+ nm_device_wifi_emit_signal_access_point (NM_DEVICE (self), ap, FALSE);
nm_dbus_object_clear_and_unexport (&ap);
}
- _notify (self, PROP_ACCESS_POINTS);
-
nm_device_emit_recheck_auto_activate (NM_DEVICE (self));
if (recheck_available_connections)
nm_device_recheck_available_connections (NM_DEVICE (self));
@@ -519,20 +494,15 @@ static void
remove_all_aps (NMDeviceWifi *self)
{
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
- GHashTableIter iter;
NMWifiAP *ap;
- if (!g_hash_table_size (priv->aps))
+ if (c_list_is_empty (&priv->aps_lst_head))
return;
set_current_ap (self, NULL, FALSE);
-again:
- g_hash_table_iter_init (&iter, priv->aps);
- if (g_hash_table_iter_next (&iter, NULL, (gpointer) &ap)) {
+ while ((ap = c_list_first_entry (&priv->aps_lst_head, NMWifiAP, aps_lst)))
ap_add_remove (self, FALSE, ap, FALSE);
- goto again;
- }
nm_device_recheck_available_connections (NM_DEVICE (self));
}
@@ -702,7 +672,7 @@ check_connection_available (NMDevice *device,
if (specific_object) {
NMWifiAP *ap;
- ap = get_ap_by_path (self, specific_object);
+ ap = nm_wifi_ap_lookup_for_device (NM_DEVICE (self), specific_object);
return ap ? nm_wifi_ap_check_compatible (ap, connection) : FALSE;
}
@@ -726,7 +696,7 @@ check_connection_available (NMDevice *device,
return TRUE;
/* check at least one AP is compatible with this connection */
- return !!nm_wifi_aps_find_first_compatible (priv->aps, connection, TRUE);
+ return !!nm_wifi_aps_find_first_compatible (&priv->aps_lst_head, connection);
}
static gboolean
@@ -774,7 +744,7 @@ complete_connection (NMDevice *device,
if (!nm_streq0 (mode, NM_SETTING_WIRELESS_MODE_AP)) {
/* Find a compatible AP in the scan list */
- ap = nm_wifi_aps_find_first_compatible (priv->aps, connection, FALSE);
+ ap = nm_wifi_aps_find_first_compatible (&priv->aps_lst_head, connection);
/* If we still don't have an AP, then the WiFI settings needs to be
* fully specified by the client. Might not be able to find an AP
@@ -796,7 +766,7 @@ complete_connection (NMDevice *device,
return FALSE;
ap = NULL;
} else {
- ap = get_ap_by_path (self, specific_object);
+ ap = nm_wifi_ap_lookup_for_device (NM_DEVICE (self), specific_object);
if (!ap) {
g_set_error (error,
NM_DEVICE_ERROR,
@@ -988,7 +958,7 @@ can_auto_connect (NMDevice *device,
return FALSE;
}
- ap = nm_wifi_aps_find_first_compatible (priv->aps, connection, FALSE);
+ ap = nm_wifi_aps_find_first_compatible (&priv->aps_lst_head, connection);
if (ap) {
/* All good; connection is usable */
NM_SET_OUT (specific_object, g_strdup (nm_dbus_object_get_path (NM_DBUS_OBJECT (ap))));
@@ -998,10 +968,10 @@ can_auto_connect (NMDevice *device,
return FALSE;
}
-GHashTable *
+const CList *
_nm_device_wifi_get_aps (NMDeviceWifi *self)
{
- return NM_DEVICE_WIFI_GET_PRIVATE (self)->aps;
+ return &NM_DEVICE_WIFI_GET_PRIVATE (self)->aps_lst_head;
}
static void
@@ -1472,17 +1442,15 @@ ap_list_dump (gpointer user_data)
priv->ap_dump_id = 0;
if (_LOGD_ENABLED (LOGD_WIFI_SCAN)) {
- gs_free NMWifiAP **list = NULL;
- gsize i;
+ NMWifiAP *ap;
gint32 now_s = nm_utils_get_monotonic_timestamp_s ();
_LOGD (LOGD_WIFI_SCAN, "APs: [now:%u last:%u next:%u]",
now_s,
priv->last_scan,
priv->scheduled_scan_time);
- list = nm_wifi_aps_get_sorted (priv->aps, TRUE);
- for (i = 0; list[i]; i++)
- _ap_dump (self, LOGL_DEBUG, list[i], "dump", now_s);
+ c_list_for_each_entry (ap, &priv->aps_lst_head, aps_lst)
+ _ap_dump (self, LOGL_DEBUG, ap, "dump", now_s);
}
return G_SOURCE_REMOVE;
}
@@ -1553,7 +1521,7 @@ supplicant_iface_bss_updated_cb (NMSupplicantInterface *iface,
if (NM_DEVICE_WIFI_GET_PRIVATE (self)->mode == NM_802_11_MODE_AP)
return;
- found_ap = get_ap_by_supplicant_path (self, object_path);
+ found_ap = nm_wifi_aps_find_by_supplicant_path (&priv->aps_lst_head, object_path);
if (found_ap) {
if (!nm_wifi_ap_update_from_properties (found_ap, object_path, properties))
return;
@@ -1609,7 +1577,7 @@ supplicant_iface_bss_removed_cb (NMSupplicantInterface *iface,
g_return_if_fail (object_path != NULL);
priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
- ap = get_ap_by_supplicant_path (self, object_path);
+ ap = nm_wifi_aps_find_by_supplicant_path (&priv->aps_lst_head, object_path);
if (!ap)
return;
@@ -2153,7 +2121,7 @@ supplicant_iface_notify_current_bss (NMSupplicantInterface *iface,
current_bss = nm_supplicant_interface_get_current_bss (iface);
if (current_bss)
- new_ap = get_ap_by_supplicant_path (self, current_bss);
+ new_ap = nm_wifi_aps_find_by_supplicant_path (&priv->aps_lst_head, current_bss);
if (new_ap != priv->current_ap) {
const char *new_bssid = NULL;
@@ -2514,11 +2482,11 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason)
/* AP mode never uses a specific object or existing scanned AP */
if (priv->mode != NM_802_11_MODE_AP) {
ap_path = nm_active_connection_get_specific_object (NM_ACTIVE_CONNECTION (req));
- ap = ap_path ? get_ap_by_path (self, ap_path) : NULL;
+ ap = ap_path ? nm_wifi_ap_lookup_for_device (NM_DEVICE (self), ap_path) : NULL;
if (ap)
goto done;
- ap = nm_wifi_aps_find_first_compatible (priv->aps, connection, FALSE);
+ ap = nm_wifi_aps_find_first_compatible (&priv->aps_lst_head, connection);
}
if (ap) {
@@ -3134,8 +3102,7 @@ get_property (GObject *object, guint prop_id,
{
NMDeviceWifi *self = NM_DEVICE_WIFI (object);
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
- gsize i;
- char **list;
+ const char **list;
switch (prop_id) {
case PROP_MODE:
@@ -3148,10 +3115,8 @@ get_property (GObject *object, guint prop_id,
g_value_set_uint (value, priv->capabilities);
break;
case PROP_ACCESS_POINTS:
- list = (char **) nm_wifi_aps_get_sorted_paths (priv->aps, TRUE);
- for (i = 0; list[i]; i++)
- list[i] = g_strdup (list[i]);
- g_value_take_boxed (value, list);
+ list = nm_wifi_aps_get_paths (&priv->aps_lst_head, TRUE);
+ g_value_take_boxed (value, nm_utils_strv_make_deep_copied (list));
break;
case PROP_ACTIVE_ACCESS_POINT:
nm_dbus_utils_g_value_set_object_path (value, priv->current_ap);
@@ -3190,8 +3155,9 @@ nm_device_wifi_init (NMDeviceWifi *self)
{
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
+ c_list_init (&priv->aps_lst_head);
+
priv->mode = NM_802_11_MODE_INFRA;
- priv->aps = g_hash_table_new (nm_str_hash, g_str_equal);
}
static void
@@ -3249,9 +3215,7 @@ finalize (GObject *object)
NMDeviceWifi *self = NM_DEVICE_WIFI (object);
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
- nm_assert (g_hash_table_size (priv->aps) == 0);
-
- g_hash_table_unref (priv->aps);
+ nm_assert (c_list_is_empty (&priv->aps_lst_head));
G_OBJECT_CLASS (nm_device_wifi_parent_class)->finalize (object);
}
diff --git a/src/devices/wifi/nm-device-wifi.h b/src/devices/wifi/nm-device-wifi.h
index 632bbac1f4..c13b00defc 100644
--- a/src/devices/wifi/nm-device-wifi.h
+++ b/src/devices/wifi/nm-device-wifi.h
@@ -47,7 +47,7 @@ GType nm_device_wifi_get_type (void);
NMDevice * nm_device_wifi_new (const char *iface, NMDeviceWifiCapabilities capabilities);
-GHashTable *_nm_device_wifi_get_aps (NMDeviceWifi *self);
+const CList *_nm_device_wifi_get_aps (NMDeviceWifi *self);
void _nm_device_wifi_request_scan (NMDeviceWifi *self,
GVariant *options,
diff --git a/src/devices/wifi/nm-wifi-ap.c b/src/devices/wifi/nm-wifi-ap.c
index 60767032cd..dd6d1deb6e 100644
--- a/src/devices/wifi/nm-wifi-ap.c
+++ b/src/devices/wifi/nm-wifi-ap.c
@@ -33,6 +33,8 @@
#include "nm-utils.h"
#include "nm-core-internal.h"
#include "platform/nm-platform.h"
+#include "devices/nm-device.h"
+#include "nm-dbus-manager.h"
#define PROTO_WPA "wpa"
#define PROTO_RSN "rsn"
@@ -52,7 +54,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMWifiAP,
PROP_LAST_SEEN,
);
-typedef struct {
+struct _NMWifiAPPrivate {
char *supplicant_path; /* D-Bus object path of this AP from wpa_supplicant */
/* Scanned or cached values */
@@ -71,20 +73,17 @@ typedef struct {
bool fake:1; /* Whether or not the AP is from a scan */
bool hotspot:1; /* Whether the AP is a local device's hotspot network */
gint32 last_seen; /* Timestamp when the AP was seen lastly (obtained via nm_utils_get_monotonic_timestamp_s()) */
-} NMWifiAPPrivate;
-
-struct _NMWifiAP {
- NMDBusObject parent;
- NMWifiAPPrivate _priv;
};
+typedef struct _NMWifiAPPrivate NMWifiAPPrivate;
+
struct _NMWifiAPClass {
NMDBusObjectClass parent;
};
G_DEFINE_TYPE (NMWifiAP, nm_wifi_ap, NM_TYPE_DBUS_OBJECT)
-#define NM_WIFI_AP_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMWifiAP, NM_IS_WIFI_AP)
+#define NM_WIFI_AP_GET_PRIVATE(self) _NM_GET_PRIVATE_PTR(self, NMWifiAP, NM_IS_WIFI_AP)
/*****************************************************************************/
@@ -96,25 +95,6 @@ nm_wifi_ap_get_supplicant_path (NMWifiAP *ap)
return NM_WIFI_AP_GET_PRIVATE (ap)->supplicant_path;
}
-guint64
-nm_wifi_ap_get_id (NMWifiAP *ap)
-{
- const char *path;
- guint64 i;
-
- g_return_val_if_fail (NM_IS_WIFI_AP (ap), 0);
-
- path = nm_dbus_object_get_path (NM_DBUS_OBJECT (ap));
- g_return_val_if_fail (path, 0);
-
- nm_assert (g_str_has_prefix (path, NM_DBUS_PATH_ACCESS_POINT"/"));
-
- i = _nm_utils_ascii_str_to_int64 (&path[NM_STRLEN (NM_DBUS_PATH_ACCESS_POINT"/")], 10, 1, G_MAXINT64, 0);
-
- nm_assert (i);
- return i;
-}
-
const GByteArray *
nm_wifi_ap_get_ssid (const NMWifiAP *ap)
{
@@ -1178,9 +1158,15 @@ get_property (GObject *object, guint prop_id,
/*****************************************************************************/
static void
-nm_wifi_ap_init (NMWifiAP *ap)
+nm_wifi_ap_init (NMWifiAP *self)
{
- NMWifiAPPrivate *priv = NM_WIFI_AP_GET_PRIVATE (ap);
+ NMWifiAPPrivate *priv;
+
+ priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NM_TYPE_WIFI_AP, NMWifiAPPrivate);
+
+ self->_priv = priv;
+
+ c_list_init (&self->aps_lst);
priv->mode = NM_802_11_MODE_INFRA;
priv->flags = NM_802_11_AP_FLAGS_NONE;
@@ -1340,7 +1326,11 @@ error:
static void
finalize (GObject *object)
{
- NMWifiAPPrivate *priv = NM_WIFI_AP_GET_PRIVATE ((NMWifiAP *) object);
+ NMWifiAP *self = NM_WIFI_AP (object);
+ NMWifiAPPrivate *priv = NM_WIFI_AP_GET_PRIVATE (self);
+
+ nm_assert (!self->wifi_device);
+ nm_assert (c_list_is_empty (&self->aps_lst));
g_free (priv->supplicant_path);
if (priv->ssid)
@@ -1391,6 +1381,8 @@ nm_wifi_ap_class_init (NMWifiAPClass *ap_class)
GObjectClass *object_class = G_OBJECT_CLASS (ap_class);
NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (ap_class);
+ g_type_class_add_private (object_class, sizeof (NMWifiAPPrivate));
+
dbus_object_class->export_path = NM_DBUS_EXPORT_PATH_NUMBERED (NM_DBUS_PATH_ACCESS_POINT);
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_access_point);
@@ -1459,86 +1451,81 @@ nm_wifi_ap_class_init (NMWifiAPClass *ap_class)
/*****************************************************************************/
-static int
-ap_id_compare (gconstpointer p_a, gconstpointer p_b, gpointer user_data)
-{
- guint64 a_id = nm_wifi_ap_get_id (*((NMWifiAP **) p_a));
- guint64 b_id = nm_wifi_ap_get_id (*((NMWifiAP **) p_b));
-
- return a_id < b_id ? -1 : (a_id == b_id ? 0 : 1);
-}
-
-NMWifiAP **
-nm_wifi_aps_get_sorted (GHashTable *aps, gboolean include_without_ssid)
+const char **
+nm_wifi_aps_get_paths (const CList *aps_lst_head, gboolean include_without_ssid)
{
- NMWifiAP **list;
- GHashTableIter iter;
NMWifiAP *ap;
gsize i, n;
+ const char **list;
+ const char *path;
- n = g_hash_table_size (aps);
- list = g_new (NMWifiAP *, n + 1);
+ n = c_list_length (aps_lst_head);
+ list = g_new (const char *, n + 1);
i = 0;
if (n > 0) {
- g_hash_table_iter_init (&iter, aps);
- while (g_hash_table_iter_next (&iter, NULL, (gpointer) &ap)) {
+ c_list_for_each_entry (ap, aps_lst_head, aps_lst) {
nm_assert (i < n);
- if ( include_without_ssid
- || nm_wifi_ap_get_ssid (ap))
- list[i++] = ap;
+ if ( !include_without_ssid
+ && !nm_wifi_ap_get_ssid (ap))
+ continue;
+
+ path = nm_dbus_object_get_path (NM_DBUS_OBJECT (ap));
+ nm_assert (path);
+
+ list[i++] = path;
}
nm_assert (i <= n);
nm_assert (!include_without_ssid || i == n);
-
- g_qsort_with_data (list,
- i,
- sizeof (gpointer),
- ap_id_compare,
- NULL);
}
list[i] = NULL;
return list;
}
-const char **
-nm_wifi_aps_get_sorted_paths (GHashTable *aps, gboolean include_without_ssid)
+NMWifiAP *
+nm_wifi_aps_find_first_compatible (const CList *aps_lst_head,
+ NMConnection *connection)
{
- gpointer *list;
- gsize i, j;
-
- list = (gpointer *) nm_wifi_aps_get_sorted (aps, include_without_ssid);
- for (i = 0, j = 0; list[i]; i++) {
- NMWifiAP *ap = list[i];
- const char *path;
-
- /* update @list inplace to hold instead the export-path. */
- path = nm_dbus_object_get_path (NM_DBUS_OBJECT (ap));
- nm_assert (path);
- list[j++] = (gpointer) path;
+ NMWifiAP *ap;
+
+ g_return_val_if_fail (connection, NULL);
+
+ c_list_for_each_entry (ap, aps_lst_head, aps_lst) {
+ if (nm_wifi_ap_check_compatible (ap, connection))
+ return ap;
}
- return (const char **) list;
+ return NULL;
}
NMWifiAP *
-nm_wifi_aps_find_first_compatible (GHashTable *aps,
- NMConnection *connection,
- gboolean allow_unstable_order)
+nm_wifi_aps_find_by_supplicant_path (const CList *aps_lst_head, const char *path)
{
- GHashTableIter iter;
NMWifiAP *ap;
- NMWifiAP *cand_ap = NULL;
- g_return_val_if_fail (connection != NULL, NULL);
+ g_return_val_if_fail (path != NULL, NULL);
- g_hash_table_iter_init (&iter, aps);
- while (g_hash_table_iter_next (&iter, NULL, (gpointer) &ap)) {
- if (!nm_wifi_ap_check_compatible (ap, connection))
- continue;
- if (allow_unstable_order)
+ c_list_for_each_entry (ap, aps_lst_head, aps_lst) {
+ if (nm_streq0 (path, nm_wifi_ap_get_supplicant_path (ap)))
return ap;
- if (!cand_ap || (nm_wifi_ap_get_id (cand_ap) < nm_wifi_ap_get_id (ap)))
- cand_ap = ap;
}
- return cand_ap;
+ return NULL;
+}
+
+/*****************************************************************************/
+
+NMWifiAP *
+nm_wifi_ap_lookup_for_device (NMDevice *device, const char *exported_path)
+{
+ NMWifiAP *ap;
+
+ g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
+
+ ap = (NMWifiAP *) nm_dbus_manager_lookup_object (nm_dbus_object_get_manager (NM_DBUS_OBJECT (device)),
+ exported_path);
+ if ( !ap
+ || !NM_IS_WIFI_AP (ap)
+ || ap->wifi_device != device)
+ return NULL;
+
+ return ap;
}
diff --git a/src/devices/wifi/nm-wifi-ap.h b/src/devices/wifi/nm-wifi-ap.h
index 314f2265f1..4fdeee935c 100644
--- a/src/devices/wifi/nm-wifi-ap.h
+++ b/src/devices/wifi/nm-wifi-ap.h
@@ -44,7 +44,13 @@
#define NM_WIFI_AP_STRENGTH "strength"
#define NM_WIFI_AP_LAST_SEEN "last-seen"
-typedef struct _NMWifiAP NMWifiAP;
+typedef struct {
+ NMDBusObject parent;
+ NMDevice *wifi_device;
+ CList aps_lst;
+ struct _NMWifiAPPrivate *_priv;
+} NMWifiAP;
+
typedef struct _NMWifiAPClass NMWifiAPClass;
GType nm_wifi_ap_get_type (void);
@@ -66,7 +72,6 @@ gboolean nm_wifi_ap_complete_connection (NMWifiAP *self,
GError **error);
const char * nm_wifi_ap_get_supplicant_path (NMWifiAP *ap);
-guint64 nm_wifi_ap_get_id (NMWifiAP *ap);
const GByteArray *nm_wifi_ap_get_ssid (const NMWifiAP *ap);
gboolean nm_wifi_ap_set_ssid (NMWifiAP *ap,
const guint8 *ssid,
@@ -95,12 +100,14 @@ const char *nm_wifi_ap_to_string (const NMWifiAP *self,
gulong buf_len,
gint32 now_s);
-NMWifiAP **nm_wifi_aps_get_sorted (GHashTable *aps,
- gboolean include_without_ssid);
-const char **nm_wifi_aps_get_sorted_paths (GHashTable *aps,
- gboolean include_without_ssid);
-NMWifiAP *nm_wifi_aps_find_first_compatible (GHashTable *aps,
- NMConnection *connection,
- gboolean allow_unstable_order);
+const char **nm_wifi_aps_get_paths (const CList *aps_lst_head,
+ gboolean include_without_ssid);
+
+NMWifiAP *nm_wifi_aps_find_first_compatible (const CList *aps_lst_head,
+ NMConnection *connection);
+
+NMWifiAP *nm_wifi_aps_find_by_supplicant_path (const CList *aps_lst_head, const char *path);
+
+NMWifiAP *nm_wifi_ap_lookup_for_device (NMDevice *device, const char *exported_path);
#endif /* __NM_WIFI_AP_H__ */
diff --git a/src/devices/wifi/nm-wifi-common.c b/src/devices/wifi/nm-wifi-common.c
index 005aac9d60..47c0ce6784 100644
--- a/src/devices/wifi/nm-wifi-common.c
+++ b/src/devices/wifi/nm-wifi-common.c
@@ -25,6 +25,7 @@
#include "devices/nm-device.h"
#include "nm-wifi-ap.h"
#include "nm-device-wifi.h"
+#include "nm-dbus-manager.h"
#if WITH_IWD
#include "nm-device-iwd.h"
@@ -32,7 +33,23 @@
/*****************************************************************************/
-static GHashTable *
+void
+nm_device_wifi_emit_signal_access_point (NMDevice *device,
+ NMWifiAP *ap,
+ gboolean is_added /* or else is_removed */)
+{
+ nm_dbus_object_emit_signal (NM_DBUS_OBJECT (device),
+ &nm_interface_info_device_wireless,
+ is_added
+ ? &nm_signal_info_wireless_access_point_added
+ : &nm_signal_info_wireless_access_point_removed,
+ "(o)",
+ nm_dbus_object_get_path (NM_DBUS_OBJECT (ap)));
+}
+
+/*****************************************************************************/
+
+static const CList *
_dispatch_get_aps (NMDevice *device)
{
#if WITH_IWD
@@ -70,12 +87,12 @@ impl_device_wifi_get_access_points (NMDBusObject *obj,
{
gs_free const char **list = NULL;
GVariant *v;
- GHashTable *aps;
+ const CList *all_aps;
/* NOTE: this handler is called both for NMDevicwWifi and NMDeviceIwd. */
- aps = _dispatch_get_aps (NM_DEVICE (obj));
- list = nm_wifi_aps_get_sorted_paths (aps, FALSE);
+ all_aps = _dispatch_get_aps (NM_DEVICE (obj));
+ list = nm_wifi_aps_get_paths (all_aps, FALSE);
v = g_variant_new_objv (list, -1);
g_dbus_method_invocation_return_value (invocation,
g_variant_new_tuple (&v, 1));
@@ -92,12 +109,12 @@ impl_device_wifi_get_all_access_points (NMDBusObject *obj,
{
gs_free const char **list = NULL;
GVariant *v;
- GHashTable *aps;
+ const CList *all_aps;
/* NOTE: this handler is called both for NMDevicwWifi and NMDeviceIwd. */
- aps = _dispatch_get_aps (NM_DEVICE (obj));
- list = nm_wifi_aps_get_sorted_paths (aps, TRUE);
+ all_aps = _dispatch_get_aps (NM_DEVICE (obj));
+ list = nm_wifi_aps_get_paths (all_aps, TRUE);
v = g_variant_new_objv (list, -1);
g_dbus_method_invocation_return_value (invocation,
g_variant_new_tuple (&v, 1));
diff --git a/src/devices/wifi/nm-wifi-common.h b/src/devices/wifi/nm-wifi-common.h
index 4df4a5903b..91cbeb558d 100644
--- a/src/devices/wifi/nm-wifi-common.h
+++ b/src/devices/wifi/nm-wifi-common.h
@@ -22,9 +22,14 @@
#define __NM_WIFI_COMMON_H__
#include "nm-dbus-utils.h"
+#include "nm-wifi-ap.h"
/*****************************************************************************/
+void nm_device_wifi_emit_signal_access_point (NMDevice *device,
+ NMWifiAP *ap,
+ gboolean is_added /* or else is_removed */);
+
extern const NMDBusInterfaceInfoExtended nm_interface_info_device_wireless;
extern const GDBusSignalInfo nm_signal_info_wireless_access_point_added;
extern const GDBusSignalInfo nm_signal_info_wireless_access_point_removed;