summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2020-04-24 19:34:44 +0200
committerThomas Haller <thaller@redhat.com>2020-04-24 19:34:44 +0200
commitfe84237cf09b29a99d70580044694c1aa7ff1a16 (patch)
tree8067197fbb8246324f884e38f24472ef2aed6f10
parent93b634f1a23c43dd71c3b7668ae738c3ab6c970e (diff)
parent16c1869476106859b684151eb1b101c24cff3451 (diff)
downloadNetworkManager-fe84237cf09b29a99d70580044694c1aa7ff1a16.tar.gz
wifi: merge branch 'th/cli-trigger-scan-retry'
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/476
-rw-r--r--clients/cli/devices.c57
-rw-r--r--shared/nm-glib-aux/nm-shared-utils.c103
-rw-r--r--shared/nm-glib-aux/nm-shared-utils.h13
-rw-r--r--src/devices/bluetooth/nm-bluez-manager.c6
-rw-r--r--src/devices/ovs/nm-device-ovs-interface.c2
-rw-r--r--src/devices/wifi/nm-device-iwd.c2
-rw-r--r--src/devices/wifi/nm-device-wifi.c8
-rw-r--r--src/devices/wwan/nm-modem-broadband.c6
-rw-r--r--src/devices/wwan/nm-modem-ofono.c6
-rw-r--r--src/platform/nm-linux-platform.c8
-rw-r--r--src/supplicant/nm-supplicant-interface.c109
-rw-r--r--src/supplicant/nm-supplicant-interface.h9
12 files changed, 253 insertions, 76 deletions
diff --git a/clients/cli/devices.c b/clients/cli/devices.c
index 4ea4e772e4..7031b43756 100644
--- a/clients/cli/devices.c
+++ b/clients/cli/devices.c
@@ -2978,6 +2978,24 @@ wifi_last_scan_updated (GObject *gobject, GParamSpec *pspec, gpointer user_data)
wifi_list_finish (user_data, FALSE);
}
+static void wifi_list_rescan_cb (GObject *source_object, GAsyncResult *res, gpointer user_data);
+
+static void
+wifi_list_rescan_retry_cb (gpointer user_data,
+ GCancellable *cancellable)
+{
+ WifiListData *wifi_list_data;
+
+ if (g_cancellable_is_cancelled (cancellable))
+ return;
+
+ wifi_list_data = user_data;
+ nm_device_wifi_request_scan_async (wifi_list_data->wifi,
+ wifi_list_data->scan_cancellable,
+ wifi_list_rescan_cb,
+ wifi_list_data);
+}
+
static void
wifi_list_rescan_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
{
@@ -2985,22 +3003,47 @@ wifi_list_rescan_cb (GObject *source_object, GAsyncResult *res, gpointer user_da
gs_free_error GError *error = NULL;
WifiListData *wifi_list_data;
gboolean force_finished;
+ gboolean done;
nm_device_wifi_request_scan_finish (wifi, res, &error);
if (nm_utils_error_is_cancelled (error))
return;
+ wifi_list_data = user_data;
+
if (g_error_matches (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_NOT_ALLOWED)) {
- /* This likely means that scanning is already in progress. There's
- * a good chance we'll get updated results soon; wait for them. */
- force_finished = FALSE;
- } else if (error)
+ if (nm_device_get_state (NM_DEVICE (wifi)) < NM_DEVICE_STATE_DISCONNECTED) {
+ /* the device is either unmanaged or unavailable.
+ *
+ * If it's unmanaged, we don't expect any scan result and are done.
+ * If it's unavailable, that usually means that we wait for wpa_supplicant
+ * to start. In that case, also quit (without scan results). */
+ force_finished = TRUE;
+ done = TRUE;
+ } else {
+ /* This likely means that scanning is already in progress. There's
+ * a good chance we'll get updated results soon; wait for them.
+ *
+ * But also, NetworkManager ratelimits (and rejects requests). That
+ * means, possibly we were just ratelimited, so waiting will not lead
+ * to a new scan result. Instead, repeatedly ask new scans... */
+ nm_utils_invoke_on_timeout (1000,
+ wifi_list_data->scan_cancellable,
+ wifi_list_rescan_retry_cb,
+ wifi_list_data);
+ force_finished = FALSE;
+ done = FALSE;
+ }
+ } else if (error) {
force_finished = TRUE;
- else
+ done = TRUE;
+ } else {
force_finished = FALSE;
+ done = TRUE;
+ }
- wifi_list_data = user_data;
- g_clear_object (&wifi_list_data->scan_cancellable);
+ if (done)
+ g_clear_object (&wifi_list_data->scan_cancellable);
wifi_list_finish (wifi_list_data, force_finished);
}
diff --git a/shared/nm-glib-aux/nm-shared-utils.c b/shared/nm-glib-aux/nm-shared-utils.c
index c06399dda8..61e3e26716 100644
--- a/shared/nm-glib-aux/nm-shared-utils.c
+++ b/shared/nm-glib-aux/nm-shared-utils.c
@@ -3655,9 +3655,9 @@ _nm_utils_user_data_unpack (gpointer user_data, int nargs, ...)
typedef struct {
gpointer callback_user_data;
GCancellable *cancellable;
+ GSource *source;
NMUtilsInvokeOnIdleCallback callback;
gulong cancelled_id;
- guint idle_id;
} InvokeOnIdleData;
static gboolean
@@ -3665,12 +3665,13 @@ _nm_utils_invoke_on_idle_cb_idle (gpointer user_data)
{
InvokeOnIdleData *data = user_data;
- data->idle_id = 0;
nm_clear_g_signal_handler (data->cancellable, &data->cancelled_id);
data->callback (data->callback_user_data, data->cancellable);
+
nm_g_object_unref (data->cancellable);
- g_slice_free (InvokeOnIdleData, data);
+ g_source_destroy (data->source);
+ nm_g_slice_free (data);
return G_SOURCE_REMOVE;
}
@@ -3680,41 +3681,87 @@ _nm_utils_invoke_on_idle_cb_cancelled (GCancellable *cancellable,
{
/* on cancellation, we invoke the callback synchronously. */
nm_clear_g_signal_handler (data->cancellable, &data->cancelled_id);
- nm_clear_g_source (&data->idle_id);
+ nm_clear_g_source_inst (&data->source);
data->callback (data->callback_user_data, data->cancellable);
nm_g_object_unref (data->cancellable);
- g_slice_free (InvokeOnIdleData, data);
+ nm_g_slice_free (data);
}
-void
-nm_utils_invoke_on_idle (NMUtilsInvokeOnIdleCallback callback,
- gpointer callback_user_data,
- GCancellable *cancellable)
+static void
+_nm_utils_invoke_on_idle_start (gboolean use_timeout,
+ guint timeout_msec,
+ GCancellable *cancellable,
+ NMUtilsInvokeOnIdleCallback callback,
+ gpointer callback_user_data)
{
InvokeOnIdleData *data;
+ GSource *source;
g_return_if_fail (callback);
data = g_slice_new (InvokeOnIdleData);
- data->callback = callback;
- data->callback_user_data = callback_user_data;
- data->cancellable = nm_g_object_ref (cancellable);
- if ( cancellable
- && !g_cancellable_is_cancelled (cancellable)) {
- /* if we are passed a non-cancelled cancellable, we register to the "cancelled"
- * signal an invoke the callback synchronously (from the signal handler).
- *
- * We don't do that,
- * - if the cancellable is already cancelled (because we don't want to invoke
- * the callback synchronously from the caller).
- * - if we have no cancellable at hand. */
- data->cancelled_id = g_signal_connect (cancellable,
- "cancelled",
- G_CALLBACK (_nm_utils_invoke_on_idle_cb_cancelled),
- data);
- } else
- data->cancelled_id = 0;
- data->idle_id = g_idle_add (_nm_utils_invoke_on_idle_cb_idle, data);
+ *data = (InvokeOnIdleData) {
+ .callback = callback,
+ .callback_user_data = callback_user_data,
+ .cancellable = nm_g_object_ref (cancellable),
+ .cancelled_id = 0,
+ };
+
+ if (cancellable) {
+ if (g_cancellable_is_cancelled (cancellable)) {
+ /* the cancellable is already cancelled. We ignore the timeout
+ * and always schedule an idle action. */
+ use_timeout = FALSE;
+ } else {
+ /* if we are passed a non-cancelled cancellable, we register to the "cancelled"
+ * signal an invoke the callback synchronously (from the signal handler).
+ *
+ * We don't do that,
+ * - if the cancellable is already cancelled (because we don't want to invoke
+ * the callback synchronously from the caller).
+ * - if we have no cancellable at hand. */
+ data->cancelled_id = g_signal_connect (cancellable,
+ "cancelled",
+ G_CALLBACK (_nm_utils_invoke_on_idle_cb_cancelled),
+ data);
+ }
+ }
+
+ if (use_timeout) {
+ source = nm_g_timeout_source_new (timeout_msec,
+ G_PRIORITY_DEFAULT,
+ _nm_utils_invoke_on_idle_cb_idle,
+ data,
+ NULL);
+ } else {
+ source = nm_g_idle_source_new (G_PRIORITY_DEFAULT,
+ _nm_utils_invoke_on_idle_cb_idle,
+ data,
+ NULL);
+ }
+
+ /* use the current thread default context. */
+ g_source_attach (source,
+ g_main_context_get_thread_default ());
+
+ data->source = source;
+}
+
+void
+nm_utils_invoke_on_idle (GCancellable *cancellable,
+ NMUtilsInvokeOnIdleCallback callback,
+ gpointer callback_user_data)
+{
+ _nm_utils_invoke_on_idle_start (FALSE, 0, cancellable, callback, callback_user_data);
+}
+
+void
+nm_utils_invoke_on_timeout (guint timeout_msec,
+ GCancellable *cancellable,
+ NMUtilsInvokeOnIdleCallback callback,
+ gpointer callback_user_data)
+{
+ _nm_utils_invoke_on_idle_start (TRUE, timeout_msec, cancellable, callback, callback_user_data);
}
/*****************************************************************************/
diff --git a/shared/nm-glib-aux/nm-shared-utils.h b/shared/nm-glib-aux/nm-shared-utils.h
index 38b100416d..9200f80fdf 100644
--- a/shared/nm-glib-aux/nm-shared-utils.h
+++ b/shared/nm-glib-aux/nm-shared-utils.h
@@ -1629,12 +1629,17 @@ void _nm_utils_user_data_unpack (gpointer user_data, int nargs, ...);
/*****************************************************************************/
-typedef void (*NMUtilsInvokeOnIdleCallback) (gpointer callback_user_data,
+typedef void (*NMUtilsInvokeOnIdleCallback) (gpointer user_data,
GCancellable *cancellable);
-void nm_utils_invoke_on_idle (NMUtilsInvokeOnIdleCallback callback,
- gpointer callback_user_data,
- GCancellable *cancellable);
+void nm_utils_invoke_on_idle (GCancellable *cancellable,
+ NMUtilsInvokeOnIdleCallback callback,
+ gpointer callback_user_data);
+
+void nm_utils_invoke_on_timeout (guint timeout_msec,
+ GCancellable *cancellable,
+ NMUtilsInvokeOnIdleCallback callback,
+ gpointer callback_user_data);
/*****************************************************************************/
diff --git a/src/devices/bluetooth/nm-bluez-manager.c b/src/devices/bluetooth/nm-bluez-manager.c
index 6ff96c323b..0bbac4c435 100644
--- a/src/devices/bluetooth/nm-bluez-manager.c
+++ b/src/devices/bluetooth/nm-bluez-manager.c
@@ -1251,9 +1251,9 @@ _network_server_unregister_bridge (NMBluezManager *self,
if (r_req_data) {
nm_clear_g_cancellable (&r_req_data->int_cancellable);
- nm_utils_invoke_on_idle (_network_server_unregister_bridge_complete_on_idle_cb,
- nm_utils_user_data_pack (r_req_data, g_strdup (reason)),
- r_req_data->ext_cancellable);
+ nm_utils_invoke_on_idle (r_req_data->ext_cancellable,
+ _network_server_unregister_bridge_complete_on_idle_cb,
+ nm_utils_user_data_pack (r_req_data, g_strdup (reason)));
}
_nm_device_bridge_notify_unregister_bt_nap (device, reason);
diff --git a/src/devices/ovs/nm-device-ovs-interface.c b/src/devices/ovs/nm-device-ovs-interface.c
index 951b578892..10f9fa9431 100644
--- a/src/devices/ovs/nm-device-ovs-interface.c
+++ b/src/devices/ovs/nm-device-ovs-interface.c
@@ -310,7 +310,7 @@ deactivate_async (NMDevice *device,
nm_device_get_iface (device))) {
_LOGT (LOGD_CORE, "deactivate: link not present, proceeding");
nm_device_update_from_platform_link (NM_DEVICE (self), NULL);
- nm_utils_invoke_on_idle (deactivate_cb_on_idle, data, cancellable);
+ nm_utils_invoke_on_idle (cancellable, deactivate_cb_on_idle, data);
return;
}
diff --git a/src/devices/wifi/nm-device-iwd.c b/src/devices/wifi/nm-device-iwd.c
index 3c1d5b2298..3dccd1cb94 100644
--- a/src/devices/wifi/nm-device-iwd.c
+++ b/src/devices/wifi/nm-device-iwd.c
@@ -507,7 +507,7 @@ deactivate_async (NMDevice *device,
user_data = nm_utils_user_data_pack (g_object_ref (self), callback, callback_user_data);
if (!priv->dbus_obj) {
- nm_utils_invoke_on_idle (disconnect_cb_on_idle, user_data, cancellable);
+ nm_utils_invoke_on_idle (cancellable, disconnect_cb_on_idle, user_data);
return;
}
diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c
index 266a842514..bf3e6ad27a 100644
--- a/src/devices/wifi/nm-device-wifi.c
+++ b/src/devices/wifi/nm-device-wifi.c
@@ -684,7 +684,7 @@ deactivate_async (NMDevice *device,
user_data = nm_utils_user_data_pack (g_object_ref (self), callback, callback_user_data);
if (!priv->sup_iface) {
- nm_utils_invoke_on_idle (disconnect_cb_on_idle, user_data, cancellable);
+ nm_utils_invoke_on_idle (cancellable, disconnect_cb_on_idle, user_data);
return;
}
@@ -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/devices/wwan/nm-modem-broadband.c b/src/devices/wwan/nm-modem-broadband.c
index f89ec86c9f..3fdc5ac54b 100644
--- a/src/devices/wwan/nm-modem-broadband.c
+++ b/src/devices/wwan/nm-modem-broadband.c
@@ -1254,9 +1254,9 @@ disconnect (NMModem *modem,
/* Already cancelled or no simple-iface? We are done. */
if ( !ctx->self->_priv.simple_iface
|| g_cancellable_is_cancelled (cancellable)) {
- nm_utils_invoke_on_idle (disconnect_context_complete_on_idle,
- ctx,
- cancellable);
+ nm_utils_invoke_on_idle (cancellable,
+ disconnect_context_complete_on_idle,
+ ctx);
return;
}
diff --git a/src/devices/wwan/nm-modem-ofono.c b/src/devices/wwan/nm-modem-ofono.c
index 2fc44881a9..96b08e7cff 100644
--- a/src/devices/wwan/nm-modem-ofono.c
+++ b/src/devices/wwan/nm-modem-ofono.c
@@ -211,9 +211,9 @@ disconnect (NMModem *modem,
if ( state != NM_MODEM_STATE_CONNECTED
|| g_cancellable_is_cancelled (cancellable)) {
- nm_utils_invoke_on_idle (disconnect_context_complete_on_idle,
- ctx,
- cancellable);
+ nm_utils_invoke_on_idle (cancellable,
+ disconnect_context_complete_on_idle,
+ ctx);
return;
}
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
index f7249bb71e..014cca71da 100644
--- a/src/platform/nm-linux-platform.c
+++ b/src/platform/nm-linux-platform.c
@@ -5131,9 +5131,9 @@ sysctl_set_async (NMPlatform *platform,
callback,
data,
error);
- nm_utils_invoke_on_idle (sysctl_set_async_return_idle,
- packed,
- cancellable);
+ nm_utils_invoke_on_idle (cancellable,
+ sysctl_set_async_return_idle,
+ packed);
return;
}
} else
@@ -7390,7 +7390,7 @@ out_idle:
g_steal_pointer (&error),
callback,
data);
- nm_utils_invoke_on_idle (sriov_idle_cb, packed, cancellable);
+ nm_utils_invoke_on_idle (cancellable, sriov_idle_cb, packed);
}
}
diff --git a/src/supplicant/nm-supplicant-interface.c b/src/supplicant/nm-supplicant-interface.c
index a02f540256..099c3bf2ca 100644
--- a/src/supplicant/nm-supplicant-interface.c
+++ b/src/supplicant/nm-supplicant-interface.c
@@ -1123,7 +1123,7 @@ set_state (NMSupplicantInterface *self, NMSupplicantInterfaceState new_state)
if (new_state == priv->state)
return;
- _LOGT ("set state \"%s\" (was \"%s\")",
+ _LOGT ("state: set state \"%s\" (was \"%s\")",
nm_supplicant_interface_state_to_string (new_state),
nm_supplicant_interface_state_to_string (priv->state));
@@ -1789,8 +1789,12 @@ _properties_changed_main (NMSupplicantInterface *self,
g_variant_unref (v_v);
}
- if (nm_g_variant_lookup (properties, "Scanning", "b", &v_b))
- priv->scanning_property = v_b;
+ if (nm_g_variant_lookup (properties, "Scanning", "b", &v_b)) {
+ if (priv->scanning_property != (!!v_b)) {
+ _LOGT ("scanning: %s (plain property)", v_b ? "yes" : "no");
+ priv->scanning_property = v_b;
+ }
+ }
if (nm_g_variant_lookup (properties, "Ifname", "&s", &v_s)) {
if (nm_utils_strdup_reset (&priv->ifname, v_s))
@@ -1816,8 +1820,13 @@ _properties_changed_main (NMSupplicantInterface *self,
state = wpas_state_string_to_enum (v_s);
if (state == NM_SUPPLICANT_INTERFACE_STATE_INVALID)
- _LOGT ("ignore unknown supplicant state '%s'", v_s);
+ _LOGT ("state: ignore unknown supplicant state '%s' (is %s, plain property)",
+ v_s,
+ nm_supplicant_interface_state_to_string (priv->supp_state));
else if (priv->supp_state != state) {
+ _LOGT ("state: %s (was %s, plain property)",
+ nm_supplicant_interface_state_to_string (state),
+ nm_supplicant_interface_state_to_string (priv->supp_state));
priv->supp_state = state;
if (priv->state > NM_SUPPLICANT_INTERFACE_STATE_STARTING) {
/* Only transition to actual wpa_supplicant interface states (ie,
@@ -2328,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);
@@ -2381,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",
@@ -2388,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);