mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-02-13 07:00:32 +01:00
libnm: add from_dbus_fcn for direct properties
There is a quest to move away from the GObject/GValue based setters. Add _nm_setting_property_from_dbus_fcn_direct(), which can parse the GVariant and use the direct_type to set the property. Note that for backward compatibility, we still need _nm_property_variant_to_gvalue() to convert alternative GVariant types to the destination value. This means, as before, on the D-Bus API a property of a certain type can be represented as various D-Bus types.
This commit is contained in:
parent
ed8e098c30
commit
e6562493ef
5 changed files with 227 additions and 19 deletions
|
|
@ -1894,9 +1894,9 @@ nm_setting_connection_class_init(NMSettingConnectionClass *klass)
|
|||
.direct_type = NM_VALUE_TYPE_STRING,
|
||||
.compare_fcn = compare_fcn_id,
|
||||
.to_dbus_fcn = _nm_setting_property_to_dbus_fcn_direct,
|
||||
.from_dbus_fcn = _nm_setting_property_from_dbus_fcn_gprop,
|
||||
.from_dbus_is_full = TRUE),
|
||||
|
||||
.from_dbus_fcn = _nm_setting_property_from_dbus_fcn_direct,
|
||||
.from_dbus_is_full = TRUE,
|
||||
.from_dbus_direct_allow_transform = TRUE),
|
||||
NMSettingConnectionPrivate,
|
||||
id);
|
||||
|
||||
|
|
@ -2021,8 +2021,9 @@ nm_setting_connection_class_init(NMSettingConnectionClass *klass)
|
|||
.to_dbus_fcn = _nm_setting_property_to_dbus_fcn_direct,
|
||||
.missing_from_dbus_fcn =
|
||||
nm_setting_connection_no_interface_name,
|
||||
.from_dbus_fcn = _nm_setting_property_from_dbus_fcn_gprop,
|
||||
.from_dbus_is_full = TRUE),
|
||||
.from_dbus_fcn = _nm_setting_property_from_dbus_fcn_direct,
|
||||
.from_dbus_is_full = TRUE,
|
||||
.from_dbus_direct_allow_transform = TRUE),
|
||||
NMSettingConnectionPrivate,
|
||||
interface_name);
|
||||
|
||||
|
|
|
|||
|
|
@ -391,6 +391,14 @@ _nm_setting_property_from_dbus_fcn_direct_mac_address(const NMSettInfoSetting *
|
|||
NMSettingParseFlags parse_flags,
|
||||
GError ** error);
|
||||
|
||||
gboolean _nm_setting_property_from_dbus_fcn_direct(const NMSettInfoSetting * sett_info,
|
||||
const NMSettInfoProperty *property_info,
|
||||
NMSetting * setting,
|
||||
GVariant * connection_dict,
|
||||
GVariant * value,
|
||||
NMSettingParseFlags parse_flags,
|
||||
GError ** error);
|
||||
|
||||
gboolean _nm_setting_property_from_dbus_fcn_gprop(const NMSettInfoSetting * sett_info,
|
||||
const NMSettInfoProperty *property_info,
|
||||
NMSetting * setting,
|
||||
|
|
|
|||
|
|
@ -1138,6 +1138,186 @@ _nm_setting_property_from_dbus_fcn_direct_mac_address(const NMSettInfoSetting *
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_nm_setting_property_from_dbus_fcn_direct(const NMSettInfoSetting * sett_info,
|
||||
const NMSettInfoProperty *property_info,
|
||||
NMSetting * setting,
|
||||
GVariant * connection_dict,
|
||||
GVariant * value,
|
||||
NMSettingParseFlags parse_flags,
|
||||
GError ** error)
|
||||
{
|
||||
nm_assert(property_info->param_spec);
|
||||
nm_assert(NM_FLAGS_HAS(property_info->param_spec->flags, G_PARAM_WRITABLE));
|
||||
nm_assert(!NM_FLAGS_HAS(property_info->param_spec->flags, G_PARAM_CONSTRUCT_ONLY));
|
||||
nm_assert(!property_info->property_type->typdata_from_dbus.gprop_fcn);
|
||||
|
||||
#define _variant_get_value_transform(property_info, value, gtype, gvalue_get, out_val) \
|
||||
({ \
|
||||
const NMSettInfoProperty const *_property_info = (property_info); \
|
||||
const GType _gtype = (gtype); \
|
||||
GVariant * _value = (value); \
|
||||
gboolean _success = FALSE; \
|
||||
\
|
||||
nm_assert(_property_info->param_spec->value_type == _gtype); \
|
||||
if (_property_info->property_type->from_dbus_direct_allow_transform) { \
|
||||
nm_auto_unset_gvalue GValue _gvalue = G_VALUE_INIT; \
|
||||
\
|
||||
g_value_init(&_gvalue, _gtype); \
|
||||
if (_nm_property_variant_to_gvalue(_value, &_gvalue)) { \
|
||||
*(out_val) = (gvalue_get(&_gvalue)); \
|
||||
_success = TRUE; \
|
||||
} \
|
||||
} \
|
||||
_success; \
|
||||
})
|
||||
|
||||
switch (property_info->property_type->direct_type) {
|
||||
case NM_VALUE_TYPE_BOOL:
|
||||
{
|
||||
bool * p_val;
|
||||
gboolean v;
|
||||
|
||||
if (g_variant_is_of_type(value, G_VARIANT_TYPE_BOOLEAN))
|
||||
v = g_variant_get_boolean(value);
|
||||
else {
|
||||
if (!_variant_get_value_transform(property_info,
|
||||
value,
|
||||
G_TYPE_BOOLEAN,
|
||||
g_value_get_boolean,
|
||||
&v))
|
||||
goto out_error_wrong_dbus_type;
|
||||
v = !!v;
|
||||
}
|
||||
|
||||
p_val = _nm_setting_get_private(setting, sett_info, property_info->direct_offset);
|
||||
if (*p_val == v)
|
||||
goto out_unchanged;
|
||||
*p_val = v;
|
||||
goto out_notify;
|
||||
}
|
||||
case NM_VALUE_TYPE_INT32:
|
||||
{
|
||||
const GParamSpecInt *param_spec;
|
||||
gint32 * p_val;
|
||||
int v;
|
||||
|
||||
if (g_variant_is_of_type(value, G_VARIANT_TYPE_INT32)) {
|
||||
G_STATIC_ASSERT(sizeof(int) >= sizeof(gint32));
|
||||
v = g_variant_get_int32(value);
|
||||
} else {
|
||||
if (!_variant_get_value_transform(property_info,
|
||||
value,
|
||||
G_TYPE_INT,
|
||||
g_value_get_int,
|
||||
&v))
|
||||
goto out_error_wrong_dbus_type;
|
||||
}
|
||||
|
||||
p_val = _nm_setting_get_private(setting, sett_info, property_info->direct_offset);
|
||||
if (*p_val == v)
|
||||
goto out_unchanged;
|
||||
|
||||
param_spec = NM_G_PARAM_SPEC_CAST_INT(property_info->param_spec);
|
||||
if (v < param_spec->minimum || v > param_spec->maximum)
|
||||
goto out_error_param_spec_validation;
|
||||
*p_val = v;
|
||||
goto out_notify;
|
||||
}
|
||||
case NM_VALUE_TYPE_UINT32:
|
||||
{
|
||||
const GParamSpecUInt *param_spec;
|
||||
guint32 * p_val;
|
||||
guint v;
|
||||
|
||||
if (g_variant_is_of_type(value, G_VARIANT_TYPE_UINT32)) {
|
||||
G_STATIC_ASSERT(sizeof(guint) >= sizeof(guint32));
|
||||
v = g_variant_get_uint32(value);
|
||||
} else {
|
||||
if (!_variant_get_value_transform(property_info,
|
||||
value,
|
||||
G_TYPE_UINT,
|
||||
g_value_get_uint,
|
||||
&v))
|
||||
goto out_error_wrong_dbus_type;
|
||||
}
|
||||
|
||||
p_val = _nm_setting_get_private(setting, sett_info, property_info->direct_offset);
|
||||
if (*p_val == v)
|
||||
goto out_unchanged;
|
||||
|
||||
param_spec = NM_G_PARAM_SPEC_CAST_UINT(property_info->param_spec);
|
||||
if (v < param_spec->minimum || v > param_spec->maximum)
|
||||
goto out_error_param_spec_validation;
|
||||
*p_val = v;
|
||||
goto out_notify;
|
||||
}
|
||||
case NM_VALUE_TYPE_STRING:
|
||||
{
|
||||
gs_free char *v_free = NULL;
|
||||
char ** p_val;
|
||||
const char * v;
|
||||
|
||||
if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) {
|
||||
v = g_variant_get_string(value, NULL);
|
||||
} else {
|
||||
if (!_variant_get_value_transform(property_info,
|
||||
value,
|
||||
G_TYPE_STRING,
|
||||
g_value_dup_string,
|
||||
&v_free))
|
||||
goto out_error_wrong_dbus_type;
|
||||
v = v_free;
|
||||
}
|
||||
|
||||
p_val = _nm_setting_get_private(setting, sett_info, property_info->direct_offset);
|
||||
if (!_property_direct_set_string(property_info, p_val, v))
|
||||
goto out_unchanged;
|
||||
|
||||
goto out_notify;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
nm_assert_not_reached();
|
||||
|
||||
out_unchanged:
|
||||
return TRUE;
|
||||
|
||||
out_notify:
|
||||
g_object_notify_by_pspec(G_OBJECT(setting), property_info->param_spec);
|
||||
return TRUE;
|
||||
|
||||
out_error_wrong_dbus_type:
|
||||
if (NM_FLAGS_HAS(parse_flags, NM_SETTING_PARSE_FLAGS_BEST_EFFORT))
|
||||
return TRUE;
|
||||
g_set_error(error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("can't set property of type '%s' from value of type '%s'"),
|
||||
property_info->property_type->dbus_type
|
||||
? g_variant_type_peek_string(property_info->property_type->dbus_type)
|
||||
: (property_info->param_spec
|
||||
? g_type_name(property_info->param_spec->value_type)
|
||||
: "(unknown)"),
|
||||
g_variant_get_type_string(value));
|
||||
g_prefix_error(error, "%s.%s: ", nm_setting_get_name(setting), property_info->name);
|
||||
return FALSE;
|
||||
|
||||
out_error_param_spec_validation:
|
||||
if (NM_FLAGS_HAS(parse_flags, NM_SETTING_PARSE_FLAGS_BEST_EFFORT))
|
||||
return TRUE;
|
||||
g_set_error(error,
|
||||
NM_UTILS_ERROR,
|
||||
NM_UTILS_ERROR_UNKNOWN,
|
||||
_("value of type '%s' is invalid or out of range for property '%s'"),
|
||||
g_variant_get_type_string(value),
|
||||
property_info->name);
|
||||
g_prefix_error(error, "%s.%s: ", nm_setting_get_name(setting), property_info->name);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_nm_setting_property_from_dbus_fcn_gprop(const NMSettInfoSetting * sett_info,
|
||||
const NMSettInfoProperty *property_info,
|
||||
|
|
@ -3014,32 +3194,36 @@ const NMSettInfoPropertType nm_sett_info_propert_type_direct_boolean =
|
|||
.direct_type = NM_VALUE_TYPE_BOOL,
|
||||
.compare_fcn = _nm_setting_property_compare_fcn_direct,
|
||||
.to_dbus_fcn = _nm_setting_property_to_dbus_fcn_direct,
|
||||
.from_dbus_fcn = _nm_setting_property_from_dbus_fcn_gprop,
|
||||
.from_dbus_is_full = TRUE);
|
||||
.from_dbus_fcn = _nm_setting_property_from_dbus_fcn_direct,
|
||||
.from_dbus_is_full = TRUE,
|
||||
.from_dbus_direct_allow_transform = TRUE);
|
||||
|
||||
const NMSettInfoPropertType nm_sett_info_propert_type_direct_int32 =
|
||||
NM_SETT_INFO_PROPERT_TYPE_DBUS_INIT(G_VARIANT_TYPE_INT32,
|
||||
.direct_type = NM_VALUE_TYPE_INT32,
|
||||
.compare_fcn = _nm_setting_property_compare_fcn_direct,
|
||||
.to_dbus_fcn = _nm_setting_property_to_dbus_fcn_direct,
|
||||
.from_dbus_fcn = _nm_setting_property_from_dbus_fcn_gprop,
|
||||
.from_dbus_is_full = TRUE);
|
||||
.from_dbus_fcn = _nm_setting_property_from_dbus_fcn_direct,
|
||||
.from_dbus_is_full = TRUE,
|
||||
.from_dbus_direct_allow_transform = TRUE);
|
||||
|
||||
const NMSettInfoPropertType nm_sett_info_propert_type_direct_uint32 =
|
||||
NM_SETT_INFO_PROPERT_TYPE_DBUS_INIT(G_VARIANT_TYPE_UINT32,
|
||||
.direct_type = NM_VALUE_TYPE_UINT32,
|
||||
.compare_fcn = _nm_setting_property_compare_fcn_direct,
|
||||
.to_dbus_fcn = _nm_setting_property_to_dbus_fcn_direct,
|
||||
.from_dbus_fcn = _nm_setting_property_from_dbus_fcn_gprop,
|
||||
.from_dbus_is_full = TRUE);
|
||||
.from_dbus_fcn = _nm_setting_property_from_dbus_fcn_direct,
|
||||
.from_dbus_is_full = TRUE,
|
||||
.from_dbus_direct_allow_transform = TRUE);
|
||||
|
||||
const NMSettInfoPropertType nm_sett_info_propert_type_direct_string =
|
||||
NM_SETT_INFO_PROPERT_TYPE_DBUS_INIT(G_VARIANT_TYPE_STRING,
|
||||
.direct_type = NM_VALUE_TYPE_STRING,
|
||||
.compare_fcn = _nm_setting_property_compare_fcn_direct,
|
||||
.to_dbus_fcn = _nm_setting_property_to_dbus_fcn_direct,
|
||||
.from_dbus_fcn = _nm_setting_property_from_dbus_fcn_gprop,
|
||||
.from_dbus_is_full = TRUE);
|
||||
.from_dbus_fcn = _nm_setting_property_from_dbus_fcn_direct,
|
||||
.from_dbus_is_full = TRUE,
|
||||
.from_dbus_direct_allow_transform = TRUE);
|
||||
|
||||
const NMSettInfoPropertType nm_sett_info_propert_type_direct_mac_address =
|
||||
NM_SETT_INFO_PROPERT_TYPE_DBUS_INIT(
|
||||
|
|
|
|||
|
|
@ -4562,11 +4562,21 @@ check_done:;
|
|||
g_assert(sip->property_type->from_dbus_fcn
|
||||
== _nm_setting_property_from_dbus_fcn_gprop);
|
||||
}
|
||||
if (sip->property_type->from_dbus_direct_allow_transform) {
|
||||
g_assert(sip->property_type->from_dbus_fcn
|
||||
== _nm_setting_property_from_dbus_fcn_direct);
|
||||
}
|
||||
if (sip->property_type->from_dbus_fcn == _nm_setting_property_from_dbus_fcn_direct) {
|
||||
/* for the moment, all direct properties allow transformation. */
|
||||
g_assert(sip->property_type->from_dbus_direct_allow_transform);
|
||||
}
|
||||
|
||||
if (sip->property_type->from_dbus_fcn == _nm_setting_property_from_dbus_fcn_gprop)
|
||||
g_assert(sip->param_spec);
|
||||
|
||||
g_assert(sip->property_type->from_dbus_is_full
|
||||
== NM_IN_SET(sip->property_type->from_dbus_fcn,
|
||||
_nm_setting_property_from_dbus_fcn_direct,
|
||||
_nm_setting_property_from_dbus_fcn_gprop,
|
||||
_nm_setting_property_from_dbus_fcn_ignore));
|
||||
|
||||
|
|
|
|||
|
|
@ -701,6 +701,13 @@ typedef struct {
|
|||
* from_dbus_fcn() are ignored. If true, then error are propagated. */
|
||||
bool from_dbus_is_full : 1;
|
||||
|
||||
/* Only if from_dbus_fcn is set to _nm_setting_property_from_dbus_fcn_direct.
|
||||
* Historically, libnm used g_dbus_gvariant_to_gvalue() and g_value_transform() to
|
||||
* convert from D-Bus to the GObject property. Thereby, various transformations are
|
||||
* allowed and supported. If this is TRUE, then such transformations are still
|
||||
* allowed for backward compatibility. */
|
||||
bool from_dbus_direct_allow_transform : 1;
|
||||
|
||||
/* compare_fcn() returns a ternary, where DEFAULT means that the property should not
|
||||
* be compared due to the compare @flags. A TRUE/FALSE result means that the property is
|
||||
* equal/not-equal.
|
||||
|
|
@ -720,12 +727,10 @@ typedef struct {
|
|||
NMSettInfoPropMissingFromDBusFcn missing_from_dbus_fcn;
|
||||
|
||||
struct {
|
||||
union {
|
||||
/* If from_dbus_fcn is set to _nm_setting_property_from_dbus_fcn_gprop,
|
||||
* then this is an optional handler for converting between GVariant and
|
||||
* GValue. */
|
||||
NMSettInfoPropGPropFromDBusFcn gprop_fcn;
|
||||
};
|
||||
/* Only if from_dbus_fcn is set to _nm_setting_property_from_dbus_fcn_gprop.
|
||||
* This is an optional handler for converting between GVariant and
|
||||
* GValue. */
|
||||
NMSettInfoPropGPropFromDBusFcn gprop_fcn;
|
||||
} typdata_from_dbus;
|
||||
|
||||
struct {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue