diff options
Diffstat (limited to 'libnm/nm-object.c')
-rw-r--r-- | libnm/nm-object.c | 865 |
1 files changed, 150 insertions, 715 deletions
diff --git a/libnm/nm-object.c b/libnm/nm-object.c index aa1c177b2f..abade94b8d 100644 --- a/libnm/nm-object.c +++ b/libnm/nm-object.c @@ -29,7 +29,6 @@ #include "nm-utils.h" #include "nm-dbus-interface.h" -#include "nm-object-cache.h" #include "nm-object-private.h" #include "nm-dbus-helpers.h" #include "nm-client.h" @@ -38,25 +37,18 @@ static gboolean debug = FALSE; #define dbgmsg(f,...) if (G_UNLIKELY (debug)) { g_message (f, ## __VA_ARGS__ ); } +G_DEFINE_QUARK (nm-obj-nm, _nm_object_obj_nm); + static void nm_object_initable_iface_init (GInitableIface *iface); static void nm_object_async_initable_iface_init (GAsyncInitableIface *iface); typedef struct { - NMObjectDecideTypeFunc type_func; - char *interface; - char *property; -} NMObjectTypeFuncData; - -static GHashTable *type_funcs; - -typedef struct { GSList *interfaces; } NMObjectClassPrivate; #define NM_OBJECT_CLASS_GET_PRIVATE(k) (G_TYPE_CLASS_GET_PRIVATE ((k), NM_TYPE_OBJECT, NMObjectClassPrivate)) G_DEFINE_ABSTRACT_TYPE_WITH_CODE (NMObject, nm_object, G_TYPE_OBJECT, - type_funcs = g_hash_table_new (NULL, NULL); g_type_add_class_private (g_define_type_id, sizeof (NMObjectClassPrivate)); G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, nm_object_initable_iface_init); G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, nm_object_async_initable_iface_init); @@ -75,15 +67,11 @@ static void reload_complete (NMObject *object, gboolean emit_now); static gboolean demarshal_generic (NMObject *object, GParamSpec *pspec, GVariant *value, gpointer field); typedef struct { - GDBusConnection *connection; - gboolean nm_running; + GDBusObject *object; + GDBusObjectManager *object_manager; - char *path; - GHashTable *proxies; - GDBusProxy *properties_proxy; GSList *property_tables; NMObject *parent; - gboolean suppress_property_updates; gboolean inited; /* async init finished? */ GSList *waiters; /* if async init did not finish, users of this object need @@ -104,50 +92,27 @@ enum { PROP_PATH, PROP_DBUS_CONNECTION, PROP_NM_RUNNING, + PROP_DBUS_OBJECT, + PROP_DBUS_OBJECT_MANAGER, LAST_PROP }; /** - * _nm_object_class_add_interface: - * @object_class: an #NMObjectClass - * @interface: a D-Bus interface name - * - * Registers that @object_class implements @interface. A proxy for that - * interface will automatically be created at construction time, and can - * be retrieved with _nm_object_get_proxy(). - */ -void -_nm_object_class_add_interface (NMObjectClass *object_class, - const char *interface) -{ - NMObjectClassPrivate *cpriv; - - g_return_if_fail (NM_IS_OBJECT_CLASS (object_class)); - g_return_if_fail (interface); - - cpriv = NM_OBJECT_CLASS_GET_PRIVATE (object_class); - - g_return_if_fail (g_slist_find_custom (cpriv->interfaces, interface, (GCompareFunc) g_strcmp0) == NULL); - - cpriv->interfaces = g_slist_prepend (cpriv->interfaces, g_strdup (interface)); -} - -/** * nm_object_get_path: * @object: a #NMObject * * Gets the DBus path of the #NMObject. * * Returns: the object's path. This is the internal string used by the - * device, and must not be modified. + * object, and must not be modified. **/ const char * nm_object_get_path (NMObject *object) { g_return_val_if_fail (NM_IS_OBJECT (object), NULL); - return NM_OBJECT_GET_PRIVATE (object)->path; + return g_dbus_object_get_object_path (NM_OBJECT_GET_PRIVATE (object)->object); } /** @@ -163,13 +128,14 @@ GDBusProxy * _nm_object_get_proxy (NMObject *object, const char *interface) { - GDBusProxy *proxy; + GDBusInterface *proxy; g_return_val_if_fail (NM_IS_OBJECT (object), NULL); - proxy = g_hash_table_lookup (NM_OBJECT_GET_PRIVATE (object)->proxies, interface); + proxy = g_dbus_object_get_interface (NM_OBJECT_GET_PRIVATE (object)->object, interface); g_return_val_if_fail (proxy != NULL, NULL); - return proxy; + + return G_DBUS_PROXY (proxy); } typedef enum { @@ -351,97 +317,6 @@ _nm_object_queue_notify (NMObject *object, const char *property) _nm_object_queue_notify_full (object, property, NULL, FALSE, NULL); } -void -_nm_object_register_type_func (GType base_type, - NMObjectDecideTypeFunc type_func, - const char *interface, - const char *property) -{ - NMObjectTypeFuncData *type_data; - - g_return_if_fail (type_func != NULL); - g_return_if_fail (interface != NULL); - g_return_if_fail (property != NULL); - - type_data = g_slice_new (NMObjectTypeFuncData); - type_data->type_func = type_func; - type_data->interface = g_strdup (interface); - type_data->property = g_strdup (property); - - g_hash_table_insert (type_funcs, - GSIZE_TO_POINTER (base_type), - type_data); -} - -static GObject * -_nm_object_create (GType type, GDBusConnection *connection, const char *path) -{ - NMObjectTypeFuncData *type_data; - GObject *object; - GError *error = NULL; - - type_data = g_hash_table_lookup (type_funcs, GSIZE_TO_POINTER (type)); - if (type_data) { - GDBusProxy *proxy; - GVariant *ret, *value; - - proxy = _nm_dbus_new_proxy_for_connection (connection, path, - DBUS_INTERFACE_PROPERTIES, - NULL, &error); - if (!proxy) { - g_warning ("Could not create proxy for %s: %s.", path, error->message); - g_error_free (error); - return NULL; - } - - ret = g_dbus_proxy_call_sync (proxy, - "Get", - g_variant_new ("(ss)", - type_data->interface, - type_data->property), - G_DBUS_CALL_FLAGS_NONE, -1, - NULL, &error); - g_object_unref (proxy); - if (!ret) { - dbgmsg ("Could not fetch property '%s' of interface '%s' on %s: %s\n", - type_data->property, type_data->interface, path, error->message); - g_error_free (error); - return NULL; - } - - g_variant_get (ret, "(v)", &value); - type = type_data->type_func (value); - g_variant_unref (value); - g_variant_unref (ret); - } - - if (type == G_TYPE_INVALID) { - dbgmsg ("Could not create object for %s: unknown object type", path); - return NULL; - } - - object = g_object_new (type, - NM_OBJECT_PATH, path, - NM_OBJECT_DBUS_CONNECTION, connection, - NULL); - /* Cache the object before initializing it (and in particular, loading its - * property values); this is necessary to make circular references work (eg, - * when creating an NMActiveConnection, it will create an NMDevice which - * will in turn try to create the parent NMActiveConnection). Since we don't - * support multi-threaded use, we know that we will have inited the object - * before any external code sees it. - */ - _nm_object_cache_add (NM_OBJECT (object)); - NM_OBJECT_GET_PRIVATE (object)->inited = TRUE; - if (!g_initable_init (G_INITABLE (object), NULL, &error)) { - dbgmsg ("Could not create object for %s: %s", path, error->message); - g_error_free (error); - g_clear_object (&object); - } - - return object; -} - typedef struct { NMObject *self; PropertyInfo *pi; @@ -465,176 +340,6 @@ odata_free (gpointer data) static void object_property_maybe_complete (NMObject *self); - -typedef void (*NMObjectCreateCallbackFunc) (GObject *, const char *, gpointer); -typedef struct { - char *path; - NMObjectCreateCallbackFunc callback; - gpointer user_data; - NMObjectTypeFuncData *type_data; - GDBusConnection *connection; -} NMObjectTypeAsyncData; - -static void -create_async_complete (GObject *object, NMObjectTypeAsyncData *async_data) -{ - async_data->callback (object, async_data->path, async_data->user_data); - - g_free (async_data->path); - g_object_unref (async_data->connection); - g_slice_free (NMObjectTypeAsyncData, async_data); -} - -static void -create_async_inited (GObject *object, GAsyncResult *result, gpointer user_data) -{ - NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object); - NMObjectPrivate *odata_priv; - NMObjectTypeAsyncData *async_data = user_data; - GError *error = NULL; - ObjectCreatedData *odata; - - priv->inited = TRUE; - if (!g_async_initable_init_finish (G_ASYNC_INITABLE (object), result, &error)) { - dbgmsg ("Could not create object for %s: %s", - nm_object_get_path (NM_OBJECT (object)), - error->message); - - while (priv->waiters) { - odata = priv->waiters->data; - odata_priv = NM_OBJECT_GET_PRIVATE (odata->self); - - priv->waiters = g_slist_remove (priv->waiters, odata); - if (!odata_priv->reload_error) - odata_priv->reload_error = g_error_copy (error); - odata_priv->reload_remaining--; - reload_complete (odata->self, FALSE); - } - - g_error_free (error); - g_clear_object (&object); - } - - create_async_complete (object, async_data); - - if (object) { - /* There are some object properties whose creation couldn't proceed - * because it depended on this object. */ - while (priv->waiters) { - odata = priv->waiters->data; - priv->waiters = g_slist_remove (priv->waiters, odata); - object_property_maybe_complete (odata->self); - } - } -} - -static void -create_async_got_type (NMObjectTypeAsyncData *async_data, GType type) -{ - GObject *object; - - /* Ensure we don't have the object already; we may get multiple type - * requests for the same object if there are multiple properties on - * other objects that refer to the object at this path. One of those - * other requests may have already completed. - */ - object = (GObject *) _nm_object_cache_get (async_data->path); - if (object) { - create_async_complete (object, async_data); - return; - } - - if (type == G_TYPE_INVALID) { - /* Don't know how to create this object */ - create_async_complete (NULL, async_data); - return; - } - - object = g_object_new (type, - NM_OBJECT_PATH, async_data->path, - NM_OBJECT_DBUS_CONNECTION, async_data->connection, - NULL); - _nm_object_cache_add (NM_OBJECT (object)); - g_async_initable_init_async (G_ASYNC_INITABLE (object), G_PRIORITY_DEFAULT, - NULL, create_async_inited, async_data); -} - -static void -create_async_got_property (GObject *proxy, GAsyncResult *result, gpointer user_data) -{ - NMObjectTypeAsyncData *async_data = user_data; - NMObjectTypeFuncData *type_data = async_data->type_data; - GVariant *ret, *value; - GError *error = NULL; - GType type; - - ret = _nm_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), result, - G_VARIANT_TYPE ("(v)"), &error); - if (ret) { - g_variant_get (ret, "(v)", &value); - type = type_data->type_func (value); - g_variant_unref (value); - g_variant_unref (ret); - } else { - dbgmsg ("Could not fetch property '%s' of interface '%s' on %s: %s\n", - type_data->property, type_data->interface, async_data->path, - error->message); - g_clear_error (&error); - type = G_TYPE_INVALID; - } - - create_async_got_type (async_data, type); -} - -static void -create_async_got_proxy (GObject *object, GAsyncResult *result, gpointer user_data) -{ - NMObjectTypeAsyncData *async_data = user_data; - GDBusProxy *proxy; - GError *error = NULL; - - proxy = _nm_dbus_new_proxy_for_connection_finish (result, &error); - if (!proxy) { - g_warning ("Could not create proxy for %s: %s.", async_data->path, error->message); - g_error_free (error); - create_async_complete (NULL, async_data); - return; - } - - g_dbus_proxy_call (proxy, - "Get", - g_variant_new ("(ss)", - async_data->type_data->interface, - async_data->type_data->property), - G_DBUS_CALL_FLAGS_NONE, -1, - NULL, - create_async_got_property, async_data); -} - -static void -_nm_object_create_async (GType type, GDBusConnection *connection, const char *path, - NMObjectCreateCallbackFunc callback, gpointer user_data) -{ - NMObjectTypeAsyncData *async_data; - - async_data = g_slice_new (NMObjectTypeAsyncData); - async_data->path = g_strdup (path); - async_data->callback = callback; - async_data->user_data = user_data; - async_data->connection = g_object_ref (connection); - - async_data->type_data = g_hash_table_lookup (type_funcs, GSIZE_TO_POINTER (type)); - if (async_data->type_data) { - _nm_dbus_new_proxy_for_connection_async (connection, path, - DBUS_INTERFACE_PROPERTIES, - NULL, - create_async_got_proxy, async_data); - return; - } - - create_async_got_type (async_data, type); -} - /* Stolen from dbus-glib */ static char* wincaps_to_dash (const char *caps) @@ -855,15 +560,16 @@ object_created (GObject *obj, const char *path, gpointer user_data) object_class->object_creation_failed (odata->self, path); } - odata->objects[--odata->remaining] = obj; + odata->objects[--odata->remaining] = obj ? g_object_ref (obj) : NULL; object_property_maybe_complete (odata->self); } static gboolean handle_object_property (NMObject *self, const char *property_name, GVariant *value, - PropertyInfo *pi, gboolean synchronously) + PropertyInfo *pi) { NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self); + gs_unref_object GDBusObject *object = NULL; GObject *obj; const char *path; ObjectCreatedData *odata; @@ -886,31 +592,28 @@ handle_object_property (NMObject *self, const char *property_name, GVariant *val return TRUE; } - obj = G_OBJECT (_nm_object_cache_get (path)); - if (obj) { - object_created (obj, path, odata); - return TRUE; - } else if (synchronously) { - obj = _nm_object_create (pi->object_type, priv->connection, path); - object_created (obj, path, odata); - return obj != NULL; - } else { - _nm_object_create_async (pi->object_type, priv->connection, path, - object_created, odata); - /* Assume success */ - return TRUE; + object = g_dbus_object_manager_get_object (priv->object_manager, path); + if (!object) { + /* This is a server bug -- a dangling object path for an object + * that does not exist. */ + g_warning ("No object known for %s", path); + return FALSE; } + + obj = g_object_get_qdata (G_OBJECT (object), _nm_object_obj_nm_quark ()); + object_created (obj, path, odata); + + return TRUE; } static gboolean handle_object_array_property (NMObject *self, const char *property_name, GVariant *value, - PropertyInfo *pi, gboolean synchronously) + PropertyInfo *pi) { NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self); GObject *obj; GVariantIter iter; gsize npaths; - GPtrArray **array = pi->field; const char *path; ObjectCreatedData *odata; @@ -934,34 +637,28 @@ handle_object_array_property (NMObject *self, const char *property_name, GVarian g_variant_iter_init (&iter, value); while (g_variant_iter_next (&iter, "&o", &path)) { + gs_unref_object GDBusObject *object = NULL; + if (!strcmp (path, "/")) { /* FIXME: can't happen? */ continue; } - obj = G_OBJECT (_nm_object_cache_get (path)); - if (obj) { - object_created (obj, path, odata); - } else if (synchronously) { - obj = _nm_object_create (pi->object_type, priv->connection, path); - object_created (obj, path, odata); - } else { - _nm_object_create_async (pi->object_type, priv->connection, path, - object_created, odata); + object = g_dbus_object_manager_get_object (priv->object_manager, path); + if (!object) { + g_warning ("no object known for %s\n", path); + return FALSE; } - } - if (!synchronously) { - /* Assume success */ - return TRUE; + obj = g_object_get_qdata (G_OBJECT (object), _nm_object_obj_nm_quark ()); + object_created (obj, path, odata); } - return *array && ((*array)->len == npaths); + return TRUE; } static void -handle_property_changed (NMObject *self, const char *dbus_name, - GVariant *value, gboolean synchronously) +handle_property_changed (NMObject *self, const char *dbus_name, GVariant *value) { NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self); char *prop_name; @@ -1015,9 +712,9 @@ handle_property_changed (NMObject *self, const char *dbus_name, if (pspec && pi->object_type) { if (g_variant_is_of_type (value, G_VARIANT_TYPE_OBJECT_PATH)) - success = handle_object_property (self, pspec->name, value, pi, synchronously); + success = handle_object_property (self, pspec->name, value, pi); else if (g_variant_is_of_type (value, G_VARIANT_TYPE ("ao"))) - success = handle_object_array_property (self, pspec->name, value, pi, synchronously); + success = handle_object_array_property (self, pspec->name, value, pi); else { g_warn_if_reached (); goto out; @@ -1037,31 +734,23 @@ out: } static void -process_properties_changed (NMObject *self, GVariant *properties, gboolean synchronously) +properties_changed (GDBusProxy *proxy, + GVariant *changed_properties, + GStrv invalidated_properties, + gpointer user_data) { - NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self); + NMObject *self = NM_OBJECT (user_data); GVariantIter iter; const char *name; GVariant *value; - if (priv->suppress_property_updates) - return; - - g_variant_iter_init (&iter, properties); + g_variant_iter_init (&iter, changed_properties); while (g_variant_iter_next (&iter, "{&sv}", &name, &value)) { - handle_property_changed (self, name, value, synchronously); + handle_property_changed (self, name, value); g_variant_unref (value); } } -static void -properties_changed (GDBusProxy *proxy, - GVariant *properties, - gpointer user_data) -{ - process_properties_changed (NM_OBJECT (user_data), properties, FALSE); -} - #define HANDLE_TYPE(vtype, ctype, getter) \ G_STMT_START { \ if (g_variant_is_of_type (value, vtype)) { \ @@ -1240,10 +929,8 @@ _nm_object_register_properties (NMObject *object, } proxy = _nm_object_get_proxy (object, interface); - g_return_if_fail (proxy != NULL); - - _nm_dbus_signal_connect (proxy, "PropertiesChanged", G_VARIANT_TYPE ("(a{sv})"), - G_CALLBACK (properties_changed), object); + g_signal_connect (proxy, "g-properties-changed", + G_CALLBACK (properties_changed), object); instance = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); priv->property_tables = g_slist_prepend (priv->property_tables, instance); @@ -1265,92 +952,6 @@ _nm_object_register_properties (NMObject *object, } } -static gboolean -_nm_object_reload_properties (NMObject *object, GError **error) -{ - NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object); - GVariant *ret, *props; - GHashTableIter iter; - const char *interface; - GDBusProxy *proxy; - - if (!g_hash_table_size (priv->proxies) || !priv->nm_running) - return TRUE; - - priv->reload_remaining++; - - g_hash_table_iter_init (&iter, priv->proxies); - while (g_hash_table_iter_next (&iter, (gpointer *) &interface, (gpointer *) &proxy)) { - ret = _nm_dbus_proxy_call_sync (priv->properties_proxy, - "GetAll", - g_variant_new ("(s)", interface), - G_VARIANT_TYPE ("(a{sv})"), - G_DBUS_CALL_FLAGS_NONE, -1, - NULL, error); - if (!ret) { - if (error && *error) - g_dbus_error_strip_remote_error (*error); - return FALSE; - } - - g_variant_get (ret, "(@a{sv})", &props); - process_properties_changed (object, props, TRUE); - g_variant_unref (props); - g_variant_unref (ret); - } - - if (--priv->reload_remaining == 0) - reload_complete (object, TRUE); - - return TRUE; -} - -void -_nm_object_suppress_property_updates (NMObject *object, gboolean suppress) -{ - NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object); - - priv->suppress_property_updates = suppress; -} - - -void -_nm_object_reload_property (NMObject *object, - const char *interface, - const char *prop_name) -{ - GVariant *ret, *value; - GError *err = NULL; - - g_return_if_fail (NM_IS_OBJECT (object)); - g_return_if_fail (interface != NULL); - g_return_if_fail (prop_name != NULL); - - if (!NM_OBJECT_GET_PRIVATE (object)->nm_running) - return; - - ret = _nm_dbus_proxy_call_sync (NM_OBJECT_GET_PRIVATE (object)->properties_proxy, - "Get", - g_variant_new ("(ss)", interface, prop_name), - G_VARIANT_TYPE ("(v)"), - G_DBUS_CALL_FLAGS_NONE, 15000, - NULL, &err); - if (!ret) { - dbgmsg ("%s: Error getting '%s' for %s: %s\n", - __func__, - prop_name, - nm_object_get_path (object), - err->message); - g_clear_error (&err); - return; - } - - g_variant_get (ret, "(v)", &value); - handle_property_changed (object, prop_name, value, TRUE); - g_variant_unref (value); - g_variant_unref (ret); -} - void _nm_object_set_property (NMObject *object, const char *interface, @@ -1366,16 +967,13 @@ _nm_object_set_property (NMObject *object, g_return_if_fail (prop_name != NULL); g_return_if_fail (format_string != NULL); - if (!NM_OBJECT_GET_PRIVATE (object)->nm_running) - return; - va_start (ap, format_string); val = g_variant_new_va (format_string, NULL, &ap); va_end (ap); g_return_if_fail (val != NULL); - ret = g_dbus_proxy_call_sync (NM_OBJECT_GET_PRIVATE (object)->properties_proxy, - "Set", + ret = g_dbus_proxy_call_sync (_nm_object_get_proxy (object, interface), + DBUS_INTERFACE_PROPERTIES ".Set", g_variant_new ("(ssv)", interface, prop_name, val), G_DBUS_CALL_FLAGS_NONE, 2000, NULL, NULL); @@ -1418,139 +1016,40 @@ reload_complete (NMObject *object, gboolean emit_now) g_clear_error (&error); } -static void -reload_got_properties (GObject *proxy, - GAsyncResult *result, - gpointer user_data) -{ - NMObject *object = user_data; - NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object); - GVariant *ret, *props; - GError *error = NULL; - - ret = _nm_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), result, - G_VARIANT_TYPE ("(a{sv})"), - &error); - if (ret) { - g_variant_get (ret, "(@a{sv})", &props); - process_properties_changed (object, props, FALSE); - g_variant_unref (props); - g_variant_unref (ret); - } else { - g_dbus_error_strip_remote_error (error); - if (priv->reload_error) - g_error_free (error); - else - priv->reload_error = error; - } - - if (--priv->reload_remaining == 0) - reload_complete (object, FALSE); -} - -void -_nm_object_reload_properties_async (NMObject *object, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object); - GSimpleAsyncResult *simple; - GHashTableIter iter; - const char *interface; - GDBusProxy *proxy; - - simple = g_simple_async_result_new (G_OBJECT (object), callback, - user_data, _nm_object_reload_properties_async); - - if (!g_hash_table_size (priv->proxies) || !priv->nm_running) { - g_simple_async_result_complete_in_idle (simple); - g_object_unref (simple); - return; - } - - priv->reload_results = g_slist_prepend (priv->reload_results, simple); - - /* If there was already a reload happening, we don't need to - * re-read the properties again, we just need to wait for the - * existing reload to finish. - */ - if (priv->reload_results->next) - return; - - g_hash_table_iter_init (&iter, priv->proxies); - while (g_hash_table_iter_next (&iter, (gpointer *) &interface, (gpointer *) &proxy)) { - priv->reload_remaining++; - g_dbus_proxy_call (priv->properties_proxy, - "GetAll", - g_variant_new ("(s)", interface), - G_DBUS_CALL_FLAGS_NONE, -1, - cancellable, - reload_got_properties, object); - } -} - -gboolean -_nm_object_reload_properties_finish (NMObject *object, GAsyncResult *result, GError **error) -{ - NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object); - GSimpleAsyncResult *simple; - - g_return_val_if_fail (NM_IS_OBJECT (object), FALSE); - g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (object), _nm_object_reload_properties_async), FALSE); - - /* NM might have disappeared meanwhile. That would cause a NoReply error to be emitted, - * but we don't care if property updates were disabled. */ - if (priv->suppress_property_updates) - return TRUE; - - simple = G_SIMPLE_ASYNC_RESULT (result); - if (g_simple_async_result_propagate_error (simple, error)) - return FALSE; - - return g_simple_async_result_get_op_res_gboolean (simple); -} - -gboolean -_nm_object_get_nm_running (NMObject *self) +GDBusObjectManager * +_nm_object_get_dbus_object_manager (NMObject *self) { - return NM_OBJECT_GET_PRIVATE (self)->nm_running; + return NM_OBJECT_GET_PRIVATE (self)->object_manager; } /*****************************************************************************/ static void -on_name_owner_changed (GObject *proxy, - GParamSpec *pspec, - gpointer user_data) +init_dbus (NMObject *object) { - NMObject *self = NM_OBJECT (user_data); - NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self); - gboolean now_running; - char *owner; - - now_running = ((owner = g_dbus_proxy_get_name_owner (priv->properties_proxy)) != NULL); - g_free (owner); - if (now_running != priv->nm_running) { - priv->nm_running = now_running; - g_object_notify (G_OBJECT (self), NM_OBJECT_NM_RUNNING); - } } static void -init_dbus (NMObject *object) +init_if (GDBusInterface *interface, gpointer user_data) { - NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object); - char *owner; - - if (_nm_dbus_is_connection_private (priv->connection)) - priv->nm_running = TRUE; - else { - priv->nm_running = ((owner = g_dbus_proxy_get_name_owner (priv->properties_proxy)) != NULL); - g_free (owner); - g_signal_connect (priv->properties_proxy, "notify::g-name-owner", - G_CALLBACK (on_name_owner_changed), object); + NMObject *self = NM_OBJECT (user_data); + GDBusProxy *proxy = G_DBUS_PROXY (interface); + gchar **props; + char **prop; + GVariant *val; + gchar *str; + + props = g_dbus_proxy_get_cached_property_names (proxy); + + for (prop = props; *prop; prop++) { + val = g_dbus_proxy_get_cached_property (proxy, *prop); + str = g_variant_print (val, TRUE); + handle_property_changed (self, *prop, val); + g_variant_unref (val); + g_free (str); } + + g_strfreev (props); } static gboolean @@ -1558,42 +1057,33 @@ init_sync (GInitable *initable, GCancellable *cancellable, GError **error) { NMObject *self = NM_OBJECT (initable); NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self); - NMObjectClassPrivate *cpriv = NM_OBJECT_CLASS_GET_PRIVATE (NM_OBJECT_GET_CLASS (self)); - GSList *iter; + GList *interfaces; - if (!priv->path) { - g_set_error_literal (error, NM_CLIENT_ERROR, NM_CLIENT_ERROR_OBJECT_CREATION_FAILED, - _("Caller did not specify D-Bus path for object")); - return FALSE; - } + g_assert (priv->object && priv->object_manager); - if (!priv->connection) - priv->connection = _nm_dbus_new_connection (cancellable, error); - if (!priv->connection) - return FALSE; + NM_OBJECT_GET_CLASS (self)->init_dbus (self); - /* Create proxies */ - for (iter = cpriv->interfaces; iter; iter = iter->next) { - const char *interface = iter->data; - GDBusProxy *proxy; + priv->reload_remaining++; - proxy = _nm_dbus_new_proxy_for_connection (priv->connection, priv->path, interface, - cancellable, error); - if (!proxy) - return FALSE; - g_hash_table_insert (priv->proxies, (char *) interface, proxy); - } + interfaces = g_dbus_object_get_interfaces (priv->object); + g_list_foreach (interfaces, (GFunc) init_if, self); + g_list_free_full (interfaces, g_object_unref); - priv->properties_proxy = _nm_dbus_new_proxy_for_connection (priv->connection, - priv->path, - DBUS_INTERFACE_PROPERTIES, - cancellable, error); - if (!priv->properties_proxy) - return FALSE; + priv->inited = TRUE; - NM_OBJECT_GET_CLASS (self)->init_dbus (self); + if (--priv->reload_remaining == 0) + reload_complete (self, TRUE); + + /* There are some object properties whose creation couldn't proceed + * because it depended on this object. */ + while (priv->waiters) { + ObjectCreatedData *odata = priv->waiters->data; - return _nm_object_reload_properties (self, error); + priv->waiters = g_slist_remove (priv->waiters, odata); + object_property_maybe_complete (odata->self); + } + + return TRUE; } /*****************************************************************************/ @@ -1613,88 +1103,13 @@ init_async_complete (NMObjectInitData *init_data) g_simple_async_result_take_error (init_data->simple, init_data->error); else g_simple_async_result_set_op_res_gboolean (init_data->simple, TRUE); - g_simple_async_result_complete (init_data->simple); + g_simple_async_result_complete_in_idle (init_data->simple); g_object_unref (init_data->simple); g_clear_object (&init_data->cancellable); g_slice_free (NMObjectInitData, init_data); } static void -init_async_got_properties (GObject *object, GAsyncResult *result, gpointer user_data) -{ - NMObjectInitData *init_data = user_data; - - _nm_object_reload_properties_finish (NM_OBJECT (object), result, &init_data->error); - init_async_complete (init_data); -} - -static void -init_async_got_proxy (GObject *object, GAsyncResult *result, gpointer user_data) -{ - NMObjectInitData *init_data = user_data; - NMObject *self = init_data->object; - NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self); - GDBusProxy *proxy; - - if (!init_data->error) { - proxy = _nm_dbus_new_proxy_for_connection_finish (result, &init_data->error); - if (proxy) { - const char *interface = g_dbus_proxy_get_interface_name (proxy); - - if (!strcmp (interface, DBUS_INTERFACE_PROPERTIES)) - priv->properties_proxy = proxy; - else - g_hash_table_insert (priv->proxies, (char *) interface, proxy); - } - } - - init_data->proxies_pending--; - if (init_data->proxies_pending) - return; - - if (init_data->error) { - init_async_complete (init_data); - return; - } - - NM_OBJECT_GET_CLASS (self)->init_dbus (self); - - _nm_object_reload_properties_async (init_data->object, init_data->cancellable, init_async_got_properties, init_data); -} - -static void -init_async_got_bus (GObject *object, GAsyncResult *result, gpointer user_data) -{ - NMObjectInitData *init_data = user_data; - NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (init_data->object); - NMObjectClassPrivate *cpriv = NM_OBJECT_CLASS_GET_PRIVATE (NM_OBJECT_GET_CLASS (init_data->object)); - GSList *iter; - - priv->connection = _nm_dbus_new_connection_finish (result, &init_data->error); - if (!priv->connection) { - init_async_complete (init_data); - return; - } - - for (iter = cpriv->interfaces; iter; iter = iter->next) { - const char *interface = iter->data; - - _nm_dbus_new_proxy_for_connection_async (priv->connection, - priv->path, interface, - init_data->cancellable, - init_async_got_proxy, init_data); - init_data->proxies_pending++; - } - - _nm_dbus_new_proxy_for_connection_async (priv->connection, - priv->path, - DBUS_INTERFACE_PROPERTIES, - init_data->cancellable, - init_async_got_proxy, init_data); - init_data->proxies_pending++; -} - -static void init_async (GAsyncInitable *initable, int io_priority, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) @@ -1702,29 +1117,40 @@ init_async (GAsyncInitable *initable, int io_priority, NMObject *self = NM_OBJECT (initable); NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self); NMObjectInitData *init_data; + GList *interfaces; - if (!priv->path) { - g_simple_async_report_error_in_idle (G_OBJECT (initable), - callback, user_data, - NM_CLIENT_ERROR, - NM_CLIENT_ERROR_OBJECT_CREATION_FAILED, - "%s", - _("Caller did not specify D-Bus path for object")); - return; - } + g_assert (priv->object && priv->object_manager); + + NM_OBJECT_GET_CLASS (self)->init_dbus (self); init_data = g_slice_new0 (NMObjectInitData); init_data->object = self; init_data->simple = g_simple_async_result_new (G_OBJECT (initable), callback, user_data, init_async); init_data->cancellable = cancellable ? g_object_ref (cancellable) : NULL; - _nm_dbus_new_connection_async (cancellable, init_async_got_bus, init_data); + interfaces = g_dbus_object_get_interfaces (priv->object); + g_list_foreach (interfaces, (GFunc) init_if, self); + g_list_free_full (interfaces, g_object_unref); + + init_async_complete (init_data); } static gboolean init_finish (GAsyncInitable *initable, GAsyncResult *result, GError **error) { GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result); + NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (initable); + + priv->inited = TRUE; + + /* There are some object properties whose creation couldn't proceed + * because it depended on this object. */ + while (priv->waiters) { + ObjectCreatedData *odata = priv->waiters->data; + + priv->waiters = g_slist_remove (priv->waiters, odata); + object_property_maybe_complete (odata->self); + } if (g_simple_async_result_propagate_error (simple, error)) return FALSE; @@ -1750,9 +1176,6 @@ nm_object_async_initable_iface_init (GAsyncInitableIface *iface) static void nm_object_init (NMObject *object) { - NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object); - - priv->proxies = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref); } static void @@ -1762,13 +1185,13 @@ set_property (GObject *object, guint prop_id, NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object); switch (prop_id) { - case PROP_PATH: + case PROP_DBUS_OBJECT: /* Construct only */ - priv->path = g_value_dup_string (value); + priv->object = g_value_dup_object (value); break; - case PROP_DBUS_CONNECTION: + case PROP_DBUS_OBJECT_MANAGER: /* Construct only */ - priv->connection = g_value_dup_object (value); + priv->object_manager = g_value_dup_object (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -1784,13 +1207,16 @@ get_property (GObject *object, guint prop_id, switch (prop_id) { case PROP_PATH: - g_value_set_string (value, priv->path); + g_value_set_string (value, nm_object_get_path (NM_OBJECT (object))); break; case PROP_DBUS_CONNECTION: - g_value_set_object (value, priv->connection); + g_value_set_object (value, g_dbus_object_manager_client_get_connection (G_DBUS_OBJECT_MANAGER_CLIENT (priv->object_manager))); break; - case PROP_NM_RUNNING: - g_value_set_boolean (value, priv->nm_running); + case PROP_DBUS_OBJECT: + g_value_set_object (value, priv->object); + break; + case PROP_DBUS_OBJECT_MANAGER: + g_value_set_object (value, priv->object_manager); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -1809,10 +1235,9 @@ dispose (GObject *object) priv->notify_items = NULL; g_slist_free_full (priv->waiters, odata_free); - g_clear_pointer (&priv->proxies, g_hash_table_unref); - g_clear_object (&priv->properties_proxy); - g_clear_object (&priv->connection); + g_clear_object (&priv->object); + g_clear_object (&priv->object_manager); G_OBJECT_CLASS (nm_object_parent_class)->dispose (object); } @@ -1823,7 +1248,6 @@ finalize (GObject *object) NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object); g_slist_free_full (priv->property_tables, (GDestroyNotify) g_hash_table_destroy); - g_free (priv->path); G_OBJECT_CLASS (nm_object_parent_class)->finalize (object); } @@ -1846,7 +1270,7 @@ nm_object_class_init (NMObjectClass *nm_object_class) /* Properties */ /** - * NMObject:path: + * NMObject:path: (skip) * * The D-Bus object path. **/ @@ -1854,8 +1278,7 @@ nm_object_class_init (NMObjectClass *nm_object_class) (object_class, PROP_PATH, g_param_spec_string (NM_OBJECT_PATH, "", "", NULL, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); /** @@ -1867,20 +1290,32 @@ nm_object_class_init (NMObjectClass *nm_object_class) (object_class, PROP_DBUS_CONNECTION, g_param_spec_object (NM_OBJECT_DBUS_CONNECTION, "", "", G_TYPE_DBUS_CONNECTION, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMObject:dbus-object: (skip) + * + * The #GDBusObject of the object. + **/ + g_object_class_install_property + (object_class, PROP_DBUS_OBJECT, + g_param_spec_object (NM_OBJECT_DBUS_OBJECT, "", "", + G_TYPE_DBUS_OBJECT, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); /** - * NMObject:manager-running: (skip) + * NMObject:dbus-object-manager: (skip) * - * Internal use only. - */ + * The #GDBusObjectManager of the object. + **/ g_object_class_install_property - (object_class, PROP_NM_RUNNING, - g_param_spec_boolean (NM_OBJECT_NM_RUNNING, "", "", - FALSE, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); + (object_class, PROP_DBUS_OBJECT_MANAGER, + g_param_spec_object (NM_OBJECT_DBUS_OBJECT_MANAGER, "", "", + G_TYPE_DBUS_OBJECT_MANAGER, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); } - |