summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Winship <danw@redhat.com>2015-03-27 08:02:25 -0400
committerDan Winship <danw@redhat.com>2015-04-02 10:04:21 -0400
commitf33e6c7d0b7b7b95a0f9b7efc7dbe5c3ce86037e (patch)
tree8e12fad9f789033a0bdd7e106094c994a5af2464
parentfa19fc0a7ab268125842f139353aac06c405e442 (diff)
downloadNetworkManager-f33e6c7d0b7b7b95a0f9b7efc7dbe5c3ce86037e.tar.gz
libnm-core: add _nm_dbus_signal_connect()
Add _nm_dbus_signal_connect(), for connecting to D-Bus signals on a GDBusProxy, with typechecking and pre-parsing of the parameters variant.
-rw-r--r--libnm-core/Makefile.libnm-core1
-rw-r--r--libnm-core/nm-core-internal.h12
-rw-r--r--libnm-core/nm-dbus-utils.c166
3 files changed, 179 insertions, 0 deletions
diff --git a/libnm-core/Makefile.libnm-core b/libnm-core/Makefile.libnm-core
index 09a80c714b..bbd504503a 100644
--- a/libnm-core/Makefile.libnm-core
+++ b/libnm-core/Makefile.libnm-core
@@ -58,6 +58,7 @@ libnm_core_sources = \
$(core_build)/nm-core-enum-types.c \
$(core)/crypto.c \
$(core)/nm-connection.c \
+ $(core)/nm-dbus-utils.c \
$(core)/nm-errors.c \
$(core)/nm-keyfile-reader.c \
$(core)/nm-keyfile-utils.c \
diff --git a/libnm-core/nm-core-internal.h b/libnm-core/nm-core-internal.h
index 8f21e8fe36..4cb628db96 100644
--- a/libnm-core/nm-core-internal.h
+++ b/libnm-core/nm-core-internal.h
@@ -33,6 +33,8 @@
* and some test programs.
**/
+#include <gio/gio.h>
+
#include "nm-connection.h"
#include "nm-core-enum-types.h"
#include "nm-dbus-interface.h"
@@ -139,4 +141,14 @@ GByteArray *nm_utils_rsa_key_encrypt (const guint8 *data,
gint64 _nm_utils_ascii_str_to_int64 (const char *str, guint base, gint64 min, gint64 max, gint64 fallback);
+gulong _nm_dbus_signal_connect_data (GDBusProxy *proxy,
+ const char *signal_name,
+ const GVariantType *signature,
+ GCallback c_handler,
+ gpointer data,
+ GClosureNotify destroy_data,
+ GConnectFlags connect_flags);
+#define _nm_dbus_signal_connect(proxy, name, signature, handler, data) \
+ _nm_dbus_signal_connect_data (proxy, name, signature, handler, data, NULL, (GConnectFlags) 0);
+
#endif
diff --git a/libnm-core/nm-dbus-utils.c b/libnm-core/nm-dbus-utils.c
new file mode 100644
index 0000000000..6d4e413f96
--- /dev/null
+++ b/libnm-core/nm-dbus-utils.c
@@ -0,0 +1,166 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2015 Red Hat, Inc.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <gio/gio.h>
+
+#include "nm-core-internal.h"
+
+typedef struct {
+ char *signal_name;
+ const GVariantType *signature;
+ GClosure *closure;
+} NMDBusSignalData;
+
+static void
+free_signal_data (gpointer data, GClosure *closure)
+{
+ NMDBusSignalData *sd = data;
+
+ g_free (sd->signal_name);
+ g_closure_unref (sd->closure);
+ g_slice_free (NMDBusSignalData, sd);
+}
+
+static void
+nm_dbus_signal_handler (GDBusProxy *proxy,
+ const char *sender_name,
+ const char *signal_name,
+ GVariant *parameters,
+ gpointer user_data)
+{
+ NMDBusSignalData *sd = user_data;
+ GValue *closure_params;
+ gsize n_params, i;
+ GVariant *param;
+
+ if (strcmp (signal_name, sd->signal_name) != 0)
+ return;
+
+ if (sd->signature) {
+ if (!g_variant_is_of_type (parameters, sd->signature)) {
+ g_warning ("%p: got signal '%s' but parameters were of type '%s', not '%s'",
+ proxy, signal_name, g_variant_get_type_string (parameters),
+ g_variant_type_peek_string (sd->signature));
+ return;
+ }
+
+ n_params = g_variant_n_children (parameters) + 1;
+ } else
+ n_params = 1;
+
+ closure_params = g_new0 (GValue, n_params);
+ g_value_init (&closure_params[0], G_TYPE_OBJECT);
+ g_value_set_object (&closure_params[0], proxy);
+
+ for (i = 1; i < n_params; i++) {
+ param = g_variant_get_child_value (parameters, i - 1);
+ if ( g_variant_is_of_type (param, G_VARIANT_TYPE ("ay"))
+ || g_variant_is_of_type (param, G_VARIANT_TYPE ("aay"))) {
+ /* g_dbus_gvariant_to_gvalue() thinks 'ay' means "non-UTF-8 NUL-terminated string" */
+ g_value_init (&closure_params[i], G_TYPE_VARIANT);
+ g_value_set_variant (&closure_params[i], param);
+ } else
+ g_dbus_gvariant_to_gvalue (param, &closure_params[i]);
+ g_variant_unref (param);
+ }
+
+ g_closure_invoke (sd->closure,
+ NULL,
+ n_params,
+ closure_params,
+ g_signal_get_invocation_hint (proxy));
+
+ for (i = 0; i < n_params; i++)
+ g_value_unset (&closure_params[i]);
+ g_free (closure_params);
+}
+
+/**
+ * _nm_dbus_signal_connect_data:
+ * @proxy: a #GDBusProxy
+ * @signal_name: the D-Bus signal to connect to
+ * @signature: (allow-none): the signal's type signature (must be a tuple)
+ * @c_handler: the signal handler function
+ * @data: (allow-none): data to pass to @c_handler
+ * @destroy_data: (allow-none): closure destroy notify for @data
+ * @connect_flags: connection flags
+ *
+ * Connects to the D-Bus signal @signal_name on @proxy. @c_handler must be a
+ * void function whose first argument is a #GDBusProxy, followed by arguments
+ * for each element of @signature, ending with a #gpointer argument for @data.
+ *
+ * The argument types in @c_handler correspond to the types output by
+ * g_dbus_gvariant_to_gvalue(), except for 'ay' and 'aay'. In particular:
+ * - both 16-bit and 32-bit integers are passed as #gint/#guint
+ * - 'as' values are passed as #GStrv (char **)
+ * - all other array, tuple, and dict types are passed as #GVariant
+ *
+ * If @signature is %NULL, then the signal's parameters will be ignored, and
+ * @c_handler should take only the #GDBusProxy and #gpointer arguments.
+ *
+ * Returns: the signal handler ID, which can be used with
+ * g_signal_handler_remove(). Note that other functions like
+ * g_signal_handlers_remove_matched() cannot be used with handlers connected
+ * via this function, since @c_handler and @data are not the actual handler
+ * and data passed to g_signal_connect_data().
+ */
+gulong
+_nm_dbus_signal_connect_data (GDBusProxy *proxy,
+ const char *signal_name,
+ const GVariantType *signature,
+ GCallback c_handler,
+ gpointer data,
+ GClosureNotify destroy_data,
+ GConnectFlags connect_flags)
+{
+ NMDBusSignalData *sd;
+
+ g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), 0);
+ g_return_val_if_fail (signal_name != NULL, 0);
+ g_return_val_if_fail (signature == NULL || g_variant_type_is_tuple (signature), 0);
+ g_return_val_if_fail (c_handler != NULL, 0);
+
+ sd = g_slice_new (NMDBusSignalData);
+ sd->signal_name = g_strdup (signal_name);
+ sd->signature = signature;
+ sd->closure = g_cclosure_new (c_handler, data, destroy_data);
+ g_closure_sink (g_closure_ref (sd->closure));
+ g_closure_set_marshal (sd->closure, g_cclosure_marshal_generic);
+
+ return g_signal_connect_data (proxy, "g-signal",
+ G_CALLBACK (nm_dbus_signal_handler), sd,
+ free_signal_data, connect_flags);
+}
+
+/**
+ * _nm_dbus_signal_connect:
+ * @proxy: a #GDBusProxy
+ * @signal_name: the D-Bus signal to connect to
+ * @signature: the signal's type signature (must be a tuple)
+ * @c_handler: the signal handler function
+ * @data: (allow-none): data to pass to @c_handler
+ *
+ * Simplified version of _nm_dbus_signal_connect_data() with fewer arguments.
+ *
+ * Returns: the signal handler ID, as with _nm_signal_connect_data().
+ */