Commit 9f15abbd authored by Lubomir Rintel's avatar Lubomir Rintel 🥕
Browse files

libnm/vpn-service-plugin: add watch-peer property

Make it possible to construct the plugin instance in a way that disconnects the
connection if the DBus client that activated it drops off the bus. This makes the
plugins conveniently clean up when NetworkManager crashes.

We need this, as with multiple VPN support we can loose track of the client bus
names when the daemon crashes leaving to nice way to clean up on respawn.

However, this behavior is not desired for debugging or hypotetical VPN plugin
users other than NetworkManager (say; "gdbus call -m o.fd.NM.VPN.Plugin.Connect").
Let the plugin decide when to use it.
parent 1bb55379
......@@ -53,11 +53,13 @@ typedef struct {
GDBusConnection *connection;
NMDBusVpnPlugin *dbus_vpn_service_plugin;
char *dbus_service_name;
gboolean dbus_watch_peer;
/* Temporary stuff */
guint connect_timer;
guint quit_timer;
guint fail_stop_id;
guint peer_watch_id;
gboolean interactive;
gboolean got_config;
......@@ -88,6 +90,7 @@ static guint signals[LAST_SIGNAL] = { 0 };
enum {
PROP_0,
PROP_DBUS_SERVICE_NAME,
PROP_DBUS_WATCH_PEER,
PROP_STATE,
LAST_PROP
......@@ -184,11 +187,13 @@ nm_vpn_service_plugin_failure (NMVpnServicePlugin *plugin,
gboolean
nm_vpn_service_plugin_disconnect (NMVpnServicePlugin *plugin, GError **err)
{
NMVpnServicePluginPrivate *priv;
gboolean ret = FALSE;
NMVpnServiceState state;
g_return_val_if_fail (NM_IS_VPN_SERVICE_PLUGIN (plugin), FALSE);
priv = NM_VPN_SERVICE_PLUGIN_GET_PRIVATE (plugin);
state = nm_vpn_service_plugin_get_state (plugin);
switch (state) {
case NM_VPN_SERVICE_STATE_STOPPING:
......@@ -207,6 +212,11 @@ nm_vpn_service_plugin_disconnect (NMVpnServicePlugin *plugin, GError **err)
break;
case NM_VPN_SERVICE_STATE_STARTING:
case NM_VPN_SERVICE_STATE_STARTED:
if (priv->peer_watch_id) {
g_dbus_connection_signal_unsubscribe (nm_vpn_service_plugin_get_connection (plugin),
priv->peer_watch_id);
priv->peer_watch_id = 0;
}
nm_vpn_service_plugin_set_state (plugin, NM_VPN_SERVICE_STATE_STOPPING);
ret = NM_VPN_SERVICE_PLUGIN_GET_CLASS (plugin)->disconnect (plugin, err);
nm_vpn_service_plugin_set_state (plugin, NM_VPN_SERVICE_STATE_STOPPED);
......@@ -413,6 +423,37 @@ connect_timer_start (NMVpnServicePlugin *plugin)
priv->connect_timer = g_timeout_add_seconds (60, connect_timer_expired, plugin);
}
static void
peer_vanished (GDBusConnection *connection,
const gchar *sender_name,
const gchar *object_path,
const gchar *interface_name,
const gchar *signal_name,
GVariant *parameters,
gpointer user_data)
{
nm_vpn_service_plugin_disconnect (NM_VPN_SERVICE_PLUGIN (user_data), NULL);
}
static guint
watch_peer (NMVpnServicePlugin *plugin,
GDBusMethodInvocation *context)
{
GDBusConnection *connection = g_dbus_method_invocation_get_connection (context);
const gchar *peer = g_dbus_message_get_sender (g_dbus_method_invocation_get_message (context));
return g_dbus_connection_signal_subscribe (connection,
"org.freedesktop.DBus",
"org.freedesktop.DBus",
"NameOwnerChanged",
"/org/freedesktop/DBus",
peer,
G_DBUS_SIGNAL_FLAGS_NONE,
peer_vanished,
plugin,
NULL);
}
static void
_connect_generic (NMVpnServicePlugin *plugin,
GDBusMethodInvocation *context,
......@@ -457,6 +498,9 @@ _connect_generic (NMVpnServicePlugin *plugin,
nm_vpn_service_plugin_set_state (plugin, NM_VPN_SERVICE_STATE_STARTING);
if (priv->dbus_watch_peer)
priv->peer_watch_id = watch_peer (plugin, context);
if (details) {
priv->interactive = TRUE;
success = vpn_class->connect_interactive (plugin, connection, details, &error);
......@@ -994,6 +1038,10 @@ set_property (GObject *object, guint prop_id,
/* Construct-only */
priv->dbus_service_name = g_value_dup_string (value);
break;
case PROP_DBUS_WATCH_PEER:
/* Construct-only */
priv->dbus_watch_peer = g_value_get_boolean (value);
break;
case PROP_STATE:
nm_vpn_service_plugin_set_state (NM_VPN_SERVICE_PLUGIN (object),
(NMVpnServiceState) g_value_get_enum (value));
......@@ -1014,6 +1062,9 @@ get_property (GObject *object, guint prop_id,
case PROP_DBUS_SERVICE_NAME:
g_value_set_string (value, priv->dbus_service_name);
break;
case PROP_DBUS_WATCH_PEER:
g_value_set_boolean (value, priv->dbus_watch_peer);
break;
case PROP_STATE:
g_value_set_enum (value, nm_vpn_service_plugin_get_state (NM_VPN_SERVICE_PLUGIN (object)));
break;
......@@ -1120,6 +1171,20 @@ nm_vpn_service_plugin_class_init (NMVpnServicePluginClass *plugin_class)
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
/**
* NMVpnServicePlugin:service-name:
*
* The D-Bus service name of this plugin.
*
* Since: 1.2
*/
g_object_class_install_property
(object_class, PROP_DBUS_WATCH_PEER,
g_param_spec_boolean (NM_VPN_SERVICE_PLUGIN_DBUS_WATCH_PEER, "", "",
FALSE,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY));
/**
* NMVpnServicePlugin:state:
*
......
......@@ -36,6 +36,7 @@ G_BEGIN_DECLS
#define NM_VPN_SERVICE_PLUGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_VPN_SERVICE_PLUGIN, NMVpnServicePluginClass))
#define NM_VPN_SERVICE_PLUGIN_DBUS_SERVICE_NAME "service-name"
#define NM_VPN_SERVICE_PLUGIN_DBUS_WATCH_PEER "watch-peer"
#define NM_VPN_SERVICE_PLUGIN_STATE "state"
typedef struct {
......
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