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
This commit is contained in:
@@ -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
|
static void
|
||||||
active_connection_state_changed (NMActiveConnection *active,
|
active_connection_state_changed (NMActiveConnection *active,
|
||||||
GParamSpec *pspec,
|
GParamSpec *pspec,
|
||||||
@@ -1859,6 +1881,9 @@ active_connection_added (NMManager *manager,
|
|||||||
g_signal_connect (active, NM_VPN_CONNECTION_INTERNAL_STATE_CHANGED,
|
g_signal_connect (active, NM_VPN_CONNECTION_INTERNAL_STATE_CHANGED,
|
||||||
G_CALLBACK (vpn_connection_state_changed),
|
G_CALLBACK (vpn_connection_state_changed),
|
||||||
policy);
|
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,
|
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,
|
g_signal_handlers_disconnect_by_func (active,
|
||||||
vpn_connection_state_changed,
|
vpn_connection_state_changed,
|
||||||
policy);
|
policy);
|
||||||
|
g_signal_handlers_disconnect_by_func (active,
|
||||||
|
vpn_connection_retry_after_failure,
|
||||||
|
policy);
|
||||||
g_signal_handlers_disconnect_by_func (active,
|
g_signal_handlers_disconnect_by_func (active,
|
||||||
active_connection_state_changed,
|
active_connection_state_changed,
|
||||||
policy);
|
policy);
|
||||||
|
@@ -111,6 +111,7 @@ typedef struct {
|
|||||||
enum {
|
enum {
|
||||||
VPN_STATE_CHANGED,
|
VPN_STATE_CHANGED,
|
||||||
INTERNAL_STATE_CHANGED,
|
INTERNAL_STATE_CHANGED,
|
||||||
|
INTERNAL_RETRY_AFTER_FAILURE,
|
||||||
|
|
||||||
LAST_SIGNAL
|
LAST_SIGNAL
|
||||||
};
|
};
|
||||||
@@ -442,6 +443,13 @@ _service_and_connection_can_persist (NMVpnConnection *self)
|
|||||||
NM_VPN_CONNECTION_GET_PRIVATE (self)->service_can_persist;
|
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
|
static void
|
||||||
device_state_changed (NMActiveConnection *active,
|
device_state_changed (NMActiveConnection *active,
|
||||||
NMDevice *device,
|
NMDevice *device,
|
||||||
@@ -736,12 +744,22 @@ plugin_state_changed (DBusGProxy *proxy,
|
|||||||
nm_connection_clear_secrets (priv->connection);
|
nm_connection_clear_secrets (priv->connection);
|
||||||
|
|
||||||
if ((priv->vpn_state >= STATE_WAITING) && (priv->vpn_state <= STATE_ACTIVATED)) {
|
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)",
|
nm_log_info (LOGD_VPN, "VPN plugin state change reason: %s (%d)",
|
||||||
vpn_reason_to_string (priv->failure_reason), priv->failure_reason);
|
vpn_reason_to_string (priv->failure_reason), priv->failure_reason);
|
||||||
_set_vpn_state (connection, STATE_FAILED, priv->failure_reason, FALSE);
|
_set_vpn_state (connection, STATE_FAILED, priv->failure_reason, FALSE);
|
||||||
|
|
||||||
/* Reset the failure reason */
|
/* Reset the failure reason */
|
||||||
priv->failure_reason = NM_VPN_CONNECTION_STATE_REASON_UNKNOWN;
|
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 &&
|
} else if (new_service_state == NM_VPN_SERVICE_STATE_STARTING &&
|
||||||
old_service_state == NM_VPN_SERVICE_STATE_STARTED) {
|
old_service_state == NM_VPN_SERVICE_STATE_STARTED) {
|
||||||
@@ -2148,6 +2166,13 @@ nm_vpn_connection_class_init (NMVpnConnectionClass *connection_class)
|
|||||||
0, NULL, NULL, NULL,
|
0, NULL, NULL, NULL,
|
||||||
G_TYPE_NONE, 3, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT);
|
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 (),
|
nm_dbus_manager_register_exported_type (nm_dbus_manager_get (),
|
||||||
G_TYPE_FROM_CLASS (object_class),
|
G_TYPE_FROM_CLASS (object_class),
|
||||||
&dbus_glib_nm_vpn_connection_object_info);
|
&dbus_glib_nm_vpn_connection_object_info);
|
||||||
|
@@ -43,6 +43,7 @@
|
|||||||
/* Signals */
|
/* Signals */
|
||||||
/* not exported: includes old reason code */
|
/* 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 {
|
typedef struct {
|
||||||
@@ -62,6 +63,8 @@ typedef struct {
|
|||||||
NMVpnConnectionState new_state,
|
NMVpnConnectionState new_state,
|
||||||
NMVpnConnectionState old_state,
|
NMVpnConnectionState old_state,
|
||||||
NMVpnConnectionStateReason reason);
|
NMVpnConnectionStateReason reason);
|
||||||
|
|
||||||
|
void (*internal_failed_retry) (NMVpnConnection *connection);
|
||||||
} NMVpnConnectionClass;
|
} NMVpnConnectionClass;
|
||||||
|
|
||||||
GType nm_vpn_connection_get_type (void);
|
GType nm_vpn_connection_get_type (void);
|
||||||
|
Reference in New Issue
Block a user