summaryrefslogtreecommitdiff
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, 200 insertions, 116 deletions
diff --git a/libnm-glib/nm-remote-connection.c b/libnm-glib/nm-remote-connection.c
index 1039a7d18..57870c624 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 - 2010 Red Hat, Inc.
+ * Copyright (C) 2007 - 2011 Red Hat, Inc.
*/
#include <string.h>
@@ -29,15 +29,11 @@
#include "nm-remote-connection.h"
#include "nm-remote-connection-private.h"
#include "nm-dbus-glib-types.h"
-#include "nm-exported-connection-bindings.h"
-#include "nm-settings-connection-interface.h"
+#include "nm-settings-connection-bindings.h"
#define NM_REMOTE_CONNECTION_BUS "bus"
-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))
+G_DEFINE_TYPE (NMRemoteConnection, nm_remote_connection, NM_TYPE_CONNECTION)
enum {
PROP_0,
@@ -47,10 +43,18 @@ 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;
@@ -59,10 +63,10 @@ typedef struct {
typedef struct {
DBusGConnection *bus;
DBusGProxy *proxy;
- DBusGProxy *secrets_proxy;
GSList *calls;
NMRemoteConnectionInitResult init_result;
+ gboolean visible;
gboolean disposed;
} NMRemoteConnectionPrivate;
@@ -88,161 +92,184 @@ static void
update_cb (DBusGProxy *proxy, GError *error, gpointer user_data)
{
RemoteCall *call = user_data;
- NMSettingsConnectionInterfaceUpdateFunc func = (NMSettingsConnectionInterfaceUpdateFunc) call->callback;
+ NMRemoteConnectionCommitFunc func = (NMRemoteConnectionCommitFunc) call->callback;
- (*func)(NM_SETTINGS_CONNECTION_INTERFACE (call->self), error, call->user_data);
+ (*func)(call->self, error, call->user_data);
remote_call_complete (call->self, call);
}
-static gboolean
-update (NMSettingsConnectionInterface *connection,
- NMSettingsConnectionInterfaceUpdateFunc callback,
- gpointer user_data)
+/**
+ * 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)
{
- NMRemoteConnection *self = NM_REMOTE_CONNECTION (connection);
- NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (self);
+ NMRemoteConnectionPrivate *priv;
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));
+ settings = nm_connection_to_hash (NM_CONNECTION (self), NM_SETTING_HASH_FLAG_ALL);
- call->call = org_freedesktop_NetworkManagerSettings_Connection_update_async (priv->proxy,
- settings,
- update_cb,
- call);
+ call->call = org_freedesktop_NetworkManager_Settings_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;
- NMSettingsConnectionInterfaceDeleteFunc func = (NMSettingsConnectionInterfaceDeleteFunc) call->callback;
+ NMRemoteConnectionDeleteFunc func = (NMRemoteConnectionDeleteFunc) call->callback;
- (*func)(NM_SETTINGS_CONNECTION_INTERFACE (call->self), error, call->user_data);
+ if (func != NULL)
+ (*func)(call->self, error, call->user_data);
remote_call_complete (call->self, call);
}
-static gboolean
-do_delete (NMSettingsConnectionInterface *connection,
- NMSettingsConnectionInterfaceDeleteFunc callback,
- gpointer user_data)
+/**
+ * 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)
{
- NMRemoteConnection *self = NM_REMOTE_CONNECTION (connection);
- NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (self);
+ NMRemoteConnectionPrivate *priv;
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_NetworkManagerSettings_Connection_delete_async (priv->proxy,
- delete_cb,
- call);
+ call->call = org_freedesktop_NetworkManager_Settings_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;
- NMSettingsConnectionInterfaceGetSecretsFunc func = (NMSettingsConnectionInterfaceGetSecretsFunc) call->callback;
+ NMRemoteConnectionGetSecretsFunc func = (NMRemoteConnectionGetSecretsFunc) call->callback;
- (*func)(NM_SETTINGS_CONNECTION_INTERFACE (call->self), error ? NULL : secrets, error, call->user_data);
+ (*func)(call->self, error ? NULL : secrets, error, call->user_data);
remote_call_complete (call->self, call);
}
-static gboolean
-get_secrets (NMSettingsConnectionInterface *connection,
- const char *setting_name,
- const char **hints,
- gboolean request_new,
- NMSettingsConnectionInterfaceGetSecretsFunc callback,
- gpointer user_data)
+/**
+ * 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)
{
- NMRemoteConnection *self = NM_REMOTE_CONNECTION (connection);
- NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (self);
+ NMRemoteConnectionPrivate *priv;
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->secrets_proxy;
-
- call->call = org_freedesktop_NetworkManagerSettings_Connection_Secrets_get_secrets_async (priv->secrets_proxy,
- setting_name,
- hints,
- request_new,
- get_secrets_cb,
- call);
+
+ call->call = org_freedesktop_NetworkManager_Settings_Connection_get_secrets_async (priv->proxy,
+ setting_name,
+ get_secrets_cb,
+ call);
g_assert (call->call);
priv->calls = g_slist_append (priv->calls, call);
-
- return TRUE;
}
/****************************************************************/
-static gboolean
+static void
replace_settings (NMRemoteConnection *self, GHashTable *new_settings)
{
GError *error = NULL;
- if (!nm_connection_replace_settings (NM_CONNECTION (self), new_settings, &error)) {
- g_warning ("%s: error updating %s connection %s settings: (%d) %s",
+ 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",
__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);
- 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;
+ g_signal_emit (self, signals[REMOVED], 0);
+ }
}
static void
-get_settings_cb (DBusGProxy *proxy,
- GHashTable *new_settings,
- GError *error,
- gpointer user_data)
+init_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) {
- 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;
+ /* 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_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;
@@ -251,34 +278,64 @@ get_settings_cb (DBusGProxy *proxy,
}
static void
-updated_cb (DBusGProxy *proxy, GHashTable *settings, gpointer user_data)
+updated_get_settings_cb (DBusGProxy *proxy,
+ GHashTable *new_settings,
+ GError *error,
+ gpointer user_data)
{
- replace_settings (NM_REMOTE_CONNECTION (user_data), settings);
+ 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);
+ }
+ }
}
static void
-removed_cb (DBusGProxy *proxy, gpointer user_data)
+updated_cb (DBusGProxy *proxy, gpointer user_data)
{
- g_signal_emit_by_name (G_OBJECT (user_data), "removed");
-}
+ 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);
+}
static void
-settings_connection_interface_init (NMSettingsConnectionInterface *klass)
+removed_cb (DBusGProxy *proxy, gpointer user_data)
{
- /* interface implementation */
- klass->update = update;
- klass->delete = do_delete;
- klass->get_secrets = get_secrets;
+ g_signal_emit (G_OBJECT (user_data), signals[REMOVED], 0);
}
+/****************************************************************/
+
/**
* 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.
*
@@ -286,7 +343,6 @@ settings_connection_interface_init (NMSettingsConnectionInterface *klass)
**/
NMRemoteConnection *
nm_remote_connection_new (DBusGConnection *bus,
- NMConnectionScope scope,
const char *path)
{
g_return_val_if_fail (bus != NULL, NULL);
@@ -294,7 +350,6 @@ 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);
}
@@ -306,7 +361,6 @@ 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)
@@ -316,32 +370,22 @@ 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,
- service,
+ NM_DBUS_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);
- 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_add_signal (priv->proxy, "Updated", 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_NetworkManagerSettings_Connection_get_settings_async (priv->proxy,
- get_settings_cb,
- object);
+ org_freedesktop_NetworkManager_Settings_Connection_get_settings_async (priv->proxy,
+ init_get_settings_cb,
+ object);
return object;
}
@@ -397,7 +441,6 @@ 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);
}
@@ -435,5 +478,46 @@ 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);
+}