diff options
author | Lubomir Rintel <lkundrak@v3.sk> | 2015-09-23 12:19:09 +0200 |
---|---|---|
committer | Lubomir Rintel <lkundrak@v3.sk> | 2015-10-13 18:20:55 +0200 |
commit | 9f15abbda786c3db0431a3a5cb82baf5bea87660 (patch) | |
tree | 25d20d2a0a7c491f62880dffc3c0feac0cb3d2db | |
parent | 1bb553798c514e5ae1bf32a3cd87e96c4a656dfb (diff) | |
download | NetworkManager-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.c | 65 | ||||
-rw-r--r-- | libnm/nm-vpn-service-plugin.h | 1 |
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 { |