summaryrefslogtreecommitdiff
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
parent8ecc325f29f5cba83daf6fca0003c7e13bafba31 (diff)
downloadNetworkManager-th/cli-trigger-scan-retry.tar.gz
wifi: add callback to nm_supplicant_interface_request_scan()th/cli-trigger-scan-retry
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.
-rw-r--r--src/devices/wifi/nm-device-wifi.c6
-rw-r--r--src/supplicant/nm-supplicant-interface.c92
-rw-r--r--src/supplicant/nm-supplicant-interface.h9
3 files changed, 90 insertions, 17 deletions
diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c
index 40faa13470..bf3e6ad27a 100644
--- a/src/devices/wifi/nm-device-wifi.c
+++ b/src/devices/wifi/nm-device-wifi.c
@@ -1509,7 +1509,11 @@ request_wireless_scan (NMDeviceWifi *self,
nm_supplicant_interface_request_scan (priv->sup_iface,
ssids ? (GBytes *const*) ssids->pdata : NULL,
- ssids ? ssids->len : 0u);
+ ssids ? ssids->len : 0u,
+ NULL,
+ NULL,
+ NULL);
+
request_started = TRUE;
} else
_LOGD (LOGD_WIFI, "wifi-scan: scanning requested but not allowed at this time");
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);