From 0ca2796d60e8fa60e63af3fdeca5499cbbf6fed7 Mon Sep 17 00:00:00 2001 From: Andy Kling Date: Thu, 21 Feb 2019 11:06:55 +0100 Subject: [PATCH] supplicant-interface: add async disconnect allow to call dbus method "Disconnect" and handle a callback given by the caller. This allows graceful disconnects that require to wait for the operation to complete. --- src/supplicant/nm-supplicant-interface.c | 60 ++++++++++++++++++++++++ src/supplicant/nm-supplicant-interface.h | 10 ++++ 2 files changed, 70 insertions(+) diff --git a/src/supplicant/nm-supplicant-interface.c b/src/supplicant/nm-supplicant-interface.c index 1c92b9a74..124e21678 100644 --- a/src/supplicant/nm-supplicant-interface.c +++ b/src/supplicant/nm-supplicant-interface.c @@ -80,6 +80,12 @@ typedef struct _AddNetworkData { AssocData *assoc_data; } AddNetworkData; +typedef struct { + NMSupplicantInterface *self; + NMSupplicantInterfaceDisconnectCb callback; + gpointer user_data; +} DisconnectData; + enum { STATE, /* change in the interface's state */ REMOVED, /* interface was removed by the supplicant */ @@ -2150,6 +2156,60 @@ nm_supplicant_interface_disconnect (NMSupplicantInterface * self) nm_supplicant_interface_cancel_wps (self); } +static void +disconnect_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) +{ + DisconnectData *disconnect_data = user_data; + gs_unref_object NMSupplicantInterface *self = disconnect_data->self; + gs_unref_variant GVariant *reply = NULL; + gs_free_error GError *error = NULL; + + reply = g_dbus_proxy_call_finish (proxy, result, &error); + + /* an already disconnected interface is not an error*/ + if ( !reply + && !strstr (error->message, "fi.w1.wpa_supplicant1.NotConnected")) { + g_clear_error(&error); + } + + disconnect_data->callback(self, error, disconnect_data->user_data); + g_slice_free (DisconnectData, disconnect_data); +} + +void +nm_supplicant_interface_disconnect_async ( NMSupplicantInterface * self, + GCancellable * cancellable, + NMSupplicantInterfaceDisconnectCb callback, + gpointer user_data) +{ + NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); + DisconnectData *disconnect_data; + + /* Don't do anything if there is no connection to the supplicant yet. */ + if (!priv->iface_proxy) + return; + + g_return_if_fail (NM_IS_SUPPLICANT_INTERFACE (self)); + g_return_if_fail (NULL != callback); + + disconnect_data = g_slice_new0(DisconnectData); + + /* Keep interface alive until disconnect finishes */ + disconnect_data->self = g_object_ref (self); + disconnect_data->callback = callback; + disconnect_data->user_data = user_data; + + /* Disconnect the interface */ + g_dbus_proxy_call (priv->iface_proxy, + "Disconnect", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + (GAsyncReadyCallback) disconnect_cb, + disconnect_data); +} + static void assoc_select_network_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) { diff --git a/src/supplicant/nm-supplicant-interface.h b/src/supplicant/nm-supplicant-interface.h index 8e9eede6f..d6d226cbb 100644 --- a/src/supplicant/nm-supplicant-interface.h +++ b/src/supplicant/nm-supplicant-interface.h @@ -116,6 +116,16 @@ nm_supplicant_interface_assoc (NMSupplicantInterface *self, void nm_supplicant_interface_disconnect (NMSupplicantInterface * iface); +typedef void (*NMSupplicantInterfaceDisconnectCb) (NMSupplicantInterface *iface, + GError *error, + gpointer user_data); + +void +nm_supplicant_interface_disconnect_async (NMSupplicantInterface * self, + GCancellable * cancellable, + NMSupplicantInterfaceDisconnectCb callback, + gpointer user_data); + const char *nm_supplicant_interface_get_object_path (NMSupplicantInterface * iface); void nm_supplicant_interface_request_scan (NMSupplicantInterface *self,