#include "nm-dbus-helpers-private.h"
#include "nm-glib-compat.h"
#include "nm-object-private.h"
+#include "nm-types.h"
/**
* SECTION:nm-remote-settings
* ]|
*/
-static void nm_remote_settings_initable_iface_init (GInitableIface *iface);
-static void nm_remote_settings_async_initable_iface_init (GAsyncInitableIface *iface);
-
-G_DEFINE_TYPE_WITH_CODE (NMRemoteSettings, nm_remote_settings, G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, nm_remote_settings_initable_iface_init);
- G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, nm_remote_settings_async_initable_iface_init);
- )
+G_DEFINE_TYPE (NMRemoteSettings, nm_remote_settings, NM_TYPE_OBJECT)
#define NM_REMOTE_SETTINGS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_REMOTE_SETTINGS, NMRemoteSettingsPrivate))
typedef struct {
- DBusGConnection *bus;
- gboolean private_bus;
-
DBusGProxy *proxy;
- GHashTable *connections;
- GHashTable *pending; /* Connections we don't have settings for yet */
- gboolean nm_running;
- guint32 init_left;
+ GPtrArray *all_connections;
+ GPtrArray *visible_connections;
/* AddConnectionInfo objects that are waiting for the connection to become initialized */
GSList *add_list;
- DBusGProxy *props_proxy;
char *hostname;
gboolean can_modify;
-
- DBusGProxy *dbus_proxy;
-
- DBusGProxyCall *listcon_call;
} NMRemoteSettingsPrivate;
enum {
PROP_0,
- PROP_BUS,
PROP_NM_RUNNING,
+ PROP_CONNECTIONS,
PROP_HOSTNAME,
PROP_CAN_MODIFY,
/* Signals */
enum {
- NEW_CONNECTION,
- CONNECTIONS_READ,
+ CONNECTION_ADDED,
+ CONNECTION_REMOVED,
LAST_SIGNAL
};
NMRemoteSettings *self;
NMRemoteSettingsAddConnectionFunc callback;
gpointer callback_data;
- NMRemoteConnection *connection;
+ char *path;
} AddConnectionInfo;
static AddConnectionInfo *
-add_connection_info_find (NMRemoteSettings *self, NMRemoteConnection *connection)
+add_connection_info_find (NMRemoteSettings *self, const char *path)
{
NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
GSList *iter;
for (iter = priv->add_list; iter; iter = g_slist_next (iter)) {
AddConnectionInfo *info = iter->data;
- if (info->connection == connection)
+ if (!g_strcmp0 (info->path, path))
return info;
}
priv->add_list = g_slist_remove (priv->add_list, info);
+ g_free (info->path);
g_free (info);
}
static void
add_connection_info_complete (NMRemoteSettings *self,
AddConnectionInfo *info,
+ NMRemoteConnection *connection,
GError *error)
{
g_return_if_fail (info != NULL);
- info->callback (info->self, error ? NULL : info->connection, error, info->callback_data);
+ info->callback (info->self, connection, error, info->callback_data);
add_connection_info_dispose (self, info);
}
+typedef const char * (*ConnectionStringGetter) (NMConnection *);
+
+static NMRemoteConnection *
+get_connection_by_string (NMRemoteSettings *settings,
+ const char *string,
+ ConnectionStringGetter get_comparison_string)
+{
+ NMRemoteSettingsPrivate *priv;
+ NMConnection *candidate;
+ int i;
+
+ if (!_nm_object_get_nm_running (NM_OBJECT (settings)))
+ return NULL;
+
+ priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings);
+
+ for (i = 0; i < priv->visible_connections->len; i++) {
+ candidate = priv->visible_connections->pdata[i];
+ if (!g_strcmp0 (string, get_comparison_string (candidate)))
+ return NM_REMOTE_CONNECTION (candidate);
+ }
+
+ return NULL;
+}
+
/**
* nm_remote_settings_get_connection_by_id:
* @settings: the %NMRemoteSettings
NMRemoteConnection *
nm_remote_settings_get_connection_by_id (NMRemoteSettings *settings, const char *id)
{
- NMRemoteSettingsPrivate *priv;
-
g_return_val_if_fail (NM_IS_REMOTE_SETTINGS (settings), NULL);
g_return_val_if_fail (id != NULL, NULL);
- priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings);
-
- if (priv->nm_running) {
- GHashTableIter iter;
- NMConnection *candidate;
-
- g_hash_table_iter_init (&iter, priv->connections);
- while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &candidate)) {
-
- if (!strcmp (id, nm_connection_get_id (candidate)))
- return NM_REMOTE_CONNECTION (candidate);
- }
- }
-
- return NULL;
+ return get_connection_by_string (settings, id, nm_connection_get_id);
}
/**
NMRemoteConnection *
nm_remote_settings_get_connection_by_path (NMRemoteSettings *settings, const char *path)
{
- NMRemoteSettingsPrivate *priv;
-
g_return_val_if_fail (NM_IS_REMOTE_SETTINGS (settings), NULL);
g_return_val_if_fail (path != NULL, NULL);
- priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings);
-
- return priv->nm_running ? g_hash_table_lookup (priv->connections, path) : NULL;
+ return get_connection_by_string (settings, path, nm_connection_get_path);
}
/**
NMRemoteConnection *
nm_remote_settings_get_connection_by_uuid (NMRemoteSettings *settings, const char *uuid)
{
- NMRemoteSettingsPrivate *priv;
- GHashTableIter iter;
- NMRemoteConnection *candidate;
-
g_return_val_if_fail (NM_IS_REMOTE_SETTINGS (settings), NULL);
g_return_val_if_fail (uuid != NULL, NULL);
- priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings);
-
- if (priv->nm_running) {
- g_hash_table_iter_init (&iter, priv->connections);
- while (g_hash_table_iter_next (&iter, NULL, (gpointer) &candidate)) {
- if (g_strcmp0 (uuid, nm_connection_get_uuid (NM_CONNECTION (candidate))) == 0)
- return candidate;
- }
- }
-
- return NULL;
+ return get_connection_by_string (settings, uuid, nm_connection_get_uuid);
}
static void
-connection_removed_cb (NMRemoteConnection *remote, gpointer user_data)
+connection_visible_changed (GObject *object,
+ GParamSpec *pspec,
+ gpointer user_data)
{
+ NMRemoteConnection *connection = NM_REMOTE_CONNECTION (object);
NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data);
- NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
- AddConnectionInfo *addinfo;
- GError *add_error;
- const char *path;
- /* Might have been removed while it was waiting to be initialized */
- addinfo = add_connection_info_find (self, remote);
- if (addinfo) {
- add_error = g_error_new_literal (NM_REMOTE_SETTINGS_ERROR,
- NM_REMOTE_SETTINGS_ERROR_CONNECTION_REMOVED,
- "Connection removed before it was initialized");
- add_connection_info_complete (self, addinfo, add_error);
- g_error_free (add_error);
- }
-
- path = nm_connection_get_path (NM_CONNECTION (remote));
- g_hash_table_remove (priv->connections, path);
- g_hash_table_remove (priv->pending, path);
+ if (nm_remote_connection_get_visible (connection))
+ g_signal_emit (self, signals[CONNECTION_ADDED], 0, connection);
+ else
+ g_signal_emit (self, signals[CONNECTION_REMOVED], 0, connection);
}
-static void connection_visible_changed_cb (GObject *object, GParamSpec *spec, gpointer user_data);
-
-/* Takes a reference to the connection when adding to 'to' */
static void
-move_connection (NMRemoteSettings *self,
- NMRemoteConnection *remote,
- GHashTable *from,
- GHashTable *to)
+cleanup_connection (NMRemoteSettings *self,
+ NMRemoteConnection *remote)
{
- const char *path = nm_connection_get_path (NM_CONNECTION (remote));
-
- g_hash_table_insert (to, g_strdup (path), g_object_ref (remote));
- if (from)
- g_hash_table_remove (from, path);
-
- /* Setup connection signals since removing from 'from' clears them, but
- * also the first time the connection is added to a hash if 'from' is NULL.
- */
- if (!g_signal_handler_find (remote, G_SIGNAL_MATCH_FUNC,
- 0, 0, NULL, connection_removed_cb, NULL)) {
- g_signal_connect (remote,
- NM_REMOTE_CONNECTION_REMOVED,
- G_CALLBACK (connection_removed_cb),
- self);
- }
-
- if (!g_signal_handler_find (remote, G_SIGNAL_MATCH_FUNC,
- 0, 0, NULL, connection_visible_changed_cb, NULL)) {
- g_signal_connect (remote,
- "notify::" NM_REMOTE_CONNECTION_VISIBLE,
- G_CALLBACK (connection_visible_changed_cb),
- self);
- }
+ g_signal_handlers_disconnect_by_func (remote, G_CALLBACK (connection_visible_changed), self);
}
static void
-connection_visible_changed_cb (GObject *object,
- GParamSpec *pspec,
- gpointer user_data)
+connection_removed (NMRemoteSettings *self,
+ NMRemoteConnection *remote)
{
- NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data);
NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
- NMRemoteConnection *remote = NM_REMOTE_CONNECTION (object);
- const char *path;
-
- path = nm_connection_get_path (NM_CONNECTION (remote));
- g_assert (path);
+ gboolean still_exists = FALSE;
+ int i;
- /* When a connection becomes invisible, we put it back in the pending
- * hash until it becomes visible again. When it does, we move it back to
- * the normal connections hash.
- */
- if (nm_remote_connection_get_visible (remote)) {
- /* Connection visible to this user again */
- if (g_hash_table_lookup (priv->pending, path)) {
- /* Move connection from pending to visible hash; emit for clients */
- move_connection (self, remote, priv->pending, priv->connections);
- g_signal_emit (self, signals[NEW_CONNECTION], 0, remote);
- }
- } else {
- /* Connection now invisible to this user */
- if (g_hash_table_lookup (priv->connections, path)) {
- /* Move connection to pending hash and wait for it to become visible again */
- move_connection (self, remote, priv->connections, priv->pending);
-
- /* Signal to clients that the connection is gone; but we have to
- * block our connection removed handler so we don't destroy
- * the connection when the signal is emitted.
- */
- g_signal_handlers_block_by_func (remote, connection_removed_cb, self);
- g_signal_emit_by_name (remote, NM_REMOTE_CONNECTION_REMOVED);
- g_signal_handlers_unblock_by_func (remote, connection_removed_cb, self);
+ /* Check if the connection was actually removed or if it just turned invisible. */
+ if (priv->all_connections) {
+ for (i = 0; i < priv->all_connections->len; i++) {
+ if (remote == priv->all_connections->pdata[i]) {
+ still_exists = TRUE;
+ break;
+ }
}
}
+
+ if (!still_exists)
+ cleanup_connection (self, remote);
+
+ /* Allow the signal to propagate if and only if @remote was in visible_connections */
+ if (!g_ptr_array_remove (priv->visible_connections, remote))
+ g_signal_stop_emission (self, signals[CONNECTION_REMOVED], 0);
}
static void
-connection_inited (GObject *source, GAsyncResult *result, gpointer user_data)
+connection_added (NMRemoteSettings *self,
+ NMRemoteConnection *remote)
{
- NMRemoteConnection *remote = NM_REMOTE_CONNECTION (source);
- NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data);
NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
AddConnectionInfo *addinfo;
const char *path;
- GError *error = NULL, *local;
-
- path = nm_connection_get_path (NM_CONNECTION (remote));
- addinfo = add_connection_info_find (self, remote);
-
- if (g_async_initable_init_finish (G_ASYNC_INITABLE (remote), result, &error)) {
- /* Connection is initialized and visible; expose it to clients */
- move_connection (self, remote, priv->pending, priv->connections);
-
- /* If there's a pending AddConnection request, complete that here before
- * signaling new-connection.
- */
- if (addinfo)
- add_connection_info_complete (self, addinfo, NULL);
-
- /* Finally, let users know of the new connection now that it has all
- * its settings and is valid.
- */
- g_signal_emit (self, signals[NEW_CONNECTION], 0, remote);
- } else {
- if (addinfo) {
- local = g_error_new (NM_REMOTE_SETTINGS_ERROR,
- NM_REMOTE_SETTINGS_ERROR_CONNECTION_UNAVAILABLE,
- "Connection not visible or not available: %s",
- error ? error->message : "(unknown)");
- add_connection_info_complete (self, addinfo, local);
- g_error_free (local);
- }
- /* PermissionDenied means the connection isn't visible to this user, so
- * keep it in priv->pending to be notified later of visibility changes.
- * Otherwise forget it.
- */
- if (!dbus_g_error_has_name (error, "org.freedesktop.NetworkManager.Settings.PermissionDenied"))
- g_hash_table_remove (priv->pending, path);
-
- g_error_free (error);
+ if (!g_signal_handler_find (remote, G_SIGNAL_MATCH_FUNC, 0, 0, NULL,
+ G_CALLBACK (connection_visible_changed), NULL)) {
+ g_signal_connect (remote,
+ "notify::" NM_REMOTE_CONNECTION_VISIBLE,
+ G_CALLBACK (connection_visible_changed),
+ self);
}
- /* Let listeners know that all connections have been found */
- priv->init_left--;
- if (priv->init_left == 0)
- g_signal_emit (self, signals[CONNECTIONS_READ], 0);
-}
-
-static NMRemoteConnection *
-new_connection_cb (DBusGProxy *proxy, const char *path, gpointer user_data)
-{
- NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data);
- NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
- NMRemoteConnection *connection = NULL;
-
- /* Make double-sure we don't already have it */
- connection = g_hash_table_lookup (priv->pending, path);
- if (connection)
- return connection;
- connection = g_hash_table_lookup (priv->connections, path);
- if (connection)
- return connection;
-
- /* Create a new connection object for it */
- connection = g_object_new (NM_TYPE_REMOTE_CONNECTION,
- NM_REMOTE_CONNECTION_BUS, priv->bus,
- NM_CONNECTION_PATH, path,
- NULL);
- g_async_initable_init_async (G_ASYNC_INITABLE (connection),
- G_PRIORITY_DEFAULT, NULL,
- connection_inited, self);
-
- /* Add the connection to the pending table to wait for it to retrieve
- * it's settings asynchronously over D-Bus. The connection isn't
- * really valid until it has all its settings, so hide it until it does.
- */
- move_connection (self, connection, NULL, priv->pending);
- g_object_unref (connection); /* move_connection() takes a ref */
+ if (nm_remote_connection_get_visible (remote))
+ g_ptr_array_add (priv->visible_connections, remote);
+ else
+ g_signal_stop_emission (self, signals[CONNECTION_ADDED], 0);
- return connection;
+ path = nm_connection_get_path (NM_CONNECTION (remote));
+ addinfo = add_connection_info_find (self, path);
+ if (addinfo)
+ add_connection_info_complete (self, addinfo, remote, NULL);
}
static void
-fetch_connections_done (DBusGProxy *proxy,
- DBusGProxyCall *call,
- gpointer user_data)
+object_creation_failed (NMObject *object, GError *error, char *failed_path)
{
- NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data);
- NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
- GPtrArray *connections;
- GError *error = NULL;
- int i;
-
- g_warn_if_fail (priv->listcon_call == call);
- priv->listcon_call = NULL;
-
- if (!dbus_g_proxy_end_call (proxy, call, &error,
- DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH, &connections,
- G_TYPE_INVALID)) {
- if ( !g_error_matches (error, DBUS_GERROR, DBUS_GERROR_SERVICE_UNKNOWN)
- && !g_error_matches (error, DBUS_GERROR, DBUS_GERROR_NAME_HAS_NO_OWNER)
- && priv->nm_running) {
- g_warning ("%s: error fetching connections: (%d) %s.",
- __func__,
- error->code,
- error->message ? error->message : "(unknown)");
- }
- g_clear_error (&error);
-
- /* We tried to read connections and failed */
- g_signal_emit (self, signals[CONNECTIONS_READ], 0);
- return;
- }
-
- /* Let listeners know we are done getting connections */
- if (connections->len == 0)
- g_signal_emit (self, signals[CONNECTIONS_READ], 0);
- else {
- priv->init_left = connections->len;
- for (i = 0; i < connections->len; i++) {
- char *path = g_ptr_array_index (connections, i);
+ NMRemoteSettings *self = NM_REMOTE_SETTINGS (object);
+ AddConnectionInfo *addinfo;
+ GError *add_error;
- new_connection_cb (proxy, path, user_data);
- g_free (path);
- }
+ addinfo = add_connection_info_find (self, failed_path);
+ if (addinfo) {
+ add_error = g_error_new_literal (NM_REMOTE_SETTINGS_ERROR,
+ NM_REMOTE_SETTINGS_ERROR_CONNECTION_REMOVED,
+ "Connection removed before it was initialized");
+ add_connection_info_complete (self, addinfo, NULL, add_error);
+ g_error_free (add_error);
}
-
- g_ptr_array_free (connections, TRUE);
}
/**
{
NMRemoteSettingsPrivate *priv;
GSList *list = NULL;
- GHashTableIter iter;
- gpointer value;
+ int i;
g_return_val_if_fail (NM_IS_REMOTE_SETTINGS (settings), NULL);
priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings);
- if (priv->nm_running) {
- g_hash_table_iter_init (&iter, priv->connections);
- while (g_hash_table_iter_next (&iter, NULL, &value))
- list = g_slist_prepend (list, NM_REMOTE_CONNECTION (value));
+ if (_nm_object_get_nm_running (NM_OBJECT (settings))) {
+ for (i = 0; i < priv->visible_connections->len; i++)
+ list = g_slist_prepend (list, priv->visible_connections->pdata[i]);
+ list = g_slist_reverse (list);
}
return list;
char *path = NULL;
if (dbus_g_proxy_end_call (proxy, call, &error, DBUS_TYPE_G_OBJECT_PATH, &path, G_TYPE_INVALID)) {
- info->connection = new_connection_cb (proxy, path, info->self);
- g_assert (info->connection);
+ info->path = path;
/* Wait until this connection is fully initialized before calling the callback */
- g_free (path);
} else
- add_connection_info_complete (info->self, info, error);
+ add_connection_info_complete (info->self, info, NULL, error);
g_clear_error (&error);
}
priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings);
- if (!priv->nm_running)
+ if (!_nm_object_get_nm_running (NM_OBJECT (settings)))
return FALSE;
info = g_malloc0 (sizeof (AddConnectionInfo));
priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings);
- if (!priv->nm_running)
+ if (!_nm_object_get_nm_running (NM_OBJECT (settings)))
return FALSE;
info = g_malloc0 (sizeof (AddConnectionInfo));
priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings);
- if (!priv->nm_running) {
+ if (!_nm_object_get_nm_running (NM_OBJECT (settings))) {
g_set_error_literal (error, NM_REMOTE_SETTINGS_ERROR,
NM_REMOTE_SETTINGS_ERROR_SERVICE_UNAVAILABLE,
"NetworkManager is not running.");
priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings);
- if (!priv->nm_running) {
+ if (!_nm_object_get_nm_running (NM_OBJECT (settings))) {
g_set_error_literal (error, NM_REMOTE_SETTINGS_ERROR,
NM_REMOTE_SETTINGS_ERROR_SERVICE_UNAVAILABLE,
"NetworkManager is not running.");
return success;
}
-static void
-clear_one_hash (GHashTable *table)
-{
- GHashTableIter iter;
- gpointer value;
- GSList *list = NULL, *list_iter;
-
- /* Build up the list of connections; we can't emit "removed" during hash
- * table iteration because emission of the "removed" signal may trigger code
- * that explicitly removes the connection from the hash table somewhere
- * else.
- */
- g_hash_table_iter_init (&iter, table);
- while (g_hash_table_iter_next (&iter, NULL, &value))
- list = g_slist_prepend (list, NM_REMOTE_CONNECTION (value));
-
- for (list_iter = list; list_iter; list_iter = g_slist_next (list_iter))
- g_signal_emit_by_name (NM_REMOTE_CONNECTION (list_iter->data), NM_REMOTE_CONNECTION_REMOVED);
- g_slist_free (list);
-
- g_hash_table_remove_all (table);
-}
-
typedef struct {
NMRemoteSettings *settings;
NMRemoteSettingsSaveHostnameFunc callback;
priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings);
- if (!priv->nm_running)
+ if (!_nm_object_get_nm_running (NM_OBJECT (settings)))
return FALSE;
info = g_malloc0 (sizeof (SaveHostnameInfo));
}
static void
-properties_changed_cb (DBusGProxy *proxy,
- GHashTable *properties,
- gpointer user_data)
+updated_properties (GObject *object, GAsyncResult *result, gpointer user_data)
{
NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data);
- NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
- GHashTableIter iter;
- gpointer key, tmp;
-
- g_hash_table_iter_init (&iter, properties);
- while (g_hash_table_iter_next (&iter, &key, &tmp)) {
- GValue *value = tmp;
-
- if (!strcmp ((const char *) key, "Hostname")) {
- g_free (priv->hostname);
- priv->hostname = g_value_dup_string (value);
- g_object_notify (G_OBJECT (self), NM_REMOTE_SETTINGS_HOSTNAME);
- }
+ GError *error = NULL;
- if (!strcmp ((const char *) key, "CanModify")) {
- priv->can_modify = g_value_get_boolean (value);
- g_object_notify (G_OBJECT (self), NM_REMOTE_SETTINGS_CAN_MODIFY);
- }
+ if (!_nm_object_reload_properties_finish (NM_OBJECT (object), result, &error)) {
+ g_warning ("%s: error reading NMRemoteSettings properties: %s", __func__, error->message);
+ g_error_free (error);
}
-}
-
-static void
-nm_appeared_got_properties (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data)
-{
- NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data);
- NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
- GHashTable *props = NULL;
- if (dbus_g_proxy_end_call (proxy, call, NULL,
- DBUS_TYPE_G_MAP_OF_VARIANT, &props,
- G_TYPE_INVALID)) {
- properties_changed_cb (priv->props_proxy, props, self);
- g_hash_table_destroy (props);
- }
+ g_object_notify (G_OBJECT (self), NM_REMOTE_SETTINGS_NM_RUNNING);
}
static void
-name_owner_changed (DBusGProxy *proxy,
- const char *name,
- const char *old_owner,
- const char *new_owner,
+nm_running_changed (GObject *object,
+ GParamSpec *pspec,
gpointer user_data)
{
- NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data);
+ NMRemoteSettings *self = NM_REMOTE_SETTINGS (object);
NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
- const char *sname = NM_DBUS_SERVICE;
- if (!strcmp (name, sname)) {
- if (new_owner && strlen (new_owner) > 0) {
- priv->nm_running = TRUE;
+ g_object_freeze_notify (object);
- priv->listcon_call = dbus_g_proxy_begin_call (priv->proxy, "ListConnections",
- fetch_connections_done, self, NULL,
- G_TYPE_INVALID);
+ if (!_nm_object_get_nm_running (NM_OBJECT (self))) {
+ if (priv->all_connections) {
+ GPtrArray *connections;
+ int i;
- dbus_g_proxy_begin_call (priv->props_proxy, "GetAll",
- nm_appeared_got_properties, self, NULL,
- G_TYPE_STRING, NM_DBUS_INTERFACE_SETTINGS,
- G_TYPE_INVALID);
- } else {
- priv->nm_running = FALSE;
+ connections = priv->all_connections;
+ priv->all_connections = NULL;
- clear_one_hash (priv->pending);
- clear_one_hash (priv->connections);
+ for (i = 0; i < connections->len; i++) {
+ g_signal_emit (self, signals[CONNECTION_REMOVED], 0, connections->pdata[i]);
+ g_object_unref (connections->pdata[i]);
+ }
+ g_ptr_array_unref (connections);
+ }
- /* Clear properties */
+ /* Clear properties */
+ if (priv->hostname) {
g_free (priv->hostname);
priv->hostname = NULL;
g_object_notify (G_OBJECT (self), NM_REMOTE_SETTINGS_HOSTNAME);
+ }
+ if (priv->can_modify) {
priv->can_modify = FALSE;
g_object_notify (G_OBJECT (self), NM_REMOTE_SETTINGS_CAN_MODIFY);
-
- if (priv->listcon_call) {
- dbus_g_proxy_cancel_call (priv->proxy, priv->listcon_call);
- priv->listcon_call = NULL;
- }
}
+
+ _nm_object_suppress_property_updates (NM_OBJECT (self), TRUE);
g_object_notify (G_OBJECT (self), NM_REMOTE_SETTINGS_NM_RUNNING);
+ } else {
+ _nm_object_suppress_property_updates (NM_OBJECT (self), FALSE);
+ _nm_object_reload_properties_async (NM_OBJECT (self), updated_properties, self);
}
+
+ g_object_thaw_notify (object);
}
/****************************************************************/
NULL);
}
-static void
-remote_settings_inited (GObject *source, GAsyncResult *result, gpointer user_data)
-{
- GSimpleAsyncResult *simple = user_data;
- GError *error = NULL;
-
- if (!g_async_initable_new_finish (G_ASYNC_INITABLE (source), result, &error))
- g_simple_async_result_take_error (simple, error);
- else
- g_simple_async_result_set_op_res_gpointer (simple, source, g_object_unref);
- g_simple_async_result_complete (simple);
- g_object_unref (simple);
-}
-
/**
* nm_remote_settings_new_async:
* @cancellable: a #GCancellable, or %NULL
**/
void
nm_remote_settings_new_async (GCancellable *cancellable,
- GAsyncReadyCallback callback, gpointer user_data)
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
- GSimpleAsyncResult *simple;
-
- simple = g_simple_async_result_new (NULL, callback, user_data, nm_remote_settings_new_async);
-
g_async_initable_new_async (NM_TYPE_REMOTE_SETTINGS, G_PRIORITY_DEFAULT, cancellable,
- remote_settings_inited, simple,
+ callback, user_data,
NULL);
}
NMRemoteSettings *
nm_remote_settings_new_finish (GAsyncResult *result, GError **error)
{
- GSimpleAsyncResult *simple;
+ GObject *source;
+ NMRemoteSettings *settings;
- g_return_val_if_fail (g_simple_async_result_is_valid (result, NULL, nm_remote_settings_new_async), NULL);
+ source = g_async_result_get_source_object (result);
+ settings = (NMRemoteSettings *) g_async_initable_new_finish (G_ASYNC_INITABLE (source), result, error);
+ g_object_unref (source);
- simple = G_SIMPLE_ASYNC_RESULT (result);
- if (g_simple_async_result_propagate_error (simple, error))
- return NULL;
- else
- return g_object_ref (g_simple_async_result_get_op_res_gpointer (simple));
-}
-
-static void
-forget_connection (gpointer user_data)
-{
- NMRemoteConnection *remote = NM_REMOTE_CONNECTION (user_data);
-
- g_signal_handlers_disconnect_matched (remote, G_SIGNAL_MATCH_FUNC,
- 0, 0, NULL, connection_removed_cb, NULL);
- g_signal_handlers_disconnect_matched (remote, G_SIGNAL_MATCH_FUNC,
- 0, 0, NULL, connection_visible_changed_cb, NULL);
- g_object_unref (remote);
+ return settings;
}
static void
{
NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
- priv->connections = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, forget_connection);
- priv->pending = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, forget_connection);
+ priv->visible_connections = g_ptr_array_new ();
}
static void
-init_common (NMRemoteSettings *self)
+init_dbus (NMObject *object)
{
- NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
-
- if (priv->private_bus == FALSE) {
- /* D-Bus proxy for clearing connections on NameOwnerChanged */
- priv->dbus_proxy = dbus_g_proxy_new_for_name (priv->bus,
- DBUS_SERVICE_DBUS,
- DBUS_PATH_DBUS,
- DBUS_INTERFACE_DBUS);
- g_assert (priv->dbus_proxy);
-
- dbus_g_object_register_marshaller (g_cclosure_marshal_generic,
- G_TYPE_NONE,
- G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
- G_TYPE_INVALID);
- dbus_g_proxy_add_signal (priv->dbus_proxy, "NameOwnerChanged",
- G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
- G_TYPE_INVALID);
- dbus_g_proxy_connect_signal (priv->dbus_proxy,
- "NameOwnerChanged",
- G_CALLBACK (name_owner_changed),
- self, NULL);
- }
-
- priv->proxy = _nm_dbus_new_proxy_for_connection (priv->bus,
- NM_DBUS_PATH_SETTINGS,
- NM_DBUS_INTERFACE_SETTINGS);
- g_assert (priv->proxy);
- dbus_g_proxy_set_default_timeout (priv->proxy, G_MAXINT);
-
- dbus_g_proxy_add_signal (priv->proxy, "NewConnection",
- DBUS_TYPE_G_OBJECT_PATH,
- G_TYPE_INVALID);
- dbus_g_proxy_connect_signal (priv->proxy, "NewConnection",
- G_CALLBACK (new_connection_cb),
- self,
- NULL);
-
- /* D-Bus properties proxy */
- priv->props_proxy = _nm_dbus_new_proxy_for_connection (priv->bus,
- NM_DBUS_PATH_SETTINGS,
- "org.freedesktop.DBus.Properties");
- g_assert (priv->props_proxy);
-
- /* Monitor properties */
- dbus_g_object_register_marshaller (g_cclosure_marshal_generic,
- G_TYPE_NONE,
- DBUS_TYPE_G_MAP_OF_VARIANT,
- G_TYPE_INVALID);
- dbus_g_proxy_add_signal (priv->proxy, "PropertiesChanged",
- DBUS_TYPE_G_MAP_OF_VARIANT,
- G_TYPE_INVALID);
- dbus_g_proxy_connect_signal (priv->proxy, "PropertiesChanged",
- G_CALLBACK (properties_changed_cb),
- self,
- NULL);
+ NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (object);
+ const NMPropertiesInfo property_info[] = {
+ { NM_REMOTE_SETTINGS_CONNECTIONS, &priv->all_connections, NULL, NM_TYPE_REMOTE_CONNECTION, "connection" },
+ { NM_REMOTE_SETTINGS_HOSTNAME, &priv->hostname },
+ { NM_REMOTE_SETTINGS_CAN_MODIFY, &priv->can_modify },
+ { NULL },
+ };
+
+ NM_OBJECT_CLASS (nm_remote_settings_parent_class)->init_dbus (object);
+
+ priv->proxy = _nm_object_new_proxy (object,
+ NM_DBUS_PATH_SETTINGS,
+ NM_DBUS_INTERFACE_SETTINGS);
+ _nm_object_register_properties (object,
+ priv->proxy,
+ property_info);
+
+ g_signal_connect (object, "notify::" NM_OBJECT_NM_RUNNING,
+ G_CALLBACK (nm_running_changed), NULL);
}
-static gboolean
-init_sync (GInitable *initable, GCancellable *cancellable, GError **error)
+static GObject *
+constructor (GType type,
+ guint n_construct_params,
+ GObjectConstructParam *construct_params)
{
- NMRemoteSettings *settings = NM_REMOTE_SETTINGS (initable);
- NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings);
- GHashTable *props;
-
- init_common (settings);
-
- if (priv->private_bus == FALSE) {
- if (!dbus_g_proxy_call (priv->dbus_proxy, "NameHasOwner", error,
- G_TYPE_STRING, NM_DBUS_SERVICE,
- G_TYPE_INVALID,
- G_TYPE_BOOLEAN, &priv->nm_running,
- G_TYPE_INVALID)) {
- priv->nm_running = FALSE;
- return FALSE;
+ guint i;
+ const char *dbus_path;
+
+ /* Fill in the right D-Bus path if none was specified */
+ for (i = 0; i < n_construct_params; i++) {
+ if (strcmp (construct_params[i].pspec->name, NM_OBJECT_DBUS_PATH) == 0) {
+ dbus_path = g_value_get_string (construct_params[i].value);
+ if (dbus_path == NULL) {
+ g_value_set_static_string (construct_params[i].value, NM_DBUS_PATH_SETTINGS);
+ } else {
+ if (!g_variant_is_object_path (dbus_path)) {
+ g_warning ("Passed D-Bus object path '%s' is invalid; using default '%s' instead",
+ dbus_path, NM_DBUS_PATH);
+ g_value_set_static_string (construct_params[i].value, NM_DBUS_PATH_SETTINGS);
+ }
+ }
+ break;
}
-
- /* If NM isn't running we'll grab properties from name_owner_changed()
- * when it starts.
- */
- if (!priv->nm_running)
- return TRUE;
- } else
- priv->nm_running = TRUE;
-
- priv->listcon_call = dbus_g_proxy_begin_call (priv->proxy, "ListConnections",
- fetch_connections_done, NM_REMOTE_SETTINGS (initable), NULL,
- G_TYPE_INVALID);
-
- /* Get properties */
- if (!dbus_g_proxy_call (priv->props_proxy, "GetAll", error,
- G_TYPE_STRING, NM_DBUS_INTERFACE_SETTINGS,
- G_TYPE_INVALID,
- DBUS_TYPE_G_MAP_OF_VARIANT, &props,
- G_TYPE_INVALID))
- return FALSE;
- properties_changed_cb (priv->props_proxy, props, settings);
- g_hash_table_destroy (props);
-
- return TRUE;
-}
-
-typedef struct {
- NMRemoteSettings *settings;
- GSimpleAsyncResult *result;
-} NMRemoteSettingsInitData;
-
-static void
-init_async_complete (NMRemoteSettingsInitData *init_data)
-{
- g_simple_async_result_complete (init_data->result);
- g_object_unref (init_data->result);
- g_slice_free (NMRemoteSettingsInitData, init_data);
-}
-
-static void
-init_read_connections (NMRemoteSettings *settings, gpointer user_data)
-{
- NMRemoteSettingsInitData *init_data = user_data;
-
- g_signal_handlers_disconnect_by_func (settings, G_CALLBACK (init_read_connections), user_data);
-
- init_async_complete (init_data);
-}
-
-static void
-init_async_got_properties (DBusGProxy *proxy, DBusGProxyCall *call,
- gpointer user_data)
-{
- NMRemoteSettingsInitData *init_data = user_data;
- NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (init_data->settings);
- GHashTable *props;
- GError *error = NULL;
-
- if (dbus_g_proxy_end_call (proxy, call, &error,
- DBUS_TYPE_G_MAP_OF_VARIANT, &props,
- G_TYPE_INVALID)) {
- properties_changed_cb (priv->props_proxy, props, init_data->settings);
- g_hash_table_destroy (props);
- g_simple_async_result_set_op_res_gboolean (init_data->result, TRUE);
- } else
- g_simple_async_result_take_error (init_data->result, error);
-
- /* Read connections and wait for the result */
- priv->listcon_call = dbus_g_proxy_begin_call (priv->proxy, "ListConnections",
- fetch_connections_done, init_data->settings, NULL,
- G_TYPE_INVALID);
- g_signal_connect (init_data->settings, "connections-read",
- G_CALLBACK (init_read_connections), init_data);
-}
-
-static void
-init_get_properties (NMRemoteSettingsInitData *init_data)
-{
- NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (init_data->settings);
-
- dbus_g_proxy_begin_call (priv->props_proxy, "GetAll",
- init_async_got_properties, init_data, NULL,
- G_TYPE_STRING, NM_DBUS_INTERFACE_SETTINGS,
- G_TYPE_INVALID);
-}
-
-static void
-init_async_got_manager_running (DBusGProxy *proxy, DBusGProxyCall *call,
- gpointer user_data)
-{
- NMRemoteSettingsInitData *init_data = user_data;
- NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (init_data->settings);
- GError *error = NULL;
-
- if (!dbus_g_proxy_end_call (proxy, call, &error,
- G_TYPE_BOOLEAN, &priv->nm_running,
- G_TYPE_INVALID)) {
- g_simple_async_result_take_error (init_data->result, error);
- init_async_complete (init_data);
- return;
- }
-
- if (!priv->nm_running) {
- g_simple_async_result_set_op_res_gboolean (init_data->result, TRUE);
- init_async_complete (init_data);
- return;
}
- init_get_properties (init_data);
-}
-
-static void
-init_async (GAsyncInitable *initable, int io_priority,
- GCancellable *cancellable, GAsyncReadyCallback callback,
- gpointer user_data)
-{
- NMRemoteSettingsInitData *init_data;
- NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (initable);
-
- init_data = g_slice_new0 (NMRemoteSettingsInitData);
- init_data->settings = NM_REMOTE_SETTINGS (initable);
- init_data->result = g_simple_async_result_new (G_OBJECT (initable), callback,
- user_data, init_async);
-
- init_common (init_data->settings);
-
- if (priv->private_bus)
- init_get_properties (init_data);
- else {
- /* Check if NM is running */
- dbus_g_proxy_begin_call (priv->dbus_proxy, "NameHasOwner",
- init_async_got_manager_running,
- init_data, NULL,
- G_TYPE_STRING, NM_DBUS_SERVICE,
- G_TYPE_INVALID);
- }
-}
-
-static gboolean
-init_finish (GAsyncInitable *initable, GAsyncResult *result, GError **error)
-{
- GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
-
- if (g_simple_async_result_propagate_error (simple, error))
- return FALSE;
- else
- return TRUE;
+ return G_OBJECT_CLASS (nm_remote_settings_parent_class)->constructor (type,
+ n_construct_params,
+ construct_params);
}
static void
while (g_slist_length (priv->add_list))
add_connection_info_dispose (self, (AddConnectionInfo *) priv->add_list->data);
- if (priv->connections) {
- g_hash_table_destroy (priv->connections);
- priv->connections = NULL;
- }
+ if (priv->all_connections) {
+ int i;
- if (priv->pending) {
- g_hash_table_destroy (priv->pending);
- priv->pending = NULL;
+ for (i = 0; i < priv->all_connections->len; i++) {
+ cleanup_connection (self, priv->all_connections->pdata[i]);
+ g_object_unref (priv->all_connections->pdata[i]);
+ }
+ g_clear_pointer (&priv->all_connections, g_ptr_array_unref);
}
-
- g_free (priv->hostname);
- priv->hostname = NULL;
-
- g_clear_object (&priv->dbus_proxy);
+ g_clear_pointer (&priv->visible_connections, g_ptr_array_unref);
+ g_clear_pointer (&priv->hostname, g_free);
g_clear_object (&priv->proxy);
- g_clear_object (&priv->props_proxy);
-
- if (priv->bus) {
- dbus_g_connection_unref (priv->bus);
- priv->bus = NULL;
- }
G_OBJECT_CLASS (nm_remote_settings_parent_class)->dispose (object);
}
-static void
-set_property (GObject *object, guint prop_id,
- const GValue *value, GParamSpec *pspec)
-{
- NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (object);
-
- switch (prop_id) {
- case PROP_BUS:
- /* Construct only */
- priv->bus = g_value_dup_boxed (value);
- if (!priv->bus) {
- priv->bus = _nm_dbus_new_connection (NULL);
- priv->private_bus = _nm_dbus_is_connection_private (priv->bus);
- }
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
static void
get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (object);
switch (prop_id) {
- case PROP_BUS:
- g_value_set_boxed (value, priv->bus);
- break;
case PROP_NM_RUNNING:
- g_value_set_boolean (value, priv->nm_running);
+ g_value_set_boolean (value, _nm_object_get_nm_running (NM_OBJECT (object)));
+ break;
+ case PROP_CONNECTIONS:
+ g_value_set_boxed (value, priv->visible_connections);
break;
case PROP_HOSTNAME:
g_value_set_string (value, priv->hostname);
nm_remote_settings_class_init (NMRemoteSettingsClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
+ NMObjectClass *nm_object_class = NM_OBJECT_CLASS (class);
g_type_class_add_private (class, sizeof (NMRemoteSettingsPrivate));
/* Virtual methods */
- object_class->set_property = set_property;
+ object_class->constructor = constructor;
object_class->get_property = get_property;
object_class->dispose = dispose;
- /* Properties */
+ nm_object_class->init_dbus = init_dbus;
+ nm_object_class->object_creation_failed = object_creation_failed;
- /**
- * NMRemoteSettings:bus:
- *
- * The #DBusGConnection that the #NMRemoteSettings is connected to. Defaults
- * to the system bus if not specified.
- */
- g_object_class_install_property
- (object_class, PROP_BUS,
- g_param_spec_boxed (NM_REMOTE_SETTINGS_BUS, "", "",
- DBUS_TYPE_G_CONNECTION,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_STATIC_STRINGS));
+ class->connection_added = connection_added;
+ class->connection_removed = connection_removed;
+
+ /* Properties */
/**
* NMRemoteSettings:nm-running:
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
+ /**
+ * NMRemoteSettings:connections:
+ *
+ * The list of configured connections that are available to the user. (Note
+ * that this differs from the underlying D-Bus property, which may also
+ * contain the object paths of connections that the user does not have
+ * permission to read the details of.)
+ *
+ * Type: GPtrArray
+ */
+ g_object_class_install_property
+ (object_class, PROP_CONNECTIONS,
+ g_param_spec_boxed (NM_REMOTE_SETTINGS_CONNECTIONS, "", "",
+ NM_TYPE_OBJECT_ARRAY,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_STRINGS));
+
/**
* NMRemoteSettings:hostname:
*
G_PARAM_STATIC_STRINGS));
/* Signals */
- signals[NEW_CONNECTION] =
- g_signal_new (NM_REMOTE_SETTINGS_NEW_CONNECTION,
+ /**
+ * NMRemoteSettings::connection-added:
+ * @settings: the settings object that received the signal
+ * @connection: the new connection
+ *
+ * Notifies that a #NMConnection has been added.
+ **/
+ signals[CONNECTION_ADDED] =
+ g_signal_new (NM_REMOTE_SETTINGS_CONNECTION_ADDED,
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (NMRemoteSettingsClass, new_connection),
+ G_STRUCT_OFFSET (NMRemoteSettingsClass, connection_added),
NULL, NULL, NULL,
- G_TYPE_NONE, 1, G_TYPE_OBJECT);
+ G_TYPE_NONE, 1,
+ NM_TYPE_REMOTE_CONNECTION);
- signals[CONNECTIONS_READ] =
- g_signal_new (NM_REMOTE_SETTINGS_CONNECTIONS_READ,
+ /**
+ * NMRemoteSettings::connection-removed:
+ * @settings: the settings object that received the signal
+ * @connection: the removed connection
+ *
+ * Notifies that a #NMConnection has been removed.
+ **/
+ signals[CONNECTION_REMOVED] =
+ g_signal_new (NM_REMOTE_SETTINGS_CONNECTION_REMOVED,
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (NMRemoteSettingsClass, connections_read),
+ G_STRUCT_OFFSET (NMRemoteSettingsClass, connection_removed),
NULL, NULL, NULL,
- G_TYPE_NONE, 0);
-}
-
-static void
-nm_remote_settings_initable_iface_init (GInitableIface *iface)
-{
- iface->init = init_sync;
-}
-
-static void
-nm_remote_settings_async_initable_iface_init (GAsyncInitableIface *iface)
-{
- iface->init_async = init_async;
- iface->init_finish = init_finish;
+ G_TYPE_NONE, 1,
+ NM_TYPE_REMOTE_CONNECTION);
}