|
Packit Service |
5ffa24 |
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
Packit Service |
5ffa24 |
/*
|
|
Packit Service |
5ffa24 |
* Copyright (C) 2018 Red Hat, Inc.
|
|
Packit Service |
5ffa24 |
*/
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
2bceb2 |
#include "src/core/nm-default-daemon.h"
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
#include "nm-dbus-utils.h"
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
#include "nm-dbus-object.h"
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
/*****************************************************************************/
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
const GDBusSignalInfo nm_signal_info_property_changed_legacy = NM_DEFINE_GDBUS_SIGNAL_INFO_INIT(
|
|
Packit Service |
5ffa24 |
"PropertiesChanged",
|
|
Packit Service |
5ffa24 |
.args = NM_DEFINE_GDBUS_ARG_INFOS(NM_DEFINE_GDBUS_ARG_INFO("properties", "a{sv}"), ), );
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
GDBusPropertyInfo *
|
|
Packit Service |
5ffa24 |
nm_dbus_utils_interface_info_lookup_property(const GDBusInterfaceInfo *interface_info,
|
|
Packit Service |
5ffa24 |
const char * property_name,
|
|
Packit Service |
5ffa24 |
guint * property_idx)
|
|
Packit Service |
5ffa24 |
{
|
|
Packit Service |
5ffa24 |
guint i;
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
nm_assert(interface_info);
|
|
Packit Service |
5ffa24 |
nm_assert(property_name);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
/* there is also g_dbus_interface_info_lookup_property(), however that makes use
|
|
Packit Service |
5ffa24 |
* of a global cache. */
|
|
Packit Service |
5ffa24 |
if (interface_info->properties) {
|
|
Packit Service |
5ffa24 |
for (i = 0; interface_info->properties[i]; i++) {
|
|
Packit Service |
5ffa24 |
GDBusPropertyInfo *info = interface_info->properties[i];
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
if (nm_streq(info->name, property_name)) {
|
|
Packit Service |
5ffa24 |
NM_SET_OUT(property_idx, i);
|
|
Packit Service |
5ffa24 |
return info;
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
return NULL;
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
GDBusMethodInfo *
|
|
Packit Service |
5ffa24 |
nm_dbus_utils_interface_info_lookup_method(const GDBusInterfaceInfo *interface_info,
|
|
Packit Service |
5ffa24 |
const char * method_name)
|
|
Packit Service |
5ffa24 |
{
|
|
Packit Service |
5ffa24 |
guint i;
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
nm_assert(interface_info);
|
|
Packit Service |
5ffa24 |
nm_assert(method_name);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
/* there is also g_dbus_interface_info_lookup_property(), however that makes use
|
|
Packit Service |
5ffa24 |
* of a global cache. */
|
|
Packit Service |
5ffa24 |
if (interface_info->methods) {
|
|
Packit Service |
5ffa24 |
for (i = 0; interface_info->methods[i]; i++) {
|
|
Packit Service |
5ffa24 |
GDBusMethodInfo *info = interface_info->methods[i];
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
if (nm_streq(info->name, method_name))
|
|
Packit Service |
5ffa24 |
return info;
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
return NULL;
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
GVariant *
|
|
Packit Service |
5ffa24 |
nm_dbus_utils_get_property(GObject *obj, const char *signature, const char *property_name)
|
|
Packit Service |
5ffa24 |
{
|
|
Packit Service |
5ffa24 |
nm_auto_unset_gvalue GValue value = G_VALUE_INIT;
|
|
Packit Service |
5ffa24 |
GParamSpec * pspec;
|
|
Packit Service |
5ffa24 |
GVariant * variant;
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
nm_assert(G_IS_OBJECT(obj));
|
|
Packit Service |
5ffa24 |
nm_assert(g_variant_type_string_is_valid(signature));
|
|
Packit Service |
5ffa24 |
nm_assert(property_name && property_name[0]);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
pspec = g_object_class_find_property(G_OBJECT_GET_CLASS(obj), property_name);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
nm_assert(pspec);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
nm_assert(pspec->value_type != G_TYPE_VARIANT
|
|
Packit Service |
5ffa24 |
|| nm_streq((char *) (((GParamSpecVariant *) pspec)->type), signature));
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
g_value_init(&value, pspec->value_type);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
g_object_get_property(obj, property_name, &value);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
variant = g_dbus_gvalue_to_gvariant(&value, G_VARIANT_TYPE(signature));
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
nm_assert(!variant || g_variant_is_of_type(variant, G_VARIANT_TYPE(signature)));
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
/* returns never-floating variant */
|
|
Packit Service |
5ffa24 |
nm_assert(!variant || !g_variant_is_floating(variant));
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
return variant;
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
/*****************************************************************************/
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
void
|
|
Packit Service |
5ffa24 |
nm_dbus_utils_g_value_set_object_path(GValue *value, gpointer object)
|
|
Packit Service |
5ffa24 |
{
|
|
Packit Service |
5ffa24 |
const char *path;
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
g_return_if_fail(!object || NM_IS_DBUS_OBJECT(object));
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
if (object && (path = nm_dbus_object_get_path(object)))
|
|
Packit Service |
5ffa24 |
g_value_set_string(value, path);
|
|
Packit Service |
5ffa24 |
else
|
|
Packit Service |
5ffa24 |
g_value_set_string(value, NULL);
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
void
|
|
Packit Service |
5ffa24 |
nm_dbus_utils_g_value_set_object_path_still_exported(GValue *value, gpointer object)
|
|
Packit Service |
5ffa24 |
{
|
|
Packit Service |
5ffa24 |
const char *path;
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
g_return_if_fail(!object || NM_IS_DBUS_OBJECT(object));
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
if (object && (path = nm_dbus_object_get_path_still_exported(object)))
|
|
Packit Service |
5ffa24 |
g_value_set_string(value, path);
|
|
Packit Service |
5ffa24 |
else
|
|
Packit Service |
5ffa24 |
g_value_set_string(value, "/");
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
void
|
|
Packit Service |
5ffa24 |
nm_dbus_utils_g_value_set_object_path_from_hash(
|
|
Packit Service |
5ffa24 |
GValue * value,
|
|
Packit Service |
5ffa24 |
GHashTable *hash /* has keys of NMDBusObject type. */,
|
|
Packit Service |
5ffa24 |
gboolean expect_all_exported)
|
|
Packit Service |
5ffa24 |
{
|
|
Packit Service |
5ffa24 |
NMDBusObject * obj;
|
|
Packit Service |
5ffa24 |
char ** strv;
|
|
Packit Service |
5ffa24 |
guint i, n;
|
|
Packit Service |
5ffa24 |
GHashTableIter iter;
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
nm_assert(value);
|
|
Packit Service |
5ffa24 |
nm_assert(hash);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
n = g_hash_table_size(hash);
|
|
Packit Service |
5ffa24 |
strv = g_new(char *, n + 1);
|
|
Packit Service |
5ffa24 |
i = 0;
|
|
Packit Service |
5ffa24 |
g_hash_table_iter_init(&iter, hash);
|
|
Packit Service |
5ffa24 |
while (g_hash_table_iter_next(&iter, (gpointer *) &obj, NULL)) {
|
|
Packit Service |
5ffa24 |
const char *path;
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
path = nm_dbus_object_get_path_still_exported(obj);
|
|
Packit Service |
5ffa24 |
if (!path) {
|
|
Packit Service |
5ffa24 |
nm_assert(!expect_all_exported);
|
|
Packit Service |
5ffa24 |
continue;
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
strv[i++] = g_strdup(path);
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
nm_assert(i <= n);
|
|
Packit Service |
5ffa24 |
strv[i] = NULL;
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
/* sort the names, to give a well-defined, stable order. */
|
|
Packit Service |
5ffa24 |
nm_utils_strv_sort(strv, i);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
g_value_take_boxed(value, strv);
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
const char **
|
|
Packit Service |
5ffa24 |
nm_dbus_utils_get_paths_for_clist(const CList *lst_head,
|
|
Packit Service |
5ffa24 |
gssize lst_len,
|
|
Packit Service |
5ffa24 |
guint member_offset,
|
|
Packit Service |
5ffa24 |
gboolean expect_all_exported)
|
|
Packit Service |
5ffa24 |
{
|
|
Packit Service |
5ffa24 |
const CList *iter;
|
|
Packit Service |
5ffa24 |
const char **strv;
|
|
Packit Service |
5ffa24 |
const char * path;
|
|
Packit Service |
5ffa24 |
gsize i, n;
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
nm_assert(lst_head);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
if (lst_len < 0)
|
|
Packit Service |
5ffa24 |
n = c_list_length(lst_head);
|
|
Packit Service |
5ffa24 |
else {
|
|
Packit Service |
5ffa24 |
n = lst_len;
|
|
Packit Service |
5ffa24 |
nm_assert(n == c_list_length(lst_head));
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
i = 0;
|
|
Packit Service |
5ffa24 |
strv = g_new(const char *, n + 1);
|
|
Packit Service |
5ffa24 |
c_list_for_each (iter, lst_head) {
|
|
Packit Service |
5ffa24 |
NMDBusObject *obj = (NMDBusObject *) (((const char *) iter) - member_offset);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
path = nm_dbus_object_get_path(obj);
|
|
Packit Service |
5ffa24 |
if (!path) {
|
|
Packit Service |
5ffa24 |
nm_assert(expect_all_exported);
|
|
Packit Service |
5ffa24 |
continue;
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
nm_assert(i < n);
|
|
Packit Service |
5ffa24 |
strv[i++] = path;
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
nm_assert(i <= n);
|
|
Packit Service |
5ffa24 |
strv[i] = NULL;
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
return strv;
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
/*****************************************************************************/
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
void
|
|
Packit Service |
5ffa24 |
nm_dbus_track_obj_path_init(NMDBusTrackObjPath *track, GObject *target, const GParamSpec *pspec)
|
|
Packit Service |
5ffa24 |
{
|
|
Packit Service |
5ffa24 |
nm_assert(track);
|
|
Packit Service |
5ffa24 |
nm_assert(G_IS_OBJECT(target));
|
|
Packit Service |
5ffa24 |
nm_assert(G_IS_PARAM_SPEC(pspec));
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
track->_obj = NULL;
|
|
Packit Service |
5ffa24 |
track->_notify_target = target;
|
|
Packit Service |
5ffa24 |
track->_notify_pspec = pspec;
|
|
Packit Service |
5ffa24 |
track->_notify_signal_id = 0;
|
|
Packit Service |
5ffa24 |
track->_visible = FALSE;
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
void
|
|
Packit Service |
5ffa24 |
nm_dbus_track_obj_path_deinit(NMDBusTrackObjPath *track)
|
|
Packit Service |
5ffa24 |
{
|
|
Packit Service |
5ffa24 |
/* we allow deinit() to be called multiple times (e.g. from
|
|
Packit Service |
5ffa24 |
* dispose(), which must be re-entrant). */
|
|
Packit Service |
5ffa24 |
nm_assert(track);
|
|
Packit Service |
5ffa24 |
nm_assert(!track->_notify_target || G_IS_OBJECT(track->_notify_target));
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
nm_clear_g_signal_handler(track->obj, &track->_notify_signal_id);
|
|
Packit Service |
5ffa24 |
track->_notify_target = NULL;
|
|
Packit Service |
5ffa24 |
track->_notify_pspec = NULL;
|
|
Packit Service |
5ffa24 |
track->_visible = FALSE;
|
|
Packit Service |
5ffa24 |
nm_clear_g_object(&track->_obj);
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
void
|
|
Packit Service |
5ffa24 |
nm_dbus_track_obj_path_notify(const NMDBusTrackObjPath *track)
|
|
Packit Service |
5ffa24 |
{
|
|
Packit Service |
5ffa24 |
nm_assert(track);
|
|
Packit Service |
5ffa24 |
nm_assert(G_IS_OBJECT(track->_notify_target));
|
|
Packit Service |
5ffa24 |
nm_assert(G_IS_PARAM_SPEC(track->_notify_pspec));
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
g_object_notify_by_pspec(track->_notify_target, (GParamSpec *) track->_notify_pspec);
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
const char *
|
|
Packit Service |
5ffa24 |
nm_dbus_track_obj_path_get(const NMDBusTrackObjPath *track)
|
|
Packit Service |
5ffa24 |
{
|
|
Packit Service |
5ffa24 |
nm_assert(track);
|
|
Packit Service |
5ffa24 |
nm_assert(G_IS_OBJECT(track->_notify_target));
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
return track->obj && track->visible ? nm_dbus_object_get_path_still_exported(track->obj) : NULL;
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
static void
|
|
Packit Service |
5ffa24 |
_track_obj_exported_changed(NMDBusObject *obj, NMDBusTrackObjPath *track)
|
|
Packit Service |
5ffa24 |
{
|
|
Packit Service |
5ffa24 |
nm_dbus_track_obj_path_notify(track);
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
void
|
|
Packit Service |
5ffa24 |
nm_dbus_track_obj_path_set(NMDBusTrackObjPath *track, gpointer obj, gboolean visible)
|
|
Packit Service |
5ffa24 |
{
|
|
Packit Service |
5ffa24 |
gs_unref_object NMDBusObject *old_obj = NULL;
|
|
Packit Service |
5ffa24 |
const char * old_path;
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
nm_assert(track);
|
|
Packit Service |
5ffa24 |
nm_assert(G_IS_OBJECT(track->_notify_target));
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
g_return_if_fail(!obj || NM_IS_DBUS_OBJECT(obj));
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
if (track->obj == obj && track->visible == !!visible)
|
|
Packit Service |
5ffa24 |
return;
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
old_path = nm_dbus_track_obj_path_get(track);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
track->_visible = visible;
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
if (track->obj != obj) {
|
|
Packit Service |
5ffa24 |
nm_clear_g_signal_handler(track->obj, &track->_notify_signal_id);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
old_obj = track->obj;
|
|
Packit Service |
5ffa24 |
track->_obj = nm_g_object_ref(obj);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
if (obj) {
|
|
Packit Service |
5ffa24 |
track->_notify_signal_id = g_signal_connect(obj,
|
|
Packit Service |
5ffa24 |
NM_DBUS_OBJECT_EXPORTED_CHANGED,
|
|
Packit Service |
5ffa24 |
G_CALLBACK(_track_obj_exported_changed),
|
|
Packit Service |
5ffa24 |
track);
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
if (!nm_streq0(old_path, nm_dbus_track_obj_path_get(track)))
|
|
Packit Service |
5ffa24 |
nm_dbus_track_obj_path_notify(track);
|
|
Packit Service |
5ffa24 |
}
|