diff options
author | Thomas Haller <thaller@redhat.com> | 2020-04-24 16:42:13 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2020-04-24 16:57:28 +0200 |
commit | 16c1869476106859b684151eb1b101c24cff3451 (patch) | |
tree | 8067197fbb8246324f884e38f24472ef2aed6f10 | |
parent | 8ecc325f29f5cba83daf6fca0003c7e13bafba31 (diff) | |
download | NetworkManager-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.c | 6 | ||||
-rw-r--r-- | src/supplicant/nm-supplicant-interface.c | 92 | ||||
-rw-r--r-- | src/supplicant/nm-supplicant-interface.h | 9 |
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); |