summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2019-10-04 13:56:36 +0200
committerThomas Haller <thaller@redhat.com>2019-10-16 08:56:00 +0200
commite6e6057a13b5cd6ac558085fd951511ffaafb79a (patch)
treeb3bfa3376ed81eaecfe21e997242d2380aa698c1
parentba2e1d52ad4f28bc91d67bf670a53405311d8215 (diff)
downloadNetworkManager-e6e6057a13b5cd6ac558085fd951511ffaafb79a.tar.gz
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.
-rw-r--r--libnm/nm-client.c48
-rw-r--r--libnm/nm-dbus-helpers.h2
-rw-r--r--libnm/nm-object-private.h48
-rw-r--r--libnm/nm-object.c209
4 files changed, 299 insertions, 8 deletions
diff --git a/libnm/nm-client.c b/libnm/nm-client.c
index 7785628624..e2c1ea751f 100644
--- a/libnm/nm-client.c
+++ b/libnm/nm-client.c
@@ -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
diff --git a/libnm/nm-dbus-helpers.h b/libnm/nm-dbus-helpers.h
index 8f823f0e87..5a0fb756ab 100644
--- a/libnm/nm-dbus-helpers.h
+++ b/libnm/nm-dbus-helpers.h
@@ -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);
diff --git a/libnm/nm-object-private.h b/libnm/nm-object-private.h
index eb9e0f1407..863b228fae 100644
--- a/libnm/nm-object-private.h
+++ b/libnm/nm-object-private.h
@@ -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);
diff --git a/libnm/nm-object.c b/libnm/nm-object.c
index 8c91e7a38e..bbe97eb6cd 100644
--- a/libnm/nm-object.c
+++ b/libnm/nm-object.c
@@ -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);
}