diff --git a/src/libnm-core-impl/nm-setting-connection.c b/src/libnm-core-impl/nm-setting-connection.c index bb5c3c82e5..4f51da5ab7 100644 --- a/src/libnm-core-impl/nm-setting-connection.c +++ b/src/libnm-core-impl/nm-setting-connection.c @@ -93,8 +93,8 @@ typedef struct { NMSettingConnectionAutoconnectSlaves autoconnect_slaves; NMMetered metered; NMSettingConnectionLldp lldp; + bool autoconnect; bool read_only : 1; - bool autoconnect : 1; } NMSettingConnectionPrivate; /** @@ -2078,13 +2078,14 @@ nm_setting_connection_class_init(NMSettingConnectionClass *klass) * description: Whether the connection should be autoconnected (not only while booting). * ---end--- */ - _nm_setting_property_define_boolean(properties_override, - obj_properties, - NM_SETTING_CONNECTION_AUTOCONNECT, - PROP_AUTOCONNECT, - TRUE, - NM_SETTING_PARAM_FUZZY_IGNORE, - nm_setting_connection_get_autoconnect); + _nm_setting_property_define_direct_boolean(properties_override, + obj_properties, + NM_SETTING_CONNECTION_AUTOCONNECT, + PROP_AUTOCONNECT, + TRUE, + NM_SETTING_PARAM_FUZZY_IGNORE, + NMSettingConnectionPrivate, + autoconnect); /** * NMSettingConnection:autoconnect-priority: diff --git a/src/libnm-core-impl/nm-setting-private.h b/src/libnm-core-impl/nm-setting-private.h index de76914df0..5c533d4ade 100644 --- a/src/libnm-core-impl/nm-setting-private.h +++ b/src/libnm-core-impl/nm-setting-private.h @@ -253,6 +253,8 @@ extern const NMSettInfoPropertType nm_sett_info_propert_type_deprecated_ignore_u extern const NMSettInfoPropertType nm_sett_info_propert_type_plain_i; extern const NMSettInfoPropertType nm_sett_info_propert_type_plain_u; +extern const NMSettInfoPropertType nm_sett_info_propert_type_direct_boolean; + extern const NMSettInfoPropertType nm_sett_info_propert_type_boolean; extern const NMSettInfoPropertType nm_sett_info_propert_type_string; @@ -275,6 +277,13 @@ GVariant *_nm_setting_property_to_dbus_fcn_gprop(const NMSettInfoSetting * NMConnectionSerializationFlags flags, const NMConnectionSerializationOptions *options); +GVariant *_nm_setting_property_to_dbus_fcn_direct(const NMSettInfoSetting * sett_info, + guint property_idx, + NMConnection * connection, + NMSetting * setting, + NMConnectionSerializationFlags flags, + const NMConnectionSerializationOptions *options); + GVariant * _nm_setting_property_to_dbus_fcn_get_boolean(const NMSettInfoSetting * sett_info, guint property_idx, @@ -376,11 +385,14 @@ _nm_properties_override(GArray *properties_override, const NMSettInfoProperty *p g_array_append_vals(properties_override, prop_info, 1); } -#define _nm_properties_override_gobj(properties_override, p_param_spec, p_property_type, ...) \ - _nm_properties_override((properties_override), \ - NM_SETT_INFO_PROPERTY(.name = NULL, \ - .param_spec = (p_param_spec), \ - .property_type = (p_property_type), \ +#define _nm_properties_override_gobj(properties_override, \ + p_param_spec, \ + p_property_type, \ + ... /* extra NMSettInfoProperty fields */) \ + _nm_properties_override((properties_override), \ + NM_SETT_INFO_PROPERTY(.name = NULL, \ + .param_spec = (p_param_spec), \ + .property_type = (p_property_type), \ __VA_ARGS__)) #define _nm_properties_override_dbus(properties_override, p_name, p_property_type) \ @@ -390,6 +402,58 @@ _nm_properties_override(GArray *properties_override, const NMSettInfoProperty *p /*****************************************************************************/ +/* Define "direct" properties. These are properties that have a GParamSpec and + * NMSettInfoPropertType.direct_type != NM_VALUE_TYPE_NONE. + * + * With this, the location of the data is known at + * + * _nm_setting_get_private(setting, sett_info, property_info->direct_offset) + * + * which allows to generically handle the property operations (like get, set, compare). + */ + +#define _nm_setting_property_define_direct_boolean(properties_override, \ + obj_properties, \ + prop_name, \ + prop_id, \ + default_value, \ + param_flags, \ + private_struct_type, \ + private_struct_field, \ + ... /* extra NMSettInfoProperty fields */) \ + G_STMT_START \ + { \ + const gboolean _default_value = (default_value); \ + GParamSpec * _param_spec; \ + \ + G_STATIC_ASSERT( \ + !NM_FLAGS_ANY((param_flags), \ + ~(NM_SETTING_PARAM_FUZZY_IGNORE | NM_SETTING_PARAM_INFERRABLE \ + | NM_SETTING_PARAM_REAPPLY_IMMEDIATELY))); \ + \ + nm_assert(NM_IN_SET(_default_value, 0, 1)); \ + \ + _param_spec = \ + g_param_spec_boolean("" prop_name "", \ + "", \ + "", \ + _default_value, \ + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | (param_flags)); \ + \ + (obj_properties)[(prop_id)] = _param_spec; \ + \ + _nm_properties_override_gobj( \ + (properties_override), \ + _param_spec, \ + &nm_sett_info_propert_type_direct_boolean, \ + .direct_offset = \ + NM_STRUCT_OFFSET_ENSURE_TYPE(bool, private_struct_type, private_struct_field), \ + __VA_ARGS__); \ + } \ + G_STMT_END + +/*****************************************************************************/ + #define _nm_setting_property_define_boolean_full(properties_override, \ obj_properties, \ prop_name, \ diff --git a/src/libnm-core-impl/nm-setting.c b/src/libnm-core-impl/nm-setting.c index 11c2096617..8dfdad26d8 100644 --- a/src/libnm-core-impl/nm-setting.c +++ b/src/libnm-core-impl/nm-setting.c @@ -544,6 +544,32 @@ _nm_setting_use_legacy_property(NMSetting * setting, /*****************************************************************************/ +GVariant * +_nm_setting_property_to_dbus_fcn_direct(const NMSettInfoSetting * sett_info, + guint property_idx, + NMConnection * connection, + NMSetting * setting, + NMConnectionSerializationFlags flags, + const NMConnectionSerializationOptions *options) +{ + const NMSettInfoProperty *property_info = &sett_info->property_infos[property_idx]; + + switch (property_info->property_type->direct_type) { + case NM_VALUE_TYPE_BOOL: + { + gboolean val; + + val = *((bool *) _nm_setting_get_private(setting, sett_info, property_info->direct_offset)); + if (!property_info->to_dbus_data.including_default + && val == NM_G_PARAM_SPEC_GET_DEFAULT_BOOLEAN(property_info->param_spec)) + return NULL; + return g_variant_ref(nm_g_variant_singleton_b(val)); + } + default: + return nm_assert_unreachable_val(NULL); + } +} + GVariant * _nm_setting_property_to_dbus_fcn_get_boolean(const NMSettInfoSetting * sett_info, guint property_idx, @@ -2415,6 +2441,11 @@ const NMSettInfoPropertType nm_sett_info_propert_type_plain_i = const NMSettInfoPropertType nm_sett_info_propert_type_plain_u = NM_SETT_INFO_PROPERT_TYPE_GPROP_INIT(G_VARIANT_TYPE_UINT32); +const NMSettInfoPropertType nm_sett_info_propert_type_direct_boolean = + NM_SETT_INFO_PROPERT_TYPE_DBUS_INIT(G_VARIANT_TYPE_BOOLEAN, + .direct_type = NM_VALUE_TYPE_BOOL, + .to_dbus_fcn = _nm_setting_property_to_dbus_fcn_direct); + const NMSettInfoPropertType nm_sett_info_propert_type_boolean = NM_SETT_INFO_PROPERT_TYPE_DBUS_INIT( G_VARIANT_TYPE_BOOLEAN, .to_dbus_fcn = _nm_setting_property_to_dbus_fcn_get_boolean); diff --git a/src/libnm-core-impl/tests/test-setting.c b/src/libnm-core-impl/tests/test-setting.c index 15dbf0f8b9..41db66e909 100644 --- a/src/libnm-core-impl/tests/test-setting.c +++ b/src/libnm-core-impl/tests/test-setting.c @@ -4433,6 +4433,19 @@ test_setting_metadata(void) g_assert(sip->property_type->dbus_type); g_assert(g_variant_type_string_is_valid((const char *) sip->property_type->dbus_type)); + if (sip->property_type->direct_type == NM_VALUE_TYPE_NONE) { + g_assert_cmpint(sip->direct_offset, ==, 0); + } else if (sip->property_type->direct_type == NM_VALUE_TYPE_BOOL) { + g_assert(sip->property_type == &nm_sett_info_propert_type_direct_boolean); + g_assert(g_variant_type_equal(sip->property_type->dbus_type, "b")); + g_assert(sip->property_type->to_dbus_fcn + == _nm_setting_property_to_dbus_fcn_direct); + g_assert(sip->param_spec); + g_assert(sip->param_spec->value_type == G_TYPE_BOOLEAN); + can_set_including_default = TRUE; + } else + g_assert_not_reached(); + if (!sip->property_type->to_dbus_fcn) { /* it's allowed to have no to_dbus_fcn(), to ignore a property. But such * properties must not have a param_spec and no gprop_to_dbus_fcn. */ @@ -4598,7 +4611,7 @@ check_done:; const NMSettInfoPropertType *pt_2 = a_property_types[prop_idx_2]; if (!g_variant_type_equal(pt->dbus_type, pt_2->dbus_type) - || pt->to_dbus_fcn != pt_2->to_dbus_fcn + || pt->direct_type != pt_2->direct_type || pt->to_dbus_fcn != pt_2->to_dbus_fcn || pt->from_dbus_fcn != pt_2->from_dbus_fcn || pt->missing_from_dbus_fcn != pt_2->missing_from_dbus_fcn || pt->gprop_from_dbus_fcn != pt_2->gprop_from_dbus_fcn diff --git a/src/libnm-core-intern/nm-core-internal.h b/src/libnm-core-intern/nm-core-internal.h index fd6f9892ec..2c5bb93428 100644 --- a/src/libnm-core-intern/nm-core-internal.h +++ b/src/libnm-core-intern/nm-core-internal.h @@ -78,6 +78,7 @@ #include "nm-vpn-dbus-interface.h" #include "nm-vpn-editor-plugin.h" #include "libnm-core-aux-intern/nm-libnm-core-utils.h" +#include "libnm-glib-aux/nm-value-type.h" /* NM_SETTING_COMPARE_FLAG_INFERRABLE: check whether a device-generated * connection can be replaced by a already-defined connection. This flag only @@ -684,6 +685,14 @@ typedef enum _nm_packed { typedef struct { const GVariantType *dbus_type; + /* If this is not NM_VALUE_TYPE_UNSPEC, then this is a "direct" property, + * meaning that _nm_setting_get_private() at NMSettInfoProperty.direct_offset + * gives direct access to the field. + * + * Direct properties can use this information to generically implement access + * to the property value. */ + NMValueType direct_type; + NMSettInfoPropToDBusFcn to_dbus_fcn; NMSettInfoPropFromDBusFcn from_dbus_fcn; NMSettInfoPropMissingFromDBusFcn missing_from_dbus_fcn; @@ -707,6 +716,11 @@ struct _NMSettInfoProperty { const NMSettInfoPropertType *property_type; + /* This only has meaning for direct properties (property_type->direct_type != NM_VALUE_TYPE_UNSPEC). + * In that case, this is the offset where _nm_setting_get_private() can find + * the direct location. */ + guint16 direct_offset; + struct { union { gpointer none;