From 8252357dd1796dd6123a56a10356d0c5496e885b Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 28 Aug 2013 09:08:43 -0500 Subject: core: watch master ActiveConnections and follow master deactivation --- src/nm-activation-request.c | 24 ++++++++++++++++++++++++ src/nm-active-connection.c | 30 ++++++++++++++++++++++++++++++ src/nm-active-connection.h | 2 ++ src/vpn-manager/nm-vpn-connection.c | 13 +++++++++++++ 4 files changed, 69 insertions(+) diff --git a/src/nm-activation-request.c b/src/nm-activation-request.c index ce9ee7da82..61d7782d44 100644 --- a/src/nm-activation-request.c +++ b/src/nm-activation-request.c @@ -334,6 +334,28 @@ device_state_changed (NMDevice *device, GParamSpec *pspec, NMActRequest *self) nm_active_connection_set_state (NM_ACTIVE_CONNECTION (self), ac_state); } +static void +master_failed (NMActiveConnection *self) +{ + NMDevice *device; + NMDeviceState device_state; + + /* If the connection has an active device, fail it */ + device = nm_active_connection_get_device (self); + if (device) { + device_state = nm_device_get_state (device); + if (nm_device_is_activating (device) || (device_state == NM_DEVICE_STATE_ACTIVATED)) { + nm_device_state_changed (device, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED); + return; + } + } + + /* 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); +} + /********************************************************************/ /** @@ -426,11 +448,13 @@ static void nm_act_request_class_init (NMActRequestClass *req_class) { GObjectClass *object_class = G_OBJECT_CLASS (req_class); + NMActiveConnectionClass *active_class = NM_ACTIVE_CONNECTION_CLASS (req_class); g_type_class_add_private (req_class, sizeof (NMActRequestPrivate)); /* virtual methods */ object_class->constructed = constructed; object_class->dispose = dispose; + active_class->master_failed = master_failed; } diff --git a/src/nm-active-connection.c b/src/nm-active-connection.c index d24c621272..f811dee82f 100644 --- a/src/nm-active-connection.c +++ b/src/nm-active-connection.c @@ -265,6 +265,26 @@ nm_active_connection_get_master (NMActiveConnection *self) return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->master; } +static void +master_state_cb (NMActiveConnection *master, + GParamSpec *pspec, + gpointer user_data) +{ + NMActiveConnection *self = NM_ACTIVE_CONNECTION (user_data); + NMActiveConnectionState self_state = nm_active_connection_get_state (self); + NMActiveConnectionState master_state = nm_active_connection_get_state (master); + + /* Master is deactivating, so this active connection must also deactivate */ + if (self_state < NM_ACTIVE_CONNECTION_STATE_DEACTIVATING && + master_state >= NM_ACTIVE_CONNECTION_STATE_DEACTIVATING) { + g_signal_handlers_disconnect_by_func (master, + (GCallback) master_state_cb, + self); + if (NM_ACTIVE_CONNECTION_GET_CLASS (self)->master_failed) + NM_ACTIVE_CONNECTION_GET_CLASS (self)->master_failed (self); + } +} + /** * nm_active_connection_set_master: * @self: the #NMActiveConnection @@ -294,6 +314,10 @@ nm_active_connection_set_master (NMActiveConnection *self, NMActiveConnection *m g_return_if_fail (master_device != priv->device); priv->master = g_object_ref (master); + g_signal_connect (priv->master, + "notify::" NM_ACTIVE_CONNECTION_STATE, + (GCallback) master_state_cb, + self); } /****************************************************************/ @@ -530,6 +554,12 @@ dispose (GObject *object) g_clear_object (&priv->connection); g_clear_object (&priv->device); + + if (priv->master) { + g_signal_handlers_disconnect_by_func (priv->master, + (GCallback) master_state_cb, + NM_ACTIVE_CONNECTION (object)); + } g_clear_object (&priv->master); g_clear_object (&priv->subject); diff --git a/src/nm-active-connection.h b/src/nm-active-connection.h index 93723c904e..1605c3963a 100644 --- a/src/nm-active-connection.h +++ b/src/nm-active-connection.h @@ -56,6 +56,8 @@ typedef struct { typedef struct { GObjectClass parent; + + void (*master_failed) (NMActiveConnection *connection); } NMActiveConnectionClass; GType nm_active_connection_get_type (void); diff --git a/src/vpn-manager/nm-vpn-connection.c b/src/vpn-manager/nm-vpn-connection.c index 129123acdb..ec66732d2f 100644 --- a/src/vpn-manager/nm-vpn-connection.c +++ b/src/vpn-manager/nm-vpn-connection.c @@ -295,6 +295,17 @@ device_state_changed (NMDevice *device, } } +static void +master_failed (NMActiveConnection *self) +{ + NMVPNConnection *connection = NM_VPN_CONNECTION (self); + + /* Master failure fails the VPN */ + nm_vpn_connection_set_vpn_state (connection, + NM_VPN_CONNECTION_STATE_FAILED, + NM_VPN_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED); +} + static void add_ip4_vpn_gateway_route (NMDevice *parent_device, guint32 vpn_gw) { @@ -1768,6 +1779,7 @@ static void nm_vpn_connection_class_init (NMVPNConnectionClass *connection_class) { GObjectClass *object_class = G_OBJECT_CLASS (connection_class); + NMActiveConnectionClass *active_class = NM_ACTIVE_CONNECTION_CLASS (connection_class); g_type_class_add_private (connection_class, sizeof (NMVPNConnectionPrivate)); @@ -1776,6 +1788,7 @@ nm_vpn_connection_class_init (NMVPNConnectionClass *connection_class) object_class->constructed = constructed; object_class->dispose = dispose; object_class->finalize = finalize; + active_class->master_failed = master_failed; g_object_class_override_property (object_class, PROP_MASTER, NM_ACTIVE_CONNECTION_MASTER); -- cgit v1.2.1