From c898594c717e0423e7b769364feb5fc231f9682d Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Thu, 12 Oct 2017 15:43:09 +0200 Subject: [PATCH] tui: improve tracking of activation state nmtui determines the activation result by tracking the active connection state but that is not enough, as the active connection may disappear or because we need to consider also the device state in some particular cases. Use the same logic implemented in nmcli that is now provided by the nmc_activation_get_effective_state() helper. --- clients/tui/nmtui-connect.c | 74 ++++++++++++++++++++++++++----------- 1 file changed, 53 insertions(+), 21 deletions(-) diff --git a/clients/tui/nmtui-connect.c b/clients/tui/nmtui-connect.c index ddabcd72ac..086e4bd3fb 100644 --- a/clients/tui/nmtui-connect.c +++ b/clients/tui/nmtui-connect.c @@ -36,6 +36,7 @@ #include "nmt-password-dialog.h" #include "nm-secret-agent-simple.h" #include "nm-vpn-helpers.h" +#include "nm-client-utils.h" #include "nmt-utils.h" /** @@ -148,38 +149,60 @@ secrets_requested (NMSecretAgentSimple *agent, g_object_unref (form); } +typedef struct { + NMDevice *device; + NMActiveConnection *active; + NmtSyncOp *op; +} ActivateConnectionInfo; + static void connect_cancelled (NmtNewtForm *form, gpointer user_data) { - NmtSyncOp *op = user_data; + ActivateConnectionInfo *info = user_data; GError *error = NULL; error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_CANCELLED, "Cancelled"); - nmt_sync_op_complete_boolean (op, FALSE, error); + nmt_sync_op_complete_boolean (info->op, FALSE, error); g_clear_error (&error); } +static void +check_activated (ActivateConnectionInfo *info) +{ + NMActiveConnectionState ac_state; + const char *reason = NULL; + gs_free_error GError *error = NULL; + + ac_state = nmc_activation_get_effective_state (info->active, info->device, &reason); + if (!NM_IN_SET (ac_state, + NM_ACTIVE_CONNECTION_STATE_ACTIVATED, + NM_ACTIVE_CONNECTION_STATE_DEACTIVATED)) + return; + + if (ac_state == NM_ACTIVE_CONNECTION_STATE_DEACTIVATED) { + nm_assert (reason); + error = g_error_new (NM_CLIENT_ERROR, NM_CLIENT_ERROR_FAILED, + _("Activation failed: %s"), reason); + } + + nmt_sync_op_complete_boolean (info->op, error == NULL, error); +} + static void activate_ac_state_changed (GObject *object, GParamSpec *pspec, gpointer user_data) { - NmtSyncOp *op = user_data; - NMActiveConnectionState state; - GError *error = NULL; + check_activated (user_data); +} - state = nm_active_connection_get_state (NM_ACTIVE_CONNECTION (object)); - if (state == NM_ACTIVE_CONNECTION_STATE_ACTIVATING) - return; - - if (state != NM_ACTIVE_CONNECTION_STATE_ACTIVATED) { - error = g_error_new_literal (NM_CLIENT_ERROR, NM_CLIENT_ERROR_FAILED, - _("Activation failed")); - } - - nmt_sync_op_complete_boolean (op, error == NULL, error); - g_clear_error (&error); +static void +activate_device_state_changed (GObject *object, + GParamSpec *pspec, + gpointer user_data) +{ + check_activated (user_data); } static void @@ -226,6 +249,7 @@ activate_connection (NMConnection *connection, const char *specific_object_path; NMActiveConnection *ac; GError *error = NULL; + ActivateConnectionInfo info = { }; form = g_object_new (NMT_TYPE_NEWT_FORM, "escape-exits", TRUE, @@ -290,12 +314,18 @@ activate_connection (NMConnection *connection, /* Now wait for the connection to actually reach the ACTIVATED state, * allowing the user to cancel if it takes too long. */ - nmt_sync_op_init (&op); + info.active = ac; + info.device = device; + info.op = &op; - g_signal_connect (form, "quit", G_CALLBACK (connect_cancelled), &op); + g_signal_connect (form, "quit", G_CALLBACK (connect_cancelled), &info); g_signal_connect (ac, "notify::" NM_ACTIVE_CONNECTION_STATE, - G_CALLBACK (activate_ac_state_changed), &op); + G_CALLBACK (activate_ac_state_changed), &info); + if (device) { + g_signal_connect (device, "notify::" NM_DEVICE_STATE, + G_CALLBACK (activate_device_state_changed), &info); + } if (!nmt_sync_op_wait_boolean (&op, &error)) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) @@ -303,8 +333,10 @@ activate_connection (NMConnection *connection, g_clear_error (&error); } - g_signal_handlers_disconnect_by_func (form, G_CALLBACK (connect_cancelled), &op); - g_signal_handlers_disconnect_by_func (ac, G_CALLBACK (activate_ac_state_changed), &op); + g_signal_handlers_disconnect_by_func (form, G_CALLBACK (connect_cancelled), &info); + g_signal_handlers_disconnect_by_func (ac, G_CALLBACK (activate_ac_state_changed), &info); + if (device) + g_signal_handlers_disconnect_by_func (device, G_CALLBACK (activate_device_state_changed), &info); done: if (nmt_newt_widget_get_realized (NMT_NEWT_WIDGET (form)))