summary refs log tree commit diff
path: root/libnm-glib/nm-remote-connection.c
diff options
context:
space:
mode:
Diffstat (limited to 'libnm-glib/nm-remote-connection.c')
-rw-r--r--libnm-glib/nm-remote-connection.c316
1 files changed, 116 insertions, 200 deletions
diff --git a/libnm-glib/nm-remote-connection.c b/libnm-glib/nm-remote-connection.c
index 57870c62..1039a7d1 100644
--- a/libnm-glib/nm-remote-connection.c
+++ b/libnm-glib/nm-remote-connection.c
@@ -18,7 +18,7 @@
  * Boston, MA 02110-1301 USA.
  *
  * Copyright (C) 2007 - 2008 Novell, Inc.
- * Copyright (C) 2007 - 2011 Red Hat, Inc.
+ * Copyright (C) 2007 - 2010 Red Hat, Inc.
  */
 
 #include <string.h>
@@ -29,11 +29,15 @@
 #include "nm-remote-connection.h"
 #include "nm-remote-connection-private.h"
 #include "nm-dbus-glib-types.h"
-#include "nm-settings-connection-bindings.h"
+#include "nm-exported-connection-bindings.h"
+#include "nm-settings-connection-interface.h"
 
 #define NM_REMOTE_CONNECTION_BUS "bus"
 
