core/dbus: merge branch 'dcbw/gdbus-object-manager' (early part)

https://bugzilla.gnome.org/show_bug.cgi?id=753566
This commit is contained in:
Thomas Haller 2015-11-10 18:17:42 +01:00
commit af10948e87
16 changed files with 521 additions and 219 deletions

View file

@ -441,8 +441,7 @@ act_stage3_ip4_config_start (NMDevice *device,
_LOGW (LOGD_ADSL, "PPP failed to start: %s", err->message);
g_error_free (err);
g_object_unref (priv->ppp_manager);
priv->ppp_manager = NULL;
nm_exported_object_clear_and_unexport (&priv->ppp_manager);
*reason = NM_DEVICE_STATE_REASON_PPP_START_FAILED;
}
@ -456,10 +455,7 @@ deactivate (NMDevice *device)
NMDeviceAdsl *self = NM_DEVICE_ADSL (device);
NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self);
if (priv->ppp_manager) {
g_object_unref (priv->ppp_manager);
priv->ppp_manager = NULL;
}
nm_exported_object_clear_and_unexport (&priv->ppp_manager);
g_signal_handlers_disconnect_by_func (nm_platform_get (), G_CALLBACK (link_changed_cb), device);

View file

@ -1010,8 +1010,7 @@ pppoe_stage3_ip4_config_start (NMDeviceEthernet *self, NMDeviceStateReason *reas
_LOGW (LOGD_DEVICE, "PPPoE failed to start: %s", err->message);
g_error_free (err);
g_object_unref (priv->ppp_manager);
priv->ppp_manager = NULL;
nm_exported_object_clear_and_unexport (&priv->ppp_manager);
*reason = NM_DEVICE_STATE_REASON_PPP_START_FAILED;
}
@ -1399,10 +1398,7 @@ deactivate (NMDevice *device)
priv->pending_ip4_config = NULL;
}
if (priv->ppp_manager) {
g_object_unref (priv->ppp_manager);
priv->ppp_manager = NULL;
}
nm_exported_object_clear_and_unexport (&priv->ppp_manager);
supplicant_interface_release (self);

View file

