diff options
60 files changed, 7074 insertions, 6914 deletions
diff --git a/Makefile.am b/Makefile.am index dde8a7b03c..718355071b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1240,15 +1240,17 @@ libnm_lib_h_priv = \ libnm/nm-dns-manager.h \ libnm/nm-ip4-config.h \ libnm/nm-ip6-config.h \ - libnm/nm-manager.h \ libnm/nm-object-private.h \ libnm/nm-remote-connection-private.h \ - libnm/nm-remote-settings.h + $(NULL) libnm_lib_c_real = \ - libnm/nm-access-point.c \ + libnm/nm-client.c \ + libnm/nm-object.c \ + libnm/nm-device.c \ libnm/nm-active-connection.c \ + \ + libnm/nm-access-point.c \ libnm/nm-checkpoint.c \ - libnm/nm-client.c \ libnm/nm-dbus-helpers.c \ libnm/nm-device-6lowpan.c \ libnm/nm-device-adsl.c \ @@ -1277,7 +1279,6 @@ libnm_lib_c_real = \ libnm/nm-device-wimax.c \ libnm/nm-device-wireguard.c \ libnm/nm-device-wpan.c \ - libnm/nm-device.c \ libnm/nm-dhcp-config.c \ libnm/nm-dhcp4-config.c \ libnm/nm-dhcp6-config.c \ @@ -1286,10 +1287,7 @@ libnm_lib_c_real = \ libnm/nm-ip4-config.c \ libnm/nm-ip6-config.c \ libnm/nm-libnm-utils.c \ - libnm/nm-manager.c \ - libnm/nm-object.c \ libnm/nm-remote-connection.c \ - libnm/nm-remote-settings.c \ libnm/nm-secret-agent-old.c \ libnm/nm-vpn-connection.c \ libnm/nm-vpn-editor.c \ @@ -23,6 +23,9 @@ USE AT YOUR OWN RISK. NOT RECOMMENDED FOR PRODUCTION USE! * libnm: retire deprecated WiMAX API NMDeviceWimax and NMWimaxNsp. WiMAX support was removed from NetworkManager in version 1.2 (2016) and no such type instances would have been created by NMClient for a while now. +* libnm: heavily internal rework NMClient. This slims down libnm and makes the + implementation more efficient. NMClient should work now well with a separate + GMainContext. ============================================= NetworkManager-1.20 diff --git a/docs/libnm/Makefile.am b/docs/libnm/Makefile.am index 20dc8de571..ce82d7eb94 100644 --- a/docs/libnm/Makefile.am +++ b/docs/libnm/Makefile.am @@ -49,7 +49,6 @@ IGNORE_HFILES= \ nm-object-private.h \ nm-property-compare.h \ nm-remote-connection-private.h \ - nm-remote-settings.h \ nm-setting-private.h \ nm-utils-private.h \ nm-core-tests-enum-types.h \ diff --git a/docs/libnm/meson.build b/docs/libnm/meson.build index 43a13f498a..6cf0e04028 100644 --- a/docs/libnm/meson.build +++ b/docs/libnm/meson.build @@ -20,7 +20,6 @@ private_headers = [ 'nm-object-private.h', 'nm-property-compare.h', 'nm-remote-connection-private.h', - 'nm-remote-settings.h', 'nm-setting-private.h', 'nm-utils-private.h', 'nm-core-tests-enum-types.h', diff --git a/libnm/libnm.ver b/libnm/libnm.ver index 30cf605c42..ed08865c97 100644 --- a/libnm/libnm.ver +++ b/libnm/libnm.ver @@ -1638,6 +1638,7 @@ libnm_1_22_0 { global: nm_client_get_dbus_connection; nm_client_get_dbus_name_owner; + nm_client_get_metered; nm_client_reload; nm_client_reload_finish; nm_manager_reload_flags_get_type; diff --git a/libnm/meson.build b/libnm/meson.build index 8b68a63679..51ca46d2bc 100644 --- a/libnm/meson.build +++ b/libnm/meson.build @@ -119,10 +119,8 @@ libnm_sources = files( 'nm-ip4-config.c', 'nm-ip6-config.c', 'nm-libnm-utils.c', - 'nm-manager.c', 'nm-object.c', 'nm-remote-connection.c', - 'nm-remote-settings.c', 'nm-secret-agent-old.c', 'nm-vpn-connection.c', 'nm-vpn-editor.c', diff --git a/libnm/nm-access-point.c b/libnm/nm-access-point.c index d21bb60acc..77ba65274c 100644 --- a/libnm/nm-access-point.c +++ b/libnm/nm-access-point.c @@ -19,7 +19,7 @@ /*****************************************************************************/ -NM_GOBJECT_PROPERTIES_DEFINE_BASE ( +NM_GOBJECT_PROPERTIES_DEFINE (NMAccessPoint, PROP_FLAGS, PROP_WPA_FLAGS, PROP_RSN_FLAGS, @@ -34,16 +34,16 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( ); typedef struct { - NM80211ApFlags flags; - NM80211ApSecurityFlags wpa_flags; - NM80211ApSecurityFlags rsn_flags; GBytes *ssid; - guint32 frequency; char *bssid; - NM80211Mode mode; + guint32 flags; + guint32 wpa_flags; + guint32 rsn_flags; + guint32 frequency; + guint32 mode; guint32 max_bitrate; + gint32 last_seen; guint8 strength; - int last_seen; } NMAccessPointPrivate; struct _NMAccessPoint { @@ -127,9 +127,7 @@ nm_access_point_get_ssid (NMAccessPoint *ap) g_return_val_if_fail (NM_IS_ACCESS_POINT (ap), NULL); priv = NM_ACCESS_POINT_GET_PRIVATE (ap); - if (!priv->ssid || g_bytes_get_size (priv->ssid) == 0) - return NULL; - + nm_assert (!priv->ssid || g_bytes_get_size (priv->ssid) > 0); return priv->ssid; } @@ -263,6 +261,9 @@ nm_access_point_connection_valid (NMAccessPoint *ap, NMConnection *connection) const char *setting_band; guint32 ap_freq, setting_chan, ap_chan; + g_return_val_if_fail (NM_IS_ACCESS_POINT (ap), FALSE); + g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE); + s_con = nm_connection_get_setting_connection (connection); if (!s_con) return FALSE; @@ -368,7 +369,12 @@ GPtrArray * nm_access_point_filter_connections (NMAccessPoint *ap, const GPtrArray *connections) { GPtrArray *filtered; - int i; + guint i; + + g_return_val_if_fail (NM_IS_ACCESS_POINT (ap), NULL); + + if (!connections) + return NULL; filtered = g_ptr_array_new_with_free_func (g_object_unref); for (i = 0; i < connections->len; i++) { @@ -383,6 +389,24 @@ nm_access_point_filter_connections (NMAccessPoint *ap, const GPtrArray *connecti /*****************************************************************************/ +static NMLDBusNotifyUpdatePropFlags +_notify_update_prop_hw_address (NMClient *client, + NMLDBusObject *dbobj, + const NMLDBusMetaIface *meta_iface, + guint dbus_property_idx, + GVariant *value) +{ + NMAccessPoint *self = NM_ACCESS_POINT (dbobj->nmobj); + NMAccessPointPrivate *priv = NM_ACCESS_POINT_GET_PRIVATE (self); + + g_free (priv->bssid); + priv->bssid = value ? g_variant_dup_string (value, NULL) : 0u; + _notify (self, PROP_HW_ADDRESS); + return NML_DBUS_NOTIFY_UPDATE_PROP_FLAGS_NOTIFY; +} + +/*****************************************************************************/ + static void nm_access_point_init (NMAccessPoint *ap) { @@ -396,7 +420,6 @@ finalize (GObject *object) if (priv->ssid) g_bytes_unref (priv->ssid); - g_free (priv->bssid); G_OBJECT_CLASS (nm_access_point_parent_class)->finalize (object); @@ -450,43 +473,32 @@ get_property (GObject *object, } } -static void -init_dbus (NMObject *object) -{ - NMAccessPointPrivate *priv = NM_ACCESS_POINT_GET_PRIVATE (object); - const NMPropertiesInfo property_info[] = { - { NM_ACCESS_POINT_FLAGS, &priv->flags }, - { NM_ACCESS_POINT_WPA_FLAGS, &priv->wpa_flags }, - { NM_ACCESS_POINT_RSN_FLAGS, &priv->rsn_flags }, - { NM_ACCESS_POINT_SSID, &priv->ssid }, - { NM_ACCESS_POINT_FREQUENCY, &priv->frequency }, - /* The D-Bus property is HwAddress, but the GObject property is "bssid" */ - { NM_ACCESS_POINT_HW_ADDRESS, &priv->bssid }, - { NM_ACCESS_POINT_MODE, &priv->mode }, - { NM_ACCESS_POINT_MAX_BITRATE, &priv->max_bitrate }, - { NM_ACCESS_POINT_STRENGTH, &priv->strength }, - { NM_ACCESS_POINT_LAST_SEEN, &priv->last_seen }, - { NULL }, - }; - - NM_OBJECT_CLASS (nm_access_point_parent_class)->init_dbus (object); - - _nm_object_register_properties (object, - NM_DBUS_INTERFACE_ACCESS_POINT, - property_info); -} +const NMLDBusMetaIface _nml_dbus_meta_iface_nm_accesspoint = NML_DBUS_META_IFACE_INIT_PROP ( + NM_DBUS_INTERFACE_ACCESS_POINT, + nm_access_point_get_type, + NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, + NML_DBUS_META_IFACE_DBUS_PROPERTIES ( + NML_DBUS_META_PROPERTY_INIT_U ("Flags", PROP_FLAGS, NMAccessPoint, _priv.flags ), + NML_DBUS_META_PROPERTY_INIT_U ("Frequency", PROP_FREQUENCY, NMAccessPoint, _priv.frequency ), + NML_DBUS_META_PROPERTY_INIT_FCN ("HwAddress", PROP_BSSID, "s", _notify_update_prop_hw_address ), + NML_DBUS_META_PROPERTY_INIT_I ("LastSeen", PROP_LAST_SEEN, NMAccessPoint, _priv.last_seen ), + NML_DBUS_META_PROPERTY_INIT_U ("MaxBitrate", PROP_MAX_BITRATE, NMAccessPoint, _priv.max_bitrate ), + NML_DBUS_META_PROPERTY_INIT_U ("Mode", PROP_MODE, NMAccessPoint, _priv.mode ), + NML_DBUS_META_PROPERTY_INIT_U ("RsnFlags", PROP_RSN_FLAGS, NMAccessPoint, _priv.rsn_flags ), + NML_DBUS_META_PROPERTY_INIT_AY ("Ssid", PROP_SSID, NMAccessPoint, _priv.ssid ), + NML_DBUS_META_PROPERTY_INIT_Y ("Strength", PROP_STRENGTH, NMAccessPoint, _priv.strength ), + NML_DBUS_META_PROPERTY_INIT_U ("WpaFlags", PROP_WPA_FLAGS, NMAccessPoint, _priv.wpa_flags ), + ), +); static void nm_access_point_class_init (NMAccessPointClass *ap_class) { GObjectClass *object_class = G_OBJECT_CLASS (ap_class); - NMObjectClass *nm_object_class = NM_OBJECT_CLASS (ap_class); object_class->get_property = get_property; object_class->finalize = finalize; - nm_object_class->init_dbus = init_dbus; - /** * NMAccessPoint:flags: * @@ -620,5 +632,5 @@ nm_access_point_class_init (NMAccessPointClass *ap_class) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + _nml_dbus_meta_class_init_with_properties (object_class, &_nml_dbus_meta_iface_nm_accesspoint); } diff --git a/libnm/nm-active-connection.c b/libnm/nm-active-connection.c index 6b49f9a5e0..aa8504e61d 100644 --- a/libnm/nm-active-connection.c +++ b/libnm/nm-active-connection.c @@ -21,8 +21,6 @@ #include "nm-ip6-config.h" #include "nm-remote-connection.h" -#include "introspection/org.freedesktop.NetworkManager.Connection.Active.h" - /*****************************************************************************/ NM_GOBJECT_PROPERTIES_DEFINE (NMActiveConnection, @@ -50,26 +48,34 @@ enum { LAST_SIGNAL }; -static guint signals[LAST_SIGNAL] = { 0 }; +static guint signals[LAST_SIGNAL]; + +enum { + PROPERTY_O_IDX_CONNECTION, + PROPERTY_O_IDX_MASTER, + PROPERTY_O_IDX_IP4_CONFIG, + PROPERTY_O_IDX_IP6_CONFIG, + PROPERTY_O_IDX_DHCP4_CONFIG, + PROPERTY_O_IDX_DHCP6_CONFIG, + _PROPERTY_O_IDX_NUM, +}; typedef struct _NMActiveConnectionPrivate { - NMRemoteConnection *connection; + NMLDBusPropertyO property_o[_PROPERTY_O_IDX_NUM]; + NMLDBusPropertyAO devices; + NMRefString *specific_object_path; char *id; char *uuid; char *type; - char *specific_object_path; - GPtrArray *devices; - NMActiveConnectionState state; - guint state_flags; - gboolean is_default; - NMIPConfig *ip4_config; - NMDhcpConfig *dhcp4_config; - gboolean is_default6; - NMIPConfig *ip6_config; - NMDhcpConfig *dhcp6_config; - gboolean is_vpn; - NMDevice *master; - NMActiveConnectionStateReason reason; + + guint32 state; + guint32 state_flags; + + bool is_default; + bool is_default6; + bool is_vpn; + + guint32 reason; } NMActiveConnectionPrivate; G_DEFINE_TYPE (NMActiveConnection, nm_active_connection, NM_TYPE_OBJECT); @@ -92,7 +98,7 @@ nm_active_connection_get_connection (NMActiveConnection *connection) { g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (connection), NULL); - return NM_ACTIVE_CONNECTION_GET_PRIVATE (connection)->connection; + return nml_dbus_property_o_get_obj (&NM_ACTIVE_CONNECTION_GET_PRIVATE (connection)->property_o[PROPERTY_O_IDX_CONNECTION]); } /** @@ -166,7 +172,7 @@ nm_active_connection_get_specific_object_path (NMActiveConnection *connection) { g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (connection), NULL); - return NM_ACTIVE_CONNECTION_GET_PRIVATE (connection)->specific_object_path; + return _nml_coerce_property_object_path (NM_ACTIVE_CONNECTION_GET_PRIVATE (connection)->specific_object_path); } /** @@ -183,7 +189,7 @@ nm_active_connection_get_devices (NMActiveConnection *connection) { g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (connection), NULL); - return NM_ACTIVE_CONNECTION_GET_PRIVATE (connection)->devices; + return nml_dbus_property_ao_get_objs_as_ptrarray (&NM_ACTIVE_CONNECTION_GET_PRIVATE (connection)->devices); } /** @@ -269,7 +275,7 @@ nm_active_connection_get_ip4_config (NMActiveConnection *connection) { g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (connection), NULL); - return NM_ACTIVE_CONNECTION_GET_PRIVATE (connection)->ip4_config; + return nml_dbus_property_o_get_obj (&NM_ACTIVE_CONNECTION_GET_PRIVATE (connection)->property_o[PROPERTY_O_IDX_IP4_CONFIG]); } /** @@ -288,7 +294,7 @@ nm_active_connection_get_dhcp4_config (NMActiveConnection *connection) { g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (connection), NULL); - return NM_ACTIVE_CONNECTION_GET_PRIVATE (connection)->dhcp4_config; + return nml_dbus_property_o_get_obj (&NM_ACTIVE_CONNECTION_GET_PRIVATE (connection)->property_o[PROPERTY_O_IDX_DHCP4_CONFIG]); } /** @@ -322,7 +328,7 @@ nm_active_connection_get_ip6_config (NMActiveConnection *connection) { g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (connection), NULL); - return NM_ACTIVE_CONNECTION_GET_PRIVATE (connection)->ip6_config; + return nml_dbus_property_o_get_obj (&NM_ACTIVE_CONNECTION_GET_PRIVATE (connection)->property_o[PROPERTY_O_IDX_IP6_CONFIG]); } /** @@ -341,7 +347,7 @@ nm_active_connection_get_dhcp6_config (NMActiveConnection *connection) { g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (connection), NULL); - return NM_ACTIVE_CONNECTION_GET_PRIVATE (connection)->dhcp6_config; + return nml_dbus_property_o_get_obj (&NM_ACTIVE_CONNECTION_GET_PRIVATE (connection)->property_o[PROPERTY_O_IDX_DHCP6_CONFIG]); } /** @@ -373,71 +379,63 @@ nm_active_connection_get_master (NMActiveConnection *connection) { g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (connection), NULL); - return NM_ACTIVE_CONNECTION_GET_PRIVATE (connection)->master; + return nml_dbus_property_o_get_obj (&NM_ACTIVE_CONNECTION_GET_PRIVATE (connection)->property_o[PROPERTY_O_IDX_MASTER]); } +/*****************************************************************************/ + static void -nm_active_connection_init (NMActiveConnection *self) +_notify_event_state_changed (NMClient *client, + NMClientNotifyEventWithPtr *notify_event) { - NMActiveConnectionPrivate *priv; - - priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NM_TYPE_ACTIVE_CONNECTION, NMActiveConnectionPrivate); - - self->_priv = priv; - - priv->devices = g_ptr_array_new (); + gs_unref_object NMActiveConnection *self = notify_event->user_data; + NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self); + + /* we expose here the value cache in @priv. In practice, this is the same + * value as we received from the signal. In the unexpected case where they + * differ, the cached value of the current instance would still be more correct. */ + g_signal_emit (self, + signals[STATE_CHANGED], + 0, + (guint) priv->state, + (guint) priv->reason); } -static void -state_changed_proxy (NMDBusActiveConnectionProxy *proxy, - NMActiveConnectionState state, - NMActiveConnectionStateReason reason, - gpointer user_data) +void +_nm_active_connection_state_changed_commit (NMActiveConnection *self, + guint32 state, + guint32 reason) { - NMActiveConnection *connection = NM_ACTIVE_CONNECTION (user_data); - NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (connection); + NMClient *client; + NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self); - priv->state = state; - priv->reason = reason; - g_signal_emit (connection, signals[STATE_CHANGED], 0, state, reason); - _notify (connection, PROP_STATE); -} + client = _nm_object_get_client (self); -static void -constructed (GObject *object) -{ - GDBusProxy *proxy; + if (priv->state != state) { + priv->state = state; + _nm_client_queue_notify_object (client, + self, + obj_properties[PROP_STATE]); + } - proxy = _nm_object_get_proxy (NM_OBJECT (object), NM_DBUS_INTERFACE_ACTIVE_CONNECTION); - g_signal_connect (proxy, "state-changed", - G_CALLBACK (state_changed_proxy), object); - g_object_unref (proxy); + priv->reason = reason; - G_OBJECT_CLASS (nm_active_connection_parent_class)->constructed (object); + _nm_client_notify_event_queue_with_ptr (client, + NM_CLIENT_NOTIFY_EVENT_PRIO_GPROP + 1, + _notify_event_state_changed, + g_object_ref (self)); } +/*****************************************************************************/ + static void -dispose (GObject *object) +nm_active_connection_init (NMActiveConnection *self) { - NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (object); - GDBusProxy *proxy; - - g_clear_pointer (&priv->devices, g_ptr_array_unref); - - g_clear_object (&priv->connection); - g_clear_object (&priv->master); - g_clear_object (&priv->ip4_config); - g_clear_object (&priv->dhcp4_config); - g_clear_object (&priv->ip6_config); - g_clear_object (&priv->dhcp6_config); + NMActiveConnectionPrivate *priv; - proxy = _nm_object_get_proxy (NM_OBJECT (object), NM_DBUS_INTERFACE_ACTIVE_CONNECTION); - if (proxy) { - g_signal_handlers_disconnect_by_data (proxy, object); - g_object_unref (proxy); - } + priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NM_TYPE_ACTIVE_CONNECTION, NMActiveConnectionPrivate); - G_OBJECT_CLASS (nm_active_connection_parent_class)->dispose (object); + self->_priv = priv; } static void @@ -448,7 +446,7 @@ finalize (GObject *object) g_free (priv->id); g_free (priv->uuid); g_free (priv->type); - g_free (priv->specific_object_path); + nm_ref_string_unref (priv->specific_object_path); G_OBJECT_CLASS (nm_active_connection_parent_class)->finalize (object); } @@ -516,73 +514,46 @@ get_property (GObject *object, } } -static gboolean -demarshal_specific_object_path (NMObject *object, GParamSpec *pspec, GVariant *value, gpointer field) -{ - const char *v; - char **param = (char **) field; - - /* We have to demarshal this manually, because the D-Bus property name - * ("SpecificObject"), doesn't match the object property name - * ("specific-object-path"). (The name "specific-object" is reserved for - * future use as an NMObject-valued property.) - */ - if (!g_variant_is_of_type (value, G_VARIANT_TYPE_OBJECT_PATH)) - return FALSE; - - v = g_variant_get_string (value, NULL); - - g_free (*param); - *param = nm_streq0 (v, "/") ? NULL : g_strdup (v); - return TRUE; -} - -static void -init_dbus (NMObject *object) -{ - NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (object); - const NMPropertiesInfo property_info[] = { - { NM_ACTIVE_CONNECTION_CONNECTION, &priv->connection, NULL, NM_TYPE_REMOTE_CONNECTION }, - { NM_ACTIVE_CONNECTION_ID, &priv->id }, - { NM_ACTIVE_CONNECTION_UUID, &priv->uuid }, - { NM_ACTIVE_CONNECTION_TYPE, &priv->type }, - { "specific-object", &priv->specific_object_path, demarshal_specific_object_path }, - { NM_ACTIVE_CONNECTION_DEVICES, &priv->devices, NULL, NM_TYPE_DEVICE }, - { NM_ACTIVE_CONNECTION_STATE, &priv->state }, - { NM_ACTIVE_CONNECTION_STATE_FLAGS, &priv->state_flags }, - { NM_ACTIVE_CONNECTION_DEFAULT, &priv->is_default }, - { NM_ACTIVE_CONNECTION_IP4_CONFIG, &priv->ip4_config, NULL, NM_TYPE_IP4_CONFIG }, - { NM_ACTIVE_CONNECTION_DHCP4_CONFIG, &priv->dhcp4_config, NULL, NM_TYPE_DHCP4_CONFIG }, - { NM_ACTIVE_CONNECTION_DEFAULT6, &priv->is_default6 }, - { NM_ACTIVE_CONNECTION_IP6_CONFIG, &priv->ip6_config, NULL, NM_TYPE_IP6_CONFIG }, - { NM_ACTIVE_CONNECTION_DHCP6_CONFIG, &priv->dhcp6_config, NULL, NM_TYPE_DHCP6_CONFIG }, - { NM_ACTIVE_CONNECTION_VPN, &priv->is_vpn }, - { NM_ACTIVE_CONNECTION_MASTER, &priv->master, NULL, NM_TYPE_DEVICE }, - - { NULL }, - }; - - NM_OBJECT_CLASS (nm_active_connection_parent_class)->init_dbus (object); - - _nm_object_register_properties (object, - NM_DBUS_INTERFACE_ACTIVE_CONNECTION, - property_info); -} +const NMLDBusMetaIface _nml_dbus_meta_iface_nm_connection_active = NML_DBUS_META_IFACE_INIT_PROP ( + NM_DBUS_INTERFACE_ACTIVE_CONNECTION, + nm_active_connection_get_type, + NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_LOW, + NML_DBUS_META_IFACE_DBUS_PROPERTIES ( + NML_DBUS_META_PROPERTY_INIT_O_PROP ("Connection", PROP_CONNECTION, NMActiveConnectionPrivate, property_o[PROPERTY_O_IDX_CONNECTION], nm_remote_connection_get_type ), + NML_DBUS_META_PROPERTY_INIT_B ("Default", PROP_DEFAULT, NMActiveConnectionPrivate, is_default ), + NML_DBUS_META_PROPERTY_INIT_B ("Default6", PROP_DEFAULT6, NMActiveConnectionPrivate, is_default6 ), + NML_DBUS_META_PROPERTY_INIT_AO_PROP ("Devices", PROP_DEVICES, NMActiveConnectionPrivate, devices, nm_device_get_type ), + NML_DBUS_META_PROPERTY_INIT_O_PROP ("Dhcp4Config", PROP_DHCP4_CONFIG, NMActiveConnectionPrivate, property_o[PROPERTY_O_IDX_DHCP4_CONFIG], nm_dhcp4_config_get_type ), + NML_DBUS_META_PROPERTY_INIT_O_PROP ("Dhcp6Config", PROP_DHCP6_CONFIG, NMActiveConnectionPrivate, property_o[PROPERTY_O_IDX_DHCP6_CONFIG], nm_dhcp6_config_get_type ), + NML_DBUS_META_PROPERTY_INIT_S ("Id", PROP_ID, NMActiveConnectionPrivate, id ), + NML_DBUS_META_PROPERTY_INIT_O_PROP ("Ip4Config", PROP_IP4_CONFIG, NMActiveConnectionPrivate, property_o[PROPERTY_O_IDX_IP4_CONFIG], nm_ip4_config_get_type ), + NML_DBUS_META_PROPERTY_INIT_O_PROP ("Ip6Config", PROP_IP6_CONFIG, NMActiveConnectionPrivate, property_o[PROPERTY_O_IDX_IP6_CONFIG], nm_ip6_config_get_type ), + NML_DBUS_META_PROPERTY_INIT_O_PROP ("Master", PROP_MASTER, NMActiveConnectionPrivate, property_o[PROPERTY_O_IDX_MASTER], nm_device_get_type ), + NML_DBUS_META_PROPERTY_INIT_O ("SpecificObject", PROP_SPECIFIC_OBJECT_PATH, NMActiveConnectionPrivate, specific_object_path ), + NML_DBUS_META_PROPERTY_INIT_U ("State", PROP_STATE, NMActiveConnectionPrivate, state ), + NML_DBUS_META_PROPERTY_INIT_U ("StateFlags", PROP_STATE_FLAGS, NMActiveConnectionPrivate, state_flags ), + NML_DBUS_META_PROPERTY_INIT_S ("Type", PROP_TYPE, NMActiveConnectionPrivate, type ), + NML_DBUS_META_PROPERTY_INIT_S ("Uuid", PROP_UUID, NMActiveConnectionPrivate, uuid ), + NML_DBUS_META_PROPERTY_INIT_B ("Vpn", PROP_VPN, NMActiveConnectionPrivate, is_vpn ), + ), + .base_struct_offset = G_STRUCT_OFFSET (NMActiveConnection, _priv), +); static void -nm_active_connection_class_init (NMActiveConnectionClass *ap_class) +nm_active_connection_class_init (NMActiveConnectionClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (ap_class); - NMObjectClass *nm_object_class = NM_OBJECT_CLASS (ap_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMObjectClass *nm_object_class = NM_OBJECT_CLASS (klass); - g_type_class_add_private (ap_class, sizeof (NMActiveConnectionPrivate)); + g_type_class_add_private (klass, sizeof (NMActiveConnectionPrivate)); object_class->get_property = get_property; - object_class->constructed = constructed; - object_class->dispose = dispose; object_class->finalize = finalize; - nm_object_class->init_dbus = init_dbus; + _NM_OBJECT_CLASS_INIT_PRIV_PTR_INDIRECT (nm_object_class, NMActiveConnection); + + _NM_OBJECT_CLASS_INIT_PROPERTY_O_FIELDS_N (nm_object_class, NMActiveConnectionPrivate, property_o); + _NM_OBJECT_CLASS_INIT_PROPERTY_AO_FIELDS_1 (nm_object_class, NMActiveConnectionPrivate, devices); /** * NMActiveConnection:connection: @@ -765,7 +736,13 @@ nm_active_connection_class_init (NMActiveConnectionClass *ap_class) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + _nml_dbus_meta_class_init_with_properties (object_class, &_nml_dbus_meta_iface_nm_connection_active); + + /* TODO: the state reason should also be exposed as a property in libnm's NMActiveConnection, + * like done for NMDevice's state reason. */ + + /* TODO: the D-Bus API should also expose the state-reason as a property instead of + * a "StateChanged" signal. Like done for Device's "StateReason". */ /** * NMActiveConnection::state-changed: diff --git a/libnm/nm-checkpoint.c b/libnm/nm-checkpoint.c index d029d6db84..89d4aa8dcb 100644 --- a/libnm/nm-checkpoint.c +++ b/libnm/nm-checkpoint.c @@ -6,6 +6,7 @@ #include "nm-default.h" #include "nm-checkpoint.h" + #include "nm-core-internal.h" #include "nm-dbus-interface.h" #include "nm-device.h" @@ -20,7 +21,7 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( ); typedef struct { - GPtrArray *devices; + NMLDBusPropertyAO devices; gint64 created; guint32 rollback_timeout; } NMCheckpointPrivate; @@ -55,7 +56,7 @@ nm_checkpoint_get_devices (NMCheckpoint *checkpoint) { g_return_val_if_fail (NM_IS_CHECKPOINT (checkpoint), NULL); - return NM_CHECKPOINT_GET_PRIVATE (checkpoint)->devices; + return nml_dbus_property_ao_get_objs_as_ptrarray (&NM_CHECKPOINT_GET_PRIVATE (checkpoint)->devices); } /** @@ -105,16 +106,6 @@ nm_checkpoint_init (NMCheckpoint *checkpoint) } static void -finalize (GObject *object) -{ - NMCheckpointPrivate *priv = NM_CHECKPOINT_GET_PRIVATE (NM_CHECKPOINT (object)); - - g_ptr_array_unref (priv->devices); - - G_OBJECT_CLASS (nm_checkpoint_parent_class)->finalize (object); -} - -static void get_property (GObject *object, guint prop_id, GValue *value, @@ -125,7 +116,7 @@ get_property (GObject *object, switch (prop_id) { case PROP_DEVICES: - g_value_take_boxed (value, _nm_utils_copy_object_array (priv->devices)); + g_value_take_boxed (value, _nm_utils_copy_object_array (nm_checkpoint_get_devices (checkpoint))); break; case PROP_CREATED: g_value_set_int64 (value, priv->created); @@ -139,34 +130,28 @@ get_property (GObject *object, } } -static void -init_dbus (NMObject *object) -{ - NMCheckpointPrivate *priv = NM_CHECKPOINT_GET_PRIVATE (NM_CHECKPOINT (object)); - const NMPropertiesInfo property_info[] = { - { NM_CHECKPOINT_DEVICES, &priv->devices, NULL, NM_TYPE_DEVICE }, - { NM_CHECKPOINT_CREATED, &priv->created }, - { NM_CHECKPOINT_ROLLBACK_TIMEOUT, &priv->rollback_timeout }, - { NULL }, - }; - - NM_OBJECT_CLASS (nm_checkpoint_parent_class)->init_dbus (object); - - _nm_object_register_properties (object, - NM_DBUS_INTERFACE_CHECKPOINT, - property_info); -} +const NMLDBusMetaIface _nml_dbus_meta_iface_nm_checkpoint = NML_DBUS_META_IFACE_INIT_PROP ( + NM_DBUS_INTERFACE_CHECKPOINT, + nm_checkpoint_get_type, + NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, + NML_DBUS_META_IFACE_DBUS_PROPERTIES ( + NML_DBUS_META_PROPERTY_INIT_X ("Created", PROP_CREATED, NMCheckpoint, _priv.created ), + NML_DBUS_META_PROPERTY_INIT_AO_PROP ("Devices", PROP_DEVICES, NMCheckpoint, _priv.devices, nm_device_get_type, .ready_without_visible = TRUE ), + NML_DBUS_META_PROPERTY_INIT_U ("RollbackTimeout", PROP_ROLLBACK_TIMEOUT, NMCheckpoint, _priv.rollback_timeout ), + ), +); static void -nm_checkpoint_class_init (NMCheckpointClass *checkpoint_class) +nm_checkpoint_class_init (NMCheckpointClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (checkpoint_class); - NMObjectClass *nm_object_class = NM_OBJECT_CLASS (checkpoint_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMObjectClass *nm_object_class = NM_OBJECT_CLASS (klass); object_class->get_property = get_property; - object_class->finalize = finalize; - nm_object_class->init_dbus = init_dbus; + _NM_OBJECT_CLASS_INIT_PRIV_PTR_DIRECT (nm_object_class, NMCheckpoint); + + _NM_OBJECT_CLASS_INIT_PROPERTY_AO_FIELDS_1 (nm_object_class, NMCheckpointPrivate, devices); /** * NMCheckpoint:devices: (type GPtrArray(NMDevice)) @@ -207,5 +192,5 @@ nm_checkpoint_class_init (NMCheckpointClass *checkpoint_class) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + _nml_dbus_meta_class_init_with_properties (object_class, &_nml_dbus_meta_iface_nm_checkpoint); } diff --git a/libnm/nm-client.c b/libnm/nm-client.c index 56367eedc1..25b36f238f 100644 --- a/libnm/nm-client.c +++ b/libnm/nm-client.c @@ -10,34 +10,16 @@ #include <libudev.h> +#include "nm-std-aux/c-list-util.h" +#include "nm-glib-aux/nm-c-list.h" #include "nm-glib-aux/nm-dbus-aux.h" -#include "nm-utils.h" -#include "nm-manager.h" -#include "nm-dns-manager.h" -#include "nm-remote-settings.h" -#include "nm-device-ethernet.h" -#include "nm-device-wifi.h" -#include "nm-core-internal.h" -#include "nm-active-connection.h" -#include "nm-vpn-connection.h" -#include "nm-remote-connection.h" -#include "nm-dbus-helpers.h" -#include "nm-wimax-nsp.h" -#include "nm-object-private.h" - -#include "introspection/org.freedesktop.NetworkManager.h" -#include "introspection/org.freedesktop.NetworkManager.Device.Wireless.h" -#include "introspection/org.freedesktop.NetworkManager.Device.WifiP2P.h" -#include "introspection/org.freedesktop.NetworkManager.Device.h" -#include "introspection/org.freedesktop.NetworkManager.DnsManager.h" -#include "introspection/org.freedesktop.NetworkManager.Settings.h" -#include "introspection/org.freedesktop.NetworkManager.Settings.Connection.h" -#include "introspection/org.freedesktop.NetworkManager.VPN.Connection.h" -#include "introspection/org.freedesktop.NetworkManager.Connection.Active.h" +#include "nm-libnm-core-intern/nm-common-macros.h" #include "nm-access-point.h" #include "nm-active-connection.h" #include "nm-checkpoint.h" +#include "nm-core-internal.h" +#include "nm-dbus-helpers.h" #include "nm-device-6lowpan.h" #include "nm-device-adsl.h" #include "nm-device-bond.h" @@ -62,31 +44,90 @@ #include "nm-device-vxlan.h" #include "nm-device-wifi-p2p.h" #include "nm-device-wifi.h" -#include "nm-device-wimax.h" #include "nm-device-wireguard.h" #include "nm-device-wpan.h" #include "nm-dhcp-config.h" #include "nm-dhcp4-config.h" #include "nm-dhcp6-config.h" +#include "nm-dns-manager.h" #include "nm-ip4-config.h" #include "nm-ip6-config.h" -#include "nm-manager.h" -#include "nm-wifi-p2p-peer.h" +#include "nm-object-private.h" #include "nm-remote-connection.h" -#include "nm-remote-settings.h" +#include "nm-utils.h" #include "nm-vpn-connection.h" +#include "nm-wifi-p2p-peer.h" /*****************************************************************************/ -static void nm_client_initable_iface_init (GInitableIface *iface); -static void nm_client_async_initable_iface_init (GAsyncInitableIface *iface); +struct _NMLDBusObjPropData { + + /* It is quite wasteful to require 2 pointers per property (of an instance) only to track whether + * the property got changed. But it's convenient! */ + CList changed_prop_lst; + + GVariant *prop_data_value; +}; + +struct _NMLDBusObjIfaceData { + CList iface_lst; + union { + const NMLDBusMetaIface *meta; + NMRefString *name; + } dbus_iface; + + CList changed_prop_lst_head; + + /* We also keep track of non-well known interfaces. The presence of a D-Bus interface + * is what makes a D-Bus alive or not. As we should track all D-Bus objects, we also + * need to track whether there are any interfaces on it -- even if we otherwise don't + * care about the interface. */ + bool dbus_iface_is_wellknown:1; + + bool nmobj_checked:1; + bool nmobj_compatible:1; + + NMLDBusObjPropData prop_datas[]; +}; + +/* The dbus_path must be the first element, so when we hash the object by the dbus_path, + * we also can lookup the object by only having a NMRefString at hand + * using nm_pdirect_hash()/nm_pdirect_equal(). */ +G_STATIC_ASSERT (G_STRUCT_OFFSET (NMLDBusObject, dbus_path) == 0); + +typedef void (*NMLDBusObjWatchNotifyFcn) (NMClient *client, + gpointer obj_watcher); + +struct _NMLDBusObjWatcher { + NMLDBusObject *dbobj; + struct { + CList watcher_lst; + NMLDBusObjWatchNotifyFcn notify_fcn; + } _priv; +}; + +typedef struct { + NMLDBusObjWatcher parent; + gpointer user_data; +} NMLDBusObjWatcherWithPtr; + +/*****************************************************************************/ typedef struct { - NMClient *client; GCancellable *cancellable; - GSimpleAsyncResult *result; - int pending_init; -} NMClientInitData; + GSource *cancel_on_idle_source; + gulong cancelled_id; + union { + struct { + GTask *task; + } async; + struct { + GMainLoop *main_loop; + GError **error_location; + } sync; + } data; + bool is_sync:1; +} InitData; NM_GOBJECT_PROPERTIES_DEFINE (NMClient, PROP_DBUS_CONNECTION, @@ -104,6 +145,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMClient, PROP_WIMAX_HARDWARE_ENABLED, PROP_ACTIVE_CONNECTIONS, PROP_CONNECTIVITY, + PROP_CONNECTIVITY_CHECK_URI, PROP_CONNECTIVITY_CHECK_AVAILABLE, PROP_CONNECTIVITY_CHECK_ENABLED, PROP_PRIMARY_CONNECTION, @@ -137,27 +179,102 @@ enum { static guint signals[LAST_SIGNAL] = { 0 }; typedef struct { + struct udev *udev; GMainContext *main_context; - NMManager *manager; - NMRemoteSettings *settings; - NMDnsManager *dns_manager; + GMainContext *dbus_context; + GSource *dbus_context_integration; GDBusConnection *dbus_connection; - GDBusObjectManager *object_manager; - GCancellable *new_object_manager_cancellable; - char *name_owner_cached; - struct udev *udev; + InitData *init_data; + GHashTable *dbus_objects; + CList dbus_object_changed_lst_head; + GCancellable *name_owner_get_cancellable; + GCancellable *get_managed_objects_cancellable; + + CList queue_notify_lst_head; + CList notify_event_lst_head; + + CList dbus_objects_lst_head_watched_only; + CList dbus_objects_lst_head_on_dbus; + CList dbus_objects_lst_head_with_nmobj_not_ready; + CList dbus_objects_lst_head_with_nmobj_maybe_ready; + CList dbus_objects_lst_head_with_nmobj_visible; + CList dbus_objects_lst_head_with_nmobj_hidden; + + NMLDBusObject *dbobj_nm; + NMLDBusObject *dbobj_settings; + NMLDBusObject *dbobj_dns_manager; + + GHashTable *permissions; + GCancellable *permissions_cancellable; + + char *name_owner; + guint name_owner_changed_id; + guint dbsid_nm_object_manager; + guint dbsid_dbus_properties_properties_changed; + guint dbsid_nm_settings_connection_updated; + guint dbsid_nm_connection_active_state_changed; + guint dbsid_nm_vpn_connection_state_changed; + guint dbsid_nm_check_permissions; + bool udev_inited:1; + bool notify_event_lst_changed:1; + bool check_dbobj_visible_all:1; + bool nm_running:1; + + struct { + NMLDBusPropertyO activating_connection; + NMLDBusPropertyO primary_connection; + NMLDBusPropertyAO devices; + NMLDBusPropertyAO all_devices; + NMLDBusPropertyAO active_connections; + NMLDBusPropertyAO checkpoints; + char *connectivity_check_uri; + char *version; + guint32 connectivity; + guint32 state; + guint32 metered; + bool connectivity_check_available; + bool connectivity_check_enabled; + bool networking_enabled; + bool startup; + bool wireless_enabled; + bool wireless_hardware_enabled; + bool wwan_enabled; + bool wwan_hardware_enabled; + } nm; + + struct { + NMLDBusPropertyAO connections; + char *hostname; + bool can_modify; + } settings; + + struct { + GPtrArray *configuration; + char *mode; + char *rc_manager; + } dns_manager; + } NMClientPrivate; struct _NMClient { - GObject parent; + union { + GObject parent; + NMObjectBase obj_base; + }; NMClientPrivate _priv; }; struct _NMClientClass { - GObjectClass parent; + union { + GObjectClass parent; + NMObjectBaseClass obj_base; + }; }; +static void nm_client_initable_iface_init (GInitableIface *iface); +static void nm_client_async_initable_iface_init (GAsyncInitableIface *iface); + G_DEFINE_TYPE_WITH_CODE (NMClient, nm_client, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, nm_client_initable_iface_init); G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, nm_client_async_initable_iface_init); @@ -167,11 +284,40 @@ G_DEFINE_TYPE_WITH_CODE (NMClient, nm_client, G_TYPE_OBJECT, /*****************************************************************************/ -void _nm_device_wifi_set_wireless_enabled (NMDeviceWifi *device, gboolean enabled); +static void _init_start_check_complete (NMClient *self); + +static void name_owner_changed_cb (GDBusConnection *connection, + const char *sender_name, + const char *object_path, + const char *interface_name, + const char *signal_name, + GVariant *parameters, + gpointer user_data); + +static void name_owner_get_cb (const char *name_owner, + GError *error, + gpointer user_data); + +static void _set_nm_running (NMClient *self); + +/*****************************************************************************/ + +static NMRefString *_dbus_path_nm = NULL; +static NMRefString *_dbus_path_settings = NULL; +static NMRefString *_dbus_path_dns_manager = NULL; /*****************************************************************************/ -static const GPtrArray empty = { 0, }; +NM_UTILS_LOOKUP_STR_DEFINE_STATIC (nml_dbus_obj_state_to_string, NMLDBusObjState, + NM_UTILS_LOOKUP_DEFAULT_WARN ("???"), + NM_UTILS_LOOKUP_ITEM (NML_DBUS_OBJ_STATE_UNLINKED, "unlinked"), + NM_UTILS_LOOKUP_ITEM (NML_DBUS_OBJ_STATE_WATCHED_ONLY, "watched-only"), + NM_UTILS_LOOKUP_ITEM (NML_DBUS_OBJ_STATE_ON_DBUS, "on-dbus"), + NM_UTILS_LOOKUP_ITEM (NML_DBUS_OBJ_STATE_WITH_NMOBJ_NOT_READY, "not-ready"), + NM_UTILS_LOOKUP_ITEM (NML_DBUS_OBJ_STATE_WITH_NMOBJ_MAYBE_READY, "maybe-ready"), + NM_UTILS_LOOKUP_ITEM (NML_DBUS_OBJ_STATE_WITH_NMOBJ_VISIBLE, "visible"), + NM_UTILS_LOOKUP_ITEM (NML_DBUS_OBJ_STATE_WITH_NMOBJ_HIDDEN, "hidden"), +); /*****************************************************************************/ @@ -186,44 +332,2985 @@ NM_CACHED_QUARK_FCN ("nm-client-error-quark", nm_client_error_quark) /*****************************************************************************/ -GDBusConnection * -_nm_client_get_dbus_connection (NMClient *client) +static InitData * +_init_data_new_sync (GCancellable *cancellable, + GMainLoop *main_loop, + GError **error_location) { - nm_assert (NM_IS_CLIENT (client)); + InitData *init_data; - return NM_CLIENT_GET_PRIVATE (client)->dbus_connection; + init_data = g_slice_new (InitData); + *init_data = (InitData) { + .cancellable = nm_g_object_ref (cancellable), + .is_sync = TRUE, + .data.sync = { + .main_loop = main_loop, + .error_location = error_location, + }, + }; + return init_data; +} + +static InitData * +_init_data_new_async (GCancellable *cancellable, + GTask *task_take) +{ + InitData *init_data; + + init_data = g_slice_new (InitData); + *init_data = (InitData) { + .cancellable = nm_g_object_ref (cancellable), + .is_sync = FALSE, + .data.async = { + .task = g_steal_pointer (&task_take), + }, + }; + return init_data; +} + +/*****************************************************************************/ + +GError * +_nm_client_new_error_nm_not_running (void) +{ + return g_error_new_literal (NM_CLIENT_ERROR, + NM_CLIENT_ERROR_MANAGER_NOT_RUNNING, + "NetworkManager is not running"); +} + +GError * +_nm_client_new_error_nm_not_cached (void) +{ + return g_error_new_literal (NM_CLIENT_ERROR, + NM_CLIENT_ERROR_FAILED, + "Object is no longer in the client cache"); +} + +void +_nm_client_dbus_call_simple (NMClient *self, + GCancellable *cancellable, + const char *object_path, + const char *interface_name, + const char *method_name, + GVariant *parameters, + const GVariantType *reply_type, + GDBusCallFlags flags, + int timeout_msec, + GAsyncReadyCallback callback, + gpointer user_data) +{ + NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self); + nm_auto_pop_gmaincontext GMainContext *dbus_context = NULL; + + nm_assert (priv->name_owner); + nm_assert (!cancellable || G_IS_CANCELLABLE (cancellable)); + nm_assert (callback); + nm_assert (object_path); + nm_assert (interface_name); + nm_assert (method_name); + nm_assert (parameters); + nm_assert (reply_type); + + dbus_context = nm_g_main_context_push_thread_default_if_necessary (priv->dbus_context); + + g_dbus_connection_call (priv->dbus_connection, + priv->name_owner, + object_path, + interface_name, + method_name, + parameters, + reply_type, + flags, + timeout_msec, + cancellable, + callback, + user_data); +} + +void +_nm_client_dbus_call (NMClient *self, + gpointer source_obj, + gpointer source_tag, + GCancellable *cancellable, + GAsyncReadyCallback user_callback, + gpointer user_callback_data, + const char *object_path, + const char *interface_name, + const char *method_name, + GVariant *parameters, + const GVariantType *reply_type, + GDBusCallFlags flags, + int timeout_msec, + GAsyncReadyCallback internal_callback) +{ + NMClientPrivate *priv; + gs_unref_object GTask *task = NULL; + + nm_assert (!source_obj || G_IS_OBJECT (source_obj)); + nm_assert (source_tag); + nm_assert (!cancellable || G_IS_CANCELLABLE (cancellable)); + nm_assert (internal_callback); + nm_assert (object_path); + nm_assert (interface_name); + nm_assert (method_name); + nm_assert (parameters); + nm_assert (reply_type); + + task = nm_g_task_new (source_obj, cancellable, source_tag, user_callback, user_callback_data); + + if (!self) { + nm_g_variant_unref_floating (parameters); + g_task_return_error (task, _nm_client_new_error_nm_not_cached ()); + return; + } + + priv = NM_CLIENT_GET_PRIVATE (self); + if (!priv->name_owner) { + nm_g_variant_unref_floating (parameters); + g_task_return_error (task, _nm_client_new_error_nm_not_running ()); + return; + } + + _nm_client_dbus_call_simple (self, + cancellable, + object_path, + interface_name, + method_name, + parameters, + reply_type, + flags, + timeout_msec, + internal_callback, + g_steal_pointer (&task)); +} + +GVariant * +_nm_client_dbus_call_sync (NMClient *self, + GCancellable *cancellable, + const char *object_path, + const char *interface_name, + const char *method_name, + GVariant *parameters, + const GVariantType *reply_type, + GDBusCallFlags flags, + int timeout_msec, + gboolean strip_dbus_error, + GError **error) +{ + NMClientPrivate *priv; + gs_unref_variant GVariant *ret = NULL; + + nm_assert (!cancellable || G_IS_CANCELLABLE (cancellable)); + nm_assert (!error || !*error); + nm_assert (object_path); + nm_assert (interface_name); + nm_assert (method_name); + nm_assert (parameters); + nm_assert (reply_type); + + if (!self) { + nm_g_variant_unref_floating (parameters); + nm_g_set_error_take_lazy (error, _nm_client_new_error_nm_not_cached ()); + return NULL; + } + + priv = NM_CLIENT_GET_PRIVATE (self); + if (!priv->name_owner) { + nm_g_variant_unref_floating (parameters); + nm_g_set_error_take_lazy (error, _nm_client_new_error_nm_not_running ()); + return NULL; + } + + ret = g_dbus_connection_call_sync (priv->dbus_connection, + priv->name_owner, + object_path, + interface_name, + method_name, + parameters, + reply_type, + flags, + timeout_msec, + cancellable, + error); + if (!ret) { + if (error && strip_dbus_error) + g_dbus_error_strip_remote_error (*error); + return NULL; + } + + return g_steal_pointer (&ret); +} + +gboolean +_nm_client_dbus_call_sync_void (NMClient *self, + GCancellable *cancellable, + const char *object_path, + const char *interface_name, + const char *method_name, + GVariant *parameters, + GDBusCallFlags flags, + int timeout_msec, + gboolean strip_dbus_error, + GError **error) +{ + gs_unref_variant GVariant *ret = NULL; + + ret = _nm_client_dbus_call_sync (self, + cancellable, + object_path, + interface_name, + method_name, + parameters, + G_VARIANT_TYPE ("()"), + flags, + timeout_msec, + strip_dbus_error, + error); + return !!ret; +} + +void +_nm_client_set_property_sync_legacy (NMClient *self, + const char *object_path, + const char *interface_name, + const char *property_name, + const char *format_string, + ...) +{ + NMClientPrivate *priv; + gs_unref_variant GVariant *val = NULL; + gs_unref_variant GVariant *ret = NULL; + va_list ap; + + nm_assert (!self || NM_IS_CLIENT (self)); + nm_assert (interface_name); + nm_assert (property_name); + nm_assert (format_string); + + if (!self) + return; + + priv = NM_CLIENT_GET_PRIVATE (self); + if (!priv->name_owner) + return; + + va_start (ap, format_string); + val = g_variant_new_va (format_string, NULL, &ap); + va_end (ap); + + nm_assert (val); + + /* A synchronous D-Bus call that is not cancellable an ignores the return value. + * This function only exists for backward compatibility. */ + ret = g_dbus_connection_call_sync (priv->dbus_connection, + priv->name_owner, + object_path, + DBUS_INTERFACE_PROPERTIES, + "Set", + g_variant_new ("(ssv)", interface_name, property_name, val), + NULL, + G_DBUS_CALL_FLAGS_NONE, + 2000, + NULL, + NULL); +} + +/*****************************************************************************/ + +#define _assert_main_context_is_current_source(self, x_context) \ + G_STMT_START { \ + if (NM_MORE_ASSERTS > 0) { \ + GSource *_source = g_main_current_source (); \ + \ + if (_source) { \ + NMClientPrivate *_priv = NM_CLIENT_GET_PRIVATE (self); \ + \ + nm_assert (g_source_get_context (_source) == _priv->x_context); \ + nm_assert (g_main_context_is_owner (_priv->x_context)); \ + } \ + } \ + } G_STMT_END + +#define _assert_main_context_is_current_thread_default(self, x_context) \ + G_STMT_START { \ + if (NM_MORE_ASSERTS > 0) { \ + NMClientPrivate *_priv = NM_CLIENT_GET_PRIVATE (self); \ + \ + nm_assert ((g_main_context_get_thread_default () ?: g_main_context_default ()) == _priv->x_context); \ + nm_assert (g_main_context_is_owner (_priv->x_context)); \ + } \ + } G_STMT_END + +/*****************************************************************************/ + +void +_nm_client_queue_notify_object (NMClient *self, + gpointer nmobj, + const GParamSpec *pspec) +{ + NMObjectBase *base; + + nm_assert (NM_IS_CLIENT (self)); + nm_assert (NM_IS_OBJECT (nmobj) || NM_IS_CLIENT (nmobj)); + + base = (NMObjectBase *) nmobj; + if (c_list_is_empty (&base->queue_notify_lst)) { + c_list_link_tail (&NM_CLIENT_GET_PRIVATE (self)->queue_notify_lst_head, + &base->queue_notify_lst); + g_object_ref (nmobj); + g_object_freeze_notify (nmobj); + } + + if (pspec) + g_object_notify_by_pspec (nmobj, (GParamSpec *) pspec); +} + +/*****************************************************************************/ + +gpointer +_nm_client_notify_event_queue (NMClient *self, + int priority, + NMClientNotifyEventCb callback, + gsize event_size) +{ + NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self); + NMClientNotifyEvent *notify_event; + + nm_assert (callback); + nm_assert (event_size > sizeof (NMClientNotifyEvent)); + + notify_event = g_malloc (event_size); + notify_event->priority = priority; + notify_event->callback = callback; + c_list_link_tail (&priv->notify_event_lst_head, ¬ify_event->lst); + priv->notify_event_lst_changed = TRUE; + return notify_event; +} + +NMClientNotifyEventWithPtr * +_nm_client_notify_event_queue_with_ptr (NMClient *self, + int priority, + NMClientNotifyEventWithPtrCb callback, + gpointer user_data) +{ + NMClientNotifyEventWithPtr *notify_event; + + notify_event = _nm_client_notify_event_queue (self, + priority, + (NMClientNotifyEventCb) callback, + sizeof (NMClientNotifyEventWithPtr)); + notify_event->user_data = user_data; + return notify_event; +} + +/*****************************************************************************/ + +typedef struct { + NMClientNotifyEvent parent; + GObject *source; + NMObject *obj; + guint signal_id; +} NMClientNotifyEventObjAddedRemove; + +static void +_nm_client_notify_event_queue_emit_obj_signal_cb (NMClient *self, + gpointer notify_event_base) +{ + NMClientNotifyEventObjAddedRemove *notify_event = notify_event_base; + + NML_NMCLIENT_LOG_T (self, "[%s] emit \"%s\" signal for %s", + NM_IS_CLIENT (notify_event->source) + ? "nmclient" + : _nm_object_get_path (notify_event->source), + g_signal_name (notify_event->signal_id), + _nm_object_get_path (notify_event->obj)); + + nm_assert ( NM_IS_OBJECT (notify_event->source) + || NM_IS_CLIENT (notify_event->source)); + + g_signal_emit (notify_event->source, + notify_event->signal_id, + 0, + notify_event->obj); + + g_object_unref (notify_event->obj); + g_object_unref (notify_event->source); +} + +void +_nm_client_notify_event_queue_emit_obj_signal (NMClient *self, + GObject *source, + NMObject *nmobj, + gboolean is_added /* or else removed */, + int prio_offset, + guint signal_id) +{ + NMClientNotifyEventObjAddedRemove *notify_event; + + nm_assert (prio_offset >= 0); + nm_assert (prio_offset < 20); + nm_assert ( NM_IS_OBJECT (source) + || NM_IS_CLIENT (source)); + nm_assert (NM_IS_OBJECT (nmobj)); + + if (((NMObjectBase *) source)->is_disposing) { + nm_assert (NM_IS_CLIENT (source)); + return; + } + + notify_event = _nm_client_notify_event_queue (self, + is_added + ? NM_CLIENT_NOTIFY_EVENT_PRIO_AFTER - 20 + prio_offset + : NM_CLIENT_NOTIFY_EVENT_PRIO_BEFORE + 20 - prio_offset, + _nm_client_notify_event_queue_emit_obj_signal_cb, + sizeof (NMClientNotifyEventObjAddedRemove)); + notify_event->source = g_object_ref (source); + notify_event->obj = g_object_ref (nmobj); + notify_event->signal_id = signal_id; +} + +/*****************************************************************************/ + +static int +_nm_client_notify_event_cmp (const CList *a, + const CList *b, + const void *user_data) +{ + NM_CMP_DIRECT (c_list_entry (a, NMClientNotifyEvent, lst)->priority, + c_list_entry (b, NMClientNotifyEvent, lst)->priority); + return 0; +} + +static void +_nm_client_notify_event_emit_parts (NMClient *self, + int max_priority /* included! */) +{ + NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self); + NMClientNotifyEvent *notify_event; + + while (TRUE) { + if (priv->notify_event_lst_changed) { + priv->notify_event_lst_changed = FALSE; + c_list_sort (&priv->notify_event_lst_head, _nm_client_notify_event_cmp, NULL); + } + notify_event = c_list_first_entry (&priv->notify_event_lst_head, NMClientNotifyEvent, lst); + if (!notify_event) + return; + if (notify_event->priority > max_priority) + return; + c_list_unlink_stale (¬ify_event->lst); + notify_event->callback (self, notify_event); + g_free (notify_event); + } +} + +static void +_nm_client_notify_event_emit (NMClient *self) +{ + NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self); + NMObjectBase *base; + + _nm_client_notify_event_emit_parts (self, NM_CLIENT_NOTIFY_EVENT_PRIO_GPROP); + + while ((base = c_list_first_entry (&priv->queue_notify_lst_head, NMObjectBase, queue_notify_lst))) { + c_list_unlink (&base->queue_notify_lst); + g_object_thaw_notify (G_OBJECT (base)); + g_object_unref (base); + } + + _nm_client_notify_event_emit_parts (self, G_MAXINT); +} + +/*****************************************************************************/ + +GDBusConnection * +_nm_client_get_dbus_connection (NMClient *self) +{ + return NM_CLIENT_GET_PRIVATE (self)->dbus_connection; } const char * -_nm_client_get_dbus_name_owner (NMClient *client) +_nm_client_get_dbus_name_owner (NMClient *self) +{ + return NM_CLIENT_GET_PRIVATE (self)->name_owner; +} + +GMainContext * +_nm_client_get_context_main (NMClient *self) +{ + return NM_CLIENT_GET_PRIVATE (self)->main_context; +} + +GMainContext * +_nm_client_get_context_dbus (NMClient *self) +{ + return NM_CLIENT_GET_PRIVATE (self)->dbus_context; +} + +struct udev * +_nm_client_get_udev (NMClient *self) +{ + NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self); + + if (G_UNLIKELY (!priv->udev_inited)) { + priv->udev_inited = TRUE; + /* for testing, we don't want to use udev in libnm. */ + if (!nm_streq0 (g_getenv ("LIBNM_USE_NO_UDEV"), "1")) + priv->udev = udev_new (); + } + + return priv->udev; +} + +/*****************************************************************************/ + +static void +_ASSERT_dbobj (NMLDBusObject *dbobj, + NMClient *self) +{ +#if NM_MORE_ASSERTS > 5 + nm_assert (NM_IS_CLIENT (self)); + nm_assert (NML_IS_DBUS_OBJECT (dbobj)); + nm_assert (dbobj == g_hash_table_lookup (NM_CLIENT_GET_PRIVATE (self)->dbus_objects, dbobj)); +#endif +} + +static NMLDBusObject * +nml_dbus_object_new (NMRefString *dbus_path_take) +{ + NMLDBusObject *dbobj; + + nm_assert (NM_IS_REF_STRING (dbus_path_take)); + + dbobj = g_slice_new (NMLDBusObject); + *dbobj = (NMLDBusObject) { + .dbus_path = g_steal_pointer (&dbus_path_take), + .ref_count = 1, + .iface_lst_head = C_LIST_INIT (dbobj->iface_lst_head), + .removed_iface_lst_head = C_LIST_INIT (dbobj->removed_iface_lst_head), + .changed_obj_lst = C_LIST_INIT (dbobj->changed_obj_lst), + .watcher_lst_head = C_LIST_INIT (dbobj->watcher_lst_head), + .obj_state = NML_DBUS_OBJ_STATE_UNLINKED, + .dbus_objects_lst = C_LIST_INIT (dbobj->dbus_objects_lst), + }; + return dbobj; +} + +NMLDBusObject * +nml_dbus_object_ref (NMLDBusObject *dbobj) +{ + nm_assert (dbobj); + nm_assert (dbobj->ref_count > 0); + + dbobj->ref_count++; + return dbobj; +} + +void +nml_dbus_object_unref (NMLDBusObject *dbobj) +{ + nm_assert (dbobj); + nm_assert (dbobj->ref_count > 0); + + if (--dbobj->ref_count > 0) + return; + + nm_assert (c_list_is_empty (&dbobj->changed_obj_lst)); + nm_assert (c_list_is_empty (&dbobj->iface_lst_head)); + nm_assert (c_list_is_empty (&dbobj->removed_iface_lst_head)); + nm_assert (c_list_is_empty (&dbobj->watcher_lst_head)); + nm_assert (!dbobj->nmobj); + + nm_ref_string_unref (dbobj->dbus_path); + nm_g_slice_free (dbobj); +} + +NMLDBusObjIfaceData * +nml_dbus_object_iface_data_get (NMLDBusObject *dbobj, + const char *dbus_iface_name, + gboolean allow_create) +{ + const NMLDBusMetaIface *meta_iface; + NMLDBusObjIfaceData *db_iface_data; + NMLDBusObjPropData *db_prop_data; + guint count = 0; + guint i; + + nm_assert (NML_IS_DBUS_OBJECT (dbobj)); + nm_assert (dbus_iface_name); + +#if NM_MORE_ASSERTS > 10 + { + gboolean expect_well_known = TRUE; + + /* all well-known interfaces must come first in the list. */ + c_list_for_each_entry (db_iface_data, &dbobj->iface_lst_head, iface_lst) { + if (db_iface_data->dbus_iface_is_wellknown == expect_well_known) + continue; + nm_assert (expect_well_known); + expect_well_known = FALSE; + } + } +#endif + + meta_iface = nml_dbus_meta_iface_get (dbus_iface_name); + if (meta_iface) { + c_list_for_each_entry (db_iface_data, &dbobj->iface_lst_head, iface_lst) { + if (!db_iface_data->dbus_iface_is_wellknown) + break; + if (db_iface_data->dbus_iface.meta == meta_iface) + return db_iface_data; + count++; + } + } else { + nm_c_list_for_each_entry_prev (db_iface_data, &dbobj->iface_lst_head, iface_lst) { + if (db_iface_data->dbus_iface_is_wellknown) + break; + if (nm_streq (db_iface_data->dbus_iface.name->str, dbus_iface_name)) + return db_iface_data; + count++; + } + } + + if (!allow_create) + return NULL; + + if (count > 20) { + /* We track the list of interfaces that an object has in a linked list. + * That is efficient and convenient, if we assume that each object only has a small + * number of interfaces (which very much should be the case). Here, something is very + * odd, maybe there is a bug or the server side is misbehaving. Anyway, error out. */ + return NULL; + } + + db_iface_data = g_malloc ( G_STRUCT_OFFSET (NMLDBusObjIfaceData, prop_datas) + + (meta_iface ? (sizeof (NMLDBusObjPropData) * meta_iface->n_dbus_properties): 0u)); + if (meta_iface) { + *db_iface_data = (NMLDBusObjIfaceData) { + .dbus_iface.meta = meta_iface, + .dbus_iface_is_wellknown = TRUE, + .changed_prop_lst_head = C_LIST_INIT (db_iface_data->changed_prop_lst_head), + }; + db_prop_data = &db_iface_data->prop_datas[0]; + for (i = 0; i < meta_iface->n_dbus_properties; i++, db_prop_data++) { + *db_prop_data = (NMLDBusObjPropData) { + .prop_data_value = NULL, + .changed_prop_lst = C_LIST_INIT (db_prop_data->changed_prop_lst), + }; + } + c_list_link_front (&dbobj->iface_lst_head, &db_iface_data->iface_lst); + } else { + /* Intentionally don't initialize the other fields. We are not supposed + * to touch them, and a valgrind warning would be preferable. */ + db_iface_data->dbus_iface.name = nm_ref_string_new (dbus_iface_name); + db_iface_data->dbus_iface_is_wellknown = FALSE; + c_list_link_tail (&dbobj->iface_lst_head, &db_iface_data->iface_lst); + } + + return db_iface_data; +} + +static void +nml_dbus_obj_iface_data_destroy (NMLDBusObjIfaceData *db_iface_data) +{ + guint i; + + nm_assert (db_iface_data); + nm_assert (c_list_is_empty (&db_iface_data->iface_lst)); + + if (db_iface_data->dbus_iface_is_wellknown) { + for (i = 0; i < db_iface_data->dbus_iface.meta->n_dbus_properties; i++) + nm_g_variant_unref (db_iface_data->prop_datas[i].prop_data_value); + } else + nm_ref_string_unref (db_iface_data->dbus_iface.name); + + g_free (db_iface_data); +} + +gpointer +nml_dbus_object_get_property_location (NMLDBusObject *dbobj, + const NMLDBusMetaIface *meta_iface, + const NMLDBusMetaProperty *meta_property) +{ + char *target_c; + + target_c = (char *) dbobj->nmobj; + if (meta_iface->base_struct_offset > 0) + target_c = *((gpointer *) (&target_c[meta_iface->base_struct_offset])); + return &target_c[meta_property->prop_struct_offset]; +} + +static void +nml_dbus_object_set_obj_state (NMLDBusObject *dbobj, + NMLDBusObjState obj_state, + NMClient *self) { NMClientPrivate *priv; - nm_assert (NM_IS_CLIENT (client)); + nm_assert (NM_IS_CLIENT (self)); + nm_assert (NML_IS_DBUS_OBJECT (dbobj)); + +#if NM_MORE_ASSERTS > 10 + priv = NM_CLIENT_GET_PRIVATE (self); + switch (dbobj->obj_state) { + case NML_DBUS_OBJ_STATE_UNLINKED: nm_assert (c_list_is_empty (&dbobj->dbus_objects_lst)); break; + case NML_DBUS_OBJ_STATE_WATCHED_ONLY: nm_assert (c_list_contains (&priv->dbus_objects_lst_head_watched_only, &dbobj->dbus_objects_lst)); break; + case NML_DBUS_OBJ_STATE_ON_DBUS: nm_assert (c_list_contains (&priv->dbus_objects_lst_head_on_dbus, &dbobj->dbus_objects_lst)); break; + case NML_DBUS_OBJ_STATE_WITH_NMOBJ_NOT_READY: nm_assert (c_list_contains (&priv->dbus_objects_lst_head_with_nmobj_not_ready, &dbobj->dbus_objects_lst)); break; + case NML_DBUS_OBJ_STATE_WITH_NMOBJ_MAYBE_READY: nm_assert (c_list_contains (&priv->dbus_objects_lst_head_with_nmobj_maybe_ready, &dbobj->dbus_objects_lst)); break; + case NML_DBUS_OBJ_STATE_WITH_NMOBJ_VISIBLE: nm_assert (c_list_contains (&priv->dbus_objects_lst_head_with_nmobj_visible, &dbobj->dbus_objects_lst)); break; + case NML_DBUS_OBJ_STATE_WITH_NMOBJ_HIDDEN: nm_assert (c_list_contains (&priv->dbus_objects_lst_head_with_nmobj_hidden, &dbobj->dbus_objects_lst)); break; + } +#endif - priv = NM_CLIENT_GET_PRIVATE (client); + if (dbobj->obj_state == obj_state) + return; - nm_clear_g_free (&priv->name_owner_cached); + NML_NMCLIENT_LOG_T (self, "[%s]: set D-Bus object state %s", dbobj->dbus_path->str, nml_dbus_obj_state_to_string (obj_state)); + + priv = NM_CLIENT_GET_PRIVATE (self); + dbobj->obj_state = obj_state; + switch (obj_state) { + case NML_DBUS_OBJ_STATE_UNLINKED: c_list_unlink (&dbobj->dbus_objects_lst); break; + case NML_DBUS_OBJ_STATE_WATCHED_ONLY: nm_c_list_move_tail (&priv->dbus_objects_lst_head_watched_only, &dbobj->dbus_objects_lst); break; + case NML_DBUS_OBJ_STATE_ON_DBUS: nm_c_list_move_tail (&priv->dbus_objects_lst_head_on_dbus, &dbobj->dbus_objects_lst); break; + case NML_DBUS_OBJ_STATE_WITH_NMOBJ_NOT_READY: nm_c_list_move_tail (&priv->dbus_objects_lst_head_with_nmobj_not_ready, &dbobj->dbus_objects_lst); break; + case NML_DBUS_OBJ_STATE_WITH_NMOBJ_MAYBE_READY: nm_c_list_move_tail (&priv->dbus_objects_lst_head_with_nmobj_maybe_ready, &dbobj->dbus_objects_lst); break; + case NML_DBUS_OBJ_STATE_WITH_NMOBJ_VISIBLE: nm_c_list_move_tail (&priv->dbus_objects_lst_head_with_nmobj_visible, &dbobj->dbus_objects_lst); break; + case NML_DBUS_OBJ_STATE_WITH_NMOBJ_HIDDEN: nm_c_list_move_tail (&priv->dbus_objects_lst_head_with_nmobj_hidden, &dbobj->dbus_objects_lst); break; + default: + nm_assert_not_reached (); + } +} - if (!priv->object_manager) +/*****************************************************************************/ + +static void +_dbobjs_notify_watchers_for_dbobj (NMClient *self, + NMLDBusObject *dbobj) +{ + NMLDBusObjWatcher *obj_watcher; + NMLDBusObjWatcher *obj_watcher_safe; + + c_list_for_each_entry_safe (obj_watcher, obj_watcher_safe, &dbobj->watcher_lst_head, _priv.watcher_lst) + obj_watcher->_priv.notify_fcn (self, obj_watcher); +} + +static gboolean +_dbobjs_check_dbobj_visible (NMClient *self, + NMLDBusObject *dbobj, + gboolean force_recheck, + gboolean need_definite_answer, + gboolean *out_notified_watchers) +{ + NMClientPrivate *priv; + NMObjectClass *klass; + NMLDBusObjState obj_state; + + nm_assert (NM_IS_CLIENT (self)); + nm_assert (NML_IS_DBUS_OBJECT (dbobj)); + nm_assert (G_IS_OBJECT (dbobj->nmobj)); + nm_assert ( NM_IS_OBJECT (dbobj->nmobj) + || NM_IS_CLIENT (dbobj->nmobj)); + nm_assert (NM_IN_SET ((NMLDBusObjState) dbobj->obj_state, NML_DBUS_OBJ_STATE_WITH_NMOBJ_NOT_READY, + NML_DBUS_OBJ_STATE_WITH_NMOBJ_MAYBE_READY, + NML_DBUS_OBJ_STATE_WITH_NMOBJ_VISIBLE, + NML_DBUS_OBJ_STATE_WITH_NMOBJ_HIDDEN)); + + NM_SET_OUT (out_notified_watchers, FALSE); + + if (force_recheck) + nm_assert (!need_definite_answer); + else { + if (dbobj->obj_state == NML_DBUS_OBJ_STATE_WITH_NMOBJ_VISIBLE) + return TRUE; + if (dbobj->obj_state == NML_DBUS_OBJ_STATE_WITH_NMOBJ_HIDDEN) + return FALSE; + if (!need_definite_answer) { + priv = NM_CLIENT_GET_PRIVATE (self); + if (!priv->check_dbobj_visible_all) + nml_dbus_object_set_obj_state (dbobj, NML_DBUS_OBJ_STATE_WITH_NMOBJ_MAYBE_READY, self); + return FALSE; + } + } + + klass = NM_OBJECT_GET_CLASS (dbobj->nmobj); + + obj_state = klass->is_visible (NM_OBJECT (dbobj->nmobj)); + + nm_assert (NM_IN_SET (obj_state, NML_DBUS_OBJ_STATE_WITH_NMOBJ_NOT_READY, + NML_DBUS_OBJ_STATE_WITH_NMOBJ_VISIBLE, + NML_DBUS_OBJ_STATE_WITH_NMOBJ_HIDDEN)); + + if (obj_state == NML_DBUS_OBJ_STATE_WITH_NMOBJ_NOT_READY) { + if (NM_IN_SET ((NMLDBusObjState) dbobj->obj_state, NML_DBUS_OBJ_STATE_WITH_NMOBJ_VISIBLE, + NML_DBUS_OBJ_STATE_WITH_NMOBJ_HIDDEN)) + obj_state = NML_DBUS_OBJ_STATE_WITH_NMOBJ_HIDDEN; + else if (!need_definite_answer) { + nm_assert (NM_IN_SET ((NMLDBusObjState) dbobj->obj_state, NML_DBUS_OBJ_STATE_WITH_NMOBJ_NOT_READY, + NML_DBUS_OBJ_STATE_WITH_NMOBJ_MAYBE_READY)); + priv = NM_CLIENT_GET_PRIVATE (self); + if (!priv->check_dbobj_visible_all) + nml_dbus_object_set_obj_state (dbobj, NML_DBUS_OBJ_STATE_WITH_NMOBJ_MAYBE_READY, self); + return FALSE; + } + } + + if (obj_state != dbobj->obj_state) { + gboolean notify_watchers; + + notify_watchers = ( dbobj->obj_state != NML_DBUS_OBJ_STATE_WITH_NMOBJ_MAYBE_READY + || obj_state != NML_DBUS_OBJ_STATE_WITH_NMOBJ_NOT_READY); + nml_dbus_object_set_obj_state (dbobj, obj_state, self); + if (notify_watchers) { + _dbobjs_notify_watchers_for_dbobj (self, dbobj); + NM_SET_OUT (out_notified_watchers, TRUE); + } + } + + return dbobj->obj_state == NML_DBUS_OBJ_STATE_WITH_NMOBJ_VISIBLE; +} + +void +_nm_client_notify_object_changed (NMClient *self, + NMLDBusObject *dbobj) +{ + gboolean notified_watchers; + + _dbobjs_check_dbobj_visible (self, dbobj, TRUE, FALSE, ¬ified_watchers); + if (!notified_watchers) + _dbobjs_notify_watchers_for_dbobj (self, dbobj); +} + +static void +_dbobjs_check_dbobj_visible_all (NMClient *self) +{ + NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self); + NMLDBusObject *dbobj; + + nm_assert (!priv->check_dbobj_visible_all); + priv->check_dbobj_visible_all = TRUE; + while ((dbobj = c_list_first_entry (&priv->dbus_objects_lst_head_with_nmobj_maybe_ready, NMLDBusObject, dbus_objects_lst))) + _dbobjs_check_dbobj_visible (self, dbobj, FALSE, TRUE, NULL); + nm_assert (priv->check_dbobj_visible_all); + priv->check_dbobj_visible_all = FALSE; +} + +/*****************************************************************************/ + +static NMLDBusObject * +_dbobjs_dbobj_get_r (NMClient *self, + NMRefString *dbus_path_r) +{ + nm_assert (NM_IS_REF_STRING (dbus_path_r)); + + return g_hash_table_lookup (NM_CLIENT_GET_PRIVATE (self)->dbus_objects, &dbus_path_r); +} + +static NMLDBusObject * +_dbobjs_dbobj_get_s (NMClient *self, + const char *dbus_path) +{ + nm_auto_ref_string NMRefString *dbus_path_r = NULL; + + nm_assert (dbus_path); + dbus_path_r = nm_ref_string_new (dbus_path); + return _dbobjs_dbobj_get_r (self, dbus_path_r); +} + +static NMLDBusObject * +_dbobjs_dbobj_create (NMClient *self, + NMRefString *dbus_path_take) +{ + nm_auto_ref_string NMRefString *dbus_path = g_steal_pointer (&dbus_path_take); + NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self); + NMLDBusObject *dbobj; + + nm_assert (!_dbobjs_dbobj_get_r (self, dbus_path)); + + dbobj = nml_dbus_object_new (g_steal_pointer (&dbus_path)); + if (!g_hash_table_add (priv->dbus_objects, dbobj)) + nm_assert_not_reached (); + return dbobj; +} + +static NMLDBusObject * +_dbobjs_dbobj_get_or_create (NMClient *self, + NMRefString *dbus_path_take) +{ + nm_auto_ref_string NMRefString *dbus_path = g_steal_pointer (&dbus_path_take); + NMLDBusObject *dbobj; + + dbobj = _dbobjs_dbobj_get_r (self, dbus_path); + if (dbobj) + return dbobj; + return _dbobjs_dbobj_create (self, g_steal_pointer (&dbus_path)); +} + +static NMLDBusObject * +_dbobjs_get_nmobj (NMClient *self, + const char *dbus_path, + GType gtype) +{ + NMLDBusObject *dbobj; + + nm_assert ( gtype == G_TYPE_NONE + || g_type_is_a (gtype, NM_TYPE_OBJECT)); + + dbobj = _dbobjs_dbobj_get_s (self, dbus_path); + + if (!dbobj) + return NULL; + if (!dbobj->nmobj) return NULL; - priv->name_owner_cached = g_dbus_object_manager_client_get_name_owner (G_DBUS_OBJECT_MANAGER_CLIENT (priv->object_manager)); - return priv->name_owner_cached; + if ( gtype != G_TYPE_NONE + && !g_type_is_a (G_OBJECT_TYPE (dbobj->nmobj), gtype)) + return NULL; + + return dbobj; +} + +static gpointer +_dbobjs_get_nmobj_unpack_visible (NMClient *self, + const char *dbus_path, + GType gtype) +{ + NMLDBusObject *dbobj; + + dbobj = _dbobjs_get_nmobj (self, dbus_path, gtype); + if (!dbobj) + return NULL; + if (dbobj->obj_state != NML_DBUS_OBJ_STATE_WITH_NMOBJ_VISIBLE) + return NULL; + return dbobj->nmobj; } /*****************************************************************************/ +static gpointer +_dbobjs_obj_watcher_register_o (NMClient *self, + NMLDBusObject *dbobj, + NMLDBusObjWatchNotifyFcn notify_fcn, + gsize struct_size) +{ + NMLDBusObjWatcher *obj_watcher; + + nm_assert (NM_IS_CLIENT (self)); + _ASSERT_dbobj (dbobj, self); + nm_assert (notify_fcn); + nm_assert (struct_size > sizeof (NMLDBusObjWatcher)); + + obj_watcher = g_malloc (struct_size); + obj_watcher->dbobj = dbobj; + obj_watcher->_priv.notify_fcn = notify_fcn; + + /* we must enqueue the item in the front of the list. That is, because while + * invoking notify_fcn(), we iterate the watchers front-to-end. As we want to + * allow the callee to register new watches and unregister itself, this is + * the right way to do it. */ + c_list_link_front (&dbobj->watcher_lst_head, &obj_watcher->_priv.watcher_lst); + + return obj_watcher; +} + +static gpointer +_dbobjs_obj_watcher_register_r (NMClient *self, + NMRefString *dbus_path_take, + NMLDBusObjWatchNotifyFcn notify_fcn, + gsize struct_size) +{ + nm_auto_ref_string NMRefString *dbus_path = g_steal_pointer (&dbus_path_take); + NMLDBusObject *dbobj; + + nm_assert (NM_IS_CLIENT (self)); + nm_assert (notify_fcn); + + dbobj = _dbobjs_dbobj_get_or_create (self, g_steal_pointer (&dbus_path)); + if (dbobj->obj_state == NML_DBUS_OBJ_STATE_UNLINKED) + nml_dbus_object_set_obj_state (dbobj, NML_DBUS_OBJ_STATE_WATCHED_ONLY, self); + return _dbobjs_obj_watcher_register_o (self, dbobj, notify_fcn, struct_size); +} + +static void +_dbobjs_obj_watcher_unregister (NMClient *self, + gpointer obj_watcher_base) +{ + NMLDBusObjWatcher *obj_watcher = obj_watcher_base; + NMLDBusObject *dbobj; + + nm_assert (NM_IS_CLIENT (self)); + nm_assert (obj_watcher); + nm_assert (NML_IS_DBUS_OBJECT (obj_watcher->dbobj)); + nm_assert (g_hash_table_lookup (NM_CLIENT_GET_PRIVATE (self)->dbus_objects, obj_watcher->dbobj) == obj_watcher->dbobj); + nm_assert (c_list_contains (&obj_watcher->dbobj->watcher_lst_head, &obj_watcher->_priv.watcher_lst)); + + c_list_unlink (&obj_watcher->_priv.watcher_lst); + + dbobj = obj_watcher->dbobj; + + g_free (obj_watcher); + + if ( c_list_is_empty (&dbobj->iface_lst_head) + && c_list_is_empty (&dbobj->watcher_lst_head) + && c_list_is_empty (&dbobj->changed_obj_lst)) { + NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self); + + NML_NMCLIENT_LOG_T (self, "[%s]: drop D-Bus watcher", dbobj->dbus_path->str); + nml_dbus_object_set_obj_state (dbobj, NML_DBUS_OBJ_STATE_UNLINKED, self); + if (!g_hash_table_steal (priv->dbus_objects, dbobj)) + nm_assert_not_reached (); + nml_dbus_object_unref (dbobj); + } +} + +/*****************************************************************************/ + +typedef struct { + NMLDBusObjWatcher parent; + NMLDBusPropertyO *pr_o; +} PropertyOData; + +gpointer +nml_dbus_property_o_get_obj (NMLDBusPropertyO *pr_o) +{ + return pr_o->nmobj; +} + +static gboolean +nml_dbus_property_o_get_eval (NMLDBusPropertyO *pr_o, + NMClient *self) +{ + const NMLDBusPropertVTableO *vtable; + GObject *nmobj = NULL; + gboolean is_ready; + GType gtype; + + nm_assert (pr_o); + nm_assert (NM_IS_CLIENT (self)); + nm_assert (pr_o->owner_dbobj); + + if (!pr_o->obj_watcher) { + is_ready = TRUE; + goto done; + } + + if (!pr_o->obj_watcher->dbobj->nmobj) { + is_ready = FALSE; + goto done; + } + + vtable = pr_o->meta_iface->dbus_properties[pr_o->dbus_property_idx].extra.property_vtable_o; + + gtype = vtable->get_o_type_fcn (); + if (!g_type_is_a (G_OBJECT_TYPE (pr_o->obj_watcher->dbobj->nmobj), gtype)) { +#if NM_MORE_ASSERTS > 10 + NML_NMCLIENT_LOG_E (self, "[%s]: property %s references %s with unexpected GObject type %s instead of %s", + pr_o->owner_dbobj->dbus_path->str, + pr_o->meta_iface->dbus_properties[pr_o->dbus_property_idx].dbus_property_name, + pr_o->obj_watcher->dbobj->dbus_path->str, + G_OBJECT_TYPE_NAME (pr_o->obj_watcher->dbobj->nmobj), + g_type_name (gtype)); +#endif + is_ready = TRUE; + goto done; + } + + if ( pr_o->obj_watcher->dbobj != pr_o->owner_dbobj + && !_dbobjs_check_dbobj_visible (self, + pr_o->obj_watcher->dbobj, + FALSE, + FALSE, + NULL)) { + if (pr_o->obj_watcher->dbobj->obj_state == NML_DBUS_OBJ_STATE_WITH_NMOBJ_HIDDEN) + is_ready = TRUE; + else + is_ready = vtable->ready_without_visible; + goto done; + } + + nmobj = pr_o->obj_watcher->dbobj->nmobj; + is_ready = TRUE; + +done: + pr_o->is_ready |= is_ready; + if (pr_o->nmobj != nmobj) { + pr_o->nmobj = nmobj; + return TRUE; + } + return FALSE; +} + +gboolean +nml_dbus_property_o_is_ready (const NMLDBusPropertyO *pr_o) +{ + return pr_o->is_ready + || !pr_o->owner_dbobj; +} + +static void +nml_dbus_property_o_notify_watch_cb (NMClient *self, + gpointer obj_watcher) +{ + PropertyOData *pr_o_data = obj_watcher; + NMLDBusPropertyO *pr_o = pr_o_data->pr_o; + + nm_assert (pr_o->obj_watcher == obj_watcher); + + if (nml_dbus_property_o_get_eval (pr_o, self)) { + _nm_client_queue_notify_object (self, + pr_o->owner_dbobj->nmobj, + pr_o->meta_iface->obj_properties[pr_o->meta_iface->dbus_properties[pr_o->dbus_property_idx].obj_properties_idx]); + } + if (pr_o->owner_dbobj->obj_state == NML_DBUS_OBJ_STATE_WITH_NMOBJ_NOT_READY) + nml_dbus_object_set_obj_state (pr_o->owner_dbobj, NML_DBUS_OBJ_STATE_WITH_NMOBJ_MAYBE_READY, self); +} + +static NMLDBusNotifyUpdatePropFlags +nml_dbus_property_o_notify (NMClient *self, + NMLDBusPropertyO *pr_o, + NMLDBusObject *dbobj, + const NMLDBusMetaIface *meta_iface, + guint dbus_property_idx, + GVariant *value) +{ + const char *dbus_path = NULL; + + if (!pr_o->owner_dbobj) { + nm_assert (!pr_o->meta_iface); + nm_assert (pr_o->dbus_property_idx == 0); + nm_assert (!pr_o->is_ready); + pr_o->owner_dbobj = dbobj; + pr_o->meta_iface = meta_iface; + pr_o->dbus_property_idx = dbus_property_idx; + } else { + nm_assert (pr_o->owner_dbobj == dbobj); + nm_assert (pr_o->meta_iface == meta_iface); + nm_assert (pr_o->dbus_property_idx == dbus_property_idx); + } + + if (value) + dbus_path = nm_dbus_path_not_empty (g_variant_get_string (value, NULL)); + + if ( pr_o->obj_watcher + && ( !dbus_path + || !nm_streq (dbus_path, pr_o->obj_watcher->dbobj->dbus_path->str))) { + _dbobjs_obj_watcher_unregister (self, + g_steal_pointer (&pr_o->obj_watcher)); + } + if ( !pr_o->obj_watcher + && dbus_path) { + pr_o->obj_watcher = _dbobjs_obj_watcher_register_r (self, + nm_ref_string_new (dbus_path), + nml_dbus_property_o_notify_watch_cb, + sizeof (PropertyOData)); + ((PropertyOData *) pr_o->obj_watcher)->pr_o = pr_o; + } + + if (nml_dbus_property_o_get_eval (pr_o, self)) + return NML_DBUS_NOTIFY_UPDATE_PROP_FLAGS_NOTIFY; + + return NML_DBUS_NOTIFY_UPDATE_PROP_FLAGS_NONE; +} + +void +nml_dbus_property_o_clear (NMLDBusPropertyO *pr_o, + NMClient *self) +{ + if (pr_o->obj_watcher) { + nm_assert (NM_IS_CLIENT (self)); + _dbobjs_obj_watcher_unregister (self, + g_steal_pointer (&pr_o->obj_watcher)); + } + if ( pr_o->nmobj + && pr_o->owner_dbobj + && pr_o->owner_dbobj->nmobj) { + _nm_client_queue_notify_object (self, + pr_o->owner_dbobj->nmobj, + pr_o->meta_iface->obj_properties[pr_o->meta_iface->dbus_properties[pr_o->dbus_property_idx].obj_properties_idx]); + } + pr_o->owner_dbobj = NULL; + pr_o->meta_iface = NULL; + pr_o->dbus_property_idx = 0; + pr_o->is_ready = TRUE; +} + +/*****************************************************************************/ + +typedef struct { + NMLDBusObjWatcher obj_watcher; + NMLDBusPropertyAO *parent; + CList lst; + GObject *nmobj; + bool is_ready:1; + bool is_new:1; + bool is_notified:1; +} PropertyAOData; + +const GPtrArray * +nml_dbus_property_ao_get_objs_as_ptrarray (NMLDBusPropertyAO *pr_ao) +{ + if (!pr_ao->arr) { + PropertyAOData *pr_ao_data; + gsize n; + + n = 0; + if (pr_ao->owner_dbobj) { + c_list_for_each_entry (pr_ao_data, &pr_ao->lst, lst) { + if (pr_ao_data->nmobj) + n++; + } + } + + pr_ao->arr = g_ptr_array_new_full (n, g_object_unref); + if (pr_ao->owner_dbobj) { + c_list_for_each_entry (pr_ao_data, &pr_ao->lst, lst) { + if (pr_ao_data->nmobj) + g_ptr_array_add (pr_ao->arr, g_object_ref (pr_ao_data->nmobj)); + } + } + } + return pr_ao->arr; +} + +static void +nml_dbus_property_ao_notify_changed (PropertyAOData *pr_ao_data, + NMClient *self, + gboolean is_added /* or else removed */) +{ + NMLDBusPropertyAO *pr_ao; + const NMLDBusPropertVTableAO *vtable; + + if (!pr_ao_data->nmobj) + return; + + nm_assert (pr_ao_data->is_ready); + + if (is_added) { + if (pr_ao_data->is_notified) + return; + pr_ao_data->is_notified = TRUE; + } else { + if (!pr_ao_data->is_notified) + return; + pr_ao_data->is_notified = FALSE; + } + + pr_ao = pr_ao_data->parent; + + vtable = pr_ao->meta_iface->dbus_properties[pr_ao->dbus_property_idx].extra.property_vtable_ao; + + if (vtable->notify_changed_ao) + vtable->notify_changed_ao (pr_ao, self, NM_OBJECT (pr_ao_data->nmobj), is_added); +} + +static gboolean +nml_dbus_property_ao_get_eval (PropertyAOData *pr_ao_data, + NMClient *self) +{ + NMLDBusPropertyAO *pr_ao; + const NMLDBusPropertVTableAO *vtable; + GObject *nmobj = NULL; + gboolean is_ready; + GType gtype; + gboolean changed = FALSE; + + nm_assert (pr_ao_data); + nm_assert (NM_IS_CLIENT (self)); + + pr_ao = pr_ao_data->parent; + + if (!pr_ao_data->obj_watcher.dbobj->nmobj) { + is_ready = FALSE; + goto done; + } + + vtable = pr_ao->meta_iface->dbus_properties[pr_ao->dbus_property_idx].extra.property_vtable_ao; + + gtype = vtable->get_o_type_fcn (); + + if (!g_type_is_a (G_OBJECT_TYPE (pr_ao_data->obj_watcher.dbobj->nmobj), gtype)) { +#if NM_MORE_ASSERTS > 10 + NML_NMCLIENT_LOG_E (self, "[%s]: property %s references %s with unexpected GObject type %s instead of %s", + pr_ao->owner_dbobj->dbus_path->str, + pr_ao->meta_iface->dbus_properties[pr_ao->dbus_property_idx].dbus_property_name, + pr_ao_data->obj_watcher.dbobj->dbus_path->str, + G_OBJECT_TYPE_NAME (pr_ao_data->obj_watcher.dbobj->nmobj), + g_type_name (gtype)); +#endif + is_ready = TRUE; + goto done; + } + + if ( pr_ao_data->obj_watcher.dbobj != pr_ao->owner_dbobj + && !_dbobjs_check_dbobj_visible (self, + pr_ao_data->obj_watcher.dbobj, + FALSE, + FALSE, + NULL)) { + if (pr_ao_data->obj_watcher.dbobj->obj_state == NML_DBUS_OBJ_STATE_WITH_NMOBJ_HIDDEN) + is_ready = TRUE; + else + is_ready = vtable->ready_without_visible; + goto done; + } + + if ( vtable->check_nmobj_visible_fcn + && !vtable->check_nmobj_visible_fcn (pr_ao_data->obj_watcher.dbobj->nmobj)) { + is_ready = TRUE; + goto done; + } + + nmobj = pr_ao_data->obj_watcher.dbobj->nmobj; + is_ready = TRUE; + +done: + if ( is_ready + && !pr_ao_data->is_ready) { + nm_assert (pr_ao->n_not_ready > 0); + nm_assert (pr_ao->n_not_ready != G_MAXUINT); + pr_ao->n_not_ready--; + pr_ao_data->is_ready = TRUE; + } + + if (pr_ao_data->nmobj != nmobj) { + nml_dbus_property_ao_notify_changed (pr_ao_data, self, FALSE); + pr_ao_data->nmobj = nmobj; + changed = TRUE; + } + + if (!pr_ao_data->is_notified) + nml_dbus_property_ao_notify_changed (pr_ao_data, self, TRUE); + + return changed; +} + +gboolean +nml_dbus_property_ao_is_ready (const NMLDBusPropertyAO *pr_ao) +{ + return NM_IN_SET (pr_ao->n_not_ready, 0, G_MAXUINT) + || !pr_ao->owner_dbobj; +} + +static void +nml_dbus_property_ao_notify_watch_cb (NMClient *self, + gpointer obj_watcher) +{ + PropertyAOData *pr_ao_data = obj_watcher; + + nm_assert (g_hash_table_lookup (pr_ao_data->parent->hash, pr_ao_data) == pr_ao_data); + + if (nml_dbus_property_ao_get_eval (pr_ao_data, self)) { + nm_clear_pointer (&pr_ao_data->parent->arr, g_ptr_array_unref); + _nm_client_queue_notify_object (self, + pr_ao_data->parent->owner_dbobj->nmobj, + pr_ao_data->parent->meta_iface->obj_properties[pr_ao_data->parent->meta_iface->dbus_properties[pr_ao_data->parent->dbus_property_idx].obj_properties_idx]); + } + if (pr_ao_data->parent->owner_dbobj->obj_state == NML_DBUS_OBJ_STATE_WITH_NMOBJ_NOT_READY) + nml_dbus_object_set_obj_state (pr_ao_data->parent->owner_dbobj, NML_DBUS_OBJ_STATE_WITH_NMOBJ_MAYBE_READY, self); +} + +static NMLDBusNotifyUpdatePropFlags +nml_dbus_property_ao_notify (NMClient *self, + NMLDBusPropertyAO *pr_ao, + NMLDBusObject *dbobj, + const NMLDBusMetaIface *meta_iface, + guint dbus_property_idx, + GVariant *value) +{ + CList stale_lst_head = C_LIST_INIT (stale_lst_head); + gboolean changed = FALSE; + PropertyAOData *pr_ao_data; + + // XXX: ensure we properly handle loops. Add a unit test for that + // first. + + if (!pr_ao->owner_dbobj) { + nm_assert (!pr_ao->lst.next); + nm_assert (!pr_ao->lst.prev); + nm_assert (!pr_ao->hash); + nm_assert (!pr_ao->meta_iface); + nm_assert (pr_ao->dbus_property_idx == 0); + nm_assert (pr_ao->n_not_ready == 0); + c_list_init (&pr_ao->lst); + pr_ao->hash = g_hash_table_new (nm_ppdirect_hash, nm_ppdirect_equal); + pr_ao->owner_dbobj = dbobj; + pr_ao->meta_iface = meta_iface; + pr_ao->dbus_property_idx = dbus_property_idx; + } else { + nm_assert (pr_ao->lst.next); + nm_assert (pr_ao->lst.prev); + nm_assert (pr_ao->hash); + nm_assert (pr_ao->meta_iface == meta_iface); + nm_assert (pr_ao->dbus_property_idx == dbus_property_idx); + } + + c_list_splice (&stale_lst_head, &pr_ao->lst); + + if (value) { + GVariantIter iter; + const char *path; + + g_variant_iter_init (&iter, value); + while (g_variant_iter_next (&iter, "&o", &path)) { + nm_auto_ref_string NMRefString *dbus_path_r = NULL; + gpointer p_dbus_path_1; + + G_STATIC_ASSERT_EXPR (G_STRUCT_OFFSET (PropertyAOData, obj_watcher) == 0); + G_STATIC_ASSERT_EXPR (G_STRUCT_OFFSET (NMLDBusObjWatcher, dbobj) == 0); + G_STATIC_ASSERT_EXPR (G_STRUCT_OFFSET (NMLDBusObject, dbus_path) == 0); + + if (!nm_dbus_path_not_empty (path)) { + /* should not happen. Anyway, silently skip empty paths. */ + continue; + } + + dbus_path_r = nm_ref_string_new (path); + p_dbus_path_1 = &dbus_path_r; + pr_ao_data = g_hash_table_lookup (pr_ao->hash, &p_dbus_path_1); + + if (pr_ao_data) { + /* With this implementation we cannot track the same path multiple times. + * Of course, for none of the properties where we use this, the server + * should expose the same path more than once, so in practice this is fine + * (maybe even preferable to drop duplicates form NMClient's API). */ + nm_assert (pr_ao_data->obj_watcher.dbobj->dbus_path == dbus_path_r); + nm_c_list_move_tail (&pr_ao->lst, &pr_ao_data->lst); + } else { + pr_ao_data = _dbobjs_obj_watcher_register_r (self, + g_steal_pointer (&dbus_path_r), + nml_dbus_property_ao_notify_watch_cb, + sizeof (PropertyAOData)), + pr_ao_data->parent = pr_ao; + pr_ao_data->nmobj = NULL; + pr_ao_data->is_new = TRUE; + pr_ao_data->is_ready = FALSE; + pr_ao_data->is_notified = FALSE; + c_list_link_tail (&pr_ao->lst, &pr_ao_data->lst); + if (!g_hash_table_add (pr_ao->hash, pr_ao_data)) + nm_assert_not_reached (); + nm_assert (pr_ao->n_not_ready < G_MAXUINT); + pr_ao->n_not_ready++; + } + +#if NM_MORE_ASSERTS > 10 + { + nm_auto_ref_string NMRefString *p = nm_ref_string_new (path); + gpointer pp = &p; + + nm_assert (g_hash_table_lookup (pr_ao->hash, &pp) == pr_ao_data); + } +#endif + } + } + + while ((pr_ao_data = c_list_first_entry (&stale_lst_head, PropertyAOData, lst))) { + c_list_unlink (&pr_ao_data->lst); + if (!g_hash_table_remove (pr_ao->hash, pr_ao_data)) + nm_assert_not_reached (); + if (pr_ao_data->nmobj) + changed = TRUE; + if (!pr_ao_data->is_ready) { + nm_assert (pr_ao->n_not_ready > 0); + nm_assert (pr_ao->n_not_ready != G_MAXUINT); + pr_ao->n_not_ready--; + } else + nml_dbus_property_ao_notify_changed (pr_ao_data, self, FALSE); + _dbobjs_obj_watcher_unregister (self, pr_ao_data); + } + + c_list_for_each_entry (pr_ao_data, &pr_ao->lst, lst) { + if (pr_ao_data->is_new) { + pr_ao_data->is_new = FALSE; + if (nml_dbus_property_ao_get_eval (pr_ao_data, self)) + changed = TRUE; + } + } + +#if NM_MORE_ASSERTS > 10 + { + guint c = 0; + + c_list_for_each_entry (pr_ao_data, &pr_ao->lst, lst) + c += (!pr_ao_data->is_ready); + nm_assert (pr_ao->n_not_ready == c); + } +#endif + + if (changed) { + nm_clear_pointer (&pr_ao->arr, g_ptr_array_unref); + return NML_DBUS_NOTIFY_UPDATE_PROP_FLAGS_NOTIFY; + } + + return NML_DBUS_NOTIFY_UPDATE_PROP_FLAGS_NONE; +} + +void +nml_dbus_property_ao_clear (NMLDBusPropertyAO *pr_ao, + NMClient *self) +{ + + if (!pr_ao->owner_dbobj) { + nm_assert (NM_IN_SET (pr_ao->n_not_ready, 0, G_MAXUINT)); + nm_assert (pr_ao->n_not_ready != G_MAXUINT || (!pr_ao->lst.next && !pr_ao->lst.prev) || c_list_is_empty (&pr_ao->lst)); + nm_assert (pr_ao->n_not_ready != 0 || (!pr_ao->lst.next && !pr_ao->lst.prev)); + nm_assert (!pr_ao->hash); + nm_assert (!pr_ao->meta_iface); + nm_assert (pr_ao->dbus_property_idx == 0); + pr_ao->n_not_ready = G_MAXUINT; + } else { + PropertyAOData *pr_ao_data; + gboolean changed = FALSE; + + nm_assert (NM_IS_CLIENT (self)); + nm_assert (pr_ao->lst.next); + nm_assert (pr_ao->lst.prev); + nm_assert (pr_ao->hash); + nm_assert (pr_ao->meta_iface); + nm_assert (pr_ao->n_not_ready != G_MAXUINT); + + while ((pr_ao_data = c_list_first_entry (&pr_ao->lst, PropertyAOData, lst))) { + if (pr_ao_data->nmobj) + changed = TRUE; + if (!pr_ao_data->is_ready) { + nm_assert (pr_ao->n_not_ready > 0); + pr_ao->n_not_ready--; + } else + nml_dbus_property_ao_notify_changed (pr_ao_data, self, FALSE); + c_list_unlink (&pr_ao_data->lst); + if (!g_hash_table_remove (pr_ao->hash, pr_ao_data)) + nm_assert_not_reached (); + _dbobjs_obj_watcher_unregister (self, pr_ao_data); + } + + nm_assert (c_list_is_empty (&pr_ao->lst)); + nm_assert (pr_ao->n_not_ready == 0); + nm_assert (g_hash_table_size (pr_ao->hash) == 0); + + if ( changed + && pr_ao->owner_dbobj->nmobj) { + _nm_client_queue_notify_object (self, + pr_ao->owner_dbobj->nmobj, + pr_ao->meta_iface->obj_properties[pr_ao->meta_iface->dbus_properties[pr_ao->dbus_property_idx].obj_properties_idx]); + } + + nm_assert (c_list_is_empty (&pr_ao->lst)); + nm_assert (pr_ao->n_not_ready == 0); + nm_assert (g_hash_table_size (pr_ao->hash) == 0); + nm_clear_pointer (&pr_ao->hash, g_hash_table_unref); + pr_ao->owner_dbobj = NULL; + pr_ao->meta_iface = NULL; + pr_ao->dbus_property_idx = 0; + pr_ao->n_not_ready = G_MAXUINT; + } + + nm_clear_pointer (&pr_ao->arr, g_ptr_array_unref); +} + +/*****************************************************************************/ + +NMLDBusNotifyUpdatePropFlags +_nml_dbus_notify_update_prop_ignore (NMClient *self, + NMLDBusObject *dbobj, + const NMLDBusMetaIface *meta_iface, + guint dbus_property_idx, + GVariant *value) +{ + return NML_DBUS_NOTIFY_UPDATE_PROP_FLAGS_NONE; +} + +NMLDBusNotifyUpdatePropFlags +_nml_dbus_notify_update_prop_o (NMClient *self, + NMLDBusObject *dbobj, + const NMLDBusMetaIface *meta_iface, + guint dbus_property_idx, + GVariant *value) +{ + const char *path = NULL; + NMRefString **p_property; + + if (value) + path = g_variant_get_string (value, NULL); + + p_property = nml_dbus_object_get_property_location (dbobj, + meta_iface, + &meta_iface->dbus_properties[dbus_property_idx]); + + if (!nm_streq0 (nm_ref_string_get_str (*p_property), path)) { + nm_ref_string_unref (*p_property); + *p_property = nm_ref_string_new (path); + } + return NML_DBUS_NOTIFY_UPDATE_PROP_FLAGS_NOTIFY; +} + +/*****************************************************************************/ + +static void +_obj_notify_update_prop (NMClient *self, + NMLDBusObject *dbobj, + NMLDBusObjIfaceData *db_iface_data, + guint dbus_property_idx, + GVariant *value) +{ + const NMLDBusMetaIface *meta_iface = db_iface_data->dbus_iface.meta; + const NMLDBusMetaProperty *meta_property = &meta_iface->dbus_properties[dbus_property_idx]; + gpointer p_property; + const char *dbus_type_s; + const GParamSpec *param_spec; + NMLDBusNotifyUpdatePropFlags notify_update_prop_flags; + + nm_assert (G_IS_OBJECT (dbobj->nmobj)); + + if ( value + && !g_variant_is_of_type (value, meta_property->dbus_type)) { + NML_NMCLIENT_LOG_E (self, "[%s] property %s.%s expected of type \"%s\" but is \"%s\". Ignore", + dbobj->dbus_path->str, + meta_iface->dbus_iface_name, + meta_property->dbus_property_name, + (const char *) meta_property->dbus_type, + (const char *) g_variant_get_type (value)); + value = NULL; + } + + if (meta_property->use_notify_update_prop) { + notify_update_prop_flags = meta_property->notify_update_prop (self, + dbobj, + meta_iface, + dbus_property_idx, + value); + if (notify_update_prop_flags == NML_DBUS_NOTIFY_UPDATE_PROP_FLAGS_NONE) + return; + + nm_assert (notify_update_prop_flags == NML_DBUS_NOTIFY_UPDATE_PROP_FLAGS_NOTIFY); + nm_assert (G_IS_OBJECT (dbobj->nmobj)); + nm_assert (meta_iface->obj_properties); + nm_assert (meta_property->obj_properties_idx > 0); + param_spec = meta_iface->obj_properties[meta_property->obj_properties_idx]; + goto notify; + } + + p_property = nml_dbus_object_get_property_location (dbobj, meta_iface, meta_property); + + dbus_type_s = (const char *) meta_property->dbus_type; + + nm_assert (G_IS_OBJECT (dbobj->nmobj)); + nm_assert (meta_iface->obj_properties); + nm_assert (meta_property->obj_properties_idx > 0); + param_spec = meta_iface->obj_properties[meta_property->obj_properties_idx]; + + notify_update_prop_flags = NML_DBUS_NOTIFY_UPDATE_PROP_FLAGS_NOTIFY; + + switch (dbus_type_s[0]) { + case 'b': + nm_assert (dbus_type_s[1] == '\0'); + if (value) + *((bool *) p_property) = g_variant_get_boolean (value); + else if (param_spec->value_type == G_TYPE_BOOLEAN) + *((bool *) p_property) = ((GParamSpecBoolean *) param_spec)->default_value; + else { + nm_assert_not_reached (); + *((bool *) p_property) = FALSE; + } + break; + case 'y': + nm_assert (dbus_type_s[1] == '\0'); + if (value) + *((guint8 *) p_property) = g_variant_get_byte (value); + else { + nm_assert (nm_utils_g_param_spec_is_default (param_spec)); + *((guint8 *) p_property) = 0; + } + break; + case 'q': + nm_assert (dbus_type_s[1] == '\0'); + if (value) + *((guint16 *) p_property) = g_variant_get_uint16 (value); + else { + nm_assert (nm_utils_g_param_spec_is_default (param_spec)); + *((guint16 *) p_property) = 0; + } + break; + case 'i': + nm_assert (dbus_type_s[1] == '\0'); + if (value) + *((gint32 *) p_property) = g_variant_get_int32 (value); + else if (param_spec->value_type == G_TYPE_INT) + *((gint32 *) p_property) = ((GParamSpecInt *) param_spec)->default_value; + else { + nm_assert (nm_utils_g_param_spec_is_default (param_spec)); + *((gint32 *) p_property) = 0; + } + break; + case 'u': + nm_assert (dbus_type_s[1] == '\0'); + if (value) + *((guint32 *) p_property) = g_variant_get_uint32 (value); + else { + nm_assert (nm_utils_g_param_spec_is_default (param_spec)); + *((guint32 *) p_property) = 0; + } + break; + case 'x': + nm_assert (dbus_type_s[1] == '\0'); + if (value) + *((gint64 *) p_property) = g_variant_get_int64 (value); + else if (param_spec->value_type == G_TYPE_INT64) + *((gint64 *) p_property) = ((GParamSpecInt64 *) param_spec)->default_value; + else { + nm_assert (nm_utils_g_param_spec_is_default (param_spec)); + *((gint64 *) p_property) = 0; + } + break; + case 's': + nm_assert (dbus_type_s[1] == '\0'); + nm_clear_g_free ((char **) p_property); + if (value) + *((char **) p_property) = g_variant_dup_string (value, NULL); + else { + nm_assert (nm_utils_g_param_spec_is_default (param_spec)); + *((char **) p_property) = NULL; + } + break; + case 'o': + nm_assert (dbus_type_s[1] == '\0'); + notify_update_prop_flags = nml_dbus_property_o_notify (self, + p_property, + dbobj, + meta_iface, + dbus_property_idx, + value); + break; + case 'a': + switch (dbus_type_s[1]) { + case 'y': + nm_assert (dbus_type_s[2] == '\0'); + { + gconstpointer v; + gsize l; + GBytes *b = NULL; + + if (value) { + v = g_variant_get_fixed_array (value, &l, 1); + + if (l > 0) { + /* empty arrays are coerced to NULL. */ + b = g_bytes_new (v, l); + } + } + + nm_clear_pointer ((GBytes **) p_property, g_bytes_unref); + *((GBytes **) p_property) = b; + } + break; + case 's': + nm_assert (dbus_type_s[2] == '\0'); + nm_assert (param_spec->value_type == G_TYPE_STRV); + + g_strfreev (*((char ***) p_property)); + if (value) + *((char ***) p_property) = g_variant_dup_strv (value, NULL); + else + *((char ***) p_property) = NULL; + break; + case 'o': + nm_assert (dbus_type_s[2] == '\0'); + notify_update_prop_flags = nml_dbus_property_ao_notify (self, + p_property, + dbobj, + meta_iface, + dbus_property_idx, + value); + break; + default: + nm_assert_not_reached (); + } + break; + default: + nm_assert_not_reached (); + } + +notify: + if (NM_FLAGS_HAS (notify_update_prop_flags, NML_DBUS_NOTIFY_UPDATE_PROP_FLAGS_NOTIFY)) + g_object_notify_by_pspec (dbobj->nmobj, (GParamSpec *) param_spec); +} + +static void +_obj_notify_update_iface (NMClient *self, + NMLDBusObject *dbobj, + NMLDBusObjIfaceData *db_iface_data) +{ + NMLDBusObjPropData *db_prop_data; + gboolean is_self = (G_OBJECT (self) == dbobj->nmobj); + gboolean is_removed; + gboolean type_compatible; + guint8 i_prop; + + nm_assert (NM_IS_CLIENT (self)); + nm_assert (is_self || NM_IS_OBJECT (dbobj->nmobj)); + + if (G_UNLIKELY (!db_iface_data->nmobj_checked)) { + db_iface_data->nmobj_checked = TRUE; + type_compatible = db_iface_data->dbus_iface.meta->get_type_fcn + && g_type_is_a (G_OBJECT_TYPE (dbobj->nmobj), db_iface_data->dbus_iface.meta->get_type_fcn ()); + db_iface_data->nmobj_compatible = type_compatible; + } else + type_compatible = db_iface_data->nmobj_compatible; + + if (!type_compatible) { + /* on D-Bus, we have this interface associate with the object, but apparently + * it is not compatible. This is either a bug, or NetworkManager exposed an + * unexpected interface on D-Bus object for which we create a certain NMObject + * type. */ + return; + } + + is_removed = c_list_is_empty (&db_iface_data->iface_lst); + + nm_assert ( (is_removed && db_iface_data->dbus_iface.meta->n_dbus_properties > 0) + || (!is_removed && !c_list_is_empty (&db_iface_data->changed_prop_lst_head))); + + _nm_client_queue_notify_object (self, dbobj->nmobj, NULL); + + if (is_removed) { + for (i_prop = 0; i_prop < db_iface_data->dbus_iface.meta->n_dbus_properties; i_prop++) { + _obj_notify_update_prop (self, + dbobj, + db_iface_data, + i_prop, + NULL); + } + } else { + while ((db_prop_data = c_list_first_entry (&db_iface_data->changed_prop_lst_head, NMLDBusObjPropData, changed_prop_lst))) { + gs_unref_variant GVariant *prop_data_value = NULL; + + c_list_unlink (&db_prop_data->changed_prop_lst); + + nm_assert (db_prop_data >= db_iface_data->prop_datas); + nm_assert (db_prop_data < &db_iface_data->prop_datas[db_iface_data->dbus_iface.meta->n_dbus_properties]); + nm_assert (db_prop_data->prop_data_value); + + /* currently NMLDBusObject forgets about the variant. Theoretically, it could cache + * it, but there is no need because we update the property in nmobj (which extracts and + * keeps the property value itself). */ + prop_data_value = g_steal_pointer (&db_prop_data->prop_data_value); + + i_prop = (db_prop_data - &db_iface_data->prop_datas[0]); + _obj_notify_update_prop (self, + dbobj, + db_iface_data, + i_prop, + prop_data_value); + } + } +} + +static void +_obj_notify_update (NMClient *self, + NMLDBusObject *dbobj) +{ + NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self); + NMLDBusObjIfaceData *db_iface_data; + gboolean notify_watchers = TRUE; + gs_unref_object GObject *nmobj_unregistering = NULL; + + _ASSERT_dbobj (dbobj, self); + + if ( G_UNLIKELY (!dbobj->nmobj) + && !c_list_is_empty (&dbobj->iface_lst_head)) { + + /* Try to create a NMObject for this D-Bus object. Note that we detect the type + * based on the interfaces that it has, and if we make a choice once, we don't + * change. That means, one D-Bus object can only be of one type. */ + + if (NM_IN_SET (dbobj->dbus_path, _dbus_path_nm, + _dbus_path_settings, + _dbus_path_dns_manager)) { + /* For the main types, we don't detect them based on the interfaces present, + * but on the path names. Of course, both should correspond anyway. */ + NML_NMCLIENT_LOG_T (self, "[%s]: register NMClient for D-Bus object", + dbobj->dbus_path->str); + dbobj->nmobj = G_OBJECT (self); + if (dbobj->dbus_path == _dbus_path_nm) { + nm_assert (!priv->dbobj_nm); + priv->dbobj_nm = dbobj; + } else if (dbobj->dbus_path == _dbus_path_settings) { + nm_assert (!priv->dbobj_settings); + priv->dbobj_settings = dbobj; + } else { + nm_assert (dbobj->dbus_path == _dbus_path_dns_manager); + nm_assert (!priv->dbobj_dns_manager); + priv->dbobj_dns_manager = dbobj; + } + nml_dbus_object_set_obj_state (dbobj, NML_DBUS_OBJ_STATE_WITH_NMOBJ_VISIBLE, self); + } else { + GType gtype = G_TYPE_NONE; + NMLDBusMetaInteracePrio curr_prio = NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_LOW - 1; + + c_list_for_each_entry (db_iface_data, &dbobj->iface_lst_head, iface_lst) { + if (!db_iface_data->dbus_iface_is_wellknown) + break; + if (db_iface_data->dbus_iface.meta->interface_prio <= curr_prio) + continue; + curr_prio = db_iface_data->dbus_iface.meta->interface_prio; + gtype = db_iface_data->dbus_iface.meta->get_type_fcn (); + } + if (gtype != G_TYPE_NONE) { + dbobj->nmobj = g_object_new (gtype, NULL); + + NML_NMCLIENT_LOG_T (self, "[%s]: register new NMObject "NM_HASH_OBFUSCATE_PTR_FMT" of type %s", + dbobj->dbus_path->str, + NM_HASH_OBFUSCATE_PTR (dbobj->nmobj), + g_type_name (gtype)); + + nm_assert (NM_IS_OBJECT (dbobj->nmobj)); + NM_OBJECT_GET_CLASS (dbobj->nmobj)->register_client (NM_OBJECT (dbobj->nmobj), self, dbobj); + nml_dbus_object_set_obj_state (dbobj, NML_DBUS_OBJ_STATE_WITH_NMOBJ_NOT_READY, self); + } + } + } + + while ((db_iface_data = c_list_first_entry (&dbobj->removed_iface_lst_head, NMLDBusObjIfaceData, iface_lst))) { + c_list_unlink (&db_iface_data->iface_lst); + if ( db_iface_data->dbus_iface_is_wellknown + && dbobj->nmobj) + _obj_notify_update_iface (self, dbobj, db_iface_data); + nml_dbus_obj_iface_data_destroy (db_iface_data); + } + + c_list_for_each_entry (db_iface_data, &dbobj->iface_lst_head, iface_lst) { + if (!db_iface_data->dbus_iface_is_wellknown) + break; + if (c_list_is_empty (&db_iface_data->changed_prop_lst_head)) + continue; + if (dbobj->nmobj) + _obj_notify_update_iface (self, dbobj, db_iface_data); + } + + if ( c_list_is_empty (&dbobj->iface_lst_head) + && dbobj->nmobj) { + + if (dbobj->nmobj == G_OBJECT (self)) { + dbobj->nmobj = NULL; + NML_NMCLIENT_LOG_T (self, "[%s]: unregister NMClient from D-Bus object", + dbobj->dbus_path->str); + if (dbobj->dbus_path == _dbus_path_nm) { + nm_assert (priv->dbobj_nm == dbobj); + priv->dbobj_nm = NULL; + nml_dbus_property_o_clear (&priv->nm.activating_connection, self); + nml_dbus_property_o_clear (&priv->nm.primary_connection, self); + nml_dbus_property_ao_clear (&priv->nm.devices, self); + nml_dbus_property_ao_clear (&priv->nm.all_devices, self); + nml_dbus_property_ao_clear (&priv->nm.active_connections, self); + nml_dbus_property_ao_clear (&priv->nm.checkpoints, self); + } else if (dbobj->dbus_path == _dbus_path_settings) { + nm_assert (priv->dbobj_settings == dbobj); + priv->dbobj_settings = NULL; + nml_dbus_property_ao_clear (&priv->settings.connections, self); + } else { + nm_assert (dbobj->dbus_path == _dbus_path_dns_manager); + nm_assert (priv->dbobj_dns_manager == dbobj); + priv->dbobj_dns_manager = NULL; + } + } else { + nmobj_unregistering = g_steal_pointer (&dbobj->nmobj); + nml_dbus_object_set_obj_state (dbobj, NML_DBUS_OBJ_STATE_WATCHED_ONLY, self); + NML_NMCLIENT_LOG_T (self, "[%s]: unregister NMObject "NM_HASH_OBFUSCATE_PTR_FMT" of type %s", + dbobj->dbus_path->str, + NM_HASH_OBFUSCATE_PTR (nmobj_unregistering), + g_type_name (G_OBJECT_TYPE (nmobj_unregistering))); + NM_OBJECT_GET_CLASS (nmobj_unregistering)->unregister_client (NM_OBJECT (nmobj_unregistering), self, dbobj); + } + } else if (dbobj->nmobj) { + if (dbobj->nmobj != G_OBJECT (self)) { + gboolean notified_watchers; + + _dbobjs_check_dbobj_visible (self, dbobj, FALSE, FALSE, ¬ified_watchers); + notify_watchers = !notified_watchers; + } + } + + if (notify_watchers) + _dbobjs_notify_watchers_for_dbobj (self, dbobj); +} + +/*****************************************************************************/ + +static void +_dbus_handle_objects_changed (NMClient *self, + const char *log_context) +{ + NMClientPrivate *priv; + NMLDBusObject *dbobj_next; + + priv = NM_CLIENT_GET_PRIVATE (self); + + while ((dbobj_next = c_list_first_entry (&priv->dbus_object_changed_lst_head, NMLDBusObject, changed_obj_lst))) { + nm_auto_unref_nml_dbusobj NMLDBusObject *dbobj = nml_dbus_object_ref (dbobj_next); + + c_list_unlink (&dbobj->changed_obj_lst); + + _obj_notify_update (self, dbobj); + + if (dbobj->obj_state == NML_DBUS_OBJ_STATE_UNLINKED) + continue; + + if ( c_list_is_empty (&dbobj->iface_lst_head) + && c_list_is_empty (&dbobj->watcher_lst_head)) { + NML_NMCLIENT_LOG_T (self, "[%s]: drop D-Bus instance", dbobj->dbus_path->str); + nml_dbus_object_set_obj_state (dbobj, NML_DBUS_OBJ_STATE_UNLINKED, self); + if (!g_hash_table_steal (priv->dbus_objects, dbobj)) + nm_assert_not_reached (); + nml_dbus_object_unref (dbobj); + } + } +} + +static void +_dbus_handle_changes_commit (NMClient *self, + gboolean allow_init_start_check_complete) +{ + NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self); + nm_auto_pop_gmaincontext GMainContext *dbus_context = NULL; + + _dbobjs_check_dbobj_visible_all (self); + + dbus_context = nm_g_main_context_push_thread_default_if_necessary (priv->main_context); + + _nm_client_notify_event_emit (self); + + _set_nm_running (self); + + if (allow_init_start_check_complete) + _init_start_check_complete (self); +} + +static void +_dbus_handle_changes (NMClient *self, + const char *log_context, + gboolean allow_init_start_check_complete) +{ + _dbus_handle_objects_changed (self, log_context); + _dbus_handle_changes_commit (self, allow_init_start_check_complete); +} + static gboolean -_nm_client_check_nm_running (NMClient *client, GError **error) +_dbus_handle_properties_changed (NMClient *self, + const char *log_context, + const char *object_path, + const char *interface_name, + gboolean allow_add_iface, + GVariant *changed_properties, + NMLDBusObject **inout_dbobj) { - if (!nm_client_get_nm_running (client)) { - _nm_object_set_error_nm_not_running (error); + NMClientPrivate *priv; + NMLDBusObject *dbobj = NULL; + NMLDBusObjIfaceData *db_iface_data = NULL; + nm_auto_ref_string NMRefString *dbus_path = NULL; + + nm_assert (!changed_properties || g_variant_is_of_type (changed_properties, G_VARIANT_TYPE ("a{sv}"))); + + { + gs_free char *ss = NULL; + + NML_NMCLIENT_LOG_T (self, "[%s]: %s: properties changed for interface %s { %s }", + object_path, log_context, interface_name, + (ss = g_variant_print (changed_properties, TRUE))); + } + + if (inout_dbobj) { + dbobj = *inout_dbobj; + nm_assert (!dbobj || nm_streq (object_path, dbobj->dbus_path->str)); + } + if (!dbobj) { + dbus_path = nm_ref_string_new (object_path); + dbobj = _dbobjs_dbobj_get_r (self, dbus_path); + } + + if (dbobj) + db_iface_data = nml_dbus_object_iface_data_get (dbobj, interface_name, allow_add_iface); + else if (allow_add_iface) { + dbobj = _dbobjs_dbobj_create (self, g_steal_pointer (&dbus_path)); + nml_dbus_object_set_obj_state (dbobj, NML_DBUS_OBJ_STATE_ON_DBUS, self); + db_iface_data = nml_dbus_object_iface_data_get (dbobj, interface_name, TRUE); + } + + NM_SET_OUT (inout_dbobj, dbobj); + + if (!db_iface_data) { + if (allow_add_iface) + NML_NMCLIENT_LOG_E (self, "%s: [%s] too many interfaces on object. Something is very wrong", log_context, object_path); + else + NML_NMCLIENT_LOG_E (self, "%s: [%s] property changed signal for non existing interface %s", log_context, object_path, interface_name); + nm_assert ( !dbobj + || dbobj->obj_state != NML_DBUS_OBJ_STATE_UNLINKED); return FALSE; } + + if (!db_iface_data->dbus_iface_is_wellknown) + NML_NMCLIENT_LOG_W (self, "%s: [%s] ignore unknown interface %s", log_context, object_path, interface_name); + else if (changed_properties) { + GVariantIter iter_prop; + const char *property_name; + GVariant *property_value_tmp; + + g_variant_iter_init (&iter_prop, changed_properties); + while (g_variant_iter_next (&iter_prop, "{&sv}", &property_name, &property_value_tmp)) { + _nm_unused gs_unref_variant GVariant *property_value = property_value_tmp; + const NMLDBusMetaProperty *meta_property; + NMLDBusObjPropData *db_propdata; + guint property_idx; + + meta_property = nml_dbus_meta_property_get (db_iface_data->dbus_iface.meta, property_name, &property_idx); + if (!meta_property) { + NML_NMCLIENT_LOG_W (self, "%s: [%s]: ignore unknown property %s.%s", log_context, object_path, interface_name, property_name); + continue; + } + + db_propdata = &db_iface_data->prop_datas[property_idx]; + + NML_NMCLIENT_LOG_T (self, "[%s]: %s: %s property %s.%s", + object_path, log_context, + db_propdata->prop_data_value ? "update" : "set", + interface_name, property_name); + + nm_g_variant_unref (db_propdata->prop_data_value); + db_propdata->prop_data_value = g_steal_pointer (&property_value); + nm_c_list_move_tail (&db_iface_data->changed_prop_lst_head, &db_propdata->changed_prop_lst); + } + } + + priv = NM_CLIENT_GET_PRIVATE (self); + if (c_list_is_empty (&dbobj->changed_obj_lst)) + c_list_link_tail (&priv->dbus_object_changed_lst_head, &dbobj->changed_obj_lst); return TRUE; } +static gboolean +_dbus_handle_interface_added (NMClient *self, + const char *log_context, + const char *object_path, + GVariant *ifaces) +{ + gboolean changed = FALSE; + const char *interface_name; + GVariant *changed_properties; + GVariantIter iter_ifaces; + NMLDBusObject *dbobj = NULL; + + nm_assert (g_variant_is_of_type (ifaces, G_VARIANT_TYPE ("a{sa{sv}}"))); + + g_variant_iter_init (&iter_ifaces, ifaces); + while (g_variant_iter_next (&iter_ifaces, "{&s@a{sv}}", &interface_name, &changed_properties)) { + _nm_unused gs_unref_variant GVariant *changed_properties_free = changed_properties; + + if (_dbus_handle_properties_changed (self, log_context, object_path, interface_name, TRUE, changed_properties, &dbobj)) + changed = TRUE; + } + + return changed; +} + +static gboolean +_dbus_handle_interface_removed (NMClient *self, + const char *log_context, + const char *object_path, + NMLDBusObject **inout_dbobj, + const char *const*removed_interfaces) +{ + NMClientPrivate *priv; + gboolean changed = FALSE; + NMLDBusObject *dbobj; + gsize i; + + if ( inout_dbobj + && *inout_dbobj) { + dbobj = *inout_dbobj; + nm_assert (dbobj == _dbobjs_dbobj_get_s (self, object_path)); + } else { + dbobj = _dbobjs_dbobj_get_s (self, object_path); + if (!dbobj) { + NML_NMCLIENT_LOG_E (self, "%s: [%s]: receive interface removed event for non existing object", log_context, object_path); + return FALSE; + } + NM_SET_OUT (inout_dbobj, dbobj); + } + + for (i = 0; removed_interfaces[i]; i++) { + NMLDBusObjIfaceData *db_iface_data; + const char *interface_name = removed_interfaces[i]; + + db_iface_data = nml_dbus_object_iface_data_get (dbobj, interface_name, FALSE); + if (!db_iface_data) { + NML_NMCLIENT_LOG_E (self, "%s: [%s] receive interface remove event for unexpected interface %s", log_context, object_path, interface_name); + continue; + } + + nm_c_list_move_tail (&dbobj->removed_iface_lst_head, &db_iface_data->iface_lst); + changed = TRUE; + } + + if (changed) { + priv = NM_CLIENT_GET_PRIVATE (self); + + if (c_list_is_empty (&dbobj->changed_obj_lst)) + c_list_link_tail (&priv->dbus_object_changed_lst_head, &dbobj->changed_obj_lst); + } + + return changed; +} + +static void +_dbus_managed_objects_changed_cb (const char *object_path, + GVariant *added_interfaces_and_properties, + const char *const*removed_interfaces, + gpointer user_data) +{ + NMClient *self = user_data; + NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self); + const char *log_context; + gboolean changed; + + if (priv->get_managed_objects_cancellable) { + /* we still wait for the initial GetManagedObjects(). Ignore the event. */ + return; + } + + if (!added_interfaces_and_properties) { + log_context = "interfaces-removed"; + changed = _dbus_handle_interface_removed (self, log_context, object_path, NULL, removed_interfaces); + } else { + log_context = "interfaces-added"; + changed = _dbus_handle_interface_added (self, log_context, object_path, added_interfaces_and_properties); + } + + if (changed) + _dbus_handle_changes (self, log_context, TRUE); +} + +static void +_dbus_properties_changed_cb (GDBusConnection *connection, + const char *sender_name, + const char *object_path, + const char *signal_interface_name, + const char *signal_name, + GVariant *parameters, + gpointer user_data) +{ + NMClient *self = user_data; + NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self); + const char *interface_name; + gs_unref_variant GVariant *changed_properties = NULL; + gs_free const char **invalidated_properties = NULL; + const char *log_context = "properties-changed"; + + if (priv->get_managed_objects_cancellable) { + /* we still wait for the initial GetManagedObjects(). Ignore the event. */ + return; + } + + if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(sa{sv}as)"))) + return; + + g_variant_get (parameters, + "(&s@a{sv}^a&s)", + &interface_name, + &changed_properties, + &invalidated_properties); + + if (invalidated_properties && invalidated_properties[0]) { + NML_NMCLIENT_LOG_W (self, "%s: [%s] ignore invalidated properties on interface %s", + log_context, object_path, interface_name); + } + + if (_dbus_handle_properties_changed (self, log_context, object_path, interface_name, FALSE, changed_properties, NULL)) + _dbus_handle_changes (self, log_context, TRUE); +} + +static void +_dbus_get_managed_objects_cb (GVariant *result, + GError *error, + gpointer user_data) +{ + NMClient *self; + NMClientPrivate *priv; + + if ( !result + && nm_utils_error_is_cancelled (error, FALSE)) + return; + + self = user_data; + priv = NM_CLIENT_GET_PRIVATE (self); + + g_clear_object (&priv->get_managed_objects_cancellable); + + if (!result) { + NML_NMCLIENT_LOG_D (self, "GetManagedObjects() call failed: %s", error->message); + /* hm, now that's odd. Maybe NetworkManager just quit and we are about to get + * a name-owner changed signal soon. Treat this as if we got no managed objects at all. */ + } else + NML_NMCLIENT_LOG_D (self, "GetManagedObjects() completed"); + + if (result) { + GVariantIter iter; + const char *object_path; + GVariant *ifaces_tmp; + + g_variant_iter_init (&iter, result); + while (g_variant_iter_next (&iter, "{&o@a{sa{sv}}}", &object_path, &ifaces_tmp)) { + gs_unref_variant GVariant *ifaces = ifaces_tmp; + + _dbus_handle_interface_added (self, "get-managed-objects", object_path, ifaces); + } + } + + /* always call _dbus_handle_changes(), even if nothing changed. We need this to complete + * initialization. */ + _dbus_handle_changes (self, "get-managed-objects", TRUE); +} + +/*****************************************************************************/ + +static void +_nm_client_get_settings_call_cb (GObject *source, GAsyncResult *result, gpointer user_data) +{ + NMRemoteConnection *remote_connection; + NMClient *self; + gs_unref_variant GVariant *ret = NULL; + gs_free_error GError *error = NULL; + gs_unref_variant GVariant *settings = NULL; + NMLDBusObject *dbobj; + + ret = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), result, &error); + if ( !ret + && nm_utils_error_is_cancelled (error, FALSE)) + return; + + remote_connection = user_data; + + self = _nm_object_get_client (remote_connection); + + dbobj = _nm_object_get_dbobj (remote_connection); + + _ASSERT_dbobj (dbobj, self); + + if (!ret) { + NML_NMCLIENT_LOG_T (self, "[%s] GetSettings() completed with error: %s", + dbobj->dbus_path->str, + error->message); + } else { + NML_NMCLIENT_LOG_T (self, "[%s] GetSettings() completed with success", + dbobj->dbus_path->str); + g_variant_get (ret, + "(@a{sa{sv}})", + &settings); + } + + _nm_remote_settings_get_settings_commit (remote_connection, settings); + + _dbus_handle_changes_commit (self, TRUE); +} + +void +_nm_client_get_settings_call (NMClient *self, + NMLDBusObject *dbobj) +{ + GCancellable *cancellable; + + cancellable = _nm_remote_settings_get_settings_prepare (NM_REMOTE_CONNECTION (dbobj->nmobj)); + + _nm_client_dbus_call_simple (self, + cancellable, + dbobj->dbus_path->str, + NM_DBUS_INTERFACE_SETTINGS_CONNECTION, + "GetSettings", + g_variant_new ("()"), + G_VARIANT_TYPE ("(a{sa{sv}})"), + G_DBUS_CALL_FLAGS_NONE, + NM_DBUS_DEFAULT_TIMEOUT_MSEC, + _nm_client_get_settings_call_cb, + dbobj->nmobj); +} + +static void +_dbus_settings_updated_cb (GDBusConnection *connection, + const char *sender_name, + const char *object_path, + const char *signal_interface_name, + const char *signal_name, + GVariant *parameters, + gpointer user_data) +{ + NMClient *self = user_data; + NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self); + const char *log_context = "settings-updated"; + NMLDBusObject *dbobj; + + if (priv->get_managed_objects_cancellable) { + /* we still wait for the initial GetManagedObjects(). Ignore the event. */ + return; + } + + if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("()"))) + return; + + dbobj = _dbobjs_dbobj_get_s (self, object_path); + + if ( !dbobj + || !NM_IS_REMOTE_CONNECTION (dbobj->nmobj)) { + NML_NMCLIENT_LOG_W (self, "%s: [%s] ignore Updated signal for non-existing setting", + log_context, object_path); + return; + } + + NML_NMCLIENT_LOG_T (self, "%s: [%s] Updated signal received", + log_context, object_path); + + _nm_client_get_settings_call (self, dbobj); +} + +/*****************************************************************************/ + +static void +_dbus_nm_connection_active_state_changed_cb (GDBusConnection *connection, + const char *sender_name, + const char *object_path, + const char *signal_interface_name, + const char *signal_name, + GVariant *parameters, + gpointer user_data) +{ + NMClient *self = user_data; + NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self); + const char *log_context = "active-connection-state-changed"; + NMLDBusObject *dbobj; + guint32 state; + guint32 reason; + + if (priv->get_managed_objects_cancellable) { + /* we still wait for the initial GetManagedObjects(). Ignore the event. */ + return; + } + + if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(uu)"))) { + NML_NMCLIENT_LOG_E (self, "%s: [%s] ignore StateChanged signal with unexpected signature", + log_context, object_path); + return; + } + + dbobj = _dbobjs_dbobj_get_s (self, object_path); + + if ( !dbobj + || !NM_IS_ACTIVE_CONNECTION (dbobj->nmobj)) { + NML_NMCLIENT_LOG_E (self, "%s: [%s] ignore StateChanged signal for non-existing active connection", + log_context, object_path); + return; + } + + g_variant_get (parameters, "(uu)", &state, &reason); + + NML_NMCLIENT_LOG_T (self, "%s: [%s] StateChanged signal received", + log_context, object_path); + + _nm_active_connection_state_changed_commit (NM_ACTIVE_CONNECTION (dbobj->nmobj), + state, + reason); + + _dbus_handle_changes_commit (self, TRUE); +} + +/*****************************************************************************/ + +static void +_dbus_nm_vpn_connection_state_changed_cb (GDBusConnection *connection, + const char *sender_name, + const char *object_path, + const char *signal_interface_name, + const char *signal_name, + GVariant *parameters, + gpointer user_data) +{ + NMClient *self = user_data; + NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self); + const char *log_context = "vpn-connection-state-changed"; + NMLDBusObject *dbobj; + guint32 state; + guint32 reason; + + if (priv->get_managed_objects_cancellable) { + /* we still wait for the initial GetManagedObjects(). Ignore the event. */ + return; + } + + if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(uu)"))) { + NML_NMCLIENT_LOG_E (self, "%s: [%s] ignore VpnStateChanged signal with unexpected signature", + log_context, object_path); + return; + } + + dbobj = _dbobjs_dbobj_get_s (self, object_path); + + if ( !dbobj + || !NM_IS_VPN_CONNECTION (dbobj->nmobj)) { + NML_NMCLIENT_LOG_E (self, "%s: [%s] ignore VpnStateChanged signal for non-existing vpn connection", + log_context, object_path); + return; + } + + g_variant_get (parameters, "(uu)", &state, &reason); + + NML_NMCLIENT_LOG_T (self, "%s: [%s] VpnStateChanged signal received", + log_context, object_path); + + _nm_vpn_connection_state_changed_commit (NM_VPN_CONNECTION (dbobj->nmobj), + state, + reason); + + _dbus_handle_changes_commit (self, TRUE); +} + +/*****************************************************************************/ + +static void +_emit_permissions_changed (NMClient *self, + GHashTable *permissions, + gboolean force_unknown) +{ + GHashTableIter iter; + gpointer key; + gpointer value; + + if (!permissions) + return; + if (self->obj_base.is_disposing) + return; + + g_hash_table_iter_init (&iter, permissions); + while (g_hash_table_iter_next (&iter, &key, &value)) { + g_signal_emit (self, + signals[PERMISSION_CHANGED], + 0, + GPOINTER_TO_UINT (key), + force_unknown + ? (guint) NM_CLIENT_PERMISSION_NONE + : GPOINTER_TO_UINT (value)); + } +} + + +static void +_dbus_check_permissions_start_cb (GObject *source, GAsyncResult *result, gpointer user_data) +{ + nm_auto_pop_gmaincontext GMainContext *dbus_context = NULL; + NMClient *self; + NMClientPrivate *priv; + gs_unref_variant GVariant *ret = NULL; + nm_auto_free_variant_iter GVariantIter *v_permissions = NULL; + gs_unref_hashtable GHashTable *old_permissions = NULL; + gs_free_error GError *error = NULL; + const char *pkey; + const char *pvalue; + + ret = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), result, &error); + if ( !ret + && nm_utils_error_is_cancelled (error, FALSE)) + return; + + self = user_data; + priv = NM_CLIENT_GET_PRIVATE (self); + + g_clear_object (&priv->permissions_cancellable); + + if (!ret) { + NML_NMCLIENT_LOG_T (self, "GetPermissions call failed: %s", error->message); + return; + } + + NML_NMCLIENT_LOG_T (self, "GetPermissions call finished with success"); + + /* get list of old permissions for change notification */ + old_permissions = g_steal_pointer (&priv->permissions); + priv->permissions = g_hash_table_new (nm_direct_hash, NULL); + + g_variant_get (ret, "(a{ss})", &v_permissions); + while (g_variant_iter_next (v_permissions, "{&s&s}", &pkey, &pvalue)) { + NMClientPermission perm; + NMClientPermissionResult perm_result; + + perm = nm_permission_to_client (pkey); + if (perm == NM_CLIENT_PERMISSION_NONE) + continue; + + perm_result = nm_permission_result_to_client (pvalue); + + g_hash_table_insert (priv->permissions, + GUINT_TO_POINTER (perm), + GUINT_TO_POINTER (perm_result)); + if (old_permissions) { + g_hash_table_remove (old_permissions, + GUINT_TO_POINTER (perm)); + } + } + + dbus_context = nm_g_main_context_push_thread_default_if_necessary (priv->main_context); + _emit_permissions_changed (self, priv->permissions, FALSE); + _emit_permissions_changed (self, old_permissions, TRUE); +} + +static void +_dbus_check_permissions_start (NMClient *self) +{ + NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self); + + nm_clear_g_cancellable (&priv->permissions_cancellable); + priv->permissions_cancellable = g_cancellable_new (); + + NML_NMCLIENT_LOG_T (self, "GetPermissions() call started..."); + + _nm_client_dbus_call_simple (self, + priv->permissions_cancellable, + NM_DBUS_PATH, + NM_DBUS_INTERFACE, + "GetPermissions", + g_variant_new ("()"), + G_VARIANT_TYPE ("(a{ss})"), + G_DBUS_CALL_FLAGS_NONE, + NM_DBUS_DEFAULT_TIMEOUT_MSEC, + _dbus_check_permissions_start_cb, + self); +} + +static void +_dbus_nm_check_permissions_cb (GDBusConnection *connection, + const char *sender_name, + const char *object_path, + const char *signal_interface_name, + const char *signal_name, + GVariant *parameters, + gpointer user_data) +{ + NMClient *self = user_data; + + if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("()"))) { + NML_NMCLIENT_LOG_E (self, "ignore CheckPermissions signal with unexpected signature %s", + g_variant_get_type_string (parameters)); + return; + } + + _dbus_check_permissions_start (self); +} + +/*****************************************************************************/ + +static void +_property_ao_notify_changed_connections_cb (NMLDBusPropertyAO *pr_ao, + NMClient *self, + NMObject *nmobj, + gboolean is_added /* or else removed */) +{ + _nm_client_notify_event_queue_emit_obj_signal (self, + G_OBJECT (self), + nmobj, + is_added, + 5, + is_added + ? signals[CONNECTION_ADDED] + : signals[CONNECTION_REMOVED]); +} + +static void +_property_ao_notify_changed_all_devices_cb (NMLDBusPropertyAO *pr_ao, + NMClient *self, + NMObject *nmobj, + gboolean is_added /* or else removed */) +{ + _nm_client_notify_event_queue_emit_obj_signal (self, + G_OBJECT (self), + nmobj, + is_added, + 6, + is_added + ? signals[ANY_DEVICE_ADDED] + : signals[ANY_DEVICE_REMOVED]); +} + +static void +_property_ao_notify_changed_devices_cb (NMLDBusPropertyAO *pr_ao, + NMClient *self, + NMObject *nmobj, + gboolean is_added /* or else removed */) +{ + _nm_client_notify_event_queue_emit_obj_signal (self, + G_OBJECT (self), + nmobj, + is_added, + 7, + is_added + ? signals[DEVICE_ADDED] + : signals[DEVICE_REMOVED]); +} + +static void +_property_ao_notify_changed_active_connections_cb (NMLDBusPropertyAO *pr_ao, + NMClient *self, + NMObject *nmobj, + gboolean is_added /* or else removed */) +{ + _nm_client_notify_event_queue_emit_obj_signal (self, + G_OBJECT (self), + nmobj, + is_added, + 8, + is_added + ? signals[ACTIVE_CONNECTION_ADDED] + : signals[ACTIVE_CONNECTION_REMOVED]); +} + +/*****************************************************************************/ + +typedef struct { + NMLDBusObjWatcherWithPtr *obj_watcher; + const char *op_name; + NMLDBusObject *dbobj; + GTask *task; + GVariant *extra_results; + gpointer result; + GType gtype; + gulong cancellable_id; +} RequestWaitData; + +static void +_request_wait_data_free (RequestWaitData *request_data) +{ + nm_assert (!request_data->obj_watcher); + nm_assert (request_data->cancellable_id == 0); + nm_assert (!request_data->task || G_IS_TASK (request_data->task)); + + nm_g_object_unref (request_data->task); + nm_g_object_unref (request_data->result); + nm_g_variant_unref (request_data->extra_results); + if (request_data->dbobj) + nml_dbus_object_unref (request_data->dbobj); + nm_g_slice_free (request_data); +} + +static void +_request_wait_task_return (RequestWaitData *request_data) +{ + gs_unref_object GTask *task = NULL; + + nm_assert (request_data); + nm_assert (G_IS_TASK (request_data->task)); + nm_assert (request_data->dbobj); + nm_assert (NM_IS_OBJECT (request_data->dbobj->nmobj)); + nm_assert (!request_data->result); + + task = g_steal_pointer (&request_data->task); + + request_data->result = g_object_ref (request_data->dbobj->nmobj); + nm_clear_g_signal_handler (g_task_get_cancellable (task), &request_data->cancellable_id); + nm_clear_pointer (&request_data->dbobj, nml_dbus_object_unref); + g_task_return_pointer (task, request_data, (GDestroyNotify) _request_wait_data_free); +} + +static gboolean +_request_wait_complete (NMClient *self, + RequestWaitData *request_data, + gboolean force_complete) +{ + NMLDBusObject *dbobj; + + nm_assert (request_data); + nm_assert (!request_data->result); + nm_assert (!request_data->obj_watcher); + nm_assert (request_data->dbobj); + + dbobj = request_data->dbobj; + + if (dbobj->obj_state == NML_DBUS_OBJ_STATE_WITH_NMOBJ_VISIBLE) { + NML_NMCLIENT_LOG_D (self, "%s() succeeded with %s", request_data->op_name, dbobj->dbus_path->str); + nm_assert (G_TYPE_CHECK_INSTANCE_TYPE (dbobj->nmobj, request_data->gtype)); + _request_wait_task_return (request_data); + return TRUE; + } + + if ( force_complete + || dbobj->obj_state != NML_DBUS_OBJ_STATE_WITH_NMOBJ_NOT_READY) { + if (force_complete) + NML_NMCLIENT_LOG_D (self, "%s() succeeded with %s but object is in an unsuitable state", request_data->op_name, dbobj->dbus_path->str); + else + NML_NMCLIENT_LOG_W (self, "%s() succeeded with %s but object is in an unsuitable state", request_data->op_name, dbobj->dbus_path->str); + + g_task_return_error (request_data->task, g_error_new (NM_CLIENT_ERROR, + NM_CLIENT_ERROR_OBJECT_CREATION_FAILED, + _("request succeeded with %s but object is in an unsuitable state"), + dbobj->dbus_path->str)); + _request_wait_data_free (request_data); + return TRUE; + } + + return FALSE; +} + +static void +_request_wait_complete_cb (NMClient *self, + NMClientNotifyEventWithPtr *notify_event) +{ + _request_wait_complete (self, + notify_event->user_data, + TRUE); +} + +static void +_request_wait_obj_watcher_cb (NMClient *self, + gpointer obj_watcher_base) +{ + NMLDBusObjWatcherWithPtr *obj_watcher = obj_watcher_base; + RequestWaitData *request_data = obj_watcher->user_data; + NMLDBusObject *dbobj; + + dbobj = request_data->dbobj; + + if (NM_IN_SET ((NMLDBusObjState) dbobj->obj_state, NML_DBUS_OBJ_STATE_WITH_NMOBJ_NOT_READY, + NML_DBUS_OBJ_STATE_WITH_NMOBJ_MAYBE_READY)) { + /* Not ready. Wait and watch more. */ + return; + } + + nm_assert (NM_IN_SET ((NMLDBusObjState) dbobj->obj_state, NML_DBUS_OBJ_STATE_WATCHED_ONLY, + NML_DBUS_OBJ_STATE_ON_DBUS, + NML_DBUS_OBJ_STATE_WITH_NMOBJ_VISIBLE, + NML_DBUS_OBJ_STATE_WITH_NMOBJ_HIDDEN)); + + _dbobjs_obj_watcher_unregister (self, g_steal_pointer (&request_data->obj_watcher)); + + nm_clear_g_signal_handler (g_task_get_cancellable (request_data->task), &request_data->cancellable_id); + + _nm_client_notify_event_queue_with_ptr (self, + NM_CLIENT_NOTIFY_EVENT_PRIO_AFTER + 30, + _request_wait_complete_cb, + request_data); +} + +static void +_request_wait_cancelled_cb (GCancellable *cancellable, + gpointer user_data) +{ + RequestWaitData *request_data = user_data; + NMClient *self; + GError *error = NULL; + + nm_assert (cancellable == g_task_get_cancellable (request_data->task)); + + nm_utils_error_set_cancelled (&error, FALSE, NULL); + + self = g_task_get_source_object (request_data->task); + + nm_clear_g_signal_handler (cancellable, &request_data->cancellable_id); + + _dbobjs_obj_watcher_unregister (self, g_steal_pointer (&request_data->obj_watcher)); + + g_task_return_error (request_data->task, error); + + _request_wait_data_free (request_data); +} + +static void +_request_wait_start (GTask *task_take, + const char *op_name, + GType gtype, + const char *dbus_path, + GVariant *extra_results_take) +{ + NMClient *self; + gs_unref_object GTask *task = g_steal_pointer (&task_take); + RequestWaitData *request_data; + GCancellable *cancellable; + NMLDBusObject *dbobj; + + nm_assert (G_IS_TASK (task)); + + self = g_task_get_source_object (task); + + dbobj = _dbobjs_get_nmobj (self, dbus_path, gtype); + + if (!dbobj) { + NML_NMCLIENT_LOG_E (self, "%s() succeeded with %s but object does not exist", op_name, dbus_path); + g_task_return_error (task, g_error_new (NM_CLIENT_ERROR, + NM_CLIENT_ERROR_FAILED, + _("operation succeeded but object %s does not exist"), + dbus_path)); + return; + } + + request_data = g_slice_new (RequestWaitData); + *request_data = (RequestWaitData) { + .task = g_steal_pointer (&task), + .op_name = op_name, + .gtype = gtype, + .dbobj = nml_dbus_object_ref (dbobj), + .obj_watcher = NULL, + .extra_results = g_steal_pointer (&extra_results_take), + .result = NULL, + .cancellable_id = 0, + }; + + if (_request_wait_complete (self, request_data, FALSE)) + return; + + NML_NMCLIENT_LOG_T (self, "%s() succeeded with %s. Wait for object to become ready", op_name, dbobj->dbus_path->str); + + request_data->obj_watcher = _dbobjs_obj_watcher_register_o (self, + dbobj, + _request_wait_obj_watcher_cb, + sizeof (NMLDBusObjWatcherWithPtr)); + request_data->obj_watcher->user_data = request_data; + + cancellable = g_task_get_cancellable (request_data->task); + if (cancellable) { + gulong id; + + id = g_cancellable_connect (cancellable, + G_CALLBACK (_request_wait_cancelled_cb), + request_data, + NULL); + if (id == 0) { + /* the callback was invoked synchronously, which destroyed @request_data. + * We must not touch @info anymore. */ + } else + request_data->cancellable_id = id; + } +} + +static gpointer * +_request_wait_finish (NMClient *client, + GAsyncResult *result, + gpointer source_tag, + GVariant **out_result, + GError **error) +{ + RequestWaitData *request_data = NULL; + gpointer r; + + g_return_val_if_fail (NM_IS_CLIENT (client), NULL); + g_return_val_if_fail (nm_g_task_is_valid (result, client, source_tag), NULL); + + request_data = g_task_propagate_pointer (G_TASK (result), error); + if (!request_data) { + NM_SET_OUT (out_result, NULL); + return NULL; + } + + nm_assert (NM_IS_OBJECT (request_data->result)); + + NM_SET_OUT (out_result, g_steal_pointer (&request_data->extra_results)); + r = g_steal_pointer (&request_data->result); + + _request_wait_data_free (request_data); + return r; +} + +/*****************************************************************************/ + /** * nm_client_get_dbus_connection: * @client: a #NMClient @@ -257,8 +3344,7 @@ nm_client_get_dbus_name_owner (NMClient *client) { g_return_val_if_fail (NM_IS_CLIENT (client), NULL); - /* FIXME(release-blocker): not yet implemented. */ - return NULL; + return NM_CLIENT_GET_PRIVATE (client)->name_owner; } /** @@ -274,10 +3360,7 @@ nm_client_get_version (NMClient *client) { g_return_val_if_fail (NM_IS_CLIENT (client), NULL); - if (!nm_client_get_nm_running (client)) - return NULL; - - return nm_manager_get_version (NM_CLIENT_GET_PRIVATE (client)->manager); + return NM_CLIENT_GET_PRIVATE (client)->nm.version; } /** @@ -293,10 +3376,7 @@ nm_client_get_state (NMClient *client) { g_return_val_if_fail (NM_IS_CLIENT (client), NM_STATE_UNKNOWN); - if (!nm_client_get_nm_running (client)) - return NM_STATE_UNKNOWN; - - return nm_manager_get_state (NM_CLIENT_GET_PRIVATE (client)->manager); + return NM_CLIENT_GET_PRIVATE (client)->nm.state; } /** @@ -313,10 +3393,20 @@ nm_client_get_startup (NMClient *client) { g_return_val_if_fail (NM_IS_CLIENT (client), FALSE); - if (!nm_client_get_nm_running (client)) - return FALSE; + return NM_CLIENT_GET_PRIVATE (client)->nm.startup; +} - return nm_manager_get_startup (NM_CLIENT_GET_PRIVATE (client)->manager); +static void +_set_nm_running (NMClient *self) +{ + NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self); + gboolean nm_running; + + nm_running = priv->name_owner && !priv->get_managed_objects_cancellable; + if (priv->nm_running != nm_running) { + priv->nm_running = nm_running; + _notify (self, PROP_NM_RUNNING); + } } /** @@ -332,7 +3422,23 @@ nm_client_get_nm_running (NMClient *client) { g_return_val_if_fail (NM_IS_CLIENT (client), FALSE); - return NM_CLIENT_GET_PRIVATE (client)->manager != NULL; + return NM_CLIENT_GET_PRIVATE (client)->nm_running; +} + +/** + * nm_client_get_metered: + * @client: a #NMClient + * + * Returns: whether the default route is metered. + * + * Since: 1.22 + */ +NMMetered +nm_client_get_metered (NMClient *client) +{ + g_return_val_if_fail (NM_IS_CLIENT (client), NM_METERED_UNKNOWN); + + return NM_CLIENT_GET_PRIVATE (client)->nm.metered; } /** @@ -348,10 +3454,7 @@ nm_client_networking_get_enabled (NMClient *client) { g_return_val_if_fail (NM_IS_CLIENT (client), FALSE); - if (!nm_client_get_nm_running (client)) - return FALSE; - - return nm_manager_networking_get_enabled (NM_CLIENT_GET_PRIVATE (client)->manager); + return NM_CLIENT_GET_PRIVATE (client)->nm.networking_enabled; } /** @@ -371,22 +3474,20 @@ nm_client_networking_get_enabled (NMClient *client) gboolean nm_client_networking_set_enabled (NMClient *client, gboolean enable, GError **error) { - const char *name_owner; - g_return_val_if_fail (NM_IS_CLIENT (client), FALSE); /* FIXME(libnm-async-api): add nm_client_networking_set_enabled_async(). */ - name_owner = _nm_client_get_dbus_name_owner (client); - if (!name_owner) { - _nm_object_set_error_nm_not_running (error); - return FALSE; - } - - return _nm_manager_networking_set_enabled (_nm_client_get_dbus_connection (client), - name_owner, - enable, - error); + return _nm_client_dbus_call_sync_void (client, + NULL, + NM_DBUS_PATH, + NM_DBUS_INTERFACE, + "Enable", + g_variant_new ("(b)", enable), + G_DBUS_CALL_FLAGS_NONE, + NM_DBUS_DEFAULT_TIMEOUT_MSEC, + TRUE, + error); } /** @@ -402,10 +3503,7 @@ nm_client_wireless_get_enabled (NMClient *client) { g_return_val_if_fail (NM_IS_CLIENT (client), FALSE); - if (!nm_client_get_nm_running (client)) - return FALSE; - - return nm_manager_wireless_get_enabled (NM_CLIENT_GET_PRIVATE (client)->manager); + return NM_CLIENT_GET_PRIVATE (client)->nm.wireless_enabled; } /** @@ -423,10 +3521,13 @@ nm_client_wireless_set_enabled (NMClient *client, gboolean enabled) g_return_if_fail (NM_IS_CLIENT (client)); /* FIXME(libnm-async-api): add nm_client_wireless_set_enabled_async(). */ - if (!nm_client_get_nm_running (client)) - return; - nm_manager_wireless_set_enabled (NM_CLIENT_GET_PRIVATE (client)->manager, enabled); + _nm_client_set_property_sync_legacy (client, + NM_DBUS_PATH, + NM_DBUS_INTERFACE, + "WirelessEnabled", + "b", + enabled); } /** @@ -442,10 +3543,7 @@ nm_client_wireless_hardware_get_enabled (NMClient *client) { g_return_val_if_fail (NM_IS_CLIENT (client), FALSE); - if (!nm_client_get_nm_running (client)) - return FALSE; - - return nm_manager_wireless_hardware_get_enabled (NM_CLIENT_GET_PRIVATE (client)->manager); + return NM_CLIENT_GET_PRIVATE (client)->nm.wireless_hardware_enabled; } /** @@ -461,10 +3559,7 @@ nm_client_wwan_get_enabled (NMClient *client) { g_return_val_if_fail (NM_IS_CLIENT (client), FALSE); - if (!nm_client_get_nm_running (client)) - return FALSE; - - return nm_manager_wwan_get_enabled (NM_CLIENT_GET_PRIVATE (client)->manager); + return NM_CLIENT_GET_PRIVATE (client)->nm.wwan_enabled; } /** @@ -479,10 +3574,14 @@ nm_client_wwan_set_enabled (NMClient *client, gboolean enabled) { g_return_if_fail (NM_IS_CLIENT (client)); - if (!_nm_client_check_nm_running (client, NULL)) - return; + /* FIXME(libnm-async-api): add nm_client_wwan_set_enabled_async(). */ - nm_manager_wwan_set_enabled (NM_CLIENT_GET_PRIVATE (client)->manager, enabled); + _nm_client_set_property_sync_legacy (client, + NM_DBUS_PATH, + NM_DBUS_INTERFACE, + "WwanEnabled", + "b", + enabled); } /** @@ -498,10 +3597,7 @@ nm_client_wwan_hardware_get_enabled (NMClient *client) { g_return_val_if_fail (NM_IS_CLIENT (client), FALSE); - if (!nm_client_get_nm_running (client)) - return FALSE; - - return nm_manager_wwan_hardware_get_enabled (NM_CLIENT_GET_PRIVATE (client)->manager); + return NM_CLIENT_GET_PRIVATE (client)->nm.wwan_hardware_enabled; } /** @@ -572,10 +3668,7 @@ nm_client_connectivity_check_get_available (NMClient *client) { g_return_val_if_fail (NM_IS_CLIENT (client), FALSE); - if (!nm_client_get_nm_running (client)) - return FALSE; - - return nm_manager_connectivity_check_get_available (NM_CLIENT_GET_PRIVATE (client)->manager); + return NM_CLIENT_GET_PRIVATE (client)->nm.connectivity_check_available; } /** @@ -593,10 +3686,7 @@ nm_client_connectivity_check_get_enabled (NMClient *client) { g_return_val_if_fail (NM_IS_CLIENT (client), FALSE); - if (!nm_client_get_nm_running (client)) - return FALSE; - - return nm_manager_connectivity_check_get_enabled (NM_CLIENT_GET_PRIVATE (client)->manager); + return NM_CLIENT_GET_PRIVATE (client)->nm.connectivity_check_enabled; } /** @@ -615,10 +3705,14 @@ nm_client_connectivity_check_set_enabled (NMClient *client, gboolean enabled) { g_return_if_fail (NM_IS_CLIENT (client)); - if (!nm_client_get_nm_running (client)) - return; + /* FIXME(libnm-async-api): add nm_client_wireless_set_enabled_async(). */ - nm_manager_connectivity_check_set_enabled (NM_CLIENT_GET_PRIVATE (client)->manager, enabled); + _nm_client_set_property_sync_legacy (client, + NM_DBUS_PATH, + NM_DBUS_INTERFACE, + "ConnectivityCheckEnabled", + "b", + enabled); } /** @@ -637,10 +3731,7 @@ nm_client_connectivity_check_get_uri (NMClient *client) { g_return_val_if_fail (NM_IS_CLIENT (client), NULL); - if (!nm_client_get_nm_running (client)) - return NULL; - - return nm_manager_connectivity_check_get_uri (NM_CLIENT_GET_PRIVATE (client)->manager); + return NM_CLIENT_GET_PRIVATE (client)->nm.connectivity_check_uri; } /** @@ -672,7 +3763,7 @@ nm_client_get_logging (NMClient *client, /* FIXME(libnm-async-api): add nm_client_get_logging_async(). */ - ret = _nm_object_dbus_call_sync (client, + ret = _nm_client_dbus_call_sync (client, NULL, NM_DBUS_PATH, NM_DBUS_INTERFACE, @@ -715,7 +3806,7 @@ nm_client_set_logging (NMClient *client, const char *level, const char *domains, /* FIXME(libnm-async-api): add nm_client_set_logging_async(). */ - return _nm_object_dbus_call_sync_void (client, + return _nm_client_dbus_call_sync_void (client, NULL, NM_DBUS_PATH, NM_DBUS_INTERFACE, @@ -742,12 +3833,19 @@ nm_client_set_logging (NMClient *client, const char *level, const char *domains, NMClientPermissionResult nm_client_get_permission_result (NMClient *client, NMClientPermission permission) { + NMClientPrivate *priv; + gpointer result; + g_return_val_if_fail (NM_IS_CLIENT (client), NM_CLIENT_PERMISSION_RESULT_UNKNOWN); - if (!nm_client_get_nm_running (client)) + priv = NM_CLIENT_GET_PRIVATE (client); + if ( !priv->permissions + || !g_hash_table_lookup_extended (priv->permissions, + GUINT_TO_POINTER (permission), + NULL, + &result)) return NM_CLIENT_PERMISSION_RESULT_UNKNOWN; - - return nm_manager_get_permission_result (NM_CLIENT_GET_PRIVATE (client)->manager, permission); + return GPOINTER_TO_UINT (result); } /** @@ -766,10 +3864,7 @@ nm_client_get_connectivity (NMClient *client) { g_return_val_if_fail (NM_IS_CLIENT (client), NM_CONNECTIVITY_UNKNOWN); - if (!nm_client_get_nm_running (client)) - return NM_CONNECTIVITY_UNKNOWN; - - return nm_manager_get_connectivity (NM_CLIENT_GET_PRIVATE (client)->manager); + return NM_CLIENT_GET_PRIVATE (client)->nm.connectivity; } /** @@ -794,12 +3889,13 @@ nm_client_check_connectivity (NMClient *client, GCancellable *cancellable, GError **error) { + NMClientPrivate *priv; gs_unref_variant GVariant *ret = NULL; guint32 connectivity; g_return_val_if_fail (NM_IS_CLIENT (client), NM_CONNECTIVITY_UNKNOWN); - ret = _nm_object_dbus_call_sync (client, + ret = _nm_client_dbus_call_sync (client, cancellable, NM_DBUS_PATH, NM_DBUS_INTERFACE, @@ -822,8 +3918,13 @@ nm_client_check_connectivity (NMClient *client, * "PropertiesChanged" signals). * * This is really ugly, we shouldn't do this. */ - _nm_manager_set_connectivity_hack (NM_CLIENT_GET_PRIVATE (client)->manager, - connectivity); + + priv = NM_CLIENT_GET_PRIVATE (client); + + if (priv->nm.connectivity != connectivity) { + priv->nm.connectivity = connectivity; + _notify (client, PROP_CONNECTIVITY); + } return connectivity; } @@ -849,7 +3950,8 @@ nm_client_check_connectivity_async (NMClient *client, g_return_if_fail (NM_IS_CLIENT (client)); g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable)); - _nm_object_dbus_call (client, + _nm_client_dbus_call (client, + client, nm_client_check_connectivity_async, cancellable, callback, @@ -920,7 +4022,7 @@ nm_client_save_hostname (NMClient *client, g_return_val_if_fail (NM_IS_CLIENT (client), FALSE); g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), FALSE); - return _nm_object_dbus_call_sync_void (client, + return _nm_client_dbus_call_sync_void (client, cancellable, NM_DBUS_PATH_SETTINGS, NM_DBUS_INTERFACE_SETTINGS, @@ -954,7 +4056,8 @@ nm_client_save_hostname_async (NMClient *client, g_return_if_fail (NM_IS_CLIENT (client)); g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable)); - _nm_object_dbus_call (client, + _nm_client_dbus_call (client, + client, nm_client_save_hostname_async, cancellable, callback, @@ -1012,10 +4115,7 @@ nm_client_get_devices (NMClient *client) { g_return_val_if_fail (NM_IS_CLIENT (client), NULL); - if (!nm_client_get_nm_running (client)) - return ∅ - - return nm_manager_get_devices (NM_CLIENT_GET_PRIVATE (client)->manager); + return nml_dbus_property_ao_get_objs_as_ptrarray (&NM_CLIENT_GET_PRIVATE (client)->nm.devices); } /** @@ -1043,10 +4143,7 @@ nm_client_get_all_devices (NMClient *client) { g_return_val_if_fail (NM_IS_CLIENT (client), NULL); - if (!nm_client_get_nm_running (client)) - return ∅ - - return nm_manager_get_all_devices (NM_CLIENT_GET_PRIVATE (client)->manager); + return nml_dbus_property_ao_get_objs_as_ptrarray (&NM_CLIENT_GET_PRIVATE (client)->nm.all_devices); } /** @@ -1064,10 +4161,7 @@ nm_client_get_device_by_path (NMClient *client, const char *object_path) g_return_val_if_fail (NM_IS_CLIENT (client), NULL); g_return_val_if_fail (object_path, NULL); - if (!nm_client_get_nm_running (client)) - return NULL; - - return nm_manager_get_device_by_path (NM_CLIENT_GET_PRIVATE (client)->manager, object_path); + return _dbobjs_get_nmobj_unpack_visible (client, object_path, NM_TYPE_DEVICE); } /** @@ -1082,13 +4176,21 @@ nm_client_get_device_by_path (NMClient *client, const char *object_path) NMDevice * nm_client_get_device_by_iface (NMClient *client, const char *iface) { + const GPtrArray *devices; + guint i; + g_return_val_if_fail (NM_IS_CLIENT (client), NULL); g_return_val_if_fail (iface, NULL); - if (!nm_client_get_nm_running (client)) - return NULL; + devices = nm_client_get_devices (client); + for (i = 0; i < devices->len; i++) { + NMDevice *candidate = g_ptr_array_index (devices, i); + + if (nm_streq0 (nm_device_get_iface (candidate), iface)) + return candidate; + } - return nm_manager_get_device_by_iface (NM_CLIENT_GET_PRIVATE (client)->manager, iface); + return NULL; } /*****************************************************************************/ @@ -1110,10 +4212,7 @@ nm_client_get_active_connections (NMClient *client) { g_return_val_if_fail (NM_IS_CLIENT (client), NULL); - if (!nm_client_get_nm_running (client)) - return ∅ - - return nm_manager_get_active_connections (NM_CLIENT_GET_PRIVATE (client)->manager); + return nml_dbus_property_ao_get_objs_as_ptrarray (&NM_CLIENT_GET_PRIVATE (client)->nm.active_connections); } /** @@ -1140,10 +4239,7 @@ nm_client_get_primary_connection (NMClient *client) { g_return_val_if_fail (NM_IS_CLIENT (client), NULL); - if (!nm_client_get_nm_running (client)) - return NULL; - - return nm_manager_get_primary_connection (NM_CLIENT_GET_PRIVATE (client)->manager); + return nml_dbus_property_o_get_obj (&NM_CLIENT_GET_PRIVATE (client)->nm.primary_connection); } /** @@ -1162,18 +4258,16 @@ nm_client_get_activating_connection (NMClient *client) { g_return_val_if_fail (NM_IS_CLIENT (client), NULL); - if (!nm_client_get_nm_running (client)) - return NULL; - - return nm_manager_get_activating_connection (NM_CLIENT_GET_PRIVATE (client)->manager); + return nml_dbus_property_o_get_obj (&NM_CLIENT_GET_PRIVATE (client)->nm.activating_connection); } +/*****************************************************************************/ + static void activate_connection_cb (GObject *object, GAsyncResult *result, gpointer user_data) { - NMClient *self; gs_unref_object GTask *task = user_data; gs_unref_variant GVariant *ret = NULL; const char *v_active_connection; @@ -1181,20 +4275,19 @@ activate_connection_cb (GObject *object, ret = g_dbus_connection_call_finish (G_DBUS_CONNECTION (object), result, &error); if (!ret) { - g_dbus_error_strip_remote_error (error); + if (!nm_utils_error_is_cancelled (error, FALSE)) + g_dbus_error_strip_remote_error (error); g_task_return_error (task, error); return; } - self = g_task_get_source_object (task); - g_variant_get (ret, "(&o)", &v_active_connection); - nm_manager_wait_for_active_connection (NM_CLIENT_GET_PRIVATE (self)->manager, - v_active_connection, - NULL, - NULL, - g_steal_pointer (&task)); + _request_wait_start (g_steal_pointer (&task), + "ActivateConnection", + NM_TYPE_ACTIVE_CONNECTION, + v_active_connection, + NULL); } /** @@ -1256,7 +4349,13 @@ nm_client_activate_connection_async (NMClient *client, g_return_if_fail (arg_device); } - _nm_object_dbus_call (client, + NML_NMCLIENT_LOG_T (client, "ActivateConnection() for connection \"%s\", device \"%s\", specific_object \"%s", + arg_connection ?: "/", + arg_device ?: "/", + specific_object ?: "/"); + + _nm_client_dbus_call (client, + client, nm_client_activate_connection_async, cancellable, callback, @@ -1290,17 +4389,15 @@ nm_client_activate_connection_finish (NMClient *client, GAsyncResult *result, GError **error) { - nm_auto_free_activate_result _NMActivateResult *r = NULL; - - g_return_val_if_fail (NM_IS_CLIENT (client), NULL); - g_return_val_if_fail (nm_g_task_is_valid (result, client, nm_client_activate_connection_async), NULL); - - r = g_task_propagate_pointer (G_TASK (result), error); - if (!r) - return NULL; - return g_steal_pointer (&r->active); + return NM_ACTIVE_CONNECTION (_request_wait_finish (client, + result, + nm_client_activate_connection_async, + NULL, + error)); } +/*****************************************************************************/ + static void _add_and_activate_connection_done (GObject *object, GAsyncResult *result, @@ -1308,22 +4405,20 @@ _add_and_activate_connection_done (GObject *object, GTask *task_take) { _nm_unused gs_unref_object GTask *task = task_take; - NMClient *self; gs_unref_variant GVariant *ret = NULL; GError *error = NULL; - const char *v_path; - const char *v_active_connection; gs_unref_variant GVariant *v_result = NULL; + const char *v_active_connection; + const char *v_path; ret = g_dbus_connection_call_finish (G_DBUS_CONNECTION (object), result, &error); if (!ret) { - g_dbus_error_strip_remote_error (error); + if (!nm_utils_error_is_cancelled (error, FALSE)) + g_dbus_error_strip_remote_error (error); g_task_return_error (task, error); return; } - self = g_task_get_source_object (task); - if (use_add_and_activate_v2) { g_variant_get (ret, "(&o&o@a{sv})", @@ -1337,11 +4432,11 @@ _add_and_activate_connection_done (GObject *object, &v_active_connection); } - nm_manager_wait_for_active_connection (NM_CLIENT_GET_PRIVATE (self)->manager, - v_active_connection, - v_path, - g_steal_pointer (&v_result), - g_steal_pointer (&task)); + _request_wait_start (g_steal_pointer (&task), + "AddAndActivateConnection", + NM_TYPE_ACTIVE_CONNECTION, + v_active_connection, + g_steal_pointer (&v_result)); } static void @@ -1357,7 +4452,7 @@ _add_and_activate_connection_v2_cb (GObject *object, GAsyncResult *result, gpoin } static void -_add_and_activate_connection (NMClient *client, +_add_and_activate_connection (NMClient *self, gboolean is_v2, NMConnection *partial, NMDevice *device, @@ -1372,7 +4467,7 @@ _add_and_activate_connection (NMClient *client, const char *arg_device = NULL; gpointer source_tag; - g_return_if_fail (NM_IS_CLIENT (client)); + g_return_if_fail (NM_IS_CLIENT (self)); g_return_if_fail (!partial || NM_IS_CONNECTION (partial)); if (device) { @@ -1401,8 +4496,11 @@ _add_and_activate_connection (NMClient *client, source_tag = nm_client_add_and_activate_connection_async; } + NML_NMCLIENT_LOG_D (self, "AddAndActivateConnection() started..."); + if (use_add_and_activate_v2) { - _nm_object_dbus_call (client, + _nm_client_dbus_call (self, + self, source_tag, cancellable, callback, @@ -1420,7 +4518,8 @@ _add_and_activate_connection (NMClient *client, NM_DBUS_DEFAULT_TIMEOUT_MSEC, _add_and_activate_connection_v2_cb); } else { - _nm_object_dbus_call (client, + _nm_client_dbus_call (self, + self, source_tag, cancellable, callback, @@ -1508,15 +4607,11 @@ nm_client_add_and_activate_connection_finish (NMClient *client, GAsyncResult *result, GError **error) { - nm_auto_free_activate_result _NMActivateResult *r = NULL; - - g_return_val_if_fail (NM_IS_CLIENT (client), NULL); - g_return_val_if_fail (nm_g_task_is_valid (result, client, nm_client_add_and_activate_connection_async), NULL); - - r = g_task_propagate_pointer (G_TASK (result), error); - if (!r) - return NULL; - return g_steal_pointer (&r->active); + return NM_ACTIVE_CONNECTION (_request_wait_finish (client, + result, + nm_client_add_and_activate_connection_async, + NULL, + error)); } /** @@ -1606,20 +4701,15 @@ nm_client_add_and_activate_connection2_finish (NMClient *client, GVariant **out_result, GError **error) { - nm_auto_free_activate_result _NMActivateResult *r = NULL; - - g_return_val_if_fail (NM_IS_CLIENT (client), NULL); - g_return_val_if_fail (nm_g_task_is_valid (result, client, nm_client_add_and_activate_connection2), NULL); - - r = g_task_propagate_pointer (G_TASK (result), error); - if (!r) { - NM_SET_OUT (out_result, NULL); - return NULL; - } - NM_SET_OUT (out_result, g_steal_pointer (&r->add_and_activate_output)); - return g_steal_pointer (&r->active); + return NM_ACTIVE_CONNECTION (_request_wait_finish (client, + result, + nm_client_add_connection2, + out_result, + error)); } +/*****************************************************************************/ + /** * nm_client_deactivate_connection: * @client: a #NMClient @@ -1647,7 +4737,7 @@ nm_client_deactivate_connection (NMClient *client, active_path = nm_object_get_path (NM_OBJECT (active)); g_return_val_if_fail (active_path, FALSE); - return _nm_object_dbus_call_sync_void (client, + return _nm_client_dbus_call_sync_void (client, cancellable, NM_DBUS_PATH, NM_DBUS_INTERFACE, @@ -1684,7 +4774,8 @@ nm_client_deactivate_connection_async (NMClient *client, active_path = nm_object_get_path (NM_OBJECT (active)); g_return_if_fail (active_path); - _nm_object_dbus_call (client, + _nm_client_dbus_call (client, + client, nm_client_deactivate_connection_async, cancellable, callback, @@ -1740,10 +4831,7 @@ nm_client_get_connections (NMClient *client) { g_return_val_if_fail (NM_IS_CLIENT (client), NULL); - if (!nm_client_get_nm_running (client)) - return ∅ - - return nm_remote_settings_get_connections (NM_CLIENT_GET_PRIVATE (client)->settings); + return nml_dbus_property_ao_get_objs_as_ptrarray (&NM_CLIENT_GET_PRIVATE (client)->settings.connections); } /** @@ -1762,13 +4850,20 @@ nm_client_get_connections (NMClient *client) NMRemoteConnection * nm_client_get_connection_by_id (NMClient *client, const char *id) { + const GPtrArray *arr; + guint i; + g_return_val_if_fail (NM_IS_CLIENT (client), NULL); - g_return_val_if_fail (id != NULL, NULL); + g_return_val_if_fail (id, NULL); - if (!nm_client_get_nm_running (client)) - return NULL; + arr = nm_client_get_connections (client); + for (i = 0; i < arr->len; i++) { + NMRemoteConnection *c = NM_REMOTE_CONNECTION (arr->pdata[i]); - return nm_remote_settings_get_connection_by_id (NM_CLIENT_GET_PRIVATE (client)->settings, id); + if (nm_streq0 (id, nm_connection_get_id (NM_CONNECTION (c)))) + return c; + } + return NULL; } /** @@ -1790,10 +4885,7 @@ nm_client_get_connection_by_path (NMClient *client, const char *path) g_return_val_if_fail (NM_IS_CLIENT (client), NULL); g_return_val_if_fail (path != NULL, NULL); - if (!nm_client_get_nm_running (client)) - return NULL; - - return nm_remote_settings_get_connection_by_path (NM_CLIENT_GET_PRIVATE (client)->settings, path); + return _dbobjs_get_nmobj_unpack_visible (client, path, NM_TYPE_REMOTE_CONNECTION); } /** @@ -1812,22 +4904,30 @@ nm_client_get_connection_by_path (NMClient *client, const char *path) NMRemoteConnection * nm_client_get_connection_by_uuid (NMClient *client, const char *uuid) { + const GPtrArray *arr; + guint i; + g_return_val_if_fail (NM_IS_CLIENT (client), NULL); - g_return_val_if_fail (uuid != NULL, NULL); + g_return_val_if_fail (uuid, NULL); - if (!nm_client_get_nm_running (client)) - return NULL; + arr = nm_client_get_connections (client); + for (i = 0; i < arr->len; i++) { + NMRemoteConnection *c = NM_REMOTE_CONNECTION (arr->pdata[i]); - return nm_remote_settings_get_connection_by_uuid (NM_CLIENT_GET_PRIVATE (client)->settings, uuid); + if (nm_streq0 (uuid, nm_connection_get_uuid (NM_CONNECTION (c)))) + return c; + } + return NULL; } +/*****************************************************************************/ + static void _add_connection_cb (GObject *source, GAsyncResult *result, gboolean with_extra_arg, gpointer user_data) { - NMClient *self; gs_unref_variant GVariant *ret = NULL; gs_unref_object GTask *task = user_data; gs_unref_variant GVariant *v_result = NULL; @@ -1836,7 +4936,8 @@ _add_connection_cb (GObject *source, ret = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), result, &error); if (!ret) { - g_dbus_error_strip_remote_error (error); + if (!nm_utils_error_is_cancelled (error, FALSE)) + g_dbus_error_strip_remote_error (error); g_task_return_error (task, error); return; } @@ -1852,12 +4953,11 @@ _add_connection_cb (GObject *source, &v_path); } - self = g_task_get_source_object (task); - - nm_remote_settings_wait_for_connection (NM_CLIENT_GET_PRIVATE (self)->settings, - v_path, - g_steal_pointer (&v_result), - g_steal_pointer (&task)); + _request_wait_start (g_steal_pointer (&task), + "AddConnection", + NM_TYPE_REMOTE_CONNECTION, + v_path, + g_steal_pointer (&v_result)); } static void @@ -1887,6 +4987,8 @@ _add_connection_call (NMClient *self, g_return_if_fail (!settings || g_variant_is_of_type (settings, G_VARIANT_TYPE ("a{sa{sv}}"))); g_return_if_fail (!args || g_variant_is_of_type (args, G_VARIANT_TYPE ("a{sv}"))); + NML_NMCLIENT_LOG_D (self, "AddConnection() started..."); + if (!settings) settings = g_variant_new_array (G_VARIANT_TYPE ("{sa{sv}}"), NULL, 0); @@ -1896,7 +4998,8 @@ _add_connection_call (NMClient *self, * on 1.20 API whenever possible. */ if ( ignore_out_result && flags == NM_SETTINGS_ADD_CONNECTION2_FLAG_TO_DISK) { - _nm_object_dbus_call (self, + _nm_client_dbus_call (self, + self, source_tag, cancellable, callback, @@ -1911,7 +5014,8 @@ _add_connection_call (NMClient *self, _add_connection_cb_without_extra_result); } else if ( ignore_out_result && flags == NM_SETTINGS_ADD_CONNECTION2_FLAG_IN_MEMORY) { - _nm_object_dbus_call (self, + _nm_client_dbus_call (self, + self, source_tag, cancellable, callback, @@ -1925,7 +5029,8 @@ _add_connection_call (NMClient *self, NM_DBUS_DEFAULT_TIMEOUT_MSEC, _add_connection_cb_without_extra_result); } else { - _nm_object_dbus_call (self, + _nm_client_dbus_call (self, + self, source_tag, cancellable, callback, @@ -1945,38 +5050,6 @@ _add_connection_call (NMClient *self, } } -static NMRemoteConnection * -_add_connection_call_finish (NMClient *client, - GAsyncResult *result, - gpointer source_tag, - GVariant **out_result, - GError **error) -{ - nm_auto_free_add_connection_result_data NMAddConnectionResultData *result_data = NULL; - - g_return_val_if_fail (NM_IS_CLIENT (client), NULL); - g_return_val_if_fail (nm_g_task_is_valid (result, client, source_tag), NULL); - - result_data = g_task_propagate_pointer (G_TASK (result), error); - if (!result_data) { - NM_SET_OUT (out_result, NULL); - return NULL; - } - - nm_assert (NM_IS_REMOTE_CONNECTION (result_data->connection)); - - NM_SET_OUT (out_result, g_steal_pointer (&result_data->extra_results)); - return g_steal_pointer (&result_data->connection); -} - -void -nm_add_connection_result_data_free (NMAddConnectionResultData *result_data) -{ - nm_g_object_unref (result_data->connection); - nm_g_variant_unref (result_data->extra_results); - nm_g_slice_free (result_data); -} - /** * nm_client_add_connection_async: * @client: the %NMClient @@ -2041,11 +5114,11 @@ nm_client_add_connection_finish (NMClient *client, GAsyncResult *result, GError **error) { - return _add_connection_call_finish (client, - result, - nm_client_add_connection_async, - NULL, - error); + return NM_REMOTE_CONNECTION (_request_wait_finish (client, + result, + nm_client_add_connection_async, + NULL, + error)); } /** @@ -2112,13 +5185,15 @@ nm_client_add_connection2_finish (NMClient *client, GVariant **out_result, GError **error) { - return _add_connection_call_finish (client, - result, - nm_client_add_connection2, - out_result, - error); + return NM_REMOTE_CONNECTION (_request_wait_finish (client, + result, + nm_client_add_connection2, + out_result, + error)); } +/*****************************************************************************/ + /** * nm_client_load_connections: * @client: the %NMClient @@ -2165,7 +5240,7 @@ nm_client_load_connections (NMClient *client, g_return_val_if_fail (NM_IS_CLIENT (client), FALSE); g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), FALSE); - ret = _nm_object_dbus_call_sync (client, + ret = _nm_client_dbus_call_sync (client, cancellable, NM_DBUS_PATH_SETTINGS, NM_DBUS_INTERFACE_SETTINGS, @@ -2213,7 +5288,8 @@ nm_client_load_connections_async (NMClient *client, g_return_if_fail (NM_IS_CLIENT (client)); g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable)); - _nm_object_dbus_call (client, + _nm_client_dbus_call (client, + client, nm_client_load_connections_async, cancellable, callback, @@ -2293,7 +5369,7 @@ nm_client_reload_connections (NMClient *client, g_return_val_if_fail (NM_IS_CLIENT (client), FALSE); g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), FALSE); - ret = _nm_object_dbus_call_sync (client, + ret = _nm_client_dbus_call_sync (client, cancellable, NM_DBUS_PATH_SETTINGS, NM_DBUS_INTERFACE_SETTINGS, @@ -2330,7 +5406,8 @@ nm_client_reload_connections_async (NMClient *client, g_return_if_fail (NM_IS_CLIENT (client)); g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable)); - _nm_object_dbus_call (client, + _nm_client_dbus_call (client, + client, nm_client_reload_connections_async, cancellable, callback, @@ -2388,15 +5465,9 @@ nm_client_reload_connections_finish (NMClient *client, const char * nm_client_get_dns_mode (NMClient *client) { - NMClientPrivate *priv; - g_return_val_if_fail (NM_IS_CLIENT (client), NULL); - priv = NM_CLIENT_GET_PRIVATE (client); - if (priv->dns_manager) - return nm_dns_manager_get_mode (priv->dns_manager); - else - return NULL; + return NM_CLIENT_GET_PRIVATE (client)->dns_manager.mode; } /** @@ -2413,15 +5484,9 @@ nm_client_get_dns_mode (NMClient *client) const char * nm_client_get_dns_rc_manager (NMClient *client) { - NMClientPrivate *priv; - g_return_val_if_fail (NM_IS_CLIENT (client), NULL); - priv = NM_CLIENT_GET_PRIVATE (client); - if (priv->dns_manager) - return nm_dns_manager_get_rc_manager (priv->dns_manager); - else - return NULL; + return NM_CLIENT_GET_PRIVATE (client)->dns_manager.rc_manager; } /** @@ -2440,115 +5505,88 @@ nm_client_get_dns_rc_manager (NMClient *client) const GPtrArray * nm_client_get_dns_configuration (NMClient *client) { - NMClientPrivate *priv; - g_return_val_if_fail (NM_IS_CLIENT (client), NULL); - priv = NM_CLIENT_GET_PRIVATE (client); - if (priv->dns_manager) - return nm_dns_manager_get_configuration (priv->dns_manager); - else - return NULL; + return NM_CLIENT_GET_PRIVATE (client)->dns_manager.configuration; } -/*****************************************************************************/ - -static void -subobject_notify (GObject *object, - GParamSpec *pspec, - gpointer client) +static NMLDBusNotifyUpdatePropFlags +_notify_update_prop_dns_manager_configuration (NMClient *self, + NMLDBusObject *dbobj, + const NMLDBusMetaIface *meta_iface, + guint dbus_property_idx, + GVariant *value) { - if (!g_str_has_suffix (pspec->name, "-internal")) - g_object_notify (client, pspec->name); -} + NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self); + gs_unref_ptrarray GPtrArray *configuration_old = NULL; + gs_unref_ptrarray GPtrArray *configuration_new = NULL; + + nm_assert (G_OBJECT (self) == dbobj->nmobj); + + if (value) { + GVariant *entry_var_tmp; + GVariantIter iter; + GPtrArray *array; + + configuration_new = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_dns_entry_unref); + + g_variant_iter_init (&iter, value); + while (g_variant_iter_next (&iter, "@a{sv}", &entry_var_tmp)) { + gs_unref_variant GVariant *entry_var = entry_var_tmp; + nm_auto_free_variant_iter GVariantIter *iterp_nameservers = NULL; + nm_auto_free_variant_iter GVariantIter *iterp_domains = NULL; + gs_free char **nameservers = NULL; + gs_free char **domains = NULL; + gboolean vpn = FALSE; + NMDnsEntry *entry; + char *interface = NULL; + char *str; + gint32 priority = 0; + + if ( !g_variant_lookup (entry_var, "nameservers", "as", &iterp_nameservers) + || !g_variant_lookup (entry_var, "priority", "i", &priority)) { + g_warning ("Ignoring invalid DNS configuration"); + continue; + } -static void -manager_device_added (NMManager *manager, - NMDevice *device, - gpointer client) -{ - g_signal_emit (client, signals[DEVICE_ADDED], 0, device); -} + array = g_ptr_array_new (); + while (g_variant_iter_next (iterp_nameservers, "&s", &str)) + g_ptr_array_add (array, str); + g_ptr_array_add (array, NULL); + nameservers = (char **) g_ptr_array_free (array, FALSE); + + if (g_variant_lookup (entry_var, "domains", "as", &iterp_domains)) { + array = g_ptr_array_new (); + while (g_variant_iter_next (iterp_domains, "&s", &str)) + g_ptr_array_add (array, str); + g_ptr_array_add (array, NULL); + domains = (char **) g_ptr_array_free (array, FALSE); + } -static void -manager_device_removed (NMManager *manager, - NMDevice *device, - gpointer client) -{ - g_signal_emit (client, signals[DEVICE_REMOVED], 0, device); -} + g_variant_lookup (entry_var, "interface", "&s", &interface); + g_variant_lookup (entry_var, "vpn", "b", &vpn); -static void -manager_any_device_added (NMManager *manager, - NMDevice *device, - gpointer client) -{ - g_signal_emit (client, signals[ANY_DEVICE_ADDED], 0, device); -} - -static void -manager_any_device_removed (NMManager *manager, - NMDevice *device, - gpointer client) -{ - g_signal_emit (client, signals[ANY_DEVICE_REMOVED], 0, device); -} + entry = nm_dns_entry_new (interface, + (const char *const*) nameservers, + (const char *const*) domains, + priority, + vpn); + if (!entry) { + g_warning ("Ignoring invalid DNS entry"); + continue; + } -static void -manager_permission_changed (NMManager *manager, - NMClientPermission permission, - NMClientPermissionResult result, - gpointer client) -{ - g_signal_emit (client, signals[PERMISSION_CHANGED], 0, permission, result); -} + g_ptr_array_add (configuration_new, entry); + } + } -static void -settings_connection_added (NMRemoteSettings *manager, - NMRemoteConnection *connection, - gpointer client) -{ - g_signal_emit (client, signals[CONNECTION_ADDED], 0, connection); -} -static void -settings_connection_removed (NMRemoteSettings *manager, - NMRemoteConnection *connection, - gpointer client) -{ - g_signal_emit (client, signals[CONNECTION_REMOVED], 0, connection); -} + configuration_old = priv->dns_manager.configuration; + priv->dns_manager.configuration = g_steal_pointer (&configuration_new); -static void -manager_active_connection_added (NMManager *manager, - NMActiveConnection *active_connection, - gpointer client) -{ - g_signal_emit (client, signals[ACTIVE_CONNECTION_ADDED], 0, active_connection); + return NML_DBUS_NOTIFY_UPDATE_PROP_FLAGS_NOTIFY; } -static void -manager_active_connection_removed (NMManager *manager, - NMActiveConnection *active_connection, - gpointer client) -{ - g_signal_emit (client, signals[ACTIVE_CONNECTION_REMOVED], 0, active_connection); -} - -static void -dns_notify (GObject *object, - GParamSpec *pspec, - gpointer client) -{ - char pname[128]; - - if (NM_IN_STRSET (pspec->name, - NM_DNS_MANAGER_MODE, - NM_DNS_MANAGER_RC_MANAGER, - NM_DNS_MANAGER_CONFIGURATION)) { - nm_sprintf_buf (pname, "dns-%s", pspec->name); - g_object_notify (client, pname); - } -} +/*****************************************************************************/ /** * nm_client_get_checkpoints: @@ -2567,10 +5605,7 @@ nm_client_get_checkpoints (NMClient *client) { g_return_val_if_fail (NM_IS_CLIENT (client), NULL); - if (!nm_client_get_nm_running (client)) - return ∅ - - return nm_manager_get_checkpoints (NM_CLIENT_GET_PRIVATE (client)->manager); + return nml_dbus_property_ao_get_objs_as_ptrarray (&NM_CLIENT_GET_PRIVATE (client)->nm.checkpoints); } static void @@ -2597,9 +5632,11 @@ checkpoint_create_cb (GObject *object, self = g_task_get_source_object (task); - nm_manager_wait_for_checkpoint (NM_CLIENT_GET_PRIVATE (self)->manager, - checkpoint_path, - g_steal_pointer (&task)); + // + (void)self; + //nm_manager_wait_for_checkpoint (NM_CLIENT_GET_PRIVATE (self)->manager, + // checkpoint_path, + // g_steal_pointer (&task)); } /** @@ -2642,7 +5679,8 @@ nm_client_checkpoint_create (NMClient *client, paths[i] = NULL; } - _nm_object_dbus_call (client, + _nm_client_dbus_call (client, + client, nm_client_checkpoint_create, cancellable, callback, @@ -2706,7 +5744,8 @@ nm_client_checkpoint_destroy (NMClient *client, g_return_if_fail (NM_IS_CLIENT (client)); g_return_if_fail (checkpoint_path && checkpoint_path[0] == '/'); - _nm_object_dbus_call (client, + _nm_client_dbus_call (client, + client, nm_client_checkpoint_destroy, cancellable, callback, @@ -2767,7 +5806,8 @@ nm_client_checkpoint_rollback (NMClient *client, g_return_if_fail (NM_IS_CLIENT (client)); g_return_if_fail (checkpoint_path && checkpoint_path[0] == '/'); - _nm_object_dbus_call (client, + _nm_client_dbus_call (client, + client, nm_client_checkpoint_rollback, cancellable, callback, @@ -2854,7 +5894,8 @@ nm_client_checkpoint_adjust_rollback_timeout (NMClient *client, g_return_if_fail (NM_IS_CLIENT (client)); g_return_if_fail (checkpoint_path && checkpoint_path[0] == '/'); - _nm_object_dbus_call (client, + _nm_client_dbus_call (client, + client, nm_client_checkpoint_adjust_rollback_timeout, cancellable, callback, @@ -2919,7 +5960,8 @@ nm_client_reload (NMClient *client, { g_return_if_fail (NM_IS_CLIENT (client)); - _nm_object_dbus_call (client, + _nm_client_dbus_call (client, + client, nm_client_reload, cancellable, callback, @@ -2957,530 +5999,464 @@ nm_client_reload_finish (NMClient *client, return g_task_propagate_boolean (G_TASK (result), error); } -/****************************************************************/ -/* Object Initialization */ -/****************************************************************/ +/*****************************************************************************/ -static GType -proxy_type (GDBusObjectManagerClient *manager, - const char *object_path, - const char *interface_name, - gpointer user_data) +static void +_init_fetch_all (NMClient *self) { - /* ObjectManager asks us for an object proxy. Unfortunately, we can't - * decide that by interface name and GDBusObjectManager doesn't allow - * us to look at the known interface list. Thus we need to create a - * generic GDBusObject and only couple a NMObject subclass later. */ - if (!interface_name) - return G_TYPE_DBUS_OBJECT_PROXY; - - /* An interface proxy */ - if (strcmp (interface_name, NM_DBUS_INTERFACE) == 0) - return NMDBUS_TYPE_MANAGER_PROXY; - else if (strcmp (interface_name, NM_DBUS_INTERFACE_DEVICE_WIRELESS) == 0) - return NMDBUS_TYPE_DEVICE_WIFI_PROXY; - else if (strcmp (interface_name, NM_DBUS_INTERFACE_DEVICE_WIFI_P2P) == 0) - return NMDBUS_TYPE_DEVICE_WIFI_P2P_PROXY; - else if (strcmp (interface_name, NM_DBUS_INTERFACE_DEVICE) == 0) - return NMDBUS_TYPE_DEVICE_PROXY; - else if (strcmp (interface_name, NM_DBUS_INTERFACE_SETTINGS_CONNECTION) == 0) - return NMDBUS_TYPE_SETTINGS_CONNECTION_PROXY; - else if (strcmp (interface_name, NM_DBUS_INTERFACE_SETTINGS) == 0) - return NMDBUS_TYPE_SETTINGS_PROXY; - else if (strcmp (interface_name, NM_DBUS_INTERFACE_DNS_MANAGER) == 0) - return NMDBUS_TYPE_DNS_MANAGER_PROXY; - else if (strcmp (interface_name, NM_DBUS_INTERFACE_VPN_CONNECTION) == 0) - return NMDBUS_TYPE_VPN_CONNECTION_PROXY; - else if (strcmp (interface_name, NM_DBUS_INTERFACE_ACTIVE_CONNECTION) == 0) - return NMDBUS_TYPE_ACTIVE_CONNECTION_PROXY; - - /* Use a generic D-Bus Proxy whenever we can. The typed GDBusProxy - * subclasses actually use quite some memory, so they're better avoided. */ - return G_TYPE_DBUS_PROXY; -} - -static NMObject * -obj_nm_for_gdbus_object (NMClient *self, GDBusObject *object, GDBusObjectManager *object_manager) + NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self); + nm_auto_pop_gmaincontext GMainContext *dbus_context = NULL; + + dbus_context = nm_g_main_context_push_thread_default_if_necessary (priv->dbus_context); + + NML_NMCLIENT_LOG_D (self, "fetch all"); + + nm_assert (!priv->get_managed_objects_cancellable); + + priv->get_managed_objects_cancellable = g_cancellable_new (); + + priv->dbsid_nm_object_manager = nm_dbus_connection_signal_subscribe_object_manager (priv->dbus_connection, + priv->name_owner, + "/org/freedesktop", + _dbus_managed_objects_changed_cb, + self, + NULL); + + priv->dbsid_dbus_properties_properties_changed = nm_dbus_connection_signal_subscribe_properties_changed (priv->dbus_connection, + priv->name_owner, + NULL, + NULL, + _dbus_properties_changed_cb, + self, + NULL); + + priv->dbsid_nm_settings_connection_updated = g_dbus_connection_signal_subscribe (priv->dbus_connection, + priv->name_owner, + NM_DBUS_INTERFACE_SETTINGS_CONNECTION, + "Updated", + NULL, + NULL, + G_DBUS_SIGNAL_FLAGS_NONE, + _dbus_settings_updated_cb, + self, + NULL); + + priv->dbsid_nm_connection_active_state_changed = g_dbus_connection_signal_subscribe (priv->dbus_connection, + priv->name_owner, + NM_DBUS_INTERFACE_ACTIVE_CONNECTION, + "StateChanged", + NULL, + NULL, + G_DBUS_SIGNAL_FLAGS_NONE, + _dbus_nm_connection_active_state_changed_cb, + self, + NULL); + + priv->dbsid_nm_vpn_connection_state_changed = g_dbus_connection_signal_subscribe (priv->dbus_connection, + priv->name_owner, + NM_DBUS_INTERFACE_VPN_CONNECTION, + "VpnStateChanged", + NULL, + NULL, + G_DBUS_SIGNAL_FLAGS_NONE, + _dbus_nm_vpn_connection_state_changed_cb, + self, + NULL); + + priv->dbsid_nm_check_permissions = g_dbus_connection_signal_subscribe (priv->dbus_connection, + priv->name_owner, + NM_DBUS_INTERFACE, + "CheckPermissions", + NULL, + NULL, + G_DBUS_SIGNAL_FLAGS_NONE, + _dbus_nm_check_permissions_cb, + self, + NULL); + + nm_dbus_connection_call_get_managed_objects (priv->dbus_connection, + priv->name_owner, + "/org/freedesktop", + G_DBUS_CALL_FLAGS_NO_AUTO_START, + NM_DBUS_DEFAULT_TIMEOUT_MSEC, + priv->get_managed_objects_cancellable, + _dbus_get_managed_objects_cb, + self); + + _dbus_check_permissions_start (self); +} + +static void +_init_release_all (NMClient *self) { - NMClientPrivate *priv; - GList *interfaces; - GList *l; - GType type = G_TYPE_INVALID; - NMObject *obj_nm; - - g_return_val_if_fail (G_IS_DBUS_OBJECT_PROXY (object), NULL); - - interfaces = g_dbus_object_get_interfaces (object); - for (l = interfaces; l; l = l->next) { - GDBusProxy *proxy = G_DBUS_PROXY (l->data); - const char *ifname = g_dbus_proxy_get_interface_name (proxy); - - /* This is a performance/scalability hack. It makes sense to call it - * from here, since this is in the common object creation path. */ - _nm_dbus_proxy_replace_match (proxy); - - if (strcmp (ifname, NM_DBUS_INTERFACE) == 0) - type = NM_TYPE_MANAGER; - else if (strcmp (ifname, NM_DBUS_INTERFACE_ACCESS_POINT) == 0) - type = NM_TYPE_ACCESS_POINT; - else if (strcmp (ifname, NM_DBUS_INTERFACE_ACTIVE_CONNECTION) == 0 && type != NM_TYPE_VPN_CONNECTION) - type = NM_TYPE_ACTIVE_CONNECTION; - else if (strcmp (ifname, NM_DBUS_INTERFACE_DEVICE_6LOWPAN) == 0) - type = NM_TYPE_DEVICE_6LOWPAN; - else if (strcmp (ifname, NM_DBUS_INTERFACE_DEVICE_ADSL) == 0) - type = NM_TYPE_DEVICE_ADSL; - else if (strcmp (ifname, NM_DBUS_INTERFACE_DEVICE_BOND) == 0) - type = NM_TYPE_DEVICE_BOND; - else if (strcmp (ifname, NM_DBUS_INTERFACE_DEVICE_BRIDGE) == 0) - type = NM_TYPE_DEVICE_BRIDGE; - else if (strcmp (ifname, NM_DBUS_INTERFACE_DEVICE_BLUETOOTH) == 0) - type = NM_TYPE_DEVICE_BT; - else if (strcmp (ifname, NM_DBUS_INTERFACE_DEVICE_DUMMY) == 0) - type = NM_TYPE_DEVICE_DUMMY; - else if (strcmp (ifname, NM_DBUS_INTERFACE_DEVICE_WIRED) == 0) - type = NM_TYPE_DEVICE_ETHERNET; - else if (strcmp (ifname, NM_DBUS_INTERFACE_DEVICE_GENERIC) == 0) - type = NM_TYPE_DEVICE_GENERIC; - else if (strcmp (ifname, NM_DBUS_INTERFACE_DEVICE_INFINIBAND) == 0) - type = NM_TYPE_DEVICE_INFINIBAND; - else if (strcmp (ifname, NM_DBUS_INTERFACE_DEVICE_IP_TUNNEL) == 0) - type = NM_TYPE_DEVICE_IP_TUNNEL; - else if (strcmp (ifname, NM_DBUS_INTERFACE_DEVICE_MACSEC) == 0) - type = NM_TYPE_DEVICE_MACSEC; - else if (strcmp (ifname, NM_DBUS_INTERFACE_DEVICE_MACVLAN) == 0) - type = NM_TYPE_DEVICE_MACVLAN; - else if (strcmp (ifname, NM_DBUS_INTERFACE_DEVICE_MODEM) == 0) - type = NM_TYPE_DEVICE_MODEM; - else if (strcmp (ifname, NM_DBUS_INTERFACE_DEVICE_OLPC_MESH) == 0) - type = NM_TYPE_DEVICE_OLPC_MESH; - else if (strcmp (ifname, NM_DBUS_INTERFACE_DEVICE_OVS_INTERFACE) == 0) - type = NM_TYPE_DEVICE_OVS_INTERFACE; - else if (strcmp (ifname, NM_DBUS_INTERFACE_DEVICE_OVS_PORT) == 0) - type = NM_TYPE_DEVICE_OVS_PORT; - else if (strcmp (ifname, NM_DBUS_INTERFACE_DEVICE_OVS_BRIDGE) == 0) - type = NM_TYPE_DEVICE_OVS_BRIDGE; - else if (strcmp (ifname, NM_DBUS_INTERFACE_DEVICE_WIFI_P2P) == 0) - type = NM_TYPE_DEVICE_WIFI_P2P; - else if (strcmp (ifname, NM_DBUS_INTERFACE_DEVICE_PPP) == 0) - type = NM_TYPE_DEVICE_PPP; - else if (strcmp (ifname, NM_DBUS_INTERFACE_DEVICE_TEAM) == 0) - type = NM_TYPE_DEVICE_TEAM; - else if (strcmp (ifname, NM_DBUS_INTERFACE_DEVICE_TUN) == 0) - type = NM_TYPE_DEVICE_TUN; - else if (strcmp (ifname, NM_DBUS_INTERFACE_DEVICE_VLAN) == 0) - type = NM_TYPE_DEVICE_VLAN; - else if (strcmp (ifname, NM_DBUS_INTERFACE_DEVICE_WPAN) == 0) - type = NM_TYPE_DEVICE_WPAN; - else if (strcmp (ifname, NM_DBUS_INTERFACE_DEVICE_VXLAN) == 0) - type = NM_TYPE_DEVICE_VXLAN; - else if (strcmp (ifname, NM_DBUS_INTERFACE_DEVICE_WIRELESS) == 0) - type = NM_TYPE_DEVICE_WIFI; - else if (strcmp (ifname, NM_DBUS_INTERFACE_DEVICE_WIREGUARD) == 0) - type = NM_TYPE_DEVICE_WIREGUARD; - else if (strcmp (ifname, NM_DBUS_INTERFACE_DHCP4_CONFIG) == 0) - type = NM_TYPE_DHCP4_CONFIG; - else if (strcmp (ifname, NM_DBUS_INTERFACE_DHCP6_CONFIG) == 0) - type = NM_TYPE_DHCP6_CONFIG; - else if (strcmp (ifname, NM_DBUS_INTERFACE_IP4_CONFIG) == 0) - type = NM_TYPE_IP4_CONFIG; - else if (strcmp (ifname, NM_DBUS_INTERFACE_IP6_CONFIG) == 0) - type = NM_TYPE_IP6_CONFIG; - else if (strcmp (ifname, NM_DBUS_INTERFACE_WIFI_P2P_PEER) == 0) - type = NM_TYPE_WIFI_P2P_PEER; - else if (strcmp (ifname, NM_DBUS_INTERFACE_SETTINGS_CONNECTION) == 0) - type = NM_TYPE_REMOTE_CONNECTION; - else if (strcmp (ifname, NM_DBUS_INTERFACE_SETTINGS) == 0) - type = NM_TYPE_REMOTE_SETTINGS; - else if (strcmp (ifname, NM_DBUS_INTERFACE_DNS_MANAGER) == 0) - type = NM_TYPE_DNS_MANAGER; - else if (strcmp (ifname, NM_DBUS_INTERFACE_VPN_CONNECTION) == 0) - type = NM_TYPE_VPN_CONNECTION; - else if (strcmp (ifname, NM_DBUS_INTERFACE_CHECKPOINT) == 0) - type = NM_TYPE_CHECKPOINT; - - if (type != G_TYPE_INVALID) - break; + NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self); + CList **dbus_objects_lst_heads; + NMLDBusObject *dbobj; + int i; + + NML_NMCLIENT_LOG_D (self, "release all"); + + nm_clear_g_cancellable (&priv->permissions_cancellable); + nm_clear_g_cancellable (&priv->get_managed_objects_cancellable); + + nm_clear_g_dbus_connection_signal (priv->dbus_connection, + &priv->dbsid_nm_object_manager); + nm_clear_g_dbus_connection_signal (priv->dbus_connection, + &priv->dbsid_dbus_properties_properties_changed); + nm_clear_g_dbus_connection_signal (priv->dbus_connection, + &priv->dbsid_nm_settings_connection_updated); + nm_clear_g_dbus_connection_signal (priv->dbus_connection, + &priv->dbsid_nm_connection_active_state_changed); + nm_clear_g_dbus_connection_signal (priv->dbus_connection, + &priv->dbsid_nm_vpn_connection_state_changed); + nm_clear_g_dbus_connection_signal (priv->dbus_connection, + &priv->dbsid_nm_check_permissions); + + if (priv->permissions) { + gs_unref_hashtable GHashTable *old_permissions = g_steal_pointer (&priv->permissions); + + _emit_permissions_changed (self, old_permissions, TRUE); } - g_list_free_full (interfaces, g_object_unref); - if (type == G_TYPE_INVALID) - return NULL; - - obj_nm = g_object_new (type, - NM_OBJECT_DBUS_OBJECT, object, - NM_OBJECT_DBUS_OBJECT_MANAGER, object_manager, - NULL); - if (NM_IS_DEVICE (obj_nm)) { - priv = NM_CLIENT_GET_PRIVATE (self); - if (G_UNLIKELY (!priv->udev_inited)) { - priv->udev_inited = TRUE; - /* for testing, we don't want to use udev in libnm. */ - if (!nm_streq0 (g_getenv ("LIBNM_USE_NO_UDEV"), "1")) - priv->udev = udev_new (); + nm_assert (c_list_is_empty (&priv->dbus_object_changed_lst_head)); + + nm_assert (c_list_is_empty (&priv->dbus_objects_lst_head_with_nmobj_maybe_ready)); + dbus_objects_lst_heads = ((CList *[]) { + &priv->dbus_objects_lst_head_on_dbus, + &priv->dbus_objects_lst_head_with_nmobj_not_ready, + &priv->dbus_objects_lst_head_with_nmobj_visible, + &priv->dbus_objects_lst_head_with_nmobj_hidden, + NULL, + }); + for (i = 0; dbus_objects_lst_heads[i]; i++) { + c_list_for_each_entry (dbobj, dbus_objects_lst_heads[i], dbus_objects_lst) { + NMLDBusObjIfaceData *db_iface_data; + + nm_assert (c_list_is_empty (&dbobj->changed_obj_lst)); + while ((db_iface_data = c_list_first_entry (&dbobj->iface_lst_head, NMLDBusObjIfaceData, iface_lst))) + nm_c_list_move_tail (&dbobj->removed_iface_lst_head, &db_iface_data->iface_lst); + c_list_link_tail (&priv->dbus_object_changed_lst_head, &dbobj->changed_obj_lst); } - if (priv->udev) - _nm_device_set_udev (NM_DEVICE (obj_nm), priv->udev); } - g_object_set_qdata_full (G_OBJECT (object), _nm_object_obj_nm_quark (), - obj_nm, g_object_unref); - return obj_nm; -} -static void -obj_nm_inited (GObject *object, GAsyncResult *result, gpointer user_data) -{ - if (!g_async_initable_init_finish (G_ASYNC_INITABLE (object), result, NULL)) { - /* This is a can-not-happen situation, the NMObject subclasses are not - * supposed to fail initialization. */ - g_warn_if_reached (); - } + _dbus_handle_changes (self, "release-all", FALSE); + + /* We require that when we remove all D-Bus interfaces, that all object will go + * away. Note that a NMLDBusObject can be alive due to a NMLDBusObjWatcher, but + * even those should be all cleaned up. */ + nm_assert (c_list_is_empty (&priv->dbus_object_changed_lst_head)); + nm_assert (c_list_is_empty (&priv->dbus_objects_lst_head_with_nmobj_visible)); + nm_assert (c_list_is_empty (&priv->dbus_objects_lst_head_with_nmobj_hidden)); + nm_assert (c_list_is_empty (&priv->dbus_objects_lst_head_with_nmobj_maybe_ready)); + nm_assert (c_list_is_empty (&priv->dbus_objects_lst_head_with_nmobj_not_ready)); + nm_assert (c_list_is_empty (&priv->dbus_objects_lst_head_watched_only)); + nm_assert (g_hash_table_size (priv->dbus_objects) == 0); } +/*****************************************************************************/ + static void -object_added (GDBusObjectManager *object_manager, GDBusObject *object, gpointer user_data) +name_owner_changed (NMClient *self, + const char *name_owner) { - NMClient *client = user_data; - NMObject *obj_nm; + NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self); + gboolean changed; + gs_free char *old_name_owner_free = NULL; + const char *old_name_owner; + nm_auto_pop_gmaincontext GMainContext *dbus_context = NULL; - obj_nm = obj_nm_for_gdbus_object (client, object, object_manager); - if (obj_nm) { - g_async_initable_init_async (G_ASYNC_INITABLE (obj_nm), - G_PRIORITY_DEFAULT, NULL, - obj_nm_inited, NULL); - } -} + name_owner = nm_str_not_empty (name_owner); -static void -object_removed (GDBusObjectManager *object_manager, GDBusObject *object, gpointer user_data) -{ - g_object_set_qdata (G_OBJECT (object), _nm_object_obj_nm_quark (), NULL); -} + changed = !nm_streq0 (priv->name_owner, name_owner); -static gboolean -objects_created (NMClient *client, GDBusObjectManager *object_manager, GError **error) -{ - NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client); - gs_unref_object GDBusObject *manager = NULL; - gs_unref_object GDBusObject *settings = NULL; - gs_unref_object GDBusObject *dns_manager = NULL; - NMObject *obj_nm; - GList *objects, *iter; - - /* First just ensure all the NMObjects for known GDBusObjects exist. */ - objects = g_dbus_object_manager_get_objects (object_manager); - for (iter = objects; iter; iter = iter->next) - obj_nm_for_gdbus_object (client, iter->data, object_manager); - g_list_free_full (objects, g_object_unref); - - manager = g_dbus_object_manager_get_object (object_manager, NM_DBUS_PATH); - if (!manager) { - g_set_error_literal (error, - NM_CLIENT_ERROR, - NM_CLIENT_ERROR_MANAGER_NOT_RUNNING, - "Manager object not found"); - return FALSE; - } + if ( !name_owner + && priv->main_context != priv->dbus_context) { - obj_nm = g_object_get_qdata (G_OBJECT (manager), _nm_object_obj_nm_quark ()); - if (!obj_nm) { - g_set_error_literal (error, - NM_CLIENT_ERROR, - NM_CLIENT_ERROR_MANAGER_NOT_RUNNING, - "Manager object lacks the proper interface"); - return FALSE; - } + NML_NMCLIENT_LOG_D (self, "resync main context as we have no name owner"); - priv->manager = NM_MANAGER (g_object_ref (obj_nm)); - - g_signal_connect (priv->manager, "notify", - G_CALLBACK (subobject_notify), client); - g_signal_connect (priv->manager, "device-added", - G_CALLBACK (manager_device_added), client); - g_signal_connect (priv->manager, "device-removed", - G_CALLBACK (manager_device_removed), client); - g_signal_connect (priv->manager, "any-device-added", - G_CALLBACK (manager_any_device_added), client); - g_signal_connect (priv->manager, "any-device-removed", - G_CALLBACK (manager_any_device_removed), client); - g_signal_connect (priv->manager, "permission-changed", - G_CALLBACK (manager_permission_changed), client); - g_signal_connect (priv->manager, "active-connection-added", - G_CALLBACK (manager_active_connection_added), client); - g_signal_connect (priv->manager, "active-connection-removed", - G_CALLBACK (manager_active_connection_removed), client); - - settings = g_dbus_object_manager_get_object (object_manager, NM_DBUS_PATH_SETTINGS); - if (!settings) { - g_set_error_literal (error, - NM_CLIENT_ERROR, - NM_CLIENT_ERROR_MANAGER_NOT_RUNNING, - "Settings object not found"); - return FALSE; - } + nm_clear_g_dbus_connection_signal (priv->dbus_connection, + &priv->name_owner_changed_id); - obj_nm = g_object_get_qdata (G_OBJECT (settings), _nm_object_obj_nm_quark ()); - if (!obj_nm) { - g_set_error_literal (error, - NM_CLIENT_ERROR, - NM_CLIENT_ERROR_MANAGER_NOT_RUNNING, - "Settings object lacks the proper interface"); - return FALSE; - } + /* Our instance was initialized synchronously. Usually we must henceforth + * stick to a internal main context. But now we have no name-owner... + * at this point, we anyway are going to do a full resync. Swap the main + * contexts again. */ - priv->settings = NM_REMOTE_SETTINGS (g_object_ref (obj_nm)); - - g_signal_connect (priv->settings, "notify", - G_CALLBACK (subobject_notify), client); - g_signal_connect (priv->settings, "connection-added", - G_CALLBACK (settings_connection_added), client); - g_signal_connect (priv->settings, "connection-removed", - G_CALLBACK (settings_connection_removed), client); - - dns_manager = g_dbus_object_manager_get_object (object_manager, NM_DBUS_PATH_DNS_MANAGER); - if (dns_manager) { - obj_nm = g_object_get_qdata (G_OBJECT (dns_manager), _nm_object_obj_nm_quark ()); - if (!obj_nm) { - g_set_error_literal (error, - NM_CLIENT_ERROR, - NM_CLIENT_ERROR_MANAGER_NOT_RUNNING, - "DNS manager object lacks the proper interface"); - return FALSE; - } - priv->dns_manager = NM_DNS_MANAGER (g_object_ref (obj_nm)); + g_main_context_ref (priv->main_context); + g_main_context_unref (priv->dbus_context); + priv->dbus_context = priv->main_context; - g_signal_connect (priv->dns_manager, "notify", - G_CALLBACK (dns_notify), client); - } + nm_clear_pointer (&priv->dbus_context_integration, nm_g_source_destroy_and_unref); - /* The handlers don't really use the client instance. However - * it makes it convenient to unhook them by data. */ - g_signal_connect (object_manager, "object-added", - G_CALLBACK (object_added), client); - g_signal_connect (object_manager, "object-removed", - G_CALLBACK (object_removed), client); + dbus_context = nm_g_main_context_push_thread_default_if_necessary (priv->dbus_context); - return TRUE; -} + /* we need to sync again... */ -/* Synchronous initialization. */ + _assert_main_context_is_current_thread_default (self, dbus_context); -static void name_owner_changed (GObject *object, GParamSpec *pspec, gpointer user_data); + priv->name_owner_changed_id = nm_dbus_connection_signal_subscribe_name_owner_changed (priv->dbus_connection, + NM_DBUS_SERVICE, + name_owner_changed_cb, + self, + NULL); + priv->name_owner_get_cancellable = g_cancellable_new (); + nm_dbus_connection_call_get_name_owner (priv->dbus_connection, + NM_DBUS_SERVICE, + NM_DBUS_DEFAULT_TIMEOUT_MSEC, + priv->name_owner_get_cancellable, + name_owner_get_cb, + self); + } else + dbus_context = nm_g_main_context_push_thread_default_if_necessary (priv->dbus_context); -static gboolean -_om_has_name_owner (GDBusObjectManager *object_manager) -{ - gs_free char *name_owner = NULL; + if (changed) { + NML_NMCLIENT_LOG_D (self, "name owner changed: %s%s%s -> %s%s%s", + NM_PRINT_FMT_QUOTE_STRING (priv->name_owner), + NM_PRINT_FMT_QUOTE_STRING (name_owner)); + old_name_owner_free = priv->name_owner; + priv->name_owner = g_strdup (name_owner); + old_name_owner = old_name_owner_free; + } else + old_name_owner = priv->name_owner; - nm_assert (G_IS_DBUS_OBJECT_MANAGER_CLIENT (object_manager)); + if (changed) + _notify (self, PROP_DBUS_NAME_OWNER); - name_owner = g_dbus_object_manager_client_get_name_owner (G_DBUS_OBJECT_MANAGER_CLIENT (object_manager)); - return !!name_owner; -} + if ( changed + && old_name_owner) + _init_release_all (self); + + if ( changed + && priv->name_owner) + _init_fetch_all (self); -/* Asynchronous initialization. */ + _set_nm_running (self); + + if (priv->init_data) { + nm_auto_pop_gmaincontext GMainContext *main_context = NULL; + + if (priv->main_context != priv->dbus_context) + main_context = nm_g_main_context_push_thread_default_if_necessary (priv->main_context); + _init_start_check_complete (self); + } +} static void -init_async_complete (NMClientInitData *init_data) +name_owner_changed_cb (GDBusConnection *connection, + const char *sender_name, + const char *object_path, + const char *interface_name, + const char *signal_name, + GVariant *parameters, + gpointer user_data) { - if (init_data->pending_init > 0) + NMClient *self = user_data; + NMClientPrivate *priv; + const char *new_owner; + + if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(sss)"))) + return; + + priv = NM_CLIENT_GET_PRIVATE (self); + if (priv->name_owner_get_cancellable) return; - g_simple_async_result_complete (init_data->result); - g_object_unref (init_data->result); - g_clear_object (&init_data->cancellable); - g_slice_free (NMClientInitData, init_data); + + g_variant_get (parameters, + "(&s&s&s)", + NULL, + NULL, + &new_owner); + + name_owner_changed (self, new_owner); } static void -async_inited_obj_nm (GObject *object, GAsyncResult *result, gpointer user_data) +name_owner_get_cb (const char *name_owner, + GError *error, + gpointer user_data) { - NMClientInitData *init_data = user_data; - GError *error = NULL; + NMClient *self; + NMClientPrivate *priv; + + if ( !name_owner + && nm_utils_error_is_cancelled (error, FALSE)) + return; - nm_assert (init_data && init_data->pending_init > 0); + self = user_data; + priv = NM_CLIENT_GET_PRIVATE (self); - if (!g_async_initable_init_finish (G_ASYNC_INITABLE (object), result, &error)) - g_simple_async_result_take_error (init_data->result, error); + g_clear_object (&priv->name_owner_get_cancellable); - init_data->pending_init--; - init_async_complete (init_data); + name_owner_changed (self, name_owner); } -static void -init_async (GAsyncInitable *initable, int io_priority, - GCancellable *cancellable, GAsyncReadyCallback callback, - gpointer user_data); +/*****************************************************************************/ static void -unhook_om (NMClient *self) +_init_start_complete (NMClient *self, + GError *error_take) { NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self); - GList *objects, *iter; + InitData *init_data; - if (priv->manager) { - const GPtrArray *active_connections; - const GPtrArray *devices; - int i; + init_data = g_steal_pointer (&priv->init_data); - active_connections = nm_manager_get_active_connections (priv->manager); - for (i = 0; i < active_connections->len; i++) - g_signal_emit (self, signals[ACTIVE_CONNECTION_REMOVED], 0, active_connections->pdata[i]); + NML_NMCLIENT_LOG_D (self, "%s init complete with %s%s%s", + init_data->is_sync ? "sync" : "async", + NM_PRINT_FMT_QUOTED (error_take, "error: ", error_take->message, "", "success")); - devices = nm_manager_get_all_devices (priv->manager); - for (i = 0; i < devices->len; i++) - g_signal_emit (self, signals[DEVICE_REMOVED], 0, devices->pdata[i]); + nm_clear_pointer (&init_data->cancel_on_idle_source, nm_g_source_destroy_and_unref); + nm_clear_g_signal_handler (init_data->cancellable, &init_data->cancelled_id); - g_signal_handlers_disconnect_by_data (priv->manager, self); - g_clear_object (&priv->manager); - _notify (self, PROP_ACTIVE_CONNECTIONS); - _notify (self, PROP_NM_RUNNING); - } - if (priv->settings) { - const GPtrArray *connections; - guint i; - - connections = nm_remote_settings_get_connections (priv->settings); - for (i = 0; i < connections->len; i++) - g_signal_emit (self, signals[CONNECTION_REMOVED], 0, connections->pdata[i]); - - g_signal_handlers_disconnect_by_data (priv->settings, self); - g_clear_object (&priv->settings); - _notify (self, PROP_CONNECTIONS); - _notify (self, PROP_HOSTNAME); - _notify (self, PROP_CAN_MODIFY); - } - if (priv->dns_manager) { - g_signal_handlers_disconnect_by_data (priv->dns_manager, self); - g_clear_object (&priv->dns_manager); + if (init_data->is_sync) { + if (error_take) + g_propagate_error (init_data->data.sync.error_location, error_take); + g_main_loop_quit (init_data->data.sync.main_loop); + } else { + if (error_take) + g_task_return_error (init_data->data.async.task, error_take); + else + g_task_return_boolean (init_data->data.async.task, TRUE); + g_object_unref (init_data->data.async.task); } - - objects = g_dbus_object_manager_get_objects (priv->object_manager); - for (iter = objects; iter; iter = iter->next) - g_object_set_qdata (iter->data, _nm_object_obj_nm_quark (), NULL); - g_list_free_full (objects, g_object_unref); + nm_g_object_unref (init_data->cancellable); + nm_g_slice_free (init_data); } static void -new_object_manager (GObject *source_object, GAsyncResult *res, gpointer user_data) +_init_start_check_complete (NMClient *self) { - NMClient *self = NM_CLIENT (user_data); NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self); - g_clear_object (&priv->new_object_manager_cancellable); - _notify (user_data, PROP_NM_RUNNING); -} + _assert_main_context_is_current_thread_default (self, main_context); -static void -got_object_manager (GObject *object, GAsyncResult *result, gpointer user_data) -{ - NMClientInitData *init_data = user_data; - NMClient *client; - NMClientPrivate *priv; - GList *objects, *iter; - GError *error = NULL; - GDBusObjectManager *object_manager; + nm_assert (c_list_is_empty (&priv->dbus_objects_lst_head_with_nmobj_maybe_ready)); + + if (!priv->init_data) + return; - object_manager = (gpointer) g_async_initable_new_finish (G_ASYNC_INITABLE (object), result, &error); - if (object_manager == NULL) { - g_simple_async_result_take_error (init_data->result, error); - init_async_complete (init_data); + if (priv->get_managed_objects_cancellable) { + /* still initializing. Wait. */ return; } - nm_assert (G_IS_DBUS_OBJECT_MANAGER_CLIENT (object_manager)); +#if NM_MORE_ASSERTS > 10 + { + NMLDBusObject *dbobj; - client = init_data->client; - priv = NM_CLIENT_GET_PRIVATE (client); - priv->object_manager = object_manager; - if (!priv->dbus_connection) - priv->dbus_connection = g_object_ref (g_dbus_object_manager_client_get_connection (G_DBUS_OBJECT_MANAGER_CLIENT (priv->object_manager))); - - if (_om_has_name_owner (priv->object_manager)) { - if (!objects_created (client, priv->object_manager, &error)) { - g_simple_async_result_take_error (init_data->result, error); - init_async_complete (init_data); - return; + c_list_for_each_entry (dbobj, &priv->dbus_objects_lst_head_with_nmobj_not_ready, dbus_objects_lst) { + NML_NMCLIENT_LOG_T (self, "init-start waiting for %s", dbobj->dbus_path->str); + break; } + } +#endif + + if (!c_list_is_empty (&priv->dbus_objects_lst_head_with_nmobj_not_ready)) + return; - objects = g_dbus_object_manager_get_objects (priv->object_manager); - for (iter = objects; iter; iter = iter->next) { - NMObject *obj_nm; + _init_start_complete (self, NULL); +} - obj_nm = g_object_get_qdata (iter->data, _nm_object_obj_nm_quark ()); - if (!obj_nm) - continue; +static void +_init_start_cancelled_cb (GCancellable *cancellable, + gpointer user_data) +{ + NMClient *self = user_data; + GError *error; + + nm_assert (NM_IS_CLIENT (self)); + nm_assert (NM_CLIENT_GET_PRIVATE (self)->init_data); + nm_assert (NM_CLIENT_GET_PRIVATE (self)->init_data->cancellable == cancellable); + + nm_utils_error_set_cancelled (&error, FALSE, NULL); + _init_start_complete (self, error); +} - init_data->pending_init++; - g_async_initable_init_async (G_ASYNC_INITABLE (obj_nm), - G_PRIORITY_DEFAULT, init_data->cancellable, - async_inited_obj_nm, init_data); +static gboolean +_init_start_cancel_on_idle_cb (gpointer user_data) +{ + NMClient *self = user_data; + GError *error; + + nm_utils_error_set_cancelled (&error, FALSE, NULL); + _init_start_complete (self, error); + return G_SOURCE_CONTINUE; +} + +static void +_init_start_with_bus (NMClient *self) +{ + NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self); + + if (priv->init_data->cancellable) { + priv->init_data->cancelled_id = g_signal_connect (priv->init_data->cancellable, + "cancelled", + G_CALLBACK (_init_start_cancelled_cb), + self); + if (g_cancellable_is_cancelled (priv->init_data->cancellable)) { + priv->init_data->cancel_on_idle_source = g_idle_source_new (); + g_source_set_callback (priv->init_data->cancel_on_idle_source, _init_start_cancel_on_idle_cb, self, NULL); + g_source_attach (priv->init_data->cancel_on_idle_source, priv->main_context); + return; } - g_list_free_full (objects, g_object_unref); } - init_async_complete (init_data); + _assert_main_context_is_current_thread_default (self, dbus_context); - g_signal_connect (priv->object_manager, "notify::name-owner", - G_CALLBACK (name_owner_changed), client); + priv->name_owner_changed_id = nm_dbus_connection_signal_subscribe_name_owner_changed (priv->dbus_connection, + NM_DBUS_SERVICE, + name_owner_changed_cb, + self, + NULL); + priv->name_owner_get_cancellable = g_cancellable_new (); + nm_dbus_connection_call_get_name_owner (priv->dbus_connection, + NM_DBUS_SERVICE, + NM_DBUS_DEFAULT_TIMEOUT_MSEC, + priv->name_owner_get_cancellable, + name_owner_get_cb, + self); } static void -prepare_object_manager (NMClient *client, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) +_init_start_bus_get_cb (GObject *source, GAsyncResult *result, gpointer user_data) { - NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client); - NMClientInitData *init_data; - GBusType bus_type = G_BUS_TYPE_NONE; + NMClient *self = user_data; + NMClientPrivate *priv; + GDBusConnection *dbus_connection; + GError *error = NULL; - init_data = g_slice_new0 (NMClientInitData); - init_data->client = client; - init_data->cancellable = cancellable ? g_object_ref (cancellable) : NULL; - init_data->result = g_simple_async_result_new (G_OBJECT (client), callback, - user_data, init_async); - if (cancellable) - g_simple_async_result_set_check_cancellable (init_data->result, cancellable); - g_simple_async_result_set_op_res_gboolean (init_data->result, TRUE); + nm_assert (NM_IS_CLIENT (self)); - if (!priv->dbus_connection) - bus_type = _nm_dbus_bus_type (); + dbus_connection = g_bus_get_finish (result, &error); - g_async_initable_new_async (G_TYPE_DBUS_OBJECT_MANAGER_CLIENT, - G_PRIORITY_DEFAULT, - init_data->cancellable, - got_object_manager, - init_data, - "connection", priv->dbus_connection, - "bus-type", bus_type, - "flags", G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_DO_NOT_AUTO_START, - "name", "org.freedesktop.NetworkManager", - "object-path", "/org/freedesktop", - "get-proxy-type-func", proxy_type, - "get-proxy-type-user-data", NULL, - "get-proxy-type-destroy-notify", NULL, - NULL); + if (!dbus_connection) { + _init_start_complete (self, error); + return; + } + + priv = NM_CLIENT_GET_PRIVATE (self); + priv->dbus_connection = dbus_connection; + + _init_start_with_bus (self); } static void -name_owner_changed (GObject *object, GParamSpec *pspec, gpointer user_data) +_init_start (NMClient *self) { - NMClient *self = user_data; NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self); - GDBusObjectManager *object_manager = G_DBUS_OBJECT_MANAGER (object); - nm_assert (object_manager == priv->object_manager); + NML_NMCLIENT_LOG_D (self, "starting %s initialization...", + priv->init_data->is_sync ? "sync" : "async"); - if (_om_has_name_owner (object_manager)) { - g_signal_handlers_disconnect_by_data (priv->object_manager, self); - g_clear_object (&priv->object_manager); - nm_clear_g_cancellable (&priv->new_object_manager_cancellable); - priv->new_object_manager_cancellable = g_cancellable_new (); - prepare_object_manager (self, priv->new_object_manager_cancellable, - new_object_manager, self); - } else { - g_signal_handlers_disconnect_by_func (object_manager, object_added, self); - unhook_om (self); + if (!priv->dbus_connection) { + g_bus_get (_nm_dbus_bus_type (), + priv->init_data->cancellable, + _init_start_bus_get_cb, + self); + return; } + + _init_start_with_bus (self); } /*****************************************************************************/ @@ -3520,19 +6496,13 @@ get_property (GObject *object, guint prop_id, g_value_set_boolean (value, nm_client_wireless_get_enabled (self)); break; case PROP_WIRELESS_HARDWARE_ENABLED: - if (priv->manager) - g_object_get_property (G_OBJECT (priv->manager), pspec->name, value); - else - g_value_set_boolean (value, FALSE); + g_value_set_boolean (value, nm_client_wireless_hardware_get_enabled (self)); break; case PROP_WWAN_ENABLED: g_value_set_boolean (value, nm_client_wwan_get_enabled (self)); break; case PROP_WWAN_HARDWARE_ENABLED: - if (priv->manager) - g_object_get_property (G_OBJECT (priv->manager), pspec->name, value); - else - g_value_set_boolean (value, FALSE); + g_value_set_boolean (value, nm_client_wwan_hardware_get_enabled (self)); break; case PROP_WIMAX_ENABLED: g_value_set_boolean (value, FALSE); @@ -3552,6 +6522,9 @@ get_property (GObject *object, guint prop_id, case PROP_CONNECTIVITY_CHECK_ENABLED: g_value_set_boolean (value, nm_client_connectivity_check_get_enabled (self)); break; + case PROP_CONNECTIVITY_CHECK_URI: + g_value_set_string (value, nm_client_connectivity_check_get_uri (self)); + break; case PROP_PRIMARY_CONNECTION: g_value_set_object (value, nm_client_get_primary_connection (self)); break; @@ -3562,59 +6535,39 @@ get_property (GObject *object, guint prop_id, g_value_take_boxed (value, _nm_utils_copy_object_array (nm_client_get_devices (self))); break; case PROP_METERED: - if (priv->manager) - g_object_get_property (G_OBJECT (priv->manager), pspec->name, value); - else - g_value_set_uint (value, NM_METERED_UNKNOWN); + g_value_set_uint (value, nm_client_get_metered (self)); break; case PROP_ALL_DEVICES: g_value_take_boxed (value, _nm_utils_copy_object_array (nm_client_get_all_devices (self))); break; case PROP_CHECKPOINTS: - if (priv->manager) - g_object_get_property (G_OBJECT (priv->manager), pspec->name, value); - else - g_value_take_boxed (value, g_ptr_array_new ()); + g_value_take_boxed (value, _nm_utils_copy_object_array (nm_client_get_checkpoints (self))); break; /* Settings properties. */ case PROP_CONNECTIONS: - if (priv->settings) - g_object_get_property (G_OBJECT (priv->settings), pspec->name, value); - else - g_value_take_boxed (value, _nm_utils_copy_object_array (&empty)); + g_value_take_boxed (value, _nm_utils_copy_object_array (nm_client_get_connections (self))); break; case PROP_HOSTNAME: - if (priv->settings) - g_object_get_property (G_OBJECT (priv->settings), pspec->name, value); - else - g_value_set_string (value, NULL); + g_value_set_string (value, priv->settings.hostname); break; case PROP_CAN_MODIFY: - if (priv->settings) - g_object_get_property (G_OBJECT (priv->settings), pspec->name, value); - else - g_value_set_boolean (value, FALSE); + g_value_set_boolean (value, priv->settings.can_modify); break; /* DNS properties */ case PROP_DNS_MODE: + g_value_set_string (value, nm_client_get_dns_mode (self)); + break; case PROP_DNS_RC_MANAGER: - g_return_if_fail (pspec->name && strlen (pspec->name) > NM_STRLEN ("dns-")); - if (priv->dns_manager) - g_object_get_property (G_OBJECT (priv->dns_manager), - &pspec->name[NM_STRLEN ("dns-")], value); - else - g_value_set_string (value, NULL); + g_value_set_string (value, nm_client_get_dns_rc_manager (self)); break; case PROP_DNS_CONFIGURATION: - if (priv->dns_manager) { - g_object_get_property (G_OBJECT (priv->dns_manager), - NM_DNS_MANAGER_CONFIGURATION, - value); - } else - g_value_take_boxed (value, NULL); + g_value_take_boxed (value, _nm_utils_copy_array (nm_client_get_dns_configuration (self), + (NMUtilsCopyFunc) nm_dns_entry_dup, + (GDestroyNotify) nm_dns_entry_unref)); break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -3625,19 +6578,45 @@ static void set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { - NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (object); + NMClient *self = NM_CLIENT (object); + NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self); + gboolean b; switch (prop_id) { case PROP_DBUS_CONNECTION: /* construct-only */ priv->dbus_connection = g_value_dup_object (value); break; + case PROP_NETWORKING_ENABLED: + b = g_value_get_boolean (value); + if (priv->nm.networking_enabled != b) { + nm_client_networking_set_enabled (self, + b, + NULL); + /* Let the property value flip when we get the change signal from NM */ + } + break; case PROP_WIRELESS_ENABLED: + b = g_value_get_boolean (value); + if (priv->nm.wireless_enabled != b) { + nm_client_wireless_set_enabled (self, b); + /* Let the property value flip when we get the change signal from NM */ + } + break; case PROP_WWAN_ENABLED: + b = g_value_get_boolean (value); + if (priv->nm.wwan_enabled != b) { + nm_client_wwan_set_enabled (self, b); + /* Let the property value flip when we get the change signal from NM */ + } + break; case PROP_CONNECTIVITY_CHECK_ENABLED: - if (priv->manager) - g_object_set_property (G_OBJECT (priv->manager), pspec->name, value); + b = g_value_get_boolean (value); + if (priv->nm.connectivity_check_enabled != b) { + nm_client_connectivity_check_set_enabled (self, b); + /* Let the property value flip when we get the change signal from NM */ + } break; case PROP_WIMAX_ENABLED: break; @@ -3652,73 +6631,113 @@ set_property (GObject *object, guint prop_id, static gboolean init_sync (GInitable *initable, GCancellable *cancellable, GError **error) { - NMClient *client = NM_CLIENT (initable); - NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client); - GList *objects, *iter; + gs_unref_object NMClient *self = NULL; + NMClientPrivate *priv; + GMainContext *dbus_context; + GError *local_error = NULL; + GMainLoop *main_loop; - if (!priv->dbus_connection) { - priv->dbus_connection = g_bus_get_sync (_nm_dbus_bus_type (), - cancellable, - error); - if (!priv->dbus_connection) - return FALSE; - } + g_return_val_if_fail (NM_IS_CLIENT (initable), FALSE); - priv->object_manager = g_dbus_object_manager_client_new_sync (priv->dbus_connection, - G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_DO_NOT_AUTO_START, - "org.freedesktop.NetworkManager", - "/org/freedesktop", - proxy_type, NULL, NULL, - cancellable, error); - if (!priv->object_manager) - return FALSE; + self = g_object_ref (NM_CLIENT (initable)); /* keep instance alive. */ - if (_om_has_name_owner (priv->object_manager)) { - if (!objects_created (client, priv->object_manager, error)) - return FALSE; + priv = NM_CLIENT_GET_PRIVATE (self); - objects = g_dbus_object_manager_get_objects (priv->object_manager); - for (iter = objects; iter; iter = iter->next) { - NMObject *obj_nm; + g_return_val_if_fail (!priv->dbus_context, FALSE); - obj_nm = g_object_get_qdata (iter->data, _nm_object_obj_nm_quark ()); - if (!obj_nm) - continue; + /* when using init_sync(), we use a separate internal GMainContext for + * all D-Bus operations and use our regular async-init code. That means, + * also in sync-init, we don't actually block waiting for our D-Bus requests, + * instead, we only block (g_main_loop_run()) for the overall result. + * + * Doing this has a performance overhead. Also, we cannot ever fall back + * to the regular main-context (not unless we lose the main-owner and + * need to re-initialize). The reason is that we receive events on our + * dbus_context, and this cannot be brought in sync -- short of full + * reinitalizing. Therefor, using sync init not only is slower during + * construction of the object, but NMClient will stick to the dual GMainContext + * mode. + * + * Aside from this downside, the solution is good: + * + * - we don't duplicate the implementation of async-init. + * - we don't iterate the main-context of the caller while waiting for + * initialization to happen + * - we still invoke all changes under the main_context of the caller. + * - all D-Bus events strictly go through dbus_context and are in order. + */ - if (!g_initable_init (G_INITABLE (obj_nm), cancellable, NULL)) { - /* This is a can-not-happen situation, the NMObject subclasses are not - * supposed to fail initialization. */ - g_warn_if_reached (); - } - } - g_list_free_full (objects, g_object_unref); + dbus_context = g_main_context_new (); + priv->dbus_context = g_main_context_ref (dbus_context); + + g_main_context_push_thread_default (dbus_context); + + main_loop = g_main_loop_new (dbus_context, FALSE); + + priv->init_data = _init_data_new_sync (cancellable, main_loop, &local_error); + + _init_start (self); + + g_main_loop_run (main_loop); + + g_main_loop_unref (main_loop); + + g_main_context_pop_thread_default (dbus_context); + + if (priv->main_context != priv->dbus_context) { + priv->dbus_context_integration = nm_utils_g_main_context_create_integrate_source (priv->dbus_context); + g_source_attach (priv->dbus_context_integration, priv->main_context); } - g_signal_connect (priv->object_manager, "notify::name-owner", - G_CALLBACK (name_owner_changed), client); + g_main_context_unref (dbus_context); + if (local_error) { + g_propagate_error (error, local_error); + return FALSE; + } return TRUE; } /*****************************************************************************/ static void -init_async (GAsyncInitable *initable, int io_priority, - GCancellable *cancellable, GAsyncReadyCallback callback, +init_async (GAsyncInitable *initable, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, gpointer user_data) { - prepare_object_manager (NM_CLIENT (initable), cancellable, callback, user_data); + NMClientPrivate *priv; + NMClient *self; + nm_auto_pop_gmaincontext GMainContext *context = NULL; + GTask *task; + + g_return_if_fail (NM_IS_CLIENT (initable)); + + self = NM_CLIENT (initable); + priv = NM_CLIENT_GET_PRIVATE (self); + + g_return_if_fail (!priv->dbus_context); + + priv->dbus_context = g_main_context_ref (priv->main_context); + + context = nm_g_main_context_push_thread_default_if_necessary (priv->main_context); + + task = nm_g_task_new (self, cancellable, init_async, callback, user_data); + g_task_set_priority (task, io_priority); + + priv->init_data = _init_data_new_async (cancellable, g_steal_pointer (&task)); + + _init_start (self); } static gboolean init_finish (GAsyncInitable *initable, GAsyncResult *result, GError **error) { - GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result); + g_return_val_if_fail (NM_IS_CLIENT (initable), FALSE); + g_return_val_if_fail (nm_g_task_is_valid (result, initable, init_async), FALSE); - if (g_simple_async_result_propagate_error (simple, error)) - return FALSE; - else - return TRUE; + return g_task_propagate_boolean (G_TASK (result), error); } /*****************************************************************************/ @@ -3726,6 +6745,20 @@ init_finish (GAsyncInitable *initable, GAsyncResult *result, GError **error) static void nm_client_init (NMClient *self) { + NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self); + + c_list_init (&self->obj_base.queue_notify_lst); + c_list_init (&priv->queue_notify_lst_head); + c_list_init (&priv->notify_event_lst_head); + + priv->dbus_objects = g_hash_table_new (nm_pdirect_hash, nm_pdirect_equal); + c_list_init (&priv->dbus_objects_lst_head_watched_only); + c_list_init (&priv->dbus_objects_lst_head_on_dbus); + c_list_init (&priv->dbus_objects_lst_head_with_nmobj_not_ready); + c_list_init (&priv->dbus_objects_lst_head_with_nmobj_maybe_ready); + c_list_init (&priv->dbus_objects_lst_head_with_nmobj_visible); + c_list_init (&priv->dbus_objects_lst_head_with_nmobj_hidden); + c_list_init (&priv->dbus_object_changed_lst_head); } /** @@ -3808,59 +6841,144 @@ constructed (GObject *object) priv->main_context = g_main_context_ref_thread_default (); G_OBJECT_CLASS (nm_client_parent_class)->constructed (object); + + NML_NMCLIENT_LOG_D (self, "new NMClient instance"); } static void dispose (GObject *object) { - NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (object); + NMClient *self = NM_CLIENT (object); + NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self); - nm_clear_g_cancellable (&priv->new_object_manager_cancellable); + nm_assert (!priv->init_data); - if (priv->manager) { - g_signal_handlers_disconnect_by_data (priv->manager, object); - g_clear_object (&priv->manager); - } + self->obj_base.is_disposing = TRUE; - if (priv->settings) { - g_signal_handlers_disconnect_by_data (priv->settings, object); - g_clear_object (&priv->settings); - } + nm_clear_g_cancellable (&priv->name_owner_get_cancellable); - if (priv->dns_manager) { - g_signal_handlers_disconnect_by_data (priv->dns_manager, object); - g_clear_object (&priv->dns_manager); - } + nm_clear_g_dbus_connection_signal (priv->dbus_connection, + &priv->name_owner_changed_id); - if (priv->object_manager) { - GList *objects, *iter; + nm_clear_g_free (&priv->name_owner); - /* Unhook the NM objects. */ - objects = g_dbus_object_manager_get_objects (priv->object_manager); - for (iter = objects; iter; iter = iter->next) - g_object_set_qdata (G_OBJECT (iter->data), _nm_object_obj_nm_quark (), NULL); - g_list_free_full (objects, g_object_unref); + _init_release_all (self); - g_signal_handlers_disconnect_by_data (priv->object_manager, object); - g_clear_object (&priv->object_manager); - } + nm_assert (c_list_is_empty (&priv->dbus_objects_lst_head_watched_only)); + nm_assert (c_list_is_empty (&priv->dbus_objects_lst_head_on_dbus)); + nm_assert (c_list_is_empty (&priv->dbus_objects_lst_head_with_nmobj_not_ready)); + nm_assert (c_list_is_empty (&priv->dbus_objects_lst_head_with_nmobj_maybe_ready)); + nm_assert (c_list_is_empty (&priv->dbus_objects_lst_head_with_nmobj_visible)); + nm_assert (c_list_is_empty (&priv->dbus_objects_lst_head_with_nmobj_hidden)); + + nm_assert (c_list_is_empty (&priv->queue_notify_lst_head)); + nm_assert (c_list_is_empty (&priv->notify_event_lst_head)); + nm_assert (c_list_is_empty (&self->obj_base.queue_notify_lst)); + nm_assert (!priv->dbus_objects || g_hash_table_size (priv->dbus_objects) == 0); + + nml_dbus_property_o_clear (&priv->nm.activating_connection, NULL); + nml_dbus_property_o_clear (&priv->nm.primary_connection, NULL); + nml_dbus_property_ao_clear (&priv->nm.devices, NULL); + nml_dbus_property_ao_clear (&priv->nm.all_devices, NULL); + nml_dbus_property_ao_clear (&priv->nm.active_connections, NULL); + nml_dbus_property_ao_clear (&priv->nm.checkpoints, NULL); + + nm_clear_g_free (&priv->nm.connectivity_check_uri); + nm_clear_g_free (&priv->nm.version); + + nml_dbus_property_ao_clear (&priv->settings.connections, NULL); + nm_clear_g_free (&priv->settings.hostname); + + nm_clear_pointer (&priv->dns_manager.configuration, g_ptr_array_unref); + nm_clear_g_free (&priv->dns_manager.mode); + nm_clear_g_free (&priv->dns_manager.rc_manager); + + nm_clear_pointer (&priv->dbus_objects, g_hash_table_destroy); G_OBJECT_CLASS (nm_client_parent_class)->dispose (object); nm_clear_pointer (&priv->udev, udev_unref); + nm_clear_pointer (&priv->dbus_context_integration, nm_g_source_destroy_and_unref); + nm_clear_pointer (&priv->dbus_context, g_main_context_unref); nm_clear_pointer (&priv->main_context, g_main_context_unref); + nm_clear_pointer (&priv->permissions, g_hash_table_unref); + g_clear_object (&priv->dbus_connection); - nm_clear_g_free (&priv->name_owner_cached); + nm_clear_g_free (&priv->name_owner); } +const NMLDBusMetaIface _nml_dbus_meta_iface_nm_agentmanager = NML_DBUS_META_IFACE_INIT ( + NM_DBUS_INTERFACE_AGENT_MANAGER, + NULL, + NML_DBUS_META_INTERFACE_PRIO_NONE, +); + +const NMLDBusMetaIface _nml_dbus_meta_iface_nm = NML_DBUS_META_IFACE_INIT_PROP ( + NM_DBUS_INTERFACE, + nm_client_get_type, + NML_DBUS_META_INTERFACE_PRIO_NMCLIENT, + NML_DBUS_META_IFACE_DBUS_PROPERTIES ( + NML_DBUS_META_PROPERTY_INIT_O_PROP ("ActivatingConnection", PROP_ACTIVATING_CONNECTION, NMClient, _priv.nm.activating_connection, nm_active_connection_get_type ), + NML_DBUS_META_PROPERTY_INIT_AO_PROP ("ActiveConnections", PROP_ACTIVE_CONNECTIONS, NMClient, _priv.nm.active_connections, nm_active_connection_get_type, .notify_changed_ao = _property_ao_notify_changed_active_connections_cb ), + NML_DBUS_META_PROPERTY_INIT_AO_PROP ("AllDevices", PROP_ALL_DEVICES, NMClient, _priv.nm.all_devices, nm_device_get_type, .notify_changed_ao = _property_ao_notify_changed_all_devices_cb ), + NML_DBUS_META_PROPERTY_INIT_IGNORE ("Capabilities", "au" ), + NML_DBUS_META_PROPERTY_INIT_AO_PROP ("Checkpoints", PROP_CHECKPOINTS, NMClient, _priv.nm.checkpoints, nm_checkpoint_get_type ), + NML_DBUS_META_PROPERTY_INIT_U ("Connectivity", PROP_CONNECTIVITY, NMClient, _priv.nm.connectivity ), + NML_DBUS_META_PROPERTY_INIT_B ("ConnectivityCheckAvailable", PROP_CONNECTIVITY_CHECK_AVAILABLE, NMClient, _priv.nm.connectivity_check_available ), + NML_DBUS_META_PROPERTY_INIT_B ("ConnectivityCheckEnabled", PROP_CONNECTIVITY_CHECK_ENABLED, NMClient, _priv.nm.connectivity_check_enabled ), + NML_DBUS_META_PROPERTY_INIT_S ("ConnectivityCheckUri", PROP_CONNECTIVITY_CHECK_URI, NMClient, _priv.nm.connectivity_check_uri ), + NML_DBUS_META_PROPERTY_INIT_AO_PROP ("Devices", PROP_DEVICES, NMClient, _priv.nm.devices, nm_device_get_type, .notify_changed_ao = _property_ao_notify_changed_devices_cb ), + NML_DBUS_META_PROPERTY_INIT_IGNORE ("GlobalDnsConfiguration", "a{sv}" ), + NML_DBUS_META_PROPERTY_INIT_U ("Metered", PROP_METERED, NMClient, _priv.nm.metered ), + NML_DBUS_META_PROPERTY_INIT_B ("NetworkingEnabled", PROP_NETWORKING_ENABLED, NMClient, _priv.nm.networking_enabled ), + NML_DBUS_META_PROPERTY_INIT_O_PROP ("PrimaryConnection", PROP_PRIMARY_CONNECTION, NMClient, _priv.nm.primary_connection, nm_active_connection_get_type ), + NML_DBUS_META_PROPERTY_INIT_IGNORE ("PrimaryConnectionType", "s" ), + NML_DBUS_META_PROPERTY_INIT_B ("Startup", PROP_STARTUP, NMClient, _priv.nm.startup ), + NML_DBUS_META_PROPERTY_INIT_U ("State", PROP_STATE, NMClient, _priv.nm.state ), + NML_DBUS_META_PROPERTY_INIT_S ("Version", PROP_VERSION, NMClient, _priv.nm.version ), + NML_DBUS_META_PROPERTY_INIT_IGNORE ("WimaxEnabled", "b" ), + NML_DBUS_META_PROPERTY_INIT_IGNORE ("WimaxHardwareEnabled", "b" ), + NML_DBUS_META_PROPERTY_INIT_B ("WirelessEnabled", PROP_WIRELESS_ENABLED, NMClient, _priv.nm.wireless_enabled ), + NML_DBUS_META_PROPERTY_INIT_B ("WirelessHardwareEnabled", PROP_WIRELESS_HARDWARE_ENABLED, NMClient, _priv.nm.wireless_hardware_enabled ), + NML_DBUS_META_PROPERTY_INIT_B ("WwanEnabled", PROP_WWAN_ENABLED, NMClient, _priv.nm.wwan_enabled ), + NML_DBUS_META_PROPERTY_INIT_B ("WwanHardwareEnabled", PROP_WWAN_HARDWARE_ENABLED, NMClient, _priv.nm.wwan_hardware_enabled ), + ), +); + +const NMLDBusMetaIface _nml_dbus_meta_iface_nm_settings = NML_DBUS_META_IFACE_INIT_PROP ( + NM_DBUS_INTERFACE_SETTINGS, + nm_client_get_type, + NML_DBUS_META_INTERFACE_PRIO_NMCLIENT, + NML_DBUS_META_IFACE_DBUS_PROPERTIES ( + NML_DBUS_META_PROPERTY_INIT_B ("CanModify", PROP_CAN_MODIFY, NMClient, _priv.settings.can_modify ), + NML_DBUS_META_PROPERTY_INIT_AO_PROP ("Connections", PROP_CONNECTIONS, NMClient, _priv.settings.connections, nm_remote_connection_get_type, .notify_changed_ao = _property_ao_notify_changed_connections_cb, .check_nmobj_visible_fcn = (gboolean (*) (GObject *)) nm_remote_connection_get_visible ), + NML_DBUS_META_PROPERTY_INIT_S ("Hostname", PROP_HOSTNAME, NMClient, _priv.settings.hostname ), + ), +); + +const NMLDBusMetaIface _nml_dbus_meta_iface_nm_dnsmanager = NML_DBUS_META_IFACE_INIT_PROP ( + NM_DBUS_INTERFACE_DNS_MANAGER, + nm_client_get_type, + NML_DBUS_META_INTERFACE_PRIO_NMCLIENT, + NML_DBUS_META_IFACE_DBUS_PROPERTIES ( + NML_DBUS_META_PROPERTY_INIT_FCN ("Configuration", PROP_DNS_CONFIGURATION, "aa{sv}", _notify_update_prop_dns_manager_configuration ), + NML_DBUS_META_PROPERTY_INIT_S ("Mode", PROP_DNS_MODE, NMClient, _priv.dns_manager.mode ), + NML_DBUS_META_PROPERTY_INIT_S ("RcManager", PROP_DNS_RC_MANAGER, NMClient, _priv.dns_manager.rc_manager ), + ), +); + static void nm_client_class_init (NMClientClass *client_class) { GObjectClass *object_class = G_OBJECT_CLASS (client_class); + _dbus_path_nm = nm_ref_string_new (NM_DBUS_PATH); + _dbus_path_settings = nm_ref_string_new (NM_DBUS_PATH_SETTINGS); + _dbus_path_dns_manager = nm_ref_string_new (NM_DBUS_PATH_DNS_MANAGER); + object_class->get_property = get_property; object_class->set_property = set_property; object_class->constructed = constructed; @@ -4081,6 +7199,19 @@ nm_client_class_init (NMClientClass *client_class) G_PARAM_STATIC_STRINGS); /** + * NMClient:connectivity-check-uri: + * + * The used URI for connectivity checking. + * + * Since: 1.22 + **/ + obj_properties[PROP_CONNECTIVITY_CHECK_URI] = + g_param_spec_string (NM_CLIENT_CONNECTIVITY_CHECK_URI, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + + /** * NMClient:primary-connection: * * The #NMActiveConnection of the device with the default route; @@ -4230,7 +7361,9 @@ nm_client_class_init (NMClientClass *client_class) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + _nml_dbus_meta_class_init_with_properties (object_class, &_nml_dbus_meta_iface_nm, + &_nml_dbus_meta_iface_nm_settings, + &_nml_dbus_meta_iface_nm_dnsmanager); /** * NMClient::device-added: diff --git a/libnm/nm-client.h b/libnm/nm-client.h index 41481f11f7..4c1436f495 100644 --- a/libnm/nm-client.h +++ b/libnm/nm-client.h @@ -45,6 +45,7 @@ _NM_DEPRECATED_SYNC_WRITABLE_PROPERTY #define NM_CLIENT_ACTIVE_CONNECTIONS "active-connections" #define NM_CLIENT_CONNECTIVITY "connectivity" +#define NM_CLIENT_CONNECTIVITY_CHECK_URI "connectivity-check-uri" #define NM_CLIENT_CONNECTIVITY_CHECK_AVAILABLE "connectivity-check-available" _NM_DEPRECATED_SYNC_WRITABLE_PROPERTY @@ -224,6 +225,9 @@ NMState nm_client_get_state (NMClient *client); gboolean nm_client_get_startup (NMClient *client); gboolean nm_client_get_nm_running (NMClient *client); +NM_AVAILABLE_IN_1_22 +NMMetered nm_client_get_metered (NMClient *client); + gboolean nm_client_networking_get_enabled (NMClient *client); _NM_DEPRECATED_SYNC_METHOD diff --git a/libnm/nm-dbus-helpers.c b/libnm/nm-dbus-helpers.c index 6272dd5820..a27b7e8682 100644 --- a/libnm/nm-dbus-helpers.c +++ b/libnm/nm-dbus-helpers.c @@ -27,65 +27,6 @@ _nm_dbus_bus_type (void) return v; } -/* D-Bus has an upper limit on number of Match rules and it's rather easy - * to hit as the proxy likes to add one for each object. Let's remove the Match - * rule the proxy added and ensure a less granular rule is present instead. - * - * Also, don't do this immediately since it has a performance penalty. - * Still better than losing the signals altogether. - * - * Ideally, we should be able to tell glib not to hook its rules: - * https://bugzilla.gnome.org/show_bug.cgi?id=758749 - */ -void -_nm_dbus_proxy_replace_match (GDBusProxy *proxy) -{ - GDBusConnection *connection = g_dbus_proxy_get_connection (proxy); - static unsigned match_counter = 1024; - char *match; - - if (match_counter == 1) { - /* If we hit the low matches watermark, install a - * less granular one. */ - g_dbus_connection_call (connection, - "org.freedesktop.DBus", - "/org/freedesktop/DBus", - "org.freedesktop.DBus", - "AddMatch", - g_variant_new ("(s)", "type='signal',sender='" NM_DBUS_SERVICE "'"), - NULL, - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - NULL, - NULL); - } - - if (match_counter) - match_counter--; - if (match_counter) - return; - - /* Remove what this proxy added. */ - match = g_strdup_printf ("type='signal',sender='" NM_DBUS_SERVICE "'," - "interface='%s',path='%s'", - g_dbus_proxy_get_interface_name (proxy), - g_dbus_proxy_get_object_path (proxy)); - g_dbus_connection_call (connection, - "org.freedesktop.DBus", - "/org/freedesktop/DBus", - "org.freedesktop.DBus", - "RemoveMatch", - g_variant_new ("(s)", match), - NULL, - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - NULL, - NULL); - g_free (match); -} - /* Binds the properties on a generated server-side GDBus object to the * corresponding properties on the public object. */ diff --git a/libnm/nm-dbus-helpers.h b/libnm/nm-dbus-helpers.h index 5a0fb756ab..f83f2b0d9e 100644 --- a/libnm/nm-dbus-helpers.h +++ b/libnm/nm-dbus-helpers.h @@ -16,8 +16,6 @@ GBusType _nm_dbus_bus_type (void); -void _nm_dbus_proxy_replace_match (GDBusProxy *proxy); - void _nm_dbus_bind_properties (gpointer object, gpointer skeleton); diff --git a/libnm/nm-device-6lowpan.c b/libnm/nm-device-6lowpan.c index 25f3932979..5899df3044 100644 --- a/libnm/nm-device-6lowpan.c +++ b/libnm/nm-device-6lowpan.c @@ -17,7 +17,7 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( ); typedef struct { - NMDevice *parent; + NMLDBusPropertyO parent; char *hw_address; } NMDevice6LowpanPrivate; @@ -49,7 +49,7 @@ nm_device_6lowpan_get_parent (NMDevice6Lowpan *device) { g_return_val_if_fail (NM_IS_DEVICE_6LOWPAN (device), NULL); - return NM_DEVICE_6LOWPAN_GET_PRIVATE (device)->parent; + return nml_dbus_property_o_get_obj (&NM_DEVICE_6LOWPAN_GET_PRIVATE (device)->parent); } /** @@ -77,7 +77,7 @@ get_hw_address (NMDevice *device) return nm_device_6lowpan_get_hw_address (NM_DEVICE_6LOWPAN (device)); } -/***********************************************************/ +/*****************************************************************************/ static void nm_device_6lowpan_init (NMDevice6Lowpan *device) @@ -85,31 +85,13 @@ nm_device_6lowpan_init (NMDevice6Lowpan *device) } static void -init_dbus (NMObject *object) +dispose (GObject *object) { NMDevice6LowpanPrivate *priv = NM_DEVICE_6LOWPAN_GET_PRIVATE (object); - const NMPropertiesInfo property_info[] = { - { NM_DEVICE_6LOWPAN_PARENT, &priv->parent, NULL, NM_TYPE_DEVICE }, - { NM_DEVICE_6LOWPAN_HW_ADDRESS, &priv->hw_address }, - { NULL }, - }; - NM_OBJECT_CLASS (nm_device_6lowpan_parent_class)->init_dbus (object); + G_OBJECT_CLASS (nm_device_6lowpan_parent_class)->dispose (object); - _nm_object_register_properties (object, - NM_DBUS_INTERFACE_DEVICE_6LOWPAN, - property_info); -} - -static void -finalize (GObject *object) -{ - NMDevice6LowpanPrivate *priv = NM_DEVICE_6LOWPAN_GET_PRIVATE (object); - - g_free (priv->hw_address); - g_clear_object (&priv->parent); - - G_OBJECT_CLASS (nm_device_6lowpan_parent_class)->finalize (object); + nm_clear_g_free (&priv->hw_address); } static void @@ -133,6 +115,16 @@ get_property (GObject *object, } } +const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_lowpan = NML_DBUS_META_IFACE_INIT_PROP ( + NM_DBUS_INTERFACE_DEVICE_6LOWPAN, + nm_device_6lowpan_get_type, + NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, + NML_DBUS_META_IFACE_DBUS_PROPERTIES ( + NML_DBUS_META_PROPERTY_INIT_S ("HwAddress", PROP_HW_ADDRESS, NMDevice6Lowpan, _priv.hw_address ), + NML_DBUS_META_PROPERTY_INIT_O_PROP ("Parent", PROP_PARENT, NMDevice6Lowpan, _priv.parent, nm_device_get_type ), + ), +); + static void nm_device_6lowpan_class_init (NMDevice6LowpanClass *klass) { @@ -141,9 +133,11 @@ nm_device_6lowpan_class_init (NMDevice6LowpanClass *klass) NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); object_class->get_property = get_property; - object_class->finalize = finalize; + object_class->dispose = dispose; + + _NM_OBJECT_CLASS_INIT_PRIV_PTR_DIRECT (nm_object_class, NMDevice6Lowpan); - nm_object_class->init_dbus = init_dbus; + _NM_OBJECT_CLASS_INIT_PROPERTY_O_FIELDS_1 (nm_object_class, NMDevice6LowpanPrivate, parent); device_class->get_hw_address = get_hw_address; @@ -173,5 +167,5 @@ nm_device_6lowpan_class_init (NMDevice6LowpanClass *klass) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + _nml_dbus_meta_class_init_with_properties (object_class, &_nml_dbus_meta_iface_nm_device_lowpan); } diff --git a/libnm/nm-device-adsl.c b/libnm/nm-device-adsl.c index 08174d4063..56ab49edb7 100644 --- a/libnm/nm-device-adsl.c +++ b/libnm/nm-device-adsl.c @@ -19,7 +19,7 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( ); typedef struct { - gboolean carrier; + bool carrier; } NMDeviceAdslPrivate; struct _NMDeviceAdsl { @@ -82,22 +82,6 @@ nm_device_adsl_init (NMDeviceAdsl *device) } static void -init_dbus (NMObject *object) -{ - NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (object); - const NMPropertiesInfo property_info[] = { - { NM_DEVICE_ADSL_CARRIER, &priv->carrier }, - { NULL }, - }; - - NM_OBJECT_CLASS (nm_device_adsl_parent_class)->init_dbus (object); - - _nm_object_register_properties (object, - NM_DBUS_INTERFACE_DEVICE_ADSL, - property_info); -} - -static void get_property (GObject *object, guint prop_id, GValue *value, @@ -115,17 +99,23 @@ get_property (GObject *object, } } +const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_adsl = NML_DBUS_META_IFACE_INIT_PROP ( + NM_DBUS_INTERFACE_DEVICE_ADSL, + nm_device_adsl_get_type, + NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, + NML_DBUS_META_IFACE_DBUS_PROPERTIES ( + NML_DBUS_META_PROPERTY_INIT_B ("Carrier", PROP_CARRIER, NMDeviceAdsl, _priv.carrier), + ), +); + static void nm_device_adsl_class_init (NMDeviceAdslClass *adsl_class) { GObjectClass *object_class = G_OBJECT_CLASS (adsl_class); - NMObjectClass *nm_object_class = NM_OBJECT_CLASS (adsl_class); NMDeviceClass *device_class = NM_DEVICE_CLASS (adsl_class); object_class->get_property = get_property; - nm_object_class->init_dbus = init_dbus; - device_class->connection_compatible = connection_compatible; device_class->get_setting_type = get_setting_type; @@ -140,5 +130,5 @@ nm_device_adsl_class_init (NMDeviceAdslClass *adsl_class) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + _nml_dbus_meta_class_init_with_properties (object_class, &_nml_dbus_meta_iface_nm_device_adsl); } diff --git a/libnm/nm-device-bond.c b/libnm/nm-device-bond.c index 880c4f94b8..66c1bf8331 100644 --- a/libnm/nm-device-bond.c +++ b/libnm/nm-device-bond.c @@ -22,9 +22,9 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( ); typedef struct { + NMLDBusPropertyAO slaves; char *hw_address; - gboolean carrier; - GPtrArray *slaves; + bool carrier; } NMDeviceBondPrivate; struct _NMDeviceBond { @@ -90,7 +90,7 @@ nm_device_bond_get_slaves (NMDeviceBond *device) { g_return_val_if_fail (NM_IS_DEVICE_BOND (device), FALSE); - return NM_DEVICE_BOND_GET_PRIVATE (device)->slaves; + return nml_dbus_property_ao_get_objs_as_ptrarray (&NM_DEVICE_BOND_GET_PRIVATE (device)->slaves); } static gboolean @@ -127,37 +127,6 @@ get_hw_address (NMDevice *device) static void nm_device_bond_init (NMDeviceBond *device) { - NMDeviceBondPrivate *priv = NM_DEVICE_BOND_GET_PRIVATE (device); - - priv->slaves = g_ptr_array_new (); -} - -static void -init_dbus (NMObject *object) -{ - NMDeviceBondPrivate *priv = NM_DEVICE_BOND_GET_PRIVATE (object); - const NMPropertiesInfo property_info[] = { - { NM_DEVICE_BOND_HW_ADDRESS, &priv->hw_address }, - { NM_DEVICE_BOND_CARRIER, &priv->carrier }, - { NM_DEVICE_BOND_SLAVES, &priv->slaves, NULL, NM_TYPE_DEVICE }, - { NULL }, - }; - - NM_OBJECT_CLASS (nm_device_bond_parent_class)->init_dbus (object); - - _nm_object_register_properties (object, - NM_DBUS_INTERFACE_DEVICE_BOND, - property_info); -} - -static void -dispose (GObject *object) -{ - NMDeviceBondPrivate *priv = NM_DEVICE_BOND_GET_PRIVATE (object); - - g_clear_pointer (&priv->slaves, g_ptr_array_unref); - - G_OBJECT_CLASS (nm_device_bond_parent_class)->dispose (object); } static void @@ -194,18 +163,30 @@ get_property (GObject *object, } } +const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_bond = NML_DBUS_META_IFACE_INIT_PROP ( + NM_DBUS_INTERFACE_DEVICE_BOND, + nm_device_bond_get_type, + NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, + NML_DBUS_META_IFACE_DBUS_PROPERTIES ( + NML_DBUS_META_PROPERTY_INIT_B ("Carrier", PROP_CARRIER, NMDeviceBond, _priv.carrier ), + NML_DBUS_META_PROPERTY_INIT_S ("HwAddress", PROP_HW_ADDRESS, NMDeviceBond, _priv.hw_address ), + NML_DBUS_META_PROPERTY_INIT_AO_PROP ("Slaves", PROP_SLAVES, NMDeviceBond, _priv.slaves, nm_device_get_type ), + ), +); + static void -nm_device_bond_class_init (NMDeviceBondClass *bond_class) +nm_device_bond_class_init (NMDeviceBondClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (bond_class); - NMObjectClass *nm_object_class = NM_OBJECT_CLASS (bond_class); - NMDeviceClass *device_class = NM_DEVICE_CLASS (bond_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMObjectClass *nm_object_class = NM_OBJECT_CLASS (klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); object_class->get_property = get_property; - object_class->dispose = dispose; object_class->finalize = finalize; - nm_object_class->init_dbus = init_dbus; + _NM_OBJECT_CLASS_INIT_PRIV_PTR_DIRECT (nm_object_class, NMDeviceBond); + + _NM_OBJECT_CLASS_INIT_PROPERTY_AO_FIELDS_1 (nm_object_class, NMDeviceBondPrivate, slaves); device_class->connection_compatible = connection_compatible; device_class->get_setting_type = get_setting_type; @@ -244,5 +225,5 @@ nm_device_bond_class_init (NMDeviceBondClass *bond_class) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + _nml_dbus_meta_class_init_with_properties (object_class, &_nml_dbus_meta_iface_nm_device_bond); } diff --git a/libnm/nm-device-bridge.c b/libnm/nm-device-bridge.c index 8c3db03e9c..f50054d4b2 100644 --- a/libnm/nm-device-bridge.c +++ b/libnm/nm-device-bridge.c @@ -22,9 +22,9 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( ); typedef struct { + NMLDBusPropertyAO slaves; char *hw_address; - gboolean carrier; - GPtrArray *slaves; + bool carrier; } NMDeviceBridgePrivate; struct _NMDeviceBridge { @@ -90,7 +90,7 @@ nm_device_bridge_get_slaves (NMDeviceBridge *device) { g_return_val_if_fail (NM_IS_DEVICE_BRIDGE (device), FALSE); - return NM_DEVICE_BRIDGE_GET_PRIVATE (device)->slaves; + return nml_dbus_property_ao_get_objs_as_ptrarray (&NM_DEVICE_BRIDGE_GET_PRIVATE (device)->slaves); } static gboolean @@ -132,37 +132,6 @@ get_hw_address (NMDevice *device) static void nm_device_bridge_init (NMDeviceBridge *device) { - NMDeviceBridgePrivate *priv = NM_DEVICE_BRIDGE_GET_PRIVATE (device); - - priv->slaves = g_ptr_array_new (); -} - -static void -init_dbus (NMObject *object) -{ - NMDeviceBridgePrivate *priv = NM_DEVICE_BRIDGE_GET_PRIVATE (object); - const NMPropertiesInfo property_info[] = { - { NM_DEVICE_BRIDGE_HW_ADDRESS, &priv->hw_address }, - { NM_DEVICE_BRIDGE_CARRIER, &priv->carrier }, - { NM_DEVICE_BRIDGE_SLAVES, &priv->slaves, NULL, NM_TYPE_DEVICE }, - { NULL }, - }; - - NM_OBJECT_CLASS (nm_device_bridge_parent_class)->init_dbus (object); - - _nm_object_register_properties (object, - NM_DBUS_INTERFACE_DEVICE_BRIDGE, - property_info); -} - -static void -dispose (GObject *object) -{ - NMDeviceBridgePrivate *priv = NM_DEVICE_BRIDGE_GET_PRIVATE (object); - - g_clear_pointer (&priv->slaves, g_ptr_array_unref); - - G_OBJECT_CLASS (nm_device_bridge_parent_class)->dispose (object); } static void @@ -199,18 +168,30 @@ get_property (GObject *object, } } +const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_bridge = NML_DBUS_META_IFACE_INIT_PROP ( + NM_DBUS_INTERFACE_DEVICE_BRIDGE, + nm_device_bridge_get_type, + NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, + NML_DBUS_META_IFACE_DBUS_PROPERTIES ( + NML_DBUS_META_PROPERTY_INIT_B ("Carrier", PROP_CARRIER, NMDeviceBridge, _priv.carrier ), + NML_DBUS_META_PROPERTY_INIT_S ("HwAddress", PROP_HW_ADDRESS, NMDeviceBridge, _priv.hw_address ), + NML_DBUS_META_PROPERTY_INIT_AO_PROP ("Slaves", PROP_SLAVES, NMDeviceBridge, _priv.slaves, nm_device_get_type ), + ), +); + static void -nm_device_bridge_class_init (NMDeviceBridgeClass *bridge_class) +nm_device_bridge_class_init (NMDeviceBridgeClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (bridge_class); - NMObjectClass *nm_object_class = NM_OBJECT_CLASS (bridge_class); - NMDeviceClass *device_class = NM_DEVICE_CLASS (bridge_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMObjectClass *nm_object_class = NM_OBJECT_CLASS (klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); - object_class->dispose = dispose; object_class->finalize = finalize; object_class->get_property = get_property; - nm_object_class->init_dbus = init_dbus; + _NM_OBJECT_CLASS_INIT_PRIV_PTR_DIRECT (nm_object_class, NMDeviceBridge); + + _NM_OBJECT_CLASS_INIT_PROPERTY_AO_FIELDS_1 (nm_object_class, NMDeviceBridgePrivate, slaves); device_class->connection_compatible = connection_compatible; device_class->get_setting_type = get_setting_type; @@ -249,5 +230,5 @@ nm_device_bridge_class_init (NMDeviceBridgeClass *bridge_class) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + _nml_dbus_meta_class_init_with_properties (object_class, &_nml_dbus_meta_iface_nm_device_bridge); } diff --git a/libnm/nm-device-bt.c b/libnm/nm-device-bt.c index d1600a4277..150b5d84cb 100644 --- a/libnm/nm-device-bt.c +++ b/libnm/nm-device-bt.c @@ -184,24 +184,6 @@ nm_device_bt_init (NMDeviceBt *device) } static void -init_dbus (NMObject *object) -{ - NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (object); - const NMPropertiesInfo property_info[] = { - { NM_DEVICE_BT_HW_ADDRESS, &priv->hw_address }, - { NM_DEVICE_BT_NAME, &priv->name }, - { NM_DEVICE_BT_CAPABILITIES, &priv->bt_capabilities }, - { NULL }, - }; - - NM_OBJECT_CLASS (nm_device_bt_parent_class)->init_dbus (object); - - _nm_object_register_properties (object, - NM_DBUS_INTERFACE_DEVICE_BLUETOOTH, - property_info); -} - -static void finalize (GObject *object) { NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (object); @@ -236,18 +218,26 @@ get_property (GObject *object, } } +const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_bluetooth = NML_DBUS_META_IFACE_INIT_PROP ( + NM_DBUS_INTERFACE_DEVICE_BLUETOOTH, + nm_device_bt_get_type, + NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, + NML_DBUS_META_IFACE_DBUS_PROPERTIES ( + NML_DBUS_META_PROPERTY_INIT_U ("BtCapabilities", PROP_BT_CAPABILITIES, NMDeviceBt, _priv.bt_capabilities ), + NML_DBUS_META_PROPERTY_INIT_S ("HwAddress", PROP_HW_ADDRESS, NMDeviceBt, _priv.hw_address ), + NML_DBUS_META_PROPERTY_INIT_S ("Name", PROP_NAME, NMDeviceBt, _priv.name ), + ), +); + static void nm_device_bt_class_init (NMDeviceBtClass *bt_class) { GObjectClass *object_class = G_OBJECT_CLASS (bt_class); - NMObjectClass *nm_object_class = NM_OBJECT_CLASS (bt_class); NMDeviceClass *device_class = NM_DEVICE_CLASS (bt_class); object_class->get_property = get_property; object_class->finalize = finalize; - nm_object_class->init_dbus = init_dbus; - device_class->connection_compatible = connection_compatible; device_class->get_setting_type = get_setting_type; device_class->get_hw_address = get_hw_address; @@ -286,5 +276,5 @@ nm_device_bt_class_init (NMDeviceBtClass *bt_class) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + _nml_dbus_meta_class_init_with_properties (object_class, &_nml_dbus_meta_iface_nm_device_bluetooth); } diff --git a/libnm/nm-device-dummy.c b/libnm/nm-device-dummy.c index a7f375fdf1..4916cc7d9f 100644 --- a/libnm/nm-device-dummy.c +++ b/libnm/nm-device-dummy.c @@ -99,29 +99,13 @@ nm_device_dummy_init (NMDeviceDummy *device) } static void -init_dbus (NMObject *object) +finalize (GObject *object) { NMDeviceDummyPrivate *priv = NM_DEVICE_DUMMY_GET_PRIVATE (object); - const NMPropertiesInfo property_info[] = { - { NM_DEVICE_DUMMY_HW_ADDRESS, &priv->hw_address }, - { NULL }, - }; - NM_OBJECT_CLASS (nm_device_dummy_parent_class)->init_dbus (object); + g_free (priv->hw_address); - _nm_object_register_properties (object, - NM_DBUS_INTERFACE_DEVICE_DUMMY, - property_info); -} - -static void -dispose (GObject *object) -{ - NMDeviceDummyPrivate *priv = NM_DEVICE_DUMMY_GET_PRIVATE (object); - - g_clear_pointer (&priv->hw_address, g_free); - - G_OBJECT_CLASS (nm_device_dummy_parent_class)->dispose (object); + G_OBJECT_CLASS (nm_device_dummy_parent_class)->finalize (object); } static void @@ -142,17 +126,23 @@ get_property (GObject *object, } } +const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_dummy = NML_DBUS_META_IFACE_INIT_PROP ( + NM_DBUS_INTERFACE_DEVICE_DUMMY, + nm_device_dummy_get_type, + NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, + NML_DBUS_META_IFACE_DBUS_PROPERTIES ( + NML_DBUS_META_PROPERTY_INIT_S ("HwAddress", PROP_HW_ADDRESS, NMDeviceDummy, _priv.hw_address ), + ), +); + static void nm_device_dummy_class_init (NMDeviceDummyClass *dummy_class) { GObjectClass *object_class = G_OBJECT_CLASS (dummy_class); - NMObjectClass *nm_object_class = NM_OBJECT_CLASS (dummy_class); NMDeviceClass *device_class = NM_DEVICE_CLASS (dummy_class); object_class->get_property = get_property; - object_class->dispose = dispose; - - nm_object_class->init_dbus = init_dbus; + object_class->finalize = finalize; device_class->connection_compatible = connection_compatible; device_class->get_hw_address = get_hw_address; @@ -171,5 +161,5 @@ nm_device_dummy_class_init (NMDeviceDummyClass *dummy_class) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + _nml_dbus_meta_class_init_with_properties (object_class, &_nml_dbus_meta_iface_nm_device_dummy); } diff --git a/libnm/nm-device-ethernet.c b/libnm/nm-device-ethernet.c index 94ec318ed6..7cd5b89fc1 100644 --- a/libnm/nm-device-ethernet.c +++ b/libnm/nm-device-ethernet.c @@ -25,11 +25,11 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( ); typedef struct { + char **s390_subchannels; char *hw_address; char *perm_hw_address; guint32 speed; - gboolean carrier; - char **s390_subchannels; + bool carrier; } NMDeviceEthernetPrivate; struct _NMDeviceEthernet { @@ -124,24 +124,12 @@ nm_device_ethernet_get_carrier (NMDeviceEthernet *device) * * Since: 1.2 **/ -const char * const * +const char *const* nm_device_ethernet_get_s390_subchannels (NMDeviceEthernet *device) { g_return_val_if_fail (NM_IS_DEVICE_ETHERNET (device), NULL); - return (const char * const *) NM_DEVICE_ETHERNET_GET_PRIVATE (device)->s390_subchannels; -} - -static guint32 -_subchannels_count_num (const char * const *array) -{ - int i; - - if (!array) - return 0; - for (i = 0; array[i]; i++) - /* NOP */; - return i; + return (const char *const*) NM_DEVICE_ETHERNET_GET_PRIVATE (device)->s390_subchannels; } static gboolean @@ -149,14 +137,14 @@ match_subchans (NMDeviceEthernet *self, NMSettingWired *s_wired, gboolean *try_m { NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); const char * const *subchans; - guint32 num1, num2; - int i, j; + gsize num1, num2; + gsize i, j; *try_mac = TRUE; subchans = nm_setting_wired_get_s390_subchannels (s_wired); - num1 = _subchannels_count_num (subchans); - num2 = _subchannels_count_num ((const char * const *) priv->s390_subchannels); + num1 = NM_PTRARRAY_LEN (subchans); + num2 = NM_PTRARRAY_LEN (priv->s390_subchannels); /* connection has no subchannels */ if (num1 == 0) return TRUE; @@ -277,26 +265,6 @@ nm_device_ethernet_init (NMDeviceEthernet *device) } static void -init_dbus (NMObject *object) -{ - NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (object); - const NMPropertiesInfo property_info[] = { - { NM_DEVICE_ETHERNET_HW_ADDRESS, &priv->hw_address }, - { NM_DEVICE_ETHERNET_PERMANENT_HW_ADDRESS, &priv->perm_hw_address }, - { NM_DEVICE_ETHERNET_SPEED, &priv->speed }, - { NM_DEVICE_ETHERNET_CARRIER, &priv->carrier }, - { NM_DEVICE_ETHERNET_S390_SUBCHANNELS, &priv->s390_subchannels }, - { NULL }, - }; - - NM_OBJECT_CLASS (nm_device_ethernet_parent_class)->init_dbus (object); - - _nm_object_register_properties (object, - NM_DBUS_INTERFACE_DEVICE_WIRED, - property_info); -} - -static void finalize (GObject *object) { NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (object); @@ -339,18 +307,35 @@ get_property (GObject *object, } } +/* TODO: implemented Veth. */ +const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_veth = NML_DBUS_META_IFACE_INIT ( + NM_DBUS_INTERFACE_DEVICE_VETH, + NULL, + NML_DBUS_META_INTERFACE_PRIO_NONE, +); + +const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_wired = NML_DBUS_META_IFACE_INIT_PROP ( + NM_DBUS_INTERFACE_DEVICE_WIRED, + nm_device_ethernet_get_type, + NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, + NML_DBUS_META_IFACE_DBUS_PROPERTIES ( + NML_DBUS_META_PROPERTY_INIT_B ("Carrier", PROP_CARRIER, NMDeviceEthernet, _priv.carrier ), + NML_DBUS_META_PROPERTY_INIT_S ("HwAddress", PROP_HW_ADDRESS, NMDeviceEthernet, _priv.hw_address ), + NML_DBUS_META_PROPERTY_INIT_S ("PermHwAddress", PROP_PERM_HW_ADDRESS, NMDeviceEthernet, _priv.perm_hw_address ), + NML_DBUS_META_PROPERTY_INIT_AS ("S390Subchannels", PROP_S390_SUBCHANNELS, NMDeviceEthernet, _priv.s390_subchannels ), + NML_DBUS_META_PROPERTY_INIT_U ("Speed", PROP_SPEED, NMDeviceEthernet, _priv.speed ), + ), +); + static void nm_device_ethernet_class_init (NMDeviceEthernetClass *eth_class) { GObjectClass *object_class = G_OBJECT_CLASS (eth_class); - NMObjectClass *nm_object_class = NM_OBJECT_CLASS (eth_class); NMDeviceClass *device_class = NM_DEVICE_CLASS (eth_class); object_class->get_property = get_property; object_class->finalize = finalize; - nm_object_class->init_dbus = init_dbus; - device_class->connection_compatible = connection_compatible; device_class->get_setting_type = get_setting_type; device_class->get_hw_address = get_hw_address; @@ -413,5 +398,5 @@ nm_device_ethernet_class_init (NMDeviceEthernetClass *eth_class) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + _nml_dbus_meta_class_init_with_properties (object_class, &_nml_dbus_meta_iface_nm_device_wired); } diff --git a/libnm/nm-device-generic.c b/libnm/nm-device-generic.c index f8c4d25737..b1c784757f 100644 --- a/libnm/nm-device-generic.c +++ b/libnm/nm-device-generic.c @@ -109,23 +109,6 @@ nm_device_generic_init (NMDeviceGeneric *device) } static void -init_dbus (NMObject *object) -{ - NMDeviceGenericPrivate *priv = NM_DEVICE_GENERIC_GET_PRIVATE (object); - const NMPropertiesInfo property_info[] = { - { NM_DEVICE_GENERIC_HW_ADDRESS, &priv->hw_address }, - { NM_DEVICE_GENERIC_TYPE_DESCRIPTION, &priv->type_description }, - { NULL }, - }; - - NM_OBJECT_CLASS (nm_device_generic_parent_class)->init_dbus (object); - - _nm_object_register_properties (object, - NM_DBUS_INTERFACE_DEVICE_GENERIC, - property_info); -} - -static void finalize (GObject *object) { NMDeviceGenericPrivate *priv = NM_DEVICE_GENERIC_GET_PRIVATE (object); @@ -158,18 +141,25 @@ get_property (GObject *object, } } +const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_generic = NML_DBUS_META_IFACE_INIT_PROP ( + NM_DBUS_INTERFACE_DEVICE_GENERIC, + nm_device_generic_get_type, + NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, + NML_DBUS_META_IFACE_DBUS_PROPERTIES ( + NML_DBUS_META_PROPERTY_INIT_S ("HwAddress", PROP_HW_ADDRESS, NMDeviceGeneric, _priv.hw_address ), + NML_DBUS_META_PROPERTY_INIT_S ("TypeDescription", PROP_TYPE_DESCRIPTION, NMDeviceGeneric, _priv.type_description ), + ), +); + static void nm_device_generic_class_init (NMDeviceGenericClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMObjectClass *nm_object_class = NM_OBJECT_CLASS (klass); NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); object_class->get_property = get_property; object_class->finalize = finalize; - nm_object_class->init_dbus = init_dbus; - device_class->get_type_description = get_type_description; device_class->get_hw_address = get_hw_address; device_class->connection_compatible = connection_compatible; @@ -198,5 +188,5 @@ nm_device_generic_class_init (NMDeviceGenericClass *klass) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + _nml_dbus_meta_class_init_with_properties (object_class, &_nml_dbus_meta_iface_nm_device_generic); } diff --git a/libnm/nm-device-infiniband.c b/libnm/nm-device-infiniband.c index b48431a91c..c3e57c9596 100644 --- a/libnm/nm-device-infiniband.c +++ b/libnm/nm-device-infiniband.c @@ -21,7 +21,7 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( typedef struct { char *hw_address; - gboolean carrier; + bool carrier; } NMDeviceInfinibandPrivate; struct _NMDeviceInfiniband { @@ -127,23 +127,6 @@ nm_device_infiniband_init (NMDeviceInfiniband *device) } static void -init_dbus (NMObject *object) -{ - NMDeviceInfinibandPrivate *priv = NM_DEVICE_INFINIBAND_GET_PRIVATE (object); - const NMPropertiesInfo property_info[] = { - { NM_DEVICE_INFINIBAND_HW_ADDRESS, &priv->hw_address }, - { NM_DEVICE_INFINIBAND_CARRIER, &priv->carrier }, - { NULL }, - }; - - NM_OBJECT_CLASS (nm_device_infiniband_parent_class)->init_dbus (object); - - _nm_object_register_properties (object, - NM_DBUS_INTERFACE_DEVICE_INFINIBAND, - property_info); -} - -static void finalize (GObject *object) { NMDeviceInfinibandPrivate *priv = NM_DEVICE_INFINIBAND_GET_PRIVATE (object); @@ -174,18 +157,25 @@ get_property (GObject *object, } } +const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_infiniband = NML_DBUS_META_IFACE_INIT_PROP ( + NM_DBUS_INTERFACE_DEVICE_INFINIBAND, + nm_device_infiniband_get_type, + NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, + NML_DBUS_META_IFACE_DBUS_PROPERTIES ( + NML_DBUS_META_PROPERTY_INIT_B ("Carrier", PROP_CARRIER, NMDeviceInfiniband, _priv.carrier ), + NML_DBUS_META_PROPERTY_INIT_S ("HwAddress", PROP_HW_ADDRESS, NMDeviceInfiniband, _priv.hw_address ), + ), +); + static void nm_device_infiniband_class_init (NMDeviceInfinibandClass *ib_class) { GObjectClass *object_class = G_OBJECT_CLASS (ib_class); - NMObjectClass *nm_object_class = NM_OBJECT_CLASS (ib_class); NMDeviceClass *device_class = NM_DEVICE_CLASS (ib_class); object_class->get_property = get_property; object_class->finalize = finalize; - nm_object_class->init_dbus = init_dbus; - device_class->connection_compatible = connection_compatible; device_class->get_setting_type = get_setting_type; device_class->get_hw_address = get_hw_address; @@ -212,5 +202,5 @@ nm_device_infiniband_class_init (NMDeviceInfinibandClass *ib_class) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + _nml_dbus_meta_class_init_with_properties (object_class, &_nml_dbus_meta_iface_nm_device_infiniband); } diff --git a/libnm/nm-device-ip-tunnel.c b/libnm/nm-device-ip-tunnel.c index 3408dd28f0..2990e204a6 100644 --- a/libnm/nm-device-ip-tunnel.c +++ b/libnm/nm-device-ip-tunnel.c @@ -31,18 +31,18 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( ); typedef struct { - NMIPTunnelMode mode; - NMDevice *parent; + NMLDBusPropertyO parent; char *local; char *remote; - guint8 ttl; - guint8 tos; - gboolean path_mtu_discovery; char *input_key; char *output_key; - guint8 encap_limit; + guint32 mode; guint32 flow_label; guint32 flags; + guint8 ttl; + guint8 tos; + guint8 encapsulation_limit; + bool path_mtu_discovery; } NMDeviceIPTunnelPrivate; struct _NMDeviceIPTunnel { @@ -89,7 +89,7 @@ nm_device_ip_tunnel_get_parent (NMDeviceIPTunnel *device) { g_return_val_if_fail (NM_IS_DEVICE_IP_TUNNEL (device), NULL); - return NM_DEVICE_IP_TUNNEL_GET_PRIVATE (device)->parent; + return nml_dbus_property_o_get_obj (&NM_DEVICE_IP_TUNNEL_GET_PRIVATE (device)->parent); } /** @@ -218,7 +218,7 @@ nm_device_ip_tunnel_get_encapsulation_limit (NMDeviceIPTunnel *device) { g_return_val_if_fail (NM_IS_DEVICE_IP_TUNNEL (device), 0); - return NM_DEVICE_IP_TUNNEL_GET_PRIVATE (device)->encap_limit; + return NM_DEVICE_IP_TUNNEL_GET_PRIVATE (device)->encapsulation_limit; } /** @@ -282,33 +282,6 @@ nm_device_ip_tunnel_init (NMDeviceIPTunnel *device) } static void -init_dbus (NMObject *object) -{ - NMDeviceIPTunnelPrivate *priv = NM_DEVICE_IP_TUNNEL_GET_PRIVATE (object); - const NMPropertiesInfo property_info[] = { - { NM_DEVICE_IP_TUNNEL_PARENT, &priv->parent, NULL, NM_TYPE_DEVICE }, - { NM_DEVICE_IP_TUNNEL_MODE, &priv->mode }, - { NM_DEVICE_IP_TUNNEL_LOCAL, &priv->local }, - { NM_DEVICE_IP_TUNNEL_REMOTE, &priv->remote }, - { NM_DEVICE_IP_TUNNEL_TTL, &priv->ttl }, - { NM_DEVICE_IP_TUNNEL_TOS, &priv->tos }, - { NM_DEVICE_IP_TUNNEL_PATH_MTU_DISCOVERY, &priv->path_mtu_discovery }, - { NM_DEVICE_IP_TUNNEL_INPUT_KEY, &priv->input_key }, - { NM_DEVICE_IP_TUNNEL_OUTPUT_KEY, &priv->output_key }, - { NM_DEVICE_IP_TUNNEL_ENCAPSULATION_LIMIT, &priv->encap_limit }, - { NM_DEVICE_IP_TUNNEL_FLOW_LABEL, &priv->flow_label }, - { NM_DEVICE_IP_TUNNEL_FLAGS, &priv->flags }, - { NULL }, - }; - - NM_OBJECT_CLASS (nm_device_ip_tunnel_parent_class)->init_dbus (object); - - _nm_object_register_properties (object, - NM_DBUS_INTERFACE_DEVICE_IP_TUNNEL, - property_info); -} - -static void finalize (GObject *object) { NMDeviceIPTunnelPrivate *priv = NM_DEVICE_IP_TUNNEL_GET_PRIVATE (object); @@ -317,7 +290,6 @@ finalize (GObject *object) g_free (priv->remote); g_free (priv->input_key); g_free (priv->output_key); - g_clear_object (&priv->parent); G_OBJECT_CLASS (nm_device_ip_tunnel_parent_class)->finalize (object); } @@ -373,17 +345,39 @@ get_property (GObject *object, } } +const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_iptunnel = NML_DBUS_META_IFACE_INIT_PROP ( + NM_DBUS_INTERFACE_DEVICE_IP_TUNNEL, + nm_device_ip_tunnel_get_type, + NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, + NML_DBUS_META_IFACE_DBUS_PROPERTIES ( + NML_DBUS_META_PROPERTY_INIT_Y ("EncapsulationLimit", PROP_ENCAPSULATION_LIMIT, NMDeviceIPTunnel, _priv.encapsulation_limit ), + NML_DBUS_META_PROPERTY_INIT_U ("Flags", PROP_FLAGS, NMDeviceIPTunnel, _priv.flags ), + NML_DBUS_META_PROPERTY_INIT_U ("FlowLabel", PROP_FLOW_LABEL, NMDeviceIPTunnel, _priv.flow_label ), + NML_DBUS_META_PROPERTY_INIT_S ("InputKey", PROP_INPUT_KEY, NMDeviceIPTunnel, _priv.input_key ), + NML_DBUS_META_PROPERTY_INIT_S ("Local", PROP_LOCAL, NMDeviceIPTunnel, _priv.local ), + NML_DBUS_META_PROPERTY_INIT_U ("Mode", PROP_MODE, NMDeviceIPTunnel, _priv.mode ), + NML_DBUS_META_PROPERTY_INIT_S ("OutputKey", PROP_OUTPUT_KEY, NMDeviceIPTunnel, _priv.output_key ), + NML_DBUS_META_PROPERTY_INIT_O_PROP ("Parent", PROP_PARENT, NMDeviceIPTunnel, _priv.parent, nm_device_get_type ), + NML_DBUS_META_PROPERTY_INIT_B ("PathMtuDiscovery", PROP_PATH_MTU_DISCOVERY, NMDeviceIPTunnel, _priv.path_mtu_discovery ), + NML_DBUS_META_PROPERTY_INIT_S ("Remote", PROP_REMOTE, NMDeviceIPTunnel, _priv.remote ), + NML_DBUS_META_PROPERTY_INIT_Y ("Tos", PROP_TOS, NMDeviceIPTunnel, _priv.tos ), + NML_DBUS_META_PROPERTY_INIT_Y ("Ttl", PROP_TTL, NMDeviceIPTunnel, _priv.ttl ), + ), +); + static void -nm_device_ip_tunnel_class_init (NMDeviceIPTunnelClass *bond_class) +nm_device_ip_tunnel_class_init (NMDeviceIPTunnelClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (bond_class); - NMObjectClass *nm_object_class = NM_OBJECT_CLASS (bond_class); - NMDeviceClass *device_class = NM_DEVICE_CLASS (bond_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMObjectClass *nm_object_class = NM_OBJECT_CLASS (klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); object_class->get_property = get_property; object_class->finalize = finalize; - nm_object_class->init_dbus = init_dbus; + _NM_OBJECT_CLASS_INIT_PRIV_PTR_DIRECT (nm_object_class, NMDeviceIPTunnel); + + _NM_OBJECT_CLASS_INIT_PROPERTY_O_FIELDS_1 (nm_object_class, NMDeviceIPTunnelPrivate, parent); device_class->connection_compatible = connection_compatible; device_class->get_setting_type = get_setting_type; @@ -549,5 +543,5 @@ nm_device_ip_tunnel_class_init (NMDeviceIPTunnelClass *bond_class) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + _nml_dbus_meta_class_init_with_properties (object_class, &_nml_dbus_meta_iface_nm_device_iptunnel); } diff --git a/libnm/nm-device-macsec.c b/libnm/nm-device-macsec.c index 59923a8c60..194261f07e 100644 --- a/libnm/nm-device-macsec.c +++ b/libnm/nm-device-macsec.c @@ -31,20 +31,20 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( ); typedef struct { - NMDevice *parent; + NMLDBusPropertyO parent; char *hw_address; + char *validation; guint64 sci; guint64 cipher_suite; - guint8 icv_length; guint32 window; + guint8 icv_length; guint8 encoding_sa; - gboolean encrypt; - gboolean protect; - gboolean include_sci; - gboolean es; - gboolean scb; - gboolean replay_protect; - char *validation; + bool encrypt; + bool protect; + bool include_sci; + bool es; + bool scb; + bool replay_protect; } NMDeviceMacsecPrivate; struct _NMDeviceMacsec { @@ -75,7 +75,7 @@ nm_device_macsec_get_parent (NMDeviceMacsec *device) { g_return_val_if_fail (NM_IS_DEVICE_MACSEC (device), NULL); - return NM_DEVICE_MACSEC_GET_PRIVATE (device)->parent; + return nml_dbus_property_o_get_obj (&NM_DEVICE_MACSEC_GET_PRIVATE (device)->parent); } /** @@ -332,42 +332,12 @@ nm_device_macsec_init (NMDeviceMacsec *device) } static void -init_dbus (NMObject *object) -{ - NMDeviceMacsecPrivate *priv = NM_DEVICE_MACSEC_GET_PRIVATE (object); - const NMPropertiesInfo property_info[] = { - { NM_DEVICE_MACSEC_PARENT, &priv->parent, NULL, NM_TYPE_DEVICE }, - { NM_DEVICE_MACSEC_HW_ADDRESS, &priv->hw_address }, - { NM_DEVICE_MACSEC_SCI, &priv->sci }, - { NM_DEVICE_MACSEC_CIPHER_SUITE, &priv->cipher_suite }, - { NM_DEVICE_MACSEC_ICV_LENGTH, &priv->icv_length }, - { NM_DEVICE_MACSEC_WINDOW, &priv->window }, - { NM_DEVICE_MACSEC_ENCODING_SA, &priv->encoding_sa }, - { NM_DEVICE_MACSEC_ENCRYPT, &priv->encrypt }, - { NM_DEVICE_MACSEC_PROTECT, &priv->protect }, - { NM_DEVICE_MACSEC_INCLUDE_SCI, &priv->include_sci }, - { NM_DEVICE_MACSEC_ES, &priv->es }, - { NM_DEVICE_MACSEC_SCB, &priv->scb }, - { NM_DEVICE_MACSEC_REPLAY_PROTECT, &priv->replay_protect }, - { NM_DEVICE_MACSEC_VALIDATION, &priv->validation }, - { NULL }, - }; - - NM_OBJECT_CLASS (nm_device_macsec_parent_class)->init_dbus (object); - - _nm_object_register_properties (object, - NM_DBUS_INTERFACE_DEVICE_MACSEC, - property_info); -} - -static void finalize (GObject *object) { NMDeviceMacsecPrivate *priv = NM_DEVICE_MACSEC_GET_PRIVATE (object); g_free (priv->validation); g_free (priv->hw_address); - g_clear_object (&priv->parent); G_OBJECT_CLASS (nm_device_macsec_parent_class)->finalize (object); } @@ -429,17 +399,40 @@ get_property (GObject *object, } } +const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_macsec = NML_DBUS_META_IFACE_INIT_PROP ( + NM_DBUS_INTERFACE_DEVICE_MACSEC, + nm_device_macsec_get_type, + NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, + NML_DBUS_META_IFACE_DBUS_PROPERTIES ( + NML_DBUS_META_PROPERTY_INIT_T ("CipherSuite", PROP_CIPHER_SUITE, NMDeviceMacsec, _priv.cipher_suite ), + NML_DBUS_META_PROPERTY_INIT_Y ("EncodingSa", PROP_ENCODING_SA, NMDeviceMacsec, _priv.encoding_sa ), + NML_DBUS_META_PROPERTY_INIT_B ("Encrypt", PROP_ENCRYPT, NMDeviceMacsec, _priv.encrypt ), + NML_DBUS_META_PROPERTY_INIT_B ("Es", PROP_ES, NMDeviceMacsec, _priv.es ), + NML_DBUS_META_PROPERTY_INIT_Y ("IcvLength", PROP_ICV_LENGTH, NMDeviceMacsec, _priv.icv_length ), + NML_DBUS_META_PROPERTY_INIT_B ("IncludeSci", PROP_INCLUDE_SCI, NMDeviceMacsec, _priv.include_sci ), + NML_DBUS_META_PROPERTY_INIT_O_PROP ("Parent", PROP_PARENT, NMDeviceMacsec, _priv.parent, nm_device_get_type ), + NML_DBUS_META_PROPERTY_INIT_B ("Protect", PROP_PROTECT, NMDeviceMacsec, _priv.protect ), + NML_DBUS_META_PROPERTY_INIT_B ("ReplayProtect", PROP_REPLAY_PROTECT, NMDeviceMacsec, _priv.replay_protect ), + NML_DBUS_META_PROPERTY_INIT_B ("Scb", PROP_SCB, NMDeviceMacsec, _priv.scb ), + NML_DBUS_META_PROPERTY_INIT_T ("Sci", PROP_SCI, NMDeviceMacsec, _priv.sci ), + NML_DBUS_META_PROPERTY_INIT_S ("Validation", PROP_VALIDATION, NMDeviceMacsec, _priv.validation ), + NML_DBUS_META_PROPERTY_INIT_U ("Window", PROP_WINDOW, NMDeviceMacsec, _priv.window ), + ), +); + static void -nm_device_macsec_class_init (NMDeviceMacsecClass *macsec_class) +nm_device_macsec_class_init (NMDeviceMacsecClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (macsec_class); - NMObjectClass *nm_object_class = NM_OBJECT_CLASS (macsec_class); - NMDeviceClass *device_class = NM_DEVICE_CLASS (macsec_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMObjectClass *nm_object_class = NM_OBJECT_CLASS (klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); object_class->get_property = get_property; object_class->finalize = finalize; - nm_object_class->init_dbus = init_dbus; + _NM_OBJECT_CLASS_INIT_PRIV_PTR_DIRECT (nm_object_class, NMDeviceMacsec); + + _NM_OBJECT_CLASS_INIT_PROPERTY_O_FIELDS_1 (nm_object_class, NMDeviceMacsecPrivate, parent); device_class->get_hw_address = get_hw_address; @@ -630,5 +623,5 @@ nm_device_macsec_class_init (NMDeviceMacsecClass *macsec_class) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + _nml_dbus_meta_class_init_with_properties (object_class, &_nml_dbus_meta_iface_nm_device_macsec); } diff --git a/libnm/nm-device-macvlan.c b/libnm/nm-device-macvlan.c index 59565b64a1..e703cb5ccf 100644 --- a/libnm/nm-device-macvlan.c +++ b/libnm/nm-device-macvlan.c @@ -24,10 +24,10 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( ); typedef struct { - NMDevice *parent; + NMLDBusPropertyO parent; char *mode; - gboolean no_promisc; - gboolean tap; + bool no_promisc; + bool tap; } NMDeviceMacvlanPrivate; struct _NMDeviceMacvlan { @@ -58,7 +58,7 @@ nm_device_macvlan_get_parent (NMDeviceMacvlan *device) { g_return_val_if_fail (NM_IS_DEVICE_MACVLAN (device), FALSE); - return NM_DEVICE_MACVLAN_GET_PRIVATE (device)->parent; + return nml_dbus_property_o_get_obj (&NM_DEVICE_MACVLAN_GET_PRIVATE (device)->parent); } /** @@ -181,31 +181,11 @@ nm_device_macvlan_init (NMDeviceMacvlan *device) } static void -init_dbus (NMObject *object) -{ - NMDeviceMacvlanPrivate *priv = NM_DEVICE_MACVLAN_GET_PRIVATE (object); - const NMPropertiesInfo property_info[] = { - { NM_DEVICE_MACVLAN_PARENT, &priv->parent, NULL, NM_TYPE_DEVICE }, - { NM_DEVICE_MACVLAN_MODE, &priv->mode }, - { NM_DEVICE_MACVLAN_NO_PROMISC, &priv->no_promisc }, - { NM_DEVICE_MACVLAN_TAP, &priv->tap }, - { NULL }, - }; - - NM_OBJECT_CLASS (nm_device_macvlan_parent_class)->init_dbus (object); - - _nm_object_register_properties (object, - NM_DBUS_INTERFACE_DEVICE_MACVLAN, - property_info); -} - -static void finalize (GObject *object) { NMDeviceMacvlanPrivate *priv = NM_DEVICE_MACVLAN_GET_PRIVATE (object); g_free (priv->mode); - g_clear_object (&priv->parent); G_OBJECT_CLASS (nm_device_macvlan_parent_class)->finalize (object); } @@ -240,17 +220,31 @@ get_property (GObject *object, } } +const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_macvlan = NML_DBUS_META_IFACE_INIT_PROP ( + NM_DBUS_INTERFACE_DEVICE_MACVLAN, + nm_device_macvlan_get_type, + NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, + NML_DBUS_META_IFACE_DBUS_PROPERTIES ( + NML_DBUS_META_PROPERTY_INIT_S ("Mode", PROP_MODE, NMDeviceMacvlan, _priv.mode ), + NML_DBUS_META_PROPERTY_INIT_B ("NoPromisc", PROP_NO_PROMISC, NMDeviceMacvlan, _priv.no_promisc ), + NML_DBUS_META_PROPERTY_INIT_O_PROP ("Parent", PROP_PARENT, NMDeviceMacvlan, _priv.parent, nm_device_get_type ), + NML_DBUS_META_PROPERTY_INIT_B ("Tap", PROP_TAP, NMDeviceMacvlan, _priv.tap ), + ), +); + static void -nm_device_macvlan_class_init (NMDeviceMacvlanClass *gre_class) +nm_device_macvlan_class_init (NMDeviceMacvlanClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (gre_class); - NMObjectClass *nm_object_class = NM_OBJECT_CLASS (gre_class); - NMDeviceClass *device_class = NM_DEVICE_CLASS (gre_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMObjectClass *nm_object_class = NM_OBJECT_CLASS (klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); object_class->get_property = get_property; object_class->finalize = finalize; - nm_object_class->init_dbus = init_dbus; + _NM_OBJECT_CLASS_INIT_PRIV_PTR_DIRECT (nm_object_class, NMDeviceMacvlan); + + _NM_OBJECT_CLASS_INIT_PROPERTY_O_FIELDS_1 (nm_object_class, NMDeviceMacvlanPrivate, parent); device_class->connection_compatible = connection_compatible; device_class->get_setting_type = get_setting_type; @@ -323,5 +317,5 @@ nm_device_macvlan_class_init (NMDeviceMacvlanClass *gre_class) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + _nml_dbus_meta_class_init_with_properties (object_class, &_nml_dbus_meta_iface_nm_device_macvlan); } diff --git a/libnm/nm-device-modem.c b/libnm/nm-device-modem.c index a56eeb4ada..5e7b064b78 100644 --- a/libnm/nm-device-modem.c +++ b/libnm/nm-device-modem.c @@ -25,11 +25,11 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( ); typedef struct { - NMDeviceModemCapabilities caps; - NMDeviceModemCapabilities current_caps; char *device_id; char *operator_code; char *apn; + guint32 modem_capabilities; + guint32 current_capabilities; } NMDeviceModemPrivate; struct _NMDeviceModem { @@ -62,7 +62,7 @@ nm_device_modem_get_modem_capabilities (NMDeviceModem *self) { g_return_val_if_fail (NM_IS_DEVICE_MODEM (self), NM_DEVICE_MODEM_CAPABILITY_NONE); - return NM_DEVICE_MODEM_GET_PRIVATE (self)->caps; + return NM_DEVICE_MODEM_GET_PRIVATE (self)->modem_capabilities; } /** @@ -81,7 +81,7 @@ nm_device_modem_get_current_capabilities (NMDeviceModem *self) { g_return_val_if_fail (NM_IS_DEVICE_MODEM (self), NM_DEVICE_MODEM_CAPABILITY_NONE); - return NM_DEVICE_MODEM_GET_PRIVATE (self)->current_caps; + return NM_DEVICE_MODEM_GET_PRIVATE (self)->current_capabilities; } /** @@ -216,26 +216,6 @@ nm_device_modem_init (NMDeviceModem *device) } static void -init_dbus (NMObject *object) -{ - NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (object); - const NMPropertiesInfo property_info[] = { - { NM_DEVICE_MODEM_MODEM_CAPABILITIES, &priv->caps }, - { NM_DEVICE_MODEM_CURRENT_CAPABILITIES, &priv->current_caps }, - { NM_DEVICE_MODEM_DEVICE_ID, &priv->device_id }, - { NM_DEVICE_MODEM_OPERATOR_CODE, &priv->operator_code }, - { NM_DEVICE_MODEM_APN, &priv->apn }, - { NULL }, - }; - - NM_OBJECT_CLASS (nm_device_modem_parent_class)->init_dbus (object); - - _nm_object_register_properties (object, - NM_DBUS_INTERFACE_DEVICE_MODEM, - property_info); -} - -static void finalize (GObject *object) { NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (object); @@ -277,18 +257,28 @@ get_property (GObject *object, } } +const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_modem = NML_DBUS_META_IFACE_INIT_PROP ( + NM_DBUS_INTERFACE_DEVICE_MODEM, + nm_device_modem_get_type, + NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, + NML_DBUS_META_IFACE_DBUS_PROPERTIES ( + NML_DBUS_META_PROPERTY_INIT_S ("Apn", PROP_APN, NMDeviceModem, _priv.apn ), + NML_DBUS_META_PROPERTY_INIT_U ("CurrentCapabilities", PROP_CURRENT_CAPABILITIES, NMDeviceModem, _priv.current_capabilities ), + NML_DBUS_META_PROPERTY_INIT_S ("DeviceId", PROP_DEVICE_ID, NMDeviceModem, _priv.device_id ), + NML_DBUS_META_PROPERTY_INIT_U ("ModemCapabilities", PROP_MODEM_CAPABILITIES, NMDeviceModem, _priv.modem_capabilities ), + NML_DBUS_META_PROPERTY_INIT_S ("OperatorCode", PROP_OPERATOR_CODE, NMDeviceModem, _priv.operator_code ), + ), +); + static void nm_device_modem_class_init (NMDeviceModemClass *modem_class) { GObjectClass *object_class = G_OBJECT_CLASS (modem_class); - NMObjectClass *nm_object_class = NM_OBJECT_CLASS (modem_class); NMDeviceClass *device_class = NM_DEVICE_CLASS (modem_class); object_class->get_property = get_property; object_class->finalize = finalize; - nm_object_class->init_dbus = init_dbus; - device_class->get_type_description = get_type_description; device_class->connection_compatible = connection_compatible; device_class->get_setting_type = get_setting_type; @@ -354,5 +344,5 @@ nm_device_modem_class_init (NMDeviceModemClass *modem_class) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + _nml_dbus_meta_class_init_with_properties (object_class, &_nml_dbus_meta_iface_nm_device_modem); } diff --git a/libnm/nm-device-olpc-mesh.c b/libnm/nm-device-olpc-mesh.c index 4d81abcc53..1ad320bf86 100644 --- a/libnm/nm-device-olpc-mesh.c +++ b/libnm/nm-device-olpc-mesh.c @@ -21,8 +21,8 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( ); typedef struct { + NMLDBusPropertyO companion; char *hw_address; - NMDeviceWifi *companion; guint32 active_channel; } NMDeviceOlpcMeshPrivate; @@ -71,7 +71,7 @@ nm_device_olpc_mesh_get_companion (NMDeviceOlpcMesh *device) { g_return_val_if_fail (NM_IS_DEVICE_OLPC_MESH (device), NULL); - return NM_DEVICE_OLPC_MESH_GET_PRIVATE (device)->companion; + return nml_dbus_property_o_get_obj (&NM_DEVICE_OLPC_MESH_GET_PRIVATE (device)->companion); } /** @@ -125,34 +125,6 @@ nm_device_olpc_mesh_init (NMDeviceOlpcMesh *device) } static void -init_dbus (NMObject *object) -{ - NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (object); - const NMPropertiesInfo property_info[] = { - { NM_DEVICE_OLPC_MESH_HW_ADDRESS, &priv->hw_address }, - { NM_DEVICE_OLPC_MESH_COMPANION, &priv->companion, NULL, NM_TYPE_DEVICE_WIFI }, - { NM_DEVICE_OLPC_MESH_ACTIVE_CHANNEL, &priv->active_channel }, - { NULL }, - }; - - NM_OBJECT_CLASS (nm_device_olpc_mesh_parent_class)->init_dbus (object); - - _nm_object_register_properties (object, - NM_DBUS_INTERFACE_DEVICE_OLPC_MESH, - property_info); -} - -static void -dispose (GObject *object) -{ - NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (object); - - g_clear_object (&priv->companion); - - G_OBJECT_CLASS (nm_device_olpc_mesh_parent_class)->dispose (object); -} - -static void finalize (GObject *object) { NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (object); @@ -186,18 +158,30 @@ get_property (GObject *object, } } +const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_olpcmesh = NML_DBUS_META_IFACE_INIT_PROP ( + NM_DBUS_INTERFACE_DEVICE_OLPC_MESH, + nm_device_olpc_mesh_get_type, + NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, + NML_DBUS_META_IFACE_DBUS_PROPERTIES ( + NML_DBUS_META_PROPERTY_INIT_U ("ActiveChannel", PROP_ACTIVE_CHANNEL, NMDeviceOlpcMesh, _priv.active_channel ), + NML_DBUS_META_PROPERTY_INIT_O_PROP ("Companion", PROP_COMPANION, NMDeviceOlpcMesh, _priv.companion, nm_device_wifi_get_type ), + NML_DBUS_META_PROPERTY_INIT_S ("HwAddress", PROP_HW_ADDRESS, NMDeviceOlpcMesh, _priv.hw_address ), + ), +); + static void -nm_device_olpc_mesh_class_init (NMDeviceOlpcMeshClass *olpc_mesh_class) +nm_device_olpc_mesh_class_init (NMDeviceOlpcMeshClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (olpc_mesh_class); - NMObjectClass *nm_object_class = NM_OBJECT_CLASS (olpc_mesh_class); - NMDeviceClass *device_class = NM_DEVICE_CLASS (olpc_mesh_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMObjectClass *nm_object_class = NM_OBJECT_CLASS (klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); object_class->get_property = get_property; - object_class->dispose = dispose; object_class->finalize = finalize; - nm_object_class->init_dbus = init_dbus; + _NM_OBJECT_CLASS_INIT_PRIV_PTR_DIRECT (nm_object_class, NMDeviceOlpcMesh); + + _NM_OBJECT_CLASS_INIT_PROPERTY_O_FIELDS_1 (nm_object_class, NMDeviceOlpcMeshPrivate, companion); device_class->connection_compatible = connection_compatible; device_class->get_setting_type = get_setting_type; @@ -236,5 +220,5 @@ nm_device_olpc_mesh_class_init (NMDeviceOlpcMeshClass *olpc_mesh_class) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + _nml_dbus_meta_class_init_with_properties (object_class, &_nml_dbus_meta_iface_nm_device_olpcmesh); } diff --git a/libnm/nm-device-ovs-bridge.c b/libnm/nm-device-ovs-bridge.c index b37743f361..4b946fca7d 100644 --- a/libnm/nm-device-ovs-bridge.c +++ b/libnm/nm-device-ovs-bridge.c @@ -20,7 +20,7 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( ); typedef struct { - GPtrArray *slaves; + NMLDBusPropertyAO slaves; } NMDeviceOvsBridgePrivate; struct _NMDeviceOvsBridge { @@ -55,7 +55,7 @@ nm_device_ovs_bridge_get_slaves (NMDeviceOvsBridge *device) { g_return_val_if_fail (NM_IS_DEVICE_OVS_BRIDGE (device), FALSE); - return NM_DEVICE_OVS_BRIDGE_GET_PRIVATE (device)->slaves; + return nml_dbus_property_ao_get_objs_as_ptrarray (&NM_DEVICE_OVS_BRIDGE_GET_PRIVATE (device)->slaves); } static const char * @@ -97,22 +97,6 @@ get_setting_type (NMDevice *device) /*****************************************************************************/ static void -init_dbus (NMObject *object) -{ - NMDeviceOvsBridge *device = NM_DEVICE_OVS_BRIDGE (object); - const NMPropertiesInfo property_info[] = { - { NM_DEVICE_OVS_BRIDGE_SLAVES, &device->_priv.slaves, NULL, NM_TYPE_DEVICE }, - { NULL }, - }; - - NM_OBJECT_CLASS (nm_device_ovs_bridge_parent_class)->init_dbus (object); - - _nm_object_register_properties (object, - NM_DBUS_INTERFACE_DEVICE_OVS_BRIDGE, - property_info); -} - -static void get_property (GObject *object, guint prop_id, GValue *value, @@ -130,32 +114,34 @@ get_property (GObject *object, } } +/*****************************************************************************/ + static void nm_device_ovs_bridge_init (NMDeviceOvsBridge *device) { } -static void -dispose (GObject *object) -{ - NMDeviceOvsBridgePrivate *priv = NM_DEVICE_OVS_BRIDGE_GET_PRIVATE (object); - - g_clear_pointer (&priv->slaves, g_ptr_array_unref); - - G_OBJECT_CLASS (nm_device_ovs_bridge_parent_class)->dispose (object); -} +const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_ovsbridge = NML_DBUS_META_IFACE_INIT_PROP ( + NM_DBUS_INTERFACE_DEVICE_OVS_BRIDGE, + nm_device_ovs_bridge_get_type, + NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, + NML_DBUS_META_IFACE_DBUS_PROPERTIES ( + NML_DBUS_META_PROPERTY_INIT_AO_PROP ("Slaves", PROP_SLAVES, NMDeviceOvsBridge, _priv.slaves, nm_device_get_type ), + ), +); static void -nm_device_ovs_bridge_class_init (NMDeviceOvsBridgeClass *ovs_bridge_class) +nm_device_ovs_bridge_class_init (NMDeviceOvsBridgeClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (ovs_bridge_class); - NMObjectClass *nm_object_class = NM_OBJECT_CLASS (ovs_bridge_class); - NMDeviceClass *device_class = NM_DEVICE_CLASS (ovs_bridge_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMObjectClass *nm_object_class = NM_OBJECT_CLASS (klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); object_class->get_property = get_property; - object_class->dispose = dispose; - nm_object_class->init_dbus = init_dbus; + _NM_OBJECT_CLASS_INIT_PRIV_PTR_DIRECT (nm_object_class, NMDeviceOvsBridge); + + _NM_OBJECT_CLASS_INIT_PROPERTY_AO_FIELDS_1 (nm_object_class, NMDeviceOvsBridgePrivate, slaves); device_class->get_type_description = get_type_description; device_class->connection_compatible = connection_compatible; @@ -174,5 +160,5 @@ nm_device_ovs_bridge_class_init (NMDeviceOvsBridgeClass *ovs_bridge_class) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + _nml_dbus_meta_class_init_with_properties (object_class, &_nml_dbus_meta_iface_nm_device_ovsbridge); } diff --git a/libnm/nm-device-ovs-interface.c b/libnm/nm-device-ovs-interface.c index c205dd5e7b..a2e3b2cf65 100644 --- a/libnm/nm-device-ovs-interface.c +++ b/libnm/nm-device-ovs-interface.c @@ -69,6 +69,12 @@ nm_device_ovs_interface_init (NMDeviceOvsInterface *device) { } +const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_ovsinterface = NML_DBUS_META_IFACE_INIT ( + NM_DBUS_INTERFACE_DEVICE_OVS_INTERFACE, + nm_device_ovs_interface_get_type, + NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, +); + static void nm_device_ovs_interface_class_init (NMDeviceOvsInterfaceClass *ovs_interface_class) { diff --git a/libnm/nm-device-ovs-port.c b/libnm/nm-device-ovs-port.c index ab39ff7100..f8b963b175 100644 --- a/libnm/nm-device-ovs-port.c +++ b/libnm/nm-device-ovs-port.c @@ -20,7 +20,7 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( ); typedef struct { - GPtrArray *slaves; + NMLDBusPropertyAO slaves; } NMDeviceOvsPortPrivate; struct _NMDeviceOvsPort { @@ -55,7 +55,7 @@ nm_device_ovs_port_get_slaves (NMDeviceOvsPort *device) { g_return_val_if_fail (NM_IS_DEVICE_OVS_PORT (device), FALSE); - return NM_DEVICE_OVS_PORT_GET_PRIVATE (device)->slaves; + return nml_dbus_property_ao_get_objs_as_ptrarray (&NM_DEVICE_OVS_PORT_GET_PRIVATE (device)->slaves); } static const char * @@ -97,23 +97,6 @@ get_setting_type (NMDevice *device) /*****************************************************************************/ static void -init_dbus (NMObject *object) -{ - NMDeviceOvsPort *device = NM_DEVICE_OVS_PORT (object); - NMDeviceOvsPortPrivate *priv = NM_DEVICE_OVS_PORT_GET_PRIVATE (device); - const NMPropertiesInfo property_info[] = { - { NM_DEVICE_OVS_PORT_SLAVES, &priv->slaves, NULL, NM_TYPE_DEVICE }, - { NULL }, - }; - - NM_OBJECT_CLASS (nm_device_ovs_port_parent_class)->init_dbus (object); - - _nm_object_register_properties (object, - NM_DBUS_INTERFACE_DEVICE_OVS_PORT, - property_info); -} - -static void get_property (GObject *object, guint prop_id, GValue *value, @@ -131,32 +114,34 @@ get_property (GObject *object, } } +/*****************************************************************************/ + static void nm_device_ovs_port_init (NMDeviceOvsPort *device) { } -static void -dispose (GObject *object) -{ - NMDeviceOvsPortPrivate *priv = NM_DEVICE_OVS_PORT_GET_PRIVATE (object); - - g_clear_pointer (&priv->slaves, g_ptr_array_unref); - - G_OBJECT_CLASS (nm_device_ovs_port_parent_class)->dispose (object); -} +const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_ovsport = NML_DBUS_META_IFACE_INIT_PROP ( + NM_DBUS_INTERFACE_DEVICE_OVS_PORT, + nm_device_ovs_port_get_type, + NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, + NML_DBUS_META_IFACE_DBUS_PROPERTIES ( + NML_DBUS_META_PROPERTY_INIT_AO_PROP ("Slaves", PROP_SLAVES, NMDeviceOvsPort, _priv.slaves, nm_device_get_type ), + ), +); static void -nm_device_ovs_port_class_init (NMDeviceOvsPortClass *ovs_port_class) +nm_device_ovs_port_class_init (NMDeviceOvsPortClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (ovs_port_class); - NMObjectClass *nm_object_class = NM_OBJECT_CLASS (ovs_port_class); - NMDeviceClass *device_class = NM_DEVICE_CLASS (ovs_port_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMObjectClass *nm_object_class = NM_OBJECT_CLASS (klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); object_class->get_property = get_property; - object_class->dispose = dispose; - nm_object_class->init_dbus = init_dbus; + _NM_OBJECT_CLASS_INIT_PRIV_PTR_DIRECT (nm_object_class, NMDeviceOvsPort); + + _NM_OBJECT_CLASS_INIT_PROPERTY_AO_FIELDS_1 (nm_object_class, NMDeviceOvsPortPrivate, slaves); device_class->get_type_description = get_type_description; device_class->connection_compatible = connection_compatible; @@ -175,5 +160,5 @@ nm_device_ovs_port_class_init (NMDeviceOvsPortClass *ovs_port_class) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + _nml_dbus_meta_class_init_with_properties (object_class, &_nml_dbus_meta_iface_nm_device_ovsport); } diff --git a/libnm/nm-device-ppp.c b/libnm/nm-device-ppp.c index a4ec672310..0484546e58 100644 --- a/libnm/nm-device-ppp.c +++ b/libnm/nm-device-ppp.c @@ -6,6 +6,7 @@ #include "nm-default.h" #include "nm-device-ppp.h" + #include "nm-device.h" /*****************************************************************************/ @@ -27,6 +28,12 @@ nm_device_ppp_init (NMDevicePpp *device) { } +const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_ppp = NML_DBUS_META_IFACE_INIT ( + NM_DBUS_INTERFACE_DEVICE_PPP, + nm_device_ppp_get_type, + NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, +); + static void nm_device_ppp_class_init (NMDevicePppClass *klass) { diff --git a/libnm/nm-device-team.c b/libnm/nm-device-team.c index 08b3b082c1..a1c04c18f8 100644 --- a/libnm/nm-device-team.c +++ b/libnm/nm-device-team.c @@ -23,10 +23,10 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( ); typedef struct { + NMLDBusPropertyAO slaves; char *hw_address; - gboolean carrier; - GPtrArray *slaves; char *config; + bool carrier; } NMDeviceTeamPrivate; struct _NMDeviceTeam { @@ -92,7 +92,7 @@ nm_device_team_get_slaves (NMDeviceTeam *device) { g_return_val_if_fail (NM_IS_DEVICE_TEAM (device), FALSE); - return NM_DEVICE_TEAM_GET_PRIVATE (device)->slaves; + return nml_dbus_property_ao_get_objs_as_ptrarray (&NM_DEVICE_TEAM_GET_PRIVATE (device)->slaves); } /** @@ -148,38 +148,6 @@ get_setting_type (NMDevice *device) static void nm_device_team_init (NMDeviceTeam *device) { - NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE (device); - - priv->slaves = g_ptr_array_new (); -} - -static void -init_dbus (NMObject *object) -{ - NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE (object); - const NMPropertiesInfo property_info[] = { - { NM_DEVICE_TEAM_HW_ADDRESS, &priv->hw_address }, - { NM_DEVICE_TEAM_CARRIER, &priv->carrier }, - { NM_DEVICE_TEAM_SLAVES, &priv->slaves, NULL, NM_TYPE_DEVICE }, - { NM_DEVICE_TEAM_CONFIG, &priv->config }, - { NULL }, - }; - - NM_OBJECT_CLASS (nm_device_team_parent_class)->init_dbus (object); - - _nm_object_register_properties (object, - NM_DBUS_INTERFACE_DEVICE_TEAM, - property_info); -} - -static void -dispose (GObject *object) -{ - NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE (object); - - g_clear_pointer (&priv->slaves, g_ptr_array_unref); - - G_OBJECT_CLASS (nm_device_team_parent_class)->dispose (object); } static void @@ -220,18 +188,31 @@ get_property (GObject *object, } } +const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_team = NML_DBUS_META_IFACE_INIT_PROP ( + NM_DBUS_INTERFACE_DEVICE_TEAM, + nm_device_team_get_type, + NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, + NML_DBUS_META_IFACE_DBUS_PROPERTIES ( + NML_DBUS_META_PROPERTY_INIT_B ("Carrier", PROP_CARRIER, NMDeviceTeam, _priv.carrier ), + NML_DBUS_META_PROPERTY_INIT_S ("Config", PROP_CONFIG, NMDeviceTeam, _priv.config ), + NML_DBUS_META_PROPERTY_INIT_S ("HwAddress", PROP_HW_ADDRESS, NMDeviceTeam, _priv.hw_address ), + NML_DBUS_META_PROPERTY_INIT_AO_PROP ("Slaves", PROP_SLAVES, NMDeviceTeam, _priv.slaves, nm_device_get_type ), + ), +); + static void -nm_device_team_class_init (NMDeviceTeamClass *team_class) +nm_device_team_class_init (NMDeviceTeamClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (team_class); - NMObjectClass *nm_object_class = NM_OBJECT_CLASS (team_class); - NMDeviceClass *device_class = NM_DEVICE_CLASS (team_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMObjectClass *nm_object_class = NM_OBJECT_CLASS (klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); object_class->get_property = get_property; - object_class->dispose = dispose; object_class->finalize = finalize; - nm_object_class->init_dbus = init_dbus; + _NM_OBJECT_CLASS_INIT_PRIV_PTR_DIRECT (nm_object_class, NMDeviceTeam); + + _NM_OBJECT_CLASS_INIT_PROPERTY_AO_FIELDS_1 (nm_object_class, NMDeviceTeamPrivate, slaves); device_class->connection_compatible = connection_compatible; device_class->get_setting_type = get_setting_type; @@ -283,5 +264,5 @@ nm_device_team_class_init (NMDeviceTeamClass *team_class) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + _nml_dbus_meta_class_init_with_properties (object_class, &_nml_dbus_meta_iface_nm_device_team); } diff --git a/libnm/nm-device-tun.c b/libnm/nm-device-tun.c index 220c9a2980..cc84774bca 100644 --- a/libnm/nm-device-tun.c +++ b/libnm/nm-device-tun.c @@ -31,9 +31,9 @@ typedef struct { char *mode; gint64 owner; gint64 group; - gboolean no_pi; - gboolean vnet_hdr; - gboolean multi_queue; + bool no_pi; + bool vnet_hdr; + bool multi_queue; } NMDeviceTunPrivate; struct _NMDeviceTun { @@ -235,28 +235,6 @@ nm_device_tun_init (NMDeviceTun *device) } static void -init_dbus (NMObject *object) -{ - NMDeviceTunPrivate *priv = NM_DEVICE_TUN_GET_PRIVATE (object); - const NMPropertiesInfo property_info[] = { - { NM_DEVICE_TUN_HW_ADDRESS, &priv->hw_address }, - { NM_DEVICE_TUN_MODE, &priv->mode }, - { NM_DEVICE_TUN_OWNER, &priv->owner }, - { NM_DEVICE_TUN_GROUP, &priv->group }, - { NM_DEVICE_TUN_NO_PI, &priv->no_pi }, - { NM_DEVICE_TUN_VNET_HDR, &priv->vnet_hdr }, - { NM_DEVICE_TUN_MULTI_QUEUE, &priv->multi_queue }, - { NULL }, - }; - - NM_OBJECT_CLASS (nm_device_tun_parent_class)->init_dbus (object); - - _nm_object_register_properties (object, - NM_DBUS_INTERFACE_DEVICE_TUN, - property_info); -} - -static void finalize (GObject *object) { NMDeviceTunPrivate *priv = NM_DEVICE_TUN_GET_PRIVATE (object); @@ -304,18 +282,30 @@ get_property (GObject *object, } } +const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_tun = NML_DBUS_META_IFACE_INIT_PROP ( + NM_DBUS_INTERFACE_DEVICE_TUN, + nm_device_tun_get_type, + NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, + NML_DBUS_META_IFACE_DBUS_PROPERTIES ( + NML_DBUS_META_PROPERTY_INIT_X ("Group", PROP_GROUP, NMDeviceTun, _priv.group ), + NML_DBUS_META_PROPERTY_INIT_S ("HwAddress", PROP_HW_ADDRESS, NMDeviceTun, _priv.hw_address ), + NML_DBUS_META_PROPERTY_INIT_S ("Mode", PROP_MODE, NMDeviceTun, _priv.mode ), + NML_DBUS_META_PROPERTY_INIT_B ("MultiQueue", PROP_MULTI_QUEUE, NMDeviceTun, _priv.multi_queue ), + NML_DBUS_META_PROPERTY_INIT_B ("NoPi", PROP_NO_PI, NMDeviceTun, _priv.no_pi ), + NML_DBUS_META_PROPERTY_INIT_X ("Owner", PROP_OWNER, NMDeviceTun, _priv.owner ), + NML_DBUS_META_PROPERTY_INIT_B ("VnetHdr", PROP_VNET_HDR, NMDeviceTun, _priv.vnet_hdr ), + ), +); + static void nm_device_tun_class_init (NMDeviceTunClass *gre_class) { GObjectClass *object_class = G_OBJECT_CLASS (gre_class); - NMObjectClass *nm_object_class = NM_OBJECT_CLASS (gre_class); NMDeviceClass *device_class = NM_DEVICE_CLASS (gre_class); object_class->get_property = get_property; object_class->finalize = finalize; - nm_object_class->init_dbus = init_dbus; - device_class->connection_compatible = connection_compatible; device_class->get_setting_type = get_setting_type; device_class->get_hw_address = get_hw_address; @@ -415,5 +405,5 @@ nm_device_tun_class_init (NMDeviceTunClass *gre_class) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + _nml_dbus_meta_class_init_with_properties (object_class, &_nml_dbus_meta_iface_nm_device_tun); } diff --git a/libnm/nm-device-vlan.c b/libnm/nm-device-vlan.c index ebe9f00cbe..ee57d0f43f 100644 --- a/libnm/nm-device-vlan.c +++ b/libnm/nm-device-vlan.c @@ -23,10 +23,10 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( ); typedef struct { + NMLDBusPropertyO parent; char *hw_address; - gboolean carrier; - NMDevice *parent; - guint vlan_id; + guint32 vlan_id; + bool carrier; } NMDeviceVlanPrivate; struct _NMDeviceVlan { @@ -88,7 +88,7 @@ nm_device_vlan_get_parent (NMDeviceVlan *device) { g_return_val_if_fail (NM_IS_DEVICE_VLAN (device), FALSE); - return NM_DEVICE_VLAN_GET_PRIVATE (device)->parent; + return nml_dbus_property_o_get_obj (&NM_DEVICE_VLAN_GET_PRIVATE (device)->parent); } /** @@ -167,31 +167,11 @@ nm_device_vlan_init (NMDeviceVlan *device) } static void -init_dbus (NMObject *object) -{ - NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (object); - const NMPropertiesInfo property_info[] = { - { NM_DEVICE_VLAN_HW_ADDRESS, &priv->hw_address }, - { NM_DEVICE_VLAN_CARRIER, &priv->carrier }, - { NM_DEVICE_VLAN_PARENT, &priv->parent, NULL, NM_TYPE_DEVICE }, - { NM_DEVICE_VLAN_VLAN_ID, &priv->vlan_id }, - { NULL }, - }; - - NM_OBJECT_CLASS (nm_device_vlan_parent_class)->init_dbus (object); - - _nm_object_register_properties (object, - NM_DBUS_INTERFACE_DEVICE_VLAN, - property_info); -} - -static void finalize (GObject *object) { NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (object); g_free (priv->hw_address); - g_clear_object (&priv->parent); G_OBJECT_CLASS (nm_device_vlan_parent_class)->finalize (object); } @@ -223,17 +203,31 @@ get_property (GObject *object, } } +const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_vlan = NML_DBUS_META_IFACE_INIT_PROP ( + NM_DBUS_INTERFACE_DEVICE_VLAN, + nm_device_vlan_get_type, + NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, + NML_DBUS_META_IFACE_DBUS_PROPERTIES ( + NML_DBUS_META_PROPERTY_INIT_B ("Carrier", PROP_CARRIER, NMDeviceVlan, _priv.carrier ), + NML_DBUS_META_PROPERTY_INIT_S ("HwAddress", PROP_HW_ADDRESS, NMDeviceVlan, _priv.hw_address ), + NML_DBUS_META_PROPERTY_INIT_O_PROP ("Parent", PROP_PARENT, NMDeviceVlan, _priv.parent, nm_device_get_type ), + NML_DBUS_META_PROPERTY_INIT_U ("VlanId", PROP_VLAN_ID, NMDeviceVlan, _priv.vlan_id ), + ), +); + static void -nm_device_vlan_class_init (NMDeviceVlanClass *vlan_class) +nm_device_vlan_class_init (NMDeviceVlanClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (vlan_class); - NMObjectClass *nm_object_class = NM_OBJECT_CLASS (vlan_class); - NMDeviceClass *device_class = NM_DEVICE_CLASS (vlan_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMObjectClass *nm_object_class = NM_OBJECT_CLASS (klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); object_class->get_property = get_property; object_class->finalize = finalize; - nm_object_class->init_dbus = init_dbus; + _NM_OBJECT_CLASS_INIT_PRIV_PTR_DIRECT (nm_object_class, NMDeviceVlan); + + _NM_OBJECT_CLASS_INIT_PROPERTY_O_FIELDS_1 (nm_object_class, NMDeviceVlanPrivate, parent); device_class->connection_compatible = connection_compatible; device_class->get_setting_type = get_setting_type; @@ -283,5 +277,5 @@ nm_device_vlan_class_init (NMDeviceVlanClass *vlan_class) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + _nml_dbus_meta_class_init_with_properties (object_class, &_nml_dbus_meta_iface_nm_device_vlan); } diff --git a/libnm/nm-device-vxlan.c b/libnm/nm-device-vxlan.c index 27d7db1d7e..4397977c3f 100644 --- a/libnm/nm-device-vxlan.c +++ b/libnm/nm-device-vxlan.c @@ -36,23 +36,23 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( ); typedef struct { - NMDevice *parent; + NMLDBusPropertyO parent; char *hw_address; - guint id; char *group; char *local; - guint src_port_min; - guint src_port_max; - guint dst_port; - guint tos; - guint ttl; - guint limit; - gboolean learning; - guint ageing; - gboolean proxy; - gboolean rsc; - gboolean l2miss; - gboolean l3miss; + guint32 id; + guint32 limit; + guint32 ageing; + guint16 src_port_min; + guint16 src_port_max; + guint16 dst_port; + guint8 tos; + guint8 ttl; + bool learning; + bool proxy; + bool rsc; + bool l2miss; + bool l3miss; } NMDeviceVxlanPrivate; struct _NMDeviceVxlan { @@ -123,7 +123,7 @@ nm_device_vxlan_get_parent (NMDeviceVxlan *device) { g_return_val_if_fail (NM_IS_DEVICE_VXLAN (device), NULL); - return NM_DEVICE_VXLAN_GET_PRIVATE (device)->parent; + return nml_dbus_property_o_get_obj (&NM_DEVICE_VXLAN_GET_PRIVATE (device)->parent); } /** @@ -412,44 +412,11 @@ nm_device_vxlan_init (NMDeviceVxlan *device) } static void -init_dbus (NMObject *object) -{ - NMDeviceVxlanPrivate *priv = NM_DEVICE_VXLAN_GET_PRIVATE (object); - const NMPropertiesInfo property_info[] = { - { NM_DEVICE_VXLAN_HW_ADDRESS, &priv->hw_address }, - { NM_DEVICE_VXLAN_PARENT, &priv->parent, NULL, NM_TYPE_DEVICE }, - { NM_DEVICE_VXLAN_ID, &priv->id }, - { NM_DEVICE_VXLAN_GROUP, &priv->group }, - { NM_DEVICE_VXLAN_LOCAL, &priv->local }, - { NM_DEVICE_VXLAN_SRC_PORT_MIN, &priv->src_port_min }, - { NM_DEVICE_VXLAN_SRC_PORT_MAX, &priv->src_port_max }, - { NM_DEVICE_VXLAN_DST_PORT, &priv->dst_port }, - { NM_DEVICE_VXLAN_TOS, &priv->tos }, - { NM_DEVICE_VXLAN_TTL, &priv->ttl }, - { NM_DEVICE_VXLAN_LIMIT, &priv->limit }, - { NM_DEVICE_VXLAN_LEARNING, &priv->learning }, - { NM_DEVICE_VXLAN_AGEING, &priv->ageing }, - { NM_DEVICE_VXLAN_PROXY, &priv->proxy }, - { NM_DEVICE_VXLAN_RSC, &priv->rsc }, - { NM_DEVICE_VXLAN_L2MISS, &priv->l2miss }, - { NM_DEVICE_VXLAN_L3MISS, &priv->l3miss }, - { NULL }, - }; - - NM_OBJECT_CLASS (nm_device_vxlan_parent_class)->init_dbus (object); - - _nm_object_register_properties (object, - NM_DBUS_INTERFACE_DEVICE_VXLAN, - property_info); -} - -static void finalize (GObject *object) { NMDeviceVxlanPrivate *priv = NM_DEVICE_VXLAN_GET_PRIVATE (object); g_free (priv->hw_address); - g_clear_object (&priv->parent); g_free (priv->group); g_free (priv->local); @@ -525,17 +492,44 @@ get_property (GObject *object, } } +const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_vxlan = NML_DBUS_META_IFACE_INIT_PROP ( + NM_DBUS_INTERFACE_DEVICE_VXLAN, + nm_device_vxlan_get_type, + NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, + NML_DBUS_META_IFACE_DBUS_PROPERTIES ( + NML_DBUS_META_PROPERTY_INIT_U ("Ageing", PROP_AGEING, NMDeviceVxlan, _priv.ageing ), + NML_DBUS_META_PROPERTY_INIT_Q ("DstPort", PROP_DST_PORT, NMDeviceVxlan, _priv.dst_port ), + NML_DBUS_META_PROPERTY_INIT_S ("Group", PROP_GROUP, NMDeviceVxlan, _priv.group ), + NML_DBUS_META_PROPERTY_INIT_S ("HwAddress", PROP_HW_ADDRESS, NMDeviceVxlan, _priv.hw_address ), + NML_DBUS_META_PROPERTY_INIT_U ("Id", PROP_ID, NMDeviceVxlan, _priv.id ), + NML_DBUS_META_PROPERTY_INIT_B ("L2miss", PROP_L2MISS, NMDeviceVxlan, _priv.l2miss ), + NML_DBUS_META_PROPERTY_INIT_B ("L3miss", PROP_L3MISS, NMDeviceVxlan, _priv.l3miss ), + NML_DBUS_META_PROPERTY_INIT_B ("Learning", PROP_LEARNING, NMDeviceVxlan, _priv.learning ), + NML_DBUS_META_PROPERTY_INIT_U ("Limit", PROP_LIMIT, NMDeviceVxlan, _priv.limit ), + NML_DBUS_META_PROPERTY_INIT_S ("Local", PROP_LOCAL, NMDeviceVxlan, _priv.local ), + NML_DBUS_META_PROPERTY_INIT_O_PROP ("Parent", PROP_PARENT, NMDeviceVxlan, _priv.parent, nm_device_get_type ), + NML_DBUS_META_PROPERTY_INIT_B ("Proxy", PROP_PROXY, NMDeviceVxlan, _priv.proxy ), + NML_DBUS_META_PROPERTY_INIT_B ("Rsc", PROP_RSC, NMDeviceVxlan, _priv.rsc ), + NML_DBUS_META_PROPERTY_INIT_Q ("SrcPortMax", PROP_SRC_PORT_MAX, NMDeviceVxlan, _priv.src_port_max ), + NML_DBUS_META_PROPERTY_INIT_Q ("SrcPortMin", PROP_SRC_PORT_MIN, NMDeviceVxlan, _priv.src_port_min ), + NML_DBUS_META_PROPERTY_INIT_Y ("Tos", PROP_TOS, NMDeviceVxlan, _priv.tos ), + NML_DBUS_META_PROPERTY_INIT_Y ("Ttl", PROP_TTL, NMDeviceVxlan, _priv.ttl ), + ), +); + static void -nm_device_vxlan_class_init (NMDeviceVxlanClass *vxlan_class) +nm_device_vxlan_class_init (NMDeviceVxlanClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (vxlan_class); - NMObjectClass *nm_object_class = NM_OBJECT_CLASS (vxlan_class); - NMDeviceClass *device_class = NM_DEVICE_CLASS (vxlan_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMObjectClass *nm_object_class = NM_OBJECT_CLASS (klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); object_class->get_property = get_property; object_class->finalize = finalize; - nm_object_class->init_dbus = init_dbus; + _NM_OBJECT_CLASS_INIT_PRIV_PTR_DIRECT (nm_object_class, NMDeviceVxlan); + + _NM_OBJECT_CLASS_INIT_PROPERTY_O_FIELDS_1 (nm_object_class, NMDeviceVxlanPrivate, parent); device_class->connection_compatible = connection_compatible; device_class->get_setting_type = get_setting_type; @@ -783,5 +777,5 @@ nm_device_vxlan_class_init (NMDeviceVxlanClass *vxlan_class) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + _nml_dbus_meta_class_init_with_properties (object_class, &_nml_dbus_meta_iface_nm_device_vxlan); } diff --git a/libnm/nm-device-wifi-p2p.c b/libnm/nm-device-wifi-p2p.c index 92652b3841..191d30eb37 100644 --- a/libnm/nm-device-wifi-p2p.c +++ b/libnm/nm-device-wifi-p2p.c @@ -16,8 +16,6 @@ #include "nm-core-internal.h" #include "nm-dbus-helpers.h" -#include "introspection/org.freedesktop.NetworkManager.Device.WifiP2P.h" - /*****************************************************************************/ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( @@ -35,11 +33,8 @@ enum { static guint signals[LAST_SIGNAL] = { 0 }; typedef struct { - NMDBusDeviceWifiP2P *proxy; - + NMLDBusPropertyAO peers; char *hw_address; - - GPtrArray *peers; } NMDeviceWifiP2PPrivate; struct _NMDeviceWifiP2P { @@ -93,7 +88,7 @@ nm_device_wifi_p2p_get_peers (NMDeviceWifiP2P *device) { g_return_val_if_fail (NM_IS_DEVICE_WIFI_P2P (device), NULL); - return NM_DEVICE_WIFI_P2P_GET_PRIVATE (device)->peers; + return nml_dbus_property_ao_get_objs_as_ptrarray (&NM_DEVICE_WIFI_P2P_GET_PRIVATE (device)->peers); } /** @@ -164,7 +159,8 @@ nm_device_wifi_p2p_start_find (NMDeviceWifiP2P *device, if (!options) options = g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0); - _nm_object_dbus_call (device, + _nm_client_dbus_call (_nm_object_get_client (device), + device, nm_device_wifi_p2p_start_find, cancellable, callback, @@ -222,7 +218,8 @@ nm_device_wifi_p2p_stop_find (NMDeviceWifiP2P *device, g_return_if_fail (NM_IS_DEVICE_WIFI_P2P (device)); g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable)); - _nm_object_dbus_call (device, + _nm_client_dbus_call (_nm_object_get_client (device), + device, nm_device_wifi_p2p_stop_find, cancellable, callback, @@ -260,21 +257,6 @@ nm_device_wifi_p2p_stop_find_finish (NMDeviceWifiP2P *device, return g_task_propagate_boolean (G_TASK (result), error); } -static void -clean_up_peers (NMDeviceWifiP2P *self) -{ - NMDeviceWifiP2PPrivate *priv = NM_DEVICE_WIFI_P2P_GET_PRIVATE (self); - - while (priv->peers->len > 0) { - NMWifiP2PPeer *peer; - - peer = priv->peers->pdata[priv->peers->len - 1]; - g_ptr_array_remove_index (priv->peers, priv->peers->len - 1); - - g_signal_emit (self, signals[PEER_REMOVED], 0, peer); - } -} - static gboolean connection_compatible (NMDevice *device, NMConnection *connection, GError **error) { @@ -311,6 +293,24 @@ get_type_description (NMDevice *device) /*****************************************************************************/ static void +_property_ao_notify_changed_peers_cb (NMLDBusPropertyAO *pr_ao, + NMClient *client, + NMObject *nmobj, + gboolean is_added /* or else removed */) +{ + _nm_client_notify_event_queue_emit_obj_signal (client, + G_OBJECT (pr_ao->owner_dbobj->nmobj), + nmobj, + is_added, + 10, + is_added + ? signals[PEER_ADDED] + : signals[PEER_REMOVED]); +} + +/*****************************************************************************/ + +static void get_property (GObject *object, guint prop_id, GValue *value, @@ -331,38 +331,11 @@ get_property (GObject *object, } } -static void -nm_device_wifi_p2p_init (NMDeviceWifiP2P *device) -{ - NMDeviceWifiP2PPrivate *priv = NM_DEVICE_WIFI_P2P_GET_PRIVATE (device); - - priv->peers = g_ptr_array_new (); -} - -static void -init_dbus (NMObject *object) -{ - NMDeviceWifiP2PPrivate *priv = NM_DEVICE_WIFI_P2P_GET_PRIVATE (object); - const NMPropertiesInfo property_info[] = { - { NM_DEVICE_WIFI_P2P_HW_ADDRESS, &priv->hw_address }, - { NM_DEVICE_WIFI_P2P_PEERS, &priv->peers, NULL, NM_TYPE_WIFI_P2P_PEER, "peer" }, - { NULL }, - }; - - NM_OBJECT_CLASS (nm_device_wifi_p2p_parent_class)->init_dbus (object); - - priv->proxy = NMDBUS_DEVICE_WIFI_P2P (_nm_object_get_proxy (object, NM_DBUS_INTERFACE_DEVICE_WIFI_P2P)); - _nm_object_register_properties (object, - NM_DBUS_INTERFACE_DEVICE_WIFI_P2P, - property_info); -} +/*****************************************************************************/ static void -dispose (GObject *object) +nm_device_wifi_p2p_init (NMDeviceWifiP2P *device) { - clean_up_peers (NM_DEVICE_WIFI_P2P (object)); - - G_OBJECT_CLASS (nm_device_wifi_p2p_parent_class)->dispose (object); } static void @@ -370,32 +343,40 @@ finalize (GObject *object) { NMDeviceWifiP2PPrivate *priv = NM_DEVICE_WIFI_P2P_GET_PRIVATE (object); - g_clear_object (&priv->proxy); g_free (priv->hw_address); - if (priv->peers) - g_ptr_array_unref (priv->peers); G_OBJECT_CLASS (nm_device_wifi_p2p_parent_class)->finalize (object); } +const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_wifip2p = NML_DBUS_META_IFACE_INIT_PROP ( + NM_DBUS_INTERFACE_DEVICE_WIFI_P2P, + nm_device_wifi_p2p_get_type, + NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, + NML_DBUS_META_IFACE_DBUS_PROPERTIES ( + NML_DBUS_META_PROPERTY_INIT_S ("HwAddress", PROP_HW_ADDRESS, NMDeviceWifiP2P, _priv.hw_address ), + NML_DBUS_META_PROPERTY_INIT_AO_PROP ("Peers", PROP_PEERS, NMDeviceWifiP2P, _priv.peers, nm_wifi_p2p_peer_get_type, .notify_changed_ao = _property_ao_notify_changed_peers_cb ), + ), +); + static void -nm_device_wifi_p2p_class_init (NMDeviceWifiP2PClass *wifi_class) +nm_device_wifi_p2p_class_init (NMDeviceWifiP2PClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (wifi_class); - NMObjectClass *nm_object_class = NM_OBJECT_CLASS (wifi_class); - NMDeviceClass *device_class = NM_DEVICE_CLASS (wifi_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMObjectClass *nm_object_class = NM_OBJECT_CLASS (klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); object_class->get_property = get_property; - object_class->dispose = dispose; object_class->finalize = finalize; + _NM_OBJECT_CLASS_INIT_PRIV_PTR_DIRECT (nm_object_class, NMDeviceWifiP2P); + + _NM_OBJECT_CLASS_INIT_PROPERTY_AO_FIELDS_1 (nm_object_class, NMDeviceWifiP2PPrivate, peers); + device_class->connection_compatible = connection_compatible; device_class->get_setting_type = get_setting_type; device_class->get_hw_address = get_hw_address; device_class->get_type_description = get_type_description; - nm_object_class->init_dbus = init_dbus; - /** * NMDeviceWifiP2P:hw-address: * @@ -422,7 +403,7 @@ nm_device_wifi_p2p_class_init (NMDeviceWifiP2PClass *wifi_class) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + _nml_dbus_meta_class_init_with_properties (object_class, &_nml_dbus_meta_iface_nm_device_wifip2p); /** * NMDeviceWifiP2P::peer-added: diff --git a/libnm/nm-device-wifi.c b/libnm/nm-device-wifi.c index 36b26561c2..5d8f742c5b 100644 --- a/libnm/nm-device-wifi.c +++ b/libnm/nm-device-wifi.c @@ -18,8 +18,6 @@ #include "nm-core-internal.h" #include "nm-dbus-helpers.h" -#include "introspection/org.freedesktop.NetworkManager.Device.Wireless.h" - /*****************************************************************************/ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( @@ -27,23 +25,21 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( PROP_PERM_HW_ADDRESS, PROP_MODE, PROP_BITRATE, + PROP_ACCESS_POINTS, PROP_ACTIVE_ACCESS_POINT, PROP_WIRELESS_CAPABILITIES, - PROP_ACCESS_POINTS, PROP_LAST_SCAN, ); typedef struct { - NMDBusDeviceWifi *proxy; - + NMLDBusPropertyAO access_points; + NMLDBusPropertyO active_access_point; char *hw_address; char *perm_hw_address; - NM80211Mode mode; - guint32 rate; - NMAccessPoint *active_ap; - NMDeviceWifiCapabilities wireless_caps; - GPtrArray *aps; gint64 last_scan; + guint32 mode; + guint32 bitrate; + guint32 wireless_capabilities; } NMDeviceWifiPrivate; enum { @@ -55,7 +51,6 @@ enum { static guint signals[LAST_SIGNAL] = { 0 }; - struct _NMDeviceWifi { NMDevice parent; NMDeviceWifiPrivate _priv; @@ -63,8 +58,6 @@ struct _NMDeviceWifi { struct _NMDeviceWifiClass { NMDeviceClass parent; - - void (*access_point_removed) (NMDeviceWifi *device, NMAccessPoint *ap); }; G_DEFINE_TYPE (NMDeviceWifi, nm_device_wifi, NM_TYPE_DEVICE) @@ -73,11 +66,6 @@ G_DEFINE_TYPE (NMDeviceWifi, nm_device_wifi, NM_TYPE_DEVICE) /*****************************************************************************/ -void _nm_device_wifi_set_wireless_enabled (NMDeviceWifi *device, gboolean enabled); -static void state_changed_cb (NMDevice *device, GParamSpec *pspec, gpointer user_data); - -/*****************************************************************************/ - /** * nm_device_wifi_get_hw_address: * @device: a #NMDeviceWifi @@ -155,7 +143,7 @@ nm_device_wifi_get_bitrate (NMDeviceWifi *device) return 0; } - return NM_DEVICE_WIFI_GET_PRIVATE (device)->rate; + return NM_DEVICE_WIFI_GET_PRIVATE (device)->bitrate; } /** @@ -171,7 +159,7 @@ nm_device_wifi_get_capabilities (NMDeviceWifi *device) { g_return_val_if_fail (NM_IS_DEVICE_WIFI (device), 0); - return NM_DEVICE_WIFI_GET_PRIVATE (device)->wireless_caps; + return NM_DEVICE_WIFI_GET_PRIVATE (device)->wireless_capabilities; } /** @@ -185,27 +173,9 @@ nm_device_wifi_get_capabilities (NMDeviceWifi *device) NMAccessPoint * nm_device_wifi_get_active_access_point (NMDeviceWifi *device) { - NMDeviceState state; - g_return_val_if_fail (NM_IS_DEVICE_WIFI (device), NULL); - state = nm_device_get_state (NM_DEVICE (device)); - switch (state) { - case NM_DEVICE_STATE_PREPARE: - case NM_DEVICE_STATE_CONFIG: - case NM_DEVICE_STATE_NEED_AUTH: - case NM_DEVICE_STATE_IP_CONFIG: - case NM_DEVICE_STATE_IP_CHECK: - case NM_DEVICE_STATE_SECONDARIES: - case NM_DEVICE_STATE_ACTIVATED: - case NM_DEVICE_STATE_DEACTIVATING: - break; - default: - return NULL; - break; - } - - return NM_DEVICE_WIFI_GET_PRIVATE (device)->active_ap; + return nml_dbus_property_o_get_obj (&NM_DEVICE_WIFI_GET_PRIVATE (device)->active_access_point); } /** @@ -223,7 +193,7 @@ nm_device_wifi_get_access_points (NMDeviceWifi *device) { g_return_val_if_fail (NM_IS_DEVICE_WIFI (device), NULL); - return NM_DEVICE_WIFI_GET_PRIVATE (device)->aps; + return nml_dbus_property_ao_get_objs_as_ptrarray (&NM_DEVICE_WIFI_GET_PRIVATE (device)->access_points); } /** @@ -342,9 +312,9 @@ nm_device_wifi_request_scan_options (NMDeviceWifi *device, if (!options) options = g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0); - return _nm_object_dbus_call_sync_void (device, + return _nm_client_dbus_call_sync_void (_nm_object_get_client (device), cancellable, - g_dbus_proxy_get_object_path (G_DBUS_PROXY (NM_DEVICE_WIFI_GET_PRIVATE (device)->proxy)), + _nm_object_get_path (device), NM_DBUS_INTERFACE_DEVICE_WIRELESS, "RequestScan", g_variant_new ("(@a{sv})", options), @@ -412,12 +382,13 @@ nm_device_wifi_request_scan_options_async (NMDeviceWifi *device, if (!options) options = g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0); - _nm_object_dbus_call (device, + _nm_client_dbus_call (_nm_object_get_client (device), + device, nm_device_wifi_request_scan_async, cancellable, callback, user_data, - g_dbus_proxy_get_object_path (G_DBUS_PROXY (NM_DEVICE_WIFI_GET_PRIVATE (device)->proxy)), + _nm_object_get_path (device), NM_DBUS_INTERFACE_DEVICE_WIRELESS, "RequestScan", g_variant_new ("(@a{sv})", options), @@ -454,53 +425,6 @@ nm_device_wifi_request_scan_finish (NMDeviceWifi *device, return g_task_propagate_boolean (G_TASK (result), error); } -static void -clean_up_aps (NMDeviceWifi *self, gboolean in_dispose) -{ - NMDeviceWifiPrivate *priv; - GPtrArray *aps; - int i; - - g_return_if_fail (NM_IS_DEVICE_WIFI (self)); - - priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - - g_clear_object (&priv->active_ap); - - aps = priv->aps; - - if (in_dispose) - priv->aps = NULL; - else { - priv->aps = g_ptr_array_new (); - - for (i = 0; i < aps->len; i++) { - NMAccessPoint *ap = NM_ACCESS_POINT (g_ptr_array_index (aps, i)); - - g_signal_emit (self, signals[ACCESS_POINT_REMOVED], 0, ap); - } - } - - g_ptr_array_unref (aps); -} - -/** - * _nm_device_wifi_set_wireless_enabled: - * @device: a #NMDeviceWifi - * @enabled: %TRUE to enable the device - * - * Enables or disables the wireless device. - **/ -void -_nm_device_wifi_set_wireless_enabled (NMDeviceWifi *device, - gboolean enabled) -{ - g_return_if_fail (NM_IS_DEVICE_WIFI (device)); - - if (!enabled) - clean_up_aps (device, FALSE); -} - #define WPA_CAPS (NM_WIFI_DEVICE_CAP_CIPHER_TKIP | \ NM_WIFI_DEVICE_CAP_CIPHER_CCMP | \ NM_WIFI_DEVICE_CAP_WPA | \ @@ -600,16 +524,28 @@ get_hw_address (NMDevice *device) /*****************************************************************************/ static void +_property_ao_notify_changed_access_points_cb (NMLDBusPropertyAO *pr_ao, + NMClient *client, + NMObject *nmobj, + gboolean is_added /* or else removed */) +{ + _nm_client_notify_event_queue_emit_obj_signal (client, + G_OBJECT (pr_ao->owner_dbobj->nmobj), + nmobj, + is_added, + 10, + is_added + ? signals[ACCESS_POINT_ADDED] + : signals[ACCESS_POINT_REMOVED]); +} + +/*****************************************************************************/ + +static void nm_device_wifi_init (NMDeviceWifi *device) { NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (device); - g_signal_connect (device, - "notify::" NM_DEVICE_STATE, - G_CALLBACK (state_changed_cb), - NULL); - - priv->aps = g_ptr_array_new (); priv->last_scan = -1; } @@ -653,80 +589,6 @@ get_property (GObject *object, } static void -state_changed_cb (NMDevice *device, GParamSpec *pspec, gpointer user_data) -{ - NMDeviceWifi *self = NM_DEVICE_WIFI (device); - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - - switch (nm_device_get_state (device)) { - case NM_DEVICE_STATE_UNKNOWN: - case NM_DEVICE_STATE_UNMANAGED: - case NM_DEVICE_STATE_UNAVAILABLE: - case NM_DEVICE_STATE_DISCONNECTED: - case NM_DEVICE_STATE_FAILED: - /* Just clear active AP; don't clear the AP list unless wireless is disabled completely */ - g_clear_object (&priv->active_ap); - _nm_object_queue_notify (NM_OBJECT (device), NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT); - priv->rate = 0; - _nm_object_queue_notify (NM_OBJECT (device), NM_DEVICE_WIFI_BITRATE); - break; - default: - break; - } -} - -static void -init_dbus (NMObject *object) -{ - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (object); - const NMPropertiesInfo property_info[] = { - { NM_DEVICE_WIFI_HW_ADDRESS, &priv->hw_address }, - { NM_DEVICE_WIFI_PERMANENT_HW_ADDRESS, &priv->perm_hw_address }, - { NM_DEVICE_WIFI_MODE, &priv->mode }, - { NM_DEVICE_WIFI_BITRATE, &priv->rate }, - { NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT, &priv->active_ap, NULL, NM_TYPE_ACCESS_POINT }, - { NM_DEVICE_WIFI_CAPABILITIES, &priv->wireless_caps }, - { NM_DEVICE_WIFI_ACCESS_POINTS, &priv->aps, NULL, NM_TYPE_ACCESS_POINT, "access-point" }, - { NM_DEVICE_WIFI_LAST_SCAN, &priv->last_scan }, - { NULL }, - }; - - NM_OBJECT_CLASS (nm_device_wifi_parent_class)->init_dbus (object); - - priv->proxy = NMDBUS_DEVICE_WIFI (_nm_object_get_proxy (object, NM_DBUS_INTERFACE_DEVICE_WIRELESS)); - _nm_object_register_properties (object, - NM_DBUS_INTERFACE_DEVICE_WIRELESS, - property_info); -} - -static void -access_point_removed (NMDeviceWifi *self, NMAccessPoint *ap) -{ - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - - if (ap == priv->active_ap) { - g_clear_object (&priv->active_ap); - _nm_object_queue_notify (NM_OBJECT (self), NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT); - - priv->rate = 0; - _nm_object_queue_notify (NM_OBJECT (self), NM_DEVICE_WIFI_BITRATE); - } -} - -static void -dispose (GObject *object) -{ - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (object); - - if (priv->aps) - clean_up_aps (NM_DEVICE_WIFI (object), TRUE); - - g_clear_object (&priv->proxy); - - G_OBJECT_CLASS (nm_device_wifi_parent_class)->dispose (object); -} - -static void finalize (GObject *object) { NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (object); @@ -737,25 +599,41 @@ finalize (GObject *object) G_OBJECT_CLASS (nm_device_wifi_parent_class)->finalize (object); } +const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_wireless = NML_DBUS_META_IFACE_INIT_PROP ( + NM_DBUS_INTERFACE_DEVICE_WIRELESS, + nm_device_wifi_get_type, + NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, + NML_DBUS_META_IFACE_DBUS_PROPERTIES ( + NML_DBUS_META_PROPERTY_INIT_AO_PROP ("AccessPoints", PROP_ACCESS_POINTS, NMDeviceWifi, _priv.access_points, nm_access_point_get_type, .notify_changed_ao = _property_ao_notify_changed_access_points_cb ), + NML_DBUS_META_PROPERTY_INIT_O_PROP ("ActiveAccessPoint", PROP_ACTIVE_ACCESS_POINT, NMDeviceWifi, _priv.active_access_point, nm_access_point_get_type ), + NML_DBUS_META_PROPERTY_INIT_U ("Bitrate", PROP_BITRATE, NMDeviceWifi, _priv.bitrate ), + NML_DBUS_META_PROPERTY_INIT_S ("HwAddress", PROP_HW_ADDRESS, NMDeviceWifi, _priv.hw_address ), + NML_DBUS_META_PROPERTY_INIT_X ("LastScan", PROP_LAST_SCAN, NMDeviceWifi, _priv.last_scan ), + NML_DBUS_META_PROPERTY_INIT_U ("Mode", PROP_MODE, NMDeviceWifi, _priv.mode ), + NML_DBUS_META_PROPERTY_INIT_S ("PermHwAddress", PROP_PERM_HW_ADDRESS, NMDeviceWifi, _priv.perm_hw_address ), + NML_DBUS_META_PROPERTY_INIT_U ("WirelessCapabilities", PROP_WIRELESS_CAPABILITIES, NMDeviceWifi, _priv.wireless_capabilities ), + ), +); + static void -nm_device_wifi_class_init (NMDeviceWifiClass *wifi_class) +nm_device_wifi_class_init (NMDeviceWifiClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (wifi_class); - NMObjectClass *nm_object_class = NM_OBJECT_CLASS (wifi_class); - NMDeviceClass *device_class = NM_DEVICE_CLASS (wifi_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMObjectClass *nm_object_class = NM_OBJECT_CLASS (klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); object_class->get_property = get_property; - object_class->dispose = dispose; object_class->finalize = finalize; - nm_object_class->init_dbus = init_dbus; + _NM_OBJECT_CLASS_INIT_PRIV_PTR_DIRECT (nm_object_class, NMDeviceWifi); + + _NM_OBJECT_CLASS_INIT_PROPERTY_O_FIELDS_1 (nm_object_class, NMDeviceWifiPrivate, active_access_point); + _NM_OBJECT_CLASS_INIT_PROPERTY_AO_FIELDS_1 (nm_object_class, NMDeviceWifiPrivate, access_points); device_class->connection_compatible = connection_compatible; device_class->get_setting_type = get_setting_type; device_class->get_hw_address = get_hw_address; - wifi_class->access_point_removed = access_point_removed; - /** * NMDeviceWifi:hw-address: * @@ -850,7 +728,7 @@ nm_device_wifi_class_init (NMDeviceWifiClass *wifi_class) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + _nml_dbus_meta_class_init_with_properties (object_class, &_nml_dbus_meta_iface_nm_device_wireless); /** * NMDeviceWifi::access-point-added: @@ -879,8 +757,7 @@ nm_device_wifi_class_init (NMDeviceWifiClass *wifi_class) g_signal_new ("access-point-removed", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMDeviceWifiClass, access_point_removed), - NULL, NULL, + 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_OBJECT); diff --git a/libnm/nm-device-wireguard.c b/libnm/nm-device-wireguard.c index 825095eaa5..b4e2f350f4 100644 --- a/libnm/nm-device-wireguard.c +++ b/libnm/nm-device-wireguard.c @@ -19,8 +19,8 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( typedef struct { GBytes *public_key; - guint listen_port; - guint fwmark; + guint32 fwmark; + guint16 listen_port; } NMDeviceWireGuardPrivate; struct _NMDeviceWireGuard { @@ -126,24 +126,6 @@ nm_device_wireguard_init (NMDeviceWireGuard *device) } static void -init_dbus (NMObject *object) -{ - NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE (object); - const NMPropertiesInfo property_info[] = { - { NM_DEVICE_WIREGUARD_PUBLIC_KEY, &priv->public_key }, - { NM_DEVICE_WIREGUARD_LISTEN_PORT, &priv->listen_port }, - { NM_DEVICE_WIREGUARD_FWMARK, &priv->fwmark }, - { NULL } - }; - - NM_OBJECT_CLASS (nm_device_wireguard_parent_class)->init_dbus (object); - - _nm_object_register_properties (object, - NM_DBUS_INTERFACE_DEVICE_WIREGUARD, - property_info); -} - -static void finalize (GObject *object) { NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE (object); @@ -153,17 +135,25 @@ finalize (GObject *object) G_OBJECT_CLASS (nm_device_wireguard_parent_class)->finalize (object); } +const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_wireguard = NML_DBUS_META_IFACE_INIT_PROP ( + NM_DBUS_INTERFACE_DEVICE_WIREGUARD, + nm_device_wireguard_get_type, + NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, + NML_DBUS_META_IFACE_DBUS_PROPERTIES ( + NML_DBUS_META_PROPERTY_INIT_U ("FwMark", PROP_FWMARK, NMDeviceWireGuard, _priv.fwmark ), + NML_DBUS_META_PROPERTY_INIT_Q ("ListenPort", PROP_LISTEN_PORT, NMDeviceWireGuard, _priv.listen_port ), + NML_DBUS_META_PROPERTY_INIT_AY ("PublicKey", PROP_PUBLIC_KEY, NMDeviceWireGuard, _priv.public_key ), + ), +); + static void nm_device_wireguard_class_init (NMDeviceWireGuardClass *wireguard_class) { GObjectClass *object_class = G_OBJECT_CLASS (wireguard_class); - NMObjectClass *nm_object_class = NM_OBJECT_CLASS (wireguard_class); object_class->get_property = get_property; object_class->finalize = finalize; - nm_object_class->init_dbus = init_dbus; - /** * NMDeviceWireGuard:public-key: * @@ -203,5 +193,5 @@ nm_device_wireguard_class_init (NMDeviceWireGuardClass *wireguard_class) 0, G_MAXUINT32, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + _nml_dbus_meta_class_init_with_properties (object_class, &_nml_dbus_meta_iface_nm_device_wireguard); } diff --git a/libnm/nm-device-wpan.c b/libnm/nm-device-wpan.c index 3dfa8f267c..5ddd8af37b 100644 --- a/libnm/nm-device-wpan.c +++ b/libnm/nm-device-wpan.c @@ -48,9 +48,9 @@ G_DEFINE_TYPE (NMDeviceWpan, nm_device_wpan, NM_TYPE_DEVICE) const char * nm_device_wpan_get_hw_address (NMDeviceWpan *device) { - g_return_val_if_fail (NM_IS_DEVICE_WPAN (device), NULL); + g_return_val_if_fail (NM_IS_DEVICE_WPAN (device), NULL); - return _nml_coerce_property_str_not_empty (NM_DEVICE_WPAN_GET_PRIVATE (device)->hw_address); + return _nml_coerce_property_str_not_empty (NM_DEVICE_WPAN_GET_PRIVATE (device)->hw_address); } static gboolean @@ -95,49 +95,41 @@ get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) } } +/*****************************************************************************/ + static void nm_device_wpan_init (NMDeviceWpan *device) { } static void -init_dbus (NMObject *object) -{ - NMDeviceWpanPrivate *priv = NM_DEVICE_WPAN_GET_PRIVATE (object); - const NMPropertiesInfo property_info[] = { - { NM_DEVICE_WPAN_HW_ADDRESS, &priv->hw_address }, - { NULL }, - }; - - NM_OBJECT_CLASS (nm_device_wpan_parent_class)->init_dbus (object); - - _nm_object_register_properties (object, - NM_DBUS_INTERFACE_DEVICE_WPAN, - property_info); -} - -static void finalize (GObject *object) { - NMDeviceWpanPrivate *priv = NM_DEVICE_WPAN_GET_PRIVATE (object); + NMDeviceWpanPrivate *priv = NM_DEVICE_WPAN_GET_PRIVATE (object); - g_free (priv->hw_address); + g_free (priv->hw_address); - G_OBJECT_CLASS (nm_device_wpan_parent_class)->finalize (object); + G_OBJECT_CLASS (nm_device_wpan_parent_class)->finalize (object); } +const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_wpan = NML_DBUS_META_IFACE_INIT_PROP ( + NM_DBUS_INTERFACE_DEVICE_WPAN, + nm_device_wpan_get_type, + NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, + NML_DBUS_META_IFACE_DBUS_PROPERTIES ( + NML_DBUS_META_PROPERTY_INIT_S ("HwAddress", PROP_HW_ADDRESS, NMDeviceWpan, _priv.hw_address ), + ), +); + static void nm_device_wpan_class_init (NMDeviceWpanClass *wpan_class) { GObjectClass *object_class = G_OBJECT_CLASS (wpan_class); - NMObjectClass *nm_object_class = NM_OBJECT_CLASS (wpan_class); NMDeviceClass *device_class = NM_DEVICE_CLASS (wpan_class); object_class->get_property = get_property; object_class->finalize = finalize; - nm_object_class->init_dbus = init_dbus; - device_class->connection_compatible = connection_compatible; device_class->get_setting_type = get_setting_type; device_class->get_hw_address = get_hw_address; @@ -153,5 +145,5 @@ nm_device_wpan_class_init (NMDeviceWpanClass *wpan_class) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + _nml_dbus_meta_class_init_with_properties (object_class, &_nml_dbus_meta_iface_nm_device_wpan); } diff --git a/libnm/nm-device.c b/libnm/nm-device.c index 8344f2a037..1db1c17051 100644 --- a/libnm/nm-device.c +++ b/libnm/nm-device.c @@ -27,11 +27,9 @@ #include "nm-setting-connection.h" #include "nm-udev-aux/nm-udev-utils.h" -#include "introspection/org.freedesktop.NetworkManager.Device.h" - /*****************************************************************************/ -NM_GOBJECT_PROPERTIES_DEFINE_BASE ( +NM_GOBJECT_PROPERTIES_DEFINE (NMDevice, PROP_INTERFACE, PROP_UDI, PROP_DRIVER, @@ -71,45 +69,50 @@ enum { static guint signals[LAST_SIGNAL] = { 0 }; -typedef struct _NMDevicePrivate { - NMDBusDevice *proxy; +enum { + PROPERTY_O_IDX_ACTIVE_CONNECTION, + PROPERTY_O_IDX_IP4_CONFIG, + PROPERTY_O_IDX_IP6_CONFIG, + PROPERTY_O_IDX_DHCP4_CONFIG, + PROPERTY_O_IDX_DHCP6_CONFIG, + _PROPERTY_O_IDX_NUM, +}; - char *iface; - char *ip_iface; - NMDeviceType device_type; - char *udi; +typedef struct _NMDevicePrivate { + NMLDBusPropertyO property_o[_PROPERTY_O_IDX_NUM]; + NMLDBusPropertyAO available_connections; + GPtrArray *lldp_neighbors; char *driver; char *driver_version; + char *interface; + char *ip_interface; char *firmware_version; - char *type_description; - NMMetered metered; - NMDeviceCapabilities capabilities; - gboolean real; - gboolean managed; - gboolean firmware_missing; - gboolean nm_plugin_missing; - gboolean autoconnect; - NMIPConfig *ip4_config; - NMDhcpConfig *dhcp4_config; - NMIPConfig *ip6_config; - NMDhcpConfig *dhcp6_config; - NMConnectivityState ip4_connectivity; - NMConnectivityState ip6_connectivity; - NMDeviceState state; - NMDeviceState last_seen_state; - NMDeviceStateReason reason; - - NMActiveConnection *active_connection; - GPtrArray *available_connections; + char *physical_port_id; + char *udi; + guint32 capabilities; + guint32 device_type; + guint32 ip4_connectivity; + guint32 ip6_connectivity; + guint32 metered; + guint32 mtu; + guint32 state; + guint32 state_reason; + bool firmware_missing; + bool nm_plugin_missing; + bool autoconnect; + bool managed; + bool real; + + guint32 old_state; struct udev *udev; + char *type_description; char *product; - char *vendor, *short_vendor; - char *description, *bus_name; + char *vendor; + char *short_vendor; + char *description; + char *bus_name; - char *physical_port_id; - guint32 mtu; - GPtrArray *lldp_neighbors; } NMDevicePrivate; G_DEFINE_ABSTRACT_TYPE (NMDevice, nm_device, NM_TYPE_OBJECT); @@ -130,6 +133,8 @@ struct _NMLldpNeighbor { G_DEFINE_BOXED_TYPE (NMLldpNeighbor, nm_lldp_neighbor, nm_lldp_neighbor_dup, nm_lldp_neighbor_unref) +/*****************************************************************************/ + static void nm_device_init (NMDevice *self) { @@ -139,119 +144,121 @@ nm_device_init (NMDevice *self) self->_priv = priv; - priv->ip4_connectivity = NM_CONNECTIVITY_UNKNOWN; - priv->ip6_connectivity = NM_CONNECTIVITY_UNKNOWN; - priv->state = NM_DEVICE_STATE_UNKNOWN; - priv->reason = NM_DEVICE_STATE_REASON_NONE; - priv->lldp_neighbors = g_ptr_array_new (); + priv->old_state = NM_DEVICE_STATE_UNKNOWN; } -static gboolean -demarshal_state_reason (NMObject *object, GParamSpec *pspec, GVariant *value, gpointer field) -{ - guint32 *reason_field = field; - - g_variant_get (value, "(uu)", NULL, reason_field); - _nm_object_queue_notify (object, NM_DEVICE_STATE_REASON); - return TRUE; -} +/*****************************************************************************/ -static gboolean -demarshal_lldp_neighbors (NMObject *object, GParamSpec *pspec, GVariant *value, gpointer field) +static void +_notify_event_state_changed (NMClient *client, + NMClientNotifyEventWithPtr *notify_event) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (object); - GVariantIter iter, attrs_iter; - GVariant *variant, *attr_variant; - const char *attr_name; + gs_unref_object NMDevice *self = notify_event->user_data; + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - g_return_val_if_fail (g_variant_is_of_type (value, G_VARIANT_TYPE ("aa{sv}")), FALSE); + NML_NMCLIENT_LOG_T (_nm_object_get_client (self), + "[%s] emit Device's StateChanged signal %u -> %u, reason: %u", + _nm_object_get_path (self), + (guint) priv->old_state, + (guint) priv->state, + (guint) priv->state_reason); + + g_signal_emit (self, + signals[STATE_CHANGED], + 0, + (guint) priv->state, + (guint) priv->old_state, + (guint) priv->state_reason); +} + +static NMLDBusNotifyUpdatePropFlags +_notify_update_prop_state_reason (NMClient *client, + NMLDBusObject *dbobj, + const NMLDBusMetaIface *meta_iface, + guint dbus_property_idx, + GVariant *value) +{ + NMDevice *self = NM_DEVICE (dbobj->nmobj); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + guint32 new_state = NM_DEVICE_STATE_UNKNOWN; + guint32 reason = NM_DEVICE_STATE_REASON_NONE; - g_ptr_array_unref (priv->lldp_neighbors); - priv->lldp_neighbors = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_lldp_neighbor_unref); - g_variant_iter_init (&iter, value); + /* We ignore the "State" property and the "StateChanged" signal of the device. + * This information is redundant to the "StateReason" property, and we rely + * on that one alone. In the best case, the information is identical. If it + * would not be, then we stick to the information from "StateReason" property. */ - while (g_variant_iter_next (&iter, "@a{sv}", &variant)) { - NMLldpNeighbor *neigh; + if (value) + g_variant_get (value, "(uu)", &new_state, &reason); - neigh = nm_lldp_neighbor_new (); - g_variant_iter_init (&attrs_iter, variant); + if ( priv->state == new_state + && priv->state_reason == reason) { + /* no changes. */ + return NML_DBUS_NOTIFY_UPDATE_PROP_FLAGS_NONE; + } - while (g_variant_iter_next (&attrs_iter, "{&sv}", &attr_name, &attr_variant)) - g_hash_table_insert (neigh->attrs, g_strdup (attr_name), attr_variant); + if (priv->state != new_state) { + priv->old_state = priv->state; + priv->state = new_state; + _nm_client_queue_notify_object (client, + self, + obj_properties[PROP_STATE]); + } - g_variant_unref (variant); - g_ptr_array_add (priv->lldp_neighbors, neigh); + if (priv->state_reason != reason) { + priv->state_reason = reason; + _nm_client_queue_notify_object (client, + self, + obj_properties[PROP_STATE_REASON]); } - _nm_object_queue_notify (object, NM_DEVICE_LLDP_NEIGHBORS); + _nm_client_notify_event_queue_with_ptr (client, + NM_CLIENT_NOTIFY_EVENT_PRIO_GPROP + 1, + _notify_event_state_changed, + g_object_ref (self)); - return TRUE; + return NML_DBUS_NOTIFY_UPDATE_PROP_FLAGS_NONE; } -static void -device_state_reason_changed (GObject *object, GParamSpec *pspec, gpointer user_data); - -static void -init_dbus (NMObject *object) +static NMLDBusNotifyUpdatePropFlags +_notify_update_prop_lldp_neighbors (NMClient *client, + NMLDBusObject *dbobj, + const NMLDBusMetaIface *meta_iface, + guint dbus_property_idx, + GVariant *value) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (object); - const NMPropertiesInfo property_info[] = { - { NM_DEVICE_UDI, &priv->udi }, - { NM_DEVICE_INTERFACE, &priv->iface }, - { NM_DEVICE_DEVICE_TYPE, &priv->device_type }, - { NM_DEVICE_IP_INTERFACE, &priv->ip_iface }, - { NM_DEVICE_DRIVER, &priv->driver }, - { NM_DEVICE_DRIVER_VERSION, &priv->driver_version }, - { NM_DEVICE_FIRMWARE_VERSION, &priv->firmware_version }, - { NM_DEVICE_CAPABILITIES, &priv->capabilities }, - { NM_DEVICE_REAL, &priv->real }, - { NM_DEVICE_MANAGED, &priv->managed }, - { NM_DEVICE_AUTOCONNECT, &priv->autoconnect }, - { NM_DEVICE_FIRMWARE_MISSING, &priv->firmware_missing }, - { NM_DEVICE_NM_PLUGIN_MISSING, &priv->nm_plugin_missing }, - { NM_DEVICE_IP4_CONFIG, &priv->ip4_config, NULL, NM_TYPE_IP4_CONFIG }, - { NM_DEVICE_DHCP4_CONFIG, &priv->dhcp4_config, NULL, NM_TYPE_DHCP4_CONFIG }, - { NM_DEVICE_IP6_CONFIG, &priv->ip6_config, NULL, NM_TYPE_IP6_CONFIG }, - { NM_DEVICE_DHCP6_CONFIG, &priv->dhcp6_config, NULL, NM_TYPE_DHCP6_CONFIG }, - { NM_DEVICE_IP4_CONNECTIVITY, &priv->ip4_connectivity }, - { NM_DEVICE_IP6_CONNECTIVITY, &priv->ip6_connectivity }, - { NM_DEVICE_STATE, &priv->state }, - { NM_DEVICE_STATE_REASON, &priv->reason, demarshal_state_reason }, - { NM_DEVICE_ACTIVE_CONNECTION, &priv->active_connection, NULL, NM_TYPE_ACTIVE_CONNECTION }, - { NM_DEVICE_AVAILABLE_CONNECTIONS, &priv->available_connections, NULL, NM_TYPE_REMOTE_CONNECTION }, - { NM_DEVICE_PHYSICAL_PORT_ID, &priv->physical_port_id }, - { NM_DEVICE_MTU, &priv->mtu }, - { NM_DEVICE_METERED, &priv->metered }, - { NM_DEVICE_LLDP_NEIGHBORS, &priv->lldp_neighbors, demarshal_lldp_neighbors }, - - /* Properties that exist in D-Bus but that we don't track */ - { "ip4-address", NULL }, - - { NULL }, - }; - - NM_OBJECT_CLASS (nm_device_parent_class)->init_dbus (object); - - priv->proxy = NMDBUS_DEVICE (_nm_object_get_proxy (object, NM_DBUS_INTERFACE_DEVICE)); - _nm_object_register_properties (object, - NM_DBUS_INTERFACE_DEVICE, - property_info); - - g_signal_connect (priv->proxy, "notify::state-reason", - G_CALLBACK (device_state_reason_changed), object); -} - -static void -device_state_reason_changed (GObject *object, GParamSpec *pspec, gpointer user_data) -{ - NMDevice *self = NM_DEVICE (user_data); + NMDevice *self = NM_DEVICE (dbobj->nmobj); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + gs_unref_ptrarray GPtrArray *old = NULL; + gs_unref_ptrarray GPtrArray *new = NULL; + GVariantIter *attrs_iter; + GVariantIter iter; + + new = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_lldp_neighbor_unref); + + if (value) { + g_variant_iter_init (&iter, value); + while (g_variant_iter_next (&iter, "a{sv}", &attrs_iter)) { + GVariant *attr_variant; + const char *attr_name; + NMLldpNeighbor *neigh; + + neigh = nm_lldp_neighbor_new (); + while (g_variant_iter_next (attrs_iter, "{&sv}", &attr_name, &attr_variant)) + g_hash_table_insert (neigh->attrs, g_strdup (attr_name), attr_variant); + g_ptr_array_add (new, neigh); + + g_variant_iter_free (attrs_iter); + } + } - g_signal_emit (self, signals[STATE_CHANGED], 0, - priv->state, priv->last_seen_state, priv->reason); - priv->last_seen_state = priv->state; + old = g_steal_pointer (&priv->lldp_neighbors); + priv->lldp_neighbors = g_steal_pointer (&new); + return NML_DBUS_NOTIFY_UPDATE_PROP_FLAGS_NOTIFY; } +/*****************************************************************************/ + static NMDeviceType coerce_type (NMDeviceType type) { @@ -292,37 +299,33 @@ coerce_type (NMDeviceType type) return NM_DEVICE_TYPE_UNKNOWN; } +/*****************************************************************************/ + static void -dispose (GObject *object) +register_client (NMObject *nmobj, + NMClient *client, + NMLDBusObject *dbobj) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (object); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (nmobj); - g_clear_object (&priv->ip4_config); - g_clear_object (&priv->dhcp4_config); - g_clear_object (&priv->ip6_config); - g_clear_object (&priv->dhcp6_config); - g_clear_object (&priv->active_connection); + priv->udev = _nm_client_get_udev (client); + if (priv->udev) + udev_ref (priv->udev); - udev_unref (priv->udev); - priv->udev = NULL; - - g_clear_pointer (&priv->available_connections, g_ptr_array_unref); - g_clear_pointer (&priv->lldp_neighbors, g_ptr_array_unref); - - if (priv->proxy) - g_signal_handlers_disconnect_by_func (priv->proxy, device_state_reason_changed, object); - g_clear_object (&priv->proxy); - - G_OBJECT_CLASS (nm_device_parent_class)->dispose (object); + NM_OBJECT_CLASS (nm_device_parent_class)->register_client (nmobj, client, dbobj); } +/*****************************************************************************/ + static void finalize (GObject *object) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (object); - g_free (priv->iface); - g_free (priv->ip_iface); + g_clear_pointer (&priv->lldp_neighbors, g_ptr_array_unref); + + g_free (priv->interface); + g_free (priv->ip_interface); g_free (priv->udi); g_free (priv->driver); g_free (priv->driver_version); @@ -335,6 +338,8 @@ finalize (GObject *object) g_free (priv->type_description); g_free (priv->physical_port_id); + nm_clear_pointer (&priv->udev, udev_unref); + G_OBJECT_CLASS (nm_device_parent_class)->finalize (object); } @@ -462,22 +467,75 @@ set_property (GObject *object, } } +/* TODO: statistics interface not yet implemented. */ +const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_statistics = NML_DBUS_META_IFACE_INIT ( + NM_DBUS_INTERFACE_DEVICE_STATISTICS, + NULL, + NML_DBUS_META_INTERFACE_PRIO_NONE, + NML_DBUS_META_IFACE_DBUS_PROPERTIES ( + NML_DBUS_META_PROPERTY_INIT_TODO ("RefreshRateMs", "u" ), + NML_DBUS_META_PROPERTY_INIT_TODO ("RxBytes", "t" ), + NML_DBUS_META_PROPERTY_INIT_TODO ("TxBytes", "t" ), + ), +); + +const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device = NML_DBUS_META_IFACE_INIT_PROP ( + NM_DBUS_INTERFACE_DEVICE, + nm_device_get_type, + NML_DBUS_META_INTERFACE_PRIO_PARENT_TYPE, + NML_DBUS_META_IFACE_DBUS_PROPERTIES ( + NML_DBUS_META_PROPERTY_INIT_O_PROP ("ActiveConnection", PROP_ACTIVE_CONNECTION, NMDevicePrivate, property_o[PROPERTY_O_IDX_ACTIVE_CONNECTION], nm_active_connection_get_type, .ready_without_visible = TRUE ), + NML_DBUS_META_PROPERTY_INIT_B ("Autoconnect", PROP_AUTOCONNECT, NMDevicePrivate, autoconnect ), + NML_DBUS_META_PROPERTY_INIT_AO_PROP ("AvailableConnections", PROP_AVAILABLE_CONNECTIONS, NMDevicePrivate, available_connections, nm_remote_connection_get_type, .ready_without_visible = TRUE ), + NML_DBUS_META_PROPERTY_INIT_U ("Capabilities", PROP_CAPABILITIES, NMDevicePrivate, capabilities ), + NML_DBUS_META_PROPERTY_INIT_U ("DeviceType", PROP_DEVICE_TYPE, NMDevicePrivate, device_type ), + NML_DBUS_META_PROPERTY_INIT_O_PROP ("Dhcp4Config", PROP_DHCP4_CONFIG, NMDevicePrivate, property_o[PROPERTY_O_IDX_DHCP4_CONFIG], nm_dhcp4_config_get_type ), + NML_DBUS_META_PROPERTY_INIT_O_PROP ("Dhcp6Config", PROP_DHCP6_CONFIG, NMDevicePrivate, property_o[PROPERTY_O_IDX_DHCP6_CONFIG], nm_dhcp6_config_get_type ), + NML_DBUS_META_PROPERTY_INIT_S ("Driver", PROP_DRIVER, NMDevicePrivate, driver ), + NML_DBUS_META_PROPERTY_INIT_S ("DriverVersion", PROP_DRIVER_VERSION, NMDevicePrivate, driver_version ), + NML_DBUS_META_PROPERTY_INIT_B ("FirmwareMissing", PROP_FIRMWARE_MISSING, NMDevicePrivate, firmware_missing ), + NML_DBUS_META_PROPERTY_INIT_S ("FirmwareVersion", PROP_FIRMWARE_VERSION, NMDevicePrivate, firmware_version ), + NML_DBUS_META_PROPERTY_INIT_S ("Interface", PROP_INTERFACE, NMDevicePrivate, interface ), + NML_DBUS_META_PROPERTY_INIT_IGNORE ("Ip4Address", "u" ), + NML_DBUS_META_PROPERTY_INIT_O_PROP ("Ip4Config", PROP_IP4_CONFIG, NMDevicePrivate, property_o[PROPERTY_O_IDX_IP4_CONFIG], nm_ip4_config_get_type ), + NML_DBUS_META_PROPERTY_INIT_U ("Ip4Connectivity", PROP_IP4_CONNECTIVITY, NMDevicePrivate, ip4_connectivity ), + NML_DBUS_META_PROPERTY_INIT_O_PROP ("Ip6Config", PROP_IP6_CONFIG, NMDevicePrivate, property_o[PROPERTY_O_IDX_IP6_CONFIG], nm_ip6_config_get_type ), + NML_DBUS_META_PROPERTY_INIT_U ("Ip6Connectivity", PROP_IP6_CONNECTIVITY, NMDevicePrivate, ip6_connectivity ), + NML_DBUS_META_PROPERTY_INIT_S ("IpInterface", PROP_IP_INTERFACE, NMDevicePrivate, ip_interface ), + NML_DBUS_META_PROPERTY_INIT_FCN ("LldpNeighbors", PROP_LLDP_NEIGHBORS, "aa{sv}", _notify_update_prop_lldp_neighbors ), + NML_DBUS_META_PROPERTY_INIT_B ("Managed", PROP_MANAGED, NMDevicePrivate, managed ), + NML_DBUS_META_PROPERTY_INIT_U ("Metered", PROP_METERED, NMDevicePrivate, metered ), + NML_DBUS_META_PROPERTY_INIT_U ("Mtu", PROP_MTU, NMDevicePrivate, mtu ), + NML_DBUS_META_PROPERTY_INIT_B ("NmPluginMissing", PROP_NM_PLUGIN_MISSING, NMDevicePrivate, nm_plugin_missing ), + NML_DBUS_META_PROPERTY_INIT_S ("PhysicalPortId", PROP_PHYSICAL_PORT_ID, NMDevicePrivate, physical_port_id ), + NML_DBUS_META_PROPERTY_INIT_B ("Real", PROP_REAL, NMDevicePrivate, real ), + NML_DBUS_META_PROPERTY_INIT_IGNORE ("State", "u" ), + NML_DBUS_META_PROPERTY_INIT_FCN ("StateReason", PROP_STATE_REASON, "(uu)", _notify_update_prop_state_reason ), + NML_DBUS_META_PROPERTY_INIT_S ("Udi", PROP_UDI, NMDevicePrivate, udi ), + ), + .base_struct_offset = G_STRUCT_OFFSET (NMDevice, _priv), +); + static void -nm_device_class_init (NMDeviceClass *device_class) +nm_device_class_init (NMDeviceClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (device_class); - NMObjectClass *nm_object_class = NM_OBJECT_CLASS (device_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMObjectClass *nm_object_class = NM_OBJECT_CLASS (klass); - g_type_class_add_private (device_class, sizeof (NMDevicePrivate)); + g_type_class_add_private (klass, sizeof (NMDevicePrivate)); object_class->get_property = get_property; object_class->set_property = set_property; - object_class->dispose = dispose; object_class->finalize = finalize; - nm_object_class->init_dbus = init_dbus; + nm_object_class->register_client = register_client; + + _NM_OBJECT_CLASS_INIT_PRIV_PTR_INDIRECT (nm_object_class, NMDevice); - device_class->connection_compatible = connection_compatible; + _NM_OBJECT_CLASS_INIT_PROPERTY_O_FIELDS_N (nm_object_class, NMDevicePrivate, property_o); + _NM_OBJECT_CLASS_INIT_PROPERTY_AO_FIELDS_1 (nm_object_class, NMDevicePrivate, available_connections); + + klass->connection_compatible = connection_compatible; /** * NMDevice:interface: @@ -825,7 +883,7 @@ nm_device_class_init (NMDeviceClass *device_class) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + _nml_dbus_meta_class_init_with_properties (object_class, &_nml_dbus_meta_iface_nm_device); /** * NMDevice::state-changed: @@ -840,8 +898,7 @@ nm_device_class_init (NMDeviceClass *device_class) g_signal_new ("state-changed", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMDeviceClass, state_changed), - NULL, NULL, NULL, + 0, NULL, NULL, NULL, G_TYPE_NONE, 3, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT); } @@ -860,7 +917,7 @@ nm_device_get_iface (NMDevice *device) { g_return_val_if_fail (NM_IS_DEVICE (device), NULL); - return _nml_coerce_property_str_not_empty (NM_DEVICE_GET_PRIVATE (device)->iface); + return _nml_coerce_property_str_not_empty (NM_DEVICE_GET_PRIVATE (device)->interface); } /** @@ -878,7 +935,7 @@ nm_device_get_ip_iface (NMDevice *device) { g_return_val_if_fail (NM_IS_DEVICE (device), NULL); - return _nml_coerce_property_str_not_empty (NM_DEVICE_GET_PRIVATE (device)->ip_iface); + return _nml_coerce_property_str_not_empty (NM_DEVICE_GET_PRIVATE (device)->ip_interface); } /** @@ -1082,10 +1139,12 @@ nm_device_set_managed (NMDevice *device, gboolean managed) NM_DEVICE_GET_PRIVATE (device)->managed = managed; - _nm_object_set_property (NM_OBJECT (device), - NM_DBUS_INTERFACE_DEVICE, - "Managed", - "b", managed); + _nm_client_set_property_sync_legacy (_nm_object_get_client (device), + _nm_object_get_path (device), + NM_DBUS_INTERFACE_DEVICE, + "Managed", + "b", + managed); } /** @@ -1125,10 +1184,12 @@ nm_device_set_autoconnect (NMDevice *device, gboolean autoconnect) NM_DEVICE_GET_PRIVATE (device)->autoconnect = autoconnect; - _nm_object_set_property (NM_OBJECT (device), - NM_DBUS_INTERFACE_DEVICE, - "Autoconnect", - "b", autoconnect); + _nm_client_set_property_sync_legacy (_nm_object_get_client (device), + _nm_object_get_path (device), + NM_DBUS_INTERFACE_DEVICE, + "AutoConnect", + "b", + autoconnect); } /** @@ -1184,7 +1245,7 @@ nm_device_get_ip4_config (NMDevice *device) { g_return_val_if_fail (NM_IS_DEVICE (device), NULL); - return NM_DEVICE_GET_PRIVATE (device)->ip4_config; + return nml_dbus_property_o_get_obj (&NM_DEVICE_GET_PRIVATE (device)->property_o[PROPERTY_O_IDX_IP4_CONFIG]); } /** @@ -1204,7 +1265,7 @@ nm_device_get_dhcp4_config (NMDevice *device) { g_return_val_if_fail (NM_IS_DEVICE (device), NULL); - return NM_DEVICE_GET_PRIVATE (device)->dhcp4_config; + return nml_dbus_property_o_get_obj (&NM_DEVICE_GET_PRIVATE (device)->property_o[PROPERTY_O_IDX_DHCP4_CONFIG]); } /** @@ -1223,7 +1284,7 @@ nm_device_get_ip6_config (NMDevice *device) { g_return_val_if_fail (NM_IS_DEVICE (device), NULL); - return NM_DEVICE_GET_PRIVATE (device)->ip6_config; + return nml_dbus_property_o_get_obj (&NM_DEVICE_GET_PRIVATE (device)->property_o[PROPERTY_O_IDX_IP6_CONFIG]); } /** @@ -1243,7 +1304,7 @@ nm_device_get_dhcp6_config (NMDevice *device) { g_return_val_if_fail (NM_IS_DEVICE (device), NULL); - return NM_DEVICE_GET_PRIVATE (device)->dhcp6_config; + return nml_dbus_property_o_get_obj (&NM_DEVICE_GET_PRIVATE (device)->property_o[PROPERTY_O_IDX_DHCP6_CONFIG]); } /** @@ -1305,7 +1366,7 @@ nm_device_get_state_reason (NMDevice *device) { g_return_val_if_fail (NM_IS_DEVICE (device), NM_DEVICE_STATE_REASON_UNKNOWN); - return NM_DEVICE_GET_PRIVATE (device)->reason; + return NM_DEVICE_GET_PRIVATE (device)->state_reason; } /** @@ -1322,7 +1383,7 @@ nm_device_get_active_connection (NMDevice *device) { g_return_val_if_fail (NM_IS_DEVICE (device), NULL); - return NM_DEVICE_GET_PRIVATE (device)->active_connection; + return nml_dbus_property_o_get_obj (&NM_DEVICE_GET_PRIVATE (device)->property_o[PROPERTY_O_IDX_ACTIVE_CONNECTION]); } /** @@ -1341,7 +1402,7 @@ nm_device_get_available_connections (NMDevice *device) { g_return_val_if_fail (NM_IS_DEVICE (device), NULL); - return NM_DEVICE_GET_PRIVATE (device)->available_connections; + return nml_dbus_property_ao_get_objs_as_ptrarray (&NM_DEVICE_GET_PRIVATE (device)->available_connections); } static const char * @@ -1444,7 +1505,8 @@ get_bus_name (NMDevice *device) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); struct udev_device *udevice; - const char *ifname, *bus; + const char *ifname; + const char *bus; if (priv->bus_name) goto out; @@ -1482,31 +1544,18 @@ out: return NULL; } -void -_nm_device_set_udev (NMDevice *device, struct udev *udev) -{ - NMDevicePrivate *priv; - - nm_assert (NM_IS_DEVICE (device)); - nm_assert (udev); - - priv = NM_DEVICE_GET_PRIVATE (device); - - nm_assert (!priv->udev); - - priv->udev = udev_ref (udev); -} - static char * _get_udev_property (NMDevice *device, const char *enc_prop, /* ID_XXX_ENC */ const char *db_prop) /* ID_XXX_FROM_DATABASE */ { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); - struct udev_device *udev_device, *tmpdev; + struct udev_device *udev_device; + struct udev_device *tmpdev; const char *ifname; guint32 count = 0; - char *enc_value = NULL, *db_value = NULL; + char *enc_value = NULL; + char *db_value = NULL; if (!priv->udev) return NULL; @@ -1923,9 +1972,14 @@ NM_BACKPORT_SYMBOL (libnm_1_0_6, NMMetered, nm_device_get_metered, (NMDevice *de GPtrArray * nm_device_get_lldp_neighbors (NMDevice *device) { - g_return_val_if_fail (NM_IS_DEVICE (device), NULL); + NMDevicePrivate *priv; + + g_return_val_if_fail (NM_IS_DEVICE (device), NULL); - return NM_DEVICE_GET_PRIVATE (device)->lldp_neighbors; + priv = NM_DEVICE_GET_PRIVATE (device); + if (!priv->lldp_neighbors) + priv->lldp_neighbors = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_lldp_neighbor_unref); + return priv->lldp_neighbors; } /** @@ -2003,9 +2057,9 @@ nm_device_reapply (NMDevice *device, if (!arg_connection) arg_connection = g_variant_new_array (G_VARIANT_TYPE ("{sa{sv}}"), NULL, 0); - return _nm_object_dbus_call_sync_void (device, + return _nm_client_dbus_call_sync_void (_nm_object_get_client (device), cancellable, - g_dbus_proxy_get_object_path (G_DBUS_PROXY (NM_DEVICE_GET_PRIVATE (device)->proxy)), + _nm_object_get_path (device), NM_DBUS_INTERFACE_DEVICE, "Reapply", g_variant_new ("(@a{sa{sv}}tu)", @@ -2057,12 +2111,13 @@ nm_device_reapply_async (NMDevice *device, if (!arg_connection) arg_connection = g_variant_new_array (G_VARIANT_TYPE ("{sa{sv}}"), NULL, 0); - _nm_object_dbus_call (device, + _nm_client_dbus_call (_nm_object_get_client (device), + device, nm_device_reapply_async, cancellable, callback, user_data, - g_dbus_proxy_get_object_path (G_DBUS_PROXY (NM_DEVICE_GET_PRIVATE (device)->proxy)), + _nm_object_get_path (device), NM_DBUS_INTERFACE_DEVICE, "Reapply", g_variant_new ("(@a{sa{sv}}tu)", @@ -2138,9 +2193,9 @@ nm_device_get_applied_connection (NMDevice *device, g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), NULL); g_return_val_if_fail (!error || !*error, NULL); - ret = _nm_object_dbus_call_sync (device, + ret = _nm_client_dbus_call_sync (_nm_object_get_client (device), cancellable, - g_dbus_proxy_get_object_path (G_DBUS_PROXY (NM_DEVICE_GET_PRIVATE (device)->proxy)), + _nm_object_get_path (device), NM_DBUS_INTERFACE_DEVICE, "GetAppliedConnection", g_variant_new ("(u)", flags), @@ -2187,12 +2242,13 @@ nm_device_get_applied_connection_async (NMDevice *device, g_return_if_fail (NM_IS_DEVICE (device)); g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable)); - _nm_object_dbus_call (device, + _nm_client_dbus_call (_nm_object_get_client (device), + device, nm_device_get_applied_connection_async, cancellable, callback, user_data, - g_dbus_proxy_get_object_path (G_DBUS_PROXY (NM_DEVICE_GET_PRIVATE (device)->proxy)), + _nm_object_get_path (device), NM_DBUS_INTERFACE_DEVICE, "GetAppliedConnection", g_variant_new ("(u)", flags), @@ -2277,9 +2333,9 @@ nm_device_disconnect (NMDevice *device, g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), FALSE); g_return_val_if_fail (!error || !*error, FALSE); - return _nm_object_dbus_call_sync_void (device, + return _nm_client_dbus_call_sync_void (_nm_object_get_client (device), cancellable, - g_dbus_proxy_get_object_path (G_DBUS_PROXY (NM_DEVICE_GET_PRIVATE (device)->proxy)), + _nm_object_get_path (device), NM_DBUS_INTERFACE_DEVICE, "Disconnect", g_variant_new ("()"), @@ -2309,12 +2365,13 @@ nm_device_disconnect_async (NMDevice *device, g_return_if_fail (NM_IS_DEVICE (device)); g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable)); - _nm_object_dbus_call (device, + _nm_client_dbus_call (_nm_object_get_client (device), + device, nm_device_disconnect_async, cancellable, callback, user_data, - g_dbus_proxy_get_object_path (G_DBUS_PROXY (NM_DEVICE_GET_PRIVATE (device)->proxy)), + _nm_object_get_path (device), NM_DBUS_INTERFACE_DEVICE, "Disconnect", g_variant_new ("()"), @@ -2368,9 +2425,9 @@ nm_device_delete (NMDevice *device, g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), FALSE); g_return_val_if_fail (!error || !*error, FALSE); - return _nm_object_dbus_call_sync_void (device, + return _nm_client_dbus_call_sync_void (_nm_object_get_client (device), cancellable, - g_dbus_proxy_get_object_path (G_DBUS_PROXY (NM_DEVICE_GET_PRIVATE (device)->proxy)), + _nm_object_get_path (device), NM_DBUS_INTERFACE_DEVICE, "Delete", g_variant_new ("()"), @@ -2399,12 +2456,13 @@ nm_device_delete_async (NMDevice *device, g_return_if_fail (NM_IS_DEVICE (device)); g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable)); - _nm_object_dbus_call (device, + _nm_client_dbus_call (_nm_object_get_client (device), + device, nm_device_delete_async, cancellable, callback, user_data, - g_dbus_proxy_get_object_path (G_DBUS_PROXY (NM_DEVICE_GET_PRIVATE (device)->proxy)), + _nm_object_get_path (device), NM_DBUS_INTERFACE_DEVICE, "Delete", g_variant_new ("()"), diff --git a/libnm/nm-dhcp-config.c b/libnm/nm-dhcp-config.c index df171690b1..fcafceccc7 100644 --- a/libnm/nm-dhcp-config.c +++ b/libnm/nm-dhcp-config.c @@ -16,7 +16,7 @@ /*****************************************************************************/ -NM_GOBJECT_PROPERTIES_DEFINE_BASE ( +NM_GOBJECT_PROPERTIES_DEFINE (NMDhcpConfig, PROP_FAMILY, PROP_OPTIONS, ); @@ -31,54 +31,46 @@ G_DEFINE_ABSTRACT_TYPE (NMDhcpConfig, nm_dhcp_config, NM_TYPE_OBJECT) /*****************************************************************************/ -static void -nm_dhcp_config_init (NMDhcpConfig *self) +static NMLDBusNotifyUpdatePropFlags +_notify_update_prop_options (NMClient *client, + NMLDBusObject *dbobj, + const NMLDBusMetaIface *meta_iface, + guint dbus_property_idx, + GVariant *value) { - NMDhcpConfigPrivate *priv; - - priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NM_TYPE_DHCP_CONFIG, NMDhcpConfigPrivate); - - self->_priv = priv; - - priv->options = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, g_free); -} - -static gboolean -demarshal_dhcp_options (NMObject *object, GParamSpec *pspec, GVariant *value, gpointer field) -{ - NMDhcpConfigPrivate *priv = NM_DHCP_CONFIG_GET_PRIVATE (object); - GVariantIter iter; - const char *key; - GVariant *opt; + NMDhcpConfig *self = NM_DHCP_CONFIG (dbobj->nmobj); + NMDhcpConfigPrivate *priv = NM_DHCP_CONFIG_GET_PRIVATE (self); g_hash_table_remove_all (priv->options); - g_variant_iter_init (&iter, value); - while (g_variant_iter_next (&iter, "{&sv}", &key, &opt)) { - g_hash_table_insert (priv->options, g_strdup (key), g_variant_dup_string (opt, NULL)); - g_variant_unref (opt); + if (value) { + GVariantIter iter; + const char *key; + GVariant *opt; + + g_variant_iter_init (&iter, value); + while (g_variant_iter_next (&iter, "{&sv}", &key, &opt)) { + if (g_variant_is_of_type (opt, G_VARIANT_TYPE_STRING)) + g_hash_table_insert (priv->options, g_strdup (key), g_variant_dup_string (opt, NULL)); + g_variant_unref (opt); + } } - _nm_object_queue_notify (object, NM_DHCP_CONFIG_OPTIONS); - return TRUE; + return NML_DBUS_NOTIFY_UPDATE_PROP_FLAGS_NOTIFY; } +/*****************************************************************************/ + static void -init_dbus (NMObject *object) +nm_dhcp_config_init (NMDhcpConfig *self) { - NMDhcpConfigPrivate *priv = NM_DHCP_CONFIG_GET_PRIVATE (object); - const NMPropertiesInfo property_info[] = { - { NM_DHCP_CONFIG_OPTIONS, &priv->options, demarshal_dhcp_options }, - { NULL }, - }; - - NM_OBJECT_CLASS (nm_dhcp_config_parent_class)->init_dbus (object); - - _nm_object_register_properties (object, - (NM_IS_DHCP4_CONFIG (object) ? - NM_DBUS_INTERFACE_DHCP4_CONFIG : - NM_DBUS_INTERFACE_DHCP6_CONFIG), - property_info); + NMDhcpConfigPrivate *priv; + + priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NM_TYPE_DHCP_CONFIG, NMDhcpConfigPrivate); + + self->_priv = priv; + + priv->options = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, g_free); } static void @@ -86,8 +78,7 @@ finalize (GObject *object) { NMDhcpConfigPrivate *priv = NM_DHCP_CONFIG_GET_PRIVATE (object); - if (priv->options) - g_hash_table_destroy (priv->options); + g_hash_table_destroy (priv->options); G_OBJECT_CLASS (nm_dhcp_config_parent_class)->finalize (object); } @@ -113,19 +104,36 @@ get_property (GObject *object, } } +const NMLDBusMetaIface _nml_dbus_meta_iface_nm_dhcp4config = NML_DBUS_META_IFACE_INIT_PROP ( + NM_DBUS_INTERFACE_DHCP4_CONFIG, + nm_dhcp4_config_get_type, + NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, + NML_DBUS_META_IFACE_DBUS_PROPERTIES ( + NML_DBUS_META_PROPERTY_INIT_FCN ("Options", PROP_OPTIONS, "a{sv}", _notify_update_prop_options ), + ), + .base_struct_offset = G_STRUCT_OFFSET (NMDhcpConfig, _priv), +); + +const NMLDBusMetaIface _nml_dbus_meta_iface_nm_dhcp6config = NML_DBUS_META_IFACE_INIT_PROP ( + NM_DBUS_INTERFACE_DHCP6_CONFIG, + nm_dhcp6_config_get_type, + NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, + NML_DBUS_META_IFACE_DBUS_PROPERTIES ( + NML_DBUS_META_PROPERTY_INIT_FCN ("Options", PROP_OPTIONS, "a{sv}", _notify_update_prop_options ), + ), + .base_struct_offset = G_STRUCT_OFFSET (NMDhcpConfig, _priv), +); + static void nm_dhcp_config_class_init (NMDhcpConfigClass *config_class) { GObjectClass *object_class = G_OBJECT_CLASS (config_class); - NMObjectClass *nm_object_class = NM_OBJECT_CLASS (config_class); g_type_class_add_private (config_class, sizeof (NMDhcpConfigPrivate)); object_class->get_property = get_property; object_class->finalize = finalize; - nm_object_class->init_dbus = init_dbus; - /** * NMDhcpConfig:family: * @@ -149,7 +157,8 @@ nm_dhcp_config_class_init (NMDhcpConfigClass *config_class) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + _nml_dbus_meta_class_init_with_properties (object_class, &_nml_dbus_meta_iface_nm_dhcp4config, + &_nml_dbus_meta_iface_nm_dhcp6config); } /** diff --git a/libnm/nm-dns-manager.c b/libnm/nm-dns-manager.c index 4204cd138b..9fe759d384 100644 --- a/libnm/nm-dns-manager.c +++ b/libnm/nm-dns-manager.c @@ -14,25 +14,6 @@ #include "nm-dbus-helpers.h" #include "nm-core-internal.h" -#include "introspection/org.freedesktop.NetworkManager.DnsManager.h" - -G_DEFINE_TYPE (NMDnsManager, nm_dns_manager, NM_TYPE_OBJECT) - -#define NM_DNS_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DNS_MANAGER, NMDnsManagerPrivate)) - -typedef struct { - NMDBusDnsManager *proxy; - char *mode; - char *rc_manager; - GPtrArray *configuration; -} NMDnsManagerPrivate; - -NM_GOBJECT_PROPERTIES_DEFINE_BASE ( - PROP_MODE, - PROP_RC_MANAGER, - PROP_CONFIGURATION, -); - /***************************************************************************** * NMDnsEntry *****************************************************************************/ @@ -234,192 +215,3 @@ nm_dns_entry_get_priority (NMDnsEntry *entry) return entry->priority; } - -/*****************************************************************************/ - -static gboolean -demarshal_dns_configuration (NMObject *object, GParamSpec *pspec, GVariant *value, gpointer field) -{ - NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (object); - GVariant *entry_var; - GVariantIter iter, *iterp; - NMDnsEntry *entry; - GPtrArray *array; - - g_return_val_if_fail (g_variant_is_of_type (value, G_VARIANT_TYPE ("aa{sv}")), FALSE); - - g_variant_iter_init (&iter, value); - g_ptr_array_unref (priv->configuration); - priv->configuration = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_dns_entry_unref); - - while (g_variant_iter_next (&iter, "@a{sv}", &entry_var)) { - char **nameservers = NULL, **domains = NULL; - gboolean vpn = FALSE; - char *interface = NULL, *str; - int priority; - - if ( !g_variant_lookup (entry_var, "nameservers", "as", &iterp) - || !g_variant_lookup (entry_var, "priority", "i", &priority)) { - g_warning ("Ignoring invalid DNS configuration"); - g_variant_unref (entry_var); - continue; - } - - array = g_ptr_array_new (); - while (g_variant_iter_next (iterp, "&s", &str)) - g_ptr_array_add (array, str); - g_ptr_array_add (array, NULL); - nameservers = (char **) g_ptr_array_free (array, FALSE); - g_variant_iter_free (iterp); - - if (g_variant_lookup (entry_var, "domains", "as", &iterp)) { - array = g_ptr_array_new (); - while (g_variant_iter_next (iterp, "&s", &str)) - g_ptr_array_add (array, str); - g_ptr_array_add (array, NULL); - domains = (char **) g_ptr_array_free (array, FALSE); - g_variant_iter_free (iterp); - } - - g_variant_lookup (entry_var, "interface", "&s", &interface); - g_variant_lookup (entry_var, "priority", "i", &priority); - g_variant_lookup (entry_var, "vpn", "b", &vpn); - - entry = nm_dns_entry_new (interface, - (const char * const *) nameservers, - (const char * const *) domains, - priority, - vpn); - g_free (domains); - g_free (nameservers); - g_variant_unref (entry_var); - if (!entry) { - g_warning ("Ignoring invalid DNS entry"); - continue; - } - - g_ptr_array_add (priv->configuration, entry); - } - - _nm_object_queue_notify (object, NM_DNS_MANAGER_CONFIGURATION); - - return TRUE; -} - -/*****************************************************************************/ -const char * -nm_dns_manager_get_mode (NMDnsManager *manager) -{ - return NM_DNS_MANAGER_GET_PRIVATE (manager)->mode; -} - -const char * -nm_dns_manager_get_rc_manager (NMDnsManager *manager) -{ - return NM_DNS_MANAGER_GET_PRIVATE (manager)->rc_manager; -} - -const GPtrArray * -nm_dns_manager_get_configuration (NMDnsManager *manager) -{ - return NM_DNS_MANAGER_GET_PRIVATE (manager)->configuration; -} -/*****************************************************************************/ - -static void -nm_dns_manager_init (NMDnsManager *self) -{ - NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self); - - priv->configuration = g_ptr_array_new (); -} - -static void -init_dbus (NMObject *object) -{ - NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (object); - const NMPropertiesInfo property_info[] = { - { NM_DNS_MANAGER_MODE, &priv->mode }, - { NM_DNS_MANAGER_RC_MANAGER, &priv->rc_manager }, - { NM_DNS_MANAGER_CONFIGURATION, &priv->configuration, demarshal_dns_configuration }, - { NULL }, - }; - - NM_OBJECT_CLASS (nm_dns_manager_parent_class)->init_dbus (object); - - priv->proxy = NMDBUS_DNS_MANAGER (_nm_object_get_proxy (object, NM_DBUS_INTERFACE_DNS_MANAGER)); - _nm_object_register_properties (object, - NM_DBUS_INTERFACE_DNS_MANAGER, - property_info); -} - -static void -dispose (GObject *object) -{ - NMDnsManager *self = NM_DNS_MANAGER (object); - NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self); - - g_clear_pointer (&priv->mode, g_free); - g_clear_pointer (&priv->rc_manager, g_free); - g_clear_pointer (&priv->configuration, g_ptr_array_unref); - - G_OBJECT_CLASS (nm_dns_manager_parent_class)->dispose (object); -} - -static void -get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (object); - - switch (prop_id) { - case PROP_MODE: - g_value_set_string (value, priv->mode); - break; - case PROP_RC_MANAGER: - g_value_set_string (value, priv->rc_manager); - break; - case PROP_CONFIGURATION: - g_value_take_boxed (value, _nm_utils_copy_array (priv->configuration, - (NMUtilsCopyFunc) nm_dns_entry_dup, - (GDestroyNotify) nm_dns_entry_unref)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -nm_dns_manager_class_init (NMDnsManagerClass *class) -{ - GObjectClass *object_class = G_OBJECT_CLASS (class); - NMObjectClass *nm_object_class = NM_OBJECT_CLASS (class); - - g_type_class_add_private (class, sizeof (NMDnsManagerPrivate)); - - object_class->get_property = get_property; - object_class->dispose = dispose; - - nm_object_class->init_dbus = init_dbus; - - obj_properties[PROP_MODE] = - g_param_spec_string (NM_DNS_MANAGER_MODE, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_RC_MANAGER] = - g_param_spec_string (NM_DNS_MANAGER_RC_MANAGER, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_CONFIGURATION] = - g_param_spec_boxed (NM_DNS_MANAGER_CONFIGURATION, "", "", - G_TYPE_PTR_ARRAY, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); -} diff --git a/libnm/nm-dns-manager.h b/libnm/nm-dns-manager.h index 165f47653c..c645e43488 100644 --- a/libnm/nm-dns-manager.h +++ b/libnm/nm-dns-manager.h @@ -10,45 +10,13 @@ #error Cannot use this header. #endif -#include "nm-object.h" #include "nm-client.h" -#define NM_TYPE_DNS_MANAGER (nm_dns_manager_get_type ()) -#define NM_DNS_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DNS_MANAGER, NMDnsManager)) -#define NM_DNS_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DNS_MANAGER, NMDnsManagerClass)) -#define NM_IS_DNS_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DNS_MANAGER)) -#define NM_IS_DNS_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DNS_MANAGER)) -#define NM_DNS_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DNS_MANAGER, NMDnsManagerClass)) - -#define NM_DNS_MANAGER_MODE "mode" -#define NM_DNS_MANAGER_RC_MANAGER "rc-manager" -#define NM_DNS_MANAGER_CONFIGURATION "configuration" - -typedef struct _NMDnsManager NMDnsManager; -typedef struct _NMDnsManagerClass NMDnsManagerClass; - -/** - * NMDnsManager: - */ -struct _NMDnsManager { - NMObject parent; -}; - -struct _NMDnsManagerClass { - NMObjectClass parent; -}; - -GType nm_dns_manager_get_type (void); - -const char *nm_dns_manager_get_mode (NMDnsManager *manager); -const char *nm_dns_manager_get_rc_manager (NMDnsManager *manager); -const GPtrArray *nm_dns_manager_get_configuration (NMDnsManager *manager); - -NMDnsEntry * nm_dns_entry_new (const char *interface, - const char * const *nameservers, - const char * const *domains, - int priority, - gboolean vpn); -NMDnsEntry * nm_dns_entry_dup (NMDnsEntry *entry); +NMDnsEntry *nm_dns_entry_new (const char *interface, + const char * const *nameservers, + const char * const *domains, + int priority, + gboolean vpn); +NMDnsEntry *nm_dns_entry_dup (NMDnsEntry *entry); #endif /* __NM_DNS_MANAGER_H__ */ diff --git a/libnm/nm-ip-config.c b/libnm/nm-ip-config.c index 19e008ed05..f214cdc43b 100644 --- a/libnm/nm-ip-config.c +++ b/libnm/nm-ip-config.c @@ -18,7 +18,7 @@ /*****************************************************************************/ -NM_GOBJECT_PROPERTIES_DEFINE_BASE ( +NM_GOBJECT_PROPERTIES_DEFINE (NMIPConfig, PROP_FAMILY, PROP_GATEWAY, PROP_ADDRESSES, @@ -30,15 +30,18 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( ); typedef struct _NMIPConfigPrivate { - char *gateway; GPtrArray *addresses; GPtrArray *routes; char **nameservers; char **domains; char **searches; - char **wins; + char **wins_servers; + char *gateway; - gboolean new_style_data; + bool addresses_new_style:1; + bool routes_new_style:1; + bool nameservers_new_style:1; + bool wins_servers_new_style:1; } NMIPConfigPrivate; G_DEFINE_ABSTRACT_TYPE (NMIPConfig, nm_ip_config, NM_TYPE_OBJECT) @@ -47,156 +50,191 @@ G_DEFINE_ABSTRACT_TYPE (NMIPConfig, nm_ip_config, NM_TYPE_OBJECT) /*****************************************************************************/ -static void -nm_ip_config_init (NMIPConfig *self) -{ - NMIPConfigPrivate *priv; - - priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NM_TYPE_IP_CONFIG, NMIPConfigPrivate); - - self->_priv = priv; - - priv->addresses = g_ptr_array_new (); - priv->routes = g_ptr_array_new (); - priv->nameservers = g_new0 (char *, 1); - priv->domains = g_new0 (char *, 1); - priv->searches = g_new0 (char *, 1); - priv->wins = g_new0 (char *, 1); -} - -static gboolean -demarshal_ip_addresses (NMObject *object, GParamSpec *pspec, GVariant *value, gpointer field) +static NMLDBusNotifyUpdatePropFlags +_notify_update_prop_addresses (NMClient *client, + NMLDBusObject *dbobj, + const NMLDBusMetaIface *meta_iface, + guint dbus_property_idx, + GVariant *value) { - NMIPConfigPrivate *priv = NM_IP_CONFIG_GET_PRIVATE (object); - - if (priv->new_style_data) - return TRUE; - - g_ptr_array_unref (priv->addresses); - if (NM_IS_IP4_CONFIG (object)) - priv->addresses = nm_utils_ip4_addresses_from_variant (value, NULL); - else - priv->addresses = nm_utils_ip6_addresses_from_variant (value, NULL); - _nm_object_queue_notify (object, NM_IP_CONFIG_ADDRESSES); - - return TRUE; -} - -static gboolean -demarshal_ip_address_data (NMObject *object, GParamSpec *pspec, GVariant *value, gpointer field) -{ - NMIPConfigPrivate *priv = NM_IP_CONFIG_GET_PRIVATE (object); - - priv->new_style_data = TRUE; - - g_ptr_array_unref (priv->addresses); - if (NM_IS_IP4_CONFIG (object)) - priv->addresses = nm_utils_ip_addresses_from_variant (value, AF_INET); - else - priv->addresses = nm_utils_ip_addresses_from_variant (value, AF_INET6); - _nm_object_queue_notify (object, NM_IP_CONFIG_ADDRESSES); + NMIPConfig *self = NM_IP_CONFIG (dbobj->nmobj); + NMIPConfigPrivate *priv = NM_IP_CONFIG_GET_PRIVATE (self); + gs_unref_ptrarray GPtrArray *addresses_old = NULL; + gs_unref_ptrarray GPtrArray *addresses_new = NULL; + int addr_family = meta_iface == &_nml_dbus_meta_iface_nm_ip4config + ? AF_INET : AF_INET6; + gboolean new_style; + + new_style = (((const char *) meta_iface->dbus_properties[dbus_property_idx].dbus_type)[2] == '{'); + + if (priv->addresses_new_style) { + if (!new_style) + return NML_DBUS_NOTIFY_UPDATE_PROP_FLAGS_NONE; + } else + priv->addresses_new_style = new_style; + + if (value) { + if (new_style) + addresses_new = nm_utils_ip_addresses_from_variant (value, addr_family); + else if (addr_family == AF_INET) + addresses_new = nm_utils_ip4_addresses_from_variant (value, NULL); + else + addresses_new = nm_utils_ip6_addresses_from_variant (value, NULL); + nm_assert (addresses_new); + } + if (!addresses_new) + addresses_new = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip_address_unref); - return TRUE; + addresses_old = priv->addresses; + priv->addresses = g_steal_pointer (&addresses_new); + return NML_DBUS_NOTIFY_UPDATE_PROP_FLAGS_NOTIFY; } -static gboolean -demarshal_ip_array (NMObject *object, GParamSpec *pspec, GVariant *value, gpointer field) +static NMLDBusNotifyUpdatePropFlags +_notify_update_prop_routes (NMClient *client, + NMLDBusObject *dbobj, + const NMLDBusMetaIface *meta_iface, + guint dbus_property_idx, + GVariant *value) { - char ***obj_field; - - obj_field = field; - if (*obj_field) - g_strfreev (*obj_field); - - if (NM_IS_IP4_CONFIG (object)) - *obj_field = nm_utils_ip4_dns_from_variant (value); - else - *obj_field = nm_utils_ip6_dns_from_variant (value); + NMIPConfig *self = NM_IP_CONFIG (dbobj->nmobj); + NMIPConfigPrivate *priv = NM_IP_CONFIG_GET_PRIVATE (self); + gs_unref_ptrarray GPtrArray *routes_old = NULL; + gs_unref_ptrarray GPtrArray *routes_new = NULL; + int addr_family = meta_iface == &_nml_dbus_meta_iface_nm_ip4config + ? AF_INET : AF_INET6; + gboolean new_style; + + new_style = (((const char *) meta_iface->dbus_properties[dbus_property_idx].dbus_type)[2] == '{'); + + if (priv->routes_new_style) { + if (!new_style) + return NML_DBUS_NOTIFY_UPDATE_PROP_FLAGS_NONE; + } else + priv->routes_new_style = new_style; + + if (value) { + if (new_style) + routes_new = nm_utils_ip_routes_from_variant (value, addr_family); + else if (addr_family == AF_INET) + routes_new = nm_utils_ip4_routes_from_variant (value); + else + routes_new = nm_utils_ip6_routes_from_variant (value); + nm_assert (routes_new); + } + if (!routes_new) + routes_new = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip_route_unref); - _nm_object_queue_notify (object, pspec->name); - return TRUE; + routes_old = priv->routes; + priv->routes = g_steal_pointer (&routes_new); + return NML_DBUS_NOTIFY_UPDATE_PROP_FLAGS_NOTIFY; } -static gboolean -demarshal_ip_routes (NMObject *object, GParamSpec *pspec, GVariant *value, gpointer field) +static NMLDBusNotifyUpdatePropFlags +_notify_update_prop_nameservers (NMClient *client, + NMLDBusObject *dbobj, + const NMLDBusMetaIface *meta_iface, + guint dbus_property_idx, + GVariant *value) { - NMIPConfigPrivate *priv = NM_IP_CONFIG_GET_PRIVATE (object); - - if (priv->new_style_data) - return TRUE; + NMIPConfig *self = NM_IP_CONFIG (dbobj->nmobj); + NMIPConfigPrivate *priv = NM_IP_CONFIG_GET_PRIVATE (self); + gs_strfreev char **nameservers_new = NULL; + gboolean new_style = TRUE; + int addr_family = meta_iface == &_nml_dbus_meta_iface_nm_ip4config + ? AF_INET : AF_INET6; + + if (addr_family == AF_INET) { + new_style = (((const char *) meta_iface->dbus_properties[dbus_property_idx].dbus_type)[1] == 'a'); + + if (priv->nameservers_new_style) { + if (!new_style) + return NML_DBUS_NOTIFY_UPDATE_PROP_FLAGS_NONE; + } else + priv->nameservers_new_style = new_style; + } - g_ptr_array_unref (priv->routes); - if (NM_IS_IP4_CONFIG (object)) - priv->routes = nm_utils_ip4_routes_from_variant (value); - else - priv->routes = nm_utils_ip6_routes_from_variant (value); - _nm_object_queue_notify (object, NM_IP_CONFIG_ROUTES); + if (value) { + if (addr_family == AF_INET6) + nameservers_new = nm_utils_ip6_dns_from_variant (value); + else if (!new_style) + nameservers_new = nm_utils_ip4_dns_from_variant (value); + else { + GVariantIter iter; + GVariantIter *iter_v; + gs_unref_ptrarray GPtrArray *arr = NULL; + + g_variant_iter_init (&iter, value); + while (g_variant_iter_next (&iter, "a{sv}", &iter_v)) { + const char *key; + GVariant *val; + + while (g_variant_iter_next (iter_v, "{&sv}", &key, &val)) { + if (nm_streq (key, "address")) { + gs_free char *val_str = NULL; + + if (!g_variant_is_of_type (val, G_VARIANT_TYPE_STRING)) + goto next; + if (!nm_utils_parse_inaddr (AF_INET, g_variant_get_string (val, NULL), &val_str)) + goto next; + if (!arr) + arr = g_ptr_array_new (); + g_ptr_array_add (arr, g_steal_pointer (&val_str)); + goto next; + } +next: + g_variant_unref (val); + } + g_variant_iter_free (iter_v); + } + if ( arr + && arr->len > 0) + nameservers_new = nm_utils_strv_dup (arr->pdata, arr->len, FALSE); + else + nameservers_new = g_new0 (char *, 1); + } + nm_assert (nameservers_new); + } - return TRUE; + g_strfreev (priv->nameservers); + priv->nameservers = g_steal_pointer (&nameservers_new); + return NML_DBUS_NOTIFY_UPDATE_PROP_FLAGS_NOTIFY; } -static gboolean -demarshal_ip_route_data (NMObject *object, GParamSpec *pspec, GVariant *value, gpointer field) +static NMLDBusNotifyUpdatePropFlags +_notify_update_prop_wins_servers (NMClient *client, + NMLDBusObject *dbobj, + const NMLDBusMetaIface *meta_iface, + guint dbus_property_idx, + GVariant *value) { - NMIPConfigPrivate *priv = NM_IP_CONFIG_GET_PRIVATE (object); - - priv->new_style_data = TRUE; - - g_ptr_array_unref (priv->routes); - if (NM_IS_IP4_CONFIG (object)) - priv->routes = nm_utils_ip_routes_from_variant (value, AF_INET); - else - priv->routes = nm_utils_ip_routes_from_variant (value, AF_INET6); - _nm_object_queue_notify (object, NM_IP_CONFIG_ROUTES); - - return TRUE; -} + NMIPConfig *self = NM_IP_CONFIG (dbobj->nmobj); + NMIPConfigPrivate *priv = NM_IP_CONFIG_GET_PRIVATE (self); + gs_strfreev char **wins_servers_new = NULL; + gboolean new_style; + + new_style = (((const char *) meta_iface->dbus_properties[dbus_property_idx].dbus_type)[1] == 's'); + + if (priv->wins_servers_new_style) { + if (!new_style) + return NML_DBUS_NOTIFY_UPDATE_PROP_FLAGS_NONE; + } else + priv->wins_servers_new_style = new_style; + + if (value) { + if (new_style) + wins_servers_new = g_variant_dup_strv (value, NULL); + else + wins_servers_new = nm_utils_ip4_dns_from_variant (value); + nm_assert (wins_servers_new); + } -static void -init_dbus (NMObject *object) -{ - NMIPConfigPrivate *priv = NM_IP_CONFIG_GET_PRIVATE (object); - const NMPropertiesInfo property_info[] = { - { NM_IP_CONFIG_GATEWAY, &priv->gateway, }, - { NM_IP_CONFIG_ADDRESSES, &priv->addresses, demarshal_ip_addresses }, - { "address-data", &priv->addresses, demarshal_ip_address_data }, - { NM_IP_CONFIG_ROUTES, &priv->routes, demarshal_ip_routes }, - { "route-data", &priv->routes, demarshal_ip_route_data }, - /* Still use deprecated "Nameservers" property instead of "NameserverData" */ - { NM_IP_CONFIG_NAMESERVERS, &priv->nameservers, demarshal_ip_array }, - { NM_IP_CONFIG_DOMAINS, &priv->domains, }, - { NM_IP_CONFIG_SEARCHES, &priv->searches, }, - /* Still use deprecated "WinsServers" property instead of "WinsServerData" */ - { NM_IP_CONFIG_WINS_SERVERS, &priv->wins, demarshal_ip_array }, - { NULL }, - }; - - NM_OBJECT_CLASS (nm_ip_config_parent_class)->init_dbus (object); - - _nm_object_register_properties (object, - (NM_IS_IP4_CONFIG (object) ? - NM_DBUS_INTERFACE_IP4_CONFIG : - NM_DBUS_INTERFACE_IP6_CONFIG), - property_info); + g_strfreev (priv->wins_servers); + priv->wins_servers = g_steal_pointer (&wins_servers_new); + return NML_DBUS_NOTIFY_UPDATE_PROP_FLAGS_NOTIFY; } -static void -finalize (GObject *object) -{ - NMIPConfigPrivate *priv = NM_IP_CONFIG_GET_PRIVATE (object); - - g_free (priv->gateway); - - g_ptr_array_unref (priv->addresses); - g_ptr_array_unref (priv->routes); - - g_strfreev (priv->nameservers); - g_strfreev (priv->domains); - g_strfreev (priv->searches); - g_strfreev (priv->wins); - - G_OBJECT_CLASS (nm_ip_config_parent_class)->finalize (object); -} +/*****************************************************************************/ static void get_property (GObject *object, @@ -241,19 +279,90 @@ get_property (GObject *object, } } +/*****************************************************************************/ + +static void +nm_ip_config_init (NMIPConfig *self) +{ + NMIPConfigPrivate *priv; + + priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NM_TYPE_IP_CONFIG, NMIPConfigPrivate); + + self->_priv = priv; + + priv->addresses = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip_address_unref); + priv->routes = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip_route_unref); +} + +static void +finalize (GObject *object) +{ + NMIPConfigPrivate *priv = NM_IP_CONFIG_GET_PRIVATE (object); + + g_free (priv->gateway); + + g_ptr_array_unref (priv->routes); + g_ptr_array_unref (priv->addresses); + + g_strfreev (priv->nameservers); + g_strfreev (priv->domains); + g_strfreev (priv->searches); + g_strfreev (priv->wins_servers); + + G_OBJECT_CLASS (nm_ip_config_parent_class)->finalize (object); +} + +const NMLDBusMetaIface _nml_dbus_meta_iface_nm_ip4config = NML_DBUS_META_IFACE_INIT_PROP ( + NM_DBUS_INTERFACE_IP4_CONFIG, + nm_ip4_config_get_type, + NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, + NML_DBUS_META_IFACE_DBUS_PROPERTIES ( + NML_DBUS_META_PROPERTY_INIT_FCN ("AddressData", PROP_ADDRESSES, "aa{sv}", _notify_update_prop_addresses ), + NML_DBUS_META_PROPERTY_INIT_FCN ("Addresses", PROP_ADDRESSES, "aau", _notify_update_prop_addresses, .obj_property_no_reverse_idx = TRUE ), + NML_DBUS_META_PROPERTY_INIT_TODO ("DnsOptions", "as" ), + NML_DBUS_META_PROPERTY_INIT_TODO ("DnsPriority", "i" ), + NML_DBUS_META_PROPERTY_INIT_AS ("Domains", PROP_DOMAINS, NMIPConfigPrivate, domains ), + NML_DBUS_META_PROPERTY_INIT_S ("Gateway", PROP_GATEWAY, NMIPConfigPrivate, gateway ), + NML_DBUS_META_PROPERTY_INIT_FCN ("NameserverData", PROP_NAMESERVERS, "aa{sv}", _notify_update_prop_nameservers ), + NML_DBUS_META_PROPERTY_INIT_FCN ("Nameservers", PROP_NAMESERVERS, "au", _notify_update_prop_nameservers, .obj_property_no_reverse_idx = TRUE ), + NML_DBUS_META_PROPERTY_INIT_FCN ("RouteData", PROP_ROUTES, "aa{sv}", _notify_update_prop_routes ), + NML_DBUS_META_PROPERTY_INIT_FCN ("Routes", PROP_ROUTES, "aau", _notify_update_prop_routes, .obj_property_no_reverse_idx = TRUE ), + NML_DBUS_META_PROPERTY_INIT_AS ("Searches", PROP_SEARCHES, NMIPConfigPrivate, searches ), + NML_DBUS_META_PROPERTY_INIT_FCN ("WinsServerData", PROP_WINS_SERVERS, "as", _notify_update_prop_wins_servers ), + NML_DBUS_META_PROPERTY_INIT_FCN ("WinsServers", PROP_WINS_SERVERS, "au", _notify_update_prop_wins_servers, .obj_property_no_reverse_idx = TRUE ), + ), + .base_struct_offset = G_STRUCT_OFFSET (NMIPConfig, _priv), +); + +const NMLDBusMetaIface _nml_dbus_meta_iface_nm_ip6config = NML_DBUS_META_IFACE_INIT_PROP ( + NM_DBUS_INTERFACE_IP6_CONFIG, + nm_ip6_config_get_type, + NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, + NML_DBUS_META_IFACE_DBUS_PROPERTIES ( + NML_DBUS_META_PROPERTY_INIT_FCN ("AddressData", PROP_ADDRESSES, "aa{sv}", _notify_update_prop_addresses ), + NML_DBUS_META_PROPERTY_INIT_FCN ("Addresses", PROP_ADDRESSES, "a(ayuay)", _notify_update_prop_addresses, .obj_property_no_reverse_idx = TRUE ), + NML_DBUS_META_PROPERTY_INIT_TODO ("DnsOptions", "as" ), + NML_DBUS_META_PROPERTY_INIT_TODO ("DnsPriority", "i" ), + NML_DBUS_META_PROPERTY_INIT_AS ("Domains", PROP_DOMAINS, NMIPConfigPrivate, domains ), + NML_DBUS_META_PROPERTY_INIT_S ("Gateway", PROP_GATEWAY, NMIPConfigPrivate, gateway ), + NML_DBUS_META_PROPERTY_INIT_FCN ("Nameservers", PROP_NAMESERVERS, "aay", _notify_update_prop_nameservers ), + NML_DBUS_META_PROPERTY_INIT_FCN ("RouteData", PROP_ROUTES, "aa{sv}", _notify_update_prop_routes ), + NML_DBUS_META_PROPERTY_INIT_FCN ("Routes", PROP_ROUTES, "a(ayuayu)", _notify_update_prop_routes, .obj_property_no_reverse_idx = TRUE ), + NML_DBUS_META_PROPERTY_INIT_AS ("Searches", PROP_SEARCHES, NMIPConfigPrivate, searches ), + ), + .base_struct_offset = G_STRUCT_OFFSET (NMIPConfig, _priv), +); + static void nm_ip_config_class_init (NMIPConfigClass *config_class) { GObjectClass *object_class = G_OBJECT_CLASS (config_class); - NMObjectClass *nm_object_class = NM_OBJECT_CLASS (config_class); g_type_class_add_private (config_class, sizeof (NMIPConfigPrivate)); object_class->get_property = get_property; object_class->finalize = finalize; - nm_object_class->init_dbus = init_dbus; - /** * NMIPConfig:family: * @@ -344,7 +453,8 @@ nm_ip_config_class_init (NMIPConfigClass *config_class) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + _nml_dbus_meta_class_init_with_properties (object_class, &_nml_dbus_meta_iface_nm_ip4config, + &_nml_dbus_meta_iface_nm_ip6config); } /** @@ -407,12 +517,12 @@ nm_ip_config_get_addresses (NMIPConfig *config) * * Returns: (transfer none): the array of nameserver IP addresses **/ -const char * const * +const char *const* nm_ip_config_get_nameservers (NMIPConfig *config) { g_return_val_if_fail (NM_IS_IP_CONFIG (config), NULL); - return (const char * const *) NM_IP_CONFIG_GET_PRIVATE (config)->nameservers; + return _nml_coerce_property_strv_not_null (NM_IP_CONFIG_GET_PRIVATE (config)->nameservers); } /** @@ -424,12 +534,12 @@ nm_ip_config_get_nameservers (NMIPConfig *config) * Returns: (transfer none): the array of domains. * (This is never %NULL, though it may be 0-length). **/ -const char * const * +const char *const* nm_ip_config_get_domains (NMIPConfig *config) { g_return_val_if_fail (NM_IS_IP_CONFIG (config), NULL); - return (const char * const *) NM_IP_CONFIG_GET_PRIVATE (config)->domains; + return _nml_coerce_property_strv_not_null (NM_IP_CONFIG_GET_PRIVATE (config)->domains); } /** @@ -441,12 +551,12 @@ nm_ip_config_get_domains (NMIPConfig *config) * Returns: (transfer none): the array of DNS search strings. * (This is never %NULL, though it may be 0-length). **/ -const char * const * +const char *const* nm_ip_config_get_searches (NMIPConfig *config) { g_return_val_if_fail (NM_IS_IP_CONFIG (config), NULL); - return (const char * const *) NM_IP_CONFIG_GET_PRIVATE (config)->searches; + return _nml_coerce_property_strv_not_null (NM_IP_CONFIG_GET_PRIVATE (config)->searches); } /** @@ -458,12 +568,12 @@ nm_ip_config_get_searches (NMIPConfig *config) * Returns: (transfer none): the arry of WINS server IP address strings. * (This is never %NULL, though it may be 0-length.) **/ -const char * const * +const char *const* nm_ip_config_get_wins_servers (NMIPConfig *config) { g_return_val_if_fail (NM_IS_IP_CONFIG (config), NULL); - return (const char * const *) NM_IP_CONFIG_GET_PRIVATE (config)->wins; + return _nml_coerce_property_strv_not_null (NM_IP_CONFIG_GET_PRIVATE (config)->wins_servers); } /** diff --git a/libnm/nm-libnm-utils.c b/libnm/nm-libnm-utils.c index 5638d0eae0..73de75e36b 100644 --- a/libnm/nm-libnm-utils.c +++ b/libnm/nm-libnm-utils.c @@ -10,6 +10,7 @@ #include "nm-glib-aux/nm-time-utils.h" #include "nm-libnm-core-intern/nm-common-macros.h" +#include "nm-object.h" /*****************************************************************************/ @@ -741,3 +742,205 @@ nm_permission_result_to_client (const char *nm) return NM_CLIENT_PERMISSION_RESULT_AUTH; return NM_CLIENT_PERMISSION_RESULT_UNKNOWN; } + +/*****************************************************************************/ + +const NMLDBusMetaIface *const _nml_dbus_meta_ifaces[] = { + &_nml_dbus_meta_iface_nm, + &_nml_dbus_meta_iface_nm_accesspoint, + &_nml_dbus_meta_iface_nm_agentmanager, + &_nml_dbus_meta_iface_nm_checkpoint, + &_nml_dbus_meta_iface_nm_connection_active, + &_nml_dbus_meta_iface_nm_dhcp4config, + &_nml_dbus_meta_iface_nm_dhcp6config, + &_nml_dbus_meta_iface_nm_device, + &_nml_dbus_meta_iface_nm_device_adsl, + &_nml_dbus_meta_iface_nm_device_bluetooth, + &_nml_dbus_meta_iface_nm_device_bond, + &_nml_dbus_meta_iface_nm_device_bridge, + &_nml_dbus_meta_iface_nm_device_dummy, + &_nml_dbus_meta_iface_nm_device_generic, + &_nml_dbus_meta_iface_nm_device_iptunnel, + &_nml_dbus_meta_iface_nm_device_infiniband, + &_nml_dbus_meta_iface_nm_device_lowpan, + &_nml_dbus_meta_iface_nm_device_macsec, + &_nml_dbus_meta_iface_nm_device_macvlan, + &_nml_dbus_meta_iface_nm_device_modem, + &_nml_dbus_meta_iface_nm_device_olpcmesh, + &_nml_dbus_meta_iface_nm_device_ovsbridge, + &_nml_dbus_meta_iface_nm_device_ovsinterface, + &_nml_dbus_meta_iface_nm_device_ovsport, + &_nml_dbus_meta_iface_nm_device_ppp, + &_nml_dbus_meta_iface_nm_device_statistics, + &_nml_dbus_meta_iface_nm_device_team, + &_nml_dbus_meta_iface_nm_device_tun, + &_nml_dbus_meta_iface_nm_device_veth, + &_nml_dbus_meta_iface_nm_device_vlan, + &_nml_dbus_meta_iface_nm_device_vxlan, + &_nml_dbus_meta_iface_nm_device_wifip2p, + &_nml_dbus_meta_iface_nm_device_wireguard, + &_nml_dbus_meta_iface_nm_device_wired, + &_nml_dbus_meta_iface_nm_device_wireless, + &_nml_dbus_meta_iface_nm_device_wpan, + &_nml_dbus_meta_iface_nm_dnsmanager, + &_nml_dbus_meta_iface_nm_ip4config, + &_nml_dbus_meta_iface_nm_ip6config, + &_nml_dbus_meta_iface_nm_settings, + &_nml_dbus_meta_iface_nm_settings_connection, + &_nml_dbus_meta_iface_nm_vpn_connection, + &_nml_dbus_meta_iface_nm_wifip2ppeer, +}; + +#define COMMON_PREFIX "org.freedesktop.NetworkManager" + +static int +_strcmp_common_prefix (gconstpointer a, gconstpointer b, gpointer user_data) +{ + const NMLDBusMetaIface *iface = a; + const char *dbus_iface_name = b; + + nm_assert (g_str_has_prefix (iface->dbus_iface_name, COMMON_PREFIX)); + + return strcmp (&iface->dbus_iface_name[NM_STRLEN (COMMON_PREFIX)], dbus_iface_name); +} + +const NMLDBusMetaIface * +nml_dbus_meta_iface_get (const char *dbus_iface_name) +{ + gssize idx; + + nm_assert (dbus_iface_name); + + G_STATIC_ASSERT_EXPR (G_STRUCT_OFFSET (NMLDBusMetaIface, dbus_iface_name) == 0); + + /* we assume that NetworkManager only uses unique interface names. E.g. one + * interface name always has one particular meaning (and offers one set of + * properties, signals and methods). This is a convenient assumption, and + * we sure would never violate it when extending NM's D-Bus API. */ + + if (NM_STR_HAS_PREFIX (dbus_iface_name, COMMON_PREFIX)) { + /* optimize, that in fact all our interfaces have the same prefix. */ + idx = nm_utils_ptrarray_find_binary_search ((gconstpointer *) _nml_dbus_meta_ifaces, + G_N_ELEMENTS (_nml_dbus_meta_ifaces), + &dbus_iface_name[NM_STRLEN (COMMON_PREFIX)], + _strcmp_common_prefix, + NULL, + NULL, + NULL); + } else + return NULL; + + if (idx < 0) + return NULL; + return _nml_dbus_meta_ifaces[idx]; +} + +const NMLDBusMetaProperty * +nml_dbus_meta_property_get (const NMLDBusMetaIface *meta_iface, + const char *dbus_property_name, + guint *out_idx) +{ + gssize idx; + + nm_assert (meta_iface); + nm_assert (dbus_property_name); + + idx = nm_utils_array_find_binary_search (meta_iface->dbus_properties, + sizeof (meta_iface->dbus_properties[0]), + meta_iface->n_dbus_properties, + &dbus_property_name, + nm_strcmp_p_with_data, + NULL); + if (idx < 0) { + NM_SET_OUT (out_idx, meta_iface->n_dbus_properties); + return NULL; + } + NM_SET_OUT (out_idx, idx); + return &meta_iface->dbus_properties[idx]; +} + +void +_nml_dbus_meta_class_init_with_properties_impl (GObjectClass *object_class, + const NMLDBusMetaIface *const*meta_ifaces) +{ + int i_iface; + + nm_assert (G_IS_OBJECT_CLASS (object_class)); + nm_assert (meta_ifaces); + nm_assert (meta_ifaces[0]); + + for (i_iface = 0; meta_ifaces[i_iface]; i_iface++) { + const NMLDBusMetaIface *meta_iface = meta_ifaces[i_iface]; + guint8 *reverse_idx; + guint8 i; + + nm_assert (g_type_is_a (meta_iface->get_type_fcn (), G_OBJECT_CLASS_TYPE (object_class))); + nm_assert (meta_iface->n_obj_properties > 0); + nm_assert (meta_iface->obj_properties); + nm_assert (meta_iface->obj_properties_reverse_idx[0] == 0); + nm_assert (meta_iface->obj_properties == meta_ifaces[0]->obj_properties); + + if (i_iface == 0) + g_object_class_install_properties (object_class, meta_iface->n_obj_properties, (GParamSpec **) meta_iface->obj_properties); + + reverse_idx = (guint8 *) meta_iface->obj_properties_reverse_idx; + + for (i = 0; i < meta_iface->n_obj_properties; i++) + reverse_idx[i] = 0xFFu; + for (i = 0; i < meta_iface->n_dbus_properties; i++) { + const NMLDBusMetaProperty *mpr = &meta_iface->dbus_properties[i]; + + if ( mpr->obj_properties_idx != 0 + && !mpr->obj_property_no_reverse_idx) { + nm_assert (mpr->obj_properties_idx < meta_iface->n_obj_properties); + nm_assert (reverse_idx[mpr->obj_properties_idx] == 0xFFu); + + reverse_idx[mpr->obj_properties_idx] = i; + } + } + } +} + +gboolean +nm_utils_g_param_spec_is_default (const GParamSpec *pspec) +{ + g_return_val_if_fail (pspec, FALSE); + + if (pspec->value_type == G_TYPE_BOOLEAN) + return ((((GParamSpecBoolean *) pspec)->default_value) == FALSE); + if (pspec->value_type == G_TYPE_UCHAR) + return ((((GParamSpecUChar *) pspec)->default_value) == 0u); + if (pspec->value_type == G_TYPE_INT) + return ((((GParamSpecInt *) pspec)->default_value) == 0); + if (pspec->value_type == G_TYPE_UINT) + return ((((GParamSpecUInt *) pspec)->default_value) == 0u); + if (pspec->value_type == G_TYPE_INT64) + return ((((GParamSpecInt64 *) pspec)->default_value) == 0); + if (pspec->value_type == G_TYPE_UINT64) + return ((((GParamSpecUInt64 *) pspec)->default_value) == 0u); + if (g_type_is_a (pspec->value_type, G_TYPE_ENUM)) + return ((((GParamSpecEnum *) pspec)->default_value) == 0); + if (g_type_is_a (pspec->value_type, G_TYPE_FLAGS)) + return ((((GParamSpecFlags *) pspec)->default_value) == 0u); + if (pspec->value_type == G_TYPE_STRING) + return ((((GParamSpecString *) pspec)->default_value) == NULL); + if (NM_IN_SET (pspec->value_type, G_TYPE_BYTES, + G_TYPE_PTR_ARRAY, + G_TYPE_HASH_TABLE, + G_TYPE_STRV)) { + /* boxed types have NULL default. */ + g_return_val_if_fail (G_IS_PARAM_SPEC_BOXED (pspec), FALSE); + g_return_val_if_fail (G_TYPE_IS_BOXED (pspec->value_type), FALSE); + return TRUE; + } + if (g_type_is_a (pspec->value_type, NM_TYPE_OBJECT)) { + /* object types have NULL default. */ + g_return_val_if_fail (G_IS_PARAM_SPEC_OBJECT (pspec), FALSE); + g_return_val_if_fail (G_TYPE_IS_OBJECT (pspec->value_type), FALSE); + return TRUE; + } + + /* This function is only used for asserting/testing. It thus + * strictly asserts and only support argument types that we expect. */ + g_return_val_if_reached (FALSE); +} diff --git a/libnm/nm-libnm-utils.h b/libnm/nm-libnm-utils.h index 484c00396f..9c7959e6be 100644 --- a/libnm/nm-libnm-utils.h +++ b/libnm/nm-libnm-utils.h @@ -6,8 +6,10 @@ #ifndef __NM_LIBNM_UTILS_H__ #define __NM_LIBNM_UTILS_H__ -#include "nm-types.h" +#include "c-list/src/c-list.h" #include "nm-glib-aux/nm-ref-string.h" +#include "nm-types.h" +#include "nm-object.h" #include "nm-client.h" /*****************************************************************************/ @@ -18,6 +20,15 @@ /*****************************************************************************/ +char *nm_utils_fixup_vendor_string (const char *desc); +char *nm_utils_fixup_product_string (const char *desc); + +char *nm_utils_wincaps_to_dash (const char *caps); + +gboolean nm_utils_g_param_spec_is_default (const GParamSpec *pspec); + +/*****************************************************************************/ + NMClientPermission nm_permission_to_client (const char *nm); NMClientPermissionResult nm_permission_result_to_client (const char *nm); @@ -142,35 +153,490 @@ _nml_coerce_property_strv_not_null (char **strv) /*****************************************************************************/ -char *nm_utils_wincaps_to_dash (const char *caps); +typedef struct _NMLDBusObject NMLDBusObject; +typedef struct _NMLDBusObjWatcher NMLDBusObjWatcher; +typedef struct _NMLDBusObjPropData NMLDBusObjPropData; +typedef struct _NMLDBusObjIfaceData NMLDBusObjIfaceData; +typedef struct _NMLDBusMetaIface NMLDBusMetaIface; + +typedef enum { + NML_DBUS_META_INTERFACE_PRIO_NONE = 0, + NML_DBUS_META_INTERFACE_PRIO_NMCLIENT = 1, + NML_DBUS_META_INTERFACE_PRIO_PARENT_TYPE = 2, + NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_LOW = 3, + NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH = 4, +} NMLDBusMetaInteracePrio; + +typedef struct _NMLDBusPropertyO NMLDBusPropertyO; +typedef struct _NMLDBusPropertyAO NMLDBusPropertyAO; + +typedef struct { + GType (*get_o_type_fcn) (void); + + /* This is to untangle loops. Device.ActiveConnection and ActiveConnection.Devices + * reference each other. One of them must allow to be considered visible without + * the other one. */ + bool ready_without_visible:1; + +} NMLDBusPropertVTableO; + +typedef struct { + GType (*get_o_type_fcn) (void); + + void (*notify_changed_ao) (NMLDBusPropertyAO *pr_ao, + NMClient *self, + NMObject *nmobj, + gboolean is_added /* or else removed */); + + gboolean (*check_nmobj_visible_fcn) (GObject *nmobj); + + /* This is to untangle loops. Device.ActiveConnection and ActiveConnection.Devices + * reference each other. One of them must allow to be considered visible without + * the other one. */ + bool ready_without_visible:1; + +} NMLDBusPropertVTableAO; + +struct _NMLDBusPropertyO { + NMLDBusObject *owner_dbobj; + NMLDBusObjWatcher *obj_watcher; + GObject *nmobj; + const NMLDBusMetaIface *meta_iface; + guint dbus_property_idx; + bool is_ready:1; +}; + +gpointer nml_dbus_property_o_get_obj (NMLDBusPropertyO *pr_o); + +gboolean nml_dbus_property_o_is_ready (const NMLDBusPropertyO *pr_o); + +void nml_dbus_property_o_clear (NMLDBusPropertyO *pr_o, + NMClient *client); + +struct _NMLDBusPropertyAO { + CList lst; + GHashTable *hash; + NMLDBusObject *owner_dbobj; + const NMLDBusMetaIface *meta_iface; + GPtrArray *arr; + guint dbus_property_idx; + guint n_not_ready; +}; + +const GPtrArray *nml_dbus_property_ao_get_objs_as_ptrarray (NMLDBusPropertyAO *pr_ao); + +gboolean nml_dbus_property_ao_is_ready (const NMLDBusPropertyAO *pr_ao); + +void nml_dbus_property_ao_clear (NMLDBusPropertyAO *pr_ao, + NMClient *client); + +typedef enum { + NML_DBUS_NOTIFY_UPDATE_PROP_FLAGS_NONE = 0, + NML_DBUS_NOTIFY_UPDATE_PROP_FLAGS_NOTIFY = 0x1, +} NMLDBusNotifyUpdatePropFlags; + +NMLDBusNotifyUpdatePropFlags _nml_dbus_notify_update_prop_ignore (NMClient *client, + NMLDBusObject *dbobj, + const NMLDBusMetaIface *meta_iface, + guint dbus_property_idx, + GVariant *value); + +NMLDBusNotifyUpdatePropFlags _nml_dbus_notify_update_prop_o (NMClient *client, + NMLDBusObject *dbobj, + const NMLDBusMetaIface *meta_iface, + guint dbus_property_idx, + GVariant *value); + +typedef struct { + const char *dbus_property_name; + const GVariantType *dbus_type; + + guint16 prop_struct_offset; + + guint8 obj_properties_idx; + + bool use_notify_update_prop:1; + + bool obj_property_no_reverse_idx:1; + + union { + union { + const NMLDBusPropertVTableO *property_vtable_o; + const NMLDBusPropertVTableAO *property_vtable_ao; + } extra; + + NMLDBusNotifyUpdatePropFlags (*notify_update_prop) (NMClient *client, + NMLDBusObject *dbobj, + const NMLDBusMetaIface *meta_iface, + guint dbus_property_idx, + GVariant *value); + }; + +} NMLDBusMetaProperty; + +#define NML_DBUS_META_PROPERTY_INIT(v_dbus_property_name, \ + v_dbus_type, \ + v_obj_properties_idx, \ + ...) \ + { \ + .dbus_property_name = ""v_dbus_property_name"", \ + .dbus_type = NM_G_VARIANT_TYPE (""v_dbus_type""), \ + .obj_properties_idx = v_obj_properties_idx, \ + ##__VA_ARGS__ \ + } + +#define _NML_DBUS_META_PROPERTY_INIT_DEFAULT(v_dbus_type, \ + v_exp_type, \ + v_dbus_property_name, \ + v_obj_properties_idx, \ + v_container, \ + v_field) \ + NML_DBUS_META_PROPERTY_INIT (v_dbus_property_name, \ + v_dbus_type, \ + v_obj_properties_idx, \ + .prop_struct_offset = NM_STRUCT_OFFSET_ENSURE_TYPE (v_exp_type, v_container, v_field)) + +#define NML_DBUS_META_PROPERTY_INIT_B(...) _NML_DBUS_META_PROPERTY_INIT_DEFAULT ("b", bool, __VA_ARGS__) +#define NML_DBUS_META_PROPERTY_INIT_Y(...) _NML_DBUS_META_PROPERTY_INIT_DEFAULT ("y", guint8, __VA_ARGS__) +#define NML_DBUS_META_PROPERTY_INIT_Q(...) _NML_DBUS_META_PROPERTY_INIT_DEFAULT ("q", guint16, __VA_ARGS__) +#define NML_DBUS_META_PROPERTY_INIT_I(...) _NML_DBUS_META_PROPERTY_INIT_DEFAULT ("i", gint32, __VA_ARGS__) +#define NML_DBUS_META_PROPERTY_INIT_U(...) _NML_DBUS_META_PROPERTY_INIT_DEFAULT ("u", guint32, __VA_ARGS__) +#define NML_DBUS_META_PROPERTY_INIT_X(...) _NML_DBUS_META_PROPERTY_INIT_DEFAULT ("x", gint64, __VA_ARGS__) +#define NML_DBUS_META_PROPERTY_INIT_T(...) _NML_DBUS_META_PROPERTY_INIT_DEFAULT ("t", guint64, __VA_ARGS__) +#define NML_DBUS_META_PROPERTY_INIT_S(...) _NML_DBUS_META_PROPERTY_INIT_DEFAULT ("s", char *, __VA_ARGS__) +#define NML_DBUS_META_PROPERTY_INIT_AS(...) _NML_DBUS_META_PROPERTY_INIT_DEFAULT ("as", char **, __VA_ARGS__) +#define NML_DBUS_META_PROPERTY_INIT_AY(...) _NML_DBUS_META_PROPERTY_INIT_DEFAULT ("ay", GBytes *, __VA_ARGS__) + +#define NML_DBUS_META_PROPERTY_INIT_O(v_dbus_property_name, \ + v_obj_properties_idx, \ + v_container, \ + v_field) \ + NML_DBUS_META_PROPERTY_INIT (v_dbus_property_name, \ + "o", \ + v_obj_properties_idx, \ + .prop_struct_offset = NM_STRUCT_OFFSET_ENSURE_TYPE (NMRefString *, v_container, v_field), \ + .use_notify_update_prop = TRUE, \ + .notify_update_prop = _nml_dbus_notify_update_prop_o) + +#define NML_DBUS_META_PROPERTY_INIT_O_PROP(v_dbus_property_name, \ + v_obj_properties_idx, \ + v_container, \ + v_field, \ + v_get_o_type_fcn, \ + ...) \ + NML_DBUS_META_PROPERTY_INIT (v_dbus_property_name, \ + "o", \ + v_obj_properties_idx, \ + .prop_struct_offset = NM_STRUCT_OFFSET_ENSURE_TYPE (NMLDBusPropertyO, v_container, v_field), \ + .extra.property_vtable_o = &((const NMLDBusPropertVTableO) { \ + .get_o_type_fcn = (v_get_o_type_fcn), \ + ##__VA_ARGS__ \ + })) + +#define NML_DBUS_META_PROPERTY_INIT_AO_PROP(v_dbus_property_name, \ + v_obj_properties_idx, \ + v_container, \ + v_field, \ + v_get_o_type_fcn, \ + ...) \ + NML_DBUS_META_PROPERTY_INIT (v_dbus_property_name, \ + "ao", \ + v_obj_properties_idx, \ + .prop_struct_offset = NM_STRUCT_OFFSET_ENSURE_TYPE (NMLDBusPropertyAO, v_container, v_field), \ + .extra.property_vtable_ao = &((const NMLDBusPropertVTableAO) { \ + .get_o_type_fcn = (v_get_o_type_fcn), \ + ##__VA_ARGS__ \ + })) + +#define NML_DBUS_META_PROPERTY_INIT_FCN(v_dbus_property_name, \ + v_obj_properties_idx, \ + v_dbus_type, \ + v_notify_update_prop, \ + ...) \ + NML_DBUS_META_PROPERTY_INIT (v_dbus_property_name, \ + v_dbus_type, \ + v_obj_properties_idx, \ + .use_notify_update_prop = TRUE, \ + .notify_update_prop = (v_notify_update_prop), \ + ##__VA_ARGS__) + +#define NML_DBUS_META_PROPERTY_INIT_IGNORE(v_dbus_property_name, \ + v_dbus_type) \ + NML_DBUS_META_PROPERTY_INIT (v_dbus_property_name, \ + v_dbus_type, \ + 0, \ + .use_notify_update_prop = TRUE, \ + .notify_update_prop = _nml_dbus_notify_update_prop_ignore) + +/* "TODO" is like "IGNORE". The difference is that we don't plan to ever implement "IGNORE", but + * "TODO" is something we should add support for. */ +#define NML_DBUS_META_PROPERTY_INIT_TODO(...) \ + NML_DBUS_META_PROPERTY_INIT_IGNORE (__VA_ARGS__) + +typedef struct _NMLDBusMetaIface { + const char *dbus_iface_name; + GType (*get_type_fcn) (void); + const GParamSpec *const*obj_properties; + const NMLDBusMetaProperty *dbus_properties; + const guint8 *obj_properties_reverse_idx; + guint8 n_dbus_properties; + guint8 n_obj_properties; + + /* The offsets in NMLDBusMetaProperty are based on some base struct. + * If this is 0, then the base struct is the GObject pointer itself. + * If this is non-null, then we expect at that location a pointer + * to the offset. */ + guint8 base_struct_offset; + + NMLDBusMetaInteracePrio interface_prio:3; +} NMLDBusMetaIface; + +#define NML_DBUS_META_IFACE_OBJ_PROPERTIES() \ + .obj_properties = (const GParamSpec *const*) (obj_properties), \ + .n_obj_properties = _PROPERTY_ENUMS_LAST, \ + .obj_properties_reverse_idx = ((guint8 [_PROPERTY_ENUMS_LAST]) { }) + +#define NML_DBUS_META_IFACE_DBUS_PROPERTIES(...) \ + .dbus_properties = ((const NMLDBusMetaProperty []) { __VA_ARGS__ }), \ + .n_dbus_properties = sizeof ((const NMLDBusMetaProperty []) { __VA_ARGS__ }) / sizeof (NMLDBusMetaProperty) \ + +#define NML_DBUS_META_IFACE_INIT(v_dbus_iface_name, \ + v_get_type_fcn, \ + v_interface_prio, \ + ...) \ + { \ + .dbus_iface_name = ""v_dbus_iface_name"", \ + .get_type_fcn = v_get_type_fcn, \ + .interface_prio = v_interface_prio, \ + ##__VA_ARGS__ \ + } + +#define NML_DBUS_META_IFACE_INIT_PROP(...) \ + NML_DBUS_META_IFACE_INIT (__VA_ARGS__ \ + NML_DBUS_META_IFACE_OBJ_PROPERTIES ()) + +extern const NMLDBusMetaIface *const _nml_dbus_meta_ifaces[43]; + +extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm; +extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_accesspoint; +extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_agentmanager; +extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_checkpoint; +extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_connection_active; +extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device; +extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_adsl; +extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_bluetooth; +extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_bond; +extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_bridge; +extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_dummy; +extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_generic; +extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_infiniband; +extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_iptunnel; +extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_lowpan; +extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_macsec; +extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_macvlan; +extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_modem; +extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_olpcmesh; +extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_ovsbridge; +extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_ovsinterface; +extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_ovsport; +extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_ppp; +extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_statistics; +extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_team; +extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_tun; +extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_veth; +extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_vlan; +extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_vxlan; +extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_wifip2p; +extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_wired; +extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_wireguard; +extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_wireless; +extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_wpan; +extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_dhcp4config; +extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_dhcp6config; +extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_dnsmanager; +extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_ip4config; +extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_ip6config; +extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_settings; +extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_settings_connection; +extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_vpn_connection; +extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_wifip2ppeer; + +const NMLDBusMetaIface *nml_dbus_meta_iface_get (const char *dbus_iface_name); + +const NMLDBusMetaProperty *nml_dbus_meta_property_get (const NMLDBusMetaIface *meta_iface, + const char *dbus_property_name, + guint *out_idx); + +void _nml_dbus_meta_class_init_with_properties_impl (GObjectClass *object_class, const NMLDBusMetaIface *const*meta_iface); +#define _nml_dbus_meta_class_init_with_properties(object_class, ...) \ + _nml_dbus_meta_class_init_with_properties_impl ((object_class), ((const NMLDBusMetaIface *const[]) { __VA_ARGS__, NULL })) /*****************************************************************************/ -char *nm_utils_fixup_vendor_string (const char *desc); -char *nm_utils_fixup_product_string (const char *desc); +typedef enum { + NML_DBUS_OBJ_STATE_UNLINKED = 0, + NML_DBUS_OBJ_STATE_WATCHED_ONLY, + NML_DBUS_OBJ_STATE_ON_DBUS, + NML_DBUS_OBJ_STATE_WITH_NMOBJ_NOT_READY, + NML_DBUS_OBJ_STATE_WITH_NMOBJ_MAYBE_READY, + NML_DBUS_OBJ_STATE_WITH_NMOBJ_VISIBLE, + NML_DBUS_OBJ_STATE_WITH_NMOBJ_HIDDEN, +} NMLDBusObjState; + +struct _NMLDBusObject { + NMRefString *dbus_path; + + CList iface_lst_head; + CList removed_iface_lst_head; + CList changed_obj_lst; + + CList watcher_lst_head; + + CList notify_watchers_lst; + + CList dbus_objects_lst; + + GObject *nmobj; + int ref_count; + + NMLDBusObjState obj_state:4; +}; + +static inline gboolean +NML_IS_DBUS_OBJECT (NMLDBusObject *dbobj) +{ + nm_assert ( !dbobj + || ( NM_IS_REF_STRING (dbobj->dbus_path) + && dbobj->ref_count > 0)); + nm_assert ( !dbobj->nmobj + || NM_IS_OBJECT (dbobj->nmobj) + || NM_IS_CLIENT (dbobj->nmobj)); + return !!dbobj; +} + +NMLDBusObject *nml_dbus_object_ref (NMLDBusObject *dbobj); + +void nml_dbus_object_unref (NMLDBusObject *dbobj); + +NM_AUTO_DEFINE_FCN0 (NMLDBusObject *, _nm_auto_unref_nml_dbusobj, nml_dbus_object_unref) +#define nm_auto_unref_nml_dbusobj nm_auto (_nm_auto_unref_nml_dbusobj) + +NMLDBusObjIfaceData *nml_dbus_object_iface_data_get (NMLDBusObject *dbobj, + const char *dbus_iface_name, + gboolean allow_create); + +gpointer nml_dbus_object_get_property_location (NMLDBusObject *dbobj, + const NMLDBusMetaIface *meta_iface, + const NMLDBusMetaProperty *meta_property); /*****************************************************************************/ +/* NMClient is not an NMObject, but in some aspects we want to track it like + * an NMObject. For that, both NMClient and NMObject "implement" NMObjectBase, + * despite not actually implementing such a GObject type. */ +typedef struct { + GObject parent; + CList queue_notify_lst; + bool is_disposing:1; +} NMObjectBase; + +typedef struct { + GObjectClass parent; +} NMObjectBaseClass; + struct _NMObjectPrivate; struct _NMObject { - GObject parent; + union { + GObject parent; + NMObjectBase obj_base; + }; struct _NMObjectPrivate *_priv; }; +typedef struct _NMObjectClassFieldInfo { + const struct _NMObjectClassFieldInfo *parent; + NMObjectClass *klass; + guint16 offset; + guint16 num; +} _NMObjectClassFieldInfo; + struct _NMObjectClass { - GObjectClass parent; + union { + GObjectClass parent; + NMObjectBaseClass obj_base; + }; + + void (*register_client) (NMObject *self, + NMClient *client, + NMLDBusObject *dbobj); + + void (*unregister_client) (NMObject *self, + NMClient *client, + NMLDBusObject *dbobj); + + NMLDBusObjState (*is_visible) (NMObject *self); - void (*init_dbus) (struct _NMObject *object); + const _NMObjectClassFieldInfo *property_o_info; + const _NMObjectClassFieldInfo *property_ao_info; - /* The "object-creation-failed" method is PRIVATE for libnm and - * is not meant for any external usage. It indicates that an error - * occurred during creation of an object. - */ - void (*object_creation_failed) (struct _NMObject *master_object, - const char *failed_path); + guint16 priv_ptr_offset; + + bool priv_ptr_indirect:1; }; +#define _NM_OBJECT_CLASS_INIT_PRIV_PTR_DIRECT(nm_object_class, type_name) \ + G_STMT_START { \ + (nm_object_class)->priv_ptr_offset = NM_STRUCT_OFFSET_ENSURE_TYPE (type_name##Private, type_name, _priv); \ + (nm_object_class)->priv_ptr_indirect = FALSE; \ + } G_STMT_END + +#define _NM_OBJECT_CLASS_INIT_PRIV_PTR_INDIRECT(nm_object_class, type_name) \ + G_STMT_START { \ + (nm_object_class)->priv_ptr_offset = NM_STRUCT_OFFSET_ENSURE_TYPE (type_name##Private *, type_name, _priv); \ + (nm_object_class)->priv_ptr_indirect = TRUE; \ + } G_STMT_END + +#define _NM_OBJECT_CLASS_INIT_FIELD_INFO(_nm_object_class, _field_name, _offset, _num) \ + G_STMT_START { \ + (_nm_object_class)->_field_name = ({ \ + static _NMObjectClassFieldInfo _f; \ + \ + _f = (_NMObjectClassFieldInfo) { \ + .parent = (_nm_object_class)->_field_name, \ + .klass = (_nm_object_class), \ + .offset = _offset, \ + .num = _num, \ + }; \ + &_f; \ + }); \ + } G_STMT_END + +#define _NM_OBJECT_CLASS_INIT_PROPERTY_O_FIELDS_1(nm_object_class, type_name, field_name) \ + _NM_OBJECT_CLASS_INIT_FIELD_INFO (nm_object_class, \ + property_o_info, \ + NM_STRUCT_OFFSET_ENSURE_TYPE (NMLDBusPropertyO, type_name, field_name), \ + 1) + +#define _NM_OBJECT_CLASS_INIT_PROPERTY_O_FIELDS_N(nm_object_class, type_name, field_name) \ + _NM_OBJECT_CLASS_INIT_FIELD_INFO (nm_object_class, \ + property_o_info, \ + NM_STRUCT_OFFSET_ENSURE_TYPE (NMLDBusPropertyO *, type_name, field_name), \ + G_N_ELEMENTS (((type_name *) NULL)->field_name)) + +#define _NM_OBJECT_CLASS_INIT_PROPERTY_AO_FIELDS_1(nm_object_class, type_name, field_name) \ + _NM_OBJECT_CLASS_INIT_FIELD_INFO (nm_object_class, \ + property_ao_info, \ + NM_STRUCT_OFFSET_ENSURE_TYPE (NMLDBusPropertyAO, type_name, field_name), \ + 1) + +#define _NM_OBJECT_CLASS_INIT_PROPERTY_AO_FIELDS_N(nm_object_class, type_name, field_name) \ + _NM_OBJECT_CLASS_INIT_FIELD_INFO (nm_object_class, \ + property_ao_info, \ + NM_STRUCT_OFFSET_ENSURE_TYPE (NMLDBusPropertyAO *, type_name, field_name), \ + G_N_ELEMENTS (((type_name *) NULL)->field_name)) + + /*****************************************************************************/ struct _NMDevicePrivate; @@ -183,19 +649,13 @@ struct _NMDevice { struct _NMDeviceClass { struct _NMObjectClass parent; - /* Signals */ - void (*state_changed) (NMDevice *device, - NMDeviceState new_state, - NMDeviceState old_state, - NMDeviceStateReason reason); - - /* Methods */ gboolean (*connection_compatible) (NMDevice *device, NMConnection *connection, GError **error); - const char * (*get_type_description) (NMDevice *device); - const char * (*get_hw_address) (NMDevice *device); + const char *(*get_type_description) (NMDevice *device); + + const char *(*get_hw_address) (NMDevice *device); GType (*get_setting_type) (NMDevice *device); }; @@ -241,4 +701,154 @@ struct _NMIPConfigClass { /*****************************************************************************/ +NMLDBusObject *_nm_object_get_dbobj (gpointer self); + +const char *_nm_object_get_path (gpointer self); + +NMClient *_nm_object_get_client (gpointer self); + +GDBusConnection *_nm_client_get_dbus_connection (NMClient *client); + +const char *_nm_client_get_dbus_name_owner (NMClient *client); + +GMainContext *_nm_client_get_context_main (NMClient *client); +GMainContext *_nm_client_get_context_dbus (NMClient *client); + +void _nm_client_queue_notify_object (NMClient *client, + gpointer nmobj, + const GParamSpec *pspec); + +void _nm_client_notify_object_changed (NMClient *self, + NMLDBusObject *dbobj); + +struct udev *_nm_client_get_udev (NMClient *self); + +/*****************************************************************************/ + +#define NM_CLIENT_NOTIFY_EVENT_PRIO_BEFORE (-100) +#define NM_CLIENT_NOTIFY_EVENT_PRIO_GPROP 0 +#define NM_CLIENT_NOTIFY_EVENT_PRIO_AFTER 100 + +typedef struct _NMClientNotifyEvent NMClientNotifyEvent; + +typedef void (*NMClientNotifyEventCb) (NMClient *self, + gpointer notify_event); + +struct _NMClientNotifyEvent { + CList lst; + NMClientNotifyEventCb callback; + int priority; +}; + +gpointer _nm_client_notify_event_queue (NMClient *self, + int priority, + NMClientNotifyEventCb callback, + gsize event_size); + +typedef struct _NMClientNotifyEventWithPtr NMClientNotifyEventWithPtr; + +typedef void (*NMClientNotifyEventWithPtrCb) (NMClient *self, + NMClientNotifyEventWithPtr *notify_event); + +struct _NMClientNotifyEventWithPtr { + NMClientNotifyEvent parent; + gpointer user_data; +}; + +NMClientNotifyEventWithPtr *_nm_client_notify_event_queue_with_ptr (NMClient *self, + int priority, + NMClientNotifyEventWithPtrCb callback, + gpointer user_data); + +void _nm_client_notify_event_queue_emit_obj_signal (NMClient *self, + GObject *source, + NMObject *nmobj, + gboolean is_added /* or else removed */, + int prio_offset, + guint signal_id); + +/*****************************************************************************/ + +GError *_nm_client_new_error_nm_not_running (void); +GError *_nm_client_new_error_nm_not_cached (void); + +void _nm_client_dbus_call_simple (NMClient *self, + GCancellable *cancellable, + const char *object_path, + const char *interface_name, + const char *method_name, + GVariant *parameters, + const GVariantType *reply_type, + GDBusCallFlags flags, + int timeout_msec, + GAsyncReadyCallback callback, + gpointer user_data); + +void _nm_client_dbus_call (NMClient *self, + gpointer source_obj, + gpointer source_tag, + GCancellable *cancellable, + GAsyncReadyCallback user_callback, + gpointer user_callback_data, + const char *object_path, + const char *interface_name, + const char *method_name, + GVariant *parameters, + const GVariantType *reply_type, + GDBusCallFlags flags, + int timeout_msec, + GAsyncReadyCallback internal_callback); + +GVariant *_nm_client_dbus_call_sync (NMClient *self, + GCancellable *cancellable, + const char *object_path, + const char *interface_name, + const char *method_name, + GVariant *parameters, + const GVariantType *reply_type, + GDBusCallFlags flags, + int timeout_msec, + gboolean strip_dbus_error, + GError **error); + +gboolean _nm_client_dbus_call_sync_void (NMClient *self, + GCancellable *cancellable, + const char *object_path, + const char *interface_name, + const char *method_name, + GVariant *parameters, + GDBusCallFlags flags, + int timeout_msec, + gboolean strip_dbus_error, + GError **error); + +void _nm_client_set_property_sync_legacy (NMClient *self, + const char *object_path, + const char *interface, + const char *prop_name, + const char *format_string, + ...); + +/*****************************************************************************/ + +void _nm_client_get_settings_call (NMClient *self, + NMLDBusObject *dbobj); + +GCancellable *_nm_remote_settings_get_settings_prepare (NMRemoteConnection *self); + +void _nm_remote_settings_get_settings_commit (NMRemoteConnection *self, + GVariant *settings); + +/*****************************************************************************/ + +void _nm_active_connection_state_changed_commit (NMActiveConnection *self, + guint32 state, + guint32 reason); + +void _nm_vpn_connection_state_changed_commit (NMVpnConnection *self, + guint32 state, + guint32 reason); + +/*****************************************************************************/ + #endif /* __NM_LIBNM_UTILS_H__ */ diff --git a/libnm/nm-manager.c b/libnm/nm-manager.c deleted file mode 100644 index b88aba098e..0000000000 --- a/libnm/nm-manager.c +++ /dev/null @@ -1,1532 +0,0 @@ -// SPDX-License-Identifier: LGPL-2.1+ -/* - * Copyright (C) 2007 - 2008 Novell, Inc. - * Copyright (C) 2007 - 2014 Red Hat, Inc. - */ - -#include "nm-default.h" - -#include "nm-manager.h" - -#include "nm-utils.h" -#include "nm-checkpoint.h" -#include "nm-libnm-core-intern/nm-common-macros.h" -#include "nm-device-ethernet.h" -#include "nm-device-wifi.h" -#include "nm-core-internal.h" -#include "nm-object-private.h" -#include "nm-active-connection.h" -#include "nm-vpn-connection.h" -#include "nm-dbus-helpers.h" -#include "c-list/src/c-list.h" - -#include "introspection/org.freedesktop.NetworkManager.h" - -void _nm_device_wifi_set_wireless_enabled (NMDeviceWifi *device, gboolean enabled); - -static void nm_manager_initable_iface_init (GInitableIface *iface); -static void nm_manager_async_initable_iface_init (GAsyncInitableIface *iface); -static GInitableIface *nm_manager_parent_initable_iface; -static GAsyncInitableIface *nm_manager_parent_async_initable_iface; - -G_DEFINE_TYPE_WITH_CODE (NMManager, nm_manager, NM_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, nm_manager_initable_iface_init); - G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, nm_manager_async_initable_iface_init); - ) - -#define NM_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_MANAGER, NMManagerPrivate)) - -typedef struct { - NMDBusManager *proxy; - GCancellable *props_cancellable; - char *version; - NMState state; - gboolean startup; - GPtrArray *devices; - GPtrArray *all_devices; - GPtrArray *active_connections; - GPtrArray *checkpoints; - NMConnectivityState connectivity; - NMActiveConnection *primary_connection; - NMActiveConnection *activating_connection; - NMMetered metered; - - GCancellable *perm_call_cancellable; - GHashTable *permissions; - - /* Activations waiting for their NMActiveConnection - * to appear and then their callback to be called. - */ - CList wait_for_active_connection_lst_head; - - CList wait_for_checkpoint_lst_head; - - gboolean networking_enabled; - gboolean wireless_enabled; - gboolean wireless_hw_enabled; - - gboolean wwan_enabled; - gboolean wwan_hw_enabled; - - gboolean wimax_enabled; - gboolean wimax_hw_enabled; - - gboolean connectivity_check_available; - gboolean connectivity_check_enabled; -} NMManagerPrivate; - -NM_GOBJECT_PROPERTIES_DEFINE (NMManager, - PROP_VERSION, - PROP_STATE, - PROP_STARTUP, - PROP_NETWORKING_ENABLED, - PROP_WIRELESS_ENABLED, - PROP_WIRELESS_HARDWARE_ENABLED, - PROP_WWAN_ENABLED, - PROP_WWAN_HARDWARE_ENABLED, - PROP_WIMAX_ENABLED, - PROP_WIMAX_HARDWARE_ENABLED, - PROP_ACTIVE_CONNECTIONS, - PROP_CONNECTIVITY, - PROP_CONNECTIVITY_CHECK_AVAILABLE, - PROP_CONNECTIVITY_CHECK_ENABLED, - PROP_PRIMARY_CONNECTION, - PROP_ACTIVATING_CONNECTION, - PROP_DEVICES, - PROP_CHECKPOINTS, - PROP_METERED, - PROP_ALL_DEVICES, -); - -enum { - DEVICE_ADDED, - DEVICE_REMOVED, - ANY_DEVICE_ADDED, - ANY_DEVICE_REMOVED, - ACTIVE_CONNECTION_ADDED, - ACTIVE_CONNECTION_REMOVED, - CHECKPOINT_ADDED, - CHECKPOINT_REMOVED, - PERMISSION_CHANGED, - - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -/*****************************************************************************/ - -typedef struct { - CList lst; - NMManager *self; - char *checkpoint_path; - GTask *task; - gulong cancelled_id; -} CheckpointInfo; - -static CheckpointInfo * -_wait_for_checkpoint_find_info (NMManager *manager, const char *path) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); - CheckpointInfo *info; - - c_list_for_each_entry (info, &priv->wait_for_checkpoint_lst_head, lst) { - if (nm_streq (path, info->checkpoint_path)) - return info; - } - - return NULL; -} - -static void -_wait_for_checkpoint_complete (CheckpointInfo *info, - NMCheckpoint *checkpoint, - GError *error) -{ - c_list_unlink_stale (&info->lst); - - nm_clear_g_signal_handler (g_task_get_cancellable (info->task), &info->cancelled_id); - - if (!checkpoint) - g_task_return_error (info->task, error); - else - g_task_return_pointer (info->task, g_object_ref (checkpoint), g_object_unref); - - g_object_unref (info->task); - g_object_unref (info->self); - g_free (info->checkpoint_path); - nm_g_slice_free (info); -} - -static void -nm_manager_init (NMManager *manager) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); - - c_list_init (&priv->wait_for_active_connection_lst_head); - c_list_init (&priv->wait_for_checkpoint_lst_head); - - priv->state = NM_STATE_UNKNOWN; - priv->connectivity = NM_CONNECTIVITY_UNKNOWN; - - priv->permissions = g_hash_table_new (nm_direct_hash, NULL); - priv->devices = g_ptr_array_new (); - priv->all_devices = g_ptr_array_new (); - priv->active_connections = g_ptr_array_new (); -} - -static void -poke_wireless_devices_with_rf_status (NMManager *manager) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); - int i; - - for (i = 0; i < priv->all_devices->len; i++) { - NMDevice *device = g_ptr_array_index (priv->all_devices, i); - - if (NM_IS_DEVICE_WIFI (device)) - _nm_device_wifi_set_wireless_enabled (NM_DEVICE_WIFI (device), priv->wireless_enabled); - } -} - -static void -wireless_enabled_cb (GObject *object, GParamSpec *pspec, gpointer user_data) -{ - poke_wireless_devices_with_rf_status (NM_MANAGER (object)); -} - -static void manager_recheck_permissions (NMDBusManager *proxy, gpointer user_data); - -static void -init_dbus (NMObject *object) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (object); - const NMPropertiesInfo property_info[] = { - { NM_MANAGER_VERSION, &priv->version }, - { NM_MANAGER_STATE, &priv->state }, - { NM_MANAGER_STARTUP, &priv->startup }, - { NM_MANAGER_NETWORKING_ENABLED, &priv->networking_enabled }, - { NM_MANAGER_WIRELESS_ENABLED, &priv->wireless_enabled }, - { NM_MANAGER_WIRELESS_HARDWARE_ENABLED, &priv->wireless_hw_enabled }, - { NM_MANAGER_WWAN_ENABLED, &priv->wwan_enabled }, - { NM_MANAGER_WWAN_HARDWARE_ENABLED, &priv->wwan_hw_enabled }, - { NM_MANAGER_WIMAX_ENABLED, &priv->wimax_enabled }, - { NM_MANAGER_WIMAX_HARDWARE_ENABLED, &priv->wimax_hw_enabled }, - { NM_MANAGER_ACTIVE_CONNECTIONS, &priv->active_connections, NULL, NM_TYPE_ACTIVE_CONNECTION, "active-connection" }, - { NM_MANAGER_CONNECTIVITY, &priv->connectivity }, - { NM_MANAGER_CONNECTIVITY_CHECK_AVAILABLE, &priv->connectivity_check_available }, - { NM_MANAGER_CONNECTIVITY_CHECK_ENABLED, &priv->connectivity_check_enabled }, - { NM_MANAGER_PRIMARY_CONNECTION, &priv->primary_connection, NULL, NM_TYPE_ACTIVE_CONNECTION }, - { NM_MANAGER_ACTIVATING_CONNECTION, &priv->activating_connection, NULL, NM_TYPE_ACTIVE_CONNECTION }, - { NM_MANAGER_DEVICES, &priv->devices, NULL, NM_TYPE_DEVICE, "device" }, - { NM_MANAGER_CHECKPOINTS, &priv->checkpoints, NULL, NM_TYPE_CHECKPOINT, "checkpoint" }, - { NM_MANAGER_METERED, &priv->metered }, - { NM_MANAGER_ALL_DEVICES, &priv->all_devices, NULL, NM_TYPE_DEVICE, "any-device" }, - { NULL }, - }; - - NM_OBJECT_CLASS (nm_manager_parent_class)->init_dbus (object); - - priv->proxy = NMDBUS_MANAGER (_nm_object_get_proxy (object, NM_DBUS_INTERFACE)); - _nm_object_register_properties (object, - NM_DBUS_INTERFACE, - property_info); - - /* Permissions */ - g_signal_connect_object (priv->proxy, "check-permissions", - G_CALLBACK (manager_recheck_permissions), object, 0); -} - -static void -object_creation_failed (NMObject *object, const char *failed_path) -{ - NMManager *self = NM_MANAGER (object); - CheckpointInfo *info; - GError *add_error; - - info = _wait_for_checkpoint_find_info (self, failed_path); - if (info) { - add_error = g_error_new_literal (NM_CLIENT_ERROR, - NM_CLIENT_ERROR_OBJECT_CREATION_FAILED, - _("Checkpoint was removed before it was initialized")); - _wait_for_checkpoint_complete (info, NULL, add_error); - g_error_free (add_error); - } -} - -static void -update_permissions (NMManager *self, GVariant *permissions) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - GHashTableIter iter; - gpointer key, value; - NMClientPermission perm; - NMClientPermissionResult perm_result; - GList *keys, *keys_iter; - - /* get list of old permissions for change notification */ - keys = g_hash_table_get_keys (priv->permissions); - g_hash_table_remove_all (priv->permissions); - - if (permissions) { - GVariantIter viter; - const char *pkey, *pvalue; - - /* Process new permissions */ - g_variant_iter_init (&viter, permissions); - while (g_variant_iter_next (&viter, "{&s&s}", &pkey, &pvalue)) { - perm = nm_permission_to_client (pkey); - perm_result = nm_permission_result_to_client (pvalue); - if (perm) { - g_hash_table_insert (priv->permissions, - GUINT_TO_POINTER (perm), - GUINT_TO_POINTER (perm_result)); - - /* Remove this permission from the list of previous permissions - * we'll be sending NM_CLIENT_PERMISSION_RESULT_UNKNOWN for - * in the change signal since it is still a known permission. - */ - keys = g_list_remove (keys, GUINT_TO_POINTER (perm)); - } - } - } - - /* Signal changes in all updated permissions */ - g_hash_table_iter_init (&iter, priv->permissions); - while (g_hash_table_iter_next (&iter, &key, &value)) { - g_signal_emit (self, signals[PERMISSION_CHANGED], 0, - GPOINTER_TO_UINT (key), - GPOINTER_TO_UINT (value)); - } - - /* And signal changes in all permissions that used to be valid but for - * some reason weren't received in the last request (if any). - */ - for (keys_iter = keys; keys_iter; keys_iter = g_list_next (keys_iter)) { - g_signal_emit (self, signals[PERMISSION_CHANGED], 0, - GPOINTER_TO_UINT (keys_iter->data), - NM_CLIENT_PERMISSION_RESULT_UNKNOWN); - } - g_list_free (keys); -} - -static void -get_permissions_reply (GObject *object, - GAsyncResult *result, - gpointer user_data) -{ - NMManager *self; - NMManagerPrivate *priv; - gs_unref_variant GVariant *ret = NULL; - gs_unref_variant GVariant *permissions = NULL; - gs_free_error GError *error = NULL; - - ret = g_dbus_connection_call_finish (G_DBUS_CONNECTION (object), result, &error); - if (!ret) { - if (nm_utils_error_is_cancelled (error, FALSE)) - return; - } else { - g_variant_get (ret, - "(@a{ss})", - &permissions); - } - - self = user_data; - priv = NM_MANAGER_GET_PRIVATE (self); - - g_clear_object (&priv->perm_call_cancellable); - - update_permissions (self, permissions); -} - -static void -manager_recheck_permissions (NMDBusManager *_unused_proxy, gpointer user_data) -{ - NMManager *self = NM_MANAGER (user_data); - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - const char *name_owner; - - /* If a request is already pending, then we cancel it. We anyway - * need to make a new request, to be sure that we picked up on all - * the latest changes since the "CheckPermission" signal. - * - * However, we cannot accept more than one "GetPermissions" request - * in flight. That is because NetworkManager needs to ask PolicyKit - * for each permission individually, and some of these permission - * requests might be answered before others. Hence, the collection - * of all permissions is not taken at one point in time. Hence, when - * we would allow for multiple GetPermissions requests in-flight, - * we wouldn't know which response reflects the latest state. */ - nm_clear_g_cancellable (&priv->perm_call_cancellable); - - name_owner = _nm_object_get_dbus_name_owner (self); - if (!name_owner) - return; - - priv->perm_call_cancellable = g_cancellable_new (); - g_dbus_connection_call (_nm_object_get_dbus_connection (self), - name_owner, - NM_DBUS_PATH, - NM_DBUS_INTERFACE, - "GetPermissions", - g_variant_new ("()"), - G_VARIANT_TYPE ("(a{ss})"), - G_DBUS_CALL_FLAGS_NONE, - NM_DBUS_DEFAULT_TIMEOUT_MSEC, - priv->perm_call_cancellable, - get_permissions_reply, - self); -} - -const char * -nm_manager_get_version (NMManager *manager) -{ - g_return_val_if_fail (NM_IS_MANAGER (manager), NULL); - - return _nml_coerce_property_str_not_empty (NM_MANAGER_GET_PRIVATE (manager)->version); -} - -NMState -nm_manager_get_state (NMManager *manager) -{ - g_return_val_if_fail (NM_IS_MANAGER (manager), NM_STATE_UNKNOWN); - - return NM_MANAGER_GET_PRIVATE (manager)->state; -} - -gboolean -nm_manager_get_startup (NMManager *manager) -{ - g_return_val_if_fail (NM_IS_MANAGER (manager), NM_STATE_UNKNOWN); - - return NM_MANAGER_GET_PRIVATE (manager)->startup; -} - -gboolean -nm_manager_networking_get_enabled (NMManager *manager) -{ - g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE); - - return NM_MANAGER_GET_PRIVATE (manager)->networking_enabled; -} - -gboolean -_nm_manager_networking_set_enabled (GDBusConnection *dbus_connection, - const char *name_owner, - gboolean enable, - GError **error) -{ - gs_unref_variant GVariant *ret = NULL; - - ret = g_dbus_connection_call_sync (dbus_connection, - name_owner, - NM_DBUS_PATH, - NM_DBUS_INTERFACE, - "Enable", - g_variant_new ("(b)", enable), - G_VARIANT_TYPE ("()"), - G_DBUS_CALL_FLAGS_NONE, - NM_DBUS_DEFAULT_TIMEOUT_MSEC, - NULL, - error); - if (!ret) { - if (error) - g_dbus_error_strip_remote_error (*error); - return FALSE; - } - - return TRUE; -} - -gboolean -nm_manager_wireless_get_enabled (NMManager *manager) -{ - g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE); - - return NM_MANAGER_GET_PRIVATE (manager)->wireless_enabled; -} - -void -nm_manager_wireless_set_enabled (NMManager *manager, gboolean enabled) -{ - g_return_if_fail (NM_IS_MANAGER (manager)); - - _nm_object_set_property (NM_OBJECT (manager), - NM_DBUS_INTERFACE, - "WirelessEnabled", - "b", enabled); -} - -gboolean -nm_manager_wireless_hardware_get_enabled (NMManager *manager) -{ - g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE); - - return NM_MANAGER_GET_PRIVATE (manager)->wireless_hw_enabled; -} - -gboolean -nm_manager_wwan_get_enabled (NMManager *manager) -{ - g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE); - - return NM_MANAGER_GET_PRIVATE (manager)->wwan_enabled; -} - -void -nm_manager_wwan_set_enabled (NMManager *manager, gboolean enabled) -{ - g_return_if_fail (NM_IS_MANAGER (manager)); - - _nm_object_set_property (NM_OBJECT (manager), - NM_DBUS_INTERFACE, - "WwanEnabled", - "b", enabled); -} - -gboolean -nm_manager_wwan_hardware_get_enabled (NMManager *manager) -{ - g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE); - - return NM_MANAGER_GET_PRIVATE (manager)->wwan_hw_enabled; -} - -gboolean -nm_manager_wimax_get_enabled (NMManager *manager) -{ - g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE); - - return NM_MANAGER_GET_PRIVATE (manager)->wimax_enabled; -} - -void -nm_manager_wimax_set_enabled (NMManager *manager, gboolean enabled) -{ - g_return_if_fail (NM_IS_MANAGER (manager)); - - _nm_object_set_property (NM_OBJECT (manager), - NM_DBUS_INTERFACE, - "WimaxEnabled", - "b", enabled); -} - -gboolean -nm_manager_wimax_hardware_get_enabled (NMManager *manager) -{ - g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE); - - return NM_MANAGER_GET_PRIVATE (manager)->wimax_hw_enabled; -} - -gboolean -nm_manager_connectivity_check_get_available (NMManager *manager) -{ - g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE); - - return NM_MANAGER_GET_PRIVATE (manager)->connectivity_check_available; -} - -gboolean -nm_manager_connectivity_check_get_enabled (NMManager *manager) -{ - return NM_MANAGER_GET_PRIVATE (manager)->connectivity_check_enabled; -} - -void -nm_manager_connectivity_check_set_enabled (NMManager *manager, gboolean enabled) -{ - g_return_if_fail (NM_IS_MANAGER (manager)); - - _nm_object_set_property (NM_OBJECT (manager), - NM_DBUS_INTERFACE, - "ConnectivityCheckEnabled", - "b", enabled); -} - -const char * -nm_manager_connectivity_check_get_uri (NMManager *manager) -{ - return nmdbus_manager_get_connectivity_check_uri (NM_MANAGER_GET_PRIVATE (manager)->proxy); -} - -NMClientPermissionResult -nm_manager_get_permission_result (NMManager *manager, NMClientPermission permission) -{ - gpointer result; - - g_return_val_if_fail (NM_IS_MANAGER (manager), NM_CLIENT_PERMISSION_RESULT_UNKNOWN); - - result = g_hash_table_lookup (NM_MANAGER_GET_PRIVATE (manager)->permissions, - GUINT_TO_POINTER (permission)); - return GPOINTER_TO_UINT (result); -} - -NMConnectivityState -nm_manager_get_connectivity (NMManager *manager) -{ - g_return_val_if_fail (NM_IS_MANAGER (manager), NM_CONNECTIVITY_UNKNOWN); - - return NM_MANAGER_GET_PRIVATE (manager)->connectivity; -} - -void -_nm_manager_set_connectivity_hack (NMManager *manager, - guint32 connectivity) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); - - if ((NMConnectivityState) connectivity != priv->connectivity) { - priv->connectivity = (NMConnectivityState) connectivity; - _notify (manager, PROP_CONNECTIVITY); - } -} - -/*****************************************************************************/ -/* Devices */ -/*****************************************************************************/ - -const GPtrArray * -nm_manager_get_devices (NMManager *manager) -{ - g_return_val_if_fail (NM_IS_MANAGER (manager), NULL); - - return NM_MANAGER_GET_PRIVATE (manager)->devices; -} - -const GPtrArray * -nm_manager_get_all_devices (NMManager *manager) -{ - g_return_val_if_fail (NM_IS_MANAGER (manager), NULL); - - return NM_MANAGER_GET_PRIVATE (manager)->all_devices; -} - -NMDevice * -nm_manager_get_device_by_path (NMManager *manager, const char *object_path) -{ - const GPtrArray *devices; - guint i; - - g_return_val_if_fail (NM_IS_MANAGER (manager), NULL); - g_return_val_if_fail (object_path, NULL); - - devices = nm_manager_get_devices (manager); - for (i = 0; i < devices->len; i++) { - NMDevice *candidate = g_ptr_array_index (devices, i); - if (!strcmp (nm_object_get_path (NM_OBJECT (candidate)), object_path)) { - return candidate; - } - } - return NULL; -} - -static NMCheckpoint * -get_checkpoint_by_path (NMManager *manager, const char *object_path) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); - NMCheckpoint *candidate; - guint i; - - for (i = 0; i < priv->checkpoints->len; i++) { - candidate = priv->checkpoints->pdata[i]; - if (nm_streq (nm_object_get_path (NM_OBJECT (candidate)), object_path)) - return candidate; - } - return NULL; -} - -NMDevice * -nm_manager_get_device_by_iface (NMManager *manager, const char *iface) -{ - const GPtrArray *devices; - int i; - NMDevice *device = NULL; - - g_return_val_if_fail (NM_IS_MANAGER (manager), NULL); - g_return_val_if_fail (iface, NULL); - - devices = nm_manager_get_devices (manager); - for (i = 0; i < devices->len; i++) { - NMDevice *candidate = g_ptr_array_index (devices, i); - if (!strcmp (nm_device_get_iface (candidate), iface)) { - device = candidate; - break; - } - } - - return device; -} - -/*****************************************************************************/ -/* Active Connections */ -/*****************************************************************************/ - -const GPtrArray * -nm_manager_get_active_connections (NMManager *manager) -{ - g_return_val_if_fail (NM_IS_MANAGER (manager), NULL); - - return NM_MANAGER_GET_PRIVATE (manager)->active_connections; -} - -NMActiveConnection * -nm_manager_get_primary_connection (NMManager *manager) -{ - g_return_val_if_fail (NM_IS_MANAGER (manager), NULL); - - return NM_MANAGER_GET_PRIVATE (manager)->primary_connection; -} - -NMActiveConnection * -nm_manager_get_activating_connection (NMManager *manager) -{ - g_return_val_if_fail (NM_IS_MANAGER (manager), NULL); - - return NM_MANAGER_GET_PRIVATE (manager)->activating_connection; -} - -typedef enum { - ACTIVATE_TYPE_ACTIVATE_CONNECTION, - ACTIVATE_TYPE_ADD_AND_ACTIVATE_CONNECTION, - ACTIVATE_TYPE_ADD_AND_ACTIVATE_CONNECTION2, -} ActivateType; - -typedef struct { - CList lst; - NMManager *manager; - GTask *task; - char *active_path; - GVariant *add_and_activate_output; - gulong cancelled_id; - ActivateType activate_type; -} ActivateInfo; - -_NMActivateResult * -_nm_activate_result_new (NMActiveConnection *active, - GVariant *add_and_activate_output) -{ - _NMActivateResult *r; - - nm_assert (!add_and_activate_output || g_variant_is_of_type (add_and_activate_output, G_VARIANT_TYPE ("a{sv}"))); - nm_assert (!add_and_activate_output || !g_variant_is_floating (add_and_activate_output)); - - r = g_slice_new (_NMActivateResult); - *r = (_NMActivateResult) { - .active = g_object_ref (active), - .add_and_activate_output = g_steal_pointer (&add_and_activate_output), - }; - return r; -} - -void -_nm_activate_result_free (_NMActivateResult *result) -{ - nm_g_object_unref (result->active); - nm_g_variant_unref (result->add_and_activate_output); - g_slice_free (_NMActivateResult, result); -} - -static void -activate_info_complete (ActivateInfo *info, - NMActiveConnection *active, - GError *error) -{ - nm_assert (info); - nm_assert (info->task); - nm_assert (G_IS_TASK (info->task)); - nm_assert ((!error) != (!active)); - - c_list_unlink_stale (&info->lst); - - nm_clear_g_signal_handler (g_task_get_cancellable (info->task), &info->cancelled_id); - - if (error) - g_task_return_error (info->task, error); - else { - g_task_return_pointer (info->task, - _nm_activate_result_new (active, - g_steal_pointer (&info->add_and_activate_output)), - (GDestroyNotify) _nm_activate_result_free); - } - - nm_g_variant_unref (info->add_and_activate_output); - g_free (info->active_path); - g_object_unref (info->task); - g_slice_free (ActivateInfo, info); -} - -static NMActiveConnection * -find_active_connection_by_path (NMManager *self, const char *ac_path) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - int i; - - for (i = 0; i < priv->active_connections->len; i++) { - NMActiveConnection *candidate = g_ptr_array_index (priv->active_connections, i); - const char *candidate_path = nm_object_get_path (NM_OBJECT (candidate)); - - if (g_strcmp0 (ac_path, candidate_path) == 0) - return candidate; - } - - return NULL; -} - -static void -_wait_for_active_connections_check (NMManager *self) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - CList *iter; - NMActiveConnection *candidate; - const GPtrArray *devices; - NMDevice *device; - GDBusObjectManager *object_manager; - - object_manager = _nm_object_get_dbus_object_manager (NM_OBJECT (self)); - - /* For each pending activation, look for an active connection that has the - * pending activation's object path, where the active connection and its - * device have both updated their properties to point to each other, and - * call the pending connection's callback. - */ -again: - c_list_for_each (iter, &priv->wait_for_active_connection_lst_head) { - ActivateInfo *info = c_list_entry (iter, ActivateInfo, lst); - gs_unref_object GDBusObject *dbus_obj = NULL; - - nm_assert (info->active_path); - - /* Check that the object manager still knows about the object. - * It could be that it vanished before we even learned its name. */ - dbus_obj = g_dbus_object_manager_get_object (object_manager, info->active_path); - if (!dbus_obj) { - activate_info_complete (info, - NULL, - g_error_new_literal (NM_CLIENT_ERROR, - NM_CLIENT_ERROR_OBJECT_CREATION_FAILED, - _("Active connection removed before it was initialized"))); - goto again; - } - - candidate = find_active_connection_by_path (self, info->active_path); - if (!candidate) - continue; - - /* Check that the AC and device are both ready */ - devices = nm_active_connection_get_devices (candidate); - if (devices->len == 0) - continue; - - if (!NM_IS_VPN_CONNECTION (candidate)) { - device = devices->pdata[0]; - if (nm_device_get_active_connection (device) != candidate) - continue; - } - - activate_info_complete (info, candidate, NULL); - goto again; - } -} - -static void -_wait_for_active_connection_cancelled_cb (GCancellable *cancellable, - gpointer user_data) -{ - ActivateInfo *info = user_data; - gs_free_error GError *error = NULL; - - if (!g_cancellable_set_error_if_cancelled (cancellable, &error)) - return; - - activate_info_complete (info, NULL, g_steal_pointer (&error)); -} - -void -nm_manager_wait_for_active_connection (NMManager *self, - const char *active_path, - const char *connection_path, - GVariant *add_and_activate_output_take, - GTask *task_take) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - gs_unref_object GTask *task = task_take; - gs_unref_variant GVariant *add_and_activate_output = add_and_activate_output_take; - ActivateInfo *info; - GCancellable *cancellable; - - nm_assert (NM_IS_MANAGER (self)); - nm_assert (active_path); - nm_assert (G_IS_TASK (task)); - - /* FIXME: there is no timeout for how long we wait. But this entire - * code will be reworked, also that we have a suitable GMainContext - * where we can schedule the timeout (we shouldn't use g_main_context_default()). */ - - info = g_slice_new (ActivateInfo); - *info = (ActivateInfo) { - .manager = g_object_ref (self), - .task = g_steal_pointer (&task), - .active_path = g_strdup (active_path), - .add_and_activate_output = g_steal_pointer (&add_and_activate_output), - }; - c_list_link_tail (&priv->wait_for_active_connection_lst_head, &info->lst); - - cancellable = g_task_get_cancellable (info->task); - if (cancellable) { - info->cancelled_id = g_signal_connect (cancellable, - "cancelled", - G_CALLBACK (_wait_for_active_connection_cancelled_cb), - info); - if (g_cancellable_is_cancelled (cancellable)) { - _wait_for_active_connection_cancelled_cb (cancellable, info); - return; - } - } - - _wait_for_active_connections_check (self); -} - -static void -device_ac_changed (GObject *object, GParamSpec *pspec, gpointer user_data) -{ - _wait_for_active_connections_check (user_data); -} - -static void -device_added (NMManager *self, NMDevice *device) -{ - g_signal_connect_object (device, "notify::" NM_DEVICE_ACTIVE_CONNECTION, - G_CALLBACK (device_ac_changed), self, 0); -} - -static void -device_removed (NMManager *self, NMDevice *device) -{ - g_signal_handlers_disconnect_by_func (device, G_CALLBACK (device_ac_changed), self); -} - -static void -ac_devices_changed (GObject *object, GParamSpec *pspec, gpointer user_data) -{ - _wait_for_active_connections_check (user_data); -} - -static void -active_connection_added (NMManager *self, NMActiveConnection *ac) -{ - g_signal_connect_object (ac, "notify::" NM_ACTIVE_CONNECTION_DEVICES, - G_CALLBACK (ac_devices_changed), self, 0); - _wait_for_active_connections_check (self); -} - -static void -active_connection_removed (NMManager *self, NMActiveConnection *ac) -{ - g_signal_handlers_disconnect_by_func (ac, G_CALLBACK (ac_devices_changed), self); - _wait_for_active_connections_check (self); -} - -static void -checkpoint_added (NMManager *manager, NMCheckpoint *checkpoint) -{ - CheckpointInfo *info; - - info = _wait_for_checkpoint_find_info (manager, nm_object_get_path (NM_OBJECT (checkpoint))); - if (info) - _wait_for_checkpoint_complete (info, checkpoint, NULL); -} - -/*****************************************************************************/ - -static void -free_active_connections (NMManager *manager) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); - int i; - - if (!priv->active_connections) - return; - - /* Break circular refs */ - for (i = 0; i < priv->active_connections->len; i++) - g_object_run_dispose (G_OBJECT (priv->active_connections->pdata[i])); - g_ptr_array_unref (priv->active_connections); - priv->active_connections = NULL; -} - -/*****************************************************************************/ - -const GPtrArray * -nm_manager_get_checkpoints (NMManager *manager) -{ - g_return_val_if_fail (NM_IS_MANAGER (manager), NULL); - - return NM_MANAGER_GET_PRIVATE (manager)->checkpoints; -} - -static void -_wait_for_checkpoint_cancelled_cb (GCancellable *cancellable, - gpointer user_data) -{ - CheckpointInfo *info = user_data; - gs_free_error GError *error = NULL; - - if (!g_cancellable_set_error_if_cancelled (cancellable, &error)) - return; - - _wait_for_checkpoint_complete (info, NULL, g_steal_pointer (&error)); -} - -void -nm_manager_wait_for_checkpoint (NMManager *self, - const char *checkpoint_path, - GTask *task_take) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - gs_unref_object GTask *task = task_take; - CheckpointInfo *info; - GCancellable *cancellable; - NMCheckpoint *checkpoint; - - checkpoint = get_checkpoint_by_path (self, checkpoint_path); - if (checkpoint) { - g_task_return_pointer (task, g_object_ref (checkpoint), g_object_unref); - return; - } - - /* FIXME: there is no timeout for how long we wait. But this entire - * code will be reworked, also that we have a suitable GMainContext - * where we can schedule the timeout (we shouldn't use g_main_context_default()). */ - - info = g_slice_new (CheckpointInfo); - *info = (CheckpointInfo) { - .self = g_object_ref (self), - .task = g_steal_pointer (&task), - .checkpoint_path = g_strdup (checkpoint_path), - }; - c_list_link_tail (&priv->wait_for_checkpoint_lst_head, &info->lst); - - cancellable = g_task_get_cancellable (info->task); - if (cancellable) { - info->cancelled_id = g_signal_connect (cancellable, - "cancelled", - G_CALLBACK (_wait_for_checkpoint_cancelled_cb), - info); - if (g_cancellable_is_cancelled (cancellable)) { - _wait_for_checkpoint_cancelled_cb (cancellable, info); - return; - } - } -} - -/*****************************************************************************/ - -static void -constructed (GObject *object) -{ - G_OBJECT_CLASS (nm_manager_parent_class)->constructed (object); - - g_signal_connect (object, "notify::" NM_MANAGER_WIRELESS_ENABLED, - G_CALLBACK (wireless_enabled_cb), NULL); -} - -static gboolean -init_sync (GInitable *initable, GCancellable *cancellable, GError **error) -{ - NMManager *self = NM_MANAGER (initable); - gs_unref_variant GVariant *permissions = NULL; - const char *name_owner; - - if (!nm_manager_parent_initable_iface->init (initable, cancellable, error)) - g_return_val_if_reached (FALSE); - - name_owner = _nm_object_get_dbus_name_owner (self); - if (name_owner) { - gs_unref_variant GVariant *ret = NULL; - - ret = g_dbus_connection_call_sync (_nm_object_get_dbus_connection (self), - name_owner, - NM_DBUS_PATH, - NM_DBUS_INTERFACE, - "GetPermissions", - g_variant_new ("()"), - G_VARIANT_TYPE ("(a{ss})"), - G_DBUS_CALL_FLAGS_NONE, - NM_DBUS_DEFAULT_TIMEOUT_MSEC, - cancellable, - NULL); - if (ret) { - g_variant_get (ret, - "(@a{ss})", - &permissions); - } - } - update_permissions (self, permissions); - - return TRUE; -} - -typedef struct { - NMManager *manager; - GCancellable *cancellable; - GSimpleAsyncResult *result; -} NMManagerInitData; - -static void -init_async_complete (NMManagerInitData *init_data) -{ - g_simple_async_result_complete (init_data->result); - g_object_unref (init_data->result); - g_clear_object (&init_data->cancellable); - g_slice_free (NMManagerInitData, init_data); -} - -static void -init_async_parent_inited (GObject *source, GAsyncResult *result, gpointer user_data) -{ - NMManagerInitData *init_data = user_data; - GError *error = NULL; - - if (!nm_manager_parent_async_initable_iface->init_finish (G_ASYNC_INITABLE (source), result, &error)) { - g_simple_async_result_take_error (init_data->result, error); - init_async_complete (init_data); - return; - } - - manager_recheck_permissions (NULL, init_data->manager); - - init_async_complete (init_data); -} - -static void -init_async (GAsyncInitable *initable, int io_priority, - GCancellable *cancellable, GAsyncReadyCallback callback, - gpointer user_data) -{ - NMManagerInitData *init_data; - - init_data = g_slice_new0 (NMManagerInitData); - init_data->manager = NM_MANAGER (initable); - init_data->cancellable = cancellable ? g_object_ref (cancellable) : NULL; - init_data->result = g_simple_async_result_new (G_OBJECT (initable), callback, - user_data, init_async); - if (cancellable) - g_simple_async_result_set_check_cancellable (init_data->result, cancellable); - g_simple_async_result_set_op_res_gboolean (init_data->result, TRUE); - - nm_manager_parent_async_initable_iface->init_async (initable, io_priority, cancellable, - init_async_parent_inited, init_data); -} - -static gboolean -init_finish (GAsyncInitable *initable, GAsyncResult *result, GError **error) -{ - GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result); - - if (g_simple_async_result_propagate_error (simple, error)) - return FALSE; - else - return TRUE; -} - -static void -dispose (GObject *object) -{ - NMManager *manager = NM_MANAGER (object); - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (object); - - nm_assert (c_list_is_empty (&priv->wait_for_active_connection_lst_head)); - nm_assert (c_list_is_empty (&priv->wait_for_checkpoint_lst_head)); - - nm_clear_g_cancellable (&priv->perm_call_cancellable); - - if (priv->devices) { - g_ptr_array_unref (priv->devices); - priv->devices = NULL; - } - if (priv->all_devices) { - g_ptr_array_unref (priv->all_devices); - priv->all_devices = NULL; - } - - nm_clear_pointer (&priv->checkpoints, g_ptr_array_unref); - - free_active_connections (manager); - g_clear_object (&priv->primary_connection); - g_clear_object (&priv->activating_connection); - - g_clear_object (&priv->proxy); - - g_hash_table_destroy (priv->permissions); - priv->permissions = NULL; - - G_OBJECT_CLASS (nm_manager_parent_class)->dispose (object); -} - -static void -finalize (GObject *object) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (object); - - g_free (priv->version); - - G_OBJECT_CLASS (nm_manager_parent_class)->finalize (object); -} - -static void -set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (object); - gboolean b; - const char *name_owner; - - switch (prop_id) { - case PROP_NETWORKING_ENABLED: - b = g_value_get_boolean (value); - if (priv->networking_enabled != b) { - if ((name_owner = _nm_object_get_dbus_name_owner (object))) { - _nm_manager_networking_set_enabled (_nm_object_get_dbus_connection (object), - name_owner, - b, - NULL); - } - /* Let the property value flip when we get the change signal from NM */ - } - break; - case PROP_WIRELESS_ENABLED: - b = g_value_get_boolean (value); - if (priv->wireless_enabled != b) { - nm_manager_wireless_set_enabled (NM_MANAGER (object), b); - /* Let the property value flip when we get the change signal from NM */ - } - break; - case PROP_WWAN_ENABLED: - b = g_value_get_boolean (value); - if (priv->wwan_enabled != b) { - nm_manager_wwan_set_enabled (NM_MANAGER (object), b); - /* Let the property value flip when we get the change signal from NM */ - } - break; - case PROP_WIMAX_ENABLED: - b = g_value_get_boolean (value); - if (priv->wimax_enabled != b) { - nm_manager_wimax_set_enabled (NM_MANAGER (object), b); - /* Let the property value flip when we get the change signal from NM */ - } - break; - case PROP_CONNECTIVITY_CHECK_ENABLED: - b = g_value_get_boolean (value); - if (priv->connectivity_check_enabled != b) { - nm_manager_connectivity_check_set_enabled (NM_MANAGER (object), b); - /* Let the property value flip when we get the change signal from NM */ - } - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - NMManager *self = NM_MANAGER (object); - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - - switch (prop_id) { - case PROP_VERSION: - g_value_set_string (value, nm_manager_get_version (self)); - break; - case PROP_STATE: - g_value_set_enum (value, nm_manager_get_state (self)); - break; - case PROP_STARTUP: - g_value_set_boolean (value, nm_manager_get_startup (self)); - break; - case PROP_NETWORKING_ENABLED: - g_value_set_boolean (value, nm_manager_networking_get_enabled (self)); - break; - case PROP_WIRELESS_ENABLED: - g_value_set_boolean (value, priv->wireless_enabled); - break; - case PROP_WIRELESS_HARDWARE_ENABLED: - g_value_set_boolean (value, priv->wireless_hw_enabled); - break; - case PROP_WWAN_ENABLED: - g_value_set_boolean (value, priv->wwan_enabled); - break; - case PROP_WWAN_HARDWARE_ENABLED: - g_value_set_boolean (value, priv->wwan_hw_enabled); - break; - case PROP_WIMAX_ENABLED: - g_value_set_boolean (value, priv->wimax_enabled); - break; - case PROP_WIMAX_HARDWARE_ENABLED: - g_value_set_boolean (value, priv->wimax_hw_enabled); - break; - case PROP_ACTIVE_CONNECTIONS: - g_value_take_boxed (value, _nm_utils_copy_object_array (nm_manager_get_active_connections (self))); - break; - case PROP_CONNECTIVITY: - g_value_set_enum (value, priv->connectivity); - break; - case PROP_CONNECTIVITY_CHECK_AVAILABLE: - g_value_set_boolean (value, priv->connectivity_check_available); - break; - case PROP_CONNECTIVITY_CHECK_ENABLED: - g_value_set_boolean (value, priv->connectivity_check_enabled); - break; - case PROP_PRIMARY_CONNECTION: - g_value_set_object (value, priv->primary_connection); - break; - case PROP_ACTIVATING_CONNECTION: - g_value_set_object (value, priv->activating_connection); - break; - case PROP_DEVICES: - g_value_take_boxed (value, _nm_utils_copy_object_array (nm_manager_get_devices (self))); - break; - case PROP_CHECKPOINTS: - g_value_take_boxed (value, _nm_utils_copy_object_array (nm_manager_get_checkpoints (self))); - break; - case PROP_METERED: - g_value_set_uint (value, priv->metered); - break; - case PROP_ALL_DEVICES: - g_value_take_boxed (value, _nm_utils_copy_object_array (nm_manager_get_all_devices (self))); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -nm_manager_class_init (NMManagerClass *manager_class) -{ - GObjectClass *object_class = G_OBJECT_CLASS (manager_class); - NMObjectClass *nm_object_class = NM_OBJECT_CLASS (manager_class); - - g_type_class_add_private (manager_class, sizeof (NMManagerPrivate)); - - object_class->constructed = constructed; - object_class->set_property = set_property; - object_class->get_property = get_property; - object_class->dispose = dispose; - object_class->finalize = finalize; - - nm_object_class->init_dbus = init_dbus; - nm_object_class->object_creation_failed = object_creation_failed; - - manager_class->device_added = device_added; - manager_class->device_removed = device_removed; - manager_class->active_connection_added = active_connection_added; - manager_class->active_connection_removed = active_connection_removed; - manager_class->checkpoint_added = checkpoint_added; - - obj_properties[PROP_VERSION] = - g_param_spec_string (NM_MANAGER_VERSION, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - obj_properties[PROP_STATE] = - g_param_spec_enum (NM_CLIENT_STATE, "", "", - NM_TYPE_STATE, - NM_STATE_UNKNOWN, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - obj_properties[PROP_STARTUP] = - g_param_spec_boolean (NM_MANAGER_STARTUP, "", "", - FALSE, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - obj_properties[PROP_NETWORKING_ENABLED] = - g_param_spec_boolean (NM_MANAGER_NETWORKING_ENABLED, "", "", - TRUE, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS); - obj_properties[PROP_WIRELESS_ENABLED] = - g_param_spec_boolean (NM_MANAGER_WIRELESS_ENABLED, "", "", - FALSE, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS); - obj_properties[PROP_WIRELESS_HARDWARE_ENABLED] = - g_param_spec_boolean (NM_MANAGER_WIRELESS_HARDWARE_ENABLED, "", "", - TRUE, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - obj_properties[PROP_WWAN_ENABLED] = - g_param_spec_boolean (NM_MANAGER_WWAN_ENABLED, "", "", - FALSE, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS); - obj_properties[PROP_WWAN_HARDWARE_ENABLED] = - g_param_spec_boolean (NM_MANAGER_WWAN_HARDWARE_ENABLED, "", "", - FALSE, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - obj_properties[PROP_WIMAX_ENABLED] = - g_param_spec_boolean (NM_MANAGER_WIMAX_ENABLED, "", "", - FALSE, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS); - obj_properties[PROP_WIMAX_HARDWARE_ENABLED] = - g_param_spec_boolean (NM_MANAGER_WIMAX_HARDWARE_ENABLED, "", "", - FALSE, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - obj_properties[PROP_ACTIVE_CONNECTIONS] = - g_param_spec_boxed (NM_MANAGER_ACTIVE_CONNECTIONS, "", "", - G_TYPE_PTR_ARRAY, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - obj_properties[PROP_CONNECTIVITY] = - g_param_spec_enum (NM_CLIENT_CONNECTIVITY, "", "", - NM_TYPE_CONNECTIVITY_STATE, - NM_CONNECTIVITY_UNKNOWN, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - obj_properties[PROP_CONNECTIVITY_CHECK_AVAILABLE] = - g_param_spec_boolean (NM_MANAGER_CONNECTIVITY_CHECK_AVAILABLE, "", "", - FALSE, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - obj_properties[PROP_CONNECTIVITY_CHECK_ENABLED] = - g_param_spec_boolean (NM_MANAGER_CONNECTIVITY_CHECK_ENABLED, "", "", - FALSE, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS); - obj_properties[PROP_PRIMARY_CONNECTION] = - g_param_spec_object (NM_MANAGER_PRIMARY_CONNECTION, "", "", - NM_TYPE_ACTIVE_CONNECTION, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - obj_properties[PROP_ACTIVATING_CONNECTION] = - g_param_spec_object (NM_MANAGER_ACTIVATING_CONNECTION, "", "", - NM_TYPE_ACTIVE_CONNECTION, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - obj_properties[PROP_DEVICES] = - g_param_spec_boxed (NM_MANAGER_DEVICES, "", "", - G_TYPE_PTR_ARRAY, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - obj_properties[PROP_CHECKPOINTS] = - g_param_spec_boxed (NM_MANAGER_CHECKPOINTS, "", "", - G_TYPE_PTR_ARRAY, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - /** - * NMManager:metered: - * - * Whether the connectivity is metered. - * - * Since: 1.2 - **/ - obj_properties[PROP_METERED] = - g_param_spec_uint (NM_MANAGER_METERED, "", "", - 0, G_MAXUINT32, NM_METERED_UNKNOWN, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_ALL_DEVICES] = - g_param_spec_boxed (NM_MANAGER_ALL_DEVICES, "", "", - G_TYPE_PTR_ARRAY, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - signals[DEVICE_ADDED] = - g_signal_new ("device-added", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMManagerClass, device_added), - NULL, NULL, NULL, - G_TYPE_NONE, 1, - G_TYPE_OBJECT); - signals[DEVICE_REMOVED] = - g_signal_new ("device-removed", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMManagerClass, device_removed), - NULL, NULL, NULL, - G_TYPE_NONE, 1, - G_TYPE_OBJECT); - signals[ANY_DEVICE_ADDED] = - g_signal_new ("any-device-added", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 1, - G_TYPE_OBJECT); - signals[ANY_DEVICE_REMOVED] = - g_signal_new ("any-device-removed", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 1, - G_TYPE_OBJECT); - signals[ACTIVE_CONNECTION_ADDED] = - g_signal_new ("active-connection-added", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMManagerClass, active_connection_added), - NULL, NULL, NULL, - G_TYPE_NONE, 1, - G_TYPE_OBJECT); - signals[ACTIVE_CONNECTION_REMOVED] = - g_signal_new ("active-connection-removed", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMManagerClass, active_connection_removed), - NULL, NULL, NULL, - G_TYPE_NONE, 1, - G_TYPE_OBJECT); - signals[CHECKPOINT_ADDED] = - g_signal_new ("checkpoint-added", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMManagerClass, checkpoint_added), - NULL, NULL, NULL, - G_TYPE_NONE, 1, - G_TYPE_OBJECT); - signals[CHECKPOINT_REMOVED] = - g_signal_new ("checkpoint-removed", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMManagerClass, checkpoint_removed), - NULL, NULL, NULL, - G_TYPE_NONE, 1, - G_TYPE_OBJECT); - - signals[PERMISSION_CHANGED] = - g_signal_new ("permission-changed", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT); -} - -static void -nm_manager_initable_iface_init (GInitableIface *iface) -{ - nm_manager_parent_initable_iface = g_type_interface_peek_parent (iface); - - iface->init = init_sync; -} - -static void -nm_manager_async_initable_iface_init (GAsyncInitableIface *iface) -{ - nm_manager_parent_async_initable_iface = g_type_interface_peek_parent (iface); - - iface->init_async = init_async; - iface->init_finish = init_finish; -} diff --git a/libnm/nm-manager.h b/libnm/nm-manager.h deleted file mode 100644 index 8c28cbe50d..0000000000 --- a/libnm/nm-manager.h +++ /dev/null @@ -1,166 +0,0 @@ -// SPDX-License-Identifier: LGPL-2.1+ -/* - * Copyright (C) 2007 - 2008 Novell, Inc. - * Copyright (C) 2007 - 2014 Red Hat, Inc. - */ - -#ifndef __NM_MANAGER_H__ -#define __NM_MANAGER_H__ - -#if !((NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_PRIVATE) -#error Cannot use this header. -#endif - -#include "nm-object.h" -#include "nm-client.h" - -#define NM_TYPE_MANAGER (nm_manager_get_type ()) -#define NM_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_MANAGER, NMManager)) -#define NM_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_MANAGER, NMManagerClass)) -#define NM_IS_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_MANAGER)) -#define NM_IS_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_MANAGER)) -#define NM_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_MANAGER, NMManagerClass)) - -#define NM_MANAGER_VERSION "version" -#define NM_MANAGER_STATE "state" -#define NM_MANAGER_STARTUP "startup" -#define NM_MANAGER_NETWORKING_ENABLED "networking-enabled" - -_NM_DEPRECATED_SYNC_WRITABLE_PROPERTY_INTERNAL -#define NM_MANAGER_WIRELESS_ENABLED "wireless-enabled" - -_NM_DEPRECATED_SYNC_WRITABLE_PROPERTY_INTERNAL -#define NM_MANAGER_WWAN_ENABLED "wwan-enabled" - -_NM_DEPRECATED_SYNC_WRITABLE_PROPERTY_INTERNAL -#define NM_MANAGER_WIMAX_ENABLED "wimax-enabled" - -#define NM_MANAGER_WIRELESS_HARDWARE_ENABLED "wireless-hardware-enabled" -#define NM_MANAGER_WWAN_HARDWARE_ENABLED "wwan-hardware-enabled" -#define NM_MANAGER_WIMAX_HARDWARE_ENABLED "wimax-hardware-enabled" -#define NM_MANAGER_ACTIVE_CONNECTIONS "active-connections" -#define NM_MANAGER_CONNECTIVITY "connectivity" -#define NM_MANAGER_CONNECTIVITY_CHECK_AVAILABLE "connectivity-check-available" - -_NM_DEPRECATED_SYNC_WRITABLE_PROPERTY_INTERNAL -#define NM_MANAGER_CONNECTIVITY_CHECK_ENABLED "connectivity-check-enabled" - -#define NM_MANAGER_PRIMARY_CONNECTION "primary-connection" -#define NM_MANAGER_ACTIVATING_CONNECTION "activating-connection" -#define NM_MANAGER_DEVICES "devices" -#define NM_MANAGER_CHECKPOINTS "checkpoints" -#define NM_MANAGER_METERED "metered" -#define NM_MANAGER_ALL_DEVICES "all-devices" - -/** - * NMManager: - */ -typedef struct { - NMObject parent; -} NMManager; - -typedef struct { - NMObjectClass parent; - - /* Signals */ - void (*device_added) (NMManager *manager, NMDevice *device); - void (*device_removed) (NMManager *manager, NMDevice *device); - void (*active_connection_added) (NMManager *manager, NMActiveConnection *ac); - void (*active_connection_removed) (NMManager *manager, NMActiveConnection *ac); - void (*checkpoint_added) (NMManager *manager, NMCheckpoint *checkpoint); - void (*checkpoint_removed) (NMManager *manager, NMCheckpoint *checkpoint); - void (*permission_changed) (NMManager *manager, - NMClientPermission permission, - NMClientPermissionResult result); -} NMManagerClass; - -GType nm_manager_get_type (void); - -const char *nm_manager_get_version (NMManager *manager); -NMState nm_manager_get_state (NMManager *manager); -gboolean nm_manager_get_startup (NMManager *manager); - -gboolean nm_manager_networking_get_enabled (NMManager *manager); - -_NM_DEPRECATED_SYNC_METHOD_INTERNAL -gboolean _nm_manager_networking_set_enabled (GDBusConnection *dbus_connection, - const char *name_owner, - gboolean enable, - GError **error); - -gboolean nm_manager_wireless_get_enabled (NMManager *manager); - -_NM_DEPRECATED_SYNC_METHOD_INTERNAL -void nm_manager_wireless_set_enabled (NMManager *manager, gboolean enabled); - -gboolean nm_manager_wireless_hardware_get_enabled (NMManager *manager); - -gboolean nm_manager_wwan_get_enabled (NMManager *manager); -void nm_manager_wwan_set_enabled (NMManager *manager, gboolean enabled); -gboolean nm_manager_wwan_hardware_get_enabled (NMManager *manager); - -gboolean nm_manager_wimax_get_enabled (NMManager *manager); -void nm_manager_wimax_set_enabled (NMManager *manager, gboolean enabled); -gboolean nm_manager_wimax_hardware_get_enabled (NMManager *manager); - -gboolean nm_manager_connectivity_check_get_available (NMManager *manager); - -gboolean nm_manager_connectivity_check_get_enabled (NMManager *manager); - -void nm_manager_connectivity_check_set_enabled (NMManager *manager, - gboolean enabled); - -const char *nm_manager_connectivity_check_get_uri (NMManager *manager); - -NMClientPermissionResult nm_manager_get_permission_result (NMManager *manager, - NMClientPermission permission); - -NMConnectivityState nm_manager_get_connectivity (NMManager *manager); - -void _nm_manager_set_connectivity_hack (NMManager *manager, - guint32 connectivity); - -/* Devices */ - -const GPtrArray *nm_manager_get_devices (NMManager *manager); -const GPtrArray *nm_manager_get_all_devices(NMManager *manager); -NMDevice *nm_manager_get_device_by_path (NMManager *manager, const char *object_path); -NMDevice *nm_manager_get_device_by_iface (NMManager *manager, const char *iface); - -/* Active Connections */ - -const GPtrArray *nm_manager_get_active_connections (NMManager *manager); - -NMActiveConnection *nm_manager_get_primary_connection (NMManager *manager); -NMActiveConnection *nm_manager_get_activating_connection (NMManager *manager); - -void nm_manager_wait_for_active_connection (NMManager *self, - const char *active_path, - const char *connection_path, - GVariant *add_and_activate_output_take, - GTask *task_take); - -const GPtrArray *nm_manager_get_checkpoints (NMManager *manager); - -void nm_manager_wait_for_checkpoint (NMManager *self, - const char *checkpoint_path, - GTask *task_take); - -/*****************************************************************************/ - -typedef struct { - NMActiveConnection *active; - GVariant *add_and_activate_output; -} _NMActivateResult; - -_NMActivateResult *_nm_activate_result_new (NMActiveConnection *active, - GVariant *add_and_activate_output); - -void _nm_activate_result_free (_NMActivateResult *result); - -NM_AUTO_DEFINE_FCN0 (_NMActivateResult *, _nm_auto_free_activate_result, _nm_activate_result_free) -#define nm_auto_free_activate_result nm_auto(_nm_auto_free_activate_result) - -/*****************************************************************************/ - -#endif /* __NM_MANAGER_H__ */ diff --git a/libnm/nm-object-private.h b/libnm/nm-object-private.h index 863b228fae..565329502f 100644 --- a/libnm/nm-object-private.h +++ b/libnm/nm-object-private.h @@ -12,86 +12,4 @@ #include "nm-object.h" -typedef gboolean (*PropertyMarshalFunc) (NMObject *, GParamSpec *, GVariant *, gpointer); - -typedef GObject * (*NMObjectCreatorFunc) (GDBusConnection *, const char *); - -typedef struct { - const char *name; - gpointer field; - PropertyMarshalFunc func; - GType object_type; - const char *signal_prefix; -} NMPropertiesInfo; - -void _nm_object_register_properties (NMObject *object, - const char *interface, - const NMPropertiesInfo *info); - -void _nm_object_queue_notify (NMObject *object, const char *property); - -GDBusObjectManager *_nm_object_get_dbus_object_manager (NMObject *object); - -GQuark _nm_object_obj_nm_quark (void); - -GDBusConnection *_nm_object_get_dbus_connection (gpointer self); - -const char *_nm_object_get_dbus_name_owner (gpointer self); - -GDBusConnection *_nm_client_get_dbus_connection (NMClient *client); - -const char *_nm_client_get_dbus_name_owner (NMClient *client); - -void _nm_object_dbus_call (gpointer self, - gpointer source_tag, - GCancellable *cancellable, - GAsyncReadyCallback user_callback, - gpointer user_callback_data, - const char *object_path, - const char *interface_name, - const char *method_name, - GVariant *parameters, - const GVariantType *reply_type, - GDBusCallFlags flags, - int timeout_msec, - GAsyncReadyCallback internal_callback); - -GVariant *_nm_object_dbus_call_sync (gpointer self, - GCancellable *cancellable, - const char *object_path, - const char *interface_name, - const char *method_name, - GVariant *parameters, - const GVariantType *reply_type, - GDBusCallFlags flags, - int timeout_msec, - gboolean strip_dbus_error, - GError **error); - -gboolean _nm_object_dbus_call_sync_void (gpointer self, - GCancellable *cancellable, - const char *object_path, - const char *interface_name, - const char *method_name, - GVariant *parameters, - GDBusCallFlags flags, - int timeout_msec, - gboolean strip_dbus_error, - GError **error); - -void _nm_object_set_property (NMObject *object, - const char *interface, - const char *prop_name, - const char *format_string, - ...); - -GDBusProxy *_nm_object_get_proxy (NMObject *object, - const char *interface); - -GError *_nm_object_new_error_nm_not_running (void); -void _nm_object_set_error_nm_not_running (GError **error); - -struct udev; -void _nm_device_set_udev (NMDevice *device, struct udev *udev); - #endif /* __NM_OBJECT_PRIVATE_H__ */ diff --git a/libnm/nm-object.c b/libnm/nm-object.c index a49a905859..10931a89b9 100644 --- a/libnm/nm-object.c +++ b/libnm/nm-object.c @@ -21,72 +21,54 @@ /*****************************************************************************/ -static gboolean debug = FALSE; -#define dbgmsg(f,...) if (G_UNLIKELY (debug)) { g_message (f, ## __VA_ARGS__ ); } - -NM_CACHED_QUARK_FCN ("nm-obj-nm", _nm_object_obj_nm_quark) - -/*****************************************************************************/ - NM_GOBJECT_PROPERTIES_DEFINE_BASE ( PROP_PATH, - PROP_DBUS_CONNECTION, - PROP_DBUS_OBJECT, - PROP_DBUS_OBJECT_MANAGER, ); -typedef struct { - PropertyMarshalFunc func; - GType object_type; - gpointer field; - const char *signal_prefix; -} PropertyInfo; - typedef struct _NMObjectPrivate { - GDBusObject *object; - GDBusObjectManager *object_manager; - - GSList *property_tables; - NMObject *parent; - - gboolean inited; /* async init finished? */ - GSList *waiters; /* if async init did not finish, users of this object need - * to defer their notifications by adding themselves here. */ - - CList notify_items; - guint notify_id; - - guint reload_remaining; + NMClient *client; + NMLDBusObject *dbobj; +} NMObjectPrivate; - CList pending; /* ordered list of pending property updates. */ - GPtrArray *proxies; +G_DEFINE_ABSTRACT_TYPE (NMObject, nm_object, G_TYPE_OBJECT); - char *name_owner_cached; -} NMObjectPrivate; +#define NM_OBJECT_GET_PRIVATE(self) _NM_GET_PRIVATE_PTR(self, NMObject, NM_IS_OBJECT) -typedef struct { - GSList *interfaces; -} NMObjectClassPrivate; +static NMObjectClass *_nm_object_class = NULL; -static void nm_object_initable_iface_init (GInitableIface *iface); -static void nm_object_async_initable_iface_init (GAsyncInitableIface *iface); +/*****************************************************************************/ -G_DEFINE_ABSTRACT_TYPE_WITH_CODE (NMObject, nm_object, G_TYPE_OBJECT, - g_type_add_class_private (g_define_type_id, sizeof (NMObjectClassPrivate)); - G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, nm_object_initable_iface_init); - G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, nm_object_async_initable_iface_init); - ) +static gpointer +_nm_object_get_private (NMObjectClass *klass, NMObject *self, guint16 extra_offset) +{ + char *ptr; -#define NM_OBJECT_GET_PRIVATE(self) _NM_GET_PRIVATE_PTR(self, NMObject, NM_IS_OBJECT) + nm_assert (klass->priv_ptr_offset > 0); -#define NM_OBJECT_CLASS_GET_PRIVATE(k) (G_TYPE_CLASS_GET_PRIVATE ((k), NM_TYPE_OBJECT, NMObjectClassPrivate)) + ptr = (char *) self; + ptr += klass->priv_ptr_offset; + if (klass->priv_ptr_indirect) + ptr = *((gpointer *) ptr); + return ptr + extra_offset; +} -/*****************************************************************************/ +NMLDBusObject * +_nm_object_get_dbobj (gpointer self) +{ + return NM_OBJECT_GET_PRIVATE (self)->dbobj; +} -static void reload_complete (NMObject *object, gboolean emit_now); -static gboolean demarshal_generic (NMObject *object, GParamSpec *pspec, GVariant *value, gpointer field); +const char * +_nm_object_get_path (gpointer self) +{ + return NM_OBJECT_GET_PRIVATE (self)->dbobj->dbus_path->str; +} -/*****************************************************************************/ +NMClient * +_nm_object_get_client (gpointer self) +{ + return NM_OBJECT_GET_PRIVATE (self)->client; +} /** * nm_object_get_path: @@ -102,1268 +84,122 @@ nm_object_get_path (NMObject *object) { g_return_val_if_fail (NM_IS_OBJECT (object), NULL); - return g_dbus_object_get_object_path (NM_OBJECT_GET_PRIVATE (object)->object); -} - -/** - * _nm_object_get_proxy: - * @object: an #NMObject - * @interface: a D-Bus interface implemented by @object - * - * Gets the D-Bus proxy for @interface on @object. - * - * Returns: (transfer none): a D-Bus proxy - */ -GDBusProxy * -_nm_object_get_proxy (NMObject *object, - const char *interface) -{ - NMObjectPrivate *priv; - GDBusInterface *proxy; - - g_return_val_if_fail (NM_IS_OBJECT (object), NULL); - - priv = NM_OBJECT_GET_PRIVATE (object); - if (priv->object == NULL) - return NULL; - - proxy = g_dbus_object_get_interface (priv->object, interface); - g_return_val_if_fail (proxy != NULL, NULL); - - return G_DBUS_PROXY (proxy); + return NM_OBJECT_GET_PRIVATE (object)->dbobj->dbus_path->str; } /*****************************************************************************/ -GDBusConnection * -_nm_object_get_dbus_connection (gpointer self) -{ - NMObjectPrivate *priv; - - nm_assert (NM_IS_OBJECT (self)); - - priv = NM_OBJECT_GET_PRIVATE (self); - - return g_dbus_object_manager_client_get_connection (G_DBUS_OBJECT_MANAGER_CLIENT (priv->object_manager)); -} - -const char * -_nm_object_get_dbus_name_owner (gpointer self) +static void +clear_properties (NMObject *self, + NMClient *client) { - NMObjectPrivate *priv; + NMObjectClass *klass = NM_OBJECT_GET_CLASS (self); + const _NMObjectClassFieldInfo *p; + guint16 i; nm_assert (NM_IS_OBJECT (self)); + nm_assert (!client || NM_IS_CLIENT (client)); - priv = NM_OBJECT_GET_PRIVATE (self); - - nm_clear_g_free (&priv->name_owner_cached); - priv->name_owner_cached = g_dbus_object_manager_client_get_name_owner (G_DBUS_OBJECT_MANAGER_CLIENT (priv->object_manager)); - return priv->name_owner_cached; -} + for (p = klass->property_o_info; p; p = p->parent) { + NMLDBusPropertyO *fields = _nm_object_get_private (p->klass, self, p->offset); -static gboolean -_get_dbus_params (gpointer self, - GDBusConnection **out_dbus_connection, - const char **out_name_owner) -{ - const char *name_owner; - GDBusConnection *dbus_connection = NULL; - - if (NM_IS_OBJECT (self)) { - name_owner = _nm_object_get_dbus_name_owner (self); - if (name_owner) - dbus_connection = _nm_object_get_dbus_connection (self); - } else { - nm_assert (NM_IS_CLIENT (self)); - name_owner = _nm_client_get_dbus_name_owner (self); - if (name_owner) - dbus_connection = _nm_client_get_dbus_connection (self); + for (i = 0; i < p->num; i++) + nml_dbus_property_o_clear (&fields[i], client); } - *out_dbus_connection = dbus_connection; - *out_name_owner = name_owner; - return !!name_owner; -} - -void -_nm_object_dbus_call (gpointer self, - gpointer source_tag, - GCancellable *cancellable, - GAsyncReadyCallback user_callback, - gpointer user_callback_data, - const char *object_path, - const char *interface_name, - const char *method_name, - GVariant *parameters, - const GVariantType *reply_type, - GDBusCallFlags flags, - int timeout_msec, - GAsyncReadyCallback internal_callback) -{ - gs_unref_object GTask *task = NULL; - const char *name_owner; - GDBusConnection *dbus_connection; - - nm_assert (G_IS_OBJECT (self)); - nm_assert (source_tag); - nm_assert (!cancellable || G_IS_CANCELLABLE (cancellable)); - nm_assert (internal_callback); - nm_assert (object_path); - nm_assert (interface_name); - nm_assert (method_name); - nm_assert (parameters); - nm_assert (reply_type); - - task = nm_g_task_new (self, cancellable, source_tag, user_callback, user_callback_data); - - if (!_get_dbus_params (self, &dbus_connection, &name_owner)) { - nm_g_variant_unref_floating (parameters); - g_task_return_error (task, _nm_object_new_error_nm_not_running ()); - return; - } - - g_dbus_connection_call (dbus_connection, - name_owner, - object_path, - interface_name, - method_name, - parameters, - reply_type, - flags, - timeout_msec, - cancellable, - internal_callback, - g_steal_pointer (&task)); -} - -GVariant * -_nm_object_dbus_call_sync (gpointer self, - GCancellable *cancellable, - const char *object_path, - const char *interface_name, - const char *method_name, - GVariant *parameters, - const GVariantType *reply_type, - GDBusCallFlags flags, - int timeout_msec, - gboolean strip_dbus_error, - GError **error) -{ - gs_unref_variant GVariant *ret = NULL; - GDBusConnection *dbus_connection; - const char *name_owner; - - nm_assert (G_IS_OBJECT (self)); - nm_assert (!cancellable || G_IS_CANCELLABLE (cancellable)); - nm_assert (!error || !*error); - nm_assert (object_path); - nm_assert (interface_name); - nm_assert (method_name); - nm_assert (parameters); - nm_assert (reply_type); - - if (!_get_dbus_params (self, &dbus_connection, &name_owner)) { - nm_g_variant_unref_floating (parameters); - _nm_object_set_error_nm_not_running (error); - return NULL; - } - - ret = g_dbus_connection_call_sync (dbus_connection, - name_owner, - object_path, - interface_name, - method_name, - parameters, - reply_type, - flags, - timeout_msec, - cancellable, - error); - if (!ret) { - if (error && strip_dbus_error) - g_dbus_error_strip_remote_error (*error); - return NULL; - } - - return g_steal_pointer (&ret); -} - -gboolean -_nm_object_dbus_call_sync_void (gpointer self, - GCancellable *cancellable, - const char *object_path, - const char *interface_name, - const char *method_name, - GVariant *parameters, - GDBusCallFlags flags, - int timeout_msec, - gboolean strip_dbus_error, - GError **error) -{ - gs_unref_variant GVariant *ret = NULL; - - ret = _nm_object_dbus_call_sync (self, - cancellable, - object_path, - interface_name, - method_name, - parameters, - G_VARIANT_TYPE ("()"), - flags, - timeout_msec, - strip_dbus_error, - error); - return !!ret; -} - -/*****************************************************************************/ - -GError * -_nm_object_new_error_nm_not_running (void) -{ - return g_error_new_literal (NM_CLIENT_ERROR, - NM_CLIENT_ERROR_MANAGER_NOT_RUNNING, - "NetworkManager is not running"); -} + for (p = klass->property_ao_info; p; p = p->parent) { + NMLDBusPropertyAO *fields = _nm_object_get_private (p->klass, self, p->offset); -void -_nm_object_set_error_nm_not_running (GError **error) -{ - if (error) { - if (*error) - g_return_if_reached (); - *error = _nm_object_new_error_nm_not_running (); + for (i = 0; i < p->num; i++) + nml_dbus_property_ao_clear (&fields[i], client); } } /*****************************************************************************/ -typedef enum { - NOTIFY_SIGNAL_PENDING_NONE, - NOTIFY_SIGNAL_PENDING_ADDED, - NOTIFY_SIGNAL_PENDING_REMOVED, - NOTIFY_SIGNAL_PENDING_ADDED_REMOVED, -} NotifySignalPending; - -typedef struct { - CList lst; - const char *property; - const char *signal_prefix; - NotifySignalPending pending; - NMObject *changed; -} NotifyItem; - -static void -notify_item_free (NotifyItem *item) -{ - c_list_unlink_stale (&item->lst); - g_clear_object (&item->changed); - g_slice_free (NotifyItem, item); -} - -static gboolean -deferred_notify_cb (gpointer data) +static NMLDBusObjState +is_visible (NMObject *self) { - NMObject *object = NM_OBJECT (data); - NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object); - NMObjectClass *object_class = NM_OBJECT_GET_CLASS (object); - CList props; - CList *iter, *safe; - - priv->notify_id = 0; - - /* Wait until all reloads are done before notifying */ - if (priv->reload_remaining) - return G_SOURCE_REMOVE; + NMObjectClass *klass = NM_OBJECT_GET_CLASS (self); + NMClient *client = _nm_object_get_client (self); + const _NMObjectClassFieldInfo *p; + guint16 i; - /* Clear priv->notify_items early so that an NMObject subclass that - * listens to property changes can queue up other property changes - * during the g_object_notify() call separately from the property - * list we're iterating. - */ - c_list_link_after (&priv->notify_items, &props); - c_list_unlink (&priv->notify_items); + nm_assert (NM_IS_CLIENT (client)); - g_object_ref (object); + for (p = klass->property_o_info; p; p = p->parent) { + NMLDBusPropertyO *fields = _nm_object_get_private (p->klass, self, p->offset); - /* Emit added/removed signals first since some of our internal objects - * use the added/removed signals for new object processing. - */ - c_list_for_each (iter, &props) { - NotifyItem *item = c_list_entry (iter, NotifyItem, lst); - char buf[50]; - int ret = 0; - - switch (item->pending) { - case NOTIFY_SIGNAL_PENDING_ADDED: - ret = g_snprintf (buf, sizeof (buf), "%s-added", item->signal_prefix); - break; - case NOTIFY_SIGNAL_PENDING_REMOVED: - ret = g_snprintf (buf, sizeof (buf), "%s-removed", item->signal_prefix); - break; - case NOTIFY_SIGNAL_PENDING_ADDED_REMOVED: - if (object_class->object_creation_failed) - object_class->object_creation_failed (object, nm_object_get_path (item->changed)); - break; - case NOTIFY_SIGNAL_PENDING_NONE: - default: - break; - } - if (ret > 0) { - g_assert (ret < sizeof (buf)); - g_signal_emit_by_name (object, buf, item->changed); + for (i = 0; i < p->num; i++) { + if (!nml_dbus_property_o_is_ready (&fields[i])) + return NML_DBUS_OBJ_STATE_WITH_NMOBJ_NOT_READY; } } - /* Emit property change notifications second */ - c_list_for_each (iter, &props) { - NotifyItem *item = c_list_entry (iter, NotifyItem, lst); - - if (item->property) - g_object_notify (G_OBJECT (object), item->property); - } - - g_object_unref (object); - - c_list_for_each_safe (iter, safe, &props) - notify_item_free (c_list_entry (iter, NotifyItem, lst)); + for (p = klass->property_ao_info; p; p = p->parent) { + NMLDBusPropertyAO *fields = _nm_object_get_private (p->klass, self, p->offset); - return G_SOURCE_REMOVE; -} - -static void -_nm_object_defer_notify (NMObject *object) -{ - NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object); - - if (!priv->notify_id) - priv->notify_id = g_idle_add_full (G_PRIORITY_LOW, deferred_notify_cb, object, NULL); -} - -static void -_nm_object_queue_notify_full (NMObject *object, - const char *property, - const char *signal_prefix, - gboolean added, - NMObject *changed) -{ - NMObjectPrivate *priv; - NotifyItem *item; - CList *iter; - - g_return_if_fail (NM_IS_OBJECT (object)); - g_return_if_fail (!signal_prefix != !property); - g_return_if_fail (!signal_prefix == !changed); - - priv = NM_OBJECT_GET_PRIVATE (object); - _nm_object_defer_notify (object); - - property = g_intern_string (property); - signal_prefix = g_intern_string (signal_prefix); - c_list_for_each (iter, &priv->notify_items) { - item = c_list_entry (iter, NotifyItem, lst); - - if (property && (property == item->property)) - return; - - /* Collapse signals for the same object (such as "added->removed") to - * ensure we don't emit signals when their sum should have no effect. - * The "added->removed->removed" sequence requires special handling, - * hence the addition of the ADDED_REMOVED state to ensure that no - * signal is emitted in this case: - * - * Without the ADDED_REMOVED state: - * NONE + added -> ADDED - * ADDED + removed -> NONE - * NONE + removed -> REMOVED (would emit 'removed' signal) - * - * With the ADDED_REMOVED state: - * NONE | ADDED_REMOVED + added -> ADDED - * ADDED + removed -> ADDED_REMOVED - * ADDED_REMOVED + removed -> ADDED_REMOVED (emits no signal) - */ - if (signal_prefix && (changed == item->changed) && (item->signal_prefix == signal_prefix)) { - switch (item->pending) { - case NOTIFY_SIGNAL_PENDING_ADDED: - if (!added) - item->pending = NOTIFY_SIGNAL_PENDING_ADDED_REMOVED; - break; - case NOTIFY_SIGNAL_PENDING_REMOVED: - if (added) - item->pending = NOTIFY_SIGNAL_PENDING_NONE; - break; - case NOTIFY_SIGNAL_PENDING_ADDED_REMOVED: - if (added) - item->pending = NOTIFY_SIGNAL_PENDING_ADDED; - break; - case NOTIFY_SIGNAL_PENDING_NONE: - item->pending = added ? NOTIFY_SIGNAL_PENDING_ADDED : NOTIFY_SIGNAL_PENDING_REMOVED; - break; - default: - g_assert_not_reached (); - } - return; - } - } - - item = g_slice_new0 (NotifyItem); - item->property = property; - if (signal_prefix) { - item->signal_prefix = signal_prefix; - item->pending = added ? NOTIFY_SIGNAL_PENDING_ADDED : NOTIFY_SIGNAL_PENDING_REMOVED; - item->changed = changed ? g_object_ref (changed) : NULL; - } - c_list_link_tail (&priv->notify_items, &item->lst); -} - -void -_nm_object_queue_notify (NMObject *object, const char *property) -{ - _nm_object_queue_notify_full (object, property, NULL, FALSE, NULL); -} - -typedef struct { - CList lst_pending; - NMObject *self; - PropertyInfo *pi; - - GObject **objects; - int length, remaining; - - gboolean array; - const char *property_name; -} ObjectCreatedData; - -static void -odata_free (gpointer data) -{ - ObjectCreatedData *odata = data; - - c_list_unlink_stale (&odata->lst_pending); - g_object_unref (odata->self); - g_free (odata->objects); - g_slice_free (ObjectCreatedData, odata); -} - -static void object_property_maybe_complete (NMObject *self); - -/* Adds object to array if it's not already there */ -static void -add_to_object_array_unique (GPtrArray *array, GObject *obj) -{ - guint i; - - g_return_if_fail (array != NULL); - - if (obj != NULL) { - for (i = 0; i < array->len; i++) { - if (g_ptr_array_index (array, i) == obj) { - g_object_unref (obj); - return; - } - } - g_ptr_array_add (array, obj); - } -} - -/* Places items from 'needles' that are not in 'haystack' into 'diff' */ -static void -array_diff (GPtrArray *needles, GPtrArray *haystack, GPtrArray *diff) -{ - guint i, j; - GObject *obj; - - g_assert (needles); - g_assert (haystack); - g_assert (diff); - - for (i = 0; i < needles->len; i++) { - obj = g_ptr_array_index (needles, i); - - for (j = 0; j < haystack->len; j++) { - if (g_ptr_array_index (haystack, j) == obj) - break; - } - - if (j == haystack->len) - g_ptr_array_add (diff, obj); - } -} - -static void -queue_added_removed_signal (NMObject *self, - const char *signal_prefix, - NMObject *changed, - gboolean added) -{ - _nm_object_queue_notify_full (self, NULL, signal_prefix, added, changed); -} - -static gboolean -already_awaits (ObjectCreatedData *odata, GObject *object) -{ - NMObject *self = odata->self; - NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self); - GSList *iter; - - if ((GObject *)odata->self == object) - return TRUE; - - for (iter = priv->waiters; iter; iter = g_slist_next (iter)) { - if (already_awaits (iter->data, object)) - return TRUE; - } - - return FALSE; -} - -static void -object_property_maybe_complete (NMObject *self) -{ - NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self); - /* The odata may hold the last reference. */ - _nm_unused gs_unref_object NMObject *self_keep_alive = g_object_ref (self); - int i; - CList *iter, *safe; - - c_list_for_each_safe (iter, safe, &priv->pending) { - ObjectCreatedData *odata = c_list_entry (iter, ObjectCreatedData, lst_pending); - PropertyInfo *pi = odata->pi; - gboolean different = TRUE; - - if (odata->remaining > 0) - return; - - /* Only complete the array property load when all the objects are initialized. */ - for (i = 0; i < odata->length; i++) { - GObject *obj = odata->objects[i]; - NMObjectPrivate *obj_priv; - - /* Could not load the object. Perhaps it was removed. */ - if (!obj) - continue; - - obj_priv = NM_OBJECT_GET_PRIVATE (obj); - if (!obj_priv->inited) { - - /* The object is not finished because we block its creation. */ - if (already_awaits (odata, obj)) - continue; - - if (!g_slist_find (obj_priv->waiters, odata)) - obj_priv->waiters = g_slist_prepend (obj_priv->waiters, odata); - return; - } - } - - if (odata->array) { - GPtrArray *old = *((GPtrArray **) pi->field); - GPtrArray *new; - - /* Build up new array */ - new = g_ptr_array_new_full (odata->length, g_object_unref); - for (i = 0; i < odata->length; i++) - add_to_object_array_unique (new, odata->objects[i]); - - *((GPtrArray **) pi->field) = new; - - if (pi->signal_prefix) { - GPtrArray *added = g_ptr_array_sized_new (3); - GPtrArray *removed = g_ptr_array_sized_new (3); - - if (old) { - /* Find objects in 'old' that do not exist in 'new' */ - array_diff (old, new, removed); - - /* Find objects in 'new' that do not exist in old */ - array_diff (new, old, added); - } else { - for (i = 0; i < new->len; i++) - g_ptr_array_add (added, g_ptr_array_index (new, i)); - } - - /* Emit added & removed */ - for (i = 0; i < removed->len; i++) { - queue_added_removed_signal (self, - pi->signal_prefix, - g_ptr_array_index (removed, i), - FALSE); - } - - for (i = 0; i < added->len; i++) { - queue_added_removed_signal (self, - pi->signal_prefix, - g_ptr_array_index (added, i), - TRUE); - } - - different = removed->len || added->len; - g_ptr_array_unref (added); - g_ptr_array_unref (removed); - } else { - /* No added/removed signals to send, just replace the property with - * the new values. - */ - different = TRUE; - } - - /* Free old array last since it will release references, thus freeing - * any objects in the 'removed' array. - */ - if (old) - g_ptr_array_unref (old); - } else { - GObject **obj_p = pi->field; - - different = (*obj_p != odata->objects[0]); - if (*obj_p) - g_object_unref (*obj_p); - *obj_p = odata->objects[0]; + for (i = 0; i < p->num; i++) { + if (!nml_dbus_property_ao_is_ready (&fields[i])) + return NML_DBUS_OBJ_STATE_WITH_NMOBJ_NOT_READY; } - - if (different && odata->property_name) - _nm_object_queue_notify (self, odata->property_name); - - if (--priv->reload_remaining == 0) - reload_complete (self, TRUE); - - odata_free (odata); - } -} - -static void -object_created (GObject *obj, const char *path, gpointer user_data) -{ - ObjectCreatedData *odata = user_data; - - /* We assume that on error, the creator_func printed something */ - - if (obj == NULL && g_strcmp0 (path, "/") != 0 ) { - NMObjectClass *object_class = NM_OBJECT_GET_CLASS (odata->self); - - if (object_class->object_creation_failed) - object_class->object_creation_failed (odata->self, path); - } - - odata->objects[odata->length - odata->remaining--] = obj ? g_object_ref (obj) : NULL; - object_property_maybe_complete (odata->self); -} - -static gboolean -handle_object_property (NMObject *self, const char *property_name, GVariant *value, - PropertyInfo *pi) -{ - NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self); - gs_unref_object GDBusObject *object = NULL; - GObject *obj; - const char *path; - ObjectCreatedData *odata; - - odata = g_slice_new (ObjectCreatedData); - odata->self = g_object_ref (self); - odata->pi = pi; - odata->objects = g_new0 (GObject *, 1); - odata->length = odata->remaining = 1; - odata->array = FALSE; - odata->property_name = property_name; - - c_list_link_tail (&priv->pending, &odata->lst_pending); - - priv->reload_remaining++; - - path = g_variant_get_string (value, NULL); - - if (!strcmp (path, "/")) { - object_created (NULL, path, odata); - return TRUE; - } - - object = g_dbus_object_manager_get_object (priv->object_manager, path); - if (!object) { - /* This is a server bug -- a dangling object path for an object - * that does not exist. - * - * NOTE: We've ignored this before and the server hits the condition - * more often that it should. Given we're able to recover from - * the error, let's lower the severity of the log message to - * avoid unnecessarily bothering the user. This can be removed - * once the issue is fixed on the server. */ -#if NM_MORE_ASSERTS -#define __nm_log_debug g_warning -#else -#define __nm_log_debug g_debug -#endif - __nm_log_debug ("No object known for %s", path); -#undef __nm_log_debug - return FALSE; } - obj = g_object_get_qdata (G_OBJECT (object), _nm_object_obj_nm_quark ()); - object_created (obj, path, odata); - - return TRUE; + return NML_DBUS_OBJ_STATE_WITH_NMOBJ_VISIBLE; } -static gboolean -handle_object_array_property (NMObject *self, const char *property_name, GVariant *value, - PropertyInfo *pi) -{ - NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self); - GObject *obj; - GVariantIter iter; - gsize npaths; - const char *path; - ObjectCreatedData *odata; - - npaths = g_variant_n_children (value); - - odata = g_slice_new (ObjectCreatedData); - odata->self = g_object_ref (self); - odata->pi = pi; - odata->objects = g_new0 (GObject *, npaths); - odata->length = odata->remaining = npaths; - odata->array = TRUE; - odata->property_name = property_name; - - c_list_link_tail (&priv->pending, &odata->lst_pending); - - priv->reload_remaining++; - - if (npaths == 0) { - object_property_maybe_complete (self); - return TRUE; - } - - g_variant_iter_init (&iter, value); - while (g_variant_iter_next (&iter, "&o", &path)) { - gs_unref_object GDBusObject *object = NULL; - - object = g_dbus_object_manager_get_object (priv->object_manager, path); - if (object) { - obj = g_object_get_qdata (G_OBJECT (object), _nm_object_obj_nm_quark ()); - object_created (obj, path, odata); - } else { - g_warning ("no object known for %s\n", path); - odata->remaining--; - odata->length--; - object_property_maybe_complete (self); - } - } - - return TRUE; -} +/*****************************************************************************/ static void -handle_property_changed (NMObject *self, const char *dbus_name, GVariant *value) +register_client (NMObject *self, + NMClient *client, + NMLDBusObject *dbobj) { NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self); - char *prop_name; - PropertyInfo *pi; - GParamSpec *pspec; - gboolean success = FALSE, found = FALSE; - GSList *iter; - - prop_name = nm_utils_wincaps_to_dash (dbus_name); - /* Iterate through the object and its parents to find the property */ - for (iter = priv->property_tables; iter; iter = g_slist_next (iter)) { - pi = g_hash_table_lookup ((GHashTable *) iter->data, prop_name); - if (pi) { - if (!pi->field) { - /* We know about this property but aren't tracking changes on it. */ - goto out; - } + nm_assert (!priv->client); + nm_assert (NML_IS_DBUS_OBJECT (dbobj)); + nm_assert (dbobj->nmobj == G_OBJECT (self)); - found = TRUE; - break; - } - } - - if (!found) { - dbgmsg ("Property '%s' unhandled.", prop_name); - goto out; - } - - pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (G_OBJECT (self)), prop_name); - if (!pspec && pi->func == demarshal_generic) { - dbgmsg ("%s: property '%s' changed but wasn't defined by object type %s.", - __func__, - prop_name, - G_OBJECT_TYPE_NAME (self)); - goto out; - } - - if (G_UNLIKELY (debug)) { - char *s; - s = g_variant_print (value, FALSE); - dbgmsg ("PC: (%p) %s:%s => '%s' (%s%s%s)", - self, G_OBJECT_TYPE_NAME (self), - prop_name, - s, - g_variant_get_type_string (value), - pi->object_type ? " / " : "", - pi->object_type ? g_type_name (pi->object_type) : ""); - g_free (s); - } - - if (pspec && pi->object_type) { - if (g_variant_is_of_type (value, G_VARIANT_TYPE_OBJECT_PATH)) - success = handle_object_property (self, pspec->name, value, pi); - else if (g_variant_is_of_type (value, G_VARIANT_TYPE ("ao"))) - success = handle_object_array_property (self, pspec->name, value, pi); - else { - g_warn_if_reached (); - goto out; - } - } else - success = (*(pi->func)) (self, pspec, value, pi->field); - - if (!success) { - dbgmsg ("%s: failed to update property '%s' of object type %s.", - __func__, - prop_name, - G_OBJECT_TYPE_NAME (self)); - } - -out: - g_free (prop_name); + priv->client = client; + priv->dbobj = nml_dbus_object_ref (dbobj); } static void -properties_changed (GDBusProxy *proxy, - GVariant *changed_properties, - GStrv invalidated_properties, - gpointer user_data) +unregister_client (NMObject *self, + NMClient *client, + NMLDBusObject *dbobj) { - NMObject *self = NM_OBJECT (user_data); - GVariantIter iter; - const char *name; - GVariant *value; - - g_variant_iter_init (&iter, changed_properties); - while (g_variant_iter_next (&iter, "{&sv}", &name, &value)) { - handle_property_changed (self, name, value); - g_variant_unref (value); - } -} - -#define HANDLE_TYPE_CHECK(vtype, ctype, getter) \ - ({ \ - gboolean _success = FALSE; \ - \ - if (g_variant_is_of_type (value, vtype)) { \ - ctype *param = (ctype *) field; \ - ctype newval = getter (value); \ - different = *param != newval; \ - *param = newval; \ - _success = TRUE; \ - } \ - \ - _success; \ - }) - -#define HANDLE_TYPE(vtype, ctype, getter) \ - G_STMT_START { \ - if (!HANDLE_TYPE_CHECK (vtype, ctype, getter)) {\ - success = FALSE; \ - goto done; \ - } \ - } G_STMT_END - -static gboolean -demarshal_generic (NMObject *object, - GParamSpec *pspec, - GVariant *value, - gpointer field) -{ - gboolean success = TRUE; - gboolean different = FALSE; - - if (pspec->value_type == G_TYPE_STRING) { - if (g_variant_is_of_type (value, G_VARIANT_TYPE_STRING)) { - char **param = (char **) field; - const char *newval = g_variant_get_string (value, NULL); - - different = !!g_strcmp0 (*param, newval); - if (different) { - g_free (*param); - *param = g_strdup (newval); - } - } else if (g_variant_is_of_type (value, G_VARIANT_TYPE_OBJECT_PATH)) { - char **param = (char **) field; - const char *newval = g_variant_get_string (value, NULL); - - /* Handle "NULL" object paths */ - if (g_strcmp0 (newval, "/") == 0) - newval = NULL; - different = !!g_strcmp0 (*param, newval); - if (different) { - g_free (*param); - *param = g_strdup (newval); - } - } else { - success = FALSE; - goto done; - } - } else if (pspec->value_type == G_TYPE_STRV) { - char ***param = (char ***)field; - const char **newval; - gsize i; - - newval = g_variant_get_strv (value, NULL); - if (!*param) - different = TRUE; - else { - if (!_nm_utils_strv_equal ((char **) newval, *param)) { - different = TRUE; - g_strfreev (*param); - } - } - if (different) { - for (i = 0; newval[i]; i++) - newval[i] = g_strdup (newval[i]); - *param = (char **) newval; - } else - g_free (newval); - } else if (pspec->value_type == G_TYPE_BYTES) { - GBytes **param = (GBytes **)field; - gconstpointer val; - gsize length = 0; - - val = g_variant_get_fixed_array (value, &length, 1); - - different = !nm_utils_gbytes_equal_mem (*param, val, length); - if (different) { - if (*param) - g_bytes_unref (*param); - *param = length > 0 ? g_bytes_new (val, length) : NULL; - } - } else if (G_IS_PARAM_SPEC_ENUM (pspec)) { - int *param = (int *) field; - int newval = 0; - - if (g_variant_is_of_type (value, G_VARIANT_TYPE_INT32)) - newval = g_variant_get_int32 (value); - else if (g_variant_is_of_type (value, G_VARIANT_TYPE_UINT32)) - newval = g_variant_get_uint32 (value); - else { - success = FALSE; - goto done; - } - different = *param != newval; - *param = newval; - } else if (G_IS_PARAM_SPEC_FLAGS (pspec)) { - guint *param = (guint *) field; - guint newval = 0; - - if (g_variant_is_of_type (value, G_VARIANT_TYPE_INT32)) - newval = g_variant_get_int32 (value); - else if (g_variant_is_of_type (value, G_VARIANT_TYPE_UINT32)) - newval = g_variant_get_uint32 (value); - else { - success = FALSE; - goto done; - } - different = *param != newval; - *param = newval; - } else if (pspec->value_type == G_TYPE_BOOLEAN) - HANDLE_TYPE (G_VARIANT_TYPE_BOOLEAN, gboolean, g_variant_get_boolean); - else if (pspec->value_type == G_TYPE_UCHAR) - HANDLE_TYPE (G_VARIANT_TYPE_BYTE, guchar, g_variant_get_byte); - else if (pspec->value_type == G_TYPE_DOUBLE) { - NM_PRAGMA_WARNING_DISABLE("-Wfloat-equal") - HANDLE_TYPE (G_VARIANT_TYPE_DOUBLE, double, g_variant_get_double); - NM_PRAGMA_WARNING_REENABLE - } else if (pspec->value_type == G_TYPE_INT) - HANDLE_TYPE (G_VARIANT_TYPE_INT32, int, g_variant_get_int32); - else if (pspec->value_type == G_TYPE_UINT) { - if ( !HANDLE_TYPE_CHECK (G_VARIANT_TYPE_UINT32, guint, g_variant_get_uint32) - && !HANDLE_TYPE_CHECK (G_VARIANT_TYPE_UINT16, guint, g_variant_get_uint16)) - success = FALSE; - } else if (pspec->value_type == G_TYPE_INT64) - HANDLE_TYPE (G_VARIANT_TYPE_INT64, gint64, g_variant_get_int64); - else if (pspec->value_type == G_TYPE_UINT64) - HANDLE_TYPE (G_VARIANT_TYPE_UINT64, guint64, g_variant_get_uint64); - else if (pspec->value_type == G_TYPE_LONG) - HANDLE_TYPE (G_VARIANT_TYPE_INT64, long, g_variant_get_int64); - else if (pspec->value_type == G_TYPE_ULONG) - HANDLE_TYPE (G_VARIANT_TYPE_UINT64, gulong, g_variant_get_uint64); - else { - g_warning ("%s: %s:%s unhandled type %s.", - __func__, - G_OBJECT_TYPE_NAME (object), - pspec->name, - g_type_name (pspec->value_type)); - success = FALSE; - } - -done: - if (success) { - if (different) - _nm_object_queue_notify (object, pspec->name); - } else { - dbgmsg ("%s: %s:%s (type %s) couldn't be set from D-Bus type %s.", - __func__, G_OBJECT_TYPE_NAME (object), pspec->name, - g_type_name (pspec->value_type), g_variant_get_type_string (value)); - } - return success; -} - -void -_nm_object_register_properties (NMObject *object, - const char *interface, - const NMPropertiesInfo *info) -{ - NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object); - GDBusProxy *proxy; - static gsize dval = 0; - const char *debugstr; - NMPropertiesInfo *tmp; - GHashTable *instance; - - g_return_if_fail (NM_IS_OBJECT (object)); - g_return_if_fail (interface != NULL); - g_return_if_fail (info != NULL); - - if (g_once_init_enter (&dval)) { - debugstr = getenv ("LIBNM_GLIB_DEBUG"); - if (debugstr && strstr (debugstr, "properties-changed")) - debug = TRUE; - g_once_init_leave (&dval, 1); - } - - proxy = _nm_object_get_proxy (object, interface); - g_signal_connect (proxy, "g-properties-changed", - G_CALLBACK (properties_changed), object); - g_ptr_array_add (priv->proxies, proxy); - - instance = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, g_free); - priv->property_tables = g_slist_prepend (priv->property_tables, instance); - - for (tmp = (NMPropertiesInfo *) info; tmp->name; tmp++) { - PropertyInfo *pi; - - if (!tmp->name || (tmp->func && !tmp->field)) { - g_warning ("%s: missing field in NMPropertiesInfo", __func__); - continue; - } - - pi = g_malloc0 (sizeof (PropertyInfo)); - pi->func = tmp->func ?: demarshal_generic; - pi->object_type = tmp->object_type; - pi->field = tmp->field; - pi->signal_prefix = tmp->signal_prefix; - g_hash_table_insert (instance, g_strdup (tmp->name), pi); - } -} - -void -_nm_object_set_property (NMObject *object, - const char *interface, - const char *prop_name, - const char *format_string, - ...) -{ - GVariant *val, *ret; - GDBusProxy *proxy; - va_list ap; - - g_return_if_fail (NM_IS_OBJECT (object)); - g_return_if_fail (interface != NULL); - g_return_if_fail (prop_name != NULL); - g_return_if_fail (format_string != NULL); - - va_start (ap, format_string); - val = g_variant_new_va (format_string, NULL, &ap); - va_end (ap); - g_return_if_fail (val != NULL); - - proxy = _nm_object_get_proxy (object, interface); - ret = g_dbus_proxy_call_sync (proxy, - DBUS_INTERFACE_PROPERTIES ".Set", - g_variant_new ("(ssv)", interface, prop_name, val), - G_DBUS_CALL_FLAGS_NONE, 2000, - NULL, NULL); - /* Ignore errors. */ - if (ret) - g_variant_unref (ret); - g_object_unref (proxy); -} - -static void -reload_complete (NMObject *object, gboolean emit_now) -{ - NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object); - - if (emit_now) { - nm_clear_g_source (&priv->notify_id); - deferred_notify_cb (object); - } else - _nm_object_defer_notify (object); -} - -GDBusObjectManager * -_nm_object_get_dbus_object_manager (NMObject *self) -{ - return NM_OBJECT_GET_PRIVATE (self)->object_manager; -} - -/*****************************************************************************/ - -static void -init_dbus (NMObject *object) -{ -} - -static void -init_if (GDBusProxy *proxy, NMObject *self) -{ - char **props; - char **prop; - GVariant *val; - char *str; - - nm_assert (G_IS_DBUS_PROXY (proxy)); - nm_assert (NM_IS_OBJECT (self)); - - props = g_dbus_proxy_get_cached_property_names (proxy); - - for (prop = props; prop && *prop; prop++) { - val = g_dbus_proxy_get_cached_property (proxy, *prop); - str = g_variant_print (val, TRUE); - handle_property_changed (self, *prop, val); - g_variant_unref (val); - g_free (str); - } - - g_strfreev (props); -} - -static gboolean -init_sync (GInitable *initable, GCancellable *cancellable, GError **error) -{ - NMObject *self = NM_OBJECT (initable); NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self); - GList *interfaces; - - g_assert (priv->object && priv->object_manager); - - NM_OBJECT_GET_CLASS (self)->init_dbus (self); - - priv->reload_remaining++; - - interfaces = g_dbus_object_get_interfaces (priv->object); - g_list_foreach (interfaces, (GFunc) init_if, self); - g_list_free_full (interfaces, g_object_unref); - - priv->inited = TRUE; - - if (--priv->reload_remaining == 0) - reload_complete (self, TRUE); - /* There are some object properties whose creation couldn't proceed - * because it depended on this object. */ - while (priv->waiters) { - ObjectCreatedData *odata = priv->waiters->data; + nm_assert (NM_IS_CLIENT (client)); + nm_assert (priv->client == client); + priv->client = NULL; - priv->waiters = g_slist_remove (priv->waiters, odata); - object_property_maybe_complete (odata->self); - } - - return TRUE; + clear_properties (self, client); } /*****************************************************************************/ -typedef struct { - NMObject *object; - GSimpleAsyncResult *simple; - GCancellable *cancellable; - int proxies_pending; - GError *error; -} NMObjectInitData; - static void -init_async_complete (NMObjectInitData *init_data) -{ - if (init_data->error) - g_simple_async_result_take_error (init_data->simple, init_data->error); - else - g_simple_async_result_set_op_res_gboolean (init_data->simple, TRUE); - g_simple_async_result_complete_in_idle (init_data->simple); - g_object_unref (init_data->simple); - g_clear_object (&init_data->cancellable); - g_slice_free (NMObjectInitData, init_data); -} - -static void -init_async (GAsyncInitable *initable, int io_priority, - GCancellable *cancellable, GAsyncReadyCallback callback, - gpointer user_data) -{ - NMObject *self = NM_OBJECT (initable); - NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self); - NMObjectInitData *init_data; - GList *interfaces; - - g_assert (priv->object && priv->object_manager); - - NM_OBJECT_GET_CLASS (self)->init_dbus (self); - - init_data = g_slice_new0 (NMObjectInitData); - init_data->object = self; - init_data->simple = g_simple_async_result_new (G_OBJECT (initable), callback, user_data, init_async); - if (cancellable) - g_simple_async_result_set_check_cancellable (init_data->simple, cancellable); - init_data->cancellable = cancellable ? g_object_ref (cancellable) : NULL; - - interfaces = g_dbus_object_get_interfaces (priv->object); - g_list_foreach (interfaces, (GFunc) init_if, self); - g_list_free_full (interfaces, g_object_unref); - - init_async_complete (init_data); -} - -static gboolean -init_finish (GAsyncInitable *initable, GAsyncResult *result, GError **error) +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) { - GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result); - NMObject *self = NM_OBJECT (initable); - NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self); - - priv->inited = TRUE; - - /* There are some object properties whose creation couldn't proceed - * because it depended on this object. */ - while (priv->waiters) { - ObjectCreatedData *odata = priv->waiters->data; + NMObject *self = NM_OBJECT (object); - priv->waiters = g_slist_remove (priv->waiters, odata); - object_property_maybe_complete (odata->self); + switch (prop_id) { + case PROP_PATH: + g_value_set_string (value, nm_object_get_path (self)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; } - - if (g_simple_async_result_propagate_error (simple, error)) - return FALSE; - else - return TRUE; } /*****************************************************************************/ static void -nm_object_initable_iface_init (GInitableIface *iface) -{ - iface->init = init_sync; -} - -static void -nm_object_async_initable_iface_init (GAsyncInitableIface *iface) -{ - iface->init_async = init_async; - iface->init_finish = init_finish; -} - -static void nm_object_init (NMObject *object) { NMObject *self = NM_OBJECT (object); @@ -1373,109 +209,43 @@ nm_object_init (NMObject *object) self->_priv = priv; - c_list_init (&priv->notify_items); - c_list_init (&priv->pending); - priv->proxies = g_ptr_array_new (); -} - -static void -set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) -{ - NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object); - - switch (prop_id) { - case PROP_DBUS_OBJECT: - /* construct-only */ - priv->object = g_value_dup_object (value); - if (!priv->object) - g_return_if_reached (); - break; - case PROP_DBUS_OBJECT_MANAGER: - /* construct-only */ - priv->object_manager = g_value_dup_object (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object); - - switch (prop_id) { - case PROP_PATH: - g_value_set_string (value, nm_object_get_path (NM_OBJECT (object))); - break; - case PROP_DBUS_CONNECTION: - g_value_set_object (value, g_dbus_object_manager_client_get_connection (G_DBUS_OBJECT_MANAGER_CLIENT (priv->object_manager))); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } + c_list_init (&self->obj_base.queue_notify_lst); } static void dispose (GObject *object) { - NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object); - CList *iter, *safe; - guint i; - - nm_clear_g_source (&priv->notify_id); - - c_list_for_each_safe (iter, safe, &priv->notify_items) - notify_item_free (c_list_entry (iter, NotifyItem, lst)); + NMObject *self = NM_OBJECT (object); + NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self); - g_slist_free_full (priv->waiters, odata_free); + self->obj_base.is_disposing = TRUE; - g_clear_object (&priv->object); - g_clear_object (&priv->object_manager); + nm_assert (c_list_is_empty (&self->obj_base.queue_notify_lst)); + nm_assert (!priv->client); + nm_assert (!priv->dbobj || !priv->dbobj->nmobj); - if (priv->proxies) { - for (i = 0; i < priv->proxies->len; i++) { - g_signal_handlers_disconnect_by_func (priv->proxies->pdata[i], - properties_changed, - object); - g_object_unref (priv->proxies->pdata[i]); - } - g_ptr_array_free (priv->proxies, TRUE); - priv->proxies = NULL; - } + clear_properties (self, NULL); G_OBJECT_CLASS (nm_object_parent_class)->dispose (object); -} - -static void -finalize (GObject *object) -{ - NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object); - - g_slist_free_full (priv->property_tables, (GDestroyNotify) g_hash_table_destroy); - g_free (priv->name_owner_cached); - - G_OBJECT_CLASS (nm_object_parent_class)->finalize (object); + nm_clear_pointer (&priv->dbobj, nml_dbus_object_unref); } static void -nm_object_class_init (NMObjectClass *nm_object_class) +nm_object_class_init (NMObjectClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (nm_object_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + _nm_object_class = klass; - g_type_class_add_private (nm_object_class, sizeof (NMObjectPrivate)); + g_type_class_add_private (klass, sizeof (NMObjectPrivate)); object_class->get_property = get_property; - object_class->set_property = set_property; object_class->dispose = dispose; - object_class->finalize = finalize; - nm_object_class->init_dbus = init_dbus; + klass->register_client = register_client; + klass->unregister_client = unregister_client; + klass->is_visible = is_visible; /** * NMObject:path: @@ -1488,40 +258,5 @@ nm_object_class_init (NMObjectClass *nm_object_class) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - /** - * NMObject:dbus-connection: (skip) - * - * The #GDBusConnection of the object. - **/ - obj_properties[PROP_DBUS_CONNECTION] = - g_param_spec_object (NM_OBJECT_DBUS_CONNECTION, "", "", - G_TYPE_DBUS_CONNECTION, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - - /** - * NMObject:dbus-object: (skip) - * - * The #GDBusObject of the object. - **/ - obj_properties[PROP_DBUS_OBJECT] = - g_param_spec_object (NM_OBJECT_DBUS_OBJECT, "", "", - G_TYPE_DBUS_OBJECT, - G_PARAM_WRITABLE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - - /** - * NMObject:dbus-object-manager: (skip) - * - * The #GDBusObjectManager of the object. - **/ - obj_properties[PROP_DBUS_OBJECT_MANAGER] = - g_param_spec_object (NM_OBJECT_DBUS_OBJECT_MANAGER, "", "", - G_TYPE_DBUS_OBJECT_MANAGER, - G_PARAM_WRITABLE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); } diff --git a/libnm/nm-object.h b/libnm/nm-object.h index d9ee4444c8..88c34a9eb1 100644 --- a/libnm/nm-object.h +++ b/libnm/nm-object.h @@ -23,9 +23,6 @@ G_BEGIN_DECLS #define NM_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_OBJECT, NMObjectClass)) #define NM_OBJECT_PATH "path" -#define NM_OBJECT_DBUS_CONNECTION "dbus-connection" -#define NM_OBJECT_DBUS_OBJECT "dbus-object" -#define NM_OBJECT_DBUS_OBJECT_MANAGER "dbus-object-manager" /** * NMObject: diff --git a/libnm/nm-remote-connection.c b/libnm/nm-remote-connection.c index c45c7f1fce..294ec5179d 100644 --- a/libnm/nm-remote-connection.c +++ b/libnm/nm-remote-connection.c @@ -17,8 +17,6 @@ #include "nm-object-private.h" #include "nm-dbus-helpers.h" -#include "introspection/org.freedesktop.NetworkManager.Settings.Connection.h" - /** * SECTION:nm-remote-connection * @short_description: A connection managed by NetworkManager server @@ -37,13 +35,14 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMRemoteConnection, ); typedef struct { - NMDBusSettingsConnection *proxy; + GCancellable *get_settings_cancellable; - gboolean unsaved; - guint32 flags; char *filename; + guint32 flags; + bool unsaved; - gboolean visible; + bool visible:1; + bool is_initialized:1; } NMRemoteConnectionPrivate; struct _NMRemoteConnection { @@ -56,20 +55,12 @@ struct _NMRemoteConnectionClass { }; static void nm_remote_connection_connection_iface_init (NMConnectionInterface *iface); -static void nm_remote_connection_initable_iface_init (GInitableIface *iface); -static void nm_remote_connection_async_initable_iface_init (GAsyncInitableIface *iface); G_DEFINE_TYPE_WITH_CODE (NMRemoteConnection, nm_remote_connection, NM_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (NM_TYPE_CONNECTION, nm_remote_connection_connection_iface_init); - G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, nm_remote_connection_initable_iface_init); - G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, nm_remote_connection_async_initable_iface_init); ) -#define NM_REMOTE_CONNECTION_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMRemoteConnection, NM_IS_REMOTE_CONNECTION, NMObject) - -/*****************************************************************************/ -static GInitableIface *nm_remote_connection_parent_initable_iface; -static GAsyncInitableIface *nm_remote_connection_parent_async_initable_iface; +#define NM_REMOTE_CONNECTION_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMRemoteConnection, NM_IS_REMOTE_CONNECTION, NMObject) /*****************************************************************************/ @@ -106,12 +97,13 @@ nm_remote_connection_update2 (NMRemoteConnection *connection, if (!args) args = g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0); - _nm_object_dbus_call (connection, + _nm_client_dbus_call (_nm_object_get_client (connection), + connection, nm_remote_connection_update2, cancellable, callback, user_data, - g_dbus_proxy_get_object_path (G_DBUS_PROXY (NM_REMOTE_CONNECTION_GET_PRIVATE (connection)->proxy)), + _nm_object_get_path (connection), NM_DBUS_INTERFACE_SETTINGS_CONNECTION, "Update2", g_variant_new ("(@a{sa{sv}}u@a{sv})", @@ -185,9 +177,9 @@ nm_remote_connection_commit_changes (NMRemoteConnection *connection, g_return_val_if_fail (NM_IS_REMOTE_CONNECTION (connection), FALSE); g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), FALSE); - ret = _nm_object_dbus_call_sync (connection, + ret = _nm_client_dbus_call_sync (_nm_object_get_client (connection), cancellable, - g_dbus_proxy_get_object_path (G_DBUS_PROXY (NM_REMOTE_CONNECTION_GET_PRIVATE (connection)->proxy)), + _nm_object_get_path (connection), NM_DBUS_INTERFACE_SETTINGS_CONNECTION, "Update2", g_variant_new ("(@a{sa{sv}}u@a{sv})", @@ -287,9 +279,9 @@ nm_remote_connection_save (NMRemoteConnection *connection, g_return_val_if_fail (NM_IS_REMOTE_CONNECTION (connection), FALSE); g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), FALSE); - return _nm_object_dbus_call_sync_void (connection, + return _nm_client_dbus_call_sync_void (_nm_object_get_client (connection), cancellable, - g_dbus_proxy_get_object_path (G_DBUS_PROXY (NM_REMOTE_CONNECTION_GET_PRIVATE (connection)->proxy)), + _nm_object_get_path (connection), NM_DBUS_INTERFACE_SETTINGS_CONNECTION, "Save", g_variant_new ("()"), @@ -318,12 +310,13 @@ nm_remote_connection_save_async (NMRemoteConnection *connection, g_return_if_fail (NM_IS_REMOTE_CONNECTION (connection)); g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable)); - _nm_object_dbus_call (connection, + _nm_client_dbus_call (_nm_object_get_client (connection), + connection, nm_remote_connection_save_async, cancellable, callback, user_data, - g_dbus_proxy_get_object_path (G_DBUS_PROXY (NM_REMOTE_CONNECTION_GET_PRIVATE (connection)->proxy)), + _nm_object_get_path (connection), NM_DBUS_INTERFACE_SETTINGS_CONNECTION, "Save", g_variant_new ("()"), @@ -375,9 +368,9 @@ nm_remote_connection_delete (NMRemoteConnection *connection, { g_return_val_if_fail (NM_IS_REMOTE_CONNECTION (connection), FALSE); - return _nm_object_dbus_call_sync_void (connection, + return _nm_client_dbus_call_sync_void (_nm_object_get_client (connection), cancellable, - g_dbus_proxy_get_object_path (G_DBUS_PROXY (NM_REMOTE_CONNECTION_GET_PRIVATE (connection)->proxy)), + _nm_object_get_path (connection), NM_DBUS_INTERFACE_SETTINGS_CONNECTION, "Delete", g_variant_new ("()"), @@ -405,12 +398,13 @@ nm_remote_connection_delete_async (NMRemoteConnection *connection, g_return_if_fail (NM_IS_REMOTE_CONNECTION (connection)); g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable)); - _nm_object_dbus_call (connection, + _nm_client_dbus_call (_nm_object_get_client (connection), + connection, nm_remote_connection_delete_async, cancellable, callback, user_data, - g_dbus_proxy_get_object_path (G_DBUS_PROXY (NM_REMOTE_CONNECTION_GET_PRIVATE (connection)->proxy)), + _nm_object_get_path (connection), NM_DBUS_INTERFACE_SETTINGS_CONNECTION, "Delete", g_variant_new ("()"), @@ -469,9 +463,9 @@ nm_remote_connection_get_secrets (NMRemoteConnection *connection, g_return_val_if_fail (setting_name, NULL); g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), NULL); - ret = _nm_object_dbus_call_sync (connection, + ret = _nm_client_dbus_call_sync (_nm_object_get_client (connection), cancellable, - g_dbus_proxy_get_object_path (G_DBUS_PROXY (NM_REMOTE_CONNECTION_GET_PRIVATE (connection)->proxy)), + _nm_object_get_path (connection), NM_DBUS_INTERFACE_SETTINGS_CONNECTION, "GetSecrets", g_variant_new ("(s)", setting_name), @@ -511,12 +505,13 @@ nm_remote_connection_get_secrets_async (NMRemoteConnection *connection, g_return_if_fail (setting_name); g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable)); - _nm_object_dbus_call (connection, + _nm_client_dbus_call (_nm_object_get_client (connection), + connection, nm_remote_connection_get_secrets_async, cancellable, callback, user_data, - g_dbus_proxy_get_object_path (G_DBUS_PROXY (NM_REMOTE_CONNECTION_GET_PRIVATE (connection)->proxy)), + _nm_object_get_path (connection), NM_DBUS_INTERFACE_SETTINGS_CONNECTION, "GetSecrets", g_variant_new ("(s)", setting_name), @@ -633,195 +628,102 @@ nm_remote_connection_get_visible (NMRemoteConnection *connection) /*****************************************************************************/ -static void -replace_settings (NMRemoteConnection *self, GVariant *new_settings) +GCancellable * +_nm_remote_settings_get_settings_prepare (NMRemoteConnection *self) { - GError *error = NULL; + NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (self); - if (!_nm_connection_replace_settings ((NMConnection *) self, - new_settings, - NM_SETTING_PARSE_FLAGS_BEST_EFFORT, - &error)) - g_clear_error (&error); + nm_clear_g_cancellable (&priv->get_settings_cancellable); + priv->get_settings_cancellable = g_cancellable_new (); + return priv->get_settings_cancellable; } -static void -updated_get_settings_cb (GObject *proxy, - GAsyncResult *result, - gpointer user_data) +void +_nm_remote_settings_get_settings_commit (NMRemoteConnection *self, + GVariant *settings) { - NMRemoteConnection *self = user_data; NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (self); - GVariant *new_settings; - gboolean visible; - - if (!nmdbus_settings_connection_call_get_settings_finish (priv->proxy, &new_settings, - result, NULL)) { - /* Connection is no longer visible to this user. */ - nm_connection_clear_settings (NM_CONNECTION (self)); + GError *error = NULL; + gboolean visible = FALSE; + gboolean changed = FALSE; - visible = FALSE; - } else { - replace_settings (self, new_settings); - g_variant_unref (new_settings); + g_clear_object (&priv->get_settings_cancellable); - visible = TRUE; + if (!priv->is_initialized) { + changed = TRUE; + priv->is_initialized = TRUE; } - if (visible != priv->visible) { + if (settings) { + if (!_nm_connection_replace_settings ((NMConnection *) self, + settings, + NM_SETTING_PARSE_FLAGS_BEST_EFFORT, + &error)) { + NML_NMCLIENT_LOG_E (_nm_object_get_client (self), "[%s] failure to update settings: %s", + _nm_object_get_path (self), + error->message); + g_clear_error (&error); + } else + visible = TRUE; + } else + nm_connection_clear_settings (NM_CONNECTION (self)); + + if (priv->visible != visible) { priv->visible = visible; - _notify (self, PROP_VISIBLE); + _nm_client_queue_notify_object (_nm_object_get_client (self), + self, + obj_properties[PROP_VISIBLE]); + changed = TRUE; } - g_object_unref (self); -} - -static void -updated_cb (NMDBusSettingsConnection *proxy, gpointer user_data) -{ - NMRemoteConnection *self = NM_REMOTE_CONNECTION (user_data); - NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (self); - - /* The connection got updated; request the replacement settings */ - nmdbus_settings_connection_call_get_settings (priv->proxy, - NULL, - updated_get_settings_cb, - g_object_ref (self)); + if (changed) + _nm_client_notify_object_changed (_nm_object_get_client (self), _nm_object_get_dbobj (self)); } /*****************************************************************************/ -static void -init_dbus (NMObject *object) -{ - NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (object); - const NMPropertiesInfo property_info[] = { - { NM_REMOTE_CONNECTION_UNSAVED, &priv->unsaved }, - { NM_REMOTE_CONNECTION_FLAGS, &priv->flags }, - { NM_REMOTE_CONNECTION_FILENAME, &priv->filename }, - { NULL }, - }; - - NM_OBJECT_CLASS (nm_remote_connection_parent_class)->init_dbus (object); - - _nm_object_register_properties (object, - NM_DBUS_INTERFACE_SETTINGS_CONNECTION, - property_info); -} - -static gboolean -init_sync (GInitable *initable, GCancellable *cancellable, GError **error) +static NMLDBusObjState +is_visible (NMObject *nmobj) { - NMRemoteConnection *self = NM_REMOTE_CONNECTION (initable); - NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (self); - GVariant *settings; - - priv->proxy = NMDBUS_SETTINGS_CONNECTION (_nm_object_get_proxy (NM_OBJECT (initable), NM_DBUS_INTERFACE_SETTINGS_CONNECTION)); - g_signal_connect_object (priv->proxy, "updated", G_CALLBACK (updated_cb), initable, 0); - - if (nmdbus_settings_connection_call_get_settings_sync (priv->proxy, - &settings, - cancellable, - NULL)) { - priv->visible = TRUE; - replace_settings (self, settings); - g_variant_unref (settings); - } + NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (nmobj); + NMLDBusObjState obj_state; - if (!nm_remote_connection_parent_initable_iface->init (initable, cancellable, error)) - return FALSE; + if (!priv->is_initialized) + return NML_DBUS_OBJ_STATE_WITH_NMOBJ_NOT_READY; - return TRUE; -} + obj_state = NM_OBJECT_CLASS (nm_remote_connection_parent_class)->is_visible (nmobj); -typedef struct { - NMRemoteConnection *connection; - GCancellable *cancellable; - GSimpleAsyncResult *result; - GAsyncInitable *initable; - int io_priority; -} NMRemoteConnectionInitData; + if (obj_state != NML_DBUS_OBJ_STATE_WITH_NMOBJ_VISIBLE) { + nm_assert (obj_state == NML_DBUS_OBJ_STATE_WITH_NMOBJ_NOT_READY); + return NML_DBUS_OBJ_STATE_WITH_NMOBJ_NOT_READY; + } -static void -init_async_complete (NMRemoteConnectionInitData *init_data, GError *error) -{ - if (error) - g_simple_async_result_take_error (init_data->result, error); - else - g_simple_async_result_set_op_res_gboolean (init_data->result, TRUE); - - g_simple_async_result_complete (init_data->result); - g_object_unref (init_data->result); - g_clear_object (&init_data->cancellable); - g_slice_free (NMRemoteConnectionInitData, init_data); + return NML_DBUS_OBJ_STATE_WITH_NMOBJ_VISIBLE; } -static void -init_async_parent_inited (GObject *source, GAsyncResult *result, gpointer user_data) -{ - NMRemoteConnectionInitData *init_data = user_data; - GError *error = NULL; - - init_async_complete (init_data, error); -} +/*****************************************************************************/ static void -init_get_settings_cb (GObject *proxy, - GAsyncResult *result, - gpointer user_data) +register_client (NMObject *nmobj, + NMClient *client, + NMLDBusObject *dbobj) { - NMRemoteConnectionInitData *init_data = user_data; - NMRemoteConnection *self = NM_REMOTE_CONNECTION (init_data->initable); - NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (self); - GVariant *settings; - GError *error = NULL; - - if (!nmdbus_settings_connection_call_get_settings_finish (priv->proxy, &settings, - result, &error)) { - g_error_free (error); - } else { - priv->visible = TRUE; - replace_settings (NM_REMOTE_CONNECTION (init_data->initable), settings); - g_variant_unref (settings); - } - - nm_remote_connection_parent_async_initable_iface-> - init_async (init_data->initable, init_data->io_priority, init_data->cancellable, init_async_parent_inited, init_data); + NM_OBJECT_CLASS (nm_remote_connection_parent_class)->register_client (nmobj, client, dbobj); + nm_connection_set_path (NM_CONNECTION (nmobj), + dbobj->dbus_path->str); + _nm_client_get_settings_call (client, dbobj); } static void -init_async (GAsyncInitable *initable, int io_priority, - GCancellable *cancellable, GAsyncReadyCallback callback, - gpointer user_data) +unregister_client (NMObject *nmobj, + NMClient *client, + NMLDBusObject *dbobj) { - NMRemoteConnectionInitData *init_data; - NMRemoteConnection *self = NM_REMOTE_CONNECTION (initable); - NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (self); - - init_data = g_slice_new0 (NMRemoteConnectionInitData); - init_data->cancellable = cancellable ? g_object_ref (cancellable) : NULL; - init_data->result = g_simple_async_result_new (G_OBJECT (initable), callback, - user_data, init_async); - if (cancellable) - g_simple_async_result_set_check_cancellable (init_data->result, cancellable); - init_data->initable = initable; - init_data->io_priority = io_priority; - - priv->proxy = NMDBUS_SETTINGS_CONNECTION (_nm_object_get_proxy (NM_OBJECT (initable), - NM_DBUS_INTERFACE_SETTINGS_CONNECTION)); - - g_signal_connect_object (priv->proxy, "updated", - G_CALLBACK (updated_cb), initable, 0); - - nmdbus_settings_connection_call_get_settings (NM_REMOTE_CONNECTION_GET_PRIVATE (NM_REMOTE_CONNECTION (init_data->initable))->proxy, - init_data->cancellable, - init_get_settings_cb, init_data); + nm_clear_g_cancellable (&NM_REMOTE_CONNECTION_GET_PRIVATE (nmobj)->get_settings_cancellable); + NM_OBJECT_CLASS (nm_remote_connection_parent_class)->unregister_client (nmobj, client, dbobj); } -static void -nm_remote_connection_init (NMRemoteConnection *self) -{ -} +/*****************************************************************************/ static void get_property (GObject *object, guint prop_id, @@ -846,13 +748,11 @@ get_property (GObject *object, guint prop_id, } } +/*****************************************************************************/ + static void -constructed (GObject *object) +nm_remote_connection_init (NMRemoteConnection *self) { - G_OBJECT_CLASS (nm_remote_connection_parent_class)->constructed (object); - - nm_connection_set_path (NM_CONNECTION (object), - nm_object_get_path (NM_OBJECT (object))); } static void @@ -860,23 +760,34 @@ dispose (GObject *object) { NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (object); - g_clear_object (&priv->proxy); nm_clear_g_free (&priv->filename); G_OBJECT_CLASS (nm_remote_connection_parent_class)->dispose (object); } +const NMLDBusMetaIface _nml_dbus_meta_iface_nm_settings_connection = NML_DBUS_META_IFACE_INIT_PROP ( + NM_DBUS_INTERFACE_SETTINGS_CONNECTION, + nm_remote_connection_get_type, + NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, + NML_DBUS_META_IFACE_DBUS_PROPERTIES ( + NML_DBUS_META_PROPERTY_INIT_S ("Filename", PROP_FILENAME, NMRemoteConnection, _priv.filename ), + NML_DBUS_META_PROPERTY_INIT_U ("Flags", PROP_FLAGS, NMRemoteConnection, _priv.flags ), + NML_DBUS_META_PROPERTY_INIT_B ("Unsaved", PROP_UNSAVED, NMRemoteConnection, _priv.unsaved ), + ), +); + static void -nm_remote_connection_class_init (NMRemoteConnectionClass *remote_class) +nm_remote_connection_class_init (NMRemoteConnectionClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (remote_class); - NMObjectClass *nm_object_class = NM_OBJECT_CLASS (remote_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMObjectClass *nm_object_class = NM_OBJECT_CLASS (klass); object_class->get_property = get_property; - object_class->constructed = constructed; object_class->dispose = dispose; - nm_object_class->init_dbus = init_dbus; + nm_object_class->is_visible = is_visible; + nm_object_class->register_client = register_client; + nm_object_class->unregister_client = unregister_client; /** * NMRemoteConnection:unsaved: @@ -935,26 +846,10 @@ nm_remote_connection_class_init (NMRemoteConnectionClass *remote_class) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + _nml_dbus_meta_class_init_with_properties (object_class, &_nml_dbus_meta_iface_nm_settings_connection); } static void nm_remote_connection_connection_iface_init (NMConnectionInterface *iface) { } - -static void -nm_remote_connection_initable_iface_init (GInitableIface *iface) -{ - nm_remote_connection_parent_initable_iface = g_type_interface_peek_parent (iface); - - iface->init = init_sync; -} - -static void -nm_remote_connection_async_initable_iface_init (GAsyncInitableIface *iface) -{ - nm_remote_connection_parent_async_initable_iface = g_type_interface_peek_parent (iface); - - iface->init_async = init_async; -} diff --git a/libnm/nm-remote-settings.c b/libnm/nm-remote-settings.c deleted file mode 100644 index 7e46cf98d3..0000000000 --- a/libnm/nm-remote-settings.c +++ /dev/null @@ -1,479 +0,0 @@ -// SPDX-License-Identifier: LGPL-2.1+ -/* - * Copyright (C) 2008 Novell, Inc. - * Copyright (C) 2009 - 2012 Red Hat, Inc. - */ - -#include "nm-default.h" - -#include "nm-remote-settings.h" - -#include "c-list/src/c-list.h" -#include "nm-dbus-interface.h" -#include "nm-connection.h" -#include "nm-client.h" -#include "nm-remote-connection.h" -#include "nm-remote-connection-private.h" -#include "nm-object-private.h" -#include "nm-dbus-helpers.h" -#include "nm-core-internal.h" - -#include "introspection/org.freedesktop.NetworkManager.Settings.h" - -G_DEFINE_TYPE (NMRemoteSettings, nm_remote_settings, NM_TYPE_OBJECT) - -#define NM_REMOTE_SETTINGS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_REMOTE_SETTINGS, NMRemoteSettingsPrivate)) - -typedef struct { - NMDBusSettings *proxy; - GPtrArray *all_connections; - GPtrArray *visible_connections; - - /* AddConnectionInfo objects that are waiting for the connection to become initialized */ - CList add_lst_head; - - char *hostname; - gboolean can_modify; -} NMRemoteSettingsPrivate; - -NM_GOBJECT_PROPERTIES_DEFINE_BASE ( - PROP_CONNECTIONS, - PROP_HOSTNAME, - PROP_CAN_MODIFY, -); - -/* Signals */ -enum { - CONNECTION_ADDED, - CONNECTION_REMOVED, - - LAST_SIGNAL -}; -static guint signals[LAST_SIGNAL] = { 0 }; - -/*****************************************************************************/ - -typedef struct { - CList add_lst; - NMRemoteSettings *self; - GTask *task; - char *connection_path; - GVariant *extra_results; - gulong cancellable_id; -} AddConnectionInfo; - -static AddConnectionInfo * -_add_connection_info_find (NMRemoteSettings *self, const char *connection_path) -{ - NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self); - AddConnectionInfo *info; - - c_list_for_each_entry (info, &priv->add_lst_head, add_lst) { - if (nm_streq (info->connection_path, connection_path)) - return info; - } - return NULL; -} - -static void -_add_connection_info_complete (AddConnectionInfo *info, - NMRemoteConnection *connection, - GError *error_take) -{ - nm_assert (info); - - c_list_unlink_stale (&info->add_lst); - - nm_clear_g_signal_handler (g_task_get_cancellable (info->task), &info->cancellable_id); - - if (error_take) - g_task_return_error (info->task, error_take); - else { - NMAddConnectionResultData *result_info; - - result_info = g_slice_new (NMAddConnectionResultData); - *result_info = (NMAddConnectionResultData) { - .connection = g_object_ref (connection), - .extra_results = g_steal_pointer (&info->extra_results), - }; - g_task_return_pointer (info->task, result_info, (GDestroyNotify) nm_add_connection_result_data_free); - } - - g_object_unref (info->task); - g_object_unref (info->self); - g_free (info->connection_path); - nm_g_variant_unref (info->extra_results); - nm_g_slice_free (info); -} - -static void -_wait_for_connection_cancelled_cb (GCancellable *cancellable, - AddConnectionInfo *info) -{ - _add_connection_info_complete (info, - NULL, - g_error_new_literal (G_IO_ERROR, - G_IO_ERROR_CANCELLED, - "Operation was cancelled")); -} - -typedef const char * (*ConnectionStringGetter) (NMConnection *); - -static NMRemoteConnection * -get_connection_by_string (NMRemoteSettings *settings, - const char *string, - ConnectionStringGetter get_comparison_string) -{ - NMRemoteSettingsPrivate *priv; - NMConnection *candidate; - int i; - - priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings); - - for (i = 0; i < priv->visible_connections->len; i++) { - candidate = priv->visible_connections->pdata[i]; - if (!g_strcmp0 (string, get_comparison_string (candidate))) - return NM_REMOTE_CONNECTION (candidate); - } - - return NULL; -} - -NMRemoteConnection * -nm_remote_settings_get_connection_by_id (NMRemoteSettings *settings, const char *id) -{ - g_return_val_if_fail (NM_IS_REMOTE_SETTINGS (settings), NULL); - g_return_val_if_fail (id != NULL, NULL); - - return get_connection_by_string (settings, id, nm_connection_get_id); -} - -NMRemoteConnection * -nm_remote_settings_get_connection_by_path (NMRemoteSettings *settings, const char *path) -{ - g_return_val_if_fail (NM_IS_REMOTE_SETTINGS (settings), NULL); - g_return_val_if_fail (path != NULL, NULL); - - return get_connection_by_string (settings, path, nm_connection_get_path); -} - -NMRemoteConnection * -nm_remote_settings_get_connection_by_uuid (NMRemoteSettings *settings, const char *uuid) -{ - g_return_val_if_fail (NM_IS_REMOTE_SETTINGS (settings), NULL); - g_return_val_if_fail (uuid != NULL, NULL); - - return get_connection_by_string (settings, uuid, nm_connection_get_uuid); -} - -static void -connection_visible_changed (GObject *object, - GParamSpec *pspec, - gpointer user_data) -{ - NMRemoteConnection *connection = NM_REMOTE_CONNECTION (object); - NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data); - - if (nm_remote_connection_get_visible (connection)) - g_signal_emit (self, signals[CONNECTION_ADDED], 0, connection); - else - g_signal_emit (self, signals[CONNECTION_REMOVED], 0, connection); -} - -static void -cleanup_connection (NMRemoteSettings *self, - NMRemoteConnection *remote) -{ - g_signal_handlers_disconnect_by_func (remote, G_CALLBACK (connection_visible_changed), self); -} - -static void -connection_removed (NMRemoteSettings *self, - NMRemoteConnection *remote) -{ - NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self); - gboolean still_exists = FALSE; - int i; - - /* Check if the connection was actually removed or if it just turned invisible. */ - for (i = 0; i < priv->all_connections->len; i++) { - if (remote == priv->all_connections->pdata[i]) { - still_exists = TRUE; - break; - } - } - - if (!still_exists) - cleanup_connection (self, remote); - - /* Allow the signal to propagate if and only if @remote was in visible_connections */ - if (!g_ptr_array_remove (priv->visible_connections, remote)) - g_signal_stop_emission (self, signals[CONNECTION_REMOVED], 0); -} - -static void -connection_added (NMRemoteSettings *self, - NMRemoteConnection *remote) -{ - NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self); - AddConnectionInfo *info; - const char *path; - - if (!g_signal_handler_find (remote, G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, 0, 0, NULL, - G_CALLBACK (connection_visible_changed), self)) { - g_signal_connect (remote, - "notify::" NM_REMOTE_CONNECTION_VISIBLE, - G_CALLBACK (connection_visible_changed), - self); - } - - if (nm_remote_connection_get_visible (remote)) - g_ptr_array_add (priv->visible_connections, remote); - else - g_signal_stop_emission (self, signals[CONNECTION_ADDED], 0); - - /* FIXME: this doesn't look right. Why does it not care about whether the - * connection is visible? Anyway, this will be reworked. */ - path = nm_connection_get_path (NM_CONNECTION (remote)); - info = path - ? _add_connection_info_find (self, path) - : NULL; - if (info) - _add_connection_info_complete (info, remote, NULL); -} - -static void -object_creation_failed (NMObject *object, - const char *failed_path) -{ - NMRemoteSettings *self = NM_REMOTE_SETTINGS (object); - AddConnectionInfo *info; - - info = _add_connection_info_find (self, failed_path); - if (!info) - return; - - _add_connection_info_complete (info, - NULL, - g_error_new_literal (NM_CLIENT_ERROR, - NM_CLIENT_ERROR_OBJECT_CREATION_FAILED, - _("Connection removed before it was initialized"))); -} - -const GPtrArray * -nm_remote_settings_get_connections (NMRemoteSettings *settings) -{ - g_return_val_if_fail (NM_IS_REMOTE_SETTINGS (settings), NULL); - - return NM_REMOTE_SETTINGS_GET_PRIVATE (settings)->visible_connections; -} - -void -nm_remote_settings_wait_for_connection (NMRemoteSettings *self, - const char *connection_path, - GVariant *extra_results_take, - GTask *task_take) -{ - NMRemoteSettingsPrivate *priv; - gs_unref_object GTask *task = task_take; - gs_unref_variant GVariant *extra_results = extra_results_take; - GCancellable *cancellable; - AddConnectionInfo *info; - - priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self); - - /* FIXME: there is no timeout for how long we wait. But this entire - * code will be reworked, also that we have a suitable GMainContext - * where we can schedule the timeout (we shouldn't use g_main_context_default()). */ - - info = g_slice_new (AddConnectionInfo); - *info = (AddConnectionInfo) { - .self = g_object_ref (self), - .connection_path = g_strdup (connection_path), - .task = g_steal_pointer (&task), - .extra_results = g_steal_pointer (&extra_results), - }; - c_list_link_tail (&priv->add_lst_head, &info->add_lst); - - cancellable = g_task_get_cancellable (info->task); - /* On success, we still have to wait until the connection is fully - * initialized before calling the callback. - */ - if (cancellable) { - gulong id; - - id = g_cancellable_connect (cancellable, - G_CALLBACK (_wait_for_connection_cancelled_cb), - info, - NULL); - if (id == 0) { - /* the callback was invoked synchronously, which destroyed @info. - * We must not touch @info anymore. */ - } else - info->cancellable_id = id; - } - - /* FIXME: OK, we just assume the the connection is here, and that we are bound - * to get the suitable signal when the connection is fully initalized (or failed). - * Obviously, that needs reworking. */ -} - -/*****************************************************************************/ - -static void -nm_remote_settings_init (NMRemoteSettings *self) -{ - NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self); - - c_list_init (&priv->add_lst_head); - priv->all_connections = g_ptr_array_new (); - priv->visible_connections = g_ptr_array_new (); -} - -static void -init_dbus (NMObject *object) -{ - NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (object); - const NMPropertiesInfo property_info[] = { - { NM_REMOTE_SETTINGS_CONNECTIONS, &priv->all_connections, NULL, NM_TYPE_REMOTE_CONNECTION, "connection" }, - { NM_REMOTE_SETTINGS_HOSTNAME, &priv->hostname }, - { NM_REMOTE_SETTINGS_CAN_MODIFY, &priv->can_modify }, - { NULL }, - }; - - NM_OBJECT_CLASS (nm_remote_settings_parent_class)->init_dbus (object); - - priv->proxy = NMDBUS_SETTINGS (_nm_object_get_proxy (object, NM_DBUS_INTERFACE_SETTINGS)); - _nm_object_register_properties (object, - NM_DBUS_INTERFACE_SETTINGS, - property_info); -} - -static GObject * -constructor (GType type, - guint n_construct_params, - GObjectConstructParam *construct_params) -{ - guint i; - const char *dbus_path; - - /* Fill in the right D-Bus path if none was specified */ - for (i = 0; i < n_construct_params; i++) { - if (strcmp (construct_params[i].pspec->name, NM_OBJECT_PATH) == 0) { - dbus_path = g_value_get_string (construct_params[i].value); - if (dbus_path == NULL) { - g_value_set_static_string (construct_params[i].value, NM_DBUS_PATH_SETTINGS); - } else { - if (!g_variant_is_object_path (dbus_path)) { - g_warning ("Passed D-Bus object path '%s' is invalid; using default '%s' instead", - dbus_path, NM_DBUS_PATH); - g_value_set_static_string (construct_params[i].value, NM_DBUS_PATH_SETTINGS); - } - } - break; - } - } - - return G_OBJECT_CLASS (nm_remote_settings_parent_class)->constructor (type, - n_construct_params, - construct_params); -} - -static void -dispose (GObject *object) -{ - NMRemoteSettings *self = NM_REMOTE_SETTINGS (object); - NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self); - guint i; - - if (priv->all_connections) { - for (i = 0; i < priv->all_connections->len; i++) - cleanup_connection (self, priv->all_connections->pdata[i]); - g_clear_pointer (&priv->all_connections, g_ptr_array_unref); - } - - g_clear_pointer (&priv->visible_connections, g_ptr_array_unref); - g_clear_pointer (&priv->hostname, g_free); - g_clear_object (&priv->proxy); - - G_OBJECT_CLASS (nm_remote_settings_parent_class)->dispose (object); -} - -static void -get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (object); - - switch (prop_id) { - case PROP_CONNECTIONS: - g_value_take_boxed (value, _nm_utils_copy_object_array (priv->visible_connections)); - break; - case PROP_HOSTNAME: - g_value_set_string (value, priv->hostname); - break; - case PROP_CAN_MODIFY: - g_value_set_boolean (value, priv->can_modify); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -nm_remote_settings_class_init (NMRemoteSettingsClass *class) -{ - GObjectClass *object_class = G_OBJECT_CLASS (class); - NMObjectClass *nm_object_class = NM_OBJECT_CLASS (class); - - g_type_class_add_private (class, sizeof (NMRemoteSettingsPrivate)); - - object_class->get_property = get_property; - object_class->constructor = constructor; - object_class->dispose = dispose; - - nm_object_class->init_dbus = init_dbus; - nm_object_class->object_creation_failed = object_creation_failed; - - class->connection_added = connection_added; - class->connection_removed = connection_removed; - - obj_properties[PROP_CONNECTIONS] = - g_param_spec_boxed (NM_REMOTE_SETTINGS_CONNECTIONS, "", "", - G_TYPE_PTR_ARRAY, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_HOSTNAME] = - g_param_spec_string (NM_REMOTE_SETTINGS_HOSTNAME, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_CAN_MODIFY] = - g_param_spec_boolean (NM_REMOTE_SETTINGS_CAN_MODIFY, "", "", - FALSE, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - signals[CONNECTION_ADDED] = - g_signal_new (NM_REMOTE_SETTINGS_CONNECTION_ADDED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMRemoteSettingsClass, connection_added), - NULL, NULL, NULL, - G_TYPE_NONE, 1, - NM_TYPE_REMOTE_CONNECTION); - - signals[CONNECTION_REMOVED] = - g_signal_new (NM_REMOTE_SETTINGS_CONNECTION_REMOVED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMRemoteSettingsClass, connection_removed), - NULL, NULL, NULL, - G_TYPE_NONE, 1, - NM_TYPE_REMOTE_CONNECTION); -} diff --git a/libnm/nm-remote-settings.h b/libnm/nm-remote-settings.h deleted file mode 100644 index 53d1767b58..0000000000 --- a/libnm/nm-remote-settings.h +++ /dev/null @@ -1,77 +0,0 @@ -// SPDX-License-Identifier: LGPL-2.1+ -/* - * Copyright (C) 2008 Novell, Inc. - * Copyright (C) 2009 - 2011 Red Hat, Inc. - */ - -#ifndef __NM_REMOTE_SETTINGS_H__ -#define __NM_REMOTE_SETTINGS_H__ - -#if !((NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_PRIVATE) -#error Cannot use this header. -#endif - -#include "nm-object.h" - -#define NM_TYPE_REMOTE_SETTINGS (nm_remote_settings_get_type ()) -#define NM_REMOTE_SETTINGS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_REMOTE_SETTINGS, NMRemoteSettings)) -#define NM_REMOTE_SETTINGS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_REMOTE_SETTINGS, NMRemoteSettingsClass)) -#define NM_IS_REMOTE_SETTINGS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_REMOTE_SETTINGS)) -#define NM_IS_REMOTE_SETTINGS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_REMOTE_SETTINGS)) -#define NM_REMOTE_SETTINGS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_REMOTE_SETTINGS, NMRemoteSettingsClass)) - -#define NM_REMOTE_SETTINGS_CONNECTIONS "connections" -#define NM_REMOTE_SETTINGS_HOSTNAME "hostname" -#define NM_REMOTE_SETTINGS_CAN_MODIFY "can-modify" - -#define NM_REMOTE_SETTINGS_CONNECTION_ADDED "connection-added" -#define NM_REMOTE_SETTINGS_CONNECTION_REMOVED "connection-removed" - -typedef struct _NMRemoteSettings NMRemoteSettings; -typedef struct _NMRemoteSettingsClass NMRemoteSettingsClass; - -/** - * NMRemoteSettings: - */ -struct _NMRemoteSettings { - NMObject parent; -}; - -struct _NMRemoteSettingsClass { - NMObjectClass parent; - - void (*connection_added) (NMRemoteSettings *settings, - NMRemoteConnection *connection); - void (*connection_removed) (NMRemoteSettings *settings, - NMRemoteConnection *connection); -}; - -GType nm_remote_settings_get_type (void); - -const GPtrArray *nm_remote_settings_get_connections (NMRemoteSettings *settings); - -NMRemoteConnection *nm_remote_settings_get_connection_by_id (NMRemoteSettings *settings, - const char *id); - -NMRemoteConnection *nm_remote_settings_get_connection_by_path (NMRemoteSettings *settings, - const char *path); - -NMRemoteConnection *nm_remote_settings_get_connection_by_uuid (NMRemoteSettings *settings, - const char *uuid); - -typedef struct { - NMRemoteConnection *connection; - GVariant *extra_results; -} NMAddConnectionResultData; - -void nm_add_connection_result_data_free (NMAddConnectionResultData *result_data); - -NM_AUTO_DEFINE_FCN0 (NMAddConnectionResultData *, _nm_auto_free_add_connection_result_data, nm_add_connection_result_data_free) -#define nm_auto_free_add_connection_result_data nm_auto (_nm_auto_free_add_connection_result_data) - -void nm_remote_settings_wait_for_connection (NMRemoteSettings *settings, - const char *connection_path, - GVariant *extra_results_take, - GTask *task_take); - -#endif /* __NM_REMOTE_SETTINGS_H__ */ diff --git a/libnm/nm-vpn-connection.c b/libnm/nm-vpn-connection.c index a0d673e913..26980229f3 100644 --- a/libnm/nm-vpn-connection.c +++ b/libnm/nm-vpn-connection.c @@ -14,8 +14,6 @@ #include "nm-active-connection.h" #include "nm-dbus-helpers.h" -#include "introspection/org.freedesktop.NetworkManager.VPN.Connection.h" - /*****************************************************************************/ NM_GOBJECT_PROPERTIES_DEFINE (NMVpnConnection, @@ -33,7 +31,8 @@ static guint signals[LAST_SIGNAL] = { 0 }; typedef struct { char *banner; - NMVpnConnectionState vpn_state; + guint32 vpn_state; + guint32 reason; } NMVpnConnectionPrivate; struct _NMVpnConnection { @@ -86,20 +85,48 @@ nm_vpn_connection_get_vpn_state (NMVpnConnection *vpn) return NM_VPN_CONNECTION_GET_PRIVATE (vpn)->vpn_state; } +/*****************************************************************************/ + static void -vpn_state_changed_proxy (NMDBusVpnConnection *proxy, - guint vpn_state, - guint reason, - gpointer user_data) +_notify_event_state_changed (NMClient *client, + NMClientNotifyEventWithPtr *notify_event) +{ + gs_unref_object NMVpnConnection *self = notify_event->user_data; + NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (self); + + /* we expose here the value cache in @priv. In practice, this is the same + * value as we received from the signal. In the unexpected case where they + * differ, the cached value of the current instance would still be more correct. */ + g_signal_emit (self, + signals[VPN_STATE_CHANGED], + 0, + (guint) priv->vpn_state, + (guint) priv->reason); +} + +void +_nm_vpn_connection_state_changed_commit (NMVpnConnection *self, + guint32 state, + guint32 reason) { - NMVpnConnection *connection = NM_VPN_CONNECTION (user_data); - NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (connection); + NMClient *client; + NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (self); + + client = _nm_object_get_client (self); - if (priv->vpn_state != vpn_state) { - priv->vpn_state = vpn_state; - g_signal_emit (connection, signals[VPN_STATE_CHANGED], 0, vpn_state, reason); - _notify (connection, PROP_VPN_STATE); + if (priv->vpn_state != state) { + priv->vpn_state = state; + _nm_client_queue_notify_object (client, + self, + obj_properties[PROP_VPN_STATE]); } + + priv->reason = reason; + + _nm_client_notify_event_queue_with_ptr (client, + NM_CLIENT_NOTIFY_EVENT_PRIO_GPROP + 1, + _notify_event_state_changed, + g_object_ref (self)); } /*****************************************************************************/ @@ -107,32 +134,6 @@ vpn_state_changed_proxy (NMDBusVpnConnection *proxy, static void nm_vpn_connection_init (NMVpnConnection *connection) { - NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (connection); - - priv->vpn_state = NM_VPN_CONNECTION_STATE_UNKNOWN; -} - -static void -init_dbus (NMObject *object) -{ - NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (object); - const NMPropertiesInfo property_info[] = { - { NM_VPN_CONNECTION_BANNER, &priv->banner }, - { NM_VPN_CONNECTION_VPN_STATE, &priv->vpn_state }, - { NULL }, - }; - GDBusProxy *proxy; - - NM_OBJECT_CLASS (nm_vpn_connection_parent_class)->init_dbus (object); - - _nm_object_register_properties (object, - NM_DBUS_INTERFACE_VPN_CONNECTION, - property_info); - - proxy = _nm_object_get_proxy (object, NM_DBUS_INTERFACE_VPN_CONNECTION); - g_signal_connect_object (proxy, "vpn-state-changed", - G_CALLBACK (vpn_state_changed_proxy), object, 0); - g_object_unref (proxy); } static void @@ -166,17 +167,24 @@ get_property (GObject *object, } } +const NMLDBusMetaIface _nml_dbus_meta_iface_nm_vpn_connection = NML_DBUS_META_IFACE_INIT_PROP ( + NM_DBUS_INTERFACE_VPN_CONNECTION, + nm_vpn_connection_get_type, + NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, + NML_DBUS_META_IFACE_DBUS_PROPERTIES ( + NML_DBUS_META_PROPERTY_INIT_S ("Banner", PROP_BANNER, NMVpnConnection, _priv.banner ), + NML_DBUS_META_PROPERTY_INIT_U ("VpnState", PROP_VPN_STATE, NMVpnConnection, _priv.vpn_state ), + ), +); + static void nm_vpn_connection_class_init (NMVpnConnectionClass *connection_class) { GObjectClass *object_class = G_OBJECT_CLASS (connection_class); - NMObjectClass *nm_object_class = NM_OBJECT_CLASS (connection_class); object_class->get_property = get_property; object_class->finalize = finalize; - nm_object_class->init_dbus = init_dbus; - /** * NMVpnConnection:vpn-state: * @@ -200,7 +208,13 @@ nm_vpn_connection_class_init (NMVpnConnectionClass *connection_class) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + _nml_dbus_meta_class_init_with_properties (object_class, &_nml_dbus_meta_iface_nm_vpn_connection); + + /* TODO: the state reason should also be exposed as a property in libnm's NMVpnConnection, + * like done for NMDevice's state reason. */ + + /* TODO: the D-Bus API should also expose the state-reason as a property instead of + * a "VpnStateChanged" signal. Like done for Device's "StateReason". */ G_GNUC_BEGIN_IGNORE_DEPRECATIONS signals[VPN_STATE_CHANGED] = diff --git a/libnm/nm-wifi-p2p-peer.c b/libnm/nm-wifi-p2p-peer.c index 73dc5fc047..509104454c 100644 --- a/libnm/nm-wifi-p2p-peer.c +++ b/libnm/nm-wifi-p2p-peer.c @@ -30,20 +30,15 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( ); typedef struct { + GBytes *wfd_ies; char *name; char *manufacturer; char *model; char *model_number; char *serial; - - GBytes *wfd_ies; - char *hw_address; - - int last_seen; - - NM80211ApFlags flags; - + gint32 last_seen; + guint32 flags; guint8 strength; } NMWifiP2PPeerPrivate; @@ -340,33 +335,6 @@ nm_wifi_p2p_peer_filter_connections (NMWifiP2PPeer *peer, const GPtrArray *conne /*****************************************************************************/ static void -init_dbus (NMObject *object) -{ - NMWifiP2PPeerPrivate *priv = NM_WIFI_P2P_PEER_GET_PRIVATE (object); - const NMPropertiesInfo property_info[] = { - { NM_WIFI_P2P_PEER_FLAGS, &priv->flags }, - { NM_WIFI_P2P_PEER_NAME, &priv->name }, - { NM_WIFI_P2P_PEER_MANUFACTURER, &priv->manufacturer }, - { NM_WIFI_P2P_PEER_MODEL, &priv->model }, - { NM_WIFI_P2P_PEER_MODEL_NUMBER, &priv->model_number }, - { NM_WIFI_P2P_PEER_SERIAL, &priv->serial }, - { NM_WIFI_P2P_PEER_WFD_IES, &priv->wfd_ies }, - { NM_WIFI_P2P_PEER_HW_ADDRESS, &priv->hw_address }, - { NM_WIFI_P2P_PEER_STRENGTH, &priv->strength }, - { NM_WIFI_P2P_PEER_LAST_SEEN, &priv->last_seen }, - { NULL }, - }; - - NM_OBJECT_CLASS (nm_wifi_p2p_peer_parent_class)->init_dbus (object); - - _nm_object_register_properties (object, - NM_DBUS_INTERFACE_WIFI_P2P_PEER, - property_info); -} - -/*****************************************************************************/ - -static void get_property (GObject *object, guint prop_id, GValue *value, @@ -429,7 +397,6 @@ finalize (GObject *object) g_free (priv->model); g_free (priv->model_number); g_free (priv->serial); - g_free (priv->hw_address); g_bytes_unref (priv->wfd_ies); @@ -437,17 +404,31 @@ finalize (GObject *object) G_OBJECT_CLASS (nm_wifi_p2p_peer_parent_class)->finalize (object); } +const NMLDBusMetaIface _nml_dbus_meta_iface_nm_wifip2ppeer = NML_DBUS_META_IFACE_INIT_PROP ( + NM_DBUS_INTERFACE_WIFI_P2P_PEER, + nm_wifi_p2p_peer_get_type, + NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, + NML_DBUS_META_IFACE_DBUS_PROPERTIES ( + NML_DBUS_META_PROPERTY_INIT_U ("Flags", PROP_FLAGS, NMWifiP2PPeer, _priv.flags ), + NML_DBUS_META_PROPERTY_INIT_S ("HwAddress", PROP_HW_ADDRESS, NMWifiP2PPeer, _priv.hw_address ), + NML_DBUS_META_PROPERTY_INIT_I ("LastSeen", PROP_LAST_SEEN, NMWifiP2PPeer, _priv.last_seen ), + NML_DBUS_META_PROPERTY_INIT_S ("Manufacturer", PROP_MANUFACTURER, NMWifiP2PPeer, _priv.manufacturer ), + NML_DBUS_META_PROPERTY_INIT_S ("Model", PROP_MODEL, NMWifiP2PPeer, _priv.model ), + NML_DBUS_META_PROPERTY_INIT_S ("ModelNumber", PROP_MODEL_NUMBER, NMWifiP2PPeer, _priv.model_number ), + NML_DBUS_META_PROPERTY_INIT_S ("Serial", PROP_SERIAL, NMWifiP2PPeer, _priv.serial ), + NML_DBUS_META_PROPERTY_INIT_Y ("Strength", PROP_STRENGTH, NMWifiP2PPeer, _priv.strength ), + NML_DBUS_META_PROPERTY_INIT_AY ("WfdIEs", PROP_WFD_IES, NMWifiP2PPeer, _priv.wfd_ies ), + ), +); + static void nm_wifi_p2p_peer_class_init (NMWifiP2PPeerClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMObjectClass *nm_object_class = NM_OBJECT_CLASS (klass); object_class->get_property = get_property; object_class->finalize = finalize; - nm_object_class->init_dbus = init_dbus; - /** * NMWifiP2PPeer:flags: * @@ -579,5 +560,5 @@ nm_wifi_p2p_peer_class_init (NMWifiP2PPeerClass *klass) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + _nml_dbus_meta_class_init_with_properties (object_class, &_nml_dbus_meta_iface_nm_wifip2ppeer); } diff --git a/libnm/tests/test-libnm.c b/libnm/tests/test-libnm.c index 8af1c28ffa..345fbb07b8 100644 --- a/libnm/tests/test-libnm.c +++ b/libnm/tests/test-libnm.c @@ -11,7 +11,16 @@ #include <sys/mman.h> +#include "NetworkManager.h" +#include "nm-access-point.h" +#include "nm-checkpoint.h" +#include "nm-dhcp4-config.h" +#include "nm-dhcp6-config.h" +#include "nm-dns-manager.h" +#include "nm-ip4-config.h" +#include "nm-ip6-config.h" #include "nm-libnm-utils.h" +#include "nm-object.h" #include "nm-vpn-service-plugin.h" #include "nm-utils/nm-test-utils.h" @@ -2488,7 +2497,6 @@ test_types (void) G (nm_dhcp6_config_get_type), G (nm_dhcp_config_get_type), G (nm_dns_entry_get_type), - G (nm_dns_manager_get_type), G (nm_ip4_config_get_type), G (nm_ip6_config_get_type), G (nm_ip_address_get_type), @@ -2500,12 +2508,10 @@ test_types (void) G (nm_ip_tunnel_mode_get_type), G (nm_lldp_neighbor_get_type), G (nm_manager_error_get_type), - G (nm_manager_get_type), G (nm_manager_reload_flags_get_type), G (nm_metered_get_type), G (nm_object_get_type), G (nm_remote_connection_get_type), - G (nm_remote_settings_get_type), G (nm_secret_agent_capabilities_get_type), G (nm_secret_agent_error_get_type), G (nm_secret_agent_get_secrets_flags_get_type), @@ -2665,6 +2671,401 @@ test_types (void) /*****************************************************************************/ +static void +test_nml_dbus_meta (void) +{ + const NMLDBusMetaIface *meta_iface; + const NMLDBusMetaProperty *meta_property; + guint prop_idx; + gsize i, j; + guint l, m; + + for (i = 0; i < G_N_ELEMENTS (_nml_dbus_meta_ifaces); i++) { + const NMLDBusMetaIface *mif = _nml_dbus_meta_ifaces[i]; + nm_auto_unref_gtypeclass GObjectClass *klass_unref = NULL; + GObjectClass *klass; + GType gtype; + +#define COMMON_PREFIX "org.freedesktop.NetworkManager" + + g_assert (mif); + g_assert (mif->dbus_iface_name); + g_assert ( g_str_has_prefix (mif->dbus_iface_name, COMMON_PREFIX) + && !g_str_has_suffix (mif->dbus_iface_name, ".") + && NM_IN_SET (mif->dbus_iface_name[NM_STRLEN (COMMON_PREFIX)], '\0', '.')); + for (j = i + 1; j < G_N_ELEMENTS (_nml_dbus_meta_ifaces); j++) + g_assert (mif != _nml_dbus_meta_ifaces[j]); + if (i > 0) { + if (strcmp (_nml_dbus_meta_ifaces[i - 1]->dbus_iface_name, mif->dbus_iface_name) >= 0) { + g_error ("meta-ifaces are not properly sorted: [%zu] \"%s\" should be after [%zu] \"%s\"", + i - 1, _nml_dbus_meta_ifaces[i - 1]->dbus_iface_name, i, mif->dbus_iface_name); + } + } + + g_assert ((mif->n_dbus_properties > 0) == (!!mif->dbus_properties)); + + if (mif->interface_prio == NML_DBUS_META_INTERFACE_PRIO_NONE) { + g_assert (!mif->get_type_fcn); + g_assert (!mif->obj_properties); + g_assert (mif->n_obj_properties == 0); + g_assert (!mif->obj_properties_reverse_idx); + if (!NM_IN_STRSET (mif->dbus_iface_name, NM_DBUS_INTERFACE_AGENT_MANAGER, + NM_DBUS_INTERFACE_DEVICE_STATISTICS, + NM_DBUS_INTERFACE_DEVICE_VETH)) + g_error ("D-Bus interface \"%s\" is unexpectedly empty", mif->dbus_iface_name); + if (mif->n_dbus_properties == 0) + continue; + gtype = G_TYPE_NONE; + klass = NULL; + goto check_dbus_properties; + } + + g_assert (NM_IN_SET ((NMLDBusMetaInteracePrio) mif->interface_prio, NML_DBUS_META_INTERFACE_PRIO_NMCLIENT, + NML_DBUS_META_INTERFACE_PRIO_PARENT_TYPE, + NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_LOW, + NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH)); + + g_assert (mif->get_type_fcn); + gtype = mif->get_type_fcn (); + g_assert (g_type_is_a (gtype, G_TYPE_OBJECT)); + + if (mif->interface_prio == NML_DBUS_META_INTERFACE_PRIO_NMCLIENT) + g_assert (gtype == NM_TYPE_CLIENT); + else + g_assert (g_type_is_a (gtype, NM_TYPE_OBJECT)); + + /* We only test parts of the types, and avoid initializing all the types. + * That is so that other unit tests in this process randomly run with either + * the class instance already initialized or not. */ + if ((nmtst_get_rand_uint () % 5) == 0) { + klass = (klass_unref = g_type_class_ref (gtype)); + g_assert (klass); + } else + klass = g_type_class_peek (gtype); + + if (klass) { + if (NM_IS_OBJECT_CLASS (klass)) { + NMObjectClass *nm_object_class = NM_OBJECT_CLASS (klass); + const _NMObjectClassFieldInfo *p_prev; + const _NMObjectClassFieldInfo *p; + + p_prev = NULL; + for (p = nm_object_class->property_o_info; p; p_prev = p, p = p->parent) { + g_assert (p->num > 0); + g_assert (NM_IS_OBJECT_CLASS (p->klass)); + g_assert (g_type_is_a (gtype, G_TYPE_FROM_CLASS (p->klass))); + g_assert (p->klass->property_o_info == p); + if (p_prev) { + g_assert (g_type_is_a (G_TYPE_FROM_CLASS (p_prev->klass), G_TYPE_FROM_CLASS (p->klass))); + g_assert (p_prev->klass != p->klass); + } + } + } else + g_assert (NM_IS_CLIENT_CLASS (klass)); + } + + if (!mif->obj_properties) { + g_assert_cmpint (mif->n_obj_properties, ==, 0); + g_assert (!mif->obj_properties_reverse_idx); + } else { + g_assert (mif->obj_properties); + g_assert (mif->obj_properties[0] == 0); + g_assert_cmpint (mif->n_obj_properties, >, 1); + if (klass) { + for (l = 1; l < mif->n_obj_properties; l++) { + const GParamSpec *sp = mif->obj_properties[l]; + + g_assert (sp); + g_assert (sp->name); + g_assert (strlen (sp->name) > 0); + } + } + + g_assert (mif->obj_properties_reverse_idx); + if (klass) { + g_assert (mif->obj_properties_reverse_idx[0] == 0xFFu); + for (l = 0; l < mif->n_obj_properties; l++) { + guint8 ridx = mif->obj_properties_reverse_idx[l]; + + if (ridx != 0xFFu) { + g_assert_cmpint (ridx, <=, mif->n_dbus_properties); + for (m = l + 1; m < mif->n_obj_properties; m++) + g_assert_cmpint (ridx, !=, mif->obj_properties_reverse_idx[m]); + } + } + } + } + +check_dbus_properties: + for (l = 0; l < mif->n_dbus_properties; l++) { + const NMLDBusMetaProperty *mpr = &mif->dbus_properties[l]; + gs_free char *obj_property_name = NULL; + const struct { + const char *dbus_type; + GType default_gtype; + } *p_expected_type, *p_expected_type_2, expected_types[] = { + { "b", G_TYPE_BOOLEAN }, + { "q", G_TYPE_UINT }, + { "y", G_TYPE_UCHAR }, + { "i", G_TYPE_INT }, + { "u", G_TYPE_UINT }, + { "x", G_TYPE_INT64 }, + { "t", G_TYPE_UINT64 }, + { "s", G_TYPE_STRING }, + { "o", G_TYPE_STRING }, + { "ay", G_TYPE_BYTES }, + { "as", G_TYPE_STRV }, + { "ao", G_TYPE_PTR_ARRAY }, + { "a{sv}", G_TYPE_HASH_TABLE }, + { "aa{sv}", G_TYPE_PTR_ARRAY }, + + { "(uu)", G_TYPE_NONE }, + { "aau", G_TYPE_NONE }, + { "au", G_TYPE_NONE }, + { "a(ayuay)", G_TYPE_NONE }, + { "aay", G_TYPE_NONE }, + { "a(ayuayu)", G_TYPE_NONE }, + + { "u", G_TYPE_FLAGS }, + { "u", G_TYPE_ENUM }, + { "o", NM_TYPE_OBJECT }, + }; + const GParamSpec *pspec = NULL; + + g_assert (mpr->dbus_property_name); + g_assert (g_variant_type_string_is_valid ((const char *) mpr->dbus_type)); + if (l > 0) { + if (strcmp (mif->dbus_properties[l - 1].dbus_property_name, mpr->dbus_property_name) >= 0) { + g_error ("meta-ifaces[%s] must have property #%u \"%s\" after #%u \"%s\"", + mif->dbus_iface_name, l - 1, mif->dbus_properties[l - 1].dbus_property_name, l, mpr->dbus_property_name); + } + } + + obj_property_name = nm_utils_wincaps_to_dash (mpr->dbus_property_name); + g_assert (obj_property_name); + + for (p_expected_type = &expected_types[0]; TRUE; ) { + if (nm_streq ((const char *) mpr->dbus_type, p_expected_type->dbus_type)) + break; + p_expected_type++; + if (p_expected_type >= &expected_types[G_N_ELEMENTS (expected_types)]) { + g_error ("D-Bus type \"%s\" is not implemented (in property %s.%s)", + (const char *) mpr->dbus_type, + mif->dbus_iface_name, + mpr->dbus_property_name); + } + } + + if ( klass + && mpr->obj_properties_idx > 0) { + g_assert_cmpint (mpr->obj_properties_idx, <, mif->n_obj_properties); + if (!mpr->obj_property_no_reverse_idx) + g_assert_cmpint (mif->obj_properties_reverse_idx[mpr->obj_properties_idx], ==, l); + else { + g_assert_cmpint (mif->obj_properties_reverse_idx[mpr->obj_properties_idx], !=, l); + g_assert_cmpint (mif->obj_properties_reverse_idx[mpr->obj_properties_idx], !=, 0xFFu); + } + pspec = mif->obj_properties[mpr->obj_properties_idx]; + } + + if (mpr->use_notify_update_prop) { + g_assert (mpr->notify_update_prop); + } else { + if (klass) + g_assert (pspec); + } + + if (pspec) { + const char *expected_property_name; + + if ( mif == &_nml_dbus_meta_iface_nm_connection_active + && nm_streq (pspec->name, NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT_PATH)) { + g_assert_cmpstr (obj_property_name, ==, "specific-object"); + expected_property_name = NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT_PATH; + } else if ( mif == &_nml_dbus_meta_iface_nm_accesspoint + && nm_streq (pspec->name, NM_ACCESS_POINT_BSSID)) { + g_assert_cmpstr (obj_property_name, ==, "hw-address"); + expected_property_name = NM_ACCESS_POINT_BSSID; + } else if ( mif == &_nml_dbus_meta_iface_nm_device_wireguard + && nm_streq (pspec->name, NM_DEVICE_WIREGUARD_FWMARK)) { + g_assert_cmpstr (obj_property_name, ==, "fw-mark"); + expected_property_name = NM_DEVICE_WIREGUARD_FWMARK; + } else if ( NM_IN_SET (mif, &_nml_dbus_meta_iface_nm_ip4config, + &_nml_dbus_meta_iface_nm_ip6config) + && nm_streq (pspec->name, NM_IP_CONFIG_ADDRESSES)) { + g_assert (NM_IN_STRSET (obj_property_name, "addresses", "address-data")); + expected_property_name = NM_IP_CONFIG_ADDRESSES; + } else if ( NM_IN_SET (mif, &_nml_dbus_meta_iface_nm_ip4config, + &_nml_dbus_meta_iface_nm_ip6config) + && nm_streq (pspec->name, NM_IP_CONFIG_ROUTES)) { + g_assert (NM_IN_STRSET (obj_property_name, "routes", "route-data")); + expected_property_name = NM_IP_CONFIG_ROUTES; + } else if ( NM_IN_SET (mif, &_nml_dbus_meta_iface_nm_ip4config, + &_nml_dbus_meta_iface_nm_ip6config) + && nm_streq (pspec->name, NM_IP_CONFIG_NAMESERVERS)) { + g_assert (NM_IN_STRSET (obj_property_name, "nameservers", "nameserver-data")); + expected_property_name = NM_IP_CONFIG_NAMESERVERS; + } else if ( mif == &_nml_dbus_meta_iface_nm_ip4config + && nm_streq (pspec->name, NM_IP_CONFIG_WINS_SERVERS)) { + g_assert (NM_IN_STRSET (obj_property_name, "wins-servers", "wins-server-data")); + expected_property_name = NM_IP_CONFIG_WINS_SERVERS; + } else if ( mif == &_nml_dbus_meta_iface_nm_dnsmanager + && nm_streq (pspec->name, NM_CLIENT_DNS_CONFIGURATION)) { + g_assert_cmpstr (obj_property_name, ==, "configuration"); + expected_property_name = NM_CLIENT_DNS_CONFIGURATION; + } else if ( mif == &_nml_dbus_meta_iface_nm_dnsmanager + && nm_streq (pspec->name, NM_CLIENT_DNS_MODE)) { + g_assert_cmpstr (obj_property_name, ==, "mode"); + expected_property_name = NM_CLIENT_DNS_MODE; + } else if ( mif == &_nml_dbus_meta_iface_nm_dnsmanager + && nm_streq (pspec->name, NM_CLIENT_DNS_RC_MANAGER)) { + g_assert_cmpstr (obj_property_name, ==, "rc-manager"); + expected_property_name = NM_CLIENT_DNS_RC_MANAGER; + } else + expected_property_name = obj_property_name; + + g_assert_cmpstr (expected_property_name, ==, pspec->name); + + if (!mpr->use_notify_update_prop) { + for (p_expected_type_2 = &expected_types[0]; p_expected_type_2 < &expected_types[G_N_ELEMENTS (expected_types)]; p_expected_type_2++) { + if (!nm_streq ((const char *) mpr->dbus_type, p_expected_type_2->dbus_type)) + continue; + if ( pspec->value_type == p_expected_type_2->default_gtype + || ( p_expected_type_2->default_gtype == G_TYPE_ENUM + && g_type_is_a (pspec->value_type, G_TYPE_ENUM)) + || ( p_expected_type_2->default_gtype == G_TYPE_FLAGS + && g_type_is_a (pspec->value_type, G_TYPE_FLAGS)) + || ( p_expected_type_2->default_gtype == NM_TYPE_OBJECT + && nm_streq ((const char *) mpr->dbus_type, "o") + && g_type_is_a (pspec->value_type, NM_TYPE_OBJECT))) + break; + } + if (p_expected_type_2 >= &expected_types[G_N_ELEMENTS (expected_types)]) { + g_error ("D-Bus property \"%s.%s\" (type \"%s\") maps to property \"%s\", but that has an unexpected property type %s (expected %s)", + mif->dbus_iface_name, + mpr->dbus_property_name, + (const char *) mpr->dbus_type, + pspec->name, + g_type_name (pspec->value_type), + g_type_name (p_expected_type->default_gtype)); + } + } + + if (!nm_utils_g_param_spec_is_default (pspec)) { + /* We expect our properties to have a default value of zero/NULL. + * Except those whitelisted here: */ + if ( ( mif == &_nml_dbus_meta_iface_nm_accesspoint + && nm_streq (pspec->name, NM_ACCESS_POINT_LAST_SEEN)) + || ( mif == &_nml_dbus_meta_iface_nm_device_vxlan + && nm_streq (pspec->name, NM_DEVICE_VXLAN_LEARNING)) + || ( mif == &_nml_dbus_meta_iface_nm_device_wireless + && nm_streq (pspec->name, NM_DEVICE_WIFI_LAST_SCAN)) + || ( mif == &_nml_dbus_meta_iface_nm_wifip2ppeer + && nm_streq (pspec->name, NM_WIFI_P2P_PEER_LAST_SEEN)) + || ( mif == &_nml_dbus_meta_iface_nm_device_tun + && NM_IN_STRSET (pspec->name, NM_DEVICE_TUN_GROUP, + NM_DEVICE_TUN_OWNER))) { + /* pass */ + } else { + g_error ("property %s.%s (%s.%s) does not have a default value of zero", + mif->dbus_iface_name, + mpr->dbus_property_name, + g_type_name (gtype), + pspec->name); + } + } + } + } + + if (klass) { + for (l = 0; l < mif->n_obj_properties; l++) { + guint8 ridx = mif->obj_properties_reverse_idx[l]; + + if (ridx != 0xFFu) + g_assert_cmpint (mif->dbus_properties[ridx].obj_properties_idx, ==, l); + } + } + + g_assert (mif == nml_dbus_meta_iface_get (mif->dbus_iface_name)); + } + + meta_iface = nml_dbus_meta_iface_get (NM_DBUS_INTERFACE); + g_assert (meta_iface); + g_assert (meta_iface == &_nml_dbus_meta_iface_nm); + g_assert_cmpstr (meta_iface->dbus_iface_name, ==, NM_DBUS_INTERFACE); + + meta_property = nml_dbus_meta_property_get (meta_iface, "Version", &prop_idx); + g_assert (meta_property); + g_assert_cmpstr (meta_property->dbus_property_name, ==, "Version"); + g_assert (&meta_iface->dbus_properties[prop_idx] == meta_property); +} + +/*****************************************************************************/ + +static void +test_dbus_meta_types (void) +{ + struct list_data { + const char *dbus_iface_name; + GType gtype; + NMLDBusMetaInteracePrio interface_prio; + } list[] = { + { NM_DBUS_INTERFACE, NM_TYPE_CLIENT, NML_DBUS_META_INTERFACE_PRIO_NMCLIENT, }, + { NM_DBUS_INTERFACE_ACCESS_POINT, NM_TYPE_ACCESS_POINT, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, }, + { NM_DBUS_INTERFACE_ACTIVE_CONNECTION, NM_TYPE_ACTIVE_CONNECTION, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_LOW, }, /* otherwise, NM_TYPE_VPN_CONNECTION. */ + { NM_DBUS_INTERFACE_DEVICE_6LOWPAN, NM_TYPE_DEVICE_6LOWPAN, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, }, + { NM_DBUS_INTERFACE_DEVICE_ADSL, NM_TYPE_DEVICE_ADSL, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, }, + { NM_DBUS_INTERFACE_DEVICE_BOND, NM_TYPE_DEVICE_BOND, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, }, + { NM_DBUS_INTERFACE_DEVICE_BRIDGE, NM_TYPE_DEVICE_BRIDGE, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, }, + { NM_DBUS_INTERFACE_DEVICE_BLUETOOTH, NM_TYPE_DEVICE_BT, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, }, + { NM_DBUS_INTERFACE_DEVICE_DUMMY, NM_TYPE_DEVICE_DUMMY, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, }, + { NM_DBUS_INTERFACE_DEVICE_WIRED, NM_TYPE_DEVICE_ETHERNET, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, }, + { NM_DBUS_INTERFACE_DEVICE_GENERIC, NM_TYPE_DEVICE_GENERIC, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, }, + { NM_DBUS_INTERFACE_DEVICE_INFINIBAND, NM_TYPE_DEVICE_INFINIBAND, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, }, + { NM_DBUS_INTERFACE_DEVICE_IP_TUNNEL, NM_TYPE_DEVICE_IP_TUNNEL, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, }, + { NM_DBUS_INTERFACE_DEVICE_MACSEC, NM_TYPE_DEVICE_MACSEC, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, }, + { NM_DBUS_INTERFACE_DEVICE_MACVLAN, NM_TYPE_DEVICE_MACVLAN, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, }, + { NM_DBUS_INTERFACE_DEVICE_MODEM, NM_TYPE_DEVICE_MODEM, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, }, + { NM_DBUS_INTERFACE_DEVICE_OLPC_MESH, NM_TYPE_DEVICE_OLPC_MESH, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, }, + { NM_DBUS_INTERFACE_DEVICE_OVS_INTERFACE, NM_TYPE_DEVICE_OVS_INTERFACE, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, }, + { NM_DBUS_INTERFACE_DEVICE_OVS_PORT, NM_TYPE_DEVICE_OVS_PORT, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, }, + { NM_DBUS_INTERFACE_DEVICE_OVS_BRIDGE, NM_TYPE_DEVICE_OVS_BRIDGE, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, }, + { NM_DBUS_INTERFACE_DEVICE_WIFI_P2P, NM_TYPE_DEVICE_WIFI_P2P, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, }, + { NM_DBUS_INTERFACE_DEVICE_PPP, NM_TYPE_DEVICE_PPP, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, }, + { NM_DBUS_INTERFACE_DEVICE_TEAM, NM_TYPE_DEVICE_TEAM, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, }, + { NM_DBUS_INTERFACE_DEVICE_TUN, NM_TYPE_DEVICE_TUN, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, }, + { NM_DBUS_INTERFACE_DEVICE_VLAN, NM_TYPE_DEVICE_VLAN, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, }, + { NM_DBUS_INTERFACE_DEVICE_WPAN, NM_TYPE_DEVICE_WPAN, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, }, + { NM_DBUS_INTERFACE_DEVICE_VXLAN, NM_TYPE_DEVICE_VXLAN, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, }, + { NM_DBUS_INTERFACE_DEVICE_WIRELESS, NM_TYPE_DEVICE_WIFI, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, }, + { NM_DBUS_INTERFACE_DEVICE_WIREGUARD, NM_TYPE_DEVICE_WIREGUARD, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, }, + { NM_DBUS_INTERFACE_DHCP4_CONFIG, NM_TYPE_DHCP4_CONFIG, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, }, + { NM_DBUS_INTERFACE_DHCP6_CONFIG, NM_TYPE_DHCP6_CONFIG, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, }, + { NM_DBUS_INTERFACE_IP4_CONFIG, NM_TYPE_IP4_CONFIG, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, }, + { NM_DBUS_INTERFACE_IP6_CONFIG, NM_TYPE_IP6_CONFIG, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, }, + { NM_DBUS_INTERFACE_WIFI_P2P_PEER, NM_TYPE_WIFI_P2P_PEER, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, }, + { NM_DBUS_INTERFACE_SETTINGS_CONNECTION, NM_TYPE_REMOTE_CONNECTION, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, }, + { NM_DBUS_INTERFACE_SETTINGS, NM_TYPE_CLIENT, NML_DBUS_META_INTERFACE_PRIO_NMCLIENT, }, + { NM_DBUS_INTERFACE_DNS_MANAGER, NM_TYPE_CLIENT, NML_DBUS_META_INTERFACE_PRIO_NMCLIENT, }, + { NM_DBUS_INTERFACE_VPN_CONNECTION, NM_TYPE_VPN_CONNECTION, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, }, + { NM_DBUS_INTERFACE_CHECKPOINT, NM_TYPE_CHECKPOINT, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, }, + }; + guint i; + + /* These iface<->gtype associations are copied from "nm-client.c"'s obj_nm_for_gdbus_object(). + * This is redundant to the meta-data, still check that the meta data matches. */ + for (i = 0; i < G_N_ELEMENTS (list); i++) { + const struct list_data *d = &list[i]; + const NMLDBusMetaIface *meta_iface; + + meta_iface = nml_dbus_meta_iface_get (d->dbus_iface_name); + g_assert (meta_iface); + g_assert_cmpint (meta_iface->interface_prio, ==, d->interface_prio); + g_assert (meta_iface->get_type_fcn() == d->gtype); + } +} +/*****************************************************************************/ + NMTST_DEFINE (); int main (int argc, char **argv) @@ -2675,6 +3076,8 @@ int main (int argc, char **argv) g_test_add_func ("/libnm/general/fixup_vendor_string", test_fixup_vendor_string); g_test_add_func ("/libnm/general/nm_vpn_service_plugin_read_vpn_details", test_nm_vpn_service_plugin_read_vpn_details); g_test_add_func ("/libnm/general/test_types", test_types); + g_test_add_func ("/libnm/general/test_nml_dbus_meta", test_nml_dbus_meta); + g_test_add_func ("/libnm/general/test_dbus_meta_types", test_dbus_meta_types); return g_test_run (); } diff --git a/libnm/tests/test-nm-client.c b/libnm/tests/test-nm-client.c index c6b26a21ab..4d4cad1262 100644 --- a/libnm/tests/test-nm-client.c +++ b/libnm/tests/test-nm-client.c @@ -180,8 +180,8 @@ test_device_added_signal_after_init (void) g_signal_handlers_disconnect_by_func (client, device_sai_added_cb, &result); g_signal_handlers_disconnect_by_func (client, devices_sai_notify_cb, &result); - g_assert ((result & SIGNAL_MASK) == SIGNAL_FIRST); - g_assert ((result & NOTIFY_MASK) == NOTIFY_SECOND); + g_assert ((result & SIGNAL_MASK) == SIGNAL_SECOND); + g_assert ((result & NOTIFY_MASK) == NOTIFY_FIRST); devices = nm_client_get_devices (client); g_assert (devices); @@ -635,13 +635,15 @@ assert_ac_and_device (NMClient *client) device = devices->pdata[0]; if (device != ac_device && devices->len > 1) device = devices->pdata[1]; - device_ac = nm_device_get_active_connection (device); - g_assert (device_ac != NULL); g_assert_cmpstr (nm_object_get_path (NM_OBJECT (device)), ==, nm_object_get_path (NM_OBJECT (ac_device))); g_assert (device == ac_device); - g_assert_cmpstr (nm_object_get_path (NM_OBJECT (ac)), ==, nm_object_get_path (NM_OBJECT (device_ac))); - g_assert (ac == device_ac); + + device_ac = nm_device_get_active_connection (device); + if (device_ac) { + g_assert_cmpstr (nm_object_get_path (NM_OBJECT (ac)), ==, nm_object_get_path (NM_OBJECT (device_ac))); + g_assert (ac == device_ac); + } } static void @@ -995,6 +997,8 @@ test_connection_invalid (void) gssize idx[4]; gs_unref_variant GVariant *variant = NULL; + g_assert (g_main_loop_get_context (gl.loop) == (g_main_context_get_thread_default () ?: g_main_context_default ())); + /************************************************************************** * Add three connections before starting libnm. One valid, two invalid. *************************************************************************/ diff --git a/po/POTFILES.in b/po/POTFILES.in index d3246bccfb..0279f865fa 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -106,6 +106,7 @@ libnm-core/nm-team-utils.c libnm-core/nm-utils.c libnm-core/nm-vpn-editor-plugin.c libnm-core/nm-vpn-plugin-info.c +libnm/nm-client.c libnm/nm-device-6lowpan.c libnm/nm-device-adsl.c libnm/nm-device-bond.c @@ -131,10 +132,8 @@ libnm/nm-device-wifi.c libnm/nm-device-wimax.c libnm/nm-device-wpan.c libnm/nm-device.c -libnm/nm-manager.c libnm/nm-object.c libnm/nm-remote-connection.c -libnm/nm-remote-settings.c libnm/nm-vpn-plugin-old.c libnm/nm-vpn-service-plugin.c data/org.freedesktop.NetworkManager.policy.in.in diff --git a/shared/nm-test-utils-impl.c b/shared/nm-test-utils-impl.c index bbe74a9656..6923238efc 100644 --- a/shared/nm-test-utils-impl.c +++ b/shared/nm-test-utils-impl.c @@ -528,12 +528,53 @@ _nmtstc_client_new_inside_loop (gboolean sync) return d.client; } +static NMClient * +_nmtstc_client_new_extra_context (void) +{ + GMainContext *inner_context; + NMClient *client; + GSource *source; + guint key_idx; + + inner_context = g_main_context_new (); + g_main_context_push_thread_default (inner_context); + + client = nmtstc_client_new (TRUE); + + source = nm_utils_g_main_context_create_integrate_source (inner_context); + + g_main_context_pop_thread_default (inner_context); + g_main_context_unref (inner_context); + + g_source_attach (source, g_main_context_get_thread_default ()); + + for (key_idx = 0; TRUE; key_idx++) { + char s[100]; + + /* nmtstc_client_new() may call _nmtstc_client_new_extra_context() repeatedly. We + * need to attach the source to a previously unused key. */ + nm_sprintf_buf (s, "nm-test-extra-context-%u", key_idx); + if (!g_object_get_data (G_OBJECT (client), s)) { + g_object_set_data_full (G_OBJECT (client), + s, + source, + (GDestroyNotify) nm_g_source_destroy_and_unref); + break; + } + } + + return client; +} + NMClient * nmtstc_client_new (gboolean allow_iterate_main_context) { gboolean inside_loop; gboolean sync; + if (nmtst_get_rand_uint32 () % 5 == 0) + return _nmtstc_client_new_extra_context (); + if (!allow_iterate_main_context) { sync = TRUE; inside_loop = FALSE; |