-G_DEFINE_TYPE (NMRemoteConnection, nm_remote_connection, NM_TYPE_CONNECTION)
+static void settings_connection_interface_init (NMSettingsConnectionInterface *klass);
+
+G_DEFINE_TYPE_EXTENDED (NMRemoteConnection, nm_remote_connection, NM_TYPE_CONNECTION, 0,
+                        G_IMPLEMENT_INTERFACE (NM_TYPE_SETTINGS_CONNECTION_INTERFACE, settings_connection_interface_init))
 
 enum {
 	PROP_0,
@@ -43,18 +47,10 @@ enum {
 	LAST_PROP
 };
 
-enum {
-	UPDATED,
-	REMOVED,
-	VISIBLE,
-
-	LAST_SIGNAL
-};
-static guint signals[LAST_SIGNAL] = { 0 };
-
 
 typedef struct {
 	NMRemoteConnection *self;
+	DBusGProxy *proxy;
 	DBusGProxyCall *call;
 	GFunc callback;
 	gpointer user_data;
@@ -63,10 +59,10 @@ typedef struct {
 typedef struct {
 	DBusGConnection *bus;
 	DBusGProxy *proxy;
+	DBusGProxy *secrets_proxy;
 	GSList *calls;
 
 	NMRemoteConnectionInitResult init_result;
-	gboolean visible;
 	gboolean disposed;
 } NMRemoteConnectionPrivate;
 
@@ -92,184 +88,161 @@ static void
 update_cb (DBusGProxy *proxy, GError *error, gpointer user_data)
 {
 	RemoteCall *call = user_data;
-	NMRemoteConnectionCommitFunc func = (NMRemoteConnectionCommitFunc) call->callback;
+	NMSettingsConnectionInterfaceUpdateFunc func = (NMSettingsConnectionInterfaceUpdateFunc) call->callback;
 
-	(*func)(call->self, error, call->user_data);
+	(*func)(NM_SETTINGS_CONNECTION_INTERFACE (call->self), error, call->user_data);
 	remote_call_complete (call->self, call);
 }
 
-/**
- * nm_remote_connection_commit_changes:
- * @connection: the #NMRemoteConnection
- * @callback: (scope async): a function to be called when the commit completes
- * @user_data: caller-specific data to be passed to @callback
- *
- * Save any local changes to the settings and properties of this connection and
- * save them in the settings service.
- **/
-void
-nm_remote_connection_commit_changes (NMRemoteConnection *self,
-                                     NMRemoteConnectionCommitFunc callback,
-                                     gpointer user_data)
+static gboolean
+update (NMSettingsConnectionInterface *connection,
+        NMSettingsConnectionInterfaceUpdateFunc callback,
+        gpointer user_data)
 {
-	NMRemoteConnectionPrivate *priv;
+	NMRemoteConnection *self = NM_REMOTE_CONNECTION (connection);
+	NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (self);
 	GHashTable *settings = NULL;
 	RemoteCall *call;
 
-	g_return_if_fail (self != NULL);
-	g_return_if_fail (NM_IS_REMOTE_CONNECTION (self));
-	g_return_if_fail (callback != NULL);
-
-	priv = NM_REMOTE_CONNECTION_GET_PRIVATE (self);
-
 	call = g_malloc0 (sizeof (RemoteCall));
 	call->self = self;
 	call->callback = (GFunc) callback;
 	call->user_data = user_data;
+	call->proxy = priv->proxy;
 
-	settings = nm_connection_to_hash (NM_CONNECTION (self), NM_SETTING_HASH_FLAG_ALL);
+	settings = nm_connection_to_hash (NM_CONNECTION (self));
 
-	call->call = org_freedesktop_NetworkManager_Settings_Connection_update_async (priv->proxy,
-	                                                                              settings,
-	                                                                              update_cb,
-	                                                                              call);
+	call->call = org_freedesktop_NetworkManagerSettings_Connection_update_async (priv->proxy,
+	                                                                             settings,
+	                                                                             update_cb,
+	                                                                             call);
 	g_assert (call->call);
 	priv->calls = g_slist_append (priv->calls, call);
 
 	g_hash_table_destroy (settings);
+
+	return TRUE;
 }
 
 static void
 delete_cb (DBusGProxy *proxy, GError *error, gpointer user_data)
 {
 	RemoteCall *call = user_data;
-	NMRemoteConnectionDeleteFunc func = (NMRemoteConnectionDeleteFunc) call->callback;
+	NMSettingsConnectionInterfaceDeleteFunc func = (NMSettingsConnectionInterfaceDeleteFunc) call->callback;
 
-	if (func != NULL)
-		(*func)(call->self, error, call->user_data);
+	(*func)(NM_SETTINGS_CONNECTION_INTERFACE (call->self), error, call->user_data);
 	remote_call_complete (call->self, call);
 }
 
-/**
- * nm_remote_connection_delete:
- * @connection: the #NMRemoteConnection
- * @callback: (scope async) (allow-none): a function to be called when the delete completes
- * @user_data: caller-specific data to be passed to @callback
- *
- * Delete the connection.
- **/
-void
-nm_remote_connection_delete (NMRemoteConnection *self,
-                             NMRemoteConnectionDeleteFunc callback,
-                             gpointer user_data)
+static gboolean
+do_delete (NMSettingsConnectionInterface *connection,
+           NMSettingsConnectionInterfaceDeleteFunc callback,
+           gpointer user_data)
 {
-	NMRemoteConnectionPrivate *priv;
+	NMRemoteConnection *self = NM_REMOTE_CONNECTION (connection);
+	NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (self);
 	RemoteCall *call;
 
-	g_return_if_fail (self != NULL);
-	g_return_if_fail (NM_IS_REMOTE_CONNECTION (self));
-
-	priv = NM_REMOTE_CONNECTION_GET_PRIVATE (self);
-
 	call = g_malloc0 (sizeof (RemoteCall));
 	call->self = self;
 	call->callback = (GFunc) callback;
 	call->user_data = user_data;
+	call->proxy = priv->proxy;
 
-	call->call = org_freedesktop_NetworkManager_Settings_Connection_delete_async (priv->proxy,
-	                                                                              delete_cb,
-	                                                                              call);
+	call->call = org_freedesktop_NetworkManagerSettings_Connection_delete_async (priv->proxy,
+	                                                                             delete_cb,
+	                                                                             call);
 	g_assert (call->call);
 	priv->calls = g_slist_append (priv->calls, call);
+
+	return TRUE;
 }
 
 static void
 get_secrets_cb (DBusGProxy *proxy, GHashTable *secrets, GError *error, gpointer user_data)
 {
 	RemoteCall *call = user_data;
-	NMRemoteConnectionGetSecretsFunc func = (NMRemoteConnectionGetSecretsFunc) call->callback;
+	NMSettingsConnectionInterfaceGetSecretsFunc func = (NMSettingsConnectionInterfaceGetSecretsFunc) call->callback;
 
-	(*func)(call->self, error ? NULL : secrets, error, call->user_data);
+	(*func)(NM_SETTINGS_CONNECTION_INTERFACE (call->self), error ? NULL : secrets, error, call->user_data);
 	remote_call_complete (call->self, call);
 }
 
-/**
- * nm_remote_connection_get_secrets:
- * @connection: the #NMRemoteConnection
- * @setting_name: the #NMSetting object name to get secrets for
- * @callback: (scope async): a function to be called when the update completes
- * @user_data: caller-specific data to be passed to @callback
- *
- * Request the connection's secrets.
- **/
-void
-nm_remote_connection_get_secrets (NMRemoteConnection *self,
-                                  const char *setting_name,
-                                  NMRemoteConnectionGetSecretsFunc callback,
-                                  gpointer user_data)
+static gboolean
+get_secrets (NMSettingsConnectionInterface *connection,
+             const char *setting_name,
+             const char **hints,
+             gboolean request_new,
+             NMSettingsConnectionInterfaceGetSecretsFunc callback,
+             gpointer user_data)
 {
-	NMRemoteConnectionPrivate *priv;
+	NMRemoteConnection *self = NM_REMOTE_CONNECTION (connection);
+	NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (self);
 	RemoteCall *call;
 
-	g_return_if_fail (self != NULL);
-	g_return_if_fail (NM_IS_REMOTE_CONNECTION (self));
-	g_return_if_fail (callback != NULL);
-
-	priv = NM_REMOTE_CONNECTION_GET_PRIVATE (self);
-
 	call = g_malloc0 (sizeof (RemoteCall));
 	call->self = self;
 	call->callback = (GFunc) callback;
 	call->user_data = user_data;
-
-	call->call = org_freedesktop_NetworkManager_Settings_Connection_get_secrets_async (priv->proxy,
-	                                                                                   setting_name,
-	                                                                                   get_secrets_cb,
-	                                                                                   call);
+	call->proxy = priv->secrets_proxy;
+
+	call->call = org_freedesktop_NetworkManagerSettings_Connection_Secrets_get_secrets_async (priv->secrets_proxy,
+	                                                                                          setting_name,
+	                                                                                          hints,
+	                                                                                          request_new,
+	                                                                                          get_secrets_cb,
+	                                                                                          call);
 	g_assert (call->call);
 	priv->calls = g_slist_append (priv->calls, call);
+
+	return TRUE;
 }
 
 /****************************************************************/
 
-static void
+static gboolean
 replace_settings (NMRemoteConnection *self, GHashTable *new_settings)
 {
 	GError *error = NULL;
 
-	if (nm_connection_replace_settings (NM_CONNECTION (self), new_settings, &error))
-		g_signal_emit (self, signals[UPDATED], 0, new_settings);
-	else {
-		g_warning ("%s: error updating connection %s settings: (%d) %s",
+	if (!nm_connection_replace_settings (NM_CONNECTION (self), new_settings, &error)) {
+		g_warning ("%s: error updating %s connection %s settings: (%d) %s",
 		           __func__,
+		           (nm_connection_get_scope (NM_CONNECTION (self)) == NM_CONNECTION_SCOPE_USER) ? "user" : "system",
 		           nm_connection_get_path (NM_CONNECTION (self)),
 		           error ? error->code : -1,
 		           (error && error->message) ? error->message : "(unknown)");
 		g_clear_error (&error);
-
-		g_signal_emit (self, signals[REMOVED], 0);
+		return FALSE;
 	}
+
+	/* Emit update irregardless to let listeners figure out what to do with
+	 * the connection; whether to delete / ignore it or not.
+	 */
+	nm_settings_connection_interface_emit_updated (NM_SETTINGS_CONNECTION_INTERFACE (self));
+	return TRUE;
 }
 
 static void
-init_get_settings_cb (DBusGProxy *proxy,
-                      GHashTable *new_settings,
-                      GError *error,
-                      gpointer user_data)
+get_settings_cb (DBusGProxy *proxy,
+                 GHashTable *new_settings,
+                 GError *error,
+                 gpointer user_data)
 {
 	NMRemoteConnection *self = user_data;
 	NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (self);
 
 	if (error) {
-		/* Connection doesn't exist, or isn't visible to this user */
-		if (dbus_g_error_has_name (error, "org.freedesktop.NetworkManager.Settings.PermissionDenied"))
-			priv->init_result = NM_REMOTE_CONNECTION_INIT_RESULT_INVISIBLE;
-		else
-			priv->init_result = NM_REMOTE_CONNECTION_INIT_RESULT_ERROR;
-
+		g_warning ("%s: error getting %s connection %s settings: (%d) %s",
+		           __func__,
+		           (nm_connection_get_scope (NM_CONNECTION (self)) == NM_CONNECTION_SCOPE_USER) ? "user" : "system",
+		           nm_connection_get_path (NM_CONNECTION (self)),
+		           error ? error->code : -1,
+		           (error && error->message) ? error->message : "(unknown)");
+		g_error_free (error);
+		priv->init_result = NM_REMOTE_CONNECTION_INIT_RESULT_ERROR;
 		g_object_notify (G_OBJECT (self), NM_REMOTE_CONNECTION_INIT_RESULT);
 	} else {
-		priv->visible = TRUE;
 		replace_settings (self, new_settings);
 		g_hash_table_destroy (new_settings);
 		priv->init_result = NM_REMOTE_CONNECTION_INIT_RESULT_SUCCESS;
@@ -278,64 +251,34 @@ init_get_settings_cb (DBusGProxy *proxy,
 }
 
 static void
-updated_get_settings_cb (DBusGProxy *proxy,
-                         GHashTable *new_settings,
-                         GError *error,
-                         gpointer user_data)
+updated_cb (DBusGProxy *proxy, GHashTable *settings, gpointer user_data)
 {
-	NMRemoteConnection *self = user_data;
-	NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (self);
-
-	if (error) {
-		GHashTable *hash;
-
-		/* Connection is no longer visible to this user.  Let the settings
-		 * service handle this via 'visible'.  The settings service will emit
-		 * the "removed" signal for us since it handles the lifetime of this
-		 * object.
-		 */
-		hash = g_hash_table_new (g_str_hash, g_str_equal);
-		nm_connection_replace_settings (NM_CONNECTION (self), hash, NULL);
-		g_hash_table_destroy (hash);
-
-		priv->visible = FALSE;
-		g_signal_emit (self, signals[VISIBLE], 0, FALSE);
-	} else {
-		replace_settings (self, new_settings);
-		g_hash_table_destroy (new_settings);
-
-		/* Settings service will handle announcing the connection to clients */
-		if (priv->visible == FALSE) {
-			priv->visible = TRUE;
-			g_signal_emit (self, signals[VISIBLE], 0, TRUE);
-		}
-	}
+	replace_settings (NM_REMOTE_CONNECTION (user_data), settings);
 }
 
 static void
-updated_cb (DBusGProxy *proxy, gpointer user_data)
+removed_cb (DBusGProxy *proxy, gpointer user_data)
 {
-	NMRemoteConnection *self = NM_REMOTE_CONNECTION (user_data);
-	NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (self);
-
-	/* The connection got updated; request the replacement settings */
-	org_freedesktop_NetworkManager_Settings_Connection_get_settings_async (priv->proxy,
-	                                                                       updated_get_settings_cb,
-	                                                                       self);
+	g_signal_emit_by_name (G_OBJECT (user_data), "removed");
 }
 
+/****************************************************************/
+
 static void
-removed_cb (DBusGProxy *proxy, gpointer user_data)
+settings_connection_interface_init (NMSettingsConnectionInterface *klass)
 {
-	g_signal_emit (G_OBJECT (user_data), signals[REMOVED], 0);
+	/* interface implementation */
+	klass->update = update;
+	klass->delete = do_delete;
+	klass->get_secrets = get_secrets;
 }
 
-/****************************************************************/
-
 /**
  * nm_remote_connection_new:
  * @bus: a valid and connected D-Bus connection
+ * @scope: the Connection scope (either user or system)
  * @path: the D-Bus path of the connection as exported by the settings service
+ *  indicated by @scope
  *
  * Creates a new object representing the remote connection.
  *
@@ -343,6 +286,7 @@ removed_cb (DBusGProxy *proxy, gpointer user_data)
  **/
 NMRemoteConnection *
 nm_remote_connection_new (DBusGConnection *bus,
+                          NMConnectionScope scope,
                           const char *path)
 {
 	g_return_val_if_fail (bus != NULL, NULL);
@@ -350,6 +294,7 @@ nm_remote_connection_new (DBusGConnection *bus,
 
 	return (NMRemoteConnection *) g_object_new (NM_TYPE_REMOTE_CONNECTION,
 	                                            NM_REMOTE_CONNECTION_BUS, bus,
+	                                            NM_CONNECTION_SCOPE, scope,
 	                                            NM_CONNECTION_PATH, path,
 	                                            NULL);
 }
@@ -361,6 +306,7 @@ constructor (GType type,
 {
 	GObject *object;
 	NMRemoteConnectionPrivate *priv;
+	const char *service = NM_DBUS_SERVICE_USER_SETTINGS;
 
 	object = G_OBJECT_CLASS (nm_remote_connection_parent_class)->constructor (type, n_construct_params, construct_params);
 	if (!object)
@@ -370,22 +316,32 @@ constructor (GType type,
 	g_assert (priv->bus);
 	g_assert (nm_connection_get_path (NM_CONNECTION (object)));
 
+	if (nm_connection_get_scope (NM_CONNECTION (object)) == NM_CONNECTION_SCOPE_SYSTEM)
+		service = NM_DBUS_SERVICE_SYSTEM_SETTINGS;
+
 	priv->proxy = dbus_g_proxy_new_for_name (priv->bus,
-	                                         NM_DBUS_SERVICE,
+	                                         service,
 	                                         nm_connection_get_path (NM_CONNECTION (object)),
 	                                         NM_DBUS_IFACE_SETTINGS_CONNECTION);
 	g_assert (priv->proxy);
 	dbus_g_proxy_set_default_timeout (priv->proxy, G_MAXINT);
 
-	dbus_g_proxy_add_signal (priv->proxy, "Updated", G_TYPE_INVALID);
+	priv->secrets_proxy = dbus_g_proxy_new_for_name (priv->bus,
+	                                                 service,
+	                                                 nm_connection_get_path (NM_CONNECTION (object)),
+	                                                 NM_DBUS_IFACE_SETTINGS_CONNECTION_SECRETS);
+	g_assert (priv->secrets_proxy);
+	dbus_g_proxy_set_default_timeout (priv->secrets_proxy, G_MAXINT);
+
+	dbus_g_proxy_add_signal (priv->proxy, "Updated", DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, G_TYPE_INVALID);
 	dbus_g_proxy_connect_signal (priv->proxy, "Updated", G_CALLBACK (updated_cb), object, NULL);
 
 	dbus_g_proxy_add_signal (priv->proxy, "Removed", G_TYPE_INVALID);
 	dbus_g_proxy_connect_signal (priv->proxy, "Removed", G_CALLBACK (removed_cb), object, NULL);
 
-	org_freedesktop_NetworkManager_Settings_Connection_get_settings_async (priv->proxy,
-	                                                                       init_get_settings_cb,
-	                                                                       object);
+	org_freedesktop_NetworkManagerSettings_Connection_get_settings_async (priv->proxy,
+	                                                                      get_settings_cb,
+	                                                                      object);
 	return object;
 }
 
@@ -441,6 +397,7 @@ dispose (GObject *object)
 			remote_call_complete (self, priv->calls->data);
 
 		g_object_unref (priv->proxy);
+		g_object_unref (priv->secrets_proxy);
 		dbus_g_connection_unref (priv->bus);
 	}
 
@@ -478,46 +435,5 @@ nm_remote_connection_class_init (NMRemoteConnectionClass *remote_class)
 		                    NM_REMOTE_CONNECTION_INIT_RESULT_ERROR,
 		                    NM_REMOTE_CONNECTION_INIT_RESULT_UNKNOWN,
 		                    G_PARAM_READABLE));
-
-	/* Signals */
-	/**
-	 * NMRemoteConnection::updated:
-	 * @connection: a #NMConnection
-	 *
-	 * This signal is emitted when a connection changes, and it is
-	 * still visible to the user.
-	 */
-	signals[UPDATED] = 
-		g_signal_new (NM_REMOTE_CONNECTION_UPDATED,
-		              G_TYPE_FROM_CLASS (remote_class),
-		              G_SIGNAL_RUN_FIRST,
-		              G_STRUCT_OFFSET (NMRemoteConnectionClass, updated),
-		              NULL, NULL,
-		              g_cclosure_marshal_VOID__VOID,
-		              G_TYPE_NONE, 0);
-
-	/**
-	 * NMRemoteConnection::removed:
-	 * @connection: a #NMConnection
-	 *
-	 * This signal is emitted when a connection is either deleted or becomes
-	 * invisible to the current user.
-	 */
-	signals[REMOVED] = 
-		g_signal_new (NM_REMOTE_CONNECTION_REMOVED,
-		              G_TYPE_FROM_CLASS (remote_class),
-		              G_SIGNAL_RUN_FIRST,
-		              G_STRUCT_OFFSET (NMRemoteConnectionClass, removed),
-	 	              NULL, NULL,
-		              g_cclosure_marshal_VOID__VOID,
-		              G_TYPE_NONE, 0);
-
-	/* Private signal */
-	signals[VISIBLE] =
-		g_signal_new ("visible",
-		              G_TYPE_FROM_CLASS (remote_class),
-		              G_SIGNAL_RUN_FIRST,
-		              0, NULL, NULL,
-		              g_cclosure_marshal_VOID__BOOLEAN,
-		              G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
 }
+