active-connection: emit a StateChanged signal on state changes

It includes a reason code that makes it possible for the clients to be
more reasonable about error messages.

The reason code is essentially copied from the VPN, plus three more
reasons that were useful for non-VPN connections.
This commit is contained in:
Lubomir Rintel 2017-03-05 15:30:24 +01:00
parent 67688fd2e5
commit 8b649a8c84
9 changed files with 113 additions and 11 deletions

View file

@ -80,6 +80,20 @@
-->
<property name="State" type="u" access="read"/>
<!--
StateChanged:
@state: (<link linkend="NMActiveConnectionState">NMActiveConnectionState</link>) The new state of the active connection.
@reason: (<link linkend="NMActiveConnectionStateReason">NMActiveConnectionStateReason</link>) Reason code describing the change to the new state.
Emitted when the state of the active connection has changed.
Since: 1.8
-->
<signal name="StateChanged">
<arg name="state" type="u"/>
<arg name="reason" type="u"/>
</signal>
<!--
Default:

View file

@ -30,6 +30,7 @@
#ifndef NM_VERSION_H
#define NM_AVAILABLE_IN_1_2
#define NM_AVAILABLE_IN_1_8
#endif
/*
@ -640,6 +641,62 @@ typedef enum {
NM_ACTIVE_CONNECTION_STATE_DEACTIVATED = 4,
} NMActiveConnectionState;
/**
* NMActiveConnectionStateReason:
* @NM_ACTIVE_CONNECTION_STATE_REASON_UNKNOWN: The reason for the active connection
* state change is unknown.
* @NM_ACTIVE_CONNECTION_STATE_REASON_NONE: No reason was given for the active
* connection state change.
* @NM_ACTIVE_CONNECTION_STATE_REASON_USER_DISCONNECTED: The active connection changed
* state because the user disconnected it.
* @NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED: The active connection
* changed state because the device it was using was disconnected.
* @NM_ACTIVE_CONNECTION_STATE_REASON_SERVICE_STOPPED: The service providing the
* VPN connection was stopped.
* @NM_ACTIVE_CONNECTION_STATE_REASON_IP_CONFIG_INVALID: The IP config of the active
* connection was invalid.
* @NM_ACTIVE_CONNECTION_STATE_REASON_CONNECT_TIMEOUT: The connection attempt to
* the VPN service timed out.
* @NM_ACTIVE_CONNECTION_STATE_REASON_SERVICE_START_TIMEOUT: A timeout occurred
* while starting the service providing the VPN connection.
* @NM_ACTIVE_CONNECTION_STATE_REASON_SERVICE_START_FAILED: Starting the service
* providing the VPN connection failed.
* @NM_ACTIVE_CONNECTION_STATE_REASON_NO_SECRETS: Necessary secrets for the
* connection were not provided.
* @NM_ACTIVE_CONNECTION_STATE_REASON_LOGIN_FAILED: Authentication to the
* server failed.
* @NM_ACTIVE_CONNECTION_STATE_REASON_CONNECTION_REMOVED: The connection was
* deleted from settings.
* @NM_ACTIVE_CONNECTION_STATE_REASON_DEPENDENCY_FAILED: Master connection of this
* connection failed to activate.
* @NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_REALIZE_FAILED: Could not create the
* software device link.
* @NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_REMOVED: The device this connection
* depended on disappeared.
*
* Active connection state reasons.
*
* Since: 1.8
*/
NM_AVAILABLE_IN_1_8
typedef enum {
NM_ACTIVE_CONNECTION_STATE_REASON_UNKNOWN = 0,
NM_ACTIVE_CONNECTION_STATE_REASON_NONE = 1,
NM_ACTIVE_CONNECTION_STATE_REASON_USER_DISCONNECTED = 2,
NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED = 3,
NM_ACTIVE_CONNECTION_STATE_REASON_SERVICE_STOPPED = 4,
NM_ACTIVE_CONNECTION_STATE_REASON_IP_CONFIG_INVALID = 5,
NM_ACTIVE_CONNECTION_STATE_REASON_CONNECT_TIMEOUT = 6,
NM_ACTIVE_CONNECTION_STATE_REASON_SERVICE_START_TIMEOUT = 7,
NM_ACTIVE_CONNECTION_STATE_REASON_SERVICE_START_FAILED = 8,
NM_ACTIVE_CONNECTION_STATE_REASON_NO_SECRETS = 9,
NM_ACTIVE_CONNECTION_STATE_REASON_LOGIN_FAILED = 10,
NM_ACTIVE_CONNECTION_STATE_REASON_CONNECTION_REMOVED = 11,
NM_ACTIVE_CONNECTION_STATE_REASON_DEPENDENCY_FAILED = 12,
NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_REALIZE_FAILED = 13,
NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_REMOVED = 14,
} NMActiveConnectionStateReason;
/**
* NMSecretAgentGetSecretsFlags:
* @NM_SECRET_AGENT_GET_SECRETS_FLAG_NONE: no special behavior; by default no
@ -693,6 +750,7 @@ typedef enum /*< flags >*/ {
#ifndef NM_VERSION_H
#undef NM_AVAILABLE_IN_1_2
#undef NM_AVAILABLE_IN_1_8
#endif
#define NM_LLDP_ATTR_DESTINATION "destination"

View file

@ -1146,6 +1146,7 @@ global:
libnm_1_8_0 {
global:
nm_active_connection_state_reason_get_type;
nm_connection_get_setting_dummy;
nm_device_dummy_get_type;
nm_ip_route_get_variant_attribute_spec;

View file

@ -9029,7 +9029,9 @@ static void
_clear_queued_act_request (NMDevicePrivate *priv)
{
if (priv->queued_act_request) {
nm_active_connection_set_state ((NMActiveConnection *) priv->queued_act_request, NM_ACTIVE_CONNECTION_STATE_DEACTIVATED);
nm_active_connection_set_state ((NMActiveConnection *) priv->queued_act_request,
NM_ACTIVE_CONNECTION_STATE_DEACTIVATED,
NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED);
g_clear_object (&priv->queued_act_request);
}
}

View file

@ -397,6 +397,7 @@ device_state_changed (NMActiveConnection *active,
{
NMActiveConnectionState cur_ac_state = nm_active_connection_get_state (active);
NMActiveConnectionState ac_state = NM_ACTIVE_CONNECTION_STATE_UNKNOWN;
NMActiveConnectionStateReason ac_state_reason = NM_ACTIVE_CONNECTION_STATE_REASON_UNKNOWN;
/* Decide which device state changes to handle when this active connection
* is not the device's current request. Two cases here: (a) the AC is
@ -451,6 +452,7 @@ device_state_changed (NMActiveConnection *active,
case NM_DEVICE_STATE_UNMANAGED:
case NM_DEVICE_STATE_UNAVAILABLE:
ac_state = NM_ACTIVE_CONNECTION_STATE_DEACTIVATED;
ac_state_reason = NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED;
g_signal_handlers_disconnect_by_func (device, G_CALLBACK (device_notify), active);
break;
@ -464,7 +466,7 @@ device_state_changed (NMActiveConnection *active,
nm_active_connection_set_default6 (active, FALSE);
}
nm_active_connection_set_state (active, ac_state);
nm_active_connection_set_state (active, ac_state, ac_state_reason);
}
static void
@ -486,7 +488,9 @@ master_failed (NMActiveConnection *self)
}
/* If no device, or the device wasn't active, just move to deactivated state */
nm_active_connection_set_state (self, NM_ACTIVE_CONNECTION_STATE_DEACTIVATED);
nm_active_connection_set_state (self,
NM_ACTIVE_CONNECTION_STATE_DEACTIVATED,
NM_ACTIVE_CONNECTION_STATE_REASON_DEPENDENCY_FAILED);
}
/*****************************************************************************/

View file

@ -95,6 +95,7 @@ enum {
DEVICE_CHANGED,
DEVICE_METERED_CHANGED,
PARENT_ACTIVE,
STATE_CHANGED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0 };
@ -209,7 +210,8 @@ nm_active_connection_get_state (NMActiveConnection *self)
void
nm_active_connection_set_state (NMActiveConnection *self,
NMActiveConnectionState new_state)
NMActiveConnectionState new_state,
NMActiveConnectionStateReason reason)
{
NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
NMActiveConnectionState old_state;
@ -236,6 +238,7 @@ nm_active_connection_set_state (NMActiveConnection *self,
old_state = priv->state;
priv->state = new_state;
priv->state_set = TRUE;
g_signal_emit (self, signals[STATE_CHANGED], 0, new_state, reason);
_notify (self, PROP_STATE);
check_master_ready (self);
@ -1418,6 +1421,13 @@ nm_active_connection_class_init (NMActiveConnectionClass *ac_class)
NULL, NULL, NULL,
G_TYPE_NONE, 1, NM_TYPE_ACTIVE_CONNECTION);
signals[STATE_CHANGED] =
g_signal_new (NM_ACTIVE_CONNECTION_STATE_CHANGED,
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
0, NULL, NULL, NULL,
G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (ac_class),
NMDBUS_TYPE_ACTIVE_CONNECTION_SKELETON,
NULL);

View file

@ -57,6 +57,9 @@
#define NM_ACTIVE_CONNECTION_INT_MASTER_READY "int-master-ready"
#define NM_ACTIVE_CONNECTION_INT_ACTIVATION_TYPE "int-activation-type"
/* Signals */
#define NM_ACTIVE_CONNECTION_STATE_CHANGED "state-changed"
/* Internal signals*/
#define NM_ACTIVE_CONNECTION_DEVICE_CHANGED "device-changed"
#define NM_ACTIVE_CONNECTION_DEVICE_METERED_CHANGED "device-metered-changed"
@ -139,7 +142,8 @@ gboolean nm_active_connection_get_default6 (NMActiveConnection *self);
NMActiveConnectionState nm_active_connection_get_state (NMActiveConnection *self);
void nm_active_connection_set_state (NMActiveConnection *self,
NMActiveConnectionState state);
NMActiveConnectionState state,
NMActiveConnectionStateReason reason);
NMDevice * nm_active_connection_get_device (NMActiveConnection *self);

View file

@ -3061,12 +3061,16 @@ active_connection_parent_active (NMActiveConnection *active,
} else {
_LOGW (LOGD_CORE, "Could not realize device '%s': %s",
nm_device_get_iface (device), error->message);
nm_active_connection_set_state (active, NM_ACTIVE_CONNECTION_STATE_DEACTIVATED);
nm_active_connection_set_state (active,
NM_ACTIVE_CONNECTION_STATE_DEACTIVATED,
NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_REALIZE_FAILED);
}
} else {
_LOGW (LOGD_CORE, "The parent connection device '%s' depended on disappeared.",
nm_device_get_iface (device));
nm_active_connection_set_state (active, NM_ACTIVE_CONNECTION_STATE_DEACTIVATED);
nm_active_connection_set_state (active,
NM_ACTIVE_CONNECTION_STATE_DEACTIVATED,
NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_REMOVED);
}
}
@ -3396,8 +3400,12 @@ _internal_activation_failed (NMManager *self,
error_desc);
if (nm_active_connection_get_state (active) <= NM_ACTIVE_CONNECTION_STATE_ACTIVATED) {
nm_active_connection_set_state (active, NM_ACTIVE_CONNECTION_STATE_DEACTIVATING);
nm_active_connection_set_state (active, NM_ACTIVE_CONNECTION_STATE_DEACTIVATED);
nm_active_connection_set_state (active,
NM_ACTIVE_CONNECTION_STATE_DEACTIVATING,
NM_ACTIVE_CONNECTION_STATE_REASON_UNKNOWN);
nm_active_connection_set_state (active,
NM_ACTIVE_CONNECTION_STATE_DEACTIVATED,
NM_ACTIVE_CONNECTION_STATE_REASON_UNKNOWN);
}
}

View file

@ -447,7 +447,7 @@ dispatcher_pre_down_done (guint call_id, gpointer user_data)
NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (self);
priv->dispatcher_id = 0;
_set_vpn_state (self, STATE_DISCONNECTED, NM_VPN_CONNECTION_STATE_REASON_NONE, FALSE);
_set_vpn_state (self, STATE_DISCONNECTED, NM_VPN_CONNECTION_STATE_REASON_USER_DISCONNECTED, FALSE);
}
static void
@ -500,7 +500,8 @@ _set_vpn_state (NMVpnConnection *self,
/* Update active connection base class state */
nm_active_connection_set_state (NM_ACTIVE_CONNECTION (self),
_state_to_ac_state (vpn_state));
_state_to_ac_state (vpn_state),
(NMActiveConnectionStateReason) reason);
/* Clear any in-progress secrets request */
cancel_get_secrets (self);