mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-30 08:30:11 +01:00
Currently "src/" mostly contains the source code of the daemon. I say mostly, because that is not true, there are also the device, settings, wwan, ppp plugins, the initrd generator, the pppd and dhcp helper, and probably more. Also we have source code under libnm-core/, libnm/, clients/, and shared/ directories. That is all confusing. We should have one "src" directory, that contains subdirectories. Those subdirectories should contain individual parts (libraries or applications), that possibly have dependencies on other subdirectories. There should be a flat hierarchy of directories under src/, which contains individual modules. As the name "src/" is already taken, that prevents any sensible restructuring of the code. As a first step, move "src/" to "src/core/". This gives space to reorganize the code better by moving individual components into "src/". For inspiration, look at systemd's "src/" directory. https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/743
294 lines
8.1 KiB
C
294 lines
8.1 KiB
C
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
/*
|
|
* Copyright (C) 2018 Red Hat, Inc.
|
|
*/
|
|
|
|
#include "nm-default.h"
|
|
|
|
#include "nm-dbus-utils.h"
|
|
|
|
#include "nm-dbus-object.h"
|
|
|
|
/*****************************************************************************/
|
|
|
|
const GDBusSignalInfo nm_signal_info_property_changed_legacy = NM_DEFINE_GDBUS_SIGNAL_INFO_INIT(
|
|
"PropertiesChanged",
|
|
.args = NM_DEFINE_GDBUS_ARG_INFOS(NM_DEFINE_GDBUS_ARG_INFO("properties", "a{sv}"), ), );
|
|
|
|
GDBusPropertyInfo *
|
|
nm_dbus_utils_interface_info_lookup_property(const GDBusInterfaceInfo *interface_info,
|
|
const char * property_name,
|
|
guint * property_idx)
|
|
{
|
|
guint i;
|
|
|
|
nm_assert(interface_info);
|
|
nm_assert(property_name);
|
|
|
|
/* there is also g_dbus_interface_info_lookup_property(), however that makes use
|
|
* of a global cache. */
|
|
if (interface_info->properties) {
|
|
for (i = 0; interface_info->properties[i]; i++) {
|
|
GDBusPropertyInfo *info = interface_info->properties[i];
|
|
|
|
if (nm_streq(info->name, property_name)) {
|
|
NM_SET_OUT(property_idx, i);
|
|
return info;
|
|
}
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
GDBusMethodInfo *
|
|
nm_dbus_utils_interface_info_lookup_method(const GDBusInterfaceInfo *interface_info,
|
|
const char * method_name)
|
|
{
|
|
guint i;
|
|
|
|
nm_assert(interface_info);
|
|
nm_assert(method_name);
|
|
|
|
/* there is also g_dbus_interface_info_lookup_property(), however that makes use
|
|
* of a global cache. */
|
|
if (interface_info->methods) {
|
|
for (i = 0; interface_info->methods[i]; i++) {
|
|
GDBusMethodInfo *info = interface_info->methods[i];
|
|
|
|
if (nm_streq(info->name, method_name))
|
|
return info;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
GVariant *
|
|
nm_dbus_utils_get_property(GObject *obj, const char *signature, const char *property_name)
|
|
{
|
|
nm_auto_unset_gvalue GValue value = G_VALUE_INIT;
|
|
GParamSpec * pspec;
|
|
GVariant * variant;
|
|
|
|
nm_assert(G_IS_OBJECT(obj));
|
|
nm_assert(g_variant_type_string_is_valid(signature));
|
|
nm_assert(property_name && property_name[0]);
|
|
|
|
pspec = g_object_class_find_property(G_OBJECT_GET_CLASS(obj), property_name);
|
|
|
|
nm_assert(pspec);
|
|
|
|
nm_assert(pspec->value_type != G_TYPE_VARIANT
|
|
|| nm_streq((char *) (((GParamSpecVariant *) pspec)->type), signature));
|
|
|
|
g_value_init(&value, pspec->value_type);
|
|
|
|
g_object_get_property(obj, property_name, &value);
|
|
|
|
variant = g_dbus_gvalue_to_gvariant(&value, G_VARIANT_TYPE(signature));
|
|
|
|
nm_assert(!variant || g_variant_is_of_type(variant, G_VARIANT_TYPE(signature)));
|
|
|
|
/* returns never-floating variant */
|
|
nm_assert(!variant || !g_variant_is_floating(variant));
|
|
|
|
return variant;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void
|
|
nm_dbus_utils_g_value_set_object_path(GValue *value, gpointer object)
|
|
{
|
|
const char *path;
|
|
|
|
g_return_if_fail(!object || NM_IS_DBUS_OBJECT(object));
|
|
|
|
if (object && (path = nm_dbus_object_get_path(object)))
|
|
g_value_set_string(value, path);
|
|
else
|
|
g_value_set_string(value, NULL);
|
|
}
|
|
|
|
void
|
|
nm_dbus_utils_g_value_set_object_path_still_exported(GValue *value, gpointer object)
|
|
{
|
|
const char *path;
|
|
|
|
g_return_if_fail(!object || NM_IS_DBUS_OBJECT(object));
|
|
|
|
if (object && (path = nm_dbus_object_get_path_still_exported(object)))
|
|
g_value_set_string(value, path);
|
|
else
|
|
g_value_set_string(value, "/");
|
|
}
|
|
|
|
void
|
|
nm_dbus_utils_g_value_set_object_path_from_hash(
|
|
GValue * value,
|
|
GHashTable *hash /* has keys of NMDBusObject type. */,
|
|
gboolean expect_all_exported)
|
|
{
|
|
NMDBusObject * obj;
|
|
char ** strv;
|
|
guint i, n;
|
|
GHashTableIter iter;
|
|
|
|
nm_assert(value);
|
|
nm_assert(hash);
|
|
|
|
n = g_hash_table_size(hash);
|
|
strv = g_new(char *, n + 1);
|
|
i = 0;
|
|
g_hash_table_iter_init(&iter, hash);
|
|
while (g_hash_table_iter_next(&iter, (gpointer *) &obj, NULL)) {
|
|
const char *path;
|
|
|
|
path = nm_dbus_object_get_path_still_exported(obj);
|
|
if (!path) {
|
|
nm_assert(!expect_all_exported);
|
|
continue;
|
|
}
|
|
strv[i++] = g_strdup(path);
|
|
}
|
|
nm_assert(i <= n);
|
|
strv[i] = NULL;
|
|
|
|
/* sort the names, to give a well-defined, stable order. */
|
|
nm_utils_strv_sort(strv, i);
|
|
|
|
g_value_take_boxed(value, strv);
|
|
}
|
|
|
|
const char **
|
|
nm_dbus_utils_get_paths_for_clist(const CList *lst_head,
|
|
gssize lst_len,
|
|
guint member_offset,
|
|
gboolean expect_all_exported)
|
|
{
|
|
const CList *iter;
|
|
const char **strv;
|
|
const char * path;
|
|
gsize i, n;
|
|
|
|
nm_assert(lst_head);
|
|
|
|
if (lst_len < 0)
|
|
n = c_list_length(lst_head);
|
|
else {
|
|
n = lst_len;
|
|
nm_assert(n == c_list_length(lst_head));
|
|
}
|
|
|
|
i = 0;
|
|
strv = g_new(const char *, n + 1);
|
|
c_list_for_each (iter, lst_head) {
|
|
NMDBusObject *obj = (NMDBusObject *) (((const char *) iter) - member_offset);
|
|
|
|
path = nm_dbus_object_get_path(obj);
|
|
if (!path) {
|
|
nm_assert(expect_all_exported);
|
|
continue;
|
|
}
|
|
|
|
nm_assert(i < n);
|
|
strv[i++] = path;
|
|
}
|
|
nm_assert(i <= n);
|
|
strv[i] = NULL;
|
|
|
|
return strv;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void
|
|
nm_dbus_track_obj_path_init(NMDBusTrackObjPath *track, GObject *target, const GParamSpec *pspec)
|
|
{
|
|
nm_assert(track);
|
|
nm_assert(G_IS_OBJECT(target));
|
|
nm_assert(G_IS_PARAM_SPEC(pspec));
|
|
|
|
track->_obj = NULL;
|
|
track->_notify_target = target;
|
|
track->_notify_pspec = pspec;
|
|
track->_notify_signal_id = 0;
|
|
track->_visible = FALSE;
|
|
}
|
|
|
|
void
|
|
nm_dbus_track_obj_path_deinit(NMDBusTrackObjPath *track)
|
|
{
|
|
/* we allow deinit() to be called multiple times (e.g. from
|
|
* dispose(), which must be re-entrant). */
|
|
nm_assert(track);
|
|
nm_assert(!track->_notify_target || G_IS_OBJECT(track->_notify_target));
|
|
|
|
nm_clear_g_signal_handler(track->obj, &track->_notify_signal_id);
|
|
track->_notify_target = NULL;
|
|
track->_notify_pspec = NULL;
|
|
track->_visible = FALSE;
|
|
nm_clear_g_object(&track->_obj);
|
|
}
|
|
|
|
void
|
|
nm_dbus_track_obj_path_notify(const NMDBusTrackObjPath *track)
|
|
{
|
|
nm_assert(track);
|
|
nm_assert(G_IS_OBJECT(track->_notify_target));
|
|
nm_assert(G_IS_PARAM_SPEC(track->_notify_pspec));
|
|
|
|
g_object_notify_by_pspec(track->_notify_target, (GParamSpec *) track->_notify_pspec);
|
|
}
|
|
|
|
const char *
|
|
nm_dbus_track_obj_path_get(const NMDBusTrackObjPath *track)
|
|
{
|
|
nm_assert(track);
|
|
nm_assert(G_IS_OBJECT(track->_notify_target));
|
|
|
|
return track->obj && track->visible ? nm_dbus_object_get_path_still_exported(track->obj) : NULL;
|
|
}
|
|
|
|
static void
|
|
_track_obj_exported_changed(NMDBusObject *obj, NMDBusTrackObjPath *track)
|
|
{
|
|
nm_dbus_track_obj_path_notify(track);
|
|
}
|
|
|
|
void
|
|
nm_dbus_track_obj_path_set(NMDBusTrackObjPath *track, gpointer obj, gboolean visible)
|
|
{
|
|
gs_unref_object NMDBusObject *old_obj = NULL;
|
|
const char * old_path;
|
|
|
|
nm_assert(track);
|
|
nm_assert(G_IS_OBJECT(track->_notify_target));
|
|
|
|
g_return_if_fail(!obj || NM_IS_DBUS_OBJECT(obj));
|
|
|
|
if (track->obj == obj && track->visible == !!visible)
|
|
return;
|
|
|
|
old_path = nm_dbus_track_obj_path_get(track);
|
|
|
|
track->_visible = visible;
|
|
|
|
if (track->obj != obj) {
|
|
nm_clear_g_signal_handler(track->obj, &track->_notify_signal_id);
|
|
|
|
old_obj = track->obj;
|
|
track->_obj = nm_g_object_ref(obj);
|
|
|
|
if (obj) {
|
|
track->_notify_signal_id = g_signal_connect(obj,
|
|
NM_DBUS_OBJECT_EXPORTED_CHANGED,
|
|
G_CALLBACK(_track_obj_exported_changed),
|
|
track);
|
|
}
|
|
}
|
|
|
|
if (!nm_streq0(old_path, nm_dbus_track_obj_path_get(track)))
|
|
nm_dbus_track_obj_path_notify(track);
|
|
}
|