@ -3581,7 +3581,7 @@ dhcp4_cleanup (NMDevice *self, CleanupType cleanup_type, gboolean release)
}
if (priv->dhcp4_config) {
g_clear_object (&priv->dhcp4_config);
nm_exported_object_clear_and_unexport (&priv->dhcp4_config);
g_object_notify (G_OBJECT (self), NM_DEVICE_DHCP4_CONFIG);
}
}
@ -3938,8 +3938,7 @@ dhcp4_start (NMDevice *self,
s_ip4 = nm_connection_get_setting_ip4_config (connection);
/* Clear old exported DHCP options */
if (priv->dhcp4_config)
g_object_unref (priv->dhcp4_config);
nm_exported_object_clear_and_unexport (&priv->dhcp4_config);
priv->dhcp4_config = nm_dhcp4_config_new ();
hw_addr = nm_platform_link_get_address (NM_PLATFORM_GET, nm_device_get_ip_ifindex (self), &hw_addr_len);
@ -4275,7 +4274,7 @@ dhcp6_cleanup (NMDevice *self, CleanupType cleanup_type, gboolean release)
nm_device_remove_pending_action (self, PENDING_ACTION_DHCP6, FALSE);
if (priv->dhcp6_config) {
g_clear_object (&priv->dhcp6_config);
nm_exported_object_clear_and_unexport (&priv->dhcp6_config);
g_object_notify (G_OBJECT (self), NM_DEVICE_DHCP6_CONFIG);
}
}
@ -4700,7 +4699,7 @@ dhcp6_start (NMDevice *self, gboolean wait_for_ll, NMDeviceStateReason *reason)
NMConnection *connection;
NMSettingIPConfig *s_ip6;
g_clear_object (&priv->dhcp6_config);
nm_exported_object_clear_and_unexport (&priv->dhcp6_config);
priv->dhcp6_config = nm_dhcp6_config_new ();
g_warn_if_fail (priv->dhcp6_ip6_config == NULL);
@ -6864,8 +6863,8 @@ nm_device_set_ip4_config (NMDevice *self,
g_object_notify (G_OBJECT (self), NM_DEVICE_IP4_CONFIG);
g_signal_emit (self, signals[IP4_CONFIG_CHANGED], 0, priv->ip4_config, old_config);
if (old_config != priv->ip4_config && old_config)
g_object_unref (old_config);
if (old_config != priv->ip4_config)
nm_exported_object_clear_and_unexport (&old_config);
if (nm_device_uses_generated_assumed_connection (self)) {
NMConnection *connection = nm_device_get_applied_connection (self);
@ -7031,8 +7030,8 @@ nm_device_set_ip6_config (NMDevice *self,
g_object_notify (G_OBJECT (self), NM_DEVICE_IP6_CONFIG);
g_signal_emit (self, signals[IP6_CONFIG_CHANGED], 0, priv->ip6_config, old_config);
if (old_config != priv->ip6_config && old_config)
g_object_unref (old_config);
if (old_config != priv->ip6_config)
nm_exported_object_clear_and_unexport (&old_config);
if (nm_device_uses_generated_assumed_connection (self)) {
NMConnection *connection = nm_device_get_applied_connection (self);

View file

@ -162,10 +162,10 @@ static void supplicant_iface_notify_current_bss (NMSupplicantInterface *iface,
static void request_wireless_scan (NMDeviceWifi *self, GVariant *scan_options);
static void emit_ap_added_removed (NMDeviceWifi *self,
guint signum,
NMAccessPoint *ap,
gboolean recheck_available_connections);
static void ap_add_remove (NMDeviceWifi *self,
guint signum,
NMAccessPoint *ap,
gboolean recheck_available_connections);
static void remove_supplicant_interface_error_handler (NMDeviceWifi *self);
@ -358,12 +358,8 @@ set_current_ap (NMDeviceWifi *self, NMAccessPoint *new_ap, gboolean recheck_avai
if (old_ap) {
NM80211Mode mode = nm_ap_get_mode (old_ap);
if (force_remove_old_ap || mode == NM_802_11_MODE_ADHOC || mode == NM_802_11_MODE_AP || nm_ap_get_fake (old_ap)) {
emit_ap_added_removed (self, ACCESS_POINT_REMOVED, old_ap, FALSE);
g_hash_table_remove (priv->aps, nm_exported_object_get_path (NM_EXPORTED_OBJECT (old_ap)));
if (recheck_available_connections)
nm_device_recheck_available_connections (NM_DEVICE (self));
}
if (force_remove_old_ap || mode == NM_802_11_MODE_ADHOC || mode == NM_802_11_MODE_AP || nm_ap_get_fake (old_ap))
ap_add_remove (self, ACCESS_POINT_REMOVED, old_ap, recheck_available_connections);
g_object_unref (old_ap);
}
@ -442,13 +438,30 @@ bring_up (NMDevice *device, gboolean *no_firmware)
}
static void
emit_ap_added_removed (NMDeviceWifi *self,
guint signum,
NMAccessPoint *ap,
gboolean recheck_available_connections)
ap_add_remove (NMDeviceWifi *self,
guint signum,
NMAccessPoint *ap,
gboolean recheck_available_connections)
{
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
nm_assert (NM_IN_SET (signum, ACCESS_POINT_ADDED, ACCESS_POINT_REMOVED));
if (signum == ACCESS_POINT_ADDED) {
g_hash_table_insert (priv->aps,
(gpointer) nm_exported_object_export ((NMExportedObject *) ap),
g_object_ref (ap));
}
g_signal_emit (self, signals[signum], 0, ap);
g_object_notify (G_OBJECT (self), NM_DEVICE_WIFI_ACCESS_POINTS);
if (signum == ACCESS_POINT_REMOVED) {
g_hash_table_remove (priv->aps, nm_exported_object_get_path ((NMExportedObject *) ap));
nm_exported_object_unexport ((NMExportedObject *) ap);
g_object_unref (ap);
}
nm_device_emit_recheck_auto_activate (NM_DEVICE (self));
if (recheck_available_connections)
nm_device_recheck_available_connections (NM_DEVICE (self));
@ -461,16 +474,19 @@ remove_all_aps (NMDeviceWifi *self)
GHashTableIter iter;
NMAccessPoint *ap;
if (g_hash_table_size (priv->aps)) {
set_current_ap (self, NULL, FALSE, FALSE);
if (!g_hash_table_size (priv->aps))
return;
g_hash_table_iter_init (&iter, priv->aps);
while (g_hash_table_iter_next (&iter, NULL, (gpointer) &ap)) {
emit_ap_added_removed (self, ACCESS_POINT_REMOVED, ap, FALSE);
g_hash_table_iter_remove (&iter);
}
nm_device_recheck_available_connections (NM_DEVICE (self));
set_current_ap (self, NULL, FALSE, FALSE);
again:
g_hash_table_iter_init (&iter, priv->aps);
if (g_hash_table_iter_next (&iter, NULL, (gpointer) &ap)) {
ap_add_remove (self, ACCESS_POINT_REMOVED, ap, FALSE);
goto again;
}
nm_device_recheck_available_connections (NM_DEVICE (self));
}
static void
@ -1520,7 +1536,7 @@ supplicant_iface_new_bss_cb (NMSupplicantInterface *iface,
NMAccessPoint *ap;
NMAccessPoint *found_ap = NULL;
const GByteArray *ssid;
const char *bssid, *ap_path;
const char *bssid;
g_return_if_fail (self != NULL);
g_return_if_fail (properties != NULL);
@ -1564,9 +1580,7 @@ supplicant_iface_new_bss_cb (NMSupplicantInterface *iface,
nm_ap_update_from_properties (found_ap, object_path, properties);
} else {
nm_ap_dump (ap, "added ", nm_device_get_iface (NM_DEVICE (self)));
ap_path = nm_exported_object_export (NM_EXPORTED_OBJECT (ap));
g_hash_table_insert (priv->aps, (gpointer) ap_path, g_object_ref (ap));
emit_ap_added_removed (self, ACCESS_POINT_ADDED, ap, TRUE);
ap_add_remove (self, ACCESS_POINT_ADDED, ap, TRUE);
}
g_object_unref (ap);
@ -1629,8 +1643,7 @@ supplicant_iface_bss_removed_cb (NMSupplicantInterface *iface,
nm_ap_set_fake (ap, TRUE);
} else {
nm_ap_dump (ap, "removed ", nm_device_get_iface (NM_DEVICE (self)));
emit_ap_added_removed (self, ACCESS_POINT_REMOVED, ap, TRUE);
g_hash_table_remove (priv->aps, nm_exported_object_get_path (NM_EXPORTED_OBJECT (ap)));
ap_add_remove (self, ACCESS_POINT_REMOVED, ap, TRUE);
schedule_ap_list_dump (self);
}
}
@ -2343,13 +2356,12 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason)
if (nm_ap_is_hotspot (ap))
nm_ap_set_address (ap, nm_device_get_hw_address (device));
ap_path = nm_exported_object_export (NM_EXPORTED_OBJECT (ap));
g_hash_table_insert (priv->aps, (gpointer) ap_path, ap);
g_object_freeze_notify (G_OBJECT (self));
set_current_ap (self, ap, FALSE, FALSE);
emit_ap_added_removed (self, ACCESS_POINT_ADDED, ap, TRUE);
ap_add_remove (self, ACCESS_POINT_ADDED, ap, TRUE);
g_object_thaw_notify (G_OBJECT (self));
nm_active_connection_set_specific_object (NM_ACTIVE_CONNECTION (req), ap_path);
set_current_ap (self, ap, FALSE, FALSE);
nm_active_connection_set_specific_object (NM_ACTIVE_CONNECTION (req),
nm_exported_object_get_path (NM_EXPORTED_OBJECT (ap)));
return NM_ACT_STAGE_RETURN_SUCCESS;
done:
@ -2885,7 +2897,7 @@ nm_device_wifi_init (NMDeviceWifi *self)
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
priv->mode = NM_802_11_MODE_INFRA;
priv->aps = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
priv->aps = g_hash_table_new (g_direct_hash, g_direct_equal);
}
static void
@ -2912,7 +2924,12 @@ dispose (GObject *object)
static void
finalize (GObject *object)
{
g_clear_pointer (&NM_DEVICE_WIFI_GET_PRIVATE (object)->aps, g_hash_table_unref);
NMDeviceWifi *self = NM_DEVICE_WIFI (object);
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
nm_assert (g_hash_table_size (priv->aps) == 0);
g_hash_table_unref (priv->aps);
G_OBJECT_CLASS (nm_device_wifi_parent_class)->finalize (object);
}

View file

@ -530,8 +530,7 @@ ppp_stage3_ip_config_start (NMModem *self,
error && error->message ? error->message : "(unknown)");
g_error_free (error);
g_object_unref (priv->ppp_manager);
priv->ppp_manager = NULL;
nm_exported_object_clear_and_unexport (&priv->ppp_manager);
*reason = NM_DEVICE_STATE_REASON_PPP_START_FAILED;
ret = NM_ACT_STAGE_RETURN_FAILURE;
@ -885,10 +884,7 @@ deactivate_cleanup (NMModem *self, NMDevice *device)
priv->in_bytes = priv->out_bytes = 0;
if (priv->ppp_manager) {
g_object_unref (priv->ppp_manager);
priv->ppp_manager = NULL;
}
nm_exported_object_clear_and_unexport (&priv->ppp_manager);
if (device) {
g_return_if_fail (NM_IS_DEVICE (device));

View file

@ -50,6 +50,7 @@
#include "nm-settings.h"
#include "nm-auth-manager.h"
#include "nm-core-internal.h"
#include "nm-exported-object.h"
#if !defined(NM_DIST_VERSION)
# define NM_DIST_VERSION VERSION
@ -454,6 +455,8 @@ main (int argc, char *argv[])
if (configure_and_quit == FALSE)
g_main_loop_run (main_loop);
nm_exported_object_class_set_quitting ();
nm_manager_stop (nm_manager_get ());
done:

View file

@ -104,8 +104,6 @@ nm_dhcp4_config_init (NMDhcp4Config *self)
{
NMDhcp4ConfigPrivate *priv = NM_DHCP4_CONFIG_GET_PRIVATE (self);
nm_exported_object_export (NM_EXPORTED_OBJECT (self));
priv->options = g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0);
g_variant_ref_sink (priv->options);
}
@ -145,6 +143,7 @@ nm_dhcp4_config_class_init (NMDhcp4ConfigClass *config_class)
g_type_class_add_private (config_class, sizeof (NMDhcp4ConfigPrivate));
exported_object_class->export_path = NM_DBUS_PATH "/DHCP4Config/%u";
exported_object_class->export_on_construction = TRUE;
/* virtual methods */
object_class->get_property = get_property;

View file

@ -104,8 +104,6 @@ nm_dhcp6_config_init (NMDhcp6Config *self)
{
NMDhcp6ConfigPrivate *priv = NM_DHCP6_CONFIG_GET_PRIVATE (self);
nm_exported_object_export (NM_EXPORTED_OBJECT (self));
priv->options = g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0);
g_variant_ref_sink (priv->options);
}
@ -145,6 +143,7 @@ nm_dhcp6_config_class_init (NMDhcp6ConfigClass *config_class)
g_type_class_add_private (config_class, sizeof (NMDhcp6ConfigPrivate));
exported_object_class->export_path = NM_DBUS_PATH "/DHCP6Config/%u";
exported_object_class->export_on_construction = TRUE;
/* virtual methods */
object_class->get_property = get_property;

View file

@ -28,6 +28,12 @@
#include "nm-default.h"
static GHashTable *prefix_counters;
static gboolean quitting = FALSE;
#if NM_MORE_ASSERTS >= 2
#define _ASSERT_NO_EARLY_EXPORT
#endif
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (NMExportedObject, nm_exported_object, G_TYPE_OBJECT,
prefix_counters = g_hash_table_new (g_str_hash, g_str_equal);
@ -41,16 +47,14 @@ typedef struct {
GVariantBuilder pending_notifies;
guint notify_idle_id;
#ifdef _ASSERT_NO_EARLY_EXPORT
gboolean _constructed;
#endif
} NMExportedObjectPrivate;
#define NM_EXPORTED_OBJECT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_EXPORTED_OBJECT, NMExportedObjectPrivate))
typedef struct {
GType dbus_skeleton_type;
char *method_name;
GCallback impl;
} NMExportedObjectDBusMethodImpl;
typedef struct {
GHashTable *properties;
GSList *skeleton_types;
@ -61,8 +65,8 @@ GQuark nm_exported_object_class_info_quark (void);
G_DEFINE_QUARK (NMExportedObjectClassInfo, nm_exported_object_class_info)
/* "AddConnectionUnsaved" -> "handle-add-connection-unsaved" */
static char *
skeletonify_method_name (const char *dbus_method_name)
char *
nm_exported_object_skeletonify_method_name (const char *dbus_method_name)
{
GString *out;
const char *p;
@ -255,7 +259,7 @@ nm_exported_object_class_add_interface (NMExportedObjectClass *object_class,
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;
method.method_name = skeletonify_method_name (method_name);
method.method_name = nm_exported_object_skeletonify_method_name (method_name);
g_assert (g_signal_lookup (method.method_name, dbus_skeleton_type) != 0);
method.impl = impl;
@ -361,81 +365,128 @@ typedef struct {
gulong *method_signals;
} SkeletonData;
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;
}
static void
nm_exported_object_create_skeletons (NMExportedObject *self,
GType object_type)
{
NMExportedObjectPrivate *priv = NM_EXPORTED_OBJECT_GET_PRIVATE (self);
GObjectClass *object_class = g_type_class_peek (object_type);
NMExportedObjectPrivate *priv;
GObjectClass *object_class;
NMExportedObjectClassInfo *classinfo;
GSList *iter;
GDBusInterfaceSkeleton *interface;
guint n_properties;
int i;
const NMExportedObjectDBusMethodImpl *methods;
guint methods_len;
classinfo = g_type_get_qdata (object_type, nm_exported_object_class_info_quark ());
if (!classinfo)
return;
for (iter = classinfo->skeleton_types; iter; iter = iter->next) {
GType dbus_skeleton_type = GPOINTER_TO_SIZE (iter->data);
gs_free GParamSpec **properties = NULL;
SkeletonData *skeleton_data;
guint j;
object_class = g_type_class_peek (object_type);
priv = NM_EXPORTED_OBJECT_GET_PRIVATE (self);
interface = G_DBUS_INTERFACE_SKELETON (g_object_new (dbus_skeleton_type, NULL));
methods = classinfo->methods->len ? &g_array_index (classinfo->methods, NMExportedObjectDBusMethodImpl, 0) : NULL;
methods_len = classinfo->methods->len;
for (iter = classinfo->skeleton_types; iter; iter = iter->next) {
interface = nm_exported_object_skeleton_create (GPOINTER_TO_SIZE (iter->data),
object_class,
methods,
methods_len,
(GObject *) self);
priv->interfaces = g_slist_prepend (priv->interfaces, interface);
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 (self, 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, classinfo->methods->len + 1);
for (i = 0, j = 0; i < classinfo->methods->len; i++) {
NMExportedObjectDBusMethodImpl *method = &g_array_index (classinfo->methods, NMExportedObjectDBusMethodImpl, i);
GClosure *closure;
gulong method_signal;
if (method->dbus_skeleton_type != dbus_skeleton_type)
continue;
closure = g_cclosure_new_swap (method->impl, self, 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);
}
}
void
nm_exported_object_skeleton_release (GDBusInterfaceSkeleton *interface)
{
SkeletonData *skeleton_data;
guint j;
g_return_if_fail (G_IS_DBUS_INTERFACE_SKELETON (interface));
skeleton_data = g_object_steal_qdata ((GObject *) interface, _skeleton_data_quark ());
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]);
g_free (skeleton_data->prop_bindings);
g_free (skeleton_data->method_signals);
g_slice_free (SkeletonData, skeleton_data);
g_object_unref (interface);
}
static void
nm_exported_object_destroy_skeletons (NMExportedObject *self)
{
@ -444,22 +495,10 @@ nm_exported_object_destroy_skeletons (NMExportedObject *self)
g_return_if_fail (priv->interfaces);
while (priv->interfaces) {
gs_unref_object GDBusInterfaceSkeleton *interface = G_DBUS_INTERFACE_SKELETON (priv->interfaces->data);
SkeletonData *skeleton_data;
guint j;
GDBusInterfaceSkeleton *interface = priv->interfaces->data;
priv->interfaces = g_slist_remove (priv->interfaces, interface);
skeleton_data = g_object_steal_qdata ((GObject *) interface, _skeleton_data_quark ());
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]);
g_free (skeleton_data->prop_bindings);
g_free (skeleton_data->method_signals);
g_slice_free (SkeletonData, skeleton_data);
priv->interfaces = g_slist_delete_link (priv->interfaces, priv->interfaces);
nm_exported_object_skeleton_release (interface);
}
}
@ -488,7 +527,11 @@ nm_exported_object_export (NMExportedObject *self)
priv = NM_EXPORTED_OBJECT_GET_PRIVATE (self);
g_return_val_if_fail (!priv->path, priv->path);
g_return_val_if_fail (!priv->bus_mgr, NULL);
g_return_val_if_fail (!priv->bus_mgr, priv->path);
#ifdef _ASSERT_NO_EARLY_EXPORT
nm_assert (priv->_constructed);
#endif
class_export_path = NM_EXPORTED_OBJECT_GET_CLASS (self)->export_path;
p = strchr (class_export_path, '%');
@ -620,6 +663,28 @@ nm_exported_object_get_interface_by_type (NMExportedObject *self, GType interfac
return NULL;
}
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);
}
static void
nm_exported_object_init (NMExportedObject *self)
{
@ -731,13 +796,38 @@ nm_exported_object_notify (GObject *object, GParamSpec *pspec)
priv->notify_idle_id = g_idle_add (idle_emit_properties_changed, object);
}
static void
constructed (GObject *object)
{
NMExportedObjectClass *klass;
G_OBJECT_CLASS (nm_exported_object_parent_class)->constructed (object);
#ifdef _ASSERT_NO_EARLY_EXPORT
NM_EXPORTED_OBJECT_GET_PRIVATE (object)->_constructed = TRUE;
#endif
klass = NM_EXPORTED_OBJECT_GET_CLASS (object);
if (klass->export_on_construction)
nm_exported_object_export ((NMExportedObject *) object);
}
static void
nm_exported_object_dispose (GObject *object)
{
NMExportedObjectPrivate *priv = NM_EXPORTED_OBJECT_GET_PRIVATE (object);
if (priv->path)
nm_exported_object_unexport (NM_EXPORTED_OBJECT (object));
/* 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 ();
nm_exported_object_unexport (NM_EXPORTED_OBJECT (object));
}
} else
g_clear_pointer (&priv->path, g_free);
g_variant_builder_clear (&priv->pending_notifies);
nm_clear_g_source (&priv->notify_idle_id);
@ -752,6 +842,14 @@ nm_exported_object_class_init (NMExportedObjectClass *klass)
g_type_class_add_private (object_class, sizeof (NMExportedObjectPrivate));
object_class->constructed = constructed;
object_class->notify = nm_exported_object_notify;
object_class->dispose = nm_exported_object_dispose;
}
void
nm_exported_object_class_set_quitting (void)
{
quitting = TRUE;
}

View file

@ -25,6 +25,25 @@
G_BEGIN_DECLS
/*****************************************************************************/
char *nm_exported_object_skeletonify_method_name (const char *dbus_method_name);
typedef struct {
GType dbus_skeleton_type;
char *method_name;
GCallback impl;
} NMExportedObjectDBusMethodImpl;
GDBusInterfaceSkeleton *nm_exported_object_skeleton_create (GType dbus_skeleton_type,
GObjectClass *object_class,
const NMExportedObjectDBusMethodImpl *methods,
guint methods_len,
GObject *target);
void nm_exported_object_skeleton_release (GDBusInterfaceSkeleton *interface);
/*****************************************************************************/
#define NM_TYPE_EXPORTED_OBJECT (nm_exported_object_get_type ())
#define NM_EXPORTED_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_EXPORTED_OBJECT, NMExportedObject))
#define NM_EXPORTED_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_EXPORTED_OBJECT, NMExportedObjectClass))
@ -40,10 +59,13 @@ typedef struct {
GObjectClass parent;
const char *export_path;
char export_on_construction;
} NMExportedObjectClass;
GType nm_exported_object_get_type (void);
void nm_exported_object_class_set_quitting (void);
void nm_exported_object_class_add_interface (NMExportedObjectClass *object_class,
GType dbus_skeleton_type,
...) G_GNUC_NULL_TERMINATED;
@ -55,6 +77,9 @@ void nm_exported_object_unexport (NMExportedObject *self);
GSList * nm_exported_object_get_interfaces (NMExportedObject *self);
GDBusInterfaceSkeleton *nm_exported_object_get_interface_by_type (NMExportedObject *self, GType interface_type);
void _nm_exported_object_clear_and_unexport (NMExportedObject **location);
#define nm_exported_object_clear_and_unexport(location) _nm_exported_object_clear_and_unexport ((NMExportedObject **) (location))
G_END_DECLS
#endif /* NM_EXPORTED_OBJECT_H */

View file

@ -225,7 +225,7 @@ active_connection_remove (NMManager *self, NMActiveConnection *active)
else
connection = NULL;
g_object_unref (active);
nm_exported_object_clear_and_unexport (&active);
if ( connection
&& nm_settings_has_connection (priv->settings, connection)) {
@ -801,8 +801,7 @@ remove_device (NMManager *manager,
g_object_notify (G_OBJECT (manager), NM_MANAGER_DEVICES);
nm_device_removed (device);
nm_exported_object_unexport (NM_EXPORTED_OBJECT (device));
g_object_unref (device);
nm_exported_object_clear_and_unexport (&device);
check_if_startup_complete (manager);
}

View file

@ -2053,14 +2053,7 @@ nm_settings_connection_signal_remove (NMSettingsConnection *self)
if (priv->removed)
g_return_if_reached ();
priv->removed = TRUE;
/* Emit removed first */
g_signal_emit_by_name (self, NM_SETTINGS_CONNECTION_REMOVED);
/* And unregister last to ensure the removed signal goes out before
* we take the connection off the bus.
*/
nm_exported_object_unexport (NM_EXPORTED_OBJECT (self));
}
gboolean

View file

@ -905,6 +905,8 @@ connection_removed (NMSettingsConnection *connection, gpointer user_data)
/* Re-emit for listeners like NMPolicy */
g_signal_emit_by_name (self, NM_CP_SIGNAL_CONNECTION_REMOVED, connection);
g_object_notify (G_OBJECT (self), NM_SETTINGS_CONNECTIONS);
if (nm_exported_object_is_exported (NM_EXPORTED_OBJECT (connection)))
nm_exported_object_unexport (NM_EXPORTED_OBJECT (connection));
check_startup_complete (self);

View file

@ -50,6 +50,7 @@
#include "writer.h"
#include "utils.h"
#include "nm-dbus-compat.h"
#include "nm-exported-object.h"
#include "nmdbus-ifcfg-rh.h"
@ -78,14 +79,23 @@ static NMIfcfgConnection *update_connection (SettingsPluginIfcfg *plugin,
static void settings_plugin_interface_init (NMSettingsPluginInterface *plugin_iface);
G_DEFINE_TYPE_EXTENDED (SettingsPluginIfcfg, settings_plugin_ifcfg, NM_TYPE_EXPORTED_OBJECT, 0,
G_IMPLEMENT_INTERFACE (NM_TYPE_SETTINGS_PLUGIN,
settings_plugin_interface_init))
G_DEFINE_TYPE_EXTENDED (SettingsPluginIfcfg, settings_plugin_ifcfg, G_TYPE_OBJECT, 0,
G_IMPLEMENT_INTERFACE (NM_TYPE_SETTINGS_PLUGIN,
settings_plugin_interface_init))
#define SETTINGS_PLUGIN_IFCFG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SETTINGS_TYPE_PLUGIN_IFCFG, SettingsPluginIfcfgPrivate))
typedef struct {
NMConfig *config;
struct {
GDBusConnection *connection;
GDBusInterfaceSkeleton *interface;
GCancellable *cancellable;
guint signal_id;
} dbus;
GHashTable *connections; /* uuid::connection */
gboolean initialized;
@ -725,7 +735,7 @@ impl_ifcfgrh_get_ifcfg_details (SettingsPluginIfcfg *plugin,
"unable to get the UUID");
return;
}
path = nm_connection_get_path (NM_CONNECTION (connection));
if (!path) {
g_dbus_method_invocation_return_error (context,
@ -739,6 +749,202 @@ impl_ifcfgrh_get_ifcfg_details (SettingsPluginIfcfg *plugin,
g_variant_new ("(so)", uuid, path));
}
/*****************************************************************************/
static void
_dbus_clear (SettingsPluginIfcfg *self)
{
SettingsPluginIfcfgPrivate *priv = SETTINGS_PLUGIN_IFCFG_GET_PRIVATE (self);
nm_clear_g_signal_handler (priv->dbus.connection, &priv->dbus.signal_id);
nm_clear_g_cancellable (&priv->dbus.cancellable);
if (priv->dbus.interface) {
g_dbus_interface_skeleton_unexport (priv->dbus.interface);
nm_exported_object_skeleton_release (priv->dbus.interface);
priv->dbus.interface = NULL;
}
g_clear_object (&priv->dbus.connection);
}
static void
_dbus_connection_closed (GDBusConnection *connection,
gboolean remote_peer_vanished,
GError *error,
gpointer user_data)
{
_LOGW ("dbus: %s bus closed", IFCFGRH1_DBUS_SERVICE_NAME);
_dbus_clear (SETTINGS_PLUGIN_IFCFG (user_data));
/* Retry or recover? */
}
static void
_dbus_request_name_done (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
GDBusConnection *connection = G_DBUS_CONNECTION (source_object);
SettingsPluginIfcfg *self;
SettingsPluginIfcfgPrivate *priv;
gs_free_error GError *error = NULL;
gs_unref_variant GVariant *ret = NULL;
guint32 result;
ret = g_dbus_connection_call_finish (connection, res, &error);
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return;
self = SETTINGS_PLUGIN_IFCFG (user_data);
priv = SETTINGS_PLUGIN_IFCFG_GET_PRIVATE (self);
g_clear_object (&priv->dbus.cancellable);
if (!ret) {
_LOGW ("dbus: couldn't acquire D-Bus service: %s", error->message);
_dbus_clear (self);
return;
}
g_variant_get (ret, "(u)", &result);
if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
_LOGW ("dbus: couldn't acquire ifcfgrh1 D-Bus service (already taken)");
_dbus_clear (self);
return;
}
{
GType skeleton_type = NMDBUS_TYPE_IFCFGRH1_SKELETON;
gs_free char *method_name_get_ifcfg_details = NULL;
NMExportedObjectDBusMethodImpl methods[] = {
{
.method_name = (method_name_get_ifcfg_details = nm_exported_object_skeletonify_method_name ("GetIfcfgDetails")),
.impl = G_CALLBACK (impl_ifcfgrh_get_ifcfg_details),
},
};
priv->dbus.interface = nm_exported_object_skeleton_create (skeleton_type,
g_type_class_peek (SETTINGS_TYPE_PLUGIN_IFCFG),
methods,
G_N_ELEMENTS (methods),
(GObject *) self);
if (!g_dbus_interface_skeleton_export (priv->dbus.interface,
priv->dbus.connection,
IFCFGRH1_DBUS_OBJECT_PATH,
&error)) {
nm_exported_object_skeleton_release (priv->dbus.interface);
priv->dbus.interface = NULL;
_LOGW ("dbus: failed exporting interface: %s", error->message);
_dbus_clear (self);
return;
}
}
_LOGD ("dbus: aquired D-Bus service %s and exported %s object",
IFCFGRH1_DBUS_SERVICE_NAME,
IFCFGRH1_DBUS_OBJECT_PATH);
}
static void
_dbus_create_done (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
SettingsPluginIfcfg *self;
SettingsPluginIfcfgPrivate *priv;
gs_free_error GError *error = NULL;
GDBusConnection *connection;
connection = g_dbus_connection_new_for_address_finish (res, &error);
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return;
self = SETTINGS_PLUGIN_IFCFG (user_data);
priv = SETTINGS_PLUGIN_IFCFG_GET_PRIVATE (self);
g_clear_object (&priv->dbus.cancellable);
if (!connection) {
_LOGW ("dbus: couldn't initialize system bus: %s", error->message);
return;
}
priv->dbus.connection = connection;
priv->dbus.cancellable = g_cancellable_new ();
priv->dbus.signal_id = g_signal_connect (priv->dbus.connection,
"closed",
G_CALLBACK (_dbus_connection_closed),
self);
g_dbus_connection_call (priv->dbus.connection,
DBUS_SERVICE_DBUS,
DBUS_PATH_DBUS,
DBUS_INTERFACE_DBUS,
"RequestName",
g_variant_new ("(su)",
IFCFGRH1_DBUS_SERVICE_NAME,
DBUS_NAME_FLAG_DO_NOT_QUEUE),
G_VARIANT_TYPE ("(u)"),
G_DBUS_CALL_FLAGS_NONE,
-1,
priv->dbus.cancellable,
_dbus_request_name_done,
self);
}
static void
_dbus_setup (SettingsPluginIfcfg *self)
{
SettingsPluginIfcfgPrivate *priv = SETTINGS_PLUGIN_IFCFG_GET_PRIVATE (self);
gs_free char *address = NULL;
gs_free_error GError *error = NULL;
g_return_if_fail (!priv->dbus.connection);
address = g_dbus_address_get_for_bus_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
if (address == NULL) {
_LOGW ("dbus: failed getting address for system bus: %s", error->message);
return;
}
priv->dbus.cancellable = g_cancellable_new ();
g_dbus_connection_new_for_address (address,
G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT
| G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
NULL,
priv->dbus.cancellable,
_dbus_create_done,
self);
}
static void
config_changed_cb (NMConfig *config,
NMConfigData *config_data,
NMConfigChangeFlags changes,
NMConfigData *old_data,
SettingsPluginIfcfg *self)
{
/* If the dbus connection for some reason is borked the D-Bus service
* won't be offered.
*
* On SIGHUP and SIGUSR1 try to re-connect to D-Bus. So in the unlikely
* event that the D-Bus conneciton is broken, that allows for recovery
* without need for restarting NetworkManager. */
if ( NM_FLAGS_HAS (changes, NM_CONFIG_CHANGE_SIGHUP)
|| NM_FLAGS_HAS (changes, NM_CONFIG_CHANGE_SIGUSR1)) {
if (!SETTINGS_PLUGIN_IFCFG_GET_PRIVATE (self)->dbus.connection)
_dbus_setup (self);
}
}
/*****************************************************************************/
static void
init (NMSettingsPlugin *config)
{
@ -756,51 +962,33 @@ static void
constructed (GObject *object)
{
SettingsPluginIfcfg *self = SETTINGS_PLUGIN_IFCFG (object);
GError *error = NULL;
GDBusConnection *bus;
GVariant *ret;
guint32 result;
SettingsPluginIfcfgPrivate *priv = SETTINGS_PLUGIN_IFCFG_GET_PRIVATE (self);
bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
if (!bus) {
_LOGW ("Couldn't connect to D-Bus: %s", error->message);
g_clear_error (&error);
return;
}
G_OBJECT_CLASS (settings_plugin_ifcfg_parent_class)->constructed (object);
ret = g_dbus_connection_call_sync (bus,
DBUS_SERVICE_DBUS,
DBUS_PATH_DBUS,
DBUS_INTERFACE_DBUS,
"RequestName",
g_variant_new ("(su)",
IFCFGRH1_DBUS_SERVICE_NAME,
DBUS_NAME_FLAG_DO_NOT_QUEUE),
G_VARIANT_TYPE ("(u)"),
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL, &error);
g_object_unref (bus);
if (ret) {
g_variant_get (ret, "(u)", &result);
g_variant_unref (ret);
priv->config = nm_config_get ();
g_object_add_weak_pointer ((GObject *) priv->config, (gpointer *) &priv->config);
g_signal_connect (priv->config,
NM_CONFIG_SIGNAL_CONFIG_CHANGED,
G_CALLBACK (config_changed_cb),
self);
if (result == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
nm_exported_object_export (NM_EXPORTED_OBJECT (self));
_LOGD ("Acquired D-Bus service %s", IFCFGRH1_DBUS_SERVICE_NAME);
} else
_LOGW ("Couldn't acquire ifcfgrh1 D-Bus service (already taken)");
} else {
_LOGW ("Couldn't acquire D-Bus service: %s", error->message);
g_clear_error (&error);
}
_dbus_setup (self);
}
static void
dispose (GObject *object)
{
SettingsPluginIfcfg *plugin = SETTINGS_PLUGIN_IFCFG (object);
SettingsPluginIfcfgPrivate *priv = SETTINGS_PLUGIN_IFCFG_GET_PRIVATE (plugin);
SettingsPluginIfcfg *self = SETTINGS_PLUGIN_IFCFG (object);
SettingsPluginIfcfgPrivate *priv = SETTINGS_PLUGIN_IFCFG_GET_PRIVATE (self);
if (priv->config) {
g_object_remove_weak_pointer ((GObject *) priv->config, (gpointer *) &priv->config);
g_signal_handlers_disconnect_by_func (priv->config, config_changed_cb, self);
priv->config = NULL;
}
_dbus_clear (self);
if (priv->connections) {
g_hash_table_destroy (priv->connections);
@ -853,12 +1041,9 @@ static void
settings_plugin_ifcfg_class_init (SettingsPluginIfcfgClass *req_class)
{
GObjectClass *object_class = G_OBJECT_CLASS (req_class);
NMExportedObjectClass *exported_object_class = NM_EXPORTED_OBJECT_CLASS (req_class);
g_type_class_add_private (req_class, sizeof (SettingsPluginIfcfgPrivate));
exported_object_class->export_path = IFCFGRH1_DBUS_OBJECT_PATH;
object_class->constructed = constructed;
object_class->dispose = dispose;
object_class->get_property = get_property;
@ -875,11 +1060,6 @@ settings_plugin_ifcfg_class_init (SettingsPluginIfcfgClass *req_class)
g_object_class_override_property (object_class,
NM_SETTINGS_PLUGIN_PROP_CAPABILITIES,
NM_SETTINGS_PLUGIN_CAPABILITIES);
nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (req_class),
NMDBUS_TYPE_IFCFGRH1_SKELETON,
"GetIfcfgDetails", impl_ifcfgrh_get_ifcfg_details,
NULL);
}
static void

View file

@ -37,11 +37,11 @@ typedef struct _SettingsPluginIfcfg SettingsPluginIfcfg;
typedef struct _SettingsPluginIfcfgClass SettingsPluginIfcfgClass;
struct _SettingsPluginIfcfg {
NMExportedObject parent;
GObject parent;
};
struct _SettingsPluginIfcfgClass {
NMExportedObjectClass parent;
GObjectClass parent;
};
GType settings_plugin_ifcfg_get_type (void);

View file

@ -1117,8 +1117,8 @@ _cleanup_failed_config (NMVpnConnection *self)
{
NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (self);
g_clear_object (&priv->ip4_config);
g_clear_object (&priv->ip6_config);
nm_exported_object_clear_and_unexport (&priv->ip4_config);
nm_exported_object_clear_and_unexport (&priv->ip6_config);
_LOGW ("VPN connection: did not receive valid IP config information");
_set_vpn_state (self, STATE_FAILED, NM_VPN_CONNECTION_STATE_REASON_IP_CONFIG_INVALID, FALSE);
@ -1316,12 +1316,12 @@ nm_vpn_connection_config_get (NMVpnConnection *self, GVariant *dict)
priv->has_ip4 = FALSE;
if (g_variant_lookup (dict, NM_VPN_PLUGIN_CONFIG_HAS_IP4, "b", &b))
priv->has_ip4 = b;
g_clear_object (&priv->ip4_config);
nm_exported_object_clear_and_unexport (&priv->ip4_config);
priv->has_ip6 = FALSE;
if (g_variant_lookup (dict, NM_VPN_PLUGIN_CONFIG_HAS_IP6, "b", &b))
priv->has_ip6 = b;
g_clear_object (&priv->ip6_config);
nm_exported_object_clear_and_unexport (&priv->ip6_config);
}
guint32
@ -1491,7 +1491,7 @@ nm_vpn_connection_ip4_config_get (NMVpnConnection *self, GVariant *dict)
nm_connection_get_setting_ip4_config (_get_applied_connection (self)),
route_metric);
g_clear_object (&priv->ip4_config);
nm_exported_object_clear_and_unexport (&priv->ip4_config);
priv->ip4_config = config;
nm_exported_object_export (NM_EXPORTED_OBJECT (config));
g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_IP4_CONFIG);
@ -1626,7 +1626,7 @@ next:
nm_connection_get_setting_ip6_config (_get_applied_connection (self)),
route_metric);
g_clear_object (&priv->ip6_config);
nm_exported_object_clear_and_unexport (&priv->ip6_config);
priv->ip6_config = config;
nm_exported_object_export (NM_EXPORTED_OBJECT (config));
g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_IP6_CONFIG);
@ -2444,8 +2444,8 @@ dispose (GObject *object)
g_cancellable_cancel (priv->cancellable);
g_clear_object (&priv->cancellable);
}
g_clear_object (&priv->ip4_config);
g_clear_object (&priv->ip6_config);
nm_exported_object_clear_and_unexport (&priv->ip4_config);
nm_exported_object_clear_and_unexport (&priv->ip6_config);
g_clear_object (&priv->proxy);
g_clear_object (&priv->plugin_info);