libnm: add helper functions for refactoring D-Bus calls in libnm

We will drop GDBusProxy and the gdbus-codegen classes. First, we need to
replace all D-Bus calls from nmdbus_*() API with plain uses of GDBusConnection.
For that, add accessors to get the dbus-connection and the name-owner.

This API is not beautiful, it's an interim solution for now.
This commit is contained in:
Thomas Haller
2019-10-04 13:56:36 +02:00
parent ba2e1d52ad
commit e6e6057a13
4 changed files with 299 additions and 8 deletions

View File

@@ -100,6 +100,7 @@ typedef struct {
NMDnsManager *dns_manager;
GDBusObjectManager *object_manager;
GCancellable *new_object_manager_cancellable;
char *name_owner_cached;
struct udev *udev;
bool udev_inited:1;
} NMClientPrivate;
@@ -168,6 +169,41 @@ NM_CACHED_QUARK_FCN ("nm-client-error-quark", nm_client_error_quark)
/*****************************************************************************/
GDBusConnection *
_nm_client_get_dbus_connection (NMClient *client)
{
NMClientPrivate *priv;
nm_assert (NM_IS_CLIENT (client));
priv = NM_CLIENT_GET_PRIVATE (client);
if (!priv->object_manager)
return NULL;
return g_dbus_object_manager_client_get_connection (G_DBUS_OBJECT_MANAGER_CLIENT (priv->object_manager));
}
const char *
_nm_client_get_dbus_name_owner (NMClient *client)
{
NMClientPrivate *priv;
nm_assert (NM_IS_CLIENT (client));
priv = NM_CLIENT_GET_PRIVATE (client);
nm_clear_g_free (&priv->name_owner_cached);
if (!priv->object_manager)
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;
}
/*****************************************************************************/
static void
nm_client_init (NMClient *client)
{
@@ -176,15 +212,11 @@ nm_client_init (NMClient *client)
static gboolean
_nm_client_check_nm_running (NMClient *client, GError **error)
{
if (nm_client_get_nm_running (client))
return TRUE;
else {
g_set_error_literal (error,
NM_CLIENT_ERROR,
NM_CLIENT_ERROR_MANAGER_NOT_RUNNING,
"NetworkManager is not running");
if (!nm_client_get_nm_running (client)) {
_nm_object_set_error_nm_not_running (error);
return FALSE;
}
return TRUE;
}
/**
@@ -3468,6 +3500,8 @@ dispose (GObject *object)
udev_unref (priv->udev);
priv->udev = NULL;
}
nm_clear_g_free (&priv->name_owner_cached);
}
static void

View File

@@ -12,6 +12,8 @@
#include "nm-std-aux/nm-dbus-compat.h"
#define NM_DBUS_DEFAULT_TIMEOUT_MSEC 25000
GBusType _nm_dbus_bus_type (void);
void _nm_dbus_proxy_replace_match (GDBusProxy *proxy);

View File

@@ -34,7 +34,50 @@ GDBusObjectManager *_nm_object_get_dbus_object_manager (NMObject *object);
GQuark _nm_object_obj_nm_quark (void);
/* DBus property accessors */
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,
@@ -45,6 +88,9 @@ void _nm_object_set_property (NMObject *object,
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);

View File

@@ -69,6 +69,8 @@ typedef struct {
CList pending; /* ordered list of pending property updates. */
GPtrArray *proxies;
char *name_owner_cached;
} NMObjectPrivate;
enum {
@@ -127,6 +129,211 @@ _nm_object_get_proxy (NMObject *object,
return G_DBUS_PROXY (proxy);
}
/*****************************************************************************/
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)
{
NMObjectPrivate *priv;
nm_assert (NM_IS_OBJECT (self));
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;
}
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);
}
*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");
}
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 ();
}
}
/*****************************************************************************/
typedef enum {
NOTIFY_SIGNAL_PENDING_NONE,
NOTIFY_SIGNAL_PENDING_ADDED,
@@ -1251,6 +1458,8 @@ finalize (GObject *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);
}