diff --git a/src/vpn-manager/nm-vpn-connection.c b/src/vpn-manager/nm-vpn-connection.c index 770b064f38..dcd45817ab 100644 --- a/src/vpn-manager/nm-vpn-connection.c +++ b/src/vpn-manager/nm-vpn-connection.c @@ -84,7 +84,9 @@ typedef struct { char *username; VpnState vpn_state; + guint deactivating_idle_id; NMVPNConnectionStateReason failure_reason; + DBusGProxy *proxy; GHashTable *connect_hash; guint connect_timeout; @@ -133,6 +135,10 @@ static void plugin_interactive_secrets_required (DBusGProxy *proxy, const char **secrets, gpointer user_data); +static void _set_vpn_state (NMVPNConnection *connection, + VpnState vpn_state, + NMVPNConnectionStateReason reason); + /*********************************************************************/ static NMVPNConnectionState @@ -239,6 +245,28 @@ vpn_cleanup (NMVPNConnection *connection, NMDevice *parent_dev) nm_connection_clear_secrets (priv->connection); } +static gboolean +deactivating_to_disconnected (gpointer user_data) +{ + NMVPNConnection *self = NM_VPN_CONNECTION (user_data); + NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (self); + + priv->deactivating_idle_id = 0; + _set_vpn_state (self, STATE_DISCONNECTED, NM_VPN_CONNECTION_STATE_REASON_NONE); + return G_SOURCE_REMOVE; +} + +static void +clear_deactivating_idle (NMVPNConnection *self) +{ + NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (self); + + if (priv->deactivating_idle_id) { + g_source_remove (priv->deactivating_idle_id); + priv->deactivating_idle_id = 0; + } +} + static void _set_vpn_state (NMVPNConnection *connection, VpnState vpn_state, @@ -275,6 +303,8 @@ _set_vpn_state (NMVPNConnection *connection, priv->secrets_id = 0; } + clear_deactivating_idle (connection); + /* The connection gets destroyed by the VPN manager when it enters the * disconnected/failed state, but we need to keep it around for a bit * to send out signals and handle the dispatcher. So ref it. @@ -313,6 +343,9 @@ _set_vpn_state (NMVPNConnection *connection, NULL, NULL); break; + case STATE_DEACTIVATING: + priv->deactivating_idle_id = g_idle_add (deactivating_to_disconnected, connection); + break; case STATE_FAILED: case STATE_DISCONNECTED: if ( old_vpn_state >= STATE_ACTIVATED @@ -1591,6 +1624,23 @@ nm_vpn_connection_disconnect (NMVPNConnection *connection, _set_vpn_state (connection, STATE_DISCONNECTED, reason); } +gboolean +nm_vpn_connection_deactivate (NMVPNConnection *connection, + NMVPNConnectionStateReason reason) +{ + NMVPNConnectionPrivate *priv; + gboolean success = FALSE; + + g_return_val_if_fail (NM_IS_VPN_CONNECTION (connection), FALSE); + + priv = NM_VPN_CONNECTION_GET_PRIVATE (connection); + if (priv->vpn_state > STATE_UNKNOWN && priv->vpn_state <= STATE_DEACTIVATING) { + _set_vpn_state (connection, STATE_DEACTIVATING, reason); + success = TRUE; + } + return success; +} + /******************************************************************************/ static void @@ -1838,6 +1888,8 @@ dispose (GObject *object) priv->connect_timeout = 0; } + clear_deactivating_idle (NM_VPN_CONNECTION (object)); + if (priv->secrets_id) { nm_settings_connection_cancel_secrets (NM_SETTINGS_CONNECTION (priv->connection), priv->secrets_id); diff --git a/src/vpn-manager/nm-vpn-connection.h b/src/vpn-manager/nm-vpn-connection.h index b98dcbe629..afa06e9c9d 100644 --- a/src/vpn-manager/nm-vpn-connection.h +++ b/src/vpn-manager/nm-vpn-connection.h @@ -74,10 +74,14 @@ void nm_vpn_connection_activate (NMVPNConnection *connect NMConnection * nm_vpn_connection_get_connection (NMVPNConnection *connection); NMVPNConnectionState nm_vpn_connection_get_vpn_state (NMVPNConnection *connection); const char * nm_vpn_connection_get_banner (NMVPNConnection *connection); + +gboolean nm_vpn_connection_deactivate (NMVPNConnection *connection, + NMVPNConnectionStateReason reason); void nm_vpn_connection_fail (NMVPNConnection *connection, NMVPNConnectionStateReason reason); void nm_vpn_connection_disconnect (NMVPNConnection *connection, NMVPNConnectionStateReason reason); + NMIP4Config * nm_vpn_connection_get_ip4_config (NMVPNConnection *connection); NMIP6Config * nm_vpn_connection_get_ip6_config (NMVPNConnection *connection); const char * nm_vpn_connection_get_ip_iface (NMVPNConnection *connection); diff --git a/src/vpn-manager/nm-vpn-manager.c b/src/vpn-manager/nm-vpn-manager.c index 7fa753a39c..bee31dbc2c 100644 --- a/src/vpn-manager/nm-vpn-manager.c +++ b/src/vpn-manager/nm-vpn-manager.c @@ -156,32 +156,7 @@ nm_vpn_manager_deactivate_connection (NMVPNManager *self, NMVPNConnection *connection, NMVPNConnectionStateReason reason) { - NMVPNManagerPrivate *priv; - GHashTableIter iter; - gpointer data; - const GSList *active, *aiter; - gboolean success = FALSE; - - g_return_val_if_fail (self, FALSE); - g_return_val_if_fail (NM_IS_VPN_MANAGER (self), FALSE); - g_return_val_if_fail (connection != NULL, FALSE); - - priv = NM_VPN_MANAGER_GET_PRIVATE (self); - g_hash_table_iter_init (&iter, priv->services); - while (g_hash_table_iter_next (&iter, NULL, &data) && (success == FALSE)) { - active = nm_vpn_service_get_active_connections (NM_VPN_SERVICE (data)); - for (aiter = active; aiter; aiter = g_slist_next (aiter)) { - NMVPNConnection *candidate = aiter->data; - - if (connection == candidate) { - nm_vpn_connection_disconnect (connection, reason); - success = TRUE; - break; - } - } - } - - return success; + return nm_vpn_connection_deactivate (connection, reason); } static void