summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLubomir Rintel <lkundrak@v3.sk>2015-09-23 12:19:09 +0200
committerLubomir Rintel <lkundrak@v3.sk>2015-10-13 18:20:55 +0200
commit9f15abbda786c3db0431a3a5cb82baf5bea87660 (patch)
tree25d20d2a0a7c491f62880dffc3c0feac0cb3d2db
parent1bb553798c514e5ae1bf32a3cd87e96c4a656dfb (diff)
downloadNetworkManager-9f15abbda786c3db0431a3a5cb82baf5bea87660.tar.gz
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.
-rw-r--r--libnm/nm-vpn-service-plugin.c65
-rw-r--r--libnm/nm-vpn-service-plugin.h1
2 files changed, 66 insertions, 0 deletions
diff --git a/libnm/nm-vpn-service-plugin.c b/libnm/nm-vpn-service-plugin.c
index 2644732d96..d9f669c9ee 100644
--- a/libnm/nm-vpn-service-plugin.c
+++ b/libnm/nm-vpn-service-plugin.c
@@ -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);
@@ -414,6 +424,37 @@ connect_timer_start (NMVpnServicePlugin *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,
GVariant *properties,
@@ -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;
@@ -1121,6 +1172,20 @@ nm_vpn_service_plugin_class_init (NMVpnServicePluginClass *plugin_class)
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:
*
* The state of the plugin.
diff --git a/libnm/nm-vpn-service-plugin.h b/libnm/nm-vpn-service-plugin.h
index 81ba40457f..4fb0ed360f 100644
--- a/libnm/nm-vpn-service-plugin.h
+++ b/libnm/nm-vpn-service-plugin.h
@@ -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 {