summaryrefslogtreecommitdiff
path: root/src/supplicant/nm-supplicant-interface.c
diff options
context:
space:
mode:
authorBenjamin Berg <bberg@redhat.com>2018-10-10 21:27:34 +0200
committerThomas Haller <thaller@redhat.com>2018-12-13 09:20:55 +0100
commit08c28ef96ba52486ba037c04e55c30fd472af8f4 (patch)
tree27f53aad78dd401755ce1756e92e2091d578fb58 /src/supplicant/nm-supplicant-interface.c
parentae22631d66027b8e186096159fa4927b9bdc20f5 (diff)
downloadNetworkManager-08c28ef96ba52486ba037c04e55c30fd472af8f4.tar.gz
supplicant: Monitor existance of P2P Peers found
Diffstat (limited to 'src/supplicant/nm-supplicant-interface.c')
-rw-r--r--src/supplicant/nm-supplicant-interface.c199
1 files changed, 197 insertions, 2 deletions
diff --git a/src/supplicant/nm-supplicant-interface.c b/src/supplicant/nm-supplicant-interface.c
index 3f5449ec66..43104cf4ce 100644
--- a/src/supplicant/nm-supplicant-interface.c
+++ b/src/supplicant/nm-supplicant-interface.c
@@ -35,6 +35,7 @@
#define WPAS_DBUS_IFACE_INTERFACE_WPS WPAS_DBUS_INTERFACE ".Interface.WPS"
#define WPAS_DBUS_IFACE_INTERFACE_P2P_DEVICE WPAS_DBUS_INTERFACE ".Interface.P2PDevice"
#define WPAS_DBUS_IFACE_BSS WPAS_DBUS_INTERFACE ".BSS"
+#define WPAS_DBUS_IFACE_PEER WPAS_DBUS_INTERFACE ".Peer"
#define WPAS_DBUS_IFACE_NETWORK WPAS_DBUS_INTERFACE ".Network"
#define WPAS_ERROR_INVALID_IFACE WPAS_DBUS_INTERFACE ".InvalidInterface"
#define WPAS_ERROR_EXISTS_ERROR WPAS_DBUS_INTERFACE ".InterfaceExists"
@@ -46,6 +47,11 @@ typedef struct {
gulong change_id;
} BssData;
+typedef struct {
+ GDBusProxy *proxy;
+ gulong change_id;
+} PeerData;
+
struct _AddNetworkData;
typedef struct {
@@ -79,6 +85,8 @@ enum {
REMOVED, /* interface was removed by the supplicant */
BSS_UPDATED, /* a new BSS appeared or an existing had properties changed */
BSS_REMOVED, /* supplicant removed BSS from its scan list */
+ PEER_UPDATED, /* a new Peer appeared or an existing had properties changed */
+ PEER_REMOVED, /* supplicant removed Peer from its scan list */
SCAN_DONE, /* wifi scan is complete */
CREDENTIALS_REQUEST, /* 802.1x identity or password requested */
WPS_CREDENTIALS, /* WPS credentials received */
@@ -139,6 +147,8 @@ typedef struct {
GHashTable * bss_proxies;
char * current_bss;
+ GHashTable * peer_proxies;
+
gint64 last_scan; /* timestamp as returned by nm_utils_get_monotonic_timestamp_ms() */
} NMSupplicantInterfacePrivate;
@@ -321,6 +331,122 @@ bss_add_new (NMSupplicantInterface *self, const char *object_path)
self);
}
+static void
+peer_data_destroy (gpointer user_data)
+{
+ PeerData *peer_data = user_data;
+
+ nm_clear_g_signal_handler (peer_data->proxy, &peer_data->change_id);
+ g_object_unref (peer_data->proxy);
+ g_slice_free (PeerData, peer_data);
+}
+
+static void
+peer_proxy_properties_changed_cb (GDBusProxy *proxy,
+ GVariant *changed_properties,
+ char **invalidated_properties,
+ gpointer user_data)
+{
+ NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
+
+ g_signal_emit (self, signals[PEER_UPDATED], 0,
+ g_dbus_proxy_get_object_path (proxy),
+ changed_properties);
+}
+
+static GVariant *
+peer_proxy_get_properties (NMSupplicantInterface *self, GDBusProxy *proxy)
+{
+ gs_strfreev char **properties = NULL;
+ GVariantBuilder builder;
+ char **iter;
+
+ iter = properties = g_dbus_proxy_get_cached_property_names (proxy);
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
+ if (iter) {
+ while (*iter) {
+ GVariant *copy = g_dbus_proxy_get_cached_property (proxy, *iter);
+
+ g_variant_builder_add (&builder, "{sv}", *iter++, copy);
+ g_variant_unref (copy);
+ }
+ }
+ return g_variant_builder_end (&builder);
+}
+
+static void
+peer_proxy_acquired_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
+{
+ NMSupplicantInterface *self;
+ NMSupplicantInterfacePrivate *priv;
+ gs_free_error GError *error = NULL;
+ GVariant *props = NULL;
+ const char *object_path;
+ PeerData *peer_data;
+ gboolean success;
+
+ success = g_async_initable_init_finish (G_ASYNC_INITABLE (proxy), result, &error);
+ if ( !success
+ && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ return;
+
+ self = NM_SUPPLICANT_INTERFACE (user_data);
+ priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
+
+ if (!success) {
+ _LOGD ("failed to acquire Peer proxy: (%s)", error->message);
+ g_hash_table_remove (priv->peer_proxies,
+ g_dbus_proxy_get_object_path (proxy));
+ return;
+ }
+
+ object_path = g_dbus_proxy_get_object_path (proxy);
+ peer_data = g_hash_table_lookup (priv->peer_proxies, object_path);
+ if (!peer_data)
+ return;
+
+ peer_data->change_id = g_signal_connect (proxy, "g-properties-changed", G_CALLBACK (peer_proxy_properties_changed_cb), self);
+
+ props = peer_proxy_get_properties (self, proxy);
+
+ g_signal_emit (self, signals[PEER_UPDATED], 0,
+ g_dbus_proxy_get_object_path (proxy),
+ g_variant_ref_sink (props));
+ g_variant_unref (props);
+}
+
+static void
+peer_add_new (NMSupplicantInterface *self, const char *object_path)
+{
+ NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
+ GDBusProxy *peer_proxy;
+ PeerData *peer_data;
+
+ g_return_if_fail (object_path != NULL);
+
+ if (g_hash_table_lookup (priv->peer_proxies, object_path))
+ return;
+
+ peer_proxy = g_object_new (G_TYPE_DBUS_PROXY,
+ "g-bus-type", G_BUS_TYPE_SYSTEM,
+ "g-flags", G_DBUS_PROXY_FLAGS_NONE,
+ "g-name", WPAS_DBUS_SERVICE,
+ "g-object-path", object_path,
+ "g-interface-name", WPAS_DBUS_IFACE_PEER,
+ NULL);
+ peer_data = g_slice_new0 (PeerData);
+ peer_data->proxy = peer_proxy;
+ g_hash_table_insert (priv->peer_proxies,
+ (char *) g_dbus_proxy_get_object_path (peer_proxy),
+ peer_data);
+ g_async_initable_init_async (G_ASYNC_INITABLE (peer_proxy),
+ G_PRIORITY_DEFAULT,
+ priv->other_cancellable,
+ (GAsyncReadyCallback) peer_proxy_acquired_cb,
+ self);
+}
+
/*****************************************************************************/
static void
@@ -1156,6 +1282,54 @@ props_changed_cb (GDBusProxy *proxy,
}
static void
+p2p_props_changed_cb (GDBusProxy *proxy,
+ GVariant *changed_properties,
+ GStrv invalidated_properties,
+ gpointer user_data)
+{
+ NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
+ const char **array, **iter;
+
+ g_object_freeze_notify (G_OBJECT (self));
+
+ if (g_variant_lookup (changed_properties, "Peers", "^a&o", &array)) {
+ iter = array;
+ while (*iter)
+ peer_add_new (self, *iter++);
+ g_free (array);
+ }
+
+ g_object_thaw_notify (G_OBJECT (self));
+}
+
+static void
+p2p_device_found (GDBusProxy *proxy,
+ const char *path,
+ gpointer user_data)
+{
+ NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
+
+ peer_add_new (self, path);
+}
+
+static void
+p2p_device_lost (GDBusProxy *proxy,
+ const char *path,
+ gpointer user_data)
+{
+ NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
+ NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
+ PeerData *peer_data;
+
+ peer_data = g_hash_table_lookup (priv->peer_proxies, path);
+ if (!peer_data)
+ return;
+ g_hash_table_steal (priv->peer_proxies, path);
+ g_signal_emit (self, signals[PEER_REMOVED], 0, path);
+ peer_data_destroy (peer_data);
+}
+
+static void
on_iface_proxy_acquired (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
{
NMSupplicantInterface *self;
@@ -1261,9 +1435,11 @@ on_p2p_proxy_acquired (GDBusProxy *proxy, GAsyncResult *result, gpointer user_da
self = NM_SUPPLICANT_INTERFACE (user_data);
priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
+ _nm_dbus_signal_connect (priv->p2p_proxy, "DeviceFound", G_VARIANT_TYPE ("(o)"),
+ G_CALLBACK (p2p_device_found), self);
+ _nm_dbus_signal_connect (priv->p2p_proxy, "DeviceLost", G_VARIANT_TYPE ("(o)"),
+ G_CALLBACK (p2p_device_lost), self);
/* TODO:
- * * DeviceFound
- * * DeviceLost
* * GroupStarted
* * GroupFinished
* * GroupFormationFailure
@@ -1313,6 +1489,7 @@ interface_add_done (NMSupplicantInterface *self, const char *path)
"g-object-path", priv->object_path,
"g-interface-name", WPAS_DBUS_IFACE_INTERFACE_P2P_DEVICE,
NULL);
+ g_signal_connect (priv->p2p_proxy, "g-properties-changed", G_CALLBACK (p2p_props_changed_cb), self);
g_async_initable_init_async (G_ASYNC_INITABLE (priv->p2p_proxy),
G_PRIORITY_DEFAULT,
priv->init_cancellable,
@@ -2088,6 +2265,7 @@ nm_supplicant_interface_init (NMSupplicantInterface * self)
priv->state = NM_SUPPLICANT_INTERFACE_STATE_INIT;
priv->bss_proxies = g_hash_table_new_full (nm_str_hash, g_str_equal, NULL, bss_data_destroy);
+ priv->peer_proxies = g_hash_table_new_full (nm_str_hash, g_str_equal, NULL, peer_data_destroy);
}
NMSupplicantInterface *
@@ -2151,6 +2329,7 @@ dispose (GObject *object)
g_signal_handlers_disconnect_by_data (priv->wpas_proxy, object);
g_clear_object (&priv->wpas_proxy);
g_clear_pointer (&priv->bss_proxies, g_hash_table_destroy);
+ g_clear_pointer (&priv->peer_proxies, g_hash_table_destroy);
g_clear_pointer (&priv->net_path, g_free);
g_clear_pointer (&priv->dev, g_free);
@@ -2279,6 +2458,22 @@ nm_supplicant_interface_class_init (NMSupplicantInterfaceClass *klass)
NULL, NULL, NULL,
G_TYPE_NONE, 1, G_TYPE_STRING);
+ signals[PEER_UPDATED] =
+ g_signal_new (NM_SUPPLICANT_INTERFACE_PEER_UPDATED,
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL, NULL,
+ G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_VARIANT);
+
+ signals[PEER_REMOVED] =
+ g_signal_new (NM_SUPPLICANT_INTERFACE_PEER_REMOVED,
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL, NULL,
+ G_TYPE_NONE, 1, G_TYPE_STRING);
+
signals[SCAN_DONE] =
g_signal_new (NM_SUPPLICANT_INTERFACE_SCAN_DONE,
G_OBJECT_CLASS_TYPE (object_class),