2019-09-10 11:19:01 +02:00
|
|
|
// SPDX-License-Identifier: LGPL-2.1+
|
2014-07-24 08:53:33 -04:00
|
|
|
/*
|
2019-10-01 09:20:35 +02:00
|
|
|
* Copyright (C) 2007 - 2008 Novell, Inc.
|
|
|
|
|
* Copyright (C) 2007 - 2012 Red Hat, Inc.
|
2014-07-24 08:53:33 -04:00
|
|
|
*/
|
|
|
|
|
|
2016-02-12 14:44:52 +01:00
|
|
|
#include "nm-default.h"
|
2016-02-19 14:57:48 +01:00
|
|
|
|
2016-02-12 14:44:52 +01:00
|
|
|
#include "nm-object.h"
|
|
|
|
|
|
2014-07-24 08:53:33 -04:00
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <stdio.h>
|
2016-02-12 14:44:52 +01:00
|
|
|
|
|
|
|
|
#include "nm-utils.h"
|
2014-07-05 16:23:30 -04:00
|
|
|
#include "nm-dbus-interface.h"
|
2014-07-24 08:53:33 -04:00
|
|
|
#include "nm-object-private.h"
|
2014-08-19 09:52:41 -04:00
|
|
|
#include "nm-dbus-helpers.h"
|
2014-10-20 14:03:30 -04:00
|
|
|
#include "nm-client.h"
|
2015-03-27 08:03:22 -04:00
|
|
|
#include "nm-core-internal.h"
|
2018-04-06 16:40:23 +02:00
|
|
|
#include "c-list/src/c-list.h"
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
static gboolean debug = FALSE;
|
|
|
|
|
#define dbgmsg(f,...) if (G_UNLIKELY (debug)) { g_message (f, ## __VA_ARGS__ ); }
|
|
|
|
|
|
2017-02-02 21:47:03 +01:00
|
|
|
NM_CACHED_QUARK_FCN ("nm-obj-nm", _nm_object_obj_nm_quark)
|
2016-10-18 16:35:07 +02:00
|
|
|
|
2014-07-24 08:53:33 -04:00
|
|
|
static void nm_object_initable_iface_init (GInitableIface *iface);
|
|
|
|
|
static void nm_object_async_initable_iface_init (GAsyncInitableIface *iface);
|
|
|
|
|
|
2014-08-18 14:17:52 -04:00
|
|
|
typedef struct {
|
|
|
|
|
GSList *interfaces;
|
|
|
|
|
} NMObjectClassPrivate;
|
|
|
|
|
|
|
|
|
|
#define NM_OBJECT_CLASS_GET_PRIVATE(k) (G_TYPE_CLASS_GET_PRIVATE ((k), NM_TYPE_OBJECT, NMObjectClassPrivate))
|
|
|
|
|
|
2014-07-24 08:53:33 -04:00
|
|
|
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (NMObject, nm_object, G_TYPE_OBJECT,
|
2014-08-18 14:17:52 -04:00
|
|
|
g_type_add_class_private (g_define_type_id, sizeof (NMObjectClassPrivate));
|
2014-07-24 08:53:33 -04:00
|
|
|
G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, nm_object_initable_iface_init);
|
|
|
|
|
G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, nm_object_async_initable_iface_init);
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
#define NM_OBJECT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_OBJECT, NMObjectPrivate))
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
PropertyMarshalFunc func;
|
|
|
|
|
GType object_type;
|
|
|
|
|
gpointer field;
|
|
|
|
|
const char *signal_prefix;
|
|
|
|
|
} PropertyInfo;
|
|
|
|
|
|
2014-10-22 16:44:26 -05:00
|
|
|
static void reload_complete (NMObject *object, gboolean emit_now);
|
2014-10-21 09:18:47 -04:00
|
|
|
static gboolean demarshal_generic (NMObject *object, GParamSpec *pspec, GVariant *value, gpointer field);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
typedef struct {
|
2016-10-18 16:35:07 +02:00
|
|
|
GDBusObject *object;
|
|
|
|
|
GDBusObjectManager *object_manager;
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
GSList *property_tables;
|
|
|
|
|
NMObject *parent;
|
|
|
|
|
|
2015-09-26 08:44:37 +02:00
|
|
|
gboolean inited; /* async init finished? */
|
|
|
|
|
GSList *waiters; /* if async init did not finish, users of this object need
|
|
|
|
|
* to defer their notifications by adding themselves here. */
|
|
|
|
|
|
2017-05-06 21:14:30 +02:00
|
|
|
CList notify_items;
|
2017-05-07 12:40:05 +02:00
|
|
|
guint notify_id;
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
guint reload_remaining;
|
2016-10-07 22:52:13 +02:00
|
|
|
|
2017-05-06 21:14:30 +02:00
|
|
|
CList pending; /* ordered list of pending property updates. */
|
2017-02-16 18:48:38 +01:00
|
|
|
GPtrArray *proxies;
|
2019-10-04 13:56:36 +02:00
|
|
|
|
|
|
|
|
char *name_owner_cached;
|
2014-07-24 08:53:33 -04:00
|
|
|
} NMObjectPrivate;
|
|
|
|
|
|
2019-10-10 17:57:30 +02:00
|
|
|
NM_GOBJECT_PROPERTIES_DEFINE_BASE (
|
2014-08-13 17:43:10 -04:00
|
|
|
PROP_PATH,
|
2014-10-01 12:35:07 +02:00
|
|
|
PROP_DBUS_CONNECTION,
|
2016-10-18 16:35:07 +02:00
|
|
|
PROP_DBUS_OBJECT,
|
|
|
|
|
PROP_DBUS_OBJECT_MANAGER,
|
2019-10-10 17:57:30 +02:00
|
|
|
);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
/**
|
|
|
|
|
* 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
|
2016-10-18 16:35:07 +02:00
|
|
|
* object, and must not be modified.
|
2014-10-22 15:06:27 -05:00
|
|
|
**/
|
|
|
|
|
const char *
|
|
|
|
|
nm_object_get_path (NMObject *object)
|
2014-07-24 08:53:33 -04:00
|
|
|
{
|
2014-10-22 15:06:27 -05:00
|
|
|
g_return_val_if_fail (NM_IS_OBJECT (object), NULL);
|
2014-08-18 14:17:52 -04:00
|
|
|
|
2016-10-18 16:35:07 +02:00
|
|
|
return g_dbus_object_get_object_path (NM_OBJECT_GET_PRIVATE (object)->object);
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
|
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
/**
|
|
|
|
|
* _nm_object_get_proxy:
|
|
|
|
|
* @object: an #NMObject
|
|
|
|
|
* @interface: a D-Bus interface implemented by @object
|
|
|
|
|
*
|
|
|
|
|
* Gets the D-Bus proxy for @interface on @object.
|
|
|
|
|
*
|
|
|
|
|
* Returns: (transfer none): a D-Bus proxy
|
|
|
|
|
*/
|
|
|
|
|
GDBusProxy *
|
|
|
|
|
_nm_object_get_proxy (NMObject *object,
|
|
|
|
|
const char *interface)
|
2014-05-15 14:24:56 -04:00
|
|
|
{
|
2017-03-11 14:28:32 +01:00
|
|
|
NMObjectPrivate *priv;
|
2016-10-18 16:35:07 +02:00
|
|
|
GDBusInterface *proxy;
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
g_return_val_if_fail (NM_IS_OBJECT (object), NULL);
|
|
|
|
|
|
2017-03-11 14:28:32 +01:00
|
|
|
priv = NM_OBJECT_GET_PRIVATE (object);
|
|
|
|
|
if (priv->object == NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
proxy = g_dbus_object_get_interface (priv->object, interface);
|
2014-10-22 15:06:27 -05:00
|
|
|
g_return_val_if_fail (proxy != NULL, NULL);
|
2016-10-18 16:35:07 +02:00
|
|
|
|
|
|
|
|
return G_DBUS_PROXY (proxy);
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
|
|
|
|
|
2019-10-04 13:56:36 +02:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
GDBusConnection *
|
|
|
|
|
_nm_object_get_dbus_connection (gpointer self)
|
|
|
|
|
{
|
|
|
|
|
NMObjectPrivate *priv;
|
|
|
|
|
|
|
|
|
|
nm_assert (NM_IS_OBJECT (self));
|
|
|
|
|
|
|
|
|
|
priv = NM_OBJECT_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
return g_dbus_object_manager_client_get_connection (G_DBUS_OBJECT_MANAGER_CLIENT (priv->object_manager));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const char *
|
|
|
|
|
_nm_object_get_dbus_name_owner (gpointer self)
|
|
|
|
|
{
|
|
|
|
|
NMObjectPrivate *priv;
|
|
|
|
|
|
|
|
|
|
nm_assert (NM_IS_OBJECT (self));
|
|
|
|
|
|
|
|
|
|
priv = NM_OBJECT_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
nm_clear_g_free (&priv->name_owner_cached);
|
|
|
|
|
priv->name_owner_cached = g_dbus_object_manager_client_get_name_owner (G_DBUS_OBJECT_MANAGER_CLIENT (priv->object_manager));
|
|
|
|
|
return priv->name_owner_cached;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
_get_dbus_params (gpointer self,
|
|
|
|
|
GDBusConnection **out_dbus_connection,
|
|
|
|
|
const char **out_name_owner)
|
|
|
|
|
{
|
|
|
|
|
const char *name_owner;
|
|
|
|
|
GDBusConnection *dbus_connection = NULL;
|
|
|
|
|
|
|
|
|
|
if (NM_IS_OBJECT (self)) {
|
|
|
|
|
name_owner = _nm_object_get_dbus_name_owner (self);
|
|
|
|
|
if (name_owner)
|
|
|
|
|
dbus_connection = _nm_object_get_dbus_connection (self);
|
|
|
|
|
} else {
|
|
|
|
|
nm_assert (NM_IS_CLIENT (self));
|
|
|
|
|
name_owner = _nm_client_get_dbus_name_owner (self);
|
|
|
|
|
if (name_owner)
|
|
|
|
|
dbus_connection = _nm_client_get_dbus_connection (self);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*out_dbus_connection = dbus_connection;
|
|
|
|
|
*out_name_owner = name_owner;
|
|
|
|
|
return !!name_owner;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
_nm_object_dbus_call (gpointer self,
|
|
|
|
|
gpointer source_tag,
|
|
|
|
|
GCancellable *cancellable,
|
|
|
|
|
GAsyncReadyCallback user_callback,
|
|
|
|
|
gpointer user_callback_data,
|
|
|
|
|
const char *object_path,
|
|
|
|
|
const char *interface_name,
|
|
|
|
|
const char *method_name,
|
|
|
|
|
GVariant *parameters,
|
|
|
|
|
const GVariantType *reply_type,
|
|
|
|
|
GDBusCallFlags flags,
|
|
|
|
|
int timeout_msec,
|
|
|
|
|
GAsyncReadyCallback internal_callback)
|
|
|
|
|
{
|
|
|
|
|
gs_unref_object GTask *task = NULL;
|
|
|
|
|
const char *name_owner;
|
|
|
|
|
GDBusConnection *dbus_connection;
|
|
|
|
|
|
|
|
|
|
nm_assert (G_IS_OBJECT (self));
|
|
|
|
|
nm_assert (source_tag);
|
|
|
|
|
nm_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
|
|
|
|
|
nm_assert (internal_callback);
|
|
|
|
|
nm_assert (object_path);
|
|
|
|
|
nm_assert (interface_name);
|
|
|
|
|
nm_assert (method_name);
|
|
|
|
|
nm_assert (parameters);
|
|
|
|
|
nm_assert (reply_type);
|
|
|
|
|
|
|
|
|
|
task = nm_g_task_new (self, cancellable, source_tag, user_callback, user_callback_data);
|
|
|
|
|
|
|
|
|
|
if (!_get_dbus_params (self, &dbus_connection, &name_owner)) {
|
|
|
|
|
nm_g_variant_unref_floating (parameters);
|
|
|
|
|
g_task_return_error (task, _nm_object_new_error_nm_not_running ());
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_dbus_connection_call (dbus_connection,
|
|
|
|
|
name_owner,
|
|
|
|
|
object_path,
|
|
|
|
|
interface_name,
|
|
|
|
|
method_name,
|
|
|
|
|
parameters,
|
|
|
|
|
reply_type,
|
|
|
|
|
flags,
|
|
|
|
|
timeout_msec,
|
|
|
|
|
cancellable,
|
|
|
|
|
internal_callback,
|
|
|
|
|
g_steal_pointer (&task));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GVariant *
|
|
|
|
|
_nm_object_dbus_call_sync (gpointer self,
|
|
|
|
|
GCancellable *cancellable,
|
|
|
|
|
const char *object_path,
|
|
|
|
|
const char *interface_name,
|
|
|
|
|
const char *method_name,
|
|
|
|
|
GVariant *parameters,
|
|
|
|
|
const GVariantType *reply_type,
|
|
|
|
|
GDBusCallFlags flags,
|
|
|
|
|
int timeout_msec,
|
|
|
|
|
gboolean strip_dbus_error,
|
|
|
|
|
GError **error)
|
|
|
|
|
{
|
|
|
|
|
gs_unref_variant GVariant *ret = NULL;
|
|
|
|
|
GDBusConnection *dbus_connection;
|
|
|
|
|
const char *name_owner;
|
|
|
|
|
|
|
|
|
|
nm_assert (G_IS_OBJECT (self));
|
|
|
|
|
nm_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
|
|
|
|
|
nm_assert (!error || !*error);
|
|
|
|
|
nm_assert (object_path);
|
|
|
|
|
nm_assert (interface_name);
|
|
|
|
|
nm_assert (method_name);
|
|
|
|
|
nm_assert (parameters);
|
|
|
|
|
nm_assert (reply_type);
|
|
|
|
|
|
|
|
|
|
if (!_get_dbus_params (self, &dbus_connection, &name_owner)) {
|
|
|
|
|
nm_g_variant_unref_floating (parameters);
|
|
|
|
|
_nm_object_set_error_nm_not_running (error);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ret = g_dbus_connection_call_sync (dbus_connection,
|
|
|
|
|
name_owner,
|
|
|
|
|
object_path,
|
|
|
|
|
interface_name,
|
|
|
|
|
method_name,
|
|
|
|
|
parameters,
|
|
|
|
|
reply_type,
|
|
|
|
|
flags,
|
|
|
|
|
timeout_msec,
|
|
|
|
|
cancellable,
|
|
|
|
|
error);
|
|
|
|
|
if (!ret) {
|
|
|
|
|
if (error && strip_dbus_error)
|
|
|
|
|
g_dbus_error_strip_remote_error (*error);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return g_steal_pointer (&ret);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
|
_nm_object_dbus_call_sync_void (gpointer self,
|
|
|
|
|
GCancellable *cancellable,
|
|
|
|
|
const char *object_path,
|
|
|
|
|
const char *interface_name,
|
|
|
|
|
const char *method_name,
|
|
|
|
|
GVariant *parameters,
|
|
|
|
|
GDBusCallFlags flags,
|
|
|
|
|
int timeout_msec,
|
|
|
|
|
gboolean strip_dbus_error,
|
|
|
|
|
GError **error)
|
|
|
|
|
{
|
|
|
|
|
gs_unref_variant GVariant *ret = NULL;
|
|
|
|
|
|
|
|
|
|
ret = _nm_object_dbus_call_sync (self,
|
|
|
|
|
cancellable,
|
|
|
|
|
object_path,
|
|
|
|
|
interface_name,
|
|
|
|
|
method_name,
|
|
|
|
|
parameters,
|
|
|
|
|
G_VARIANT_TYPE ("()"),
|
|
|
|
|
flags,
|
|
|
|
|
timeout_msec,
|
|
|
|
|
strip_dbus_error,
|
|
|
|
|
error);
|
|
|
|
|
return !!ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
GError *
|
|
|
|
|
_nm_object_new_error_nm_not_running (void)
|
|
|
|
|
{
|
|
|
|
|
return g_error_new_literal (NM_CLIENT_ERROR,
|
|
|
|
|
NM_CLIENT_ERROR_MANAGER_NOT_RUNNING,
|
|
|
|
|
"NetworkManager is not running");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
_nm_object_set_error_nm_not_running (GError **error)
|
|
|
|
|
{
|
|
|
|
|
if (error) {
|
|
|
|
|
if (*error)
|
|
|
|
|
g_return_if_reached ();
|
|
|
|
|
*error = _nm_object_new_error_nm_not_running ();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2014-10-22 16:44:26 -05:00
|
|
|
typedef enum {
|
|
|
|
|
NOTIFY_SIGNAL_PENDING_NONE,
|
|
|
|
|
NOTIFY_SIGNAL_PENDING_ADDED,
|
|
|
|
|
NOTIFY_SIGNAL_PENDING_REMOVED,
|
|
|
|
|
NOTIFY_SIGNAL_PENDING_ADDED_REMOVED,
|
|
|
|
|
} NotifySignalPending;
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
2017-05-06 21:14:30 +02:00
|
|
|
CList lst;
|
2014-10-22 16:44:26 -05:00
|
|
|
const char *property;
|
|
|
|
|
const char *signal_prefix;
|
|
|
|
|
NotifySignalPending pending;
|
|
|
|
|
NMObject *changed;
|
|
|
|
|
} NotifyItem;
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
notify_item_free (NotifyItem *item)
|
|
|
|
|
{
|
2017-11-28 11:22:01 +01:00
|
|
|
c_list_unlink_stale (&item->lst);
|
2014-10-22 16:44:26 -05:00
|
|
|
g_clear_object (&item->changed);
|
|
|
|
|
g_slice_free (NotifyItem, item);
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-24 08:53:33 -04:00
|
|
|
static gboolean
|
2014-10-22 15:06:27 -05:00
|
|
|
deferred_notify_cb (gpointer data)
|
2014-07-24 08:53:33 -04:00
|
|
|
{
|
2014-10-22 15:06:27 -05:00
|
|
|
NMObject *object = NM_OBJECT (data);
|
|
|
|
|
NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
|
2014-10-22 16:44:26 -05:00
|
|
|
NMObjectClass *object_class = NM_OBJECT_GET_CLASS (object);
|
2017-05-06 21:14:30 +02:00
|
|
|
CList props;
|
|
|
|
|
CList *iter, *safe;
|
2014-05-15 14:25:07 -04:00
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
priv->notify_id = 0;
|
2014-09-10 09:29:51 -04:00
|
|
|
|
2014-10-22 16:44:26 -05:00
|
|
|
/* Wait until all reloads are done before notifying */
|
|
|
|
|
if (priv->reload_remaining)
|
|
|
|
|
return G_SOURCE_REMOVE;
|
|
|
|
|
|
|
|
|
|
/* Clear priv->notify_items early so that an NMObject subclass that
|
2014-10-22 15:06:27 -05:00
|
|
|
* listens to property changes can queue up other property changes
|
|
|
|
|
* during the g_object_notify() call separately from the property
|
|
|
|
|
* list we're iterating.
|
|
|
|
|
*/
|
2017-05-06 21:14:30 +02:00
|
|
|
c_list_link_after (&priv->notify_items, &props);
|
2017-11-28 11:22:01 +01:00
|
|
|
c_list_unlink (&priv->notify_items);
|
2014-09-10 09:29:51 -04:00
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
g_object_ref (object);
|
2014-10-22 16:44:26 -05:00
|
|
|
|
2014-11-07 16:47:13 -06:00
|
|
|
/* Emit added/removed signals first since some of our internal objects
|
|
|
|
|
* use the added/removed signals for new object processing.
|
|
|
|
|
*/
|
2017-05-06 21:14:30 +02:00
|
|
|
c_list_for_each (iter, &props) {
|
|
|
|
|
NotifyItem *item = c_list_entry (iter, NotifyItem, lst);
|
2014-10-22 16:44:26 -05:00
|
|
|
char buf[50];
|
all: don't use gchar/gshort/gint/glong but C types
We commonly don't use the glib typedefs for char/short/int/long,
but their C types directly.
$ git grep '\<g\(char\|short\|int\|long\|float\|double\)\>' | wc -l
587
$ git grep '\<\(char\|short\|int\|long\|float\|double\)\>' | wc -l
21114
One could argue that using the glib typedefs is preferable in
public API (of our glib based libnm library) or where it clearly
is related to glib, like during
g_object_set (obj, PROPERTY, (gint) value, NULL);
However, that argument does not seem strong, because in practice we don't
follow that argument today, and seldomly use the glib typedefs.
Also, the style guide for this would be hard to formalize, because
"using them where clearly related to a glib" is a very loose suggestion.
Also note that glib typedefs will always just be typedefs of the
underlying C types. There is no danger of glib changing the meaning
of these typedefs (because that would be a major API break of glib).
A simple style guide is instead: don't use these typedefs.
No manual actions, I only ran the bash script:
FILES=($(git ls-files '*.[hc]'))
sed -i \
-e 's/\<g\(char\|short\|int\|long\|float\|double\)\>\( [^ ]\)/\1\2/g' \
-e 's/\<g\(char\|short\|int\|long\|float\|double\)\> /\1 /g' \
-e 's/\<g\(char\|short\|int\|long\|float\|double\)\>/\1/g' \
"${FILES[@]}"
2018-07-11 07:40:19 +02:00
|
|
|
int ret = 0;
|
2014-10-22 16:44:26 -05:00
|
|
|
|
|
|
|
|
switch (item->pending) {
|
|
|
|
|
case NOTIFY_SIGNAL_PENDING_ADDED:
|
|
|
|
|
ret = g_snprintf (buf, sizeof (buf), "%s-added", item->signal_prefix);
|
|
|
|
|
break;
|
|
|
|
|
case NOTIFY_SIGNAL_PENDING_REMOVED:
|
|
|
|
|
ret = g_snprintf (buf, sizeof (buf), "%s-removed", item->signal_prefix);
|
|
|
|
|
break;
|
|
|
|
|
case NOTIFY_SIGNAL_PENDING_ADDED_REMOVED:
|
|
|
|
|
if (object_class->object_creation_failed)
|
|
|
|
|
object_class->object_creation_failed (object, nm_object_get_path (item->changed));
|
|
|
|
|
break;
|
|
|
|
|
case NOTIFY_SIGNAL_PENDING_NONE:
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (ret > 0) {
|
|
|
|
|
g_assert (ret < sizeof (buf));
|
|
|
|
|
g_signal_emit_by_name (object, buf, item->changed);
|
|
|
|
|
}
|
2014-09-10 09:29:51 -04:00
|
|
|
}
|
2014-11-07 16:47:13 -06:00
|
|
|
|
|
|
|
|
/* Emit property change notifications second */
|
2017-05-06 21:14:30 +02:00
|
|
|
c_list_for_each (iter, &props) {
|
|
|
|
|
NotifyItem *item = c_list_entry (iter, NotifyItem, lst);
|
2014-11-07 16:47:13 -06:00
|
|
|
|
|
|
|
|
if (item->property)
|
|
|
|
|
g_object_notify (G_OBJECT (object), item->property);
|
|
|
|
|
}
|
|
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
g_object_unref (object);
|
2014-09-10 09:29:51 -04:00
|
|
|
|
2017-05-06 21:14:30 +02:00
|
|
|
c_list_for_each_safe (iter, safe, &props)
|
|
|
|
|
notify_item_free (c_list_entry (iter, NotifyItem, lst));
|
|
|
|
|
|
2014-10-22 16:44:26 -05:00
|
|
|
return G_SOURCE_REMOVE;
|
2014-10-22 15:06:27 -05:00
|
|
|
}
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-22 16:44:26 -05:00
|
|
|
static void
|
|
|
|
|
_nm_object_defer_notify (NMObject *object)
|
|
|
|
|
{
|
|
|
|
|
NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
|
|
|
|
|
|
|
|
|
|
if (!priv->notify_id)
|
|
|
|
|
priv->notify_id = g_idle_add_full (G_PRIORITY_LOW, deferred_notify_cb, object, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
_nm_object_queue_notify_full (NMObject *object,
|
|
|
|
|
const char *property,
|
|
|
|
|
const char *signal_prefix,
|
|
|
|
|
gboolean added,
|
|
|
|
|
NMObject *changed)
|
2014-10-22 15:06:27 -05:00
|
|
|
{
|
|
|
|
|
NMObjectPrivate *priv;
|
2014-10-22 16:44:26 -05:00
|
|
|
NotifyItem *item;
|
2017-05-06 21:14:30 +02:00
|
|
|
CList *iter;
|
2014-09-10 09:29:51 -04:00
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
g_return_if_fail (NM_IS_OBJECT (object));
|
2014-10-22 16:44:26 -05:00
|
|
|
g_return_if_fail (!signal_prefix != !property);
|
|
|
|
|
g_return_if_fail (!signal_prefix == !changed);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
priv = NM_OBJECT_GET_PRIVATE (object);
|
2014-10-22 16:44:26 -05:00
|
|
|
_nm_object_defer_notify (object);
|
|
|
|
|
|
|
|
|
|
property = g_intern_string (property);
|
|
|
|
|
signal_prefix = g_intern_string (signal_prefix);
|
2017-05-06 21:14:30 +02:00
|
|
|
c_list_for_each (iter, &priv->notify_items) {
|
|
|
|
|
item = c_list_entry (iter, NotifyItem, lst);
|
2014-10-22 16:44:26 -05:00
|
|
|
|
|
|
|
|
if (property && (property == item->property))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/* Collapse signals for the same object (such as "added->removed") to
|
|
|
|
|
* ensure we don't emit signals when their sum should have no effect.
|
|
|
|
|
* The "added->removed->removed" sequence requires special handling,
|
|
|
|
|
* hence the addition of the ADDED_REMOVED state to ensure that no
|
|
|
|
|
* signal is emitted in this case:
|
|
|
|
|
*
|
|
|
|
|
* Without the ADDED_REMOVED state:
|
|
|
|
|
* NONE + added -> ADDED
|
|
|
|
|
* ADDED + removed -> NONE
|
|
|
|
|
* NONE + removed -> REMOVED (would emit 'removed' signal)
|
|
|
|
|
*
|
|
|
|
|
* With the ADDED_REMOVED state:
|
|
|
|
|
* NONE | ADDED_REMOVED + added -> ADDED
|
|
|
|
|
* ADDED + removed -> ADDED_REMOVED
|
|
|
|
|
* ADDED_REMOVED + removed -> ADDED_REMOVED (emits no signal)
|
|
|
|
|
*/
|
|
|
|
|
if (signal_prefix && (changed == item->changed) && (item->signal_prefix == signal_prefix)) {
|
|
|
|
|
switch (item->pending) {
|
|
|
|
|
case NOTIFY_SIGNAL_PENDING_ADDED:
|
|
|
|
|
if (!added)
|
|
|
|
|
item->pending = NOTIFY_SIGNAL_PENDING_ADDED_REMOVED;
|
|
|
|
|
break;
|
|
|
|
|
case NOTIFY_SIGNAL_PENDING_REMOVED:
|
|
|
|
|
if (added)
|
|
|
|
|
item->pending = NOTIFY_SIGNAL_PENDING_NONE;
|
|
|
|
|
break;
|
|
|
|
|
case NOTIFY_SIGNAL_PENDING_ADDED_REMOVED:
|
|
|
|
|
if (added)
|
|
|
|
|
item->pending = NOTIFY_SIGNAL_PENDING_ADDED;
|
|
|
|
|
break;
|
|
|
|
|
case NOTIFY_SIGNAL_PENDING_NONE:
|
|
|
|
|
item->pending = added ? NOTIFY_SIGNAL_PENDING_ADDED : NOTIFY_SIGNAL_PENDING_REMOVED;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
g_assert_not_reached ();
|
|
|
|
|
}
|
|
|
|
|
return;
|
2014-10-22 15:06:27 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-10-22 16:44:26 -05:00
|
|
|
item = g_slice_new0 (NotifyItem);
|
|
|
|
|
item->property = property;
|
|
|
|
|
if (signal_prefix) {
|
|
|
|
|
item->signal_prefix = signal_prefix;
|
|
|
|
|
item->pending = added ? NOTIFY_SIGNAL_PENDING_ADDED : NOTIFY_SIGNAL_PENDING_REMOVED;
|
|
|
|
|
item->changed = changed ? g_object_ref (changed) : NULL;
|
|
|
|
|
}
|
2017-05-06 21:14:30 +02:00
|
|
|
c_list_link_tail (&priv->notify_items, &item->lst);
|
2014-10-22 16:44:26 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
_nm_object_queue_notify (NMObject *object, const char *property)
|
|
|
|
|
{
|
|
|
|
|
_nm_object_queue_notify_full (object, property, NULL, FALSE, NULL);
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
|
|
|
|
|
2016-03-10 19:22:20 +01:00
|
|
|
typedef struct {
|
2017-05-06 21:14:30 +02:00
|
|
|
CList lst_pending;
|
2016-03-10 19:22:20 +01:00
|
|
|
NMObject *self;
|
|
|
|
|
PropertyInfo *pi;
|
|
|
|
|
|
|
|
|
|
GObject **objects;
|
|
|
|
|
int length, remaining;
|
|
|
|
|
|
2016-10-07 22:52:13 +02:00
|
|
|
gboolean array;
|
2016-03-10 19:22:20 +01:00
|
|
|
const char *property_name;
|
|
|
|
|
} ObjectCreatedData;
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
odata_free (gpointer data)
|
|
|
|
|
{
|
|
|
|
|
ObjectCreatedData *odata = data;
|
|
|
|
|
|
2017-11-28 11:22:01 +01:00
|
|
|
c_list_unlink_stale (&odata->lst_pending);
|
2016-03-10 19:22:20 +01:00
|
|
|
g_object_unref (odata->self);
|
|
|
|
|
g_free (odata->objects);
|
|
|
|
|
g_slice_free (ObjectCreatedData, odata);
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-07 22:52:13 +02:00
|
|
|
static void object_property_maybe_complete (NMObject *self);
|
2016-03-10 19:22:20 +01:00
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
/* Stolen from dbus-glib */
|
|
|
|
|
static char*
|
|
|
|
|
wincaps_to_dash (const char *caps)
|
2014-07-24 08:53:33 -04:00
|
|
|
{
|
2014-10-22 15:06:27 -05:00
|
|
|
const char *p;
|
|
|
|
|
GString *str;
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
str = g_string_new (NULL);
|
|
|
|
|
p = caps;
|
|
|
|
|
while (*p) {
|
|
|
|
|
if (g_ascii_isupper (*p)) {
|
|
|
|
|
if (str->len > 0 && (str->len < 2 || str->str[str->len-2] != '-'))
|
|
|
|
|
g_string_append_c (str, '-');
|
|
|
|
|
g_string_append_c (str, g_ascii_tolower (*p));
|
|
|
|
|
} else
|
|
|
|
|
g_string_append_c (str, *p);
|
|
|
|
|
++p;
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
2014-10-22 15:06:27 -05:00
|
|
|
|
|
|
|
|
return g_string_free (str, FALSE);
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
|
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
/* Adds object to array if it's not already there */
|
2014-07-24 08:53:33 -04:00
|
|
|
static void
|
2014-10-22 15:06:27 -05:00
|
|
|
add_to_object_array_unique (GPtrArray *array, GObject *obj)
|
2014-07-24 08:53:33 -04:00
|
|
|
{
|
2014-10-22 15:06:27 -05:00
|
|
|
guint i;
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
g_return_if_fail (array != NULL);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
if (obj != NULL) {
|
|
|
|
|
for (i = 0; i < array->len; i++) {
|
|
|
|
|
if (g_ptr_array_index (array, i) == obj) {
|
|
|
|
|
g_object_unref (obj);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
g_ptr_array_add (array, obj);
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
/* Places items from 'needles' that are not in 'haystack' into 'diff' */
|
|
|
|
|
static void
|
|
|
|
|
array_diff (GPtrArray *needles, GPtrArray *haystack, GPtrArray *diff)
|
|
|
|
|
{
|
|
|
|
|
guint i, j;
|
|
|
|
|
GObject *obj;
|
2014-10-01 12:35:07 +02:00
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
g_assert (needles);
|
|
|
|
|
g_assert (haystack);
|
|
|
|
|
g_assert (diff);
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < needles->len; i++) {
|
|
|
|
|
obj = g_ptr_array_index (needles, i);
|
|
|
|
|
|
|
|
|
|
for (j = 0; j < haystack->len; j++) {
|
|
|
|
|
if (g_ptr_array_index (haystack, j) == obj)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (j == haystack->len)
|
|
|
|
|
g_ptr_array_add (diff, obj);
|
|
|
|
|
}
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2014-10-22 16:44:26 -05:00
|
|
|
queue_added_removed_signal (NMObject *self,
|
|
|
|
|
const char *signal_prefix,
|
|
|
|
|
NMObject *changed,
|
|
|
|
|
gboolean added)
|
2014-07-24 08:53:33 -04:00
|
|
|
{
|
2014-10-22 16:44:26 -05:00
|
|
|
_nm_object_queue_notify_full (self, NULL, signal_prefix, added, changed);
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
|
|
|
|
|
2016-03-10 19:22:20 +01:00
|
|
|
static gboolean
|
|
|
|
|
already_awaits (ObjectCreatedData *odata, GObject *object)
|
|
|
|
|
{
|
|
|
|
|
NMObject *self = odata->self;
|
|
|
|
|
NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self);
|
|
|
|
|
GSList *iter;
|
|
|
|
|
|
|
|
|
|
if ((GObject *)odata->self == object)
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
|
|
for (iter = priv->waiters; iter; iter = g_slist_next (iter)) {
|
|
|
|
|
if (already_awaits (iter->data, object))
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-24 08:53:33 -04:00
|
|
|
static void
|
2016-10-07 22:52:13 +02:00
|
|
|
object_property_maybe_complete (NMObject *self)
|
2014-07-24 08:53:33 -04:00
|
|
|
{
|
2014-10-22 15:06:27 -05:00
|
|
|
NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self);
|
2016-10-07 22:52:13 +02:00
|
|
|
/* The odata may hold the last reference. */
|
|
|
|
|
_nm_unused gs_unref_object NMObject *self_keep_alive = g_object_ref (self);
|
2016-03-10 19:22:20 +01:00
|
|
|
int i;
|
2017-05-06 21:14:30 +02:00
|
|
|
CList *iter, *safe;
|
2016-03-10 19:22:20 +01:00
|
|
|
|
2017-05-06 21:14:30 +02:00
|
|
|
c_list_for_each_safe (iter, safe, &priv->pending) {
|
|
|
|
|
ObjectCreatedData *odata = c_list_entry (iter, ObjectCreatedData, lst_pending);
|
2016-10-07 22:52:13 +02:00
|
|
|
PropertyInfo *pi = odata->pi;
|
|
|
|
|
gboolean different = TRUE;
|
2016-03-10 19:22:20 +01:00
|
|
|
|
2016-10-07 22:52:13 +02:00
|
|
|
if (odata->remaining > 0)
|
2016-03-10 19:22:20 +01:00
|
|
|
return;
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2016-10-07 22:52:13 +02:00
|
|
|
/* Only complete the array property load when all the objects are initialized. */
|
|
|
|
|
for (i = 0; i < odata->length; i++) {
|
|
|
|
|
GObject *obj = odata->objects[i];
|
|
|
|
|
NMObjectPrivate *obj_priv;
|
2014-08-18 14:17:52 -04:00
|
|
|
|
2016-10-07 22:52:13 +02:00
|
|
|
/* Could not load the object. Perhaps it was removed. */
|
|
|
|
|
if (!obj)
|
|
|
|
|
continue;
|
2014-08-18 14:17:52 -04:00
|
|
|
|
2016-10-07 22:52:13 +02:00
|
|
|
obj_priv = NM_OBJECT_GET_PRIVATE (obj);
|
|
|
|
|
if (!obj_priv->inited) {
|
2014-10-01 13:37:57 +02:00
|
|
|
|
2016-10-07 22:52:13 +02:00
|
|
|
/* The object is not finished because we block its creation. */
|
|
|
|
|
if (already_awaits (odata, obj))
|
|
|
|
|
continue;
|
2014-08-18 14:17:52 -04:00
|
|
|
|
2016-10-07 22:52:13 +02:00
|
|
|
if (!g_slist_find (obj_priv->waiters, odata))
|
|
|
|
|
obj_priv->waiters = g_slist_prepend (obj_priv->waiters, odata);
|
|
|
|
|
return;
|
2014-10-22 15:06:27 -05:00
|
|
|
}
|
2016-10-07 22:52:13 +02:00
|
|
|
}
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2016-10-07 22:52:13 +02:00
|
|
|
if (odata->array) {
|
|
|
|
|
GPtrArray *old = *((GPtrArray **) pi->field);
|
|
|
|
|
GPtrArray *new;
|
|
|
|
|
|
|
|
|
|
/* Build up new array */
|
|
|
|
|
new = g_ptr_array_new_full (odata->length, g_object_unref);
|
|
|
|
|
for (i = 0; i < odata->length; i++)
|
|
|
|
|
add_to_object_array_unique (new, odata->objects[i]);
|
|
|
|
|
|
|
|
|
|
*((GPtrArray **) pi->field) = new;
|
|
|
|
|
|
|
|
|
|
if (pi->signal_prefix) {
|
|
|
|
|
GPtrArray *added = g_ptr_array_sized_new (3);
|
|
|
|
|
GPtrArray *removed = g_ptr_array_sized_new (3);
|
|
|
|
|
|
|
|
|
|
if (old) {
|
|
|
|
|
/* Find objects in 'old' that do not exist in 'new' */
|
|
|
|
|
array_diff (old, new, removed);
|
|
|
|
|
|
|
|
|
|
/* Find objects in 'new' that do not exist in old */
|
|
|
|
|
array_diff (new, old, added);
|
|
|
|
|
} else {
|
|
|
|
|
for (i = 0; i < new->len; i++)
|
|
|
|
|
g_ptr_array_add (added, g_ptr_array_index (new, i));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Emit added & removed */
|
|
|
|
|
for (i = 0; i < removed->len; i++) {
|
|
|
|
|
queue_added_removed_signal (self,
|
2017-05-06 21:14:30 +02:00
|
|
|
pi->signal_prefix,
|
|
|
|
|
g_ptr_array_index (removed, i),
|
|
|
|
|
FALSE);
|
2016-10-07 22:52:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < added->len; i++) {
|
|
|
|
|
queue_added_removed_signal (self,
|
2017-05-06 21:14:30 +02:00
|
|
|
pi->signal_prefix,
|
|
|
|
|
g_ptr_array_index (added, i),
|
|
|
|
|
TRUE);
|
2016-10-07 22:52:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
different = removed->len || added->len;
|
|
|
|
|
g_ptr_array_unref (added);
|
|
|
|
|
g_ptr_array_unref (removed);
|
|
|
|
|
} else {
|
|
|
|
|
/* No added/removed signals to send, just replace the property with
|
|
|
|
|
* the new values.
|
|
|
|
|
*/
|
|
|
|
|
different = TRUE;
|
2014-10-22 15:06:27 -05:00
|
|
|
}
|
2014-08-18 14:17:52 -04:00
|
|
|
|
2016-10-07 22:52:13 +02:00
|
|
|
/* Free old array last since it will release references, thus freeing
|
|
|
|
|
* any objects in the 'removed' array.
|
2014-10-22 15:06:27 -05:00
|
|
|
*/
|
2016-10-07 22:52:13 +02:00
|
|
|
if (old)
|
|
|
|
|
g_ptr_array_unref (old);
|
|
|
|
|
} else {
|
|
|
|
|
GObject **obj_p = pi->field;
|
2014-10-22 15:06:27 -05:00
|
|
|
|
2016-10-07 22:52:13 +02:00
|
|
|
different = (*obj_p != odata->objects[0]);
|
|
|
|
|
if (*obj_p)
|
|
|
|
|
g_object_unref (*obj_p);
|
|
|
|
|
*obj_p = odata->objects[0];
|
|
|
|
|
}
|
2014-10-22 15:06:27 -05:00
|
|
|
|
2016-10-07 22:52:13 +02:00
|
|
|
if (different && odata->property_name)
|
|
|
|
|
_nm_object_queue_notify (self, odata->property_name);
|
2014-10-22 15:06:27 -05:00
|
|
|
|
2016-10-07 22:52:13 +02:00
|
|
|
if (--priv->reload_remaining == 0)
|
|
|
|
|
reload_complete (self, TRUE);
|
2014-10-22 15:06:27 -05:00
|
|
|
|
2016-10-07 22:52:13 +02:00
|
|
|
odata_free (odata);
|
|
|
|
|
}
|
2014-08-18 14:17:52 -04:00
|
|
|
}
|
|
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
static void
|
|
|
|
|
object_created (GObject *obj, const char *path, gpointer user_data)
|
2014-07-24 08:53:33 -04:00
|
|
|
{
|
2014-10-22 15:06:27 -05:00
|
|
|
ObjectCreatedData *odata = user_data;
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
/* We assume that on error, the creator_func printed something */
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
if (obj == NULL && g_strcmp0 (path, "/") != 0 ) {
|
|
|
|
|
NMObjectClass *object_class = NM_OBJECT_GET_CLASS (odata->self);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
if (object_class->object_creation_failed)
|
|
|
|
|
object_class->object_creation_failed (odata->self, path);
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
|
|
|
|
|
2017-11-08 18:57:59 +01:00
|
|
|
odata->objects[odata->length - odata->remaining--] = obj ? g_object_ref (obj) : NULL;
|
2016-10-07 22:52:13 +02:00
|
|
|
object_property_maybe_complete (odata->self);
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
|
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
static gboolean
|
|
|
|
|
handle_object_property (NMObject *self, const char *property_name, GVariant *value,
|
2016-10-18 16:35:07 +02:00
|
|
|
PropertyInfo *pi)
|
2014-07-24 08:53:33 -04:00
|
|
|
{
|
2014-10-22 15:06:27 -05:00
|
|
|
NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self);
|
2016-10-18 16:35:07 +02:00
|
|
|
gs_unref_object GDBusObject *object = NULL;
|
2014-10-22 15:06:27 -05:00
|
|
|
GObject *obj;
|
|
|
|
|
const char *path;
|
|
|
|
|
ObjectCreatedData *odata;
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
odata = g_slice_new (ObjectCreatedData);
|
|
|
|
|
odata->self = g_object_ref (self);
|
|
|
|
|
odata->pi = pi;
|
2016-10-18 14:49:30 +02:00
|
|
|
odata->objects = g_new0 (GObject *, 1);
|
2014-10-22 15:06:27 -05:00
|
|
|
odata->length = odata->remaining = 1;
|
2016-10-07 22:52:13 +02:00
|
|
|
odata->array = FALSE;
|
2014-10-22 15:06:27 -05:00
|
|
|
odata->property_name = property_name;
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2017-05-06 21:14:30 +02:00
|
|
|
c_list_link_tail (&priv->pending, &odata->lst_pending);
|
|
|
|
|
|
2014-10-22 16:44:26 -05:00
|
|
|
priv->reload_remaining++;
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
path = g_variant_get_string (value, NULL);
|
|
|
|
|
|
|
|
|
|
if (!strcmp (path, "/")) {
|
|
|
|
|
object_created (NULL, path, odata);
|
|
|
|
|
return TRUE;
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
|
|
|
|
|
2016-10-18 16:35:07 +02:00
|
|
|
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
|
2018-01-23 12:24:29 +01:00
|
|
|
* that does not exist.
|
|
|
|
|
*
|
|
|
|
|
* NOTE: We've ignored this before and the server hits the condition
|
2017-01-18 11:28:35 +01:00
|
|
|
* more often that it should. Given we're able to recover from
|
2018-09-15 07:20:54 -04:00
|
|
|
* the error, let's lower the severity of the log message to
|
2017-01-18 11:28:35 +01:00
|
|
|
* avoid unnecessarily bothering the user. This can be removed
|
|
|
|
|
* once the issue is fixed on the server. */
|
|
|
|
|
#if NM_MORE_ASSERTS
|
|
|
|
|
#define __nm_log_debug g_warning
|
|
|
|
|
#else
|
|
|
|
|
#define __nm_log_debug g_debug
|
|
|
|
|
#endif
|
|
|
|
|
__nm_log_debug ("No object known for %s", path);
|
|
|
|
|
#undef __nm_log_debug
|
2016-10-18 16:35:07 +02:00
|
|
|
return FALSE;
|
2014-10-22 15:06:27 -05:00
|
|
|
}
|
2016-10-18 16:35:07 +02:00
|
|
|
|
|
|
|
|
obj = g_object_get_qdata (G_OBJECT (object), _nm_object_obj_nm_quark ());
|
|
|
|
|
object_created (obj, path, odata);
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
|
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
static gboolean
|
|
|
|
|
handle_object_array_property (NMObject *self, const char *property_name, GVariant *value,
|
2016-10-18 16:35:07 +02:00
|
|
|
PropertyInfo *pi)
|
2014-07-24 08:53:33 -04:00
|
|
|
{
|
2014-10-22 15:06:27 -05:00
|
|
|
NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self);
|
|
|
|
|
GObject *obj;
|
|
|
|
|
GVariantIter iter;
|
|
|
|
|
gsize npaths;
|
|
|
|
|
const char *path;
|
|
|
|
|
ObjectCreatedData *odata;
|
2014-08-18 18:12:01 -04:00
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
npaths = g_variant_n_children (value);
|
2014-08-18 18:12:01 -04:00
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
odata = g_slice_new (ObjectCreatedData);
|
|
|
|
|
odata->self = g_object_ref (self);
|
|
|
|
|
odata->pi = pi;
|
|
|
|
|
odata->objects = g_new0 (GObject *, npaths);
|
|
|
|
|
odata->length = odata->remaining = npaths;
|
2016-10-07 22:52:13 +02:00
|
|
|
odata->array = TRUE;
|
2014-10-22 15:06:27 -05:00
|
|
|
odata->property_name = property_name;
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2017-05-06 21:14:30 +02:00
|
|
|
c_list_link_tail (&priv->pending, &odata->lst_pending);
|
|
|
|
|
|
2014-10-22 16:44:26 -05:00
|
|
|
priv->reload_remaining++;
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
if (npaths == 0) {
|
2016-10-07 22:52:13 +02:00
|
|
|
object_property_maybe_complete (self);
|
2014-10-22 15:06:27 -05:00
|
|
|
return TRUE;
|
|
|
|
|
}
|
2014-08-18 18:12:01 -04:00
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
g_variant_iter_init (&iter, value);
|
|
|
|
|
while (g_variant_iter_next (&iter, "&o", &path)) {
|
2016-10-18 16:35:07 +02:00
|
|
|
gs_unref_object GDBusObject *object = NULL;
|
|
|
|
|
|
|
|
|
|
object = g_dbus_object_manager_get_object (priv->object_manager, path);
|
2016-11-11 17:57:09 +01:00
|
|
|
if (object) {
|
|
|
|
|
obj = g_object_get_qdata (G_OBJECT (object), _nm_object_obj_nm_quark ());
|
|
|
|
|
object_created (obj, path, odata);
|
|
|
|
|
} else {
|
2016-10-18 16:35:07 +02:00
|
|
|
g_warning ("no object known for %s\n", path);
|
2016-11-11 17:57:09 +01:00
|
|
|
odata->remaining--;
|
|
|
|
|
odata->length--;
|
|
|
|
|
object_property_maybe_complete (self);
|
2014-08-18 18:12:01 -04:00
|
|
|
}
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
|
|
|
|
|
2016-10-18 16:35:07 +02:00
|
|
|
return TRUE;
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2016-10-18 16:35:07 +02:00
|
|
|
handle_property_changed (NMObject *self, const char *dbus_name, GVariant *value)
|
2014-07-24 08:53:33 -04:00
|
|
|
{
|
2014-10-22 15:06:27 -05:00
|
|
|
NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self);
|
|
|
|
|
char *prop_name;
|
|
|
|
|
PropertyInfo *pi;
|
|
|
|
|
GParamSpec *pspec;
|
|
|
|
|
gboolean success = FALSE, found = FALSE;
|
|
|
|
|
GSList *iter;
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
prop_name = wincaps_to_dash (dbus_name);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
/* Iterate through the object and its parents to find the property */
|
|
|
|
|
for (iter = priv->property_tables; iter; iter = g_slist_next (iter)) {
|
|
|
|
|
pi = g_hash_table_lookup ((GHashTable *) iter->data, prop_name);
|
|
|
|
|
if (pi) {
|
|
|
|
|
if (!pi->field) {
|
|
|
|
|
/* We know about this property but aren't tracking changes on it. */
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
found = TRUE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
|
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
if (!found) {
|
|
|
|
|
dbgmsg ("Property '%s' unhandled.", prop_name);
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (G_OBJECT (self)), prop_name);
|
|
|
|
|
if (!pspec && pi->func == demarshal_generic) {
|
|
|
|
|
dbgmsg ("%s: property '%s' changed but wasn't defined by object type %s.",
|
|
|
|
|
__func__,
|
|
|
|
|
prop_name,
|
|
|
|
|
G_OBJECT_TYPE_NAME (self));
|
|
|
|
|
goto out;
|
2014-10-06 21:17:14 -04:00
|
|
|
}
|
|
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
if (G_UNLIKELY (debug)) {
|
|
|
|
|
char *s;
|
|
|
|
|
s = g_variant_print (value, FALSE);
|
|
|
|
|
dbgmsg ("PC: (%p) %s:%s => '%s' (%s%s%s)",
|
|
|
|
|
self, G_OBJECT_TYPE_NAME (self),
|
|
|
|
|
prop_name,
|
|
|
|
|
s,
|
|
|
|
|
g_variant_get_type_string (value),
|
|
|
|
|
pi->object_type ? " / " : "",
|
|
|
|
|
pi->object_type ? g_type_name (pi->object_type) : "");
|
|
|
|
|
g_free (s);
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
|
|
|
|
|
2014-12-04 17:39:26 +01:00
|
|
|
if (pspec && pi->object_type) {
|
2014-10-22 15:06:27 -05:00
|
|
|
if (g_variant_is_of_type (value, G_VARIANT_TYPE_OBJECT_PATH))
|
2016-10-18 16:35:07 +02:00
|
|
|
success = handle_object_property (self, pspec->name, value, pi);
|
2014-10-22 15:06:27 -05:00
|
|
|
else if (g_variant_is_of_type (value, G_VARIANT_TYPE ("ao")))
|
2016-10-18 16:35:07 +02:00
|
|
|
success = handle_object_array_property (self, pspec->name, value, pi);
|
2014-10-22 15:06:27 -05:00
|
|
|
else {
|
|
|
|
|
g_warn_if_reached ();
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
} else
|
|
|
|
|
success = (*(pi->func)) (self, pspec, value, pi->field);
|
2014-08-18 18:12:01 -04:00
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
if (!success) {
|
|
|
|
|
dbgmsg ("%s: failed to update property '%s' of object type %s.",
|
|
|
|
|
__func__,
|
|
|
|
|
prop_name,
|
|
|
|
|
G_OBJECT_TYPE_NAME (self));
|
2014-08-18 18:12:01 -04:00
|
|
|
}
|
|
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
out:
|
|
|
|
|
g_free (prop_name);
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
|
|
|
|
|
2014-09-10 09:29:51 -04:00
|
|
|
static void
|
2016-10-18 16:35:07 +02:00
|
|
|
properties_changed (GDBusProxy *proxy,
|
|
|
|
|
GVariant *changed_properties,
|
|
|
|
|
GStrv invalidated_properties,
|
|
|
|
|
gpointer user_data)
|
2014-09-10 09:29:51 -04:00
|
|
|
{
|
2016-10-18 16:35:07 +02:00
|
|
|
NMObject *self = NM_OBJECT (user_data);
|
2014-10-22 15:06:27 -05:00
|
|
|
GVariantIter iter;
|
|
|
|
|
const char *name;
|
|
|
|
|
GVariant *value;
|
2014-09-10 09:29:51 -04:00
|
|
|
|
2016-10-18 16:35:07 +02:00
|
|
|
g_variant_iter_init (&iter, changed_properties);
|
2016-03-08 16:02:27 +01:00
|
|
|
while (g_variant_iter_next (&iter, "{&sv}", &name, &value)) {
|
2016-10-18 16:35:07 +02:00
|
|
|
handle_property_changed (self, name, value);
|
2016-03-08 16:02:27 +01:00
|
|
|
g_variant_unref (value);
|
|
|
|
|
}
|
2014-09-10 09:29:51 -04:00
|
|
|
}
|
|
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
#define HANDLE_TYPE(vtype, ctype, getter) \
|
|
|
|
|
G_STMT_START { \
|
|
|
|
|
if (g_variant_is_of_type (value, vtype)) { \
|
|
|
|
|
ctype *param = (ctype *) field; \
|
2015-03-26 17:51:51 +01:00
|
|
|
ctype newval = getter (value); \
|
|
|
|
|
different = *param != newval; \
|
|
|
|
|
*param = newval; \
|
2014-10-22 15:06:27 -05:00
|
|
|
} else { \
|
|
|
|
|
success = FALSE; \
|
|
|
|
|
goto done; \
|
|
|
|
|
} \
|
|
|
|
|
} G_STMT_END
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
static gboolean
|
|
|
|
|
demarshal_generic (NMObject *object,
|
|
|
|
|
GParamSpec *pspec,
|
|
|
|
|
GVariant *value,
|
|
|
|
|
gpointer field)
|
2014-07-24 08:53:33 -04:00
|
|
|
{
|
2014-10-22 15:06:27 -05:00
|
|
|
gboolean success = TRUE;
|
2015-03-26 17:51:51 +01:00
|
|
|
gboolean different = FALSE;
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
if (pspec->value_type == G_TYPE_STRING) {
|
|
|
|
|
if (g_variant_is_of_type (value, G_VARIANT_TYPE_STRING)) {
|
|
|
|
|
char **param = (char **) field;
|
2015-03-26 17:51:51 +01:00
|
|
|
const char *newval = g_variant_get_string (value, NULL);
|
|
|
|
|
|
|
|
|
|
different = !!g_strcmp0 (*param, newval);
|
|
|
|
|
if (different) {
|
|
|
|
|
g_free (*param);
|
|
|
|
|
*param = g_strdup (newval);
|
|
|
|
|
}
|
2014-10-22 15:06:27 -05:00
|
|
|
} else if (g_variant_is_of_type (value, G_VARIANT_TYPE_OBJECT_PATH)) {
|
|
|
|
|
char **param = (char **) field;
|
2015-03-26 17:51:51 +01:00
|
|
|
const char *newval = g_variant_get_string (value, NULL);
|
|
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
/* Handle "NULL" object paths */
|
2015-03-26 17:51:51 +01:00
|
|
|
if (g_strcmp0 (newval, "/") == 0)
|
|
|
|
|
newval = NULL;
|
|
|
|
|
different = !!g_strcmp0 (*param, newval);
|
|
|
|
|
if (different) {
|
2014-10-22 15:06:27 -05:00
|
|
|
g_free (*param);
|
2015-03-26 17:51:51 +01:00
|
|
|
*param = g_strdup (newval);
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
2014-10-22 15:06:27 -05:00
|
|
|
} else {
|
|
|
|
|
success = FALSE;
|
|
|
|
|
goto done;
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
2014-10-22 15:06:27 -05:00
|
|
|
} else if (pspec->value_type == G_TYPE_STRV) {
|
|
|
|
|
char ***param = (char ***)field;
|
2015-03-26 17:51:51 +01:00
|
|
|
const char **newval;
|
|
|
|
|
gsize i;
|
|
|
|
|
|
|
|
|
|
newval = g_variant_get_strv (value, NULL);
|
|
|
|
|
if (!*param)
|
|
|
|
|
different = TRUE;
|
|
|
|
|
else {
|
|
|
|
|
if (!_nm_utils_strv_equal ((char **) newval, *param)) {
|
|
|
|
|
different = TRUE;
|
|
|
|
|
g_strfreev (*param);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (different) {
|
|
|
|
|
for (i = 0; newval[i]; i++)
|
|
|
|
|
newval[i] = g_strdup (newval[i]);
|
|
|
|
|
*param = (char **) newval;
|
|
|
|
|
} else
|
|
|
|
|
g_free (newval);
|
2014-10-22 15:06:27 -05:00
|
|
|
} else if (pspec->value_type == G_TYPE_BYTES) {
|
|
|
|
|
GBytes **param = (GBytes **)field;
|
2018-08-22 20:49:43 +02:00
|
|
|
gconstpointer val;
|
|
|
|
|
gsize length = 0;
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
val = g_variant_get_fixed_array (value, &length, 1);
|
2015-03-26 17:51:51 +01:00
|
|
|
|
2018-08-22 20:49:43 +02:00
|
|
|
different = !nm_utils_gbytes_equal_mem (*param, val, length);
|
2015-03-26 17:51:51 +01:00
|
|
|
if (different) {
|
|
|
|
|
if (*param)
|
|
|
|
|
g_bytes_unref (*param);
|
|
|
|
|
*param = length > 0 ? g_bytes_new (val, length) : NULL;
|
|
|
|
|
}
|
2014-10-22 15:06:27 -05:00
|
|
|
} else if (G_IS_PARAM_SPEC_ENUM (pspec)) {
|
|
|
|
|
int *param = (int *) field;
|
2015-03-26 17:51:51 +01:00
|
|
|
int newval = 0;
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
if (g_variant_is_of_type (value, G_VARIANT_TYPE_INT32))
|
2015-03-26 17:51:51 +01:00
|
|
|
newval = g_variant_get_int32 (value);
|
2014-10-22 15:06:27 -05:00
|
|
|
else if (g_variant_is_of_type (value, G_VARIANT_TYPE_UINT32))
|
2015-03-26 17:51:51 +01:00
|
|
|
newval = g_variant_get_uint32 (value);
|
2014-10-22 15:06:27 -05:00
|
|
|
else {
|
|
|
|
|
success = FALSE;
|
|
|
|
|
goto done;
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
2015-03-26 17:51:51 +01:00
|
|
|
different = *param != newval;
|
|
|
|
|
*param = newval;
|
2014-10-22 15:06:27 -05:00
|
|
|
} else if (G_IS_PARAM_SPEC_FLAGS (pspec)) {
|
|
|
|
|
guint *param = (guint *) field;
|
2015-03-26 17:51:51 +01:00
|
|
|
guint newval = 0;
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
if (g_variant_is_of_type (value, G_VARIANT_TYPE_INT32))
|
2015-03-26 17:51:51 +01:00
|
|
|
newval = g_variant_get_int32 (value);
|
2014-10-22 15:06:27 -05:00
|
|
|
else if (g_variant_is_of_type (value, G_VARIANT_TYPE_UINT32))
|
2015-03-26 17:51:51 +01:00
|
|
|
newval = g_variant_get_uint32 (value);
|
2014-10-22 15:06:27 -05:00
|
|
|
else {
|
|
|
|
|
success = FALSE;
|
|
|
|
|
goto done;
|
|
|
|
|
}
|
2015-03-26 17:51:51 +01:00
|
|
|
different = *param != newval;
|
|
|
|
|
*param = newval;
|
2014-10-22 15:06:27 -05:00
|
|
|
} else if (pspec->value_type == G_TYPE_BOOLEAN)
|
|
|
|
|
HANDLE_TYPE (G_VARIANT_TYPE_BOOLEAN, gboolean, g_variant_get_boolean);
|
|
|
|
|
else if (pspec->value_type == G_TYPE_UCHAR)
|
|
|
|
|
HANDLE_TYPE (G_VARIANT_TYPE_BYTE, guchar, g_variant_get_byte);
|
2015-03-26 17:51:51 +01:00
|
|
|
else if (pspec->value_type == G_TYPE_DOUBLE) {
|
|
|
|
|
NM_PRAGMA_WARNING_DISABLE("-Wfloat-equal")
|
all: don't use gchar/gshort/gint/glong but C types
We commonly don't use the glib typedefs for char/short/int/long,
but their C types directly.
$ git grep '\<g\(char\|short\|int\|long\|float\|double\)\>' | wc -l
587
$ git grep '\<\(char\|short\|int\|long\|float\|double\)\>' | wc -l
21114
One could argue that using the glib typedefs is preferable in
public API (of our glib based libnm library) or where it clearly
is related to glib, like during
g_object_set (obj, PROPERTY, (gint) value, NULL);
However, that argument does not seem strong, because in practice we don't
follow that argument today, and seldomly use the glib typedefs.
Also, the style guide for this would be hard to formalize, because
"using them where clearly related to a glib" is a very loose suggestion.
Also note that glib typedefs will always just be typedefs of the
underlying C types. There is no danger of glib changing the meaning
of these typedefs (because that would be a major API break of glib).
A simple style guide is instead: don't use these typedefs.
No manual actions, I only ran the bash script:
FILES=($(git ls-files '*.[hc]'))
sed -i \
-e 's/\<g\(char\|short\|int\|long\|float\|double\)\>\( [^ ]\)/\1\2/g' \
-e 's/\<g\(char\|short\|int\|long\|float\|double\)\> /\1 /g' \
-e 's/\<g\(char\|short\|int\|long\|float\|double\)\>/\1/g' \
"${FILES[@]}"
2018-07-11 07:40:19 +02:00
|
|
|
HANDLE_TYPE (G_VARIANT_TYPE_DOUBLE, double, g_variant_get_double);
|
2015-03-26 17:51:51 +01:00
|
|
|
NM_PRAGMA_WARNING_REENABLE
|
|
|
|
|
} else if (pspec->value_type == G_TYPE_INT)
|
all: don't use gchar/gshort/gint/glong but C types
We commonly don't use the glib typedefs for char/short/int/long,
but their C types directly.
$ git grep '\<g\(char\|short\|int\|long\|float\|double\)\>' | wc -l
587
$ git grep '\<\(char\|short\|int\|long\|float\|double\)\>' | wc -l
21114
One could argue that using the glib typedefs is preferable in
public API (of our glib based libnm library) or where it clearly
is related to glib, like during
g_object_set (obj, PROPERTY, (gint) value, NULL);
However, that argument does not seem strong, because in practice we don't
follow that argument today, and seldomly use the glib typedefs.
Also, the style guide for this would be hard to formalize, because
"using them where clearly related to a glib" is a very loose suggestion.
Also note that glib typedefs will always just be typedefs of the
underlying C types. There is no danger of glib changing the meaning
of these typedefs (because that would be a major API break of glib).
A simple style guide is instead: don't use these typedefs.
No manual actions, I only ran the bash script:
FILES=($(git ls-files '*.[hc]'))
sed -i \
-e 's/\<g\(char\|short\|int\|long\|float\|double\)\>\( [^ ]\)/\1\2/g' \
-e 's/\<g\(char\|short\|int\|long\|float\|double\)\> /\1 /g' \
-e 's/\<g\(char\|short\|int\|long\|float\|double\)\>/\1/g' \
"${FILES[@]}"
2018-07-11 07:40:19 +02:00
|
|
|
HANDLE_TYPE (G_VARIANT_TYPE_INT32, int, g_variant_get_int32);
|
2014-10-22 15:06:27 -05:00
|
|
|
else if (pspec->value_type == G_TYPE_UINT)
|
|
|
|
|
HANDLE_TYPE (G_VARIANT_TYPE_UINT32, guint, g_variant_get_uint32);
|
|
|
|
|
else if (pspec->value_type == G_TYPE_INT64)
|
2018-06-15 15:17:28 +02:00
|
|
|
HANDLE_TYPE (G_VARIANT_TYPE_INT64, gint64, g_variant_get_int64);
|
2014-10-22 15:06:27 -05:00
|
|
|
else if (pspec->value_type == G_TYPE_UINT64)
|
2018-06-15 15:17:28 +02:00
|
|
|
HANDLE_TYPE (G_VARIANT_TYPE_UINT64, guint64, g_variant_get_uint64);
|
2014-10-22 15:06:27 -05:00
|
|
|
else if (pspec->value_type == G_TYPE_LONG)
|
all: don't use gchar/gshort/gint/glong but C types
We commonly don't use the glib typedefs for char/short/int/long,
but their C types directly.
$ git grep '\<g\(char\|short\|int\|long\|float\|double\)\>' | wc -l
587
$ git grep '\<\(char\|short\|int\|long\|float\|double\)\>' | wc -l
21114
One could argue that using the glib typedefs is preferable in
public API (of our glib based libnm library) or where it clearly
is related to glib, like during
g_object_set (obj, PROPERTY, (gint) value, NULL);
However, that argument does not seem strong, because in practice we don't
follow that argument today, and seldomly use the glib typedefs.
Also, the style guide for this would be hard to formalize, because
"using them where clearly related to a glib" is a very loose suggestion.
Also note that glib typedefs will always just be typedefs of the
underlying C types. There is no danger of glib changing the meaning
of these typedefs (because that would be a major API break of glib).
A simple style guide is instead: don't use these typedefs.
No manual actions, I only ran the bash script:
FILES=($(git ls-files '*.[hc]'))
sed -i \
-e 's/\<g\(char\|short\|int\|long\|float\|double\)\>\( [^ ]\)/\1\2/g' \
-e 's/\<g\(char\|short\|int\|long\|float\|double\)\> /\1 /g' \
-e 's/\<g\(char\|short\|int\|long\|float\|double\)\>/\1/g' \
"${FILES[@]}"
2018-07-11 07:40:19 +02:00
|
|
|
HANDLE_TYPE (G_VARIANT_TYPE_INT64, long, g_variant_get_int64);
|
2014-10-22 15:06:27 -05:00
|
|
|
else if (pspec->value_type == G_TYPE_ULONG)
|
|
|
|
|
HANDLE_TYPE (G_VARIANT_TYPE_UINT64, gulong, g_variant_get_uint64);
|
|
|
|
|
else {
|
|
|
|
|
g_warning ("%s: %s:%s unhandled type %s.",
|
|
|
|
|
__func__,
|
|
|
|
|
G_OBJECT_TYPE_NAME (object),
|
|
|
|
|
pspec->name,
|
|
|
|
|
g_type_name (pspec->value_type));
|
|
|
|
|
success = FALSE;
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
|
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
done:
|
|
|
|
|
if (success) {
|
2015-03-26 17:51:51 +01:00
|
|
|
if (different)
|
|
|
|
|
_nm_object_queue_notify (object, pspec->name);
|
2014-10-22 15:06:27 -05:00
|
|
|
} else {
|
|
|
|
|
dbgmsg ("%s: %s:%s (type %s) couldn't be set from D-Bus type %s.",
|
|
|
|
|
__func__, G_OBJECT_TYPE_NAME (object), pspec->name,
|
|
|
|
|
g_type_name (pspec->value_type), g_variant_get_type_string (value));
|
|
|
|
|
}
|
|
|
|
|
return success;
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
|
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
void
|
|
|
|
|
_nm_object_register_properties (NMObject *object,
|
|
|
|
|
const char *interface,
|
|
|
|
|
const NMPropertiesInfo *info)
|
2014-07-24 08:53:33 -04:00
|
|
|
{
|
2014-10-22 15:06:27 -05:00
|
|
|
NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
|
|
|
|
|
GDBusProxy *proxy;
|
|
|
|
|
static gsize dval = 0;
|
|
|
|
|
const char *debugstr;
|
|
|
|
|
NMPropertiesInfo *tmp;
|
|
|
|
|
GHashTable *instance;
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
g_return_if_fail (NM_IS_OBJECT (object));
|
|
|
|
|
g_return_if_fail (interface != NULL);
|
|
|
|
|
g_return_if_fail (info != NULL);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
if (g_once_init_enter (&dval)) {
|
|
|
|
|
debugstr = getenv ("LIBNM_GLIB_DEBUG");
|
|
|
|
|
if (debugstr && strstr (debugstr, "properties-changed"))
|
|
|
|
|
debug = TRUE;
|
|
|
|
|
g_once_init_leave (&dval, 1);
|
|
|
|
|
}
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
proxy = _nm_object_get_proxy (object, interface);
|
2016-10-18 16:35:07 +02:00
|
|
|
g_signal_connect (proxy, "g-properties-changed",
|
2017-05-06 21:14:30 +02:00
|
|
|
G_CALLBACK (properties_changed), object);
|
2017-02-16 18:48:38 +01:00
|
|
|
g_ptr_array_add (priv->proxies, proxy);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2017-11-15 16:06:43 +01:00
|
|
|
instance = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, g_free);
|
2014-10-22 15:06:27 -05:00
|
|
|
priv->property_tables = g_slist_prepend (priv->property_tables, instance);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
for (tmp = (NMPropertiesInfo *) info; tmp->name; tmp++) {
|
|
|
|
|
PropertyInfo *pi;
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
if (!tmp->name || (tmp->func && !tmp->field)) {
|
|
|
|
|
g_warning ("%s: missing field in NMPropertiesInfo", __func__);
|
|
|
|
|
continue;
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
|
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
pi = g_malloc0 (sizeof (PropertyInfo));
|
2018-04-24 11:20:03 +02:00
|
|
|
pi->func = tmp->func ?: demarshal_generic;
|
2014-10-22 15:06:27 -05:00
|
|
|
pi->object_type = tmp->object_type;
|
|
|
|
|
pi->field = tmp->field;
|
|
|
|
|
pi->signal_prefix = tmp->signal_prefix;
|
|
|
|
|
g_hash_table_insert (instance, g_strdup (tmp->name), pi);
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
void
|
|
|
|
|
_nm_object_set_property (NMObject *object,
|
|
|
|
|
const char *interface,
|
|
|
|
|
const char *prop_name,
|
|
|
|
|
const char *format_string,
|
|
|
|
|
...)
|
2014-07-24 08:53:33 -04:00
|
|
|
{
|
2014-10-22 15:06:27 -05:00
|
|
|
GVariant *val, *ret;
|
2016-11-14 18:47:56 +01:00
|
|
|
GDBusProxy *proxy;
|
2014-10-22 15:06:27 -05:00
|
|
|
va_list ap;
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
g_return_if_fail (NM_IS_OBJECT (object));
|
|
|
|
|
g_return_if_fail (interface != NULL);
|
|
|
|
|
g_return_if_fail (prop_name != NULL);
|
|
|
|
|
g_return_if_fail (format_string != NULL);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
va_start (ap, format_string);
|
|
|
|
|
val = g_variant_new_va (format_string, NULL, &ap);
|
|
|
|
|
va_end (ap);
|
|
|
|
|
g_return_if_fail (val != NULL);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2016-11-14 18:47:56 +01:00
|
|
|
proxy = _nm_object_get_proxy (object, interface);
|
|
|
|
|
ret = g_dbus_proxy_call_sync (proxy,
|
2016-10-18 16:35:07 +02:00
|
|
|
DBUS_INTERFACE_PROPERTIES ".Set",
|
2014-10-22 15:06:27 -05:00
|
|
|
g_variant_new ("(ssv)", interface, prop_name, val),
|
|
|
|
|
G_DBUS_CALL_FLAGS_NONE, 2000,
|
|
|
|
|
NULL, NULL);
|
|
|
|
|
/* Ignore errors. */
|
|
|
|
|
if (ret)
|
|
|
|
|
g_variant_unref (ret);
|
2016-11-14 18:47:56 +01:00
|
|
|
g_object_unref (proxy);
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2014-10-22 16:44:26 -05:00
|
|
|
reload_complete (NMObject *object, gboolean emit_now)
|
2014-07-24 08:53:33 -04:00
|
|
|
{
|
2014-10-22 15:06:27 -05:00
|
|
|
NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-22 16:44:26 -05:00
|
|
|
if (emit_now) {
|
2015-10-03 18:12:11 +02:00
|
|
|
nm_clear_g_source (&priv->notify_id);
|
2014-10-22 16:44:26 -05:00
|
|
|
deferred_notify_cb (object);
|
|
|
|
|
} else
|
|
|
|
|
_nm_object_defer_notify (object);
|
2014-10-22 15:06:27 -05:00
|
|
|
}
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2016-10-18 16:35:07 +02:00
|
|
|
GDBusObjectManager *
|
|
|
|
|
_nm_object_get_dbus_object_manager (NMObject *self)
|
2014-10-22 15:06:27 -05:00
|
|
|
{
|
2016-10-18 16:35:07 +02:00
|
|
|
return NM_OBJECT_GET_PRIVATE (self)->object_manager;
|
2014-10-22 15:06:27 -05:00
|
|
|
}
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2014-10-22 15:06:27 -05:00
|
|
|
|
|
|
|
|
static void
|
2016-10-18 16:35:07 +02:00
|
|
|
init_dbus (NMObject *object)
|
2014-10-22 15:06:27 -05:00
|
|
|
{
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
|
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
static void
|
2017-05-27 11:36:44 +02:00
|
|
|
init_if (GDBusProxy *proxy, NMObject *self)
|
2014-07-24 08:53:33 -04:00
|
|
|
{
|
all: don't use gchar/gshort/gint/glong but C types
We commonly don't use the glib typedefs for char/short/int/long,
but their C types directly.
$ git grep '\<g\(char\|short\|int\|long\|float\|double\)\>' | wc -l
587
$ git grep '\<\(char\|short\|int\|long\|float\|double\)\>' | wc -l
21114
One could argue that using the glib typedefs is preferable in
public API (of our glib based libnm library) or where it clearly
is related to glib, like during
g_object_set (obj, PROPERTY, (gint) value, NULL);
However, that argument does not seem strong, because in practice we don't
follow that argument today, and seldomly use the glib typedefs.
Also, the style guide for this would be hard to formalize, because
"using them where clearly related to a glib" is a very loose suggestion.
Also note that glib typedefs will always just be typedefs of the
underlying C types. There is no danger of glib changing the meaning
of these typedefs (because that would be a major API break of glib).
A simple style guide is instead: don't use these typedefs.
No manual actions, I only ran the bash script:
FILES=($(git ls-files '*.[hc]'))
sed -i \
-e 's/\<g\(char\|short\|int\|long\|float\|double\)\>\( [^ ]\)/\1\2/g' \
-e 's/\<g\(char\|short\|int\|long\|float\|double\)\> /\1 /g' \
-e 's/\<g\(char\|short\|int\|long\|float\|double\)\>/\1/g' \
"${FILES[@]}"
2018-07-11 07:40:19 +02:00
|
|
|
char **props;
|
2016-10-18 16:35:07 +02:00
|
|
|
char **prop;
|
|
|
|
|
GVariant *val;
|
all: don't use gchar/gshort/gint/glong but C types
We commonly don't use the glib typedefs for char/short/int/long,
but their C types directly.
$ git grep '\<g\(char\|short\|int\|long\|float\|double\)\>' | wc -l
587
$ git grep '\<\(char\|short\|int\|long\|float\|double\)\>' | wc -l
21114
One could argue that using the glib typedefs is preferable in
public API (of our glib based libnm library) or where it clearly
is related to glib, like during
g_object_set (obj, PROPERTY, (gint) value, NULL);
However, that argument does not seem strong, because in practice we don't
follow that argument today, and seldomly use the glib typedefs.
Also, the style guide for this would be hard to formalize, because
"using them where clearly related to a glib" is a very loose suggestion.
Also note that glib typedefs will always just be typedefs of the
underlying C types. There is no danger of glib changing the meaning
of these typedefs (because that would be a major API break of glib).
A simple style guide is instead: don't use these typedefs.
No manual actions, I only ran the bash script:
FILES=($(git ls-files '*.[hc]'))
sed -i \
-e 's/\<g\(char\|short\|int\|long\|float\|double\)\>\( [^ ]\)/\1\2/g' \
-e 's/\<g\(char\|short\|int\|long\|float\|double\)\> /\1 /g' \
-e 's/\<g\(char\|short\|int\|long\|float\|double\)\>/\1/g' \
"${FILES[@]}"
2018-07-11 07:40:19 +02:00
|
|
|
char *str;
|
2016-10-18 16:35:07 +02:00
|
|
|
|
2017-05-27 11:36:44 +02:00
|
|
|
nm_assert (G_IS_DBUS_PROXY (proxy));
|
|
|
|
|
nm_assert (NM_IS_OBJECT (self));
|
|
|
|
|
|
2016-10-18 16:35:07 +02:00
|
|
|
props = g_dbus_proxy_get_cached_property_names (proxy);
|
|
|
|
|
|
2017-02-01 15:19:29 +01:00
|
|
|
for (prop = props; prop && *prop; prop++) {
|
2016-10-18 16:35:07 +02:00
|
|
|
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);
|
2014-10-22 15:06:27 -05:00
|
|
|
}
|
2016-10-18 16:35:07 +02:00
|
|
|
|
|
|
|
|
g_strfreev (props);
|
2014-10-22 15:06:27 -05:00
|
|
|
}
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
static gboolean
|
|
|
|
|
init_sync (GInitable *initable, GCancellable *cancellable, GError **error)
|
|
|
|
|
{
|
|
|
|
|
NMObject *self = NM_OBJECT (initable);
|
|
|
|
|
NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self);
|
2016-10-18 16:35:07 +02:00
|
|
|
GList *interfaces;
|
2014-10-22 15:06:27 -05:00
|
|
|
|
2016-10-18 16:35:07 +02:00
|
|
|
g_assert (priv->object && priv->object_manager);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2016-10-18 16:35:07 +02:00
|
|
|
NM_OBJECT_GET_CLASS (self)->init_dbus (self);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2016-10-18 16:35:07 +02:00
|
|
|
priv->reload_remaining++;
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2016-10-18 16:35:07 +02:00
|
|
|
interfaces = g_dbus_object_get_interfaces (priv->object);
|
|
|
|
|
g_list_foreach (interfaces, (GFunc) init_if, self);
|
|
|
|
|
g_list_free_full (interfaces, g_object_unref);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2016-10-18 16:35:07 +02:00
|
|
|
priv->inited = TRUE;
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2016-10-18 16:35:07 +02:00
|
|
|
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;
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2016-10-18 16:35:07 +02:00
|
|
|
priv->waiters = g_slist_remove (priv->waiters, odata);
|
|
|
|
|
object_property_maybe_complete (odata->self);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2014-10-22 15:06:27 -05:00
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
NMObject *object;
|
|
|
|
|
GSimpleAsyncResult *simple;
|
|
|
|
|
GCancellable *cancellable;
|
|
|
|
|
int proxies_pending;
|
|
|
|
|
GError *error;
|
|
|
|
|
} NMObjectInitData;
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
init_async_complete (NMObjectInitData *init_data)
|
2014-07-24 08:53:33 -04:00
|
|
|
{
|
2014-10-22 15:06:27 -05:00
|
|
|
if (init_data->error)
|
|
|
|
|
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);
|
2016-10-18 16:35:07 +02:00
|
|
|
g_simple_async_result_complete_in_idle (init_data->simple);
|
2014-10-22 15:06:27 -05:00
|
|
|
g_object_unref (init_data->simple);
|
|
|
|
|
g_clear_object (&init_data->cancellable);
|
|
|
|
|
g_slice_free (NMObjectInitData, init_data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
init_async (GAsyncInitable *initable, int io_priority,
|
|
|
|
|
GCancellable *cancellable, GAsyncReadyCallback callback,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
NMObject *self = NM_OBJECT (initable);
|
|
|
|
|
NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self);
|
|
|
|
|
NMObjectInitData *init_data;
|
2016-10-18 16:35:07 +02:00
|
|
|
GList *interfaces;
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2016-10-18 16:35:07 +02:00
|
|
|
g_assert (priv->object && priv->object_manager);
|
|
|
|
|
|
|
|
|
|
NM_OBJECT_GET_CLASS (self)->init_dbus (self);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
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);
|
2018-03-05 16:02:24 +01:00
|
|
|
if (cancellable)
|
|
|
|
|
g_simple_async_result_set_check_cancellable (init_data->simple, cancellable);
|
2014-10-22 15:06:27 -05:00
|
|
|
init_data->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
|
|
|
|
|
|
2016-10-18 16:35:07 +02:00
|
|
|
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);
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
|
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
static gboolean
|
|
|
|
|
init_finish (GAsyncInitable *initable, GAsyncResult *result, GError **error)
|
2014-07-24 08:53:33 -04:00
|
|
|
{
|
2014-10-22 15:06:27 -05:00
|
|
|
GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
|
2016-10-18 16:35:07 +02:00
|
|
|
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);
|
|
|
|
|
}
|
2014-09-10 13:51:53 -04:00
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
if (g_simple_async_result_propagate_error (simple, error))
|
|
|
|
|
return FALSE;
|
|
|
|
|
else
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
static void
|
|
|
|
|
nm_object_initable_iface_init (GInitableIface *iface)
|
|
|
|
|
{
|
|
|
|
|
iface->init = init_sync;
|
|
|
|
|
}
|
2014-09-10 13:51:53 -04:00
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
static void
|
|
|
|
|
nm_object_async_initable_iface_init (GAsyncInitableIface *iface)
|
|
|
|
|
{
|
|
|
|
|
iface->init_async = init_async;
|
|
|
|
|
iface->init_finish = init_finish;
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2014-10-22 15:06:27 -05:00
|
|
|
nm_object_init (NMObject *object)
|
2014-07-24 08:53:33 -04:00
|
|
|
{
|
2017-05-06 21:14:30 +02:00
|
|
|
NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
|
|
|
|
|
|
|
|
|
|
c_list_init (&priv->notify_items);
|
2017-05-06 21:14:30 +02:00
|
|
|
c_list_init (&priv->pending);
|
2017-05-06 21:14:30 +02:00
|
|
|
priv->proxies = g_ptr_array_new ();
|
2014-10-22 15:06:27 -05:00
|
|
|
}
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
static void
|
|
|
|
|
set_property (GObject *object, guint prop_id,
|
|
|
|
|
const GValue *value, GParamSpec *pspec)
|
|
|
|
|
{
|
|
|
|
|
NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
switch (prop_id) {
|
2016-10-18 16:35:07 +02:00
|
|
|
case PROP_DBUS_OBJECT:
|
2017-03-08 13:43:56 +01:00
|
|
|
/* construct-only */
|
2016-10-18 16:35:07 +02:00
|
|
|
priv->object = g_value_dup_object (value);
|
2017-03-08 08:16:44 +01:00
|
|
|
if (!priv->object)
|
|
|
|
|
g_return_if_reached ();
|
2014-10-22 15:06:27 -05:00
|
|
|
break;
|
2016-10-18 16:35:07 +02:00
|
|
|
case PROP_DBUS_OBJECT_MANAGER:
|
2017-03-08 13:43:56 +01:00
|
|
|
/* construct-only */
|
2016-10-18 16:35:07 +02:00
|
|
|
priv->object_manager = g_value_dup_object (value);
|
2014-10-22 15:06:27 -05:00
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
|
|
|
break;
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2014-10-22 15:06:27 -05:00
|
|
|
get_property (GObject *object, guint prop_id,
|
|
|
|
|
GValue *value, GParamSpec *pspec)
|
2014-07-24 08:53:33 -04:00
|
|
|
{
|
|
|
|
|
NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
|
|
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
switch (prop_id) {
|
|
|
|
|
case PROP_PATH:
|
2016-10-18 16:35:07 +02:00
|
|
|
g_value_set_string (value, nm_object_get_path (NM_OBJECT (object)));
|
2014-10-22 15:06:27 -05:00
|
|
|
break;
|
|
|
|
|
case PROP_DBUS_CONNECTION:
|
2016-10-18 16:35:07 +02:00
|
|
|
g_value_set_object (value, g_dbus_object_manager_client_get_connection (G_DBUS_OBJECT_MANAGER_CLIENT (priv->object_manager)));
|
2014-10-22 15:06:27 -05:00
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
|
|
|
break;
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
static void
|
|
|
|
|
dispose (GObject *object)
|
2014-07-24 08:53:33 -04:00
|
|
|
{
|
|
|
|
|
NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
|
2017-05-06 21:14:30 +02:00
|
|
|
CList *iter, *safe;
|
2017-02-16 18:48:38 +01:00
|
|
|
guint i;
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2016-01-04 09:46:22 +01:00
|
|
|
nm_clear_g_source (&priv->notify_id);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2017-05-06 21:14:30 +02:00
|
|
|
c_list_for_each_safe (iter, safe, &priv->notify_items)
|
|
|
|
|
notify_item_free (c_list_entry (iter, NotifyItem, lst));
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2016-03-10 19:22:20 +01:00
|
|
|
g_slist_free_full (priv->waiters, odata_free);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2016-10-18 16:35:07 +02:00
|
|
|
g_clear_object (&priv->object);
|
|
|
|
|
g_clear_object (&priv->object_manager);
|
2014-10-22 15:06:27 -05:00
|
|
|
|
2017-02-16 18:48:38 +01:00
|
|
|
if (priv->proxies) {
|
|
|
|
|
for (i = 0; i < priv->proxies->len; i++) {
|
|
|
|
|
g_signal_handlers_disconnect_by_func (priv->proxies->pdata[i],
|
|
|
|
|
properties_changed,
|
|
|
|
|
object);
|
|
|
|
|
g_object_unref (priv->proxies->pdata[i]);
|
|
|
|
|
}
|
|
|
|
|
g_ptr_array_free (priv->proxies, TRUE);
|
|
|
|
|
priv->proxies = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
G_OBJECT_CLASS (nm_object_parent_class)->dispose (object);
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
|
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
static void
|
|
|
|
|
finalize (GObject *object)
|
2014-07-24 08:53:33 -04:00
|
|
|
{
|
2014-10-23 16:51:41 +02:00
|
|
|
NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
|
|
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
g_slist_free_full (priv->property_tables, (GDestroyNotify) g_hash_table_destroy);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2019-10-04 13:56:36 +02:00
|
|
|
g_free (priv->name_owner_cached);
|
|
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
G_OBJECT_CLASS (nm_object_parent_class)->finalize (object);
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
|
|
|
|
|
2014-10-22 15:06:27 -05:00
|
|
|
static void
|
|
|
|
|
nm_object_class_init (NMObjectClass *nm_object_class)
|
2014-07-14 12:17:59 -04:00
|
|
|
{
|
2014-10-22 15:06:27 -05:00
|
|
|
GObjectClass *object_class = G_OBJECT_CLASS (nm_object_class);
|
|
|
|
|
|
|
|
|
|
g_type_class_add_private (nm_object_class, sizeof (NMObjectPrivate));
|
|
|
|
|
|
|
|
|
|
object_class->get_property = get_property;
|
2019-10-10 17:57:30 +02:00
|
|
|
object_class->set_property = set_property;
|
|
|
|
|
object_class->dispose = dispose;
|
|
|
|
|
object_class->finalize = finalize;
|
2014-10-22 15:06:27 -05:00
|
|
|
|
|
|
|
|
nm_object_class->init_dbus = init_dbus;
|
|
|
|
|
|
|
|
|
|
/**
|
2018-09-19 07:57:30 +02:00
|
|
|
* NMObject:path:
|
2014-10-22 15:06:27 -05:00
|
|
|
*
|
|
|
|
|
* The D-Bus object path.
|
|
|
|
|
**/
|
2019-10-10 17:57:30 +02:00
|
|
|
obj_properties[PROP_PATH] =
|
|
|
|
|
g_param_spec_string (NM_OBJECT_PATH, "", "",
|
|
|
|
|
NULL,
|
|
|
|
|
G_PARAM_READABLE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2014-10-22 15:06:27 -05:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* NMObject:dbus-connection: (skip)
|
|
|
|
|
*
|
|
|
|
|
* The #GDBusConnection of the object.
|
|
|
|
|
**/
|
2019-10-10 17:57:30 +02:00
|
|
|
obj_properties[PROP_DBUS_CONNECTION] =
|
|
|
|
|
g_param_spec_object (NM_OBJECT_DBUS_CONNECTION, "", "",
|
|
|
|
|
G_TYPE_DBUS_CONNECTION,
|
|
|
|
|
G_PARAM_READABLE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2016-10-18 16:35:07 +02:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* NMObject:dbus-object: (skip)
|
|
|
|
|
*
|
|
|
|
|
* The #GDBusObject of the object.
|
|
|
|
|
**/
|
2019-10-10 17:57:30 +02:00
|
|
|
obj_properties[PROP_DBUS_OBJECT] =
|
|
|
|
|
g_param_spec_object (NM_OBJECT_DBUS_OBJECT, "", "",
|
|
|
|
|
G_TYPE_DBUS_OBJECT,
|
|
|
|
|
G_PARAM_WRITABLE |
|
|
|
|
|
G_PARAM_CONSTRUCT_ONLY |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2014-10-22 15:06:27 -05:00
|
|
|
|
|
|
|
|
/**
|
2016-10-18 16:35:07 +02:00
|
|
|
* NMObject:dbus-object-manager: (skip)
|
2014-10-22 15:06:27 -05:00
|
|
|
*
|
2016-10-18 16:35:07 +02:00
|
|
|
* The #GDBusObjectManager of the object.
|
|
|
|
|
**/
|
2019-10-10 17:57:30 +02:00
|
|
|
obj_properties[PROP_DBUS_OBJECT_MANAGER] =
|
|
|
|
|
g_param_spec_object (NM_OBJECT_DBUS_OBJECT_MANAGER, "", "",
|
|
|
|
|
G_TYPE_DBUS_OBJECT_MANAGER,
|
|
|
|
|
G_PARAM_WRITABLE |
|
|
|
|
|
G_PARAM_CONSTRUCT_ONLY |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
|
|
|
|
|
|
|
|
|
g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
|
2014-07-14 12:17:59 -04:00
|
|
|
}
|