Commit 6cbbb9c0 authored by Dan Williams's avatar Dan Williams
Browse files

vpn: reconnect on service failures (bgo #349151)

Attempt to reconnect the VPN on failures, except when the underlying
device fails.

https://bugzilla.gnome.org/show_bug.cgi?id=349151
parent b11798a1
......@@ -1835,6 +1835,28 @@ vpn_connection_state_changed (NMVpnConnection *vpn,
}
}
static void
vpn_connection_retry_after_failure (NMVpnConnection *vpn, NMPolicy *policy)
{
NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy);
NMActiveConnection *ac = NM_ACTIVE_CONNECTION (vpn);
NMConnection *connection = nm_active_connection_get_connection (ac);
GError *error = NULL;
/* Attempt to reconnect VPN connections that failed after being connected */
if (!nm_manager_activate_connection (priv->manager,
connection,
NULL,
NULL,
nm_active_connection_get_subject (ac),
&error)) {
nm_log_warn (LOGD_DEVICE, "VPN '%s' reconnect failed: %s",
nm_connection_get_id (connection),
error->message ? error->message : "unknown");
g_clear_error (&error);
}
}
static void
active_connection_state_changed (NMActiveConnection *active,
GParamSpec *pspec,
......@@ -1859,6 +1881,9 @@ active_connection_added (NMManager *manager,
g_signal_connect (active, NM_VPN_CONNECTION_INTERNAL_STATE_CHANGED,
G_CALLBACK (vpn_connection_state_changed),
policy);
g_signal_connect (active, NM_VPN_CONNECTION_INTERNAL_RETRY_AFTER_FAILURE,
G_CALLBACK (vpn_connection_retry_after_failure),
policy);
}
g_signal_connect (active, "notify::" NM_ACTIVE_CONNECTION_STATE,
......@@ -1876,6 +1901,9 @@ active_connection_removed (NMManager *manager,
g_signal_handlers_disconnect_by_func (active,
vpn_connection_state_changed,
policy);
g_signal_handlers_disconnect_by_func (active,
vpn_connection_retry_after_failure,
policy);
g_signal_handlers_disconnect_by_func (active,
active_connection_state_changed,
policy);
......
......@@ -111,6 +111,7 @@ typedef struct {
enum {
VPN_STATE_CHANGED,
INTERNAL_STATE_CHANGED,
INTERNAL_RETRY_AFTER_FAILURE,
LAST_SIGNAL
};
......@@ -442,6 +443,13 @@ _service_and_connection_can_persist (NMVpnConnection *self)
NM_VPN_CONNECTION_GET_PRIVATE (self)->service_can_persist;
}
static gboolean
_connection_only_can_persist (NMVpnConnection *self)
{
return NM_VPN_CONNECTION_GET_PRIVATE (self)->connection_can_persist &&
!NM_VPN_CONNECTION_GET_PRIVATE (self)->service_can_persist;
}
static void
device_state_changed (NMActiveConnection *active,
NMDevice *device,
......@@ -736,12 +744,22 @@ plugin_state_changed (DBusGProxy *proxy,
nm_connection_clear_secrets (priv->connection);
if ((priv->vpn_state >= STATE_WAITING) && (priv->vpn_state <= STATE_ACTIVATED)) {
VpnState old_state = priv->vpn_state;
nm_log_info (LOGD_VPN, "VPN plugin state change reason: %s (%d)",
vpn_reason_to_string (priv->failure_reason), priv->failure_reason);
_set_vpn_state (connection, STATE_FAILED, priv->failure_reason, FALSE);
/* Reset the failure reason */
priv->failure_reason = NM_VPN_CONNECTION_STATE_REASON_UNKNOWN;
/* If the connection failed, the service cannot persist, but the
* connection can persist, ask listeners to re-activate the connection.
*/
if ( old_state == STATE_ACTIVATED
&& priv->vpn_state == STATE_FAILED
&& _connection_only_can_persist (connection))
g_signal_emit (connection, signals[INTERNAL_RETRY_AFTER_FAILURE], 0);
}
} else if (new_service_state == NM_VPN_SERVICE_STATE_STARTING &&
old_service_state == NM_VPN_SERVICE_STATE_STARTED) {
......@@ -2148,6 +2166,13 @@ nm_vpn_connection_class_init (NMVpnConnectionClass *connection_class)
0, NULL, NULL, NULL,
G_TYPE_NONE, 3, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT);
signals[INTERNAL_RETRY_AFTER_FAILURE] =
g_signal_new (NM_VPN_CONNECTION_INTERNAL_RETRY_AFTER_FAILURE,
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
0, NULL, NULL, NULL,
G_TYPE_NONE, 0);
nm_dbus_manager_register_exported_type (nm_dbus_manager_get (),
G_TYPE_FROM_CLASS (object_class),
&dbus_glib_nm_vpn_connection_object_info);
......
......@@ -42,7 +42,8 @@
/* Signals */
/* not exported: includes old reason code */
#define NM_VPN_CONNECTION_INTERNAL_STATE_CHANGED "internal-state-changed"
#define NM_VPN_CONNECTION_INTERNAL_STATE_CHANGED "internal-state-changed"
#define NM_VPN_CONNECTION_INTERNAL_RETRY_AFTER_FAILURE "internal-retry-after-failure"
typedef struct {
......@@ -62,6 +63,8 @@ typedef struct {
NMVpnConnectionState new_state,
NMVpnConnectionState old_state,
NMVpnConnectionStateReason reason);
void (*internal_failed_retry) (NMVpnConnection *connection);
} NMVpnConnectionClass;
GType nm_vpn_connection_get_type (void);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment