summaryrefslogtreecommitdiff
path: root/src/supplicant
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2020-04-24 16:42:13 +0200
committerThomas Haller <thaller@redhat.com>2020-04-24 16:57:28 +0200
commit16c1869476106859b684151eb1b101c24cff3451 (patch)
tree8067197fbb8246324f884e38f24472ef2aed6f10 /src/supplicant
parent8ecc325f29f5cba83daf6fca0003c7e13bafba31 (diff)
wifi: add callback to nm_supplicant_interface_request_scan()
While we request a scan, we are not yet actually scanning. That means, the supplicant's "scanning" property will only change to TRUE a while after we initiate the scan. It may even never happen. We thus need to handle that the request is currently pending and react when the request completes.
Diffstat (limited to 'src/supplicant')
-rw-r--r--src/supplicant/nm-supplicant-interface.c92
-rw-r--r--src/supplicant/nm-supplicant-interface.h9
2 files changed, 85 insertions, 16 deletions
diff --git a/src/supplicant/nm-supplicant-interface.c b/src/supplicant/nm-supplicant-interface.c
index bfee298445..099c3bf2ca 100644
--- a/src/supplicant/nm-supplicant-interface.c
+++ b/src/supplicant/nm-supplicant-interface.c
@@ -2337,40 +2337,82 @@ nm_supplicant_interface_assoc (NMSupplicantInterface *self,
/*****************************************************************************/
+typedef struct {
+ NMSupplicantInterface *self;
+ GCancellable *cancellable;
+ NMSupplicantInterfaceRequestScanCallback callback;
+ gpointer user_data;
+} ScanRequestData;
+
static void
scan_request_cb (GObject *source, GAsyncResult *result, gpointer user_data)
{
+ gs_unref_object NMSupplicantInterface *self_keep_alive = NULL;
NMSupplicantInterface *self;
gs_unref_variant GVariant *res = NULL;
gs_free_error GError *error = NULL;
+ ScanRequestData *data = user_data;
+ gboolean cancelled = FALSE;
res = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), result, &error);
- if (nm_utils_error_is_cancelled (error))
- return;
-
- self = NM_SUPPLICANT_INTERFACE (user_data);
- if (error) {
- if (_nm_dbus_error_has_name (error, "fi.w1.wpa_supplicant1.Interface.ScanError"))
- _LOGD ("request-scan: could not get scan request result: %s", error->message);
- else {
- g_dbus_error_strip_remote_error (error);
- _LOGW ("request-scan: could not get scan request result: %s", error->message);
+ if (nm_utils_error_is_cancelled (error)) {
+ if (!data->callback) {
+ /* the self instance was not kept alive. We also must not touch it. Return. */
+ nm_g_object_unref (data->cancellable);
+ nm_g_slice_free (data);
+ return;
}
- } else
- _LOGT ("request-scan: request scanning success");
+ cancelled = TRUE;
+ }
+
+ self = data->self;
+ if (data->callback) {
+ /* the self instance was kept alive. Balance the reference count. */
+ self_keep_alive = self;
+ }
+
+ /* we don't propagate the error/success. That is, because either answer is not
+ * reliable. What is important to us is whether the request completed, and
+ * the current nm_supplicant_interface_get_scanning() state. */
+ if (cancelled)
+ _LOGD ("request-scan: request cancelled");
+ else {
+ if (error) {
+ if (_nm_dbus_error_has_name (error, "fi.w1.wpa_supplicant1.Interface.ScanError"))
+ _LOGD ("request-scan: could not get scan request result: %s", error->message);
+ else {
+ g_dbus_error_strip_remote_error (error);
+ _LOGW ("request-scan: could not get scan request result: %s", error->message);
+ }
+ } else
+ _LOGT ("request-scan: request scanning success");
+ }
+
+ if (data->callback)
+ data->callback (self, data->cancellable, data->user_data);
+
+ nm_g_object_unref (data->cancellable);
+ nm_g_slice_free (data);
}
void
nm_supplicant_interface_request_scan (NMSupplicantInterface *self,
GBytes *const*ssids,
- guint ssids_len)
+ guint ssids_len,
+ GCancellable *cancellable,
+ NMSupplicantInterfaceRequestScanCallback callback,
+ gpointer user_data)
{
NMSupplicantInterfacePrivate *priv;
GVariantBuilder builder;
+ ScanRequestData *data;
guint i;
g_return_if_fail (NM_IS_SUPPLICANT_INTERFACE (self));
+ nm_assert ( (!cancellable && !callback)
+ || (G_IS_CANCELLABLE (cancellable) && callback));
+
priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
_LOGT ("request-scan: request scanning (%u ssids)...", ssids_len);
@@ -2390,6 +2432,26 @@ nm_supplicant_interface_request_scan (NMSupplicantInterface *self,
g_variant_builder_add (&builder, "{sv}", "SSIDs", g_variant_builder_end (&ssids_builder));
}
+ data = g_slice_new (ScanRequestData);
+ *data = (ScanRequestData) {
+ .self = self,
+ .callback = callback,
+ .user_data = user_data,
+ .cancellable = nm_g_object_ref (cancellable),
+ };
+
+ if (callback) {
+ /* A callback was provided. This keeps @self alive. The caller
+ * must provide a cancellable as the caller must never leave an asynchronous
+ * operation pending indefinitely. */
+ nm_assert (G_IS_CANCELLABLE (cancellable));
+ g_object_ref (self);
+ } else {
+ /* We don't keep @self alive, and we don't accept a cancellable either. */
+ nm_assert (!cancellable);
+ cancellable = priv->main_cancellable;
+ }
+
_dbus_connection_call (self,
NM_WPAS_DBUS_IFACE_INTERFACE,
"Scan",
@@ -2397,9 +2459,9 @@ nm_supplicant_interface_request_scan (NMSupplicantInterface *self,
G_VARIANT_TYPE ("()"),
G_DBUS_CALL_FLAGS_NONE,
DBUS_TIMEOUT_MSEC,
- priv->main_cancellable,
+ cancellable,
scan_request_cb,
- self);
+ data);
}
/*****************************************************************************/
diff --git a/src/supplicant/nm-supplicant-interface.h b/src/supplicant/nm-supplicant-interface.h
index eb414f26f5..9ef198167f 100644
--- a/src/supplicant/nm-supplicant-interface.h
+++ b/src/supplicant/nm-supplicant-interface.h
@@ -128,9 +128,16 @@ nm_supplicant_interface_disconnect_async (NMSupplicantInterface * self,
NMSupplicantInterfaceDisconnectCb callback,
gpointer user_data);
+typedef void (*NMSupplicantInterfaceRequestScanCallback) (NMSupplicantInterface *self,
+ GCancellable *cancellable,
+ gpointer user_data);
+
void nm_supplicant_interface_request_scan (NMSupplicantInterface *self,
GBytes *const*ssids,
- guint ssids_len);
+ guint ssids_len,
+ GCancellable *cancellable,
+ NMSupplicantInterfaceRequestScanCallback callback,
+ gpointer user_data);
NMSupplicantInterfaceState nm_supplicant_interface_get_state (NMSupplicantInterface * self);