2015-04-13 13:31:42 -04:00
|
|
|
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
|
|
|
|
/* NetworkManager -- Network link manager
|
|
|
|
|
*
|
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
|
* (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License along
|
|
|
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
|
|
*
|
2016-03-30 16:59:12 +02:00
|
|
|
* Copyright 2014-2016 Red Hat, Inc.
|
2015-04-13 13:31:42 -04:00
|
|
|
*/
|
|
|
|
|
|
2016-02-19 14:57:48 +01:00
|
|
|
#include "nm-default.h"
|
2015-04-13 13:31:42 -04:00
|
|
|
|
2016-03-30 16:59:12 +02:00
|
|
|
#include "nm-exported-object.h"
|
|
|
|
|
|
2015-04-15 14:53:30 -04:00
|
|
|
#include <stdarg.h>
|
2015-04-13 13:31:42 -04:00
|
|
|
#include <string.h>
|
|
|
|
|
|
2015-04-16 14:20:51 -04:00
|
|
|
#include "nm-bus-manager.h"
|
2015-04-13 13:31:42 -04:00
|
|
|
|
2016-11-21 00:43:52 +01:00
|
|
|
#include "devices/nm-device.h"
|
dbus: fix emitting D-Bus NetworkManager's old-style PropertiesChange signal
Before switching to gdbus (before 1.2.0), NetworkManager used dbus-glib.
Most objects in the D-Bus API with properties had a signal
NetworkManager-specific "PropertiesChanged" signal. Nowadays, this way of
handling of property changes is deprecated for the common "PropertiesChanged"
signal on the "org.freedesktop.DBus.Properties" interface.
There were a few pecularities in 1.0.0 and earlier:
(1) Due to the implementation with dbus-glib, a property-changed
signal was emitted on *all* interfaces. For example:
- a change on a NMDeviceVeth of "NMDeviceEthernet.HwAddress" would be
emitted both for the interfaces "fdo.NM.Device.Ethernet" and
"fdo.NM.Device.Veth". Note that NMDeviceVeth is derived from
NMDeviceEthernet and there is no "HwAddress" on veth device.
- a change of "NMVpnConnection.VpnState" was emitted on both
interfaces "fdo.NM.VPN.Connection" and "fdo.NM.Connecion.Active".
Note that NMActiveConnection is the parent type of NMVpnConnection and
only the latter has a property "VpnState".
(2) NMDevice's "fdo.NM.Device" interface doesn't have a "PropertiesChanged"
signal. From (1) follows that all property-changes for this type were instead
invoked with an interface like "fdo.NM.Device.Ethernet" (or multiple
interfaces in case of NMDeviceVeth).
1.2.0 introduced gdbus, which gives us the standard "fdo.DBus.Properties"
signal. However, it made the mistake of not realizing (1), thus instead
of emitting the signal once for each interface, it would pick the first
one in the inheritance tree.
With 1.4.0, a bug from merge commit 844345e caused signals for devices
to be only emitted for the interface "fdo.NM.Device.Statistics", instead
of "fdo.NM.Device.Ethernet" or "fdo.NM.Device.Veth" (or both).
The latter is what bgo#770629 is about and what commit 82e9439 tried to fix.
However, the fix was wrong because it tried to do the theoretically correct
thing of emitting the property-changed signal exactly once for the
interface that actually ontains the property. In addition, it missed that
NMDevice doesn't have a PropertiesChanged signal, which caused signals for
"fdo.NM.Device" to get lost *sigh*.
Now, restore the (broken) behavior of 1.0.0. These old-style property changed
signals are anyway considered deprecated and exist solely to satisfy old clients
and preserve the old API.
Fixes: 63fbfad3705db5901e6a2a6a2fc332da0f0ae4be
https://bugzilla.gnome.org/show_bug.cgi?id=770629
https://bugzilla.redhat.com/show_bug.cgi?id=1371920
2016-09-01 13:00:21 +02:00
|
|
|
#include "nm-active-connection.h"
|
2016-11-23 13:14:08 +01:00
|
|
|
#include "introspection/org.freedesktop.NetworkManager.Device.Statistics.h"
|
dbus: fix emitting D-Bus NetworkManager's old-style PropertiesChange signal
Before switching to gdbus (before 1.2.0), NetworkManager used dbus-glib.
Most objects in the D-Bus API with properties had a signal
NetworkManager-specific "PropertiesChanged" signal. Nowadays, this way of
handling of property changes is deprecated for the common "PropertiesChanged"
signal on the "org.freedesktop.DBus.Properties" interface.
There were a few pecularities in 1.0.0 and earlier:
(1) Due to the implementation with dbus-glib, a property-changed
signal was emitted on *all* interfaces. For example:
- a change on a NMDeviceVeth of "NMDeviceEthernet.HwAddress" would be
emitted both for the interfaces "fdo.NM.Device.Ethernet" and
"fdo.NM.Device.Veth". Note that NMDeviceVeth is derived from
NMDeviceEthernet and there is no "HwAddress" on veth device.
- a change of "NMVpnConnection.VpnState" was emitted on both
interfaces "fdo.NM.VPN.Connection" and "fdo.NM.Connecion.Active".
Note that NMActiveConnection is the parent type of NMVpnConnection and
only the latter has a property "VpnState".
(2) NMDevice's "fdo.NM.Device" interface doesn't have a "PropertiesChanged"
signal. From (1) follows that all property-changes for this type were instead
invoked with an interface like "fdo.NM.Device.Ethernet" (or multiple
interfaces in case of NMDeviceVeth).
1.2.0 introduced gdbus, which gives us the standard "fdo.DBus.Properties"
signal. However, it made the mistake of not realizing (1), thus instead
of emitting the signal once for each interface, it would pick the first
one in the inheritance tree.
With 1.4.0, a bug from merge commit 844345e caused signals for devices
to be only emitted for the interface "fdo.NM.Device.Statistics", instead
of "fdo.NM.Device.Ethernet" or "fdo.NM.Device.Veth" (or both).
The latter is what bgo#770629 is about and what commit 82e9439 tried to fix.
However, the fix was wrong because it tried to do the theoretically correct
thing of emitting the property-changed signal exactly once for the
interface that actually ontains the property. In addition, it missed that
NMDevice doesn't have a PropertiesChanged signal, which caused signals for
"fdo.NM.Device" to get lost *sigh*.
Now, restore the (broken) behavior of 1.0.0. These old-style property changed
signals are anyway considered deprecated and exist solely to satisfy old clients
and preserve the old API.
Fixes: 63fbfad3705db5901e6a2a6a2fc332da0f0ae4be
https://bugzilla.gnome.org/show_bug.cgi?id=770629
https://bugzilla.redhat.com/show_bug.cgi?id=1371920
2016-09-01 13:00:21 +02:00
|
|
|
|
2015-11-04 14:44:29 +01:00
|
|
|
#if NM_MORE_ASSERTS >= 2
|
|
|
|
|
#define _ASSERT_NO_EARLY_EXPORT
|
|
|
|
|
#endif
|
|
|
|
|
|
2017-01-24 18:50:38 +01:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2016-03-30 16:59:12 +02:00
|
|
|
static gboolean quitting = FALSE;
|
|
|
|
|
|
2017-01-24 18:50:38 +01:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
NM_GOBJECT_PROPERTIES_DEFINE (NMExportedObject,
|
|
|
|
|
PROP_PATH,
|
|
|
|
|
);
|
|
|
|
|
|
2016-03-30 12:28:28 +02:00
|
|
|
typedef struct {
|
|
|
|
|
GDBusInterfaceSkeleton *interface;
|
2016-03-30 12:36:37 +02:00
|
|
|
guint property_changed_signal_id;
|
2016-08-31 11:21:08 +02:00
|
|
|
GHashTable *pending_notifies;
|
2016-03-30 12:28:28 +02:00
|
|
|
} InterfaceData;
|
|
|
|
|
|
2016-09-28 15:58:24 +02:00
|
|
|
typedef struct _NMExportedObjectPrivate {
|
2015-09-15 11:32:43 +02:00
|
|
|
NMBusManager *bus_mgr;
|
2015-04-03 10:08:52 -04:00
|
|
|
char *path;
|
|
|
|
|
|
2016-03-30 12:28:28 +02:00
|
|
|
InterfaceData *interfaces;
|
|
|
|
|
guint num_interfaces;
|
2016-03-30 12:00:58 +02:00
|
|
|
|
2015-04-13 13:31:42 -04:00
|
|
|
guint notify_idle_id;
|
2015-11-04 14:44:29 +01:00
|
|
|
|
|
|
|
|
#ifdef _ASSERT_NO_EARLY_EXPORT
|
2016-03-30 12:00:58 +02:00
|
|
|
bool _constructed:1;
|
2015-11-04 14:44:29 +01:00
|
|
|
#endif
|
2015-04-13 13:31:42 -04:00
|
|
|
} NMExportedObjectPrivate;
|
|
|
|
|
|
2016-09-28 15:58:24 +02:00
|
|
|
G_DEFINE_ABSTRACT_TYPE (NMExportedObject, nm_exported_object, G_TYPE_DBUS_OBJECT_SKELETON);
|
|
|
|
|
|
|
|
|
|
#define NM_EXPORTED_OBJECT_GET_PRIVATE(self) _NM_GET_PRIVATE_PTR (self, NMExportedObject, NM_IS_EXPORTED_OBJECT)
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
2015-04-13 13:31:42 -04:00
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
GHashTable *properties;
|
2015-04-15 14:53:30 -04:00
|
|
|
GSList *skeleton_types;
|
|
|
|
|
GArray *methods;
|
2015-04-13 13:31:42 -04:00
|
|
|
} NMExportedObjectClassInfo;
|
|
|
|
|
|
2017-02-02 21:47:03 +01:00
|
|
|
static NM_CACHED_QUARK_FCN ("NMExportedObjectClassInfo", nm_exported_object_class_info_quark)
|
2015-04-13 13:31:42 -04:00
|
|
|
|
2015-07-20 17:30:02 -05:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2016-10-14 15:32:56 +02:00
|
|
|
#define _NMLOG_DOMAIN LOGD_CORE
|
|
|
|
|
#define _NMLOG(level, ...) __NMLOG_DEFAULT_WITH_ADDR (level, _NMLOG_DOMAIN, "exported-object", __VA_ARGS__)
|
|
|
|
|
|
|
|
|
|
#define _NMLOG2_DOMAIN LOGD_DBUS_PROPS
|
|
|
|
|
#define _NMLOG2(level, ...) __NMLOG_DEFAULT_WITH_ADDR (level, _NMLOG2_DOMAIN, "properties-changed", __VA_ARGS__)
|
2016-09-01 15:09:01 +02:00
|
|
|
|
2015-07-20 17:30:02 -05:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2015-04-15 14:53:30 -04:00
|
|
|
/* "AddConnectionUnsaved" -> "handle-add-connection-unsaved" */
|
2015-11-04 17:29:46 +01:00
|
|
|
char *
|
|
|
|
|
nm_exported_object_skeletonify_method_name (const char *dbus_method_name)
|
2015-04-15 14:53:30 -04:00
|
|
|
{
|
|
|
|
|
GString *out;
|
|
|
|
|
const char *p;
|
|
|
|
|
|
|
|
|
|
out = g_string_new ("handle");
|
|
|
|
|
for (p = dbus_method_name; *p; p++) {
|
|
|
|
|
if (g_ascii_isupper (*p) || p == dbus_method_name) {
|
|
|
|
|
g_string_append_c (out, '-');
|
|
|
|
|
g_string_append_c (out, g_ascii_tolower (*p));
|
|
|
|
|
} else
|
|
|
|
|
g_string_append_c (out, *p);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return g_string_free (out, FALSE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* "can-modify" -> "CanModify" */
|
|
|
|
|
static char *
|
|
|
|
|
dbusify_name (const char *gobject_name)
|
|
|
|
|
{
|
|
|
|
|
GString *out;
|
|
|
|
|
const char *p;
|
|
|
|
|
gboolean capitalize = TRUE;
|
|
|
|
|
|
|
|
|
|
out = g_string_new ("");
|
|
|
|
|
for (p = gobject_name; *p; p++) {
|
|
|
|
|
if (capitalize) {
|
|
|
|
|
g_string_append_c (out, g_ascii_toupper (*p));
|
|
|
|
|
capitalize = FALSE;
|
|
|
|
|
} else if (*p == '-')
|
|
|
|
|
capitalize = TRUE;
|
|
|
|
|
else
|
|
|
|
|
g_string_append_c (out, *p);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return g_string_free (out, FALSE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* "can_modify" -> "can-modify". Returns %NULL if @gobject_name contains no underscores */
|
|
|
|
|
static char *
|
|
|
|
|
hyphenify_name (const char *gobject_name)
|
|
|
|
|
{
|
|
|
|
|
char *hyphen_name, *p;
|
|
|
|
|
|
|
|
|
|
if (!strchr (gobject_name, '_'))
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
hyphen_name = g_strdup (gobject_name);
|
|
|
|
|
for (p = hyphen_name; *p; p++) {
|
|
|
|
|
if (*p == '_')
|
|
|
|
|
*p = '-';
|
|
|
|
|
}
|
|
|
|
|
return hyphen_name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Called when an #NMExportedObject emits a signal that corresponds to a D-Bus
|
|
|
|
|
* signal, and re-emits that signal on the correct skeleton object as well.
|
|
|
|
|
*/
|
|
|
|
|
static gboolean
|
|
|
|
|
nm_exported_object_signal_hook (GSignalInvocationHint *ihint,
|
|
|
|
|
guint n_param_values,
|
|
|
|
|
const GValue *param_values,
|
|
|
|
|
gpointer data)
|
|
|
|
|
{
|
|
|
|
|
NMExportedObject *self = g_value_get_object (¶m_values[0]);
|
|
|
|
|
NMExportedObjectPrivate *priv;
|
|
|
|
|
GSignalQuery *signal_info = data;
|
2015-09-17 16:57:22 +02:00
|
|
|
GDBusInterfaceSkeleton *interface = NULL;
|
2015-04-15 14:53:30 -04:00
|
|
|
GValue *dbus_param_values;
|
2016-03-30 12:28:28 +02:00
|
|
|
guint i;
|
2015-04-15 14:53:30 -04:00
|
|
|
|
|
|
|
|
priv = NM_EXPORTED_OBJECT_GET_PRIVATE (self);
|
|
|
|
|
if (!priv->path)
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
2016-03-30 12:28:28 +02:00
|
|
|
for (i = 0; i < priv->num_interfaces; i++) {
|
|
|
|
|
InterfaceData *ifdata = &priv->interfaces[i];
|
|
|
|
|
|
|
|
|
|
if (g_type_is_a (G_OBJECT_TYPE (ifdata->interface), signal_info->itype)) {
|
|
|
|
|
interface = ifdata->interface;
|
2015-04-15 14:53:30 -04:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
g_return_val_if_fail (interface != NULL, TRUE);
|
|
|
|
|
|
2016-03-30 13:20:44 +02:00
|
|
|
dbus_param_values = g_newa (GValue, n_param_values);
|
|
|
|
|
memset (dbus_param_values, 0, sizeof (GValue) * n_param_values);
|
2015-04-15 14:53:30 -04:00
|
|
|
g_value_init (&dbus_param_values[0], G_OBJECT_TYPE (interface));
|
|
|
|
|
g_value_set_object (&dbus_param_values[0], interface);
|
|
|
|
|
for (i = 1; i < n_param_values; i++) {
|
|
|
|
|
if (g_type_is_a (param_values[i].g_type, NM_TYPE_EXPORTED_OBJECT)) {
|
|
|
|
|
NMExportedObject *arg = g_value_get_object (¶m_values[i]);
|
|
|
|
|
|
|
|
|
|
g_value_init (&dbus_param_values[i], G_TYPE_STRING);
|
|
|
|
|
if (arg && nm_exported_object_is_exported (arg))
|
|
|
|
|
g_value_set_string (&dbus_param_values[i], nm_exported_object_get_path (arg));
|
|
|
|
|
else
|
|
|
|
|
g_value_set_string (&dbus_param_values[i], "/");
|
|
|
|
|
} else {
|
|
|
|
|
g_value_init (&dbus_param_values[i], param_values[i].g_type);
|
|
|
|
|
g_value_copy (¶m_values[i], &dbus_param_values[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_signal_emitv (dbus_param_values, signal_info->signal_id, 0, NULL);
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < n_param_values; i++)
|
|
|
|
|
g_value_unset (&dbus_param_values[i]);
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-13 13:31:42 -04:00
|
|
|
/**
|
|
|
|
|
* nm_exported_object_class_add_interface:
|
|
|
|
|
* @object_class: an #NMExportedObjectClass
|
2015-09-17 16:57:22 +02:00
|
|
|
* @dbus_skeleton_type: the type of the #GDBusInterfaceSkeleton to add
|
2015-04-15 14:53:30 -04:00
|
|
|
* @...: method name / handler pairs, %NULL-terminated
|
|
|
|
|
*
|
|
|
|
|
* Adds @dbus_skeleton_type to the list of D-Bus interfaces implemented by
|
|
|
|
|
* @object_class. Instances of @object_class will automatically have a skeleton
|
|
|
|
|
* of that type created, which will be exported when you call
|
|
|
|
|
* nm_exported_object_export().
|
|
|
|
|
*
|
|
|
|
|
* The skeleton's properties will be initialized from the #NMExportedObject's,
|
|
|
|
|
* and bidirectional bindings will be set up between them. When exported
|
|
|
|
|
* properties change, both the org.freedesktop.DBus.Properties.PropertiesChanged
|
|
|
|
|
* signal and the traditional NetworkManager PropertiesChanged signal will be
|
|
|
|
|
* emitted.
|
|
|
|
|
*
|
|
|
|
|
* When a signal is emitted on an #NMExportedObject that has the same name as a
|
|
|
|
|
* signal on @dbus_skeleton_type, it will automatically be emitted on the
|
|
|
|
|
* skeleton as well; #NMExportedObject arguments in the signal will be converted
|
|
|
|
|
* to D-Bus object paths in the skeleton signal.
|
2015-04-13 13:31:42 -04:00
|
|
|
*
|
2015-04-15 14:53:30 -04:00
|
|
|
* The arguments after @dbus_skeleton_type are pairs of D-Bus method names (in
|
|
|
|
|
* CamelCase), and the corresponding handlers for them (which must have the same
|
|
|
|
|
* prototype as the corresponding "handle-..." signal on @dbus_skeleton_type,
|
|
|
|
|
* except with no return value, and with the first argument being an object of
|
|
|
|
|
* @object_class's type, not of @dbus_skeleton_type).
|
2015-04-13 13:31:42 -04:00
|
|
|
*
|
2015-04-15 14:53:30 -04:00
|
|
|
* It is a programmer error if:
|
|
|
|
|
* - @object_class does not define a property of the same name and type as
|
|
|
|
|
* each of @dbus_skeleton_type's properties.
|
|
|
|
|
* - @object_class does not define a signal with the same name and arguments
|
|
|
|
|
* as each of @dbus_skeleton_type's signals.
|
|
|
|
|
* - the list of method names includes any names that do not correspond to
|
|
|
|
|
* "handle-" signals on @dbus_skeleton_type.
|
|
|
|
|
* - the list of method names does not include every method defined by
|
|
|
|
|
* @dbus_skeleton_type.
|
2015-04-13 13:31:42 -04:00
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
nm_exported_object_class_add_interface (NMExportedObjectClass *object_class,
|
2015-04-15 14:53:30 -04:00
|
|
|
GType dbus_skeleton_type,
|
|
|
|
|
...)
|
2015-04-13 13:31:42 -04:00
|
|
|
{
|
|
|
|
|
NMExportedObjectClassInfo *classinfo;
|
2015-04-15 14:53:30 -04:00
|
|
|
NMExportedObjectDBusMethodImpl method;
|
|
|
|
|
va_list ap;
|
|
|
|
|
const char *method_name;
|
|
|
|
|
GCallback impl;
|
2015-08-12 11:06:47 +02:00
|
|
|
gs_free GType *interfaces = NULL;
|
2015-04-15 14:53:30 -04:00
|
|
|
guint n_interfaces;
|
2015-08-12 11:06:47 +02:00
|
|
|
guint n_signals, n_method_signals;
|
2015-04-15 14:53:30 -04:00
|
|
|
guint object_signal_id;
|
|
|
|
|
GSignalQuery query;
|
|
|
|
|
int i, s;
|
|
|
|
|
GObjectClass *dbus_object_class;
|
2015-08-12 11:06:47 +02:00
|
|
|
gs_free GParamSpec **dbus_properties = NULL;
|
|
|
|
|
GParamSpec *object_property;
|
2015-04-15 14:53:30 -04:00
|
|
|
guint n_dbus_properties;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (NM_IS_EXPORTED_OBJECT_CLASS (object_class));
|
|
|
|
|
g_return_if_fail (g_type_is_a (dbus_skeleton_type, G_TYPE_DBUS_INTERFACE_SKELETON));
|
|
|
|
|
|
2016-08-10 11:54:29 +02:00
|
|
|
classinfo = g_type_get_qdata (G_TYPE_FROM_CLASS (object_class),
|
|
|
|
|
nm_exported_object_class_info_quark ());
|
|
|
|
|
if (!classinfo) {
|
|
|
|
|
classinfo = g_slice_new (NMExportedObjectClassInfo);
|
|
|
|
|
classinfo->skeleton_types = NULL;
|
|
|
|
|
classinfo->methods = g_array_new (FALSE, FALSE, sizeof (NMExportedObjectDBusMethodImpl));
|
2017-10-13 16:12:35 +02:00
|
|
|
classinfo->properties = g_hash_table_new (nm_str_hash, g_str_equal);
|
2016-08-10 11:54:29 +02:00
|
|
|
g_type_set_qdata (G_TYPE_FROM_CLASS (object_class),
|
|
|
|
|
nm_exported_object_class_info_quark (), classinfo);
|
|
|
|
|
}
|
2015-04-15 14:53:30 -04:00
|
|
|
|
dbus: fix emitting D-Bus NetworkManager's old-style PropertiesChange signal
Before switching to gdbus (before 1.2.0), NetworkManager used dbus-glib.
Most objects in the D-Bus API with properties had a signal
NetworkManager-specific "PropertiesChanged" signal. Nowadays, this way of
handling of property changes is deprecated for the common "PropertiesChanged"
signal on the "org.freedesktop.DBus.Properties" interface.
There were a few pecularities in 1.0.0 and earlier:
(1) Due to the implementation with dbus-glib, a property-changed
signal was emitted on *all* interfaces. For example:
- a change on a NMDeviceVeth of "NMDeviceEthernet.HwAddress" would be
emitted both for the interfaces "fdo.NM.Device.Ethernet" and
"fdo.NM.Device.Veth". Note that NMDeviceVeth is derived from
NMDeviceEthernet and there is no "HwAddress" on veth device.
- a change of "NMVpnConnection.VpnState" was emitted on both
interfaces "fdo.NM.VPN.Connection" and "fdo.NM.Connecion.Active".
Note that NMActiveConnection is the parent type of NMVpnConnection and
only the latter has a property "VpnState".
(2) NMDevice's "fdo.NM.Device" interface doesn't have a "PropertiesChanged"
signal. From (1) follows that all property-changes for this type were instead
invoked with an interface like "fdo.NM.Device.Ethernet" (or multiple
interfaces in case of NMDeviceVeth).
1.2.0 introduced gdbus, which gives us the standard "fdo.DBus.Properties"
signal. However, it made the mistake of not realizing (1), thus instead
of emitting the signal once for each interface, it would pick the first
one in the inheritance tree.
With 1.4.0, a bug from merge commit 844345e caused signals for devices
to be only emitted for the interface "fdo.NM.Device.Statistics", instead
of "fdo.NM.Device.Ethernet" or "fdo.NM.Device.Veth" (or both).
The latter is what bgo#770629 is about and what commit 82e9439 tried to fix.
However, the fix was wrong because it tried to do the theoretically correct
thing of emitting the property-changed signal exactly once for the
interface that actually ontains the property. In addition, it missed that
NMDevice doesn't have a PropertiesChanged signal, which caused signals for
"fdo.NM.Device" to get lost *sigh*.
Now, restore the (broken) behavior of 1.0.0. These old-style property changed
signals are anyway considered deprecated and exist solely to satisfy old clients
and preserve the old API.
Fixes: 63fbfad3705db5901e6a2a6a2fc332da0f0ae4be
https://bugzilla.gnome.org/show_bug.cgi?id=770629
https://bugzilla.redhat.com/show_bug.cgi?id=1371920
2016-09-01 13:00:21 +02:00
|
|
|
classinfo->skeleton_types = g_slist_prepend (classinfo->skeleton_types,
|
|
|
|
|
GSIZE_TO_POINTER (dbus_skeleton_type));
|
2015-04-15 14:53:30 -04:00
|
|
|
|
|
|
|
|
/* Ensure @dbus_skeleton_type's class_init has run, so its signals/properties
|
|
|
|
|
* will be defined.
|
|
|
|
|
*/
|
|
|
|
|
dbus_object_class = g_type_class_ref (dbus_skeleton_type);
|
|
|
|
|
|
|
|
|
|
/* Add method implementations from the varargs */
|
|
|
|
|
va_start (ap, dbus_skeleton_type);
|
|
|
|
|
while ((method_name = va_arg (ap, const char *)) && (impl = va_arg (ap, GCallback))) {
|
|
|
|
|
method.dbus_skeleton_type = dbus_skeleton_type;
|
2015-11-04 17:29:46 +01:00
|
|
|
method.method_name = nm_exported_object_skeletonify_method_name (method_name);
|
2015-04-15 14:53:30 -04:00
|
|
|
g_assert (g_signal_lookup (method.method_name, dbus_skeleton_type) != 0);
|
|
|
|
|
method.impl = impl;
|
|
|
|
|
|
|
|
|
|
g_array_append_val (classinfo->methods, method);
|
|
|
|
|
}
|
|
|
|
|
va_end (ap);
|
2015-04-13 13:31:42 -04:00
|
|
|
|
2015-04-15 14:53:30 -04:00
|
|
|
/* Properties */
|
|
|
|
|
dbus_properties = g_object_class_list_properties (dbus_object_class, &n_dbus_properties);
|
|
|
|
|
for (i = 0; i < n_dbus_properties; i++) {
|
|
|
|
|
char *hyphen_name;
|
2015-04-13 13:31:42 -04:00
|
|
|
|
2015-04-15 14:53:30 -04:00
|
|
|
if (g_str_has_prefix (dbus_properties[i]->name, "g-"))
|
|
|
|
|
continue;
|
2015-04-13 13:31:42 -04:00
|
|
|
|
2015-04-15 14:53:30 -04:00
|
|
|
object_property = g_object_class_find_property (G_OBJECT_CLASS (object_class),
|
|
|
|
|
dbus_properties[i]->name);
|
|
|
|
|
g_assert (object_property != NULL);
|
|
|
|
|
g_assert (object_property->value_type == dbus_properties[i]->value_type);
|
|
|
|
|
|
|
|
|
|
g_assert (!g_hash_table_contains (classinfo->properties, dbus_properties[i]->name));
|
|
|
|
|
g_hash_table_insert (classinfo->properties,
|
|
|
|
|
g_strdup (dbus_properties[i]->name),
|
|
|
|
|
dbusify_name (dbus_properties[i]->name));
|
|
|
|
|
hyphen_name = hyphenify_name (dbus_properties[i]->name);
|
|
|
|
|
if (hyphen_name) {
|
2015-04-13 13:31:42 -04:00
|
|
|
g_assert (!g_hash_table_contains (classinfo->properties, hyphen_name));
|
|
|
|
|
g_hash_table_insert (classinfo->properties,
|
2015-04-15 14:53:30 -04:00
|
|
|
hyphen_name,
|
|
|
|
|
dbusify_name (dbus_properties[i]->name));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Signals. Unlike g_object_class_list_properties(), g_signal_list_ids() is
|
|
|
|
|
* "shallow", so we need to query each implemented gdbus-generated interface
|
|
|
|
|
* separately.
|
|
|
|
|
*/
|
|
|
|
|
interfaces = g_type_interfaces (dbus_skeleton_type, &n_interfaces);
|
|
|
|
|
n_method_signals = 0;
|
|
|
|
|
for (i = 0; i < n_interfaces; i++) {
|
2015-08-12 11:06:47 +02:00
|
|
|
gs_free guint *dbus_signals = NULL;
|
|
|
|
|
|
2015-04-15 14:53:30 -04:00
|
|
|
dbus_signals = g_signal_list_ids (interfaces[i], &n_signals);
|
|
|
|
|
for (s = 0; s < n_signals; s++) {
|
|
|
|
|
g_signal_query (dbus_signals[s], &query);
|
|
|
|
|
|
|
|
|
|
/* PropertiesChanged is handled specially */
|
|
|
|
|
if (!strcmp (query.signal_name, "properties-changed"))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (g_str_has_prefix (query.signal_name, "handle-")) {
|
|
|
|
|
n_method_signals++;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
object_signal_id = g_signal_lookup (query.signal_name, G_TYPE_FROM_CLASS (object_class));
|
|
|
|
|
g_assert (object_signal_id != 0);
|
|
|
|
|
|
|
|
|
|
g_signal_add_emission_hook (object_signal_id, 0,
|
|
|
|
|
nm_exported_object_signal_hook,
|
|
|
|
|
g_memdup (&query, sizeof (query)),
|
|
|
|
|
g_free);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_type_class_unref (dbus_object_class);
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-30 16:58:02 +02:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2015-04-15 14:53:30 -04:00
|
|
|
/* "meta-marshaller" that receives the skeleton "handle-foo" signal, replaces
|
|
|
|
|
* the skeleton object with an #NMExportedObject in the parameters, drops the
|
|
|
|
|
* user_data parameter, and adds a "TRUE" return value (indicating to gdbus that
|
|
|
|
|
* the signal was handled).
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
nm_exported_object_meta_marshal (GClosure *closure, GValue *return_value,
|
|
|
|
|
guint n_param_values, const GValue *param_values,
|
|
|
|
|
gpointer invocation_hint, gpointer marshal_data)
|
|
|
|
|
{
|
|
|
|
|
GValue *local_param_values;
|
|
|
|
|
|
|
|
|
|
local_param_values = g_new0 (GValue, n_param_values);
|
|
|
|
|
g_value_init (&local_param_values[0], G_TYPE_POINTER);
|
|
|
|
|
g_value_set_pointer (&local_param_values[0], closure->data);
|
|
|
|
|
memcpy (local_param_values + 1, param_values + 1, (n_param_values - 1) * sizeof (GValue));
|
|
|
|
|
|
|
|
|
|
g_cclosure_marshal_generic (closure, NULL,
|
|
|
|
|
n_param_values, local_param_values,
|
|
|
|
|
invocation_hint,
|
|
|
|
|
((GCClosure *)closure)->callback);
|
|
|
|
|
g_value_set_boolean (return_value, TRUE);
|
|
|
|
|
|
|
|
|
|
g_value_unset (&local_param_values[0]);
|
|
|
|
|
g_free (local_param_values);
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-02 21:47:03 +01:00
|
|
|
static NM_CACHED_QUARK_FCN ("skeleton-data", _skeleton_data_quark)
|
2015-09-17 17:13:30 +02:00
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
GBinding **prop_bindings;
|
|
|
|
|
gulong *method_signals;
|
|
|
|
|
} SkeletonData;
|
|
|
|
|
|
2015-11-04 17:29:46 +01:00
|
|
|
GDBusInterfaceSkeleton *
|
|
|
|
|
nm_exported_object_skeleton_create (GType dbus_skeleton_type,
|
|
|
|
|
GObjectClass *object_class,
|
|
|
|
|
const NMExportedObjectDBusMethodImpl *methods,
|
|
|
|
|
guint methods_len,
|
|
|
|
|
GObject *target)
|
|
|
|
|
{
|
|
|
|
|
GDBusInterfaceSkeleton *interface;
|
|
|
|
|
gs_free GParamSpec **properties = NULL;
|
|
|
|
|
SkeletonData *skeleton_data;
|
|
|
|
|
guint n_properties;
|
|
|
|
|
guint i, j;
|
|
|
|
|
|
|
|
|
|
interface = G_DBUS_INTERFACE_SKELETON (g_object_new (dbus_skeleton_type, NULL));
|
|
|
|
|
|
|
|
|
|
skeleton_data = g_slice_new (SkeletonData);
|
|
|
|
|
|
|
|
|
|
/* Bind properties */
|
|
|
|
|
properties = g_object_class_list_properties (G_OBJECT_GET_CLASS (interface), &n_properties);
|
|
|
|
|
skeleton_data->prop_bindings = g_new (GBinding *, n_properties + 1);
|
|
|
|
|
for (i = 0, j = 0; i < n_properties; i++) {
|
|
|
|
|
GParamSpec *nm_property;
|
|
|
|
|
GBindingFlags flags;
|
|
|
|
|
GBinding *prop_binding;
|
|
|
|
|
|
|
|
|
|
nm_property = g_object_class_find_property (object_class, properties[i]->name);
|
|
|
|
|
if (!nm_property)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
flags = G_BINDING_SYNC_CREATE;
|
|
|
|
|
if ( (nm_property->flags & G_PARAM_WRITABLE)
|
|
|
|
|
&& !(nm_property->flags & G_PARAM_CONSTRUCT_ONLY))
|
|
|
|
|
flags |= G_BINDING_BIDIRECTIONAL;
|
|
|
|
|
prop_binding = g_object_bind_property (target, properties[i]->name,
|
|
|
|
|
interface, properties[i]->name,
|
|
|
|
|
flags);
|
|
|
|
|
if (prop_binding)
|
|
|
|
|
skeleton_data->prop_bindings[j++] = prop_binding;
|
|
|
|
|
}
|
|
|
|
|
skeleton_data->prop_bindings[j++] = NULL;
|
|
|
|
|
|
|
|
|
|
/* Bind methods */
|
|
|
|
|
skeleton_data->method_signals = g_new (gulong, methods_len + 1);
|
|
|
|
|
for (i = 0, j = 0; i < methods_len; i++) {
|
|
|
|
|
const NMExportedObjectDBusMethodImpl *method = &methods[i];
|
|
|
|
|
GClosure *closure;
|
|
|
|
|
gulong method_signal;
|
|
|
|
|
|
|
|
|
|
/* ignore methods that are for a different skeleton-type. */
|
|
|
|
|
if ( method->dbus_skeleton_type
|
|
|
|
|
&& method->dbus_skeleton_type != dbus_skeleton_type)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
closure = g_cclosure_new_swap (method->impl, target, NULL);
|
|
|
|
|
g_closure_set_meta_marshal (closure, NULL, nm_exported_object_meta_marshal);
|
|
|
|
|
method_signal = g_signal_connect_closure (interface, method->method_name, closure, FALSE);
|
|
|
|
|
|
|
|
|
|
if (method_signal != 0)
|
|
|
|
|
skeleton_data->method_signals[j++] = method_signal;
|
|
|
|
|
}
|
|
|
|
|
skeleton_data->method_signals[j++] = 0;
|
|
|
|
|
|
|
|
|
|
g_object_set_qdata ((GObject *) interface, _skeleton_data_quark (), skeleton_data);
|
|
|
|
|
|
|
|
|
|
return interface;
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-15 14:53:30 -04:00
|
|
|
static void
|
|
|
|
|
nm_exported_object_create_skeletons (NMExportedObject *self,
|
|
|
|
|
GType object_type)
|
|
|
|
|
{
|
2015-11-04 17:29:46 +01:00
|
|
|
NMExportedObjectPrivate *priv;
|
|
|
|
|
GObjectClass *object_class;
|
2015-04-15 14:53:30 -04:00
|
|
|
NMExportedObjectClassInfo *classinfo;
|
|
|
|
|
GSList *iter;
|
2015-11-04 17:29:46 +01:00
|
|
|
const NMExportedObjectDBusMethodImpl *methods;
|
2016-03-30 12:28:28 +02:00
|
|
|
guint i, methods_len;
|
|
|
|
|
guint num_interfaces;
|
|
|
|
|
InterfaceData *interfaces;
|
2015-04-15 14:53:30 -04:00
|
|
|
|
|
|
|
|
classinfo = g_type_get_qdata (object_type, nm_exported_object_class_info_quark ());
|
|
|
|
|
if (!classinfo)
|
|
|
|
|
return;
|
|
|
|
|
|
2015-11-04 17:29:46 +01:00
|
|
|
object_class = g_type_class_peek (object_type);
|
|
|
|
|
priv = NM_EXPORTED_OBJECT_GET_PRIVATE (self);
|
2015-04-15 14:53:30 -04:00
|
|
|
|
2015-11-04 17:29:46 +01:00
|
|
|
methods = classinfo->methods->len ? &g_array_index (classinfo->methods, NMExportedObjectDBusMethodImpl, 0) : NULL;
|
|
|
|
|
methods_len = classinfo->methods->len;
|
2015-09-17 17:13:30 +02:00
|
|
|
|
2016-03-30 12:28:28 +02:00
|
|
|
num_interfaces = g_slist_length (classinfo->skeleton_types);
|
|
|
|
|
g_return_if_fail (num_interfaces > 0);
|
|
|
|
|
|
|
|
|
|
interfaces = g_slice_alloc (sizeof (InterfaceData) * (num_interfaces + priv->num_interfaces));
|
2015-04-15 14:53:30 -04:00
|
|
|
|
2016-03-30 12:28:28 +02:00
|
|
|
for (i = num_interfaces, iter = classinfo->skeleton_types; iter; iter = iter->next) {
|
|
|
|
|
InterfaceData *ifdata = &interfaces[--i];
|
2015-07-20 17:30:02 -05:00
|
|
|
|
2016-03-30 12:28:28 +02:00
|
|
|
ifdata->interface = nm_exported_object_skeleton_create (GPOINTER_TO_SIZE (iter->data),
|
|
|
|
|
object_class,
|
|
|
|
|
methods,
|
|
|
|
|
methods_len,
|
|
|
|
|
(GObject *) self);
|
|
|
|
|
g_dbus_object_skeleton_add_interface ((GDBusObjectSkeleton *) self, ifdata->interface);
|
2016-03-30 12:36:37 +02:00
|
|
|
|
|
|
|
|
ifdata->property_changed_signal_id = g_signal_lookup ("properties-changed", G_OBJECT_TYPE (ifdata->interface));
|
2016-08-31 11:21:08 +02:00
|
|
|
|
|
|
|
|
ifdata->pending_notifies = g_hash_table_new_full (g_direct_hash,
|
|
|
|
|
g_direct_equal,
|
|
|
|
|
NULL,
|
|
|
|
|
(GDestroyNotify) g_variant_unref);
|
2015-11-04 17:29:46 +01:00
|
|
|
}
|
2016-03-30 12:28:28 +02:00
|
|
|
nm_assert (i == 0);
|
|
|
|
|
|
dbus: fix emitting D-Bus NetworkManager's old-style PropertiesChange signal
Before switching to gdbus (before 1.2.0), NetworkManager used dbus-glib.
Most objects in the D-Bus API with properties had a signal
NetworkManager-specific "PropertiesChanged" signal. Nowadays, this way of
handling of property changes is deprecated for the common "PropertiesChanged"
signal on the "org.freedesktop.DBus.Properties" interface.
There were a few pecularities in 1.0.0 and earlier:
(1) Due to the implementation with dbus-glib, a property-changed
signal was emitted on *all* interfaces. For example:
- a change on a NMDeviceVeth of "NMDeviceEthernet.HwAddress" would be
emitted both for the interfaces "fdo.NM.Device.Ethernet" and
"fdo.NM.Device.Veth". Note that NMDeviceVeth is derived from
NMDeviceEthernet and there is no "HwAddress" on veth device.
- a change of "NMVpnConnection.VpnState" was emitted on both
interfaces "fdo.NM.VPN.Connection" and "fdo.NM.Connecion.Active".
Note that NMActiveConnection is the parent type of NMVpnConnection and
only the latter has a property "VpnState".
(2) NMDevice's "fdo.NM.Device" interface doesn't have a "PropertiesChanged"
signal. From (1) follows that all property-changes for this type were instead
invoked with an interface like "fdo.NM.Device.Ethernet" (or multiple
interfaces in case of NMDeviceVeth).
1.2.0 introduced gdbus, which gives us the standard "fdo.DBus.Properties"
signal. However, it made the mistake of not realizing (1), thus instead
of emitting the signal once for each interface, it would pick the first
one in the inheritance tree.
With 1.4.0, a bug from merge commit 844345e caused signals for devices
to be only emitted for the interface "fdo.NM.Device.Statistics", instead
of "fdo.NM.Device.Ethernet" or "fdo.NM.Device.Veth" (or both).
The latter is what bgo#770629 is about and what commit 82e9439 tried to fix.
However, the fix was wrong because it tried to do the theoretically correct
thing of emitting the property-changed signal exactly once for the
interface that actually ontains the property. In addition, it missed that
NMDevice doesn't have a PropertiesChanged signal, which caused signals for
"fdo.NM.Device" to get lost *sigh*.
Now, restore the (broken) behavior of 1.0.0. These old-style property changed
signals are anyway considered deprecated and exist solely to satisfy old clients
and preserve the old API.
Fixes: 63fbfad3705db5901e6a2a6a2fc332da0f0ae4be
https://bugzilla.gnome.org/show_bug.cgi?id=770629
https://bugzilla.redhat.com/show_bug.cgi?id=1371920
2016-09-01 13:00:21 +02:00
|
|
|
/* The list of interfaces priv->interfaces is to be sorted from parent-class to derived-class.
|
|
|
|
|
* On the other hand, if one class defines multiple interfaces, the interfaces are sorted in
|
|
|
|
|
* the order of calls to nm_exported_object_class_add_interface(). */
|
2016-03-30 12:28:28 +02:00
|
|
|
if (priv->num_interfaces > 0) {
|
|
|
|
|
memcpy (&interfaces[num_interfaces], priv->interfaces, sizeof (InterfaceData) * priv->num_interfaces);
|
|
|
|
|
g_slice_free1 (sizeof (InterfaceData) * priv->num_interfaces, priv->interfaces);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
priv->num_interfaces = num_interfaces + priv->num_interfaces;
|
|
|
|
|
priv->interfaces = interfaces;
|
2015-11-04 17:29:46 +01:00
|
|
|
}
|
2015-04-15 14:53:30 -04:00
|
|
|
|
2015-11-04 17:29:46 +01:00
|
|
|
void
|
|
|
|
|
nm_exported_object_skeleton_release (GDBusInterfaceSkeleton *interface)
|
|
|
|
|
{
|
|
|
|
|
SkeletonData *skeleton_data;
|
|
|
|
|
guint j;
|
2015-04-15 14:53:30 -04:00
|
|
|
|
2015-11-04 17:29:46 +01:00
|
|
|
g_return_if_fail (G_IS_DBUS_INTERFACE_SKELETON (interface));
|
2015-04-15 14:53:30 -04:00
|
|
|
|
2015-11-04 17:29:46 +01:00
|
|
|
skeleton_data = g_object_steal_qdata ((GObject *) interface, _skeleton_data_quark ());
|
2015-04-15 14:53:30 -04:00
|
|
|
|
2015-11-04 17:29:46 +01:00
|
|
|
for (j = 0; skeleton_data->prop_bindings[j]; j++)
|
|
|
|
|
g_object_unref (skeleton_data->prop_bindings[j]);
|
|
|
|
|
for (j = 0; skeleton_data->method_signals[j]; j++)
|
|
|
|
|
g_signal_handler_disconnect (interface, skeleton_data->method_signals[j]);
|
2015-09-17 17:13:30 +02:00
|
|
|
|
2015-11-04 17:29:46 +01:00
|
|
|
g_free (skeleton_data->prop_bindings);
|
|
|
|
|
g_free (skeleton_data->method_signals);
|
|
|
|
|
g_slice_free (SkeletonData, skeleton_data);
|
2015-09-17 17:13:30 +02:00
|
|
|
|
2015-11-04 17:29:46 +01:00
|
|
|
g_object_unref (interface);
|
2015-09-17 17:13:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
nm_exported_object_destroy_skeletons (NMExportedObject *self)
|
|
|
|
|
{
|
|
|
|
|
NMExportedObjectPrivate *priv = NM_EXPORTED_OBJECT_GET_PRIVATE (self);
|
2016-03-30 12:28:28 +02:00
|
|
|
guint n;
|
2015-09-17 17:13:30 +02:00
|
|
|
|
2016-03-30 12:28:28 +02:00
|
|
|
g_return_if_fail (priv->num_interfaces > 0);
|
|
|
|
|
nm_assert (priv->interfaces);
|
2015-09-17 17:13:30 +02:00
|
|
|
|
2016-03-30 12:28:28 +02:00
|
|
|
n = priv->num_interfaces;
|
2015-09-17 17:13:30 +02:00
|
|
|
|
2016-03-30 12:28:28 +02:00
|
|
|
while (priv->num_interfaces > 0) {
|
|
|
|
|
InterfaceData *ifdata = &priv->interfaces[--priv->num_interfaces];
|
|
|
|
|
|
|
|
|
|
g_dbus_object_skeleton_remove_interface ((GDBusObjectSkeleton *) self, ifdata->interface);
|
|
|
|
|
nm_exported_object_skeleton_release (ifdata->interface);
|
2016-08-31 11:21:08 +02:00
|
|
|
g_hash_table_destroy (ifdata->pending_notifies);
|
2015-04-13 13:31:42 -04:00
|
|
|
}
|
2016-03-30 12:28:28 +02:00
|
|
|
|
|
|
|
|
g_slice_free1 (sizeof (InterfaceData) * n, priv->interfaces);
|
|
|
|
|
priv->interfaces = NULL;
|
2015-04-13 13:31:42 -04:00
|
|
|
}
|
|
|
|
|
|
2016-03-30 16:50:38 +02:00
|
|
|
static char *
|
|
|
|
|
_create_export_path (NMExportedObjectClass *klass)
|
|
|
|
|
{
|
|
|
|
|
const char *class_export_path, *p;
|
|
|
|
|
static GHashTable *prefix_counters;
|
2017-01-03 15:28:22 +01:00
|
|
|
guint64 *counter;
|
2016-03-30 16:50:38 +02:00
|
|
|
|
|
|
|
|
class_export_path = klass->export_path;
|
|
|
|
|
|
|
|
|
|
nm_assert (class_export_path);
|
|
|
|
|
|
|
|
|
|
p = strchr (class_export_path, '%');
|
|
|
|
|
if (p) {
|
|
|
|
|
if (G_UNLIKELY (!prefix_counters))
|
2017-10-13 16:12:35 +02:00
|
|
|
prefix_counters = g_hash_table_new (nm_str_hash, g_str_equal);
|
2016-03-30 16:50:38 +02:00
|
|
|
|
2017-01-03 15:28:22 +01:00
|
|
|
nm_assert (p[1] == 'l');
|
|
|
|
|
nm_assert (p[2] == 'l');
|
|
|
|
|
nm_assert (p[3] == 'u');
|
|
|
|
|
nm_assert (p[4] == '\0');
|
2016-03-30 16:50:38 +02:00
|
|
|
|
|
|
|
|
counter = g_hash_table_lookup (prefix_counters, class_export_path);
|
|
|
|
|
if (!counter) {
|
2017-01-03 15:28:22 +01:00
|
|
|
counter = g_slice_new0 (guint64);
|
2017-01-03 15:44:06 +01:00
|
|
|
g_hash_table_insert (prefix_counters, (char *) class_export_path, counter);
|
2016-03-30 16:50:38 +02:00
|
|
|
}
|
|
|
|
|
|
2016-06-05 11:46:06 +02:00
|
|
|
NM_PRAGMA_WARNING_DISABLE("-Wformat-nonliteral")
|
2017-03-14 11:15:05 +01:00
|
|
|
return g_strdup_printf (class_export_path, (unsigned long long) (++(*counter)));
|
2016-06-05 11:46:06 +02:00
|
|
|
NM_PRAGMA_WARNING_REENABLE
|
2016-03-30 16:50:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return g_strdup (class_export_path);
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-30 16:58:02 +02:00
|
|
|
/**
|
|
|
|
|
* nm_exported_object_get_path:
|
|
|
|
|
* @self: an #NMExportedObject
|
|
|
|
|
*
|
|
|
|
|
* Gets @self's D-Bus path.
|
|
|
|
|
*
|
|
|
|
|
* Returns: @self's D-Bus path, or %NULL if @self is not exported.
|
|
|
|
|
*/
|
|
|
|
|
const char *
|
|
|
|
|
nm_exported_object_get_path (NMExportedObject *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (NM_IS_EXPORTED_OBJECT (self), NULL);
|
|
|
|
|
|
|
|
|
|
return NM_EXPORTED_OBJECT_GET_PRIVATE (self)->path;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_exported_object_is_exported:
|
|
|
|
|
* @self: an #NMExportedObject
|
|
|
|
|
*
|
|
|
|
|
* Checks if @self is exported
|
|
|
|
|
*
|
|
|
|
|
* Returns: %TRUE if @self is exported
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_exported_object_is_exported (NMExportedObject *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (NM_IS_EXPORTED_OBJECT (self), FALSE);
|
|
|
|
|
|
|
|
|
|
return NM_EXPORTED_OBJECT_GET_PRIVATE (self)->path != NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-03 10:08:52 -04:00
|
|
|
/**
|
|
|
|
|
* nm_exported_object_export:
|
|
|
|
|
* @self: an #NMExportedObject
|
|
|
|
|
*
|
|
|
|
|
* Exports @self on all active and future D-Bus connections.
|
|
|
|
|
*
|
|
|
|
|
* The path to export @self on is taken from its #NMObjectClass's %export_path
|
|
|
|
|
* member. If the %export_path contains "%u", then it will be replaced with a
|
|
|
|
|
* monotonically increasing integer ID (with each distinct %export_path having
|
|
|
|
|
* its own counter). Otherwise, %export_path will be used literally (implying
|
|
|
|
|
* that @self must be a singleton).
|
|
|
|
|
*
|
|
|
|
|
* Returns: the path @self was exported under
|
|
|
|
|
*/
|
|
|
|
|
const char *
|
|
|
|
|
nm_exported_object_export (NMExportedObject *self)
|
|
|
|
|
{
|
|
|
|
|
NMExportedObjectPrivate *priv;
|
2015-04-15 14:53:30 -04:00
|
|
|
GType type;
|
2015-04-03 10:08:52 -04:00
|
|
|
|
|
|
|
|
g_return_val_if_fail (NM_IS_EXPORTED_OBJECT (self), NULL);
|
|
|
|
|
priv = NM_EXPORTED_OBJECT_GET_PRIVATE (self);
|
|
|
|
|
|
2015-09-15 11:32:43 +02:00
|
|
|
g_return_val_if_fail (!priv->path, priv->path);
|
2015-11-04 12:43:56 +01:00
|
|
|
g_return_val_if_fail (!priv->bus_mgr, priv->path);
|
2015-04-03 10:08:52 -04:00
|
|
|
|
2015-11-04 14:44:29 +01:00
|
|
|
#ifdef _ASSERT_NO_EARLY_EXPORT
|
|
|
|
|
nm_assert (priv->_constructed);
|
|
|
|
|
#endif
|
|
|
|
|
|
2015-07-20 17:30:02 -05:00
|
|
|
priv->bus_mgr = nm_bus_manager_get ();
|
|
|
|
|
if (!priv->bus_mgr)
|
|
|
|
|
g_return_val_if_reached (NULL);
|
|
|
|
|
g_object_add_weak_pointer ((GObject *) priv->bus_mgr, (gpointer *) &priv->bus_mgr);
|
|
|
|
|
|
2015-04-15 14:53:30 -04:00
|
|
|
type = G_OBJECT_TYPE (self);
|
|
|
|
|
while (type != NM_TYPE_EXPORTED_OBJECT) {
|
|
|
|
|
nm_exported_object_create_skeletons (self, type);
|
|
|
|
|
type = g_type_parent (type);
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-30 16:50:38 +02:00
|
|
|
priv->path = _create_export_path (NM_EXPORTED_OBJECT_GET_CLASS (self));
|
|
|
|
|
|
2016-02-11 11:58:51 +01:00
|
|
|
_LOGT ("export: \"%s\"", priv->path);
|
|
|
|
|
g_dbus_object_skeleton_set_object_path (G_DBUS_OBJECT_SKELETON (self), priv->path);
|
|
|
|
|
|
2015-09-15 11:32:43 +02:00
|
|
|
/* Important: priv->path and priv->interfaces must not change while
|
|
|
|
|
* the object is registered. */
|
|
|
|
|
|
2015-07-20 17:30:02 -05:00
|
|
|
nm_bus_manager_register_object (priv->bus_mgr, (GDBusObjectSkeleton *) self);
|
2015-04-03 10:08:52 -04:00
|
|
|
|
2017-01-24 18:50:38 +01:00
|
|
|
_notify (self, PROP_PATH);
|
|
|
|
|
|
2015-04-03 10:08:52 -04:00
|
|
|
return priv->path;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_exported_object_unexport:
|
|
|
|
|
* @self: an #NMExportedObject
|
|
|
|
|
*
|
|
|
|
|
* Unexports @self on all active D-Bus connections (and prevents it from being
|
|
|
|
|
* auto-exported on future connections).
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
nm_exported_object_unexport (NMExportedObject *self)
|
|
|
|
|
{
|
|
|
|
|
NMExportedObjectPrivate *priv;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (NM_IS_EXPORTED_OBJECT (self));
|
|
|
|
|
priv = NM_EXPORTED_OBJECT_GET_PRIVATE (self);
|
|
|
|
|
|
2015-09-15 11:32:43 +02:00
|
|
|
g_return_if_fail (priv->path);
|
2015-04-03 10:08:52 -04:00
|
|
|
|
2015-09-15 11:32:43 +02:00
|
|
|
/* Important: priv->path and priv->interfaces must not change while
|
|
|
|
|
* the object is registered. */
|
|
|
|
|
|
2015-07-20 17:30:02 -05:00
|
|
|
_LOGT ("unexport: \"%s\"", priv->path);
|
|
|
|
|
|
|
|
|
|
if (priv->bus_mgr) {
|
|
|
|
|
nm_bus_manager_unregister_object (priv->bus_mgr, (GDBusObjectSkeleton *) self);
|
|
|
|
|
g_object_remove_weak_pointer ((GObject *) priv->bus_mgr, (gpointer *) &priv->bus_mgr);
|
|
|
|
|
priv->bus_mgr = NULL;
|
|
|
|
|
}
|
2015-04-03 10:08:52 -04:00
|
|
|
|
2015-09-17 17:13:30 +02:00
|
|
|
nm_exported_object_destroy_skeletons (self);
|
2015-08-13 17:04:39 +02:00
|
|
|
|
2015-07-20 17:30:02 -05:00
|
|
|
g_dbus_object_skeleton_set_object_path ((GDBusObjectSkeleton *) self, NULL);
|
|
|
|
|
|
2015-09-15 11:32:43 +02:00
|
|
|
g_clear_pointer (&priv->path, g_free);
|
|
|
|
|
|
2016-08-31 11:21:08 +02:00
|
|
|
nm_clear_g_source (&priv->notify_idle_id);
|
2017-01-24 18:50:38 +01:00
|
|
|
|
|
|
|
|
_notify (self, PROP_PATH);
|
2015-04-13 13:31:42 -04:00
|
|
|
}
|
|
|
|
|
|
2016-03-30 16:58:02 +02:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
_nm_exported_object_clear_and_unexport (NMExportedObject **location)
|
|
|
|
|
{
|
|
|
|
|
NMExportedObject *self;
|
|
|
|
|
NMExportedObjectPrivate *priv;
|
|
|
|
|
|
|
|
|
|
if (!location || !*location)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
self = *location;
|
|
|
|
|
*location = NULL;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (NM_IS_EXPORTED_OBJECT (self));
|
|
|
|
|
|
|
|
|
|
priv = NM_EXPORTED_OBJECT_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
if (priv->path)
|
|
|
|
|
nm_exported_object_unexport (self);
|
|
|
|
|
|
|
|
|
|
g_object_unref (self);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2016-03-30 12:28:28 +02:00
|
|
|
GDBusInterfaceSkeleton *
|
|
|
|
|
nm_exported_object_get_interface_by_type (NMExportedObject *self, GType interface_type)
|
2015-09-15 11:32:43 +02:00
|
|
|
{
|
|
|
|
|
NMExportedObjectPrivate *priv;
|
2016-03-30 12:28:28 +02:00
|
|
|
guint i;
|
2015-09-15 11:32:43 +02:00
|
|
|
|
|
|
|
|
g_return_val_if_fail (NM_IS_EXPORTED_OBJECT (self), NULL);
|
|
|
|
|
|
|
|
|
|
priv = NM_EXPORTED_OBJECT_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (priv->path, NULL);
|
2016-03-30 12:28:28 +02:00
|
|
|
g_return_val_if_fail (priv->num_interfaces > 0, NULL);
|
2015-09-15 11:32:43 +02:00
|
|
|
|
2016-03-30 12:28:28 +02:00
|
|
|
nm_assert (priv->interfaces);
|
2015-09-15 11:32:43 +02:00
|
|
|
|
2016-03-30 12:28:28 +02:00
|
|
|
for (i = 0; i < priv->num_interfaces; i++) {
|
|
|
|
|
InterfaceData *ifdata = &priv->interfaces[i];
|
2015-09-15 11:34:00 +02:00
|
|
|
|
2016-03-30 12:28:28 +02:00
|
|
|
if (G_TYPE_CHECK_INSTANCE_TYPE (ifdata->interface, interface_type))
|
|
|
|
|
return ifdata->interface;
|
2015-09-15 11:34:00 +02:00
|
|
|
}
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-30 16:58:02 +02:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2015-07-23 10:03:21 -05:00
|
|
|
void
|
2016-03-30 16:58:02 +02:00
|
|
|
nm_exported_object_class_set_quitting (void)
|
2015-07-23 10:03:21 -05:00
|
|
|
{
|
2016-03-30 16:58:02 +02:00
|
|
|
quitting = TRUE;
|
2015-07-23 10:03:21 -05:00
|
|
|
}
|
|
|
|
|
|
2016-03-30 16:58:02 +02:00
|
|
|
/*****************************************************************************/
|
2015-04-13 13:31:42 -04:00
|
|
|
|
2016-03-30 11:55:50 +02:00
|
|
|
typedef struct {
|
|
|
|
|
const char *property_name;
|
|
|
|
|
GVariant *variant;
|
|
|
|
|
} PendingNotifiesItem;
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
_sort_pending_notifies (gconstpointer a, gconstpointer b, gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
return strcmp (((const PendingNotifiesItem *) a)->property_name,
|
|
|
|
|
((const PendingNotifiesItem *) b)->property_name);
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-13 13:31:42 -04:00
|
|
|
static gboolean
|
|
|
|
|
idle_emit_properties_changed (gpointer self)
|
|
|
|
|
{
|
2016-09-28 15:58:24 +02:00
|
|
|
NMExportedObjectPrivate *priv = NM_EXPORTED_OBJECT_GET_PRIVATE (NM_EXPORTED_OBJECT (self));
|
2016-08-31 11:21:08 +02:00
|
|
|
guint k;
|
2015-04-13 13:31:42 -04:00
|
|
|
|
|
|
|
|
priv->notify_idle_id = 0;
|
2016-03-22 13:00:56 -05:00
|
|
|
|
2016-08-31 11:21:08 +02:00
|
|
|
for (k = 0; k < priv->num_interfaces; k++) {
|
|
|
|
|
InterfaceData *ifdata = &priv->interfaces[k];
|
|
|
|
|
gs_unref_variant GVariant *variant = NULL;
|
|
|
|
|
PendingNotifiesItem *values;
|
|
|
|
|
GVariantBuilder notifies;
|
|
|
|
|
GHashTableIter hash_iter;
|
|
|
|
|
guint i, n;
|
|
|
|
|
|
|
|
|
|
n = g_hash_table_size (ifdata->pending_notifies);
|
|
|
|
|
if (n == 0)
|
|
|
|
|
continue;
|
2016-03-30 11:55:50 +02:00
|
|
|
|
dbus: fix emitting D-Bus NetworkManager's old-style PropertiesChange signal
Before switching to gdbus (before 1.2.0), NetworkManager used dbus-glib.
Most objects in the D-Bus API with properties had a signal
NetworkManager-specific "PropertiesChanged" signal. Nowadays, this way of
handling of property changes is deprecated for the common "PropertiesChanged"
signal on the "org.freedesktop.DBus.Properties" interface.
There were a few pecularities in 1.0.0 and earlier:
(1) Due to the implementation with dbus-glib, a property-changed
signal was emitted on *all* interfaces. For example:
- a change on a NMDeviceVeth of "NMDeviceEthernet.HwAddress" would be
emitted both for the interfaces "fdo.NM.Device.Ethernet" and
"fdo.NM.Device.Veth". Note that NMDeviceVeth is derived from
NMDeviceEthernet and there is no "HwAddress" on veth device.
- a change of "NMVpnConnection.VpnState" was emitted on both
interfaces "fdo.NM.VPN.Connection" and "fdo.NM.Connecion.Active".
Note that NMActiveConnection is the parent type of NMVpnConnection and
only the latter has a property "VpnState".
(2) NMDevice's "fdo.NM.Device" interface doesn't have a "PropertiesChanged"
signal. From (1) follows that all property-changes for this type were instead
invoked with an interface like "fdo.NM.Device.Ethernet" (or multiple
interfaces in case of NMDeviceVeth).
1.2.0 introduced gdbus, which gives us the standard "fdo.DBus.Properties"
signal. However, it made the mistake of not realizing (1), thus instead
of emitting the signal once for each interface, it would pick the first
one in the inheritance tree.
With 1.4.0, a bug from merge commit 844345e caused signals for devices
to be only emitted for the interface "fdo.NM.Device.Statistics", instead
of "fdo.NM.Device.Ethernet" or "fdo.NM.Device.Veth" (or both).
The latter is what bgo#770629 is about and what commit 82e9439 tried to fix.
However, the fix was wrong because it tried to do the theoretically correct
thing of emitting the property-changed signal exactly once for the
interface that actually ontains the property. In addition, it missed that
NMDevice doesn't have a PropertiesChanged signal, which caused signals for
"fdo.NM.Device" to get lost *sigh*.
Now, restore the (broken) behavior of 1.0.0. These old-style property changed
signals are anyway considered deprecated and exist solely to satisfy old clients
and preserve the old API.
Fixes: 63fbfad3705db5901e6a2a6a2fc332da0f0ae4be
https://bugzilla.gnome.org/show_bug.cgi?id=770629
https://bugzilla.redhat.com/show_bug.cgi?id=1371920
2016-09-01 13:00:21 +02:00
|
|
|
nm_assert (ifdata->property_changed_signal_id);
|
2016-03-30 11:55:50 +02:00
|
|
|
|
2016-08-31 11:21:08 +02:00
|
|
|
/* We use here alloca in a loop, something that is usually avoided.
|
|
|
|
|
* But the number of interfaces "priv->num_interfaces" is small (determined by
|
dbus: fix emitting D-Bus NetworkManager's old-style PropertiesChange signal
Before switching to gdbus (before 1.2.0), NetworkManager used dbus-glib.
Most objects in the D-Bus API with properties had a signal
NetworkManager-specific "PropertiesChanged" signal. Nowadays, this way of
handling of property changes is deprecated for the common "PropertiesChanged"
signal on the "org.freedesktop.DBus.Properties" interface.
There were a few pecularities in 1.0.0 and earlier:
(1) Due to the implementation with dbus-glib, a property-changed
signal was emitted on *all* interfaces. For example:
- a change on a NMDeviceVeth of "NMDeviceEthernet.HwAddress" would be
emitted both for the interfaces "fdo.NM.Device.Ethernet" and
"fdo.NM.Device.Veth". Note that NMDeviceVeth is derived from
NMDeviceEthernet and there is no "HwAddress" on veth device.
- a change of "NMVpnConnection.VpnState" was emitted on both
interfaces "fdo.NM.VPN.Connection" and "fdo.NM.Connecion.Active".
Note that NMActiveConnection is the parent type of NMVpnConnection and
only the latter has a property "VpnState".
(2) NMDevice's "fdo.NM.Device" interface doesn't have a "PropertiesChanged"
signal. From (1) follows that all property-changes for this type were instead
invoked with an interface like "fdo.NM.Device.Ethernet" (or multiple
interfaces in case of NMDeviceVeth).
1.2.0 introduced gdbus, which gives us the standard "fdo.DBus.Properties"
signal. However, it made the mistake of not realizing (1), thus instead
of emitting the signal once for each interface, it would pick the first
one in the inheritance tree.
With 1.4.0, a bug from merge commit 844345e caused signals for devices
to be only emitted for the interface "fdo.NM.Device.Statistics", instead
of "fdo.NM.Device.Ethernet" or "fdo.NM.Device.Veth" (or both).
The latter is what bgo#770629 is about and what commit 82e9439 tried to fix.
However, the fix was wrong because it tried to do the theoretically correct
thing of emitting the property-changed signal exactly once for the
interface that actually ontains the property. In addition, it missed that
NMDevice doesn't have a PropertiesChanged signal, which caused signals for
"fdo.NM.Device" to get lost *sigh*.
Now, restore the (broken) behavior of 1.0.0. These old-style property changed
signals are anyway considered deprecated and exist solely to satisfy old clients
and preserve the old API.
Fixes: 63fbfad3705db5901e6a2a6a2fc332da0f0ae4be
https://bugzilla.gnome.org/show_bug.cgi?id=770629
https://bugzilla.redhat.com/show_bug.cgi?id=1371920
2016-09-01 13:00:21 +02:00
|
|
|
* the depth of the type inheritance) and the number of possible pending_notifies
|
2016-08-31 11:21:08 +02:00
|
|
|
* "n" is small (determined by the number of GObject properties). */
|
|
|
|
|
values = g_alloca (sizeof (values[0]) * n);
|
2016-03-30 11:55:50 +02:00
|
|
|
|
2016-08-31 11:21:08 +02:00
|
|
|
i = 0;
|
|
|
|
|
g_hash_table_iter_init (&hash_iter, ifdata->pending_notifies);
|
|
|
|
|
while (g_hash_table_iter_next (&hash_iter, (gpointer) &values[i].property_name, (gpointer) &values[i].variant))
|
|
|
|
|
i++;
|
|
|
|
|
nm_assert (i == n);
|
2016-03-30 11:55:50 +02:00
|
|
|
|
2016-08-31 11:21:08 +02:00
|
|
|
g_qsort_with_data (values, n, sizeof (values[0]), _sort_pending_notifies, NULL);
|
2016-03-30 11:55:50 +02:00
|
|
|
|
2016-08-31 11:21:08 +02:00
|
|
|
g_variant_builder_init (¬ifies, G_VARIANT_TYPE_VARDICT);
|
|
|
|
|
for (i = 0; i < n; i++)
|
|
|
|
|
g_variant_builder_add (¬ifies, "{sv}", values[i].property_name, values[i].variant);
|
|
|
|
|
variant = g_variant_ref_sink (g_variant_builder_end (¬ifies));
|
2016-03-30 11:55:50 +02:00
|
|
|
|
2015-04-15 14:53:30 -04:00
|
|
|
|
2016-09-01 15:09:01 +02:00
|
|
|
if (_LOG2D_ENABLED ()) {
|
2016-08-31 11:21:08 +02:00
|
|
|
gs_free char *notification = g_variant_print (variant, TRUE);
|
|
|
|
|
|
2016-09-01 15:09:01 +02:00
|
|
|
_LOG2D ("type %s, iface %s: %s",
|
|
|
|
|
G_OBJECT_TYPE_NAME (self), G_OBJECT_TYPE_NAME (ifdata->interface),
|
|
|
|
|
notification);
|
2015-04-15 14:53:30 -04:00
|
|
|
}
|
2015-04-13 13:31:42 -04:00
|
|
|
|
2016-08-31 11:21:08 +02:00
|
|
|
g_signal_emit (ifdata->interface, ifdata->property_changed_signal_id, 0, variant);
|
2015-04-13 13:31:42 -04:00
|
|
|
|
2016-08-31 11:21:08 +02:00
|
|
|
g_hash_table_remove_all (ifdata->pending_notifies);
|
2015-04-13 13:31:42 -04:00
|
|
|
}
|
|
|
|
|
|
2016-08-31 11:21:08 +02:00
|
|
|
return G_SOURCE_REMOVE;
|
2015-04-13 13:31:42 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
nm_exported_object_notify (GObject *object, GParamSpec *pspec)
|
|
|
|
|
{
|
dbus: fix emitting D-Bus NetworkManager's old-style PropertiesChange signal
Before switching to gdbus (before 1.2.0), NetworkManager used dbus-glib.
Most objects in the D-Bus API with properties had a signal
NetworkManager-specific "PropertiesChanged" signal. Nowadays, this way of
handling of property changes is deprecated for the common "PropertiesChanged"
signal on the "org.freedesktop.DBus.Properties" interface.
There were a few pecularities in 1.0.0 and earlier:
(1) Due to the implementation with dbus-glib, a property-changed
signal was emitted on *all* interfaces. For example:
- a change on a NMDeviceVeth of "NMDeviceEthernet.HwAddress" would be
emitted both for the interfaces "fdo.NM.Device.Ethernet" and
"fdo.NM.Device.Veth". Note that NMDeviceVeth is derived from
NMDeviceEthernet and there is no "HwAddress" on veth device.
- a change of "NMVpnConnection.VpnState" was emitted on both
interfaces "fdo.NM.VPN.Connection" and "fdo.NM.Connecion.Active".
Note that NMActiveConnection is the parent type of NMVpnConnection and
only the latter has a property "VpnState".
(2) NMDevice's "fdo.NM.Device" interface doesn't have a "PropertiesChanged"
signal. From (1) follows that all property-changes for this type were instead
invoked with an interface like "fdo.NM.Device.Ethernet" (or multiple
interfaces in case of NMDeviceVeth).
1.2.0 introduced gdbus, which gives us the standard "fdo.DBus.Properties"
signal. However, it made the mistake of not realizing (1), thus instead
of emitting the signal once for each interface, it would pick the first
one in the inheritance tree.
With 1.4.0, a bug from merge commit 844345e caused signals for devices
to be only emitted for the interface "fdo.NM.Device.Statistics", instead
of "fdo.NM.Device.Ethernet" or "fdo.NM.Device.Veth" (or both).
The latter is what bgo#770629 is about and what commit 82e9439 tried to fix.
However, the fix was wrong because it tried to do the theoretically correct
thing of emitting the property-changed signal exactly once for the
interface that actually ontains the property. In addition, it missed that
NMDevice doesn't have a PropertiesChanged signal, which caused signals for
"fdo.NM.Device" to get lost *sigh*.
Now, restore the (broken) behavior of 1.0.0. These old-style property changed
signals are anyway considered deprecated and exist solely to satisfy old clients
and preserve the old API.
Fixes: 63fbfad3705db5901e6a2a6a2fc332da0f0ae4be
https://bugzilla.gnome.org/show_bug.cgi?id=770629
https://bugzilla.redhat.com/show_bug.cgi?id=1371920
2016-09-01 13:00:21 +02:00
|
|
|
NMExportedObject *self = (NMExportedObject *) object;
|
2016-09-01 15:05:03 +02:00
|
|
|
NMExportedObjectPrivate *priv = NM_EXPORTED_OBJECT_GET_PRIVATE (self);
|
2015-04-13 13:31:42 -04:00
|
|
|
NMExportedObjectClassInfo *classinfo;
|
|
|
|
|
GType type;
|
2015-04-15 14:53:30 -04:00
|
|
|
const char *dbus_property_name = NULL;
|
|
|
|
|
GValue value = G_VALUE_INIT;
|
dbus: fix emitting D-Bus NetworkManager's old-style PropertiesChange signal
Before switching to gdbus (before 1.2.0), NetworkManager used dbus-glib.
Most objects in the D-Bus API with properties had a signal
NetworkManager-specific "PropertiesChanged" signal. Nowadays, this way of
handling of property changes is deprecated for the common "PropertiesChanged"
signal on the "org.freedesktop.DBus.Properties" interface.
There were a few pecularities in 1.0.0 and earlier:
(1) Due to the implementation with dbus-glib, a property-changed
signal was emitted on *all* interfaces. For example:
- a change on a NMDeviceVeth of "NMDeviceEthernet.HwAddress" would be
emitted both for the interfaces "fdo.NM.Device.Ethernet" and
"fdo.NM.Device.Veth". Note that NMDeviceVeth is derived from
NMDeviceEthernet and there is no "HwAddress" on veth device.
- a change of "NMVpnConnection.VpnState" was emitted on both
interfaces "fdo.NM.VPN.Connection" and "fdo.NM.Connecion.Active".
Note that NMActiveConnection is the parent type of NMVpnConnection and
only the latter has a property "VpnState".
(2) NMDevice's "fdo.NM.Device" interface doesn't have a "PropertiesChanged"
signal. From (1) follows that all property-changes for this type were instead
invoked with an interface like "fdo.NM.Device.Ethernet" (or multiple
interfaces in case of NMDeviceVeth).
1.2.0 introduced gdbus, which gives us the standard "fdo.DBus.Properties"
signal. However, it made the mistake of not realizing (1), thus instead
of emitting the signal once for each interface, it would pick the first
one in the inheritance tree.
With 1.4.0, a bug from merge commit 844345e caused signals for devices
to be only emitted for the interface "fdo.NM.Device.Statistics", instead
of "fdo.NM.Device.Ethernet" or "fdo.NM.Device.Veth" (or both).
The latter is what bgo#770629 is about and what commit 82e9439 tried to fix.
However, the fix was wrong because it tried to do the theoretically correct
thing of emitting the property-changed signal exactly once for the
interface that actually ontains the property. In addition, it missed that
NMDevice doesn't have a PropertiesChanged signal, which caused signals for
"fdo.NM.Device" to get lost *sigh*.
Now, restore the (broken) behavior of 1.0.0. These old-style property changed
signals are anyway considered deprecated and exist solely to satisfy old clients
and preserve the old API.
Fixes: 63fbfad3705db5901e6a2a6a2fc332da0f0ae4be
https://bugzilla.gnome.org/show_bug.cgi?id=770629
https://bugzilla.redhat.com/show_bug.cgi?id=1371920
2016-09-01 13:00:21 +02:00
|
|
|
GVariant *value_variant;
|
2016-08-31 11:21:08 +02:00
|
|
|
InterfaceData *ifdata = NULL;
|
2015-04-15 14:53:30 -04:00
|
|
|
const GVariantType *vtype;
|
2016-03-30 13:29:05 +02:00
|
|
|
guint i, j;
|
2015-04-15 14:53:30 -04:00
|
|
|
|
dbus: fix emitting D-Bus NetworkManager's old-style PropertiesChange signal
Before switching to gdbus (before 1.2.0), NetworkManager used dbus-glib.
Most objects in the D-Bus API with properties had a signal
NetworkManager-specific "PropertiesChanged" signal. Nowadays, this way of
handling of property changes is deprecated for the common "PropertiesChanged"
signal on the "org.freedesktop.DBus.Properties" interface.
There were a few pecularities in 1.0.0 and earlier:
(1) Due to the implementation with dbus-glib, a property-changed
signal was emitted on *all* interfaces. For example:
- a change on a NMDeviceVeth of "NMDeviceEthernet.HwAddress" would be
emitted both for the interfaces "fdo.NM.Device.Ethernet" and
"fdo.NM.Device.Veth". Note that NMDeviceVeth is derived from
NMDeviceEthernet and there is no "HwAddress" on veth device.
- a change of "NMVpnConnection.VpnState" was emitted on both
interfaces "fdo.NM.VPN.Connection" and "fdo.NM.Connecion.Active".
Note that NMActiveConnection is the parent type of NMVpnConnection and
only the latter has a property "VpnState".
(2) NMDevice's "fdo.NM.Device" interface doesn't have a "PropertiesChanged"
signal. From (1) follows that all property-changes for this type were instead
invoked with an interface like "fdo.NM.Device.Ethernet" (or multiple
interfaces in case of NMDeviceVeth).
1.2.0 introduced gdbus, which gives us the standard "fdo.DBus.Properties"
signal. However, it made the mistake of not realizing (1), thus instead
of emitting the signal once for each interface, it would pick the first
one in the inheritance tree.
With 1.4.0, a bug from merge commit 844345e caused signals for devices
to be only emitted for the interface "fdo.NM.Device.Statistics", instead
of "fdo.NM.Device.Ethernet" or "fdo.NM.Device.Veth" (or both).
The latter is what bgo#770629 is about and what commit 82e9439 tried to fix.
However, the fix was wrong because it tried to do the theoretically correct
thing of emitting the property-changed signal exactly once for the
interface that actually ontains the property. In addition, it missed that
NMDevice doesn't have a PropertiesChanged signal, which caused signals for
"fdo.NM.Device" to get lost *sigh*.
Now, restore the (broken) behavior of 1.0.0. These old-style property changed
signals are anyway considered deprecated and exist solely to satisfy old clients
and preserve the old API.
Fixes: 63fbfad3705db5901e6a2a6a2fc332da0f0ae4be
https://bugzilla.gnome.org/show_bug.cgi?id=770629
https://bugzilla.redhat.com/show_bug.cgi?id=1371920
2016-09-01 13:00:21 +02:00
|
|
|
/* Hook to emit deprecated "PropertiesChanged" signal on NetworkManager interfaces.
|
|
|
|
|
* This is to preserve deprecated D-Bus API, nowadays we use instead
|
|
|
|
|
* the "PropertiesChanged" signal of "org.freedesktop.DBus.Properties". */
|
|
|
|
|
|
2016-03-30 12:28:28 +02:00
|
|
|
if (priv->num_interfaces == 0)
|
2015-04-15 14:53:30 -04:00
|
|
|
return;
|
2015-04-13 13:31:42 -04:00
|
|
|
|
2016-09-01 15:05:03 +02:00
|
|
|
for (type = G_OBJECT_TYPE (self); type; type = g_type_parent (type)) {
|
2015-04-13 13:31:42 -04:00
|
|
|
classinfo = g_type_get_qdata (type, nm_exported_object_class_info_quark ());
|
|
|
|
|
if (!classinfo)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
dbus_property_name = g_hash_table_lookup (classinfo->properties, pspec->name);
|
|
|
|
|
if (dbus_property_name)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (!dbus_property_name) {
|
2016-09-01 15:09:01 +02:00
|
|
|
_LOG2T ("ignoring notification for prop %s on type %s",
|
|
|
|
|
pspec->name, G_OBJECT_TYPE_NAME (self));
|
2015-04-13 13:31:42 -04:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-30 13:29:05 +02:00
|
|
|
for (i = 0; i < priv->num_interfaces; i++) {
|
|
|
|
|
GDBusInterfaceInfo *iinfo;
|
|
|
|
|
|
2016-08-31 11:21:08 +02:00
|
|
|
ifdata = &priv->interfaces[i];
|
|
|
|
|
iinfo = g_dbus_interface_skeleton_get_info (ifdata->interface);
|
2016-03-30 13:29:05 +02:00
|
|
|
for (j = 0; iinfo->properties[j]; j++) {
|
|
|
|
|
if (nm_streq (iinfo->properties[j]->name, dbus_property_name)) {
|
|
|
|
|
vtype = G_VARIANT_TYPE (iinfo->properties[j]->signature);
|
|
|
|
|
goto vtype_found;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
g_return_if_reached ();
|
|
|
|
|
|
|
|
|
|
vtype_found:
|
2015-04-15 14:53:30 -04:00
|
|
|
g_value_init (&value, pspec->value_type);
|
2016-09-01 15:05:03 +02:00
|
|
|
g_object_get_property ((GObject *) self, pspec->name, &value);
|
dbus: fix emitting D-Bus NetworkManager's old-style PropertiesChange signal
Before switching to gdbus (before 1.2.0), NetworkManager used dbus-glib.
Most objects in the D-Bus API with properties had a signal
NetworkManager-specific "PropertiesChanged" signal. Nowadays, this way of
handling of property changes is deprecated for the common "PropertiesChanged"
signal on the "org.freedesktop.DBus.Properties" interface.
There were a few pecularities in 1.0.0 and earlier:
(1) Due to the implementation with dbus-glib, a property-changed
signal was emitted on *all* interfaces. For example:
- a change on a NMDeviceVeth of "NMDeviceEthernet.HwAddress" would be
emitted both for the interfaces "fdo.NM.Device.Ethernet" and
"fdo.NM.Device.Veth". Note that NMDeviceVeth is derived from
NMDeviceEthernet and there is no "HwAddress" on veth device.
- a change of "NMVpnConnection.VpnState" was emitted on both
interfaces "fdo.NM.VPN.Connection" and "fdo.NM.Connecion.Active".
Note that NMActiveConnection is the parent type of NMVpnConnection and
only the latter has a property "VpnState".
(2) NMDevice's "fdo.NM.Device" interface doesn't have a "PropertiesChanged"
signal. From (1) follows that all property-changes for this type were instead
invoked with an interface like "fdo.NM.Device.Ethernet" (or multiple
interfaces in case of NMDeviceVeth).
1.2.0 introduced gdbus, which gives us the standard "fdo.DBus.Properties"
signal. However, it made the mistake of not realizing (1), thus instead
of emitting the signal once for each interface, it would pick the first
one in the inheritance tree.
With 1.4.0, a bug from merge commit 844345e caused signals for devices
to be only emitted for the interface "fdo.NM.Device.Statistics", instead
of "fdo.NM.Device.Ethernet" or "fdo.NM.Device.Veth" (or both).
The latter is what bgo#770629 is about and what commit 82e9439 tried to fix.
However, the fix was wrong because it tried to do the theoretically correct
thing of emitting the property-changed signal exactly once for the
interface that actually ontains the property. In addition, it missed that
NMDevice doesn't have a PropertiesChanged signal, which caused signals for
"fdo.NM.Device" to get lost *sigh*.
Now, restore the (broken) behavior of 1.0.0. These old-style property changed
signals are anyway considered deprecated and exist solely to satisfy old clients
and preserve the old API.
Fixes: 63fbfad3705db5901e6a2a6a2fc332da0f0ae4be
https://bugzilla.gnome.org/show_bug.cgi?id=770629
https://bugzilla.redhat.com/show_bug.cgi?id=1371920
2016-09-01 13:00:21 +02:00
|
|
|
value_variant = g_dbus_gvalue_to_gvariant (&value, vtype);
|
2015-04-15 14:53:30 -04:00
|
|
|
g_value_unset (&value);
|
2015-04-13 13:31:42 -04:00
|
|
|
|
dbus: fix emitting D-Bus NetworkManager's old-style PropertiesChange signal
Before switching to gdbus (before 1.2.0), NetworkManager used dbus-glib.
Most objects in the D-Bus API with properties had a signal
NetworkManager-specific "PropertiesChanged" signal. Nowadays, this way of
handling of property changes is deprecated for the common "PropertiesChanged"
signal on the "org.freedesktop.DBus.Properties" interface.
There were a few pecularities in 1.0.0 and earlier:
(1) Due to the implementation with dbus-glib, a property-changed
signal was emitted on *all* interfaces. For example:
- a change on a NMDeviceVeth of "NMDeviceEthernet.HwAddress" would be
emitted both for the interfaces "fdo.NM.Device.Ethernet" and
"fdo.NM.Device.Veth". Note that NMDeviceVeth is derived from
NMDeviceEthernet and there is no "HwAddress" on veth device.
- a change of "NMVpnConnection.VpnState" was emitted on both
interfaces "fdo.NM.VPN.Connection" and "fdo.NM.Connecion.Active".
Note that NMActiveConnection is the parent type of NMVpnConnection and
only the latter has a property "VpnState".
(2) NMDevice's "fdo.NM.Device" interface doesn't have a "PropertiesChanged"
signal. From (1) follows that all property-changes for this type were instead
invoked with an interface like "fdo.NM.Device.Ethernet" (or multiple
interfaces in case of NMDeviceVeth).
1.2.0 introduced gdbus, which gives us the standard "fdo.DBus.Properties"
signal. However, it made the mistake of not realizing (1), thus instead
of emitting the signal once for each interface, it would pick the first
one in the inheritance tree.
With 1.4.0, a bug from merge commit 844345e caused signals for devices
to be only emitted for the interface "fdo.NM.Device.Statistics", instead
of "fdo.NM.Device.Ethernet" or "fdo.NM.Device.Veth" (or both).
The latter is what bgo#770629 is about and what commit 82e9439 tried to fix.
However, the fix was wrong because it tried to do the theoretically correct
thing of emitting the property-changed signal exactly once for the
interface that actually ontains the property. In addition, it missed that
NMDevice doesn't have a PropertiesChanged signal, which caused signals for
"fdo.NM.Device" to get lost *sigh*.
Now, restore the (broken) behavior of 1.0.0. These old-style property changed
signals are anyway considered deprecated and exist solely to satisfy old clients
and preserve the old API.
Fixes: 63fbfad3705db5901e6a2a6a2fc332da0f0ae4be
https://bugzilla.gnome.org/show_bug.cgi?id=770629
https://bugzilla.redhat.com/show_bug.cgi?id=1371920
2016-09-01 13:00:21 +02:00
|
|
|
if ( ( NM_IS_DEVICE (self)
|
|
|
|
|
&& !NMDBUS_IS_DEVICE_STATISTICS_SKELETON (ifdata->interface))
|
|
|
|
|
|| NM_IS_ACTIVE_CONNECTION (self)) {
|
|
|
|
|
/* This PropertiesChanged signal is nodaways deprecated in favor
|
|
|
|
|
* of "org.freedesktop.DBus.Properties"'s PropertiesChanged signal.
|
|
|
|
|
* This function solely exists to raise the NM version of PropertiesChanged.
|
|
|
|
|
*
|
|
|
|
|
* With types exported on D-Bus that are implemented as derived
|
|
|
|
|
* types in glib (NMDevice and NMActiveConnection), multiple types
|
|
|
|
|
* in the inheritance tree define a "PropertiesChanged" signal.
|
|
|
|
|
*
|
|
|
|
|
* In 1.0.0 and earlier, the signal was emitted once for every interface
|
|
|
|
|
* that had a "PropertiesChanged" signal. For example:
|
|
|
|
|
* - NMDeviceEthernet.HwAddress was emitted on "fdo.NM.Device.Ethernet"
|
|
|
|
|
* and "fdo.NM.Device.Veth" (if the device was of type NMDeviceVeth).
|
|
|
|
|
* - NMVpnConnection.VpnState was emitted on "fdo.NM.Connecion.Active"
|
|
|
|
|
* and "fdo.NM.VPN.Connection".
|
|
|
|
|
*
|
|
|
|
|
* NMDevice is special in that it didn't have a "PropertiesChanged" signal.
|
|
|
|
|
* Thus, a change to "NMDevice.StateReason" would be emitted on "fdo.NM.Device.Ethernet"
|
|
|
|
|
* and also on "fdo.NM.Device.Veth" (in case of a device of type NMDeviceVeth).
|
|
|
|
|
*
|
|
|
|
|
* The releases of 1.2.0 and 1.4.0 failed to realize above and broke this behavior.
|
|
|
|
|
* This special handling here is to bring back the 1.0.0 behavior.
|
|
|
|
|
*
|
|
|
|
|
* The Device.Statistics signal is special, because it was only added with 1.4.0
|
|
|
|
|
* and didn't have above behavior. So let's save the overhead of emitting multiple
|
|
|
|
|
* deprecated signals for wrong interfaces. */
|
|
|
|
|
for (i = 0, j = 0; i < priv->num_interfaces; i++) {
|
|
|
|
|
ifdata = &priv->interfaces[i];
|
|
|
|
|
if ( ifdata->property_changed_signal_id
|
|
|
|
|
&& !NMDBUS_IS_DEVICE_STATISTICS_SKELETON (ifdata->interface)) {
|
|
|
|
|
j++;
|
|
|
|
|
g_hash_table_insert (ifdata->pending_notifies,
|
|
|
|
|
(gpointer) dbus_property_name,
|
|
|
|
|
g_variant_ref (value_variant));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
nm_assert (j > 0);
|
|
|
|
|
g_variant_unref (value_variant);
|
|
|
|
|
} else if (ifdata->property_changed_signal_id) {
|
|
|
|
|
/* @dbus_property_name is inside classinfo and never freed, thus we don't clone it.
|
|
|
|
|
* Also, we do a pointer, not string comparison. */
|
|
|
|
|
g_hash_table_insert (ifdata->pending_notifies,
|
|
|
|
|
(gpointer) dbus_property_name,
|
|
|
|
|
value_variant);
|
2016-12-20 10:13:44 +01:00
|
|
|
} else
|
|
|
|
|
g_variant_unref (value_variant);
|
dbus: fix emitting D-Bus NetworkManager's old-style PropertiesChange signal
Before switching to gdbus (before 1.2.0), NetworkManager used dbus-glib.
Most objects in the D-Bus API with properties had a signal
NetworkManager-specific "PropertiesChanged" signal. Nowadays, this way of
handling of property changes is deprecated for the common "PropertiesChanged"
signal on the "org.freedesktop.DBus.Properties" interface.
There were a few pecularities in 1.0.0 and earlier:
(1) Due to the implementation with dbus-glib, a property-changed
signal was emitted on *all* interfaces. For example:
- a change on a NMDeviceVeth of "NMDeviceEthernet.HwAddress" would be
emitted both for the interfaces "fdo.NM.Device.Ethernet" and
"fdo.NM.Device.Veth". Note that NMDeviceVeth is derived from
NMDeviceEthernet and there is no "HwAddress" on veth device.
- a change of "NMVpnConnection.VpnState" was emitted on both
interfaces "fdo.NM.VPN.Connection" and "fdo.NM.Connecion.Active".
Note that NMActiveConnection is the parent type of NMVpnConnection and
only the latter has a property "VpnState".
(2) NMDevice's "fdo.NM.Device" interface doesn't have a "PropertiesChanged"
signal. From (1) follows that all property-changes for this type were instead
invoked with an interface like "fdo.NM.Device.Ethernet" (or multiple
interfaces in case of NMDeviceVeth).
1.2.0 introduced gdbus, which gives us the standard "fdo.DBus.Properties"
signal. However, it made the mistake of not realizing (1), thus instead
of emitting the signal once for each interface, it would pick the first
one in the inheritance tree.
With 1.4.0, a bug from merge commit 844345e caused signals for devices
to be only emitted for the interface "fdo.NM.Device.Statistics", instead
of "fdo.NM.Device.Ethernet" or "fdo.NM.Device.Veth" (or both).
The latter is what bgo#770629 is about and what commit 82e9439 tried to fix.
However, the fix was wrong because it tried to do the theoretically correct
thing of emitting the property-changed signal exactly once for the
interface that actually ontains the property. In addition, it missed that
NMDevice doesn't have a PropertiesChanged signal, which caused signals for
"fdo.NM.Device" to get lost *sigh*.
Now, restore the (broken) behavior of 1.0.0. These old-style property changed
signals are anyway considered deprecated and exist solely to satisfy old clients
and preserve the old API.
Fixes: 63fbfad3705db5901e6a2a6a2fc332da0f0ae4be
https://bugzilla.gnome.org/show_bug.cgi?id=770629
https://bugzilla.redhat.com/show_bug.cgi?id=1371920
2016-09-01 13:00:21 +02:00
|
|
|
|
2015-04-13 13:31:42 -04:00
|
|
|
if (!priv->notify_idle_id)
|
2016-09-01 15:05:03 +02:00
|
|
|
priv->notify_idle_id = g_idle_add (idle_emit_properties_changed, self);
|
2015-04-13 13:31:42 -04:00
|
|
|
}
|
|
|
|
|
|
2016-03-30 16:58:02 +02:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2017-01-25 13:45:20 +01:00
|
|
|
static void
|
|
|
|
|
get_property (GObject *object, guint prop_id,
|
|
|
|
|
GValue *value, GParamSpec *pspec)
|
|
|
|
|
{
|
|
|
|
|
NMExportedObject *self = NM_EXPORTED_OBJECT (object);
|
|
|
|
|
NMExportedObjectPrivate *priv = NM_EXPORTED_OBJECT_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
switch (prop_id) {
|
|
|
|
|
case PROP_PATH:
|
|
|
|
|
g_value_set_string (value, priv->path);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-30 16:58:02 +02:00
|
|
|
static void
|
|
|
|
|
nm_exported_object_init (NMExportedObject *self)
|
|
|
|
|
{
|
2016-09-28 15:58:24 +02:00
|
|
|
NMExportedObjectPrivate *priv;
|
|
|
|
|
|
|
|
|
|
priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NM_TYPE_EXPORTED_OBJECT, NMExportedObjectPrivate);
|
|
|
|
|
self->_priv = priv;
|
2016-03-30 16:58:02 +02:00
|
|
|
}
|
|
|
|
|
|
2015-11-04 14:44:29 +01:00
|
|
|
static void
|
|
|
|
|
constructed (GObject *object)
|
|
|
|
|
{
|
|
|
|
|
NMExportedObjectClass *klass;
|
|
|
|
|
|
|
|
|
|
G_OBJECT_CLASS (nm_exported_object_parent_class)->constructed (object);
|
|
|
|
|
|
|
|
|
|
#ifdef _ASSERT_NO_EARLY_EXPORT
|
2016-09-28 15:58:24 +02:00
|
|
|
NM_EXPORTED_OBJECT_GET_PRIVATE (NM_EXPORTED_OBJECT (object))->_constructed = TRUE;
|
2015-11-04 14:44:29 +01:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
klass = NM_EXPORTED_OBJECT_GET_CLASS (object);
|
|
|
|
|
|
|
|
|
|
if (klass->export_on_construction)
|
|
|
|
|
nm_exported_object_export ((NMExportedObject *) object);
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-13 13:31:42 -04:00
|
|
|
static void
|
2016-09-29 13:49:01 +02:00
|
|
|
dispose (GObject *object)
|
2015-04-13 13:31:42 -04:00
|
|
|
{
|
2017-01-24 18:50:38 +01:00
|
|
|
NMExportedObject *self = NM_EXPORTED_OBJECT (object);
|
|
|
|
|
NMExportedObjectPrivate *priv = NM_EXPORTED_OBJECT_GET_PRIVATE (self);
|
2015-04-13 13:31:42 -04:00
|
|
|
|
2015-07-23 10:03:21 -05:00
|
|
|
/* Objects should have already been unexported by their owner, unless
|
|
|
|
|
* we are quitting, where many objects stick around until exit.
|
|
|
|
|
*/
|
|
|
|
|
if (!quitting) {
|
|
|
|
|
if (priv->path) {
|
|
|
|
|
g_warn_if_reached ();
|
2017-01-25 13:45:20 +01:00
|
|
|
nm_exported_object_unexport (self);
|
2015-07-23 10:03:21 -05:00
|
|
|
}
|
2017-01-24 18:50:38 +01:00
|
|
|
} else if (nm_clear_g_free (&priv->path))
|
|
|
|
|
_notify (self, PROP_PATH);
|
2015-04-03 10:08:52 -04:00
|
|
|
|
2015-04-13 13:31:42 -04:00
|
|
|
nm_clear_g_source (&priv->notify_idle_id);
|
|
|
|
|
|
2015-04-15 14:53:30 -04:00
|
|
|
G_OBJECT_CLASS (nm_exported_object_parent_class)->dispose (object);
|
2015-04-13 13:31:42 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
nm_exported_object_class_init (NMExportedObjectClass *klass)
|
|
|
|
|
{
|
|
|
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
|
|
|
|
|
|
g_type_class_add_private (object_class, sizeof (NMExportedObjectPrivate));
|
|
|
|
|
|
2015-11-04 14:44:29 +01:00
|
|
|
object_class->constructed = constructed;
|
2015-04-15 14:53:30 -04:00
|
|
|
object_class->notify = nm_exported_object_notify;
|
2016-09-29 13:49:01 +02:00
|
|
|
object_class->dispose = dispose;
|
2017-01-25 13:45:20 +01:00
|
|
|
object_class->get_property = get_property;
|
2017-01-24 18:50:38 +01:00
|
|
|
|
|
|
|
|
obj_properties[PROP_PATH] =
|
|
|
|
|
g_param_spec_string (NM_EXPORTED_OBJECT_PATH, "", "",
|
|
|
|
|
NULL,
|
|
|
|
|
G_PARAM_READABLE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
|
|
|
|
|
|
|
|
|
g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
|
2015-04-13 13:31:42 -04:00
|
|
|
}
|