diff --git a/libnm-core/Makefile.libnm-core b/libnm-core/Makefile.libnm-core index 09a80c714..bbd504503 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 8f21e8fe3..f586f4b35 100644 --- a/libnm-core/nm-core-internal.h +++ b/libnm-core/nm-core-internal.h @@ -33,6 +33,8 @@ * and some test programs. **/ +#include + #include "nm-connection.h" #include "nm-core-enum-types.h" #include "nm-dbus-interface.h" @@ -139,4 +141,30 @@ 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) + +GVariant *_nm_dbus_proxy_call_finish (GDBusProxy *proxy, + GAsyncResult *res, + const GVariantType *reply_type, + GError **error); + +GVariant *_nm_dbus_proxy_call_sync (GDBusProxy *proxy, + const gchar *method_name, + GVariant *parameters, + const GVariantType *reply_type, + GDBusCallFlags flags, + gint timeout_msec, + GCancellable *cancellable, + GError **error); + +gboolean _nm_dbus_error_has_name (GError *error, + const char *dbus_error_name); #endif diff --git a/libnm-core/nm-dbus-utils.c b/libnm-core/nm-dbus-utils.c new file mode 100644 index 000000000..1f1e20ced --- /dev/null +++ b/libnm-core/nm-dbus-utils.c @@ -0,0 +1,290 @@ +/* -*- 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 +#include +#include + +#include "nm-core-internal.h" + +typedef struct { + char *signal_name; + const GVariantType *signature; +} NMDBusSignalData; + +static void +dbus_signal_data_free (gpointer data, GClosure *closure) +{ + NMDBusSignalData *sd = data; + + g_free (sd->signal_name); + g_slice_free (NMDBusSignalData, sd); +} + +static void +dbus_signal_meta_marshal (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data) +{ + NMDBusSignalData *sd = marshal_data; + const char *signal_name; + GVariant *parameters, *param; + GValue *closure_params; + gsize n_params, i; + + g_return_if_fail (n_param_values == 4); + + signal_name = g_value_get_string (¶m_values[2]); + parameters = g_value_get_variant (¶m_values[3]); + + 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'", + g_value_get_object (¶m_values[0]), + 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_copy (¶m_values[0], &closure_params[0]); + + 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_cclosure_marshal_generic (closure, + NULL, + n_params, + closure_params, + invocation_hint, + NULL); + + 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(). Beware that because of the way the signal is + * connected, you will not be able to remove it with + * g_signal_handlers_disconnect_by_func(), although + * g_signal_handlers_disconnect_by_data() will work correctly. + */ +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; + GClosure *closure; + gboolean swapped = !!(connect_flags & G_CONNECT_SWAPPED); + gboolean after = !!(connect_flags & G_CONNECT_AFTER); + + 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; + + closure = (swapped ? g_cclosure_new_swap : g_cclosure_new) (c_handler, data, destroy_data); + g_closure_set_marshal (closure, g_cclosure_marshal_generic); + g_closure_set_meta_marshal (closure, sd, dbus_signal_meta_marshal); + g_closure_add_finalize_notifier (closure, sd, dbus_signal_data_free); + + return g_signal_connect_closure (proxy, "g-signal", closure, after); +} + +/** + * _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(). + */ + + +static void +typecheck_response (GVariant **response, + const GVariantType *reply_type, + GError **error) +{ + if (*response && reply_type && !g_variant_is_of_type (*response, reply_type)) { + /* This is the same error code that g_dbus_connection_call() returns if + * @reply_type doesn't match. + */ + g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, + _("Method returned type '%s', but expected '%s'"), + g_variant_get_type_string (*response), + g_variant_type_peek_string (reply_type)); + g_clear_pointer (response, g_variant_unref); + } +} + +/** + * _nm_dbus_proxy_call_finish: + * @proxy: A #GDBusProxy. + * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback passed to + * g_dbus_proxy_call(). + * @reply_type: (allow-none): the expected type of the reply, or %NULL + * @error: Return location for error or %NULL. + * + * Finishes an operation started with g_dbus_proxy_call(), as with + * g_dbus_proxy_call_finish(), except thatif @reply_type is non-%NULL, then it + * will also check that the response matches that type signature, and return + * an error if not. + * + * Returns: %NULL if @error is set. Otherwise a #GVariant tuple with + * return values. Free with g_variant_unref(). + */ +GVariant * +_nm_dbus_proxy_call_finish (GDBusProxy *proxy, + GAsyncResult *res, + const GVariantType *reply_type, + GError **error) +{ + GVariant *ret; + + ret = g_dbus_proxy_call_finish (proxy, res, error); + typecheck_response (&ret, reply_type, error); + return ret; +} + +/** + * _nm_dbus_proxy_call_sync: + * @proxy: A #GDBusProxy. + * @method_name: Name of method to invoke. + * @parameters: (allow-none): A #GVariant tuple with parameters for the signal + * or %NULL if not passing parameters. + * @reply_type: (allow-none): the expected type of the reply, or %NULL + * @flags: Flags from the #GDBusCallFlags enumeration. + * @timeout_msec: The timeout in milliseconds (with %G_MAXINT meaning + * "infinite") or -1 to use the proxy default timeout. + * @cancellable: (allow-none): A #GCancellable or %NULL. + * @error: Return location for error or %NULL. + * + * Synchronously invokes the @method_name method on @proxy, as with + * g_dbus_proxy_call_sync(), except that if @reply_type is non-%NULL, then the + * reply to the call will be checked against it, and an error returned if it + * does not match. + * + * Returns: %NULL if @error is set. Otherwise a #GVariant tuple with + * return values. Free with g_variant_unref(). + */ +GVariant * +_nm_dbus_proxy_call_sync (GDBusProxy *proxy, + const gchar *method_name, + GVariant *parameters, + const GVariantType *reply_type, + GDBusCallFlags flags, + gint timeout_msec, + GCancellable *cancellable, + GError **error) +{ + GVariant *ret; + + ret = g_dbus_proxy_call_sync (proxy, method_name, parameters, + flags, timeout_msec, + cancellable, error); + typecheck_response (&ret, reply_type, error); + return ret; +} + +/** + * _nm_dbus_error_has_name: + * @error: (allow-none): a #GError, or %NULL + * @dbus_error_name: a D-Bus error name + * + * Checks if @error is set and corresponds to the D-Bus error @dbus_error_name. + * + * Returns: %TRUE or %FALSE + */ +gboolean +_nm_dbus_error_has_name (GError *error, + const char *dbus_error_name) +{ + gboolean has_name = FALSE; + + if (error && g_dbus_error_is_remote_error (error)) { + char *error_name; + + error_name = g_dbus_error_get_remote_error (error); + has_name = !g_strcmp0 (error_name, dbus_error_name); + g_free (error_name); + } + + return has_name; +} diff --git a/libnm/nm-object.c b/libnm/nm-object.c index 5504efbe5..bf25000bc 100644 --- a/libnm/nm-object.c +++ b/libnm/nm-object.c @@ -34,6 +34,7 @@ #include "nm-glib-compat.h" #include "nm-dbus-helpers.h" #include "nm-client.h" +#include "nm-core-internal.h" static gboolean debug = FALSE; #define dbgmsg(f,...) if (G_UNLIKELY (debug)) { g_message (f, ## __VA_ARGS__ ); } @@ -511,7 +512,8 @@ create_async_got_property (GObject *proxy, GAsyncResult *result, gpointer user_d GError *error = NULL; GType type; - ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), result, &error); + ret = _nm_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), result, + G_VARIANT_TYPE ("(v)"), &error); if (ret) { g_variant_get (ret, "(v)", &value); type = type_data->type_func (value); @@ -519,8 +521,8 @@ create_async_got_property (GObject *proxy, GAsyncResult *result, gpointer user_d g_variant_unref (ret); } else { dbgmsg ("Could not fetch property '%s' of interface '%s' on %s: %s\n", - type_data->property, type_data->interface, async_data->path, - error->message); + type_data->property, type_data->interface, async_data->path, + error->message); g_clear_error (&error); type = G_TYPE_INVALID; } @@ -961,20 +963,11 @@ process_properties_changed (NMObject *self, GVariant *properties, gboolean synch } static void -property_proxy_signal (GDBusProxy *proxy, - const char *sender_name, - const char *signal_name, - GVariant *parameters, - gpointer user_data) +properties_changed (GDBusProxy *proxy, + GVariant *properties, + gpointer user_data) { - GVariant *properties; - - if (strcmp (signal_name, "PropertiesChanged") != 0) - return; - - g_variant_get (parameters, "(@a{sv})", &properties); process_properties_changed (NM_OBJECT (user_data), properties, FALSE); - g_variant_unref (properties); } #define HANDLE_TYPE(vtype, ctype, getter) \ @@ -1117,8 +1110,8 @@ _nm_object_register_properties (NMObject *object, proxy = _nm_object_get_proxy (object, interface); g_return_if_fail (proxy != NULL); - g_signal_connect (proxy, "g-signal", - G_CALLBACK (property_proxy_signal), object); + _nm_dbus_signal_connect (proxy, "PropertiesChanged", G_VARIANT_TYPE ("(a{sv})"), + G_CALLBACK (properties_changed), object); instance = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); priv->property_tables = g_slist_prepend (priv->property_tables, instance); @@ -1156,11 +1149,12 @@ _nm_object_reload_properties (NMObject *object, GError **error) g_hash_table_iter_init (&iter, priv->proxies); while (g_hash_table_iter_next (&iter, (gpointer *) &interface, (gpointer *) &proxy)) { - ret = g_dbus_proxy_call_sync (priv->properties_proxy, - "GetAll", - g_variant_new ("(s)", interface), - G_DBUS_CALL_FLAGS_NONE, -1, - NULL, error); + ret = _nm_dbus_proxy_call_sync (priv->properties_proxy, + "GetAll", + g_variant_new ("(s)", interface), + G_VARIANT_TYPE ("(a{sv})"), + G_DBUS_CALL_FLAGS_NONE, -1, + NULL, error); if (!ret) { if (error && *error) g_dbus_error_strip_remote_error (*error); @@ -1203,11 +1197,12 @@ _nm_object_reload_property (NMObject *object, if (!NM_OBJECT_GET_PRIVATE (object)->nm_running) return; - ret = g_dbus_proxy_call_sync (NM_OBJECT_GET_PRIVATE (object)->properties_proxy, - "Get", - g_variant_new ("(ss)", interface, prop_name), - G_DBUS_CALL_FLAGS_NONE, 15000, - NULL, &err); + ret = _nm_dbus_proxy_call_sync (NM_OBJECT_GET_PRIVATE (object)->properties_proxy, + "Get", + g_variant_new ("(ss)", interface, prop_name), + G_VARIANT_TYPE ("(v)"), + G_DBUS_CALL_FLAGS_NONE, 15000, + NULL, &err); if (!ret) { dbgmsg ("%s: Error getting '%s' for %s: (%d) %s\n", __func__, @@ -1305,7 +1300,9 @@ reload_got_properties (GObject *proxy, GVariant *ret, *props; GError *error = NULL; - ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), result, &error); + ret = _nm_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), result, + G_VARIANT_TYPE ("(a{sv})"), + &error); if (ret) { g_variant_get (ret, "(@a{sv})", &props); process_properties_changed (object, props, FALSE); diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c index 66108afe2..ba2319af5 100644 --- a/src/NetworkManagerUtils.c +++ b/src/NetworkManagerUtils.c @@ -1153,101 +1153,6 @@ nm_utils_get_shared_wifi_permission (NMConnection *connection) /*********************************/ -static void -nm_gvalue_destroy (gpointer data) -{ - GValue *value = (GValue *) data; - - g_value_unset (value); - g_slice_free (GValue, value); -} - -GHashTable * -value_hash_create (void) -{ - return g_hash_table_new_full (g_str_hash, g_str_equal, g_free, nm_gvalue_destroy); -} - -void -value_hash_add (GHashTable *hash, - const char *key, - GValue *value) -{ - g_hash_table_insert (hash, g_strdup (key), value); -} - -void -value_hash_add_str (GHashTable *hash, - const char *key, - const char *str) -{ - GValue *value; - - value = g_slice_new0 (GValue); - g_value_init (value, G_TYPE_STRING); - g_value_set_string (value, str); - - value_hash_add (hash, key, value); -} - -void -value_hash_add_object_path (GHashTable *hash, - const char *key, - const char *op) -{ - GValue *value; - - value = g_slice_new0 (GValue); - g_value_init (value, DBUS_TYPE_G_OBJECT_PATH); - g_value_set_boxed (value, op); - - value_hash_add (hash, key, value); -} - -void -value_hash_add_uint (GHashTable *hash, - const char *key, - guint32 val) -{ - GValue *value; - - value = g_slice_new0 (GValue); - g_value_init (value, G_TYPE_UINT); - g_value_set_uint (value, val); - - value_hash_add (hash, key, value); -} - -void -value_hash_add_bool (GHashTable *hash, - const char *key, - gboolean val) -{ - GValue *value; - - value = g_slice_new0 (GValue); - g_value_init (value, G_TYPE_BOOLEAN); - g_value_set_boolean (value, val); - - value_hash_add (hash, key, value); -} - -void -value_hash_add_object_property (GHashTable *hash, - const char *key, - GObject *object, - const char *prop, - GType val_type) -{ - GValue *value; - - value = g_slice_new0 (GValue); - g_value_init (value, val_type); - g_object_get_property (object, prop, value); - value_hash_add (hash, key, value); -} - - static char * get_new_connection_name (const GSList *existing, const char *preferred, diff --git a/src/NetworkManagerUtils.h b/src/NetworkManagerUtils.h index b74fd1cbf..5633d4b2f 100644 --- a/src/NetworkManagerUtils.h +++ b/src/NetworkManagerUtils.h @@ -109,33 +109,6 @@ GSList *nm_match_spec_split (const char *value); const char *nm_utils_get_shared_wifi_permission (NMConnection *connection); -GHashTable *value_hash_create (void); -void value_hash_add (GHashTable *hash, - const char *key, - GValue *value); - -void value_hash_add_str (GHashTable *hash, - const char *key, - const char *str); - -void value_hash_add_object_path (GHashTable *hash, - const char *key, - const char *op); - -void value_hash_add_uint (GHashTable *hash, - const char *key, - guint32 val); - -void value_hash_add_bool (GHashTable *hash, - const char *key, - gboolean val); - -void value_hash_add_object_property (GHashTable *hash, - const char *key, - GObject *object, - const char *prop, - GType val_type); - const char *nm_utils_get_ip_config_method (NMConnection *connection, GType ip_setting_type); diff --git a/src/devices/bluetooth/nm-bluez-device.c b/src/devices/bluetooth/nm-bluez-device.c index fe1a97bba..48f7ddf0e 100644 --- a/src/devices/bluetooth/nm-bluez-device.c +++ b/src/devices/bluetooth/nm-bluez-device.c @@ -864,21 +864,14 @@ properties_changed (GDBusProxy *proxy, static void bluez4_property_changed (GDBusProxy *proxy, - const char *sender, - const char *signal_name, - GVariant *parameters, - gpointer user_data) + const char *property, + GVariant *v, + gpointer user_data) { NMBluezDevice *self = NM_BLUEZ_DEVICE (user_data); - if (g_strcmp0 (signal_name, "PropertyChanged") == 0) { - const char *property = NULL; - GVariant *v = NULL; - - g_variant_get (parameters, "(&sv)", &property, &v); - _take_one_variant_property (self, property, v); - check_emit_usable (self); - } + _take_one_variant_property (self, property, v); + check_emit_usable (self); } static void @@ -888,27 +881,21 @@ get_properties_cb_4 (GObject *source_object, GAsyncResult *res, gpointer user_da NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); GError *err = NULL; GVariant *v_properties, *v_dict; - GVariantType *v_type; - v_properties = g_dbus_proxy_call_finish (priv->proxy, res, &err); + v_properties = _nm_dbus_proxy_call_finish (priv->proxy, res, + G_VARIANT_TYPE ("(a{sv})"), + &err); if (!v_properties) { nm_log_warn (LOGD_BT, "bluez[%s] error getting device properties: %s", - priv->path, err && err->message ? err->message : "(unknown)"); + priv->path, err->message); g_error_free (err); g_signal_emit (self, signals[INITIALIZED], 0, FALSE); goto END; } - v_type = g_variant_type_new ("(a{sv})"); - if (g_variant_is_of_type (v_properties, v_type)) { - v_dict = g_variant_get_child_value (v_properties, 0); - _set_properties (self, v_dict); - g_variant_unref (v_dict); - } else { - nm_log_warn (LOGD_BT, "bluez[%s] GetProperties returns unexpected result of type %s", priv->path, g_variant_get_type_string (v_properties)); - } - g_variant_type_free (v_type); - + v_dict = g_variant_get_child_value (v_properties, 0); + _set_properties (self, v_dict); + g_variant_unref (v_dict); g_variant_unref (v_properties); /* Check if any connections match this device */ @@ -917,7 +904,6 @@ get_properties_cb_4 (GObject *source_object, GAsyncResult *res, gpointer user_da priv->initialized = TRUE; g_signal_emit (self, signals[INITIALIZED], 0, TRUE); - check_emit_usable (self); END: @@ -985,8 +971,8 @@ on_proxy_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self) G_CALLBACK (properties_changed), self); if (priv->bluez_version == 4) { /* Watch for custom Bluez4 PropertyChanged signals */ - g_signal_connect (priv->proxy, "g-signal", - G_CALLBACK (bluez4_property_changed), self); + _nm_dbus_signal_connect (priv->proxy, "PropertyChanged", G_VARIANT_TYPE ("(sv)"), + G_CALLBACK (bluez4_property_changed), self); } query_properties (self); diff --git a/src/devices/bluetooth/nm-bluez-manager.c b/src/devices/bluetooth/nm-bluez-manager.c index e176a4b46..6b0de9949 100644 --- a/src/devices/bluetooth/nm-bluez-manager.c +++ b/src/devices/bluetooth/nm-bluez-manager.c @@ -35,8 +35,7 @@ #include "nm-bluez-common.h" #include "nm-connection-provider.h" #include "nm-device-bt.h" - -#include "nm-dbus-manager.h" +#include "nm-core-internal.h" typedef struct { int bluez_version; @@ -276,8 +275,8 @@ check_bluez_and_try_setup_do_introspect (GObject *source_object, g_clear_object (&priv->async_cancellable); - result = g_dbus_proxy_call_finish (priv->introspect_proxy, res, &error); - + result = _nm_dbus_proxy_call_finish (priv->introspect_proxy, res, + G_VARIANT_TYPE ("(s)"), &error); if (!result) { char *reason2 = g_strdup_printf ("introspect failed with %s", error->message); check_bluez_and_try_setup_final_step (self, 0, reason2); diff --git a/src/devices/bluetooth/nm-bluez4-adapter.c b/src/devices/bluetooth/nm-bluez4-adapter.c index 9d1cfe1fe..f0aa42ae8 100644 --- a/src/devices/bluetooth/nm-bluez4-adapter.c +++ b/src/devices/bluetooth/nm-bluez4-adapter.c @@ -24,13 +24,11 @@ #include #include "nm-dbus-interface.h" -#include "nm-dbus-manager.h" #include "nm-bluez4-adapter.h" #include "nm-bluez-device.h" #include "nm-bluez-common.h" -#include "nm-dbus-glib-types.h" #include "nm-logging.h" - +#include "nm-core-internal.h" G_DEFINE_TYPE (NMBluez4Adapter, nm_bluez4_adapter, G_TYPE_OBJECT) @@ -38,7 +36,7 @@ G_DEFINE_TYPE (NMBluez4Adapter, nm_bluez4_adapter, G_TYPE_OBJECT) typedef struct { char *path; - DBusGProxy *proxy; + GDBusProxy *proxy; gboolean initialized; char *address; @@ -158,7 +156,7 @@ device_do_remove (NMBluez4Adapter *self, NMBluezDevice *device) } static void -device_created (DBusGProxy *proxy, const char *path, gpointer user_data) +device_created (GDBusProxy *proxy, const char *path, gpointer user_data) { NMBluez4Adapter *self = NM_BLUEZ4_ADAPTER (user_data); NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self); @@ -173,7 +171,7 @@ device_created (DBusGProxy *proxy, const char *path, gpointer user_data) } static void -device_removed (DBusGProxy *proxy, const char *path, gpointer user_data) +device_removed (GDBusProxy *proxy, const char *path, gpointer user_data) { NMBluez4Adapter *self = NM_BLUEZ4_ADAPTER (user_data); NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self); @@ -186,37 +184,35 @@ device_removed (DBusGProxy *proxy, const char *path, gpointer user_data) device_do_remove (self, device); } - static void -get_properties_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) +get_properties_cb (GObject *proxy, GAsyncResult *result, gpointer user_data) { NMBluez4Adapter *self = NM_BLUEZ4_ADAPTER (user_data); NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self); - GHashTable *properties = NULL; GError *err = NULL; - GValue *value; - GPtrArray *devices; + GVariant *ret, *properties; + char **devices; int i; - if (!dbus_g_proxy_end_call (proxy, call, &err, - DBUS_TYPE_G_MAP_OF_VARIANT, &properties, - G_TYPE_INVALID)) { - nm_log_warn (LOGD_BT, "bluez error getting adapter properties: %s", - err && err->message ? err->message : "(unknown)"); + ret = _nm_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), result, + G_VARIANT_TYPE ("(a{sv})"), &err); + if (!ret) { + nm_log_warn (LOGD_BT, "bluez error getting adapter properties: %s", err->message); g_error_free (err); goto done; } - value = g_hash_table_lookup (properties, "Address"); - priv->address = value ? g_value_dup_string (value) : NULL; + properties = g_variant_get_child_value (ret, 0); - value = g_hash_table_lookup (properties, "Devices"); - devices = value ? g_value_get_boxed (value) : NULL; + g_variant_lookup (properties, "Address", "s", &priv->address); + if (g_variant_lookup (properties, "Devices", "^ao", &devices)) { + for (i = 0; devices[i]; i++) + device_created (priv->proxy, devices[i], self); + g_strfreev (devices); + } - for (i = 0; devices && i < devices->len; i++) - device_created (priv->proxy, g_ptr_array_index (devices, i), self); - - g_hash_table_unref (properties); + g_variant_unref (properties); + g_variant_unref (ret); priv->initialized = TRUE; @@ -228,16 +224,12 @@ static void query_properties (NMBluez4Adapter *self) { NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self); - DBusGProxyCall *call; - call = dbus_g_proxy_begin_call (priv->proxy, "GetProperties", - get_properties_cb, - self, - NULL, G_TYPE_INVALID); - if (!call) { - nm_log_warn (LOGD_BT, "failed to request Bluetooth adapter properties for %s.", - priv->path); - } + g_dbus_proxy_call (priv->proxy, "GetProperties", + NULL, + G_DBUS_CALL_FLAGS_NONE, -1, + NULL, + get_properties_cb, self); } /***********************************************************/ @@ -247,34 +239,25 @@ nm_bluez4_adapter_new (const char *path, NMConnectionProvider *provider) { NMBluez4Adapter *self; NMBluez4AdapterPrivate *priv; - DBusGConnection *connection; self = (NMBluez4Adapter *) g_object_new (NM_TYPE_BLUEZ4_ADAPTER, NM_BLUEZ4_ADAPTER_PATH, path, NULL); - if (!self) - return NULL; - priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self); priv->provider = provider; - connection = nm_dbus_manager_get_connection (nm_dbus_manager_get ()); - - priv->proxy = dbus_g_proxy_new_for_name (connection, - BLUEZ_SERVICE, - priv->path, - BLUEZ4_ADAPTER_INTERFACE); - - dbus_g_proxy_add_signal (priv->proxy, "DeviceCreated", - DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID); - dbus_g_proxy_connect_signal (priv->proxy, "DeviceCreated", - G_CALLBACK (device_created), self, NULL); - - dbus_g_proxy_add_signal (priv->proxy, "DeviceRemoved", - DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID); - dbus_g_proxy_connect_signal (priv->proxy, "DeviceRemoved", - G_CALLBACK (device_removed), self, NULL); + priv->proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, + NULL, + BLUEZ_SERVICE, + priv->path, + BLUEZ4_ADAPTER_INTERFACE, + NULL, NULL); + _nm_dbus_signal_connect (priv->proxy, "DeviceCreated", G_VARIANT_TYPE ("(o)"), + G_CALLBACK (device_created), self); + _nm_dbus_signal_connect (priv->proxy, "DeviceRemoved", G_VARIANT_TYPE ("(o)"), + G_CALLBACK (device_removed), self); query_properties (self); return self; diff --git a/src/devices/bluetooth/nm-bluez4-manager.c b/src/devices/bluetooth/nm-bluez4-manager.c index 23b13d32d..9df80bf15 100644 --- a/src/devices/bluetooth/nm-bluez4-manager.c +++ b/src/devices/bluetooth/nm-bluez4-manager.c @@ -24,24 +24,20 @@ #include #include #include -#include #include "nm-logging.h" -#include "nm-dbus-glib-types.h" #include "nm-bluez-manager.h" #include "nm-bluez4-manager.h" #include "nm-bluez4-adapter.h" -#include "nm-dbus-manager.h" #include "nm-bluez-common.h" - +#include "nm-core-internal.h" typedef struct { - NMDBusManager *dbus_mgr; gulong name_owner_changed_id; NMConnectionProvider *provider; - DBusGProxy *proxy; + GDBusProxy *proxy; NMBluez4Adapter *adapter; } NMBluez4ManagerPrivate; @@ -120,7 +116,7 @@ adapter_initialized (NMBluez4Adapter *adapter, gboolean success, gpointer user_d } static void -adapter_removed (DBusGProxy *proxy, const char *path, NMBluez4Manager *self) +adapter_removed (GDBusProxy *proxy, const char *path, NMBluez4Manager *self) { NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); @@ -140,7 +136,7 @@ adapter_removed (DBusGProxy *proxy, const char *path, NMBluez4Manager *self) } static void -default_adapter_changed (DBusGProxy *proxy, const char *path, NMBluez4Manager *self) +default_adapter_changed (GDBusProxy *proxy, const char *path, NMBluez4Manager *self) { NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); const char *cur_path = NULL; @@ -166,130 +162,65 @@ default_adapter_changed (DBusGProxy *proxy, const char *path, NMBluez4Manager *s } static void -default_adapter_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) +default_adapter_cb (GObject *proxy, GAsyncResult *result, gpointer user_data) { NMBluez4Manager *self = NM_BLUEZ4_MANAGER (user_data); NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); - const char *default_adapter = NULL; + GVariant *ret; GError *err = NULL; - if (!dbus_g_proxy_end_call (proxy, call, &err, - DBUS_TYPE_G_OBJECT_PATH, &default_adapter, - G_TYPE_INVALID)) { + ret = _nm_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), result, + G_VARIANT_TYPE ("(o)"), &err); + if (ret) { + const char *default_adapter; + + g_variant_get (ret, "(&o)", &default_adapter); + default_adapter_changed (priv->proxy, default_adapter, self); + g_variant_unref (ret); + } else { /* Ignore "No such adapter" errors; just means bluetooth isn't active */ - if ( !dbus_g_error_has_name (err, "org.bluez.Error.NoSuchAdapter") - && !dbus_g_error_has_name (err, "org.freedesktop.systemd1.LoadFailed") - && !g_error_matches (err, DBUS_GERROR, DBUS_GERROR_SERVICE_UNKNOWN)) { + if ( !_nm_dbus_error_has_name (err, "org.bluez.Error.NoSuchAdapter") + && !_nm_dbus_error_has_name (err, "org.freedesktop.systemd1.LoadFailed") + && !g_error_matches (err, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN)) { + g_dbus_error_strip_remote_error (err); nm_log_warn (LOGD_BT, "bluez error getting default adapter: %s", - err && err->message ? err->message : "(unknown)"); + err->message); } g_error_free (err); - return; } - - default_adapter_changed (priv->proxy, default_adapter, self); } static void query_default_adapter (NMBluez4Manager *self) { NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); - DBusGProxyCall *call; - call = dbus_g_proxy_begin_call (priv->proxy, "DefaultAdapter", - default_adapter_cb, - self, - NULL, G_TYPE_INVALID); - if (!call) - nm_log_warn (LOGD_BT, "failed to request default Bluetooth adapter."); + g_dbus_proxy_call (priv->proxy, "DefaultAdapter", + NULL, + G_DBUS_CALL_FLAGS_NONE, -1, + NULL, + default_adapter_cb, self); } static void -bluez_connect (NMBluez4Manager *self) -{ - NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); - DBusGConnection *connection; - - g_return_if_fail (priv->proxy == NULL); - - connection = nm_dbus_manager_get_connection (priv->dbus_mgr); - if (!connection) - return; - - priv->proxy = dbus_g_proxy_new_for_name (connection, - BLUEZ_SERVICE, - BLUEZ_MANAGER_PATH, - BLUEZ4_MANAGER_INTERFACE); - - dbus_g_proxy_add_signal (priv->proxy, "AdapterRemoved", - DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID); - dbus_g_proxy_connect_signal (priv->proxy, "AdapterRemoved", - G_CALLBACK (adapter_removed), self, NULL); - - dbus_g_proxy_add_signal (priv->proxy, "DefaultAdapterChanged", - DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID); - dbus_g_proxy_connect_signal (priv->proxy, "DefaultAdapterChanged", - G_CALLBACK (default_adapter_changed), self, NULL); - - query_default_adapter (self); -} - -static void -name_owner_changed_cb (NMDBusManager *dbus_mgr, - const char *name, - const char *old_owner, - const char *new_owner, +name_owner_changed_cb (GObject *object, + GParamSpec *pspec, gpointer user_data) { NMBluez4Manager *self = NM_BLUEZ4_MANAGER (user_data); NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); - gboolean old_owner_good = (old_owner && strlen (old_owner)); - gboolean new_owner_good = (new_owner && strlen (new_owner)); + char *owner; - /* Can't handle the signal if its not from the Bluez */ - if (strcmp (BLUEZ_SERVICE, name)) - return; - - if (!old_owner_good && new_owner_good) + owner = g_dbus_proxy_get_name_owner (priv->proxy); + if (owner) { query_default_adapter (self); - else if (old_owner_good && !new_owner_good) { + g_free (owner); + } else { /* Throwing away the adapter removes all devices too */ - if (priv->adapter) { - g_object_unref (priv->adapter); - priv->adapter = NULL; - } + g_clear_object (&priv->adapter); } } -static void -bluez_cleanup (NMBluez4Manager *self, gboolean do_signal) -{ - NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); - - if (priv->proxy) { - g_object_unref (priv->proxy); - priv->proxy = NULL; - } - - if (priv->adapter) { - g_object_unref (priv->adapter); - priv->adapter = NULL; - } -} - -static void -dbus_connection_changed_cb (NMDBusManager *dbus_mgr, - DBusGConnection *connection, - gpointer user_data) -{ - NMBluez4Manager *self = NM_BLUEZ4_MANAGER (user_data); - - if (!connection) - bluez_cleanup (self, TRUE); - else - bluez_connect (self); -} - /****************************************************************/ NMBluez4Manager * @@ -307,20 +238,21 @@ nm_bluez4_manager_init (NMBluez4Manager *self) { NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); - priv->dbus_mgr = nm_dbus_manager_get (); - g_assert (priv->dbus_mgr); + priv->proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, + NULL, + BLUEZ_SERVICE, + BLUEZ_MANAGER_PATH, + BLUEZ4_MANAGER_INTERFACE, + NULL, NULL); + _nm_dbus_signal_connect (priv->proxy, "AdapterRemoved", G_VARIANT_TYPE ("(o)"), + G_CALLBACK (adapter_removed), self); + _nm_dbus_signal_connect (priv->proxy, "DefaultAdapterChanged", G_VARIANT_TYPE ("(o)"), + G_CALLBACK (default_adapter_changed), self); + g_signal_connect (priv->proxy, "notify::g-name-owner", + G_CALLBACK (name_owner_changed_cb), self); - g_signal_connect (priv->dbus_mgr, - NM_DBUS_MANAGER_NAME_OWNER_CHANGED, - G_CALLBACK (name_owner_changed_cb), - self); - - g_signal_connect (priv->dbus_mgr, - NM_DBUS_MANAGER_DBUS_CONNECTION_CHANGED, - G_CALLBACK (dbus_connection_changed_cb), - self); - - bluez_connect (self); + query_default_adapter (self); } static void @@ -329,13 +261,8 @@ dispose (GObject *object) NMBluez4Manager *self = NM_BLUEZ4_MANAGER (object); NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); - bluez_cleanup (self, FALSE); - - if (priv->dbus_mgr) { - g_signal_handlers_disconnect_by_func (priv->dbus_mgr, name_owner_changed_cb, self); - g_signal_handlers_disconnect_by_func (priv->dbus_mgr, dbus_connection_changed_cb, self); - priv->dbus_mgr = NULL; - } + g_clear_object (&priv->proxy); + g_clear_object (&priv->adapter); G_OBJECT_CLASS (nm_bluez4_manager_parent_class)->dispose (object); } diff --git a/src/devices/bluetooth/nm-bluez5-manager.c b/src/devices/bluetooth/nm-bluez5-manager.c index b85685239..148fe3cbe 100644 --- a/src/devices/bluetooth/nm-bluez5-manager.c +++ b/src/devices/bluetooth/nm-bluez5-manager.c @@ -34,6 +34,7 @@ #include "nm-bluez-common.h" #include "nm-dbus-manager.h" +#include "nm-core-internal.h" typedef struct { NMDBusManager *dbus_mgr; @@ -170,39 +171,23 @@ device_removed (GDBusProxy *proxy, const gchar *path, NMBluez5Manager *self) } static void -object_manager_g_signal (GDBusProxy *proxy, - gchar *sender_name, - gchar *signal_name, - GVariant *parameters, - NMBluez5Manager *self) +object_manager_interfaces_added (GDBusProxy *proxy, + const char *path, + GVariant *dict, + NMBluez5Manager *self) { - GVariant *variant; - const gchar *path; + if (g_variant_lookup (dict, BLUEZ5_DEVICE_INTERFACE, "a{sv}", NULL)) + device_added (proxy, path, self); +} - if (!strcmp (signal_name, "InterfacesRemoved")) { - const gchar **ifaces; - gsize i, length; - - g_variant_get (parameters, "(&o*)", &path, &variant); - - ifaces = g_variant_get_strv (variant, &length); - - for (i = 0; i < length; i++) { - if (!strcmp (ifaces[i], BLUEZ5_DEVICE_INTERFACE)) { - device_removed (proxy, path, self); - break; - } - } - - g_free (ifaces); - - } else if (!strcmp (signal_name, "InterfacesAdded")) { - g_variant_get (parameters, "(&o*)", &path, &variant); - - if (g_variant_lookup_value (variant, BLUEZ5_DEVICE_INTERFACE, - G_VARIANT_TYPE_DICTIONARY)) - device_added (proxy, path, self); - } +static void +object_manager_interfaces_removed (GDBusProxy *proxy, + const char *path, + const char **ifaces, + NMBluez5Manager *self) +{ + if (_nm_utils_string_in_list (BLUEZ5_DEVICE_INTERFACE, ifaces)) + device_removed (proxy, path, self); } static void @@ -215,8 +200,9 @@ get_managed_objects_cb (GDBusProxy *proxy, GError *error = NULL; const char *path; - variant = g_dbus_proxy_call_finish (proxy, res, &error); - + variant = _nm_dbus_proxy_call_finish (proxy, res, + G_VARIANT_TYPE ("(a{oa{sa{sv}}})"), + &error); if (!variant) { if (g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD)) nm_log_warn (LOGD_BT, "Couldn't get managed objects: not running Bluez5?"); @@ -264,8 +250,10 @@ on_proxy_acquired (GObject *object, (GAsyncReadyCallback) get_managed_objects_cb, self); - g_signal_connect (priv->proxy, "g-signal", - G_CALLBACK (object_manager_g_signal), self); + _nm_dbus_signal_connect (priv->proxy, "InterfacesAdded", G_VARIANT_TYPE ("(oa{sa{sv}})"), + G_CALLBACK (object_manager_interfaces_added), self); + _nm_dbus_signal_connect (priv->proxy, "InterfacesRemoved", G_VARIANT_TYPE ("(oas)"), + G_CALLBACK (object_manager_interfaces_removed), self); } static void diff --git a/src/nm-auth-manager.c b/src/nm-auth-manager.c index c1b352c92..3dd151168 100644 --- a/src/nm-auth-manager.c +++ b/src/nm-auth-manager.c @@ -24,6 +24,7 @@ #include "nm-logging.h" #include "nm-errors.h" +#include "nm-core-internal.h" #define POLKIT_SERVICE "org.freedesktop.PolicyKit1" #define POLKIT_OBJECT_PATH "/org/freedesktop/PolicyKit1/Authority" @@ -176,7 +177,7 @@ check_authorization_cb (GDBusProxy *proxy, GVariant *value; GError *error = NULL; - value = g_dbus_proxy_call_finish (proxy, res, &error); + value = _nm_dbus_proxy_call_finish (proxy, res, G_VARIANT_TYPE ("((bba{ss}))"), &error); if (value == NULL) { if (data->cancellation_id != NULL && (!g_dbus_error_is_remote_error (error) && @@ -200,18 +201,15 @@ check_authorization_cb (GDBusProxy *proxy, error->message); g_error_free (error); } else { - GVariant *result_value; CheckAuthorizationResult *result; result = g_new0 (CheckAuthorizationResult, 1); - result_value = g_variant_get_child_value (value, 0); - g_variant_get (result_value, - "(bb@a{ss})", + g_variant_get (value, + "((bb@a{ss}))", &result->is_authorized, &result->is_challenge, NULL); - g_variant_unref (result_value); g_variant_unref (value); _LOGD ("call[%u]: CheckAuthorization succeeded: (is_authorized=%d, is_challenge=%d)", data->call_id, result->is_authorized, result->is_challenge); @@ -394,21 +392,16 @@ _dbus_on_name_owner_notify_cb (GObject *object, } static void -_dbus_on_g_signal_cb (GDBusProxy *proxy, - const gchar *sender_name, - const gchar *signal_name, - GVariant *parameters, - gpointer user_data) +_dbus_on_changed_signal_cb (GDBusProxy *proxy, + gpointer user_data) { NMAuthManager *self = user_data; NMAuthManagerPrivate *priv = NM_AUTH_MANAGER_GET_PRIVATE (self); g_return_if_fail (priv->proxy == proxy); - _LOGD ("dbus signal: \"%s\"", signal_name ? signal_name : "(null)"); - - if (g_strcmp0 (signal_name, "Changed") == 0) - _emit_changed_signal (self); + _LOGD ("dbus signal: \"Changed\""); + _emit_changed_signal (self); } static void @@ -463,10 +456,9 @@ _dbus_new_proxy_cb (GObject *source_object, "notify::g-name-owner", G_CALLBACK (_dbus_on_name_owner_notify_cb), self); - g_signal_connect (priv->proxy, - "g-signal", - G_CALLBACK (_dbus_on_g_signal_cb), - self); + _nm_dbus_signal_connect (priv->proxy, "Changed", NULL, + G_CALLBACK (_dbus_on_changed_signal_cb), + self); _log_name_owner (self, NULL); @@ -604,8 +596,7 @@ dispose (GObject *object) } if (priv->proxy) { - g_signal_handlers_disconnect_by_func (priv->proxy, _dbus_on_name_owner_notify_cb, self); - g_signal_handlers_disconnect_by_func (priv->proxy, _dbus_on_g_signal_cb, self); + g_signal_handlers_disconnect_by_data (priv->proxy, self); g_clear_object (&priv->proxy); } #endif diff --git a/src/nm-dispatcher.c b/src/nm-dispatcher.c index 8fdb43dfb..4ba518754 100644 --- a/src/nm-dispatcher.c +++ b/src/nm-dispatcher.c @@ -35,12 +35,17 @@ #include "nm-device.h" #include "nm-dhcp4-config.h" #include "nm-dhcp6-config.h" +#include "nm-ip4-config.h" +#include "nm-ip6-config.h" #include "nm-dbus-glib-types.h" #include "nm-glib-compat.h" #include "nm-settings-connection.h" +#include "nm-platform.h" +#include "nm-core-internal.h" #define CALL_TIMEOUT (1000 * 60 * 10) /* 10 minutes for all scripts */ +static GDBusProxy *dispatcher_proxy; static GHashTable *requests = NULL; typedef struct { @@ -80,24 +85,145 @@ _get_monitor_by_action (DispatcherAction action) } static void -dump_object_to_props (GObject *object, GHashTable *hash) +dump_ip4_to_props (NMIP4Config *ip4, GVariantBuilder *builder) { - GParamSpec **pspecs; - guint len = 0, i; + GVariantBuilder int_builder; + guint n, i; + const NMPlatformIP4Address *addr; + const NMPlatformIP4Route *route; + guint32 array[4]; - pspecs = g_object_class_list_properties (G_OBJECT_GET_CLASS (object), &len); - for (i = 0; i < len; i++) { - value_hash_add_object_property (hash, - pspecs[i]->name, - object, - pspecs[i]->name, - pspecs[i]->value_type); + /* Addresses */ + g_variant_builder_init (&int_builder, G_VARIANT_TYPE ("aau")); + n = nm_ip4_config_get_num_addresses (ip4); + for (i = 0; i < n; i++) { + addr = nm_ip4_config_get_address (ip4, i); + array[0] = addr->address; + array[1] = addr->plen; + array[2] = (i == 0) ? nm_ip4_config_get_gateway (ip4) : 0; + g_variant_builder_add (&int_builder, "@au", + g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32, + array, 3, sizeof (guint32))); } - g_free (pspecs); + g_variant_builder_add (builder, "{sv}", + "addresses", + g_variant_builder_end (&int_builder)); + + /* DNS servers */ + g_variant_builder_init (&int_builder, G_VARIANT_TYPE ("au")); + n = nm_ip4_config_get_num_nameservers (ip4); + for (i = 0; i < n; i++) + g_variant_builder_add (&int_builder, "u", nm_ip4_config_get_nameserver (ip4, i)); + g_variant_builder_add (builder, "{sv}", + "nameservers", + g_variant_builder_end (&int_builder)); + + /* Search domains */ + g_variant_builder_init (&int_builder, G_VARIANT_TYPE ("as")); + n = nm_ip4_config_get_num_domains (ip4); + for (i = 0; i < n; i++) + g_variant_builder_add (&int_builder, "s", nm_ip4_config_get_domain (ip4, i)); + g_variant_builder_add (builder, "{sv}", + "domains", + g_variant_builder_end (&int_builder)); + + /* WINS servers */ + g_variant_builder_init (&int_builder, G_VARIANT_TYPE ("au")); + n = nm_ip4_config_get_num_wins (ip4); + for (i = 0; i < n; i++) + g_variant_builder_add (&int_builder, "u", nm_ip4_config_get_wins (ip4, i)); + g_variant_builder_add (builder, "{sv}", + "wins-servers", + g_variant_builder_end (&int_builder)); + + /* Static routes */ + g_variant_builder_init (&int_builder, G_VARIANT_TYPE ("aau")); + n = nm_ip4_config_get_num_routes (ip4); + for (i = 0; i < n; i++) { + route = nm_ip4_config_get_route (ip4, i); + array[0] = route->network; + array[1] = route->plen; + array[2] = route->gateway; + array[3] = route->metric; + g_variant_builder_add (&int_builder, "@au", + g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32, + array, 4, sizeof (guint32))); + } + g_variant_builder_add (builder, "{sv}", + "routes", + g_variant_builder_end (&int_builder)); } static void -dump_dhcp4_to_props (NMDhcp4Config *config, GHashTable *hash) +dump_ip6_to_props (NMIP6Config *ip6, GVariantBuilder *builder) +{ + GVariantBuilder int_builder; + guint n, i; + const NMPlatformIP6Address *addr; + const struct in6_addr *gw_bytes; + const NMPlatformIP6Route *route; + GVariant *ip, *gw; + + /* Addresses */ + g_variant_builder_init (&int_builder, G_VARIANT_TYPE ("a(ayuay)")); + n = nm_ip6_config_get_num_addresses (ip6); + for (i = 0; i < n; i++) { + addr = nm_ip6_config_get_address (ip6, i); + gw_bytes = nm_ip6_config_get_gateway (ip6); + ip = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, + &addr->address, + sizeof (struct in6_addr), 1); + gw = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, + (i == 0 && gw_bytes) ? gw_bytes : &in6addr_any, + sizeof (struct in6_addr), 1); + g_variant_builder_add (&int_builder, "(@ayu@ay)", ip, addr->plen, gw); + } + g_variant_builder_add (builder, "{sv}", + "addresses", + g_variant_builder_end (&int_builder)); + + /* DNS servers */ + g_variant_builder_init (&int_builder, G_VARIANT_TYPE ("aay")); + n = nm_ip6_config_get_num_nameservers (ip6); + for (i = 0; i < n; i++) { + ip = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, + nm_ip6_config_get_nameserver (ip6, i), + sizeof (struct in6_addr), 1); + g_variant_builder_add (&int_builder, "@ay", ip); + } + g_variant_builder_add (builder, "{sv}", + "nameservers", + g_variant_builder_end (&int_builder)); + + /* Search domains */ + g_variant_builder_init (&int_builder, G_VARIANT_TYPE ("as")); + n = nm_ip6_config_get_num_domains (ip6); + for (i = 0; i < n; i++) + g_variant_builder_add (&int_builder, "s", nm_ip6_config_get_domain (ip6, i)); + g_variant_builder_add (builder, "{sv}", + "domains", + g_variant_builder_end (&int_builder)); + + /* Static routes */ + g_variant_builder_init (&int_builder, G_VARIANT_TYPE ("a(ayuayu)")); + n = nm_ip6_config_get_num_routes (ip6); + for (i = 0; i < n; i++) { + route = nm_ip6_config_get_route (ip6, i); + ip = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, + &route->network, + sizeof (struct in6_addr), 1); + gw = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, + &route->gateway, + sizeof (struct in6_addr), 1); + g_variant_builder_add (&int_builder, "(@ayu@ayu)", ip, route->plen, gw, route->metric); + } + g_variant_builder_add (builder, "{sv}", + "routes", + g_variant_builder_end (&int_builder)); +} + +static void +dump_dhcp4_to_props (NMDhcp4Config *config, GVariantBuilder *builder) { GSList *options, *iter; @@ -107,13 +233,13 @@ dump_dhcp4_to_props (NMDhcp4Config *config, GHashTable *hash) const char *val; val = nm_dhcp4_config_get_option (config, option); - value_hash_add_str (hash, option, val); + g_variant_builder_add (builder, "{sv}", option, g_variant_new_string (val)); } g_slist_free (options); } static void -dump_dhcp6_to_props (NMDhcp6Config *config, GHashTable *hash) +dump_dhcp6_to_props (NMDhcp6Config *config, GVariantBuilder *builder) { GSList *options, *iter; @@ -123,18 +249,18 @@ dump_dhcp6_to_props (NMDhcp6Config *config, GHashTable *hash) const char *val; val = nm_dhcp6_config_get_option (config, option); - value_hash_add_str (hash, option, val); + g_variant_builder_add (builder, "{sv}", option, g_variant_new_string (val)); } g_slist_free (options); } static void fill_device_props (NMDevice *device, - GHashTable *dev_hash, - GHashTable *ip4_hash, - GHashTable *ip6_hash, - GHashTable *dhcp4_hash, - GHashTable *dhcp6_hash) + GVariantBuilder *dev_builder, + GVariantBuilder *ip4_builder, + GVariantBuilder *ip6_builder, + GVariantBuilder *dhcp4_builder, + GVariantBuilder *dhcp6_builder) { NMIP4Config *ip4_config; NMIP6Config *ip6_config; @@ -142,39 +268,44 @@ fill_device_props (NMDevice *device, NMDhcp6Config *dhcp6_config; /* If the action is for a VPN, send the VPN's IP interface instead of the device's */ - value_hash_add_str (dev_hash, NMD_DEVICE_PROPS_IP_INTERFACE, nm_device_get_ip_iface (device)); - value_hash_add_str (dev_hash, NMD_DEVICE_PROPS_INTERFACE, nm_device_get_iface (device)); - value_hash_add_uint (dev_hash, NMD_DEVICE_PROPS_TYPE, nm_device_get_device_type (device)); - value_hash_add_uint (dev_hash, NMD_DEVICE_PROPS_STATE, nm_device_get_state (device)); - value_hash_add_object_path (dev_hash, NMD_DEVICE_PROPS_PATH, nm_device_get_path (device)); + g_variant_builder_add (dev_builder, "{sv}", NMD_DEVICE_PROPS_IP_INTERFACE, + g_variant_new_string (nm_device_get_ip_iface (device))); + g_variant_builder_add (dev_builder, "{sv}", NMD_DEVICE_PROPS_INTERFACE, + g_variant_new_string (nm_device_get_iface (device))); + g_variant_builder_add (dev_builder, "{sv}", NMD_DEVICE_PROPS_TYPE, + g_variant_new_uint32 (nm_device_get_device_type (device))); + g_variant_builder_add (dev_builder, "{sv}", NMD_DEVICE_PROPS_STATE, + g_variant_new_uint32 (nm_device_get_state (device))); + g_variant_builder_add (dev_builder, "{sv}", NMD_DEVICE_PROPS_PATH, + g_variant_new_object_path (nm_device_get_path (device))); ip4_config = nm_device_get_ip4_config (device); if (ip4_config) - dump_object_to_props (G_OBJECT (ip4_config), ip4_hash); + dump_ip4_to_props (ip4_config, ip4_builder); ip6_config = nm_device_get_ip6_config (device); if (ip6_config) - dump_object_to_props (G_OBJECT (ip6_config), ip6_hash); + dump_ip6_to_props (ip6_config, ip6_builder); dhcp4_config = nm_device_get_dhcp4_config (device); if (dhcp4_config) - dump_dhcp4_to_props (dhcp4_config, dhcp4_hash); + dump_dhcp4_to_props (dhcp4_config, dhcp4_builder); dhcp6_config = nm_device_get_dhcp6_config (device); if (dhcp6_config) - dump_dhcp6_to_props (dhcp6_config, dhcp6_hash); + dump_dhcp6_to_props (dhcp6_config, dhcp6_builder); } static void fill_vpn_props (NMIP4Config *ip4_config, NMIP6Config *ip6_config, - GHashTable *ip4_hash, - GHashTable *ip6_hash) + GVariantBuilder *ip4_builder, + GVariantBuilder *ip6_builder) { if (ip4_config) - dump_object_to_props (G_OBJECT (ip4_config), ip4_hash); + dump_ip4_to_props (ip4_config, ip4_builder); if (ip6_config) - dump_object_to_props (G_OBJECT (ip6_config), ip6_hash); + dump_ip6_to_props (ip6_config, ip6_builder); } typedef struct { @@ -228,51 +359,25 @@ dispatch_result_to_string (DispatchResult result) g_assert_not_reached (); } -static gboolean -validate_element (guint request_id, GValue *val, GType expected_type, guint idx, guint eltnum) -{ - if (G_VALUE_TYPE (val) != expected_type) { - nm_log_dbg (LOGD_DISPATCH, "(%u) result %d element %d invalid type %s", - request_id, idx, eltnum, G_VALUE_TYPE_NAME (val)); - return FALSE; - } - return TRUE; -} - static void -dispatcher_results_process (guint request_id, DispatcherAction action, GPtrArray *results) +dispatcher_results_process (guint request_id, DispatcherAction action, GVariantIter *results) { - guint i; + const char *script, *err; + guint32 result; const Monitor *monitor = _get_monitor_by_action (action); g_return_if_fail (results != NULL); - if (results->len == 0) { + if (g_variant_iter_n_children (results) == 0) { nm_log_dbg (LOGD_DISPATCH, "(%u) succeeded but no scripts invoked", request_id); return; } - for (i = 0; i < results->len; i++) { - GValueArray *item = g_ptr_array_index (results, i); - GValue *tmp; - const char *script, *err; - DispatchResult result; + while (g_variant_iter_next (results, "(&su&s)", &script, &result, &err)) { const char *script_validation_msg = ""; - if (item->n_values != 3) { - nm_log_dbg (LOGD_DISPATCH, "(%u) unexpected number of items in " - "dispatcher result (got %d, expected 3)", - request_id, item->n_values); - continue; - } - - /* Script */ - tmp = g_value_array_get_nth (item, 0); - if (!validate_element (request_id, tmp, G_TYPE_STRING, i, 0)) - continue; - script = g_value_get_string (tmp); - if (!script) { + if (!*script) { script_validation_msg = " (path is NULL)"; script = "(unknown)"; } else if (!strncmp (script, monitor->dir, monitor->dir_len) /* check: prefixed by script directory */ @@ -284,20 +389,6 @@ dispatcher_results_process (guint request_id, DispatcherAction action, GPtrArray } else script_validation_msg = " (unexpected path)"; - - /* Result */ - tmp = g_value_array_get_nth (item, 1); - if (!validate_element (request_id, tmp, G_TYPE_UINT, i, 1)) - continue; - result = g_value_get_uint (tmp); - - /* Error */ - tmp = g_value_array_get_nth (item, 2); - if (!validate_element (request_id, tmp, G_TYPE_STRING, i, 2)) - continue; - err = g_value_get_string (tmp); - - if (result == DISPATCH_RESULT_SUCCESS) { nm_log_dbg (LOGD_DISPATCH, "(%u) %s succeeded%s", request_id, @@ -307,52 +398,43 @@ dispatcher_results_process (guint request_id, DispatcherAction action, GPtrArray request_id, script, dispatch_result_to_string (result), - err ? err : "", script_validation_msg); + err, script_validation_msg); } } } static void -free_results (GPtrArray *results) -{ - g_return_if_fail (results != NULL); - g_ptr_array_foreach (results, (GFunc) g_value_array_free, NULL); - g_ptr_array_free (results, TRUE); -} - -static void -dispatcher_done_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) +dispatcher_done_cb (GObject *proxy, GAsyncResult *result, gpointer user_data) { DispatchInfo *info = user_data; + GVariant *ret; + GVariantIter *results; GError *error = NULL; - GPtrArray *results = NULL; - if (dbus_g_proxy_end_call (proxy, call, &error, - DISPATCHER_TYPE_RESULT_ARRAY, &results, - G_TYPE_INVALID)) { + ret = _nm_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), result, + G_VARIANT_TYPE ("(a(sus))"), + &error); + if (ret) { + g_variant_get (ret, "(a(sus))", &results); dispatcher_results_process (info->request_id, info->action, results); - free_results (results); + g_variant_iter_free (results); + g_variant_unref (ret); } else { - g_assert (error); - - if (!g_error_matches (error, DBUS_GERROR, DBUS_GERROR_REMOTE_EXCEPTION)) { - nm_log_warn (LOGD_DISPATCH, "(%u) failed to call dispatcher scripts: (%s:%d) %s", - info->request_id, g_quark_to_string (error->domain), - error->code, error->message); - } else if (!dbus_g_error_has_name (error, "org.freedesktop.systemd1.LoadFailed")) { - nm_log_warn (LOGD_DISPATCH, "(%u) failed to call dispatcher scripts: (%s) %s", - info->request_id, dbus_g_error_get_name (error), error->message); + if (_nm_dbus_error_has_name (error, "org.freedesktop.systemd1.LoadFailed")) { + g_dbus_error_strip_remote_error (error); + nm_log_warn (LOGD_DISPATCH, "(%u) failed to call dispatcher scripts: %s", + info->request_id, error->message); } else { - nm_log_dbg (LOGD_DISPATCH, "(%u) failed to call dispatcher scripts: (%s) %s", - info->request_id, dbus_g_error_get_name (error), error->message); + nm_log_dbg (LOGD_DISPATCH, "(%u) failed to call dispatcher scripts: %s", + info->request_id, error->message); } + g_clear_error (&error); } if (info->callback) info->callback (info->request_id, info->user_data); - g_clear_error (&error); - g_object_unref (proxy); + dispatcher_info_cleanup (info); } static const char *action_table[] = { @@ -400,23 +482,24 @@ _dispatcher_call (DispatcherAction action, gpointer user_data, guint *out_call_id) { - DBusGProxy *proxy; - DBusGConnection *g_connection; - GHashTable *connection_hash; - GHashTable *connection_props; - GHashTable *device_props; - GHashTable *device_ip4_props; - GHashTable *device_ip6_props; - GHashTable *device_dhcp4_props; - GHashTable *device_dhcp6_props; - GHashTable *vpn_ip4_props; - GHashTable *vpn_ip6_props; + GVariant *connection_dict; + GVariantBuilder connection_props; + GVariantBuilder device_props; + GVariantBuilder device_ip4_props; + GVariantBuilder device_ip6_props; + GVariantBuilder device_dhcp4_props; + GVariantBuilder device_dhcp6_props; + GVariantBuilder vpn_ip4_props; + GVariantBuilder vpn_ip6_props; DispatchInfo *info = NULL; gboolean success = FALSE; GError *error = NULL; static guint request_counter = 0; guint reqid = ++request_counter; + if (!dispatcher_proxy) + return FALSE; + /* Wrapping protection */ if (G_UNLIKELY (!reqid)) reqid = ++request_counter; @@ -463,92 +546,87 @@ _dispatcher_call (DispatcherAction action, goto done; } - g_connection = nm_dbus_manager_get_connection (nm_dbus_manager_get ()); - proxy = dbus_g_proxy_new_for_name (g_connection, - NM_DISPATCHER_DBUS_SERVICE, - NM_DISPATCHER_DBUS_PATH, - NM_DISPATCHER_DBUS_INTERFACE); - if (!proxy) { - nm_log_err (LOGD_DISPATCH, "(%u) could not get dispatcher proxy!", reqid); - return FALSE; - } - if (connection) { - GVariant *connection_dict; const char *filename; connection_dict = nm_connection_to_dbus (connection, NM_CONNECTION_SERIALIZE_NO_SECRETS); - connection_hash = nm_utils_connection_dict_to_hash (connection_dict); - g_variant_unref (connection_dict); - connection_props = value_hash_create (); - value_hash_add_object_path (connection_props, - NMD_CONNECTION_PROPS_PATH, - nm_connection_get_path (connection)); + g_variant_builder_init (&connection_props, G_VARIANT_TYPE_VARDICT); + g_variant_builder_add (&connection_props, "{sv}", + NMD_CONNECTION_PROPS_PATH, + g_variant_new_object_path (nm_connection_get_path (connection))); filename = nm_settings_connection_get_filename (NM_SETTINGS_CONNECTION (connection)); if (filename) { - value_hash_add_str (connection_props, - NMD_CONNECTION_PROPS_FILENAME, - filename); + g_variant_builder_add (&connection_props, "{sv}", + NMD_CONNECTION_PROPS_FILENAME, + g_variant_new_string (filename)); } if (nm_settings_connection_get_nm_generated_assumed (NM_SETTINGS_CONNECTION (connection))) { - value_hash_add_bool (connection_props, - NMD_CONNECTION_PROPS_EXTERNAL, - TRUE); + g_variant_builder_add (&connection_props, "{sv}", + NMD_CONNECTION_PROPS_EXTERNAL, + g_variant_new_boolean (TRUE)); } } else { - connection_hash = value_hash_create (); - connection_props = value_hash_create (); + connection_dict = g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0); + g_variant_builder_init (&connection_props, G_VARIANT_TYPE_VARDICT); } - device_props = value_hash_create (); - device_ip4_props = value_hash_create (); - device_ip6_props = value_hash_create (); - device_dhcp4_props = value_hash_create (); - device_dhcp6_props = value_hash_create (); - vpn_ip4_props = value_hash_create (); - vpn_ip6_props = value_hash_create (); + g_variant_builder_init (&device_props, G_VARIANT_TYPE_VARDICT); + g_variant_builder_init (&device_ip4_props, G_VARIANT_TYPE_VARDICT); + g_variant_builder_init (&device_ip6_props, G_VARIANT_TYPE_VARDICT); + g_variant_builder_init (&device_dhcp4_props, G_VARIANT_TYPE_VARDICT); + g_variant_builder_init (&device_dhcp6_props, G_VARIANT_TYPE_VARDICT); + g_variant_builder_init (&vpn_ip4_props, G_VARIANT_TYPE_VARDICT); + g_variant_builder_init (&vpn_ip6_props, G_VARIANT_TYPE_VARDICT); /* hostname actions only send the hostname */ if (action != DISPATCHER_ACTION_HOSTNAME) { fill_device_props (device, - device_props, - device_ip4_props, - device_ip6_props, - device_dhcp4_props, - device_dhcp6_props); - if (vpn_ip4_config || vpn_ip6_config) - fill_vpn_props (vpn_ip4_config, vpn_ip6_config, vpn_ip4_props, vpn_ip6_props); + &device_props, + &device_ip4_props, + &device_ip6_props, + &device_dhcp4_props, + &device_dhcp6_props); + if (vpn_ip4_config || vpn_ip6_config) { + fill_vpn_props (vpn_ip4_config, + vpn_ip6_config, + &vpn_ip4_props, + &vpn_ip6_props); + } } /* Send the action to the dispatcher */ if (blocking) { - GPtrArray *results = NULL; + GVariant *ret; + GVariantIter *results; - success = dbus_g_proxy_call_with_timeout (proxy, "Action", - CALL_TIMEOUT, - &error, - G_TYPE_STRING, action_to_string (action), - DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, connection_hash, - DBUS_TYPE_G_MAP_OF_VARIANT, connection_props, - DBUS_TYPE_G_MAP_OF_VARIANT, device_props, - DBUS_TYPE_G_MAP_OF_VARIANT, device_ip4_props, - DBUS_TYPE_G_MAP_OF_VARIANT, device_ip6_props, - DBUS_TYPE_G_MAP_OF_VARIANT, device_dhcp4_props, - DBUS_TYPE_G_MAP_OF_VARIANT, device_dhcp6_props, - G_TYPE_STRING, vpn_iface ? vpn_iface : "", - DBUS_TYPE_G_MAP_OF_VARIANT, vpn_ip4_props, - DBUS_TYPE_G_MAP_OF_VARIANT, vpn_ip6_props, - G_TYPE_BOOLEAN, nm_logging_enabled (LOGL_DEBUG, LOGD_DISPATCH), - G_TYPE_INVALID, - DISPATCHER_TYPE_RESULT_ARRAY, &results, - G_TYPE_INVALID); - if (success) { + ret = _nm_dbus_proxy_call_sync (dispatcher_proxy, "Action", + g_variant_new ("(s@a{sa{sv}}a{sv}a{sv}a{sv}a{sv}a{sv}a{sv}sa{sv}a{sv}b)", + action_to_string (action), + connection_dict, + &connection_props, + &device_props, + &device_ip4_props, + &device_ip6_props, + &device_dhcp4_props, + &device_dhcp6_props, + vpn_iface ? vpn_iface : "", + &vpn_ip4_props, + &vpn_ip6_props, + nm_logging_enabled (LOGL_DEBUG, LOGD_DISPATCH)), + G_VARIANT_TYPE ("(a(sus))"), + G_DBUS_CALL_FLAGS_NONE, CALL_TIMEOUT, + NULL, &error); + if (ret) { + g_variant_get (ret, "(a(sus))", &results); dispatcher_results_process (reqid, action, results); - free_results (results); + g_variant_iter_free (results); + g_variant_unref (ret); + success = TRUE; } else { - nm_log_warn (LOGD_DISPATCH, "(%u) failed: (%d) %s", reqid, error->code, error->message); - g_error_free (error); + nm_log_warn (LOGD_DISPATCH, "(%u) failed: %s", reqid, error->message); + g_clear_error (&error); + success = FALSE; } } else { info = g_malloc0 (sizeof (*info)); @@ -556,37 +634,25 @@ _dispatcher_call (DispatcherAction action, info->request_id = reqid; info->callback = callback; info->user_data = user_data; - dbus_g_proxy_begin_call_with_timeout (proxy, "Action", - dispatcher_done_cb, - info, - (GDestroyNotify) dispatcher_info_cleanup, - CALL_TIMEOUT, - G_TYPE_STRING, action_to_string (action), - DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, connection_hash, - DBUS_TYPE_G_MAP_OF_VARIANT, connection_props, - DBUS_TYPE_G_MAP_OF_VARIANT, device_props, - DBUS_TYPE_G_MAP_OF_VARIANT, device_ip4_props, - DBUS_TYPE_G_MAP_OF_VARIANT, device_ip6_props, - DBUS_TYPE_G_MAP_OF_VARIANT, device_dhcp4_props, - DBUS_TYPE_G_MAP_OF_VARIANT, device_dhcp6_props, - G_TYPE_STRING, vpn_iface ? vpn_iface : "", - DBUS_TYPE_G_MAP_OF_VARIANT, vpn_ip4_props, - DBUS_TYPE_G_MAP_OF_VARIANT, vpn_ip6_props, - G_TYPE_BOOLEAN, nm_logging_enabled (LOGL_DEBUG, LOGD_DISPATCH), - G_TYPE_INVALID); + g_dbus_proxy_call (dispatcher_proxy, "Action", + g_variant_new ("(s@a{sa{sv}}a{sv}a{sv}a{sv}a{sv}a{sv}a{sv}sa{sv}a{sv}b)", + action_to_string (action), + connection_dict, + &connection_props, + &device_props, + &device_ip4_props, + &device_ip6_props, + &device_dhcp4_props, + &device_dhcp6_props, + vpn_iface ? vpn_iface : "", + &vpn_ip4_props, + &vpn_ip6_props, + nm_logging_enabled (LOGL_DEBUG, LOGD_DISPATCH)), + G_DBUS_CALL_FLAGS_NONE, CALL_TIMEOUT, + NULL, dispatcher_done_cb, info); success = TRUE; } - g_hash_table_destroy (connection_hash); - g_hash_table_destroy (connection_props); - g_hash_table_destroy (device_props); - g_hash_table_destroy (device_ip4_props); - g_hash_table_destroy (device_ip6_props); - g_hash_table_destroy (device_dhcp4_props); - g_hash_table_destroy (device_dhcp6_props); - g_hash_table_destroy (vpn_ip4_props); - g_hash_table_destroy (vpn_ip6_props); - done: if (success && info) { /* Track the request in case of cancelation */ @@ -777,6 +843,7 @@ nm_dispatcher_init (void) { GFile *file; guint i; + GError *error = NULL; for (i = 0; i < G_N_ELEMENTS (monitors); i++) { file = g_file_new_for_path (monitors[i].dir); @@ -787,5 +854,18 @@ nm_dispatcher_init (void) } g_object_unref (file); } + + dispatcher_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | + G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, + NULL, + NM_DISPATCHER_DBUS_SERVICE, + NM_DISPATCHER_DBUS_PATH, + NM_DISPATCHER_DBUS_INTERFACE, + NULL, &error); + if (!dispatcher_proxy) { + nm_log_err (LOGD_DISPATCH, "could not get dispatcher proxy! %s", error->message); + g_clear_error (&error); + } } diff --git a/src/nm-firewall-manager.c b/src/nm-firewall-manager.c index 4d302e9d2..711b542ec 100644 --- a/src/nm-firewall-manager.c +++ b/src/nm-firewall-manager.c @@ -23,11 +23,10 @@ #include #include #include -#include #include "nm-firewall-manager.h" -#include "nm-dbus-manager.h" #include "nm-logging.h" +#include "gsystem-local-alloc.h" #define NM_FIREWALL_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \ NM_TYPE_FIREWALL_MANAGER, \ @@ -43,9 +42,7 @@ enum { }; typedef struct { - NMDBusManager * dbus_mgr; - guint name_owner_id; - DBusGProxy * proxy; + GDBusProxy * proxy; gboolean running; GSList *pending_calls; @@ -70,36 +67,50 @@ typedef struct { FwAddToZoneFunc callback; gpointer user_data; guint id; - gboolean completed; guint idle_id; - DBusGProxyCall *dbus_call; + GCancellable *cancellable; } CBInfo; static void -_cb_info_free (CBInfo *info) +_cb_info_complete_and_free (CBInfo *info, + const char *tag, + const char *debug_error_match, + GError *error) { - NMFirewallManagerPrivate *priv; + gs_free_error GError *local = NULL; g_return_if_fail (info != NULL); + g_return_if_fail (tag != NULL); - if (!info->completed) { - nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone call cancelled [%u]", info->iface, info->id); - if (info->callback) { - GError *error; - - error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_CANCELLED, - "Operation was cancelled"); - info->callback (error, info->user_data); - g_error_free (error); - } + /* A cancelled idle call won't set the error; catch that here */ + if (!error && g_cancellable_is_cancelled (info->cancellable)) { + error = local = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_CANCELLED, + "Operation was cancelled"); } + + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone %s call cancelled [%u]", + info->iface, tag, info->id); + } else if (error) { + g_dbus_error_strip_remote_error (error); + if (!g_strcmp0 (error->message, debug_error_match)) { + nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone %s failed [%u]: %s", + info->iface, tag, info->id, error->message); + } else { + nm_log_warn (LOGD_FIREWALL, "(%s) firewall zone %s failed [%u]: %s", + info->iface, tag, info->id, error->message); + } + } else { + nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone %s succeeded [%u]", + info->iface, tag, info->id); + } + + if (info->callback) + info->callback (error, info->user_data); + g_free (info->iface); - - priv = NM_FIREWALL_MANAGER_GET_PRIVATE (info->self); - priv->pending_calls = g_slist_remove (priv->pending_calls, info); - g_object_unref (info->self); - + g_object_unref (info->cancellable); g_slice_free (CBInfo, info); } @@ -107,16 +118,14 @@ static CBInfo * _cb_info_create (NMFirewallManager *self, const char *iface, FwAddToZoneFunc callback, gpointer user_data) { NMFirewallManagerPrivate *priv = NM_FIREWALL_MANAGER_GET_PRIVATE (self); - static guint id; + static guint id = 1; CBInfo *info; info = g_slice_new0 (CBInfo); - if (++id == 0) - ++id; info->self = g_object_ref (self); - info->id = id; + info->id = id++; info->iface = g_strdup (iface); - info->completed = FALSE; + info->cancellable = g_cancellable_new (); info->callback = callback; info->user_data = user_data; @@ -129,50 +138,20 @@ add_or_change_idle_cb (gpointer user_data) { CBInfo *info = user_data; - if (info->idle_id == 0) { - /* operation was cancelled. _cb_info_free will invoke callback. */ - } else { - nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone call pretends success [%u]", - info->iface, info->id); - if (info->callback) - info->callback (NULL, info->user_data); - info->completed = TRUE; - info->idle_id = 0; - } - - _cb_info_free (info); + info->idle_id = 0; + _cb_info_complete_and_free (info, "idle call", NULL, NULL); return G_SOURCE_REMOVE; } static void -add_or_change_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) +add_or_change_cb (GObject *proxy, GAsyncResult *result, gpointer user_data) { CBInfo *info = user_data; - GError *error = NULL; - char *zone = NULL; + gs_free_error GError *error = NULL; + gs_unref_variant GVariant *ret = NULL; - if (!dbus_g_proxy_end_call (proxy, call_id, &error, - G_TYPE_STRING, &zone, - G_TYPE_INVALID)) { - g_assert (error); - if (g_strcmp0 (error->message, "ZONE_ALREADY_SET") != 0) { - nm_log_warn (LOGD_FIREWALL, "(%s) firewall zone add/change failed [%u]: (%d) %s", - info->iface, info->id, error->code, error->message); - } else { - nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone add/change failed [%u]: (%d) %s", - info->iface, info->id, error->code, error->message); - } - } else { - nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone add/change succeeded [%u]", - info->iface, info->id); - } - - if (info->callback) - info->callback (error, info->user_data); - - info->completed = TRUE; - g_free (zone); - g_clear_error (&error); + ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), result, &error); + _cb_info_complete_and_free (info, "add/change", "ZONE_ALREADY_SET", error); } NMFirewallPendingCall @@ -203,45 +182,24 @@ nm_firewall_manager_add_or_change_zone (NMFirewallManager *self, nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone %s -> %s%s%s [%u]", iface, add ? "add" : "change", zone?"\"":"", zone ? zone : "default", zone?"\"":"", info->id); - info->dbus_call = dbus_g_proxy_begin_call_with_timeout (priv->proxy, - add ? "addInterface" : "changeZone", - add_or_change_cb, - info, - (GDestroyNotify) _cb_info_free, - 10000, /* timeout */ - G_TYPE_STRING, zone ? zone : "", - G_TYPE_STRING, iface, - G_TYPE_INVALID); - return PENDING_CALL_FROM_INFO (info); + g_dbus_proxy_call (priv->proxy, + add ? "addInterface" : "changeZone", + g_variant_new ("(ss)", zone ? zone : "", iface), + G_DBUS_CALL_FLAGS_NONE, 10000, + info->cancellable, + add_or_change_cb, info); + return (NMFirewallPendingCall) info; } static void -remove_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) +remove_cb (GObject *proxy, GAsyncResult *result, gpointer user_data) { CBInfo *info = user_data; - GError *error = NULL; - char * zone = NULL; + gs_free_error GError *error = NULL; + gs_unref_variant GVariant *ret = NULL; - if (!dbus_g_proxy_end_call (proxy, call_id, &error, - G_TYPE_STRING, &zone, - G_TYPE_INVALID)) { - g_assert (error); - /* ignore UNKNOWN_INTERFACE errors */ - if (error->message && !strstr (error->message, "UNKNOWN_INTERFACE")) { - nm_log_warn (LOGD_FIREWALL, "(%s) firewall zone remove failed [%u]: (%d) %s", - info->iface, info->id, error->code, error->message); - } else { - nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone remove failed [%u]: (%d) %s", - info->iface, info->id, error->code, error->message); - } - } else { - nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone remove succeeded [%u]", - info->iface, info->id); - } - - info->completed = TRUE; - g_free (zone); - g_clear_error (&error); + ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), result, &error); + _cb_info_complete_and_free (info, "remove", "UNKNOWN_INTERFACE", error); } NMFirewallPendingCall @@ -261,42 +219,25 @@ nm_firewall_manager_remove_from_zone (NMFirewallManager *self, nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone remove -> %s%s%s [%u]", iface, zone?"\"":"", zone ? zone : "*", zone?"\"":"", info->id); - info->dbus_call = dbus_g_proxy_begin_call_with_timeout (priv->proxy, - "removeInterface", - remove_cb, - info, - (GDestroyNotify) _cb_info_free, - 10000, /* timeout */ - G_TYPE_STRING, zone ? zone : "", - G_TYPE_STRING, iface, - G_TYPE_INVALID); - return PENDING_CALL_FROM_INFO (info); + g_dbus_proxy_call (priv->proxy, + "removeInterface", + g_variant_new ("(ss)", zone ? zone : "", iface), + G_DBUS_CALL_FLAGS_NONE, 10000, + info->cancellable, + remove_cb, info); + return (NMFirewallPendingCall) info; } -void nm_firewall_manager_cancel_call (NMFirewallManager *self, NMFirewallPendingCall call) +void +nm_firewall_manager_cancel_call (NMFirewallManager *self, NMFirewallPendingCall call) { - NMFirewallManagerPrivate *priv = NM_FIREWALL_MANAGER_GET_PRIVATE (self); - GSList *pending; - CBInfo *info; + CBInfo *info = (CBInfo *) call; g_return_if_fail (NM_IS_FIREWALL_MANAGER (self)); - if (call == PENDING_CALL_DUMMY) - return; - - pending = g_slist_find (priv->pending_calls, call); - - if (!pending) - return; - priv->pending_calls = g_slist_remove_link (priv->pending_calls, pending); - - info = (CBInfo *) call; - if (info->idle_id) - info->idle_id = 0; - else { - dbus_g_proxy_cancel_call (NM_FIREWALL_MANAGER_GET_PRIVATE (self)->proxy, - info->dbus_call); - } + info->callback = NULL; + info->idle_id = 0; + g_cancellable_cancel (info->cancellable); } static void @@ -311,25 +252,19 @@ set_running (NMFirewallManager *self, gboolean now_running) } static void -name_owner_changed (NMDBusManager *dbus_mgr, - const char *name, - const char *old_owner, - const char *new_owner, - gpointer user_data) +name_owner_changed (GObject *object, + GParamSpec *pspec, + gpointer user_data) { NMFirewallManager *self = NM_FIREWALL_MANAGER (user_data); - gboolean old_owner_good = (old_owner && strlen (old_owner)); - gboolean new_owner_good = (new_owner && strlen (new_owner)); + gs_free char *owner = NULL; - /* We only care about the firewall here */ - if (strcmp (FIREWALL_DBUS_SERVICE, name) != 0) - return; - - if (!old_owner_good && new_owner_good) { + owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (object)); + if (owner) { nm_log_dbg (LOGD_FIREWALL, "firewall started"); set_running (self, TRUE); g_signal_emit (self, signals[STARTED], 0); - } else if (old_owner_good && !new_owner_good) { + } else { nm_log_dbg (LOGD_FIREWALL, "firewall stopped"); set_running (self, FALSE); } @@ -343,21 +278,23 @@ static void nm_firewall_manager_init (NMFirewallManager * self) { NMFirewallManagerPrivate *priv = NM_FIREWALL_MANAGER_GET_PRIVATE (self); - DBusGConnection *bus; + gs_free char *owner = NULL; - priv->dbus_mgr = g_object_ref (nm_dbus_manager_get ()); - priv->name_owner_id = g_signal_connect (priv->dbus_mgr, - NM_DBUS_MANAGER_NAME_OWNER_CHANGED, - G_CALLBACK (name_owner_changed), - self); - priv->running = nm_dbus_manager_name_has_owner (priv->dbus_mgr, FIREWALL_DBUS_SERVICE); + priv->proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | + G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, + NULL, + FIREWALL_DBUS_SERVICE, + FIREWALL_DBUS_PATH, + FIREWALL_DBUS_INTERFACE_ZONE, + NULL, NULL); + + g_signal_connect (priv->proxy, "notify::g-name-owner", + G_CALLBACK (name_owner_changed), self); + owner = g_dbus_proxy_get_name_owner (priv->proxy); + priv->running = (owner != NULL); nm_log_dbg (LOGD_FIREWALL, "firewall %s running", priv->running ? "is" : "is not" ); - bus = nm_dbus_manager_get_connection (priv->dbus_mgr); - priv->proxy = dbus_g_proxy_new_for_name (bus, - FIREWALL_DBUS_SERVICE, - FIREWALL_DBUS_PATH, - FIREWALL_DBUS_INTERFACE_ZONE); } static void @@ -386,12 +323,6 @@ dispose (GObject *object) g_assert (priv->pending_calls == NULL); - if (priv->dbus_mgr) { - g_signal_handler_disconnect (priv->dbus_mgr, priv->name_owner_id); - priv->name_owner_id = 0; - g_clear_object (&priv->dbus_mgr); - } - g_clear_object (&priv->proxy); /* Chain up to the parent class */ diff --git a/src/nm-manager.c b/src/nm-manager.c index 6e78dbe6d..704296d3c 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -190,7 +190,7 @@ typedef struct { NMVpnManager *vpn_manager; - DBusGProxy *aipd_proxy; + GDBusProxy *aipd_proxy; NMSleepMonitor *sleep_monitor; GSList *auth_chains; @@ -801,7 +801,7 @@ device_removed_cb (NMDevice *device, gpointer user_data) } static void -aipd_handle_event (DBusGProxy *proxy, +aipd_handle_event (GDBusProxy *proxy, const char *event, const char *iface, const char *address, @@ -812,11 +812,6 @@ aipd_handle_event (DBusGProxy *proxy, GSList *iter; gboolean handled = FALSE; - if (!event || !iface) { - nm_log_warn (LOGD_AUTOIP4, "incomplete message received from avahi-autoipd"); - return; - } - if ( (strcmp (event, "BIND") != 0) && (strcmp (event, "CONFLICT") != 0) && (strcmp (event, "UNBIND") != 0) @@ -3865,14 +3860,14 @@ impl_manager_sleep (NMManager *self, } static void -sleeping_cb (DBusGProxy *proxy, gpointer user_data) +sleeping_cb (NMSleepMonitor *monitor, gpointer user_data) { nm_log_dbg (LOGD_SUSPEND, "Received sleeping signal"); _internal_sleep (NM_MANAGER (user_data), TRUE); } static void -resuming_cb (DBusGProxy *proxy, gpointer user_data) +resuming_cb (NMSleepMonitor *monitor, gpointer user_data) { nm_log_dbg (LOGD_SUSPEND, "Received resuming signal"); _internal_sleep (NM_MANAGER (user_data), FALSE); @@ -4870,9 +4865,9 @@ static void nm_manager_init (NMManager *manager) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); - DBusGConnection *g_connection; guint i; GFile *file; + GError *error = NULL; /* Initialize rfkill structures and states */ memset (priv->radio_states, 0, sizeof (priv->radio_states)); @@ -4913,30 +4908,22 @@ nm_manager_init (NMManager *manager) priv->vpn_manager = g_object_ref (nm_vpn_manager_get ()); - g_connection = nm_dbus_manager_get_connection (priv->dbus_mgr); - /* avahi-autoipd stuff */ - priv->aipd_proxy = dbus_g_proxy_new_for_name (g_connection, - NM_AUTOIP_DBUS_SERVICE, - "/", - NM_AUTOIP_DBUS_IFACE); + priv->aipd_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, + NULL, + NM_AUTOIP_DBUS_SERVICE, + "/", + NM_AUTOIP_DBUS_IFACE, + NULL, &error); if (priv->aipd_proxy) { - dbus_g_object_register_marshaller (g_cclosure_marshal_generic, - G_TYPE_NONE, - G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, - G_TYPE_INVALID); - - dbus_g_proxy_add_signal (priv->aipd_proxy, - "Event", - G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, - G_TYPE_INVALID); - - dbus_g_proxy_connect_signal (priv->aipd_proxy, "Event", - G_CALLBACK (aipd_handle_event), - manager, - NULL); - } else - nm_log_warn (LOGD_AUTOIP4, "could not initialize avahi-autoipd D-Bus proxy"); + _nm_dbus_signal_connect (priv->aipd_proxy, "Event", G_VARIANT_TYPE ("(sss)"), + G_CALLBACK (aipd_handle_event), manager); + } else { + nm_log_warn (LOGD_AUTOIP4, "could not initialize avahi-autoipd D-Bus proxy: %s", + error->message); + g_clear_error (&error); + } /* sleep/wake handling */ priv->sleep_monitor = g_object_ref (nm_sleep_monitor_get ()); diff --git a/src/nm-sleep-monitor-systemd.c b/src/nm-sleep-monitor-systemd.c index 44523a4a2..18c847831 100644 --- a/src/nm-sleep-monitor-systemd.c +++ b/src/nm-sleep-monitor-systemd.c @@ -28,6 +28,7 @@ #include "nm-logging.h" #include "nm-dbus-manager.h" +#include "nm-core-internal.h" #include "nm-sleep-monitor.h" @@ -123,19 +124,12 @@ take_inhibitor (NMSleepMonitor *self) } static void -signal_cb (GDBusProxy *proxy, - const gchar *sendername, - const gchar *signalname, - GVariant *args, - gpointer data) +prepare_for_sleep_cb (GDBusProxy *proxy, + gboolean is_about_to_suspend, + gpointer data) { NMSleepMonitor *self = data; - gboolean is_about_to_suspend; - if (strcmp (signalname, "PrepareForSleep") != 0) - return; - - g_variant_get (args, "(b)", &is_about_to_suspend); nm_log_dbg (LOGD_SUSPEND, "Received PrepareForSleep signal: %d", is_about_to_suspend); if (is_about_to_suspend) { @@ -182,7 +176,8 @@ on_proxy_acquired (GObject *object, } g_signal_connect (self->sd_proxy, "notify::g-name-owner", G_CALLBACK (name_owner_cb), self); - g_signal_connect (self->sd_proxy, "g-signal", G_CALLBACK (signal_cb), self); + _nm_dbus_signal_connect (self->sd_proxy, "PrepareForSleep", G_VARIANT_TYPE ("(b)"), + G_CALLBACK (prepare_for_sleep_cb), self); owner = g_dbus_proxy_get_name_owner (self->sd_proxy); if (owner) diff --git a/src/nm-sleep-monitor-upower.c b/src/nm-sleep-monitor-upower.c index 0c46ae10f..a9abb08b0 100644 --- a/src/nm-sleep-monitor-upower.c +++ b/src/nm-sleep-monitor-upower.c @@ -22,33 +22,32 @@ #include #include #include -#include #include #include "nm-logging.h" -#include "nm-dbus-manager.h" +#include "nm-core-internal.h" #include "nm-sleep-monitor.h" #define UPOWER_DBUS_SERVICE "org.freedesktop.UPower" struct _NMSleepMonitor { - GObject parent_instance; + GObject parent_instance; - DBusGProxy *upower_proxy; + GDBusProxy *upower_proxy; }; struct _NMSleepMonitorClass { - GObjectClass parent_class; + GObjectClass parent_class; - void (*sleeping) (NMSleepMonitor *monitor); - void (*resuming) (NMSleepMonitor *monitor); + void (*sleeping) (NMSleepMonitor *monitor); + void (*resuming) (NMSleepMonitor *monitor); }; enum { - SLEEPING, - RESUMING, - LAST_SIGNAL, + SLEEPING, + RESUMING, + LAST_SIGNAL, }; static guint signals[LAST_SIGNAL] = {0}; @@ -57,80 +56,78 @@ G_DEFINE_TYPE (NMSleepMonitor, nm_sleep_monitor, G_TYPE_OBJECT); /********************************************************************/ static void -upower_sleeping_cb (DBusGProxy *proxy, gpointer user_data) +upower_sleeping_cb (GDBusProxy *proxy, gpointer user_data) { - nm_log_dbg (LOGD_SUSPEND, "Received UPower sleeping signal"); - g_signal_emit (user_data, signals[SLEEPING], 0); + nm_log_dbg (LOGD_SUSPEND, "Received UPower sleeping signal"); + g_signal_emit (user_data, signals[SLEEPING], 0); } static void -upower_resuming_cb (DBusGProxy *proxy, gpointer user_data) +upower_resuming_cb (GDBusProxy *proxy, gpointer user_data) { - nm_log_dbg (LOGD_SUSPEND, "Received UPower resuming signal"); - g_signal_emit (user_data, signals[RESUMING], 0); + nm_log_dbg (LOGD_SUSPEND, "Received UPower resuming signal"); + g_signal_emit (user_data, signals[RESUMING], 0); } static void nm_sleep_monitor_init (NMSleepMonitor *self) { - DBusGConnection *bus; + GError *error = NULL; - bus = nm_dbus_manager_get_connection (nm_dbus_manager_get ()); - self->upower_proxy = dbus_g_proxy_new_for_name (bus, - UPOWER_DBUS_SERVICE, - "/org/freedesktop/UPower", - "org.freedesktop.UPower"); - if (self->upower_proxy) { - dbus_g_proxy_add_signal (self->upower_proxy, "Sleeping", G_TYPE_INVALID); - dbus_g_proxy_connect_signal (self->upower_proxy, "Sleeping", - G_CALLBACK (upower_sleeping_cb), - self, NULL); - - dbus_g_proxy_add_signal (self->upower_proxy, "Resuming", G_TYPE_INVALID); - dbus_g_proxy_connect_signal (self->upower_proxy, "Resuming", - G_CALLBACK (upower_resuming_cb), - self, NULL); - } else - nm_log_warn (LOGD_SUSPEND, "could not initialize UPower D-Bus proxy"); + self->upower_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START | + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, + NULL, + UPOWER_DBUS_SERVICE, + "/org/freedesktop/UPower", + "org.freedesktop.UPower", + NULL, &error); + if (self->upower_proxy) { + _nm_dbus_signal_connect (self->upower_proxy, "Sleeping", NULL, + G_CALLBACK (upower_sleeping_cb), self); + _nm_dbus_signal_connect (self->upower_proxy, "Resuming", NULL, + G_CALLBACK (upower_resuming_cb), self); + } else { + nm_log_warn (LOGD_SUSPEND, "could not initialize UPower D-Bus proxy: %s", error->message); + g_error_free (error); + } } static void finalize (GObject *object) { - NMSleepMonitor *self = NM_SLEEP_MONITOR (object); + NMSleepMonitor *self = NM_SLEEP_MONITOR (object); - if (self->upower_proxy) - g_object_unref (self->upower_proxy); + g_clear_object (&self->upower_proxy); - if (G_OBJECT_CLASS (nm_sleep_monitor_parent_class)->finalize != NULL) - G_OBJECT_CLASS (nm_sleep_monitor_parent_class)->finalize (object); + G_OBJECT_CLASS (nm_sleep_monitor_parent_class)->finalize (object); } static void nm_sleep_monitor_class_init (NMSleepMonitorClass *klass) { - GObjectClass *gobject_class; + GObjectClass *gobject_class; - gobject_class = G_OBJECT_CLASS (klass); + gobject_class = G_OBJECT_CLASS (klass); - gobject_class->finalize = finalize; + gobject_class->finalize = finalize; - signals[SLEEPING] = g_signal_new (NM_SLEEP_MONITOR_SLEEPING, - NM_TYPE_SLEEP_MONITOR, - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMSleepMonitorClass, sleeping), - NULL, /* accumulator */ - NULL, /* accumulator data */ - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - signals[RESUMING] = g_signal_new (NM_SLEEP_MONITOR_RESUMING, - NM_TYPE_SLEEP_MONITOR, - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMSleepMonitorClass, resuming), - NULL, /* accumulator */ - NULL, /* accumulator data */ - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); + signals[SLEEPING] = g_signal_new (NM_SLEEP_MONITOR_SLEEPING, + NM_TYPE_SLEEP_MONITOR, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (NMSleepMonitorClass, sleeping), + NULL, /* accumulator */ + NULL, /* accumulator data */ + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + signals[RESUMING] = g_signal_new (NM_SLEEP_MONITOR_RESUMING, + NM_TYPE_SLEEP_MONITOR, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (NMSleepMonitorClass, resuming), + NULL, /* accumulator */ + NULL, /* accumulator data */ + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); } NM_DEFINE_SINGLETON_GETTER (NMSleepMonitor, nm_sleep_monitor_get, NM_TYPE_SLEEP_MONITOR); diff --git a/src/supplicant-manager/nm-supplicant-interface.c b/src/supplicant-manager/nm-supplicant-interface.c index e9775a199..a190afb45 100644 --- a/src/supplicant-manager/nm-supplicant-interface.c +++ b/src/supplicant-manager/nm-supplicant-interface.c @@ -404,19 +404,6 @@ nm_supplicant_interface_credentials_reply (NMSupplicantInterface *self, return !!reply; } -static gboolean -_dbus_error_has_name (GError *error, const char *dbus_error_name) -{ - gs_free char *error_name = NULL; - gboolean is_error = FALSE; - - if (error && g_dbus_error_is_remote_error (error)) { - error_name = g_dbus_error_get_remote_error (error); - is_error = !g_strcmp0 (error_name, dbus_error_name); - } - return is_error; -} - static void iface_check_netreply_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) { @@ -439,7 +426,7 @@ iface_check_netreply_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_ self = NM_SUPPLICANT_INTERFACE (user_data); priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - if (variant || _dbus_error_has_name (error, "fi.w1.wpa_supplicant1.InvalidArgs")) + if (variant || _nm_dbus_error_has_name (error, "fi.w1.wpa_supplicant1.InvalidArgs")) priv->has_credreq = TRUE; nm_log_dbg (LOGD_SUPPLICANT, "Supplicant %s network credentials requests", @@ -477,14 +464,16 @@ iface_check_ap_mode_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_d const char *data; /* The ProbeRequest method only exists if AP mode has been enabled */ - variant = g_dbus_proxy_call_finish (proxy, result, &error); + variant = _nm_dbus_proxy_call_finish (proxy, result, + G_VARIANT_TYPE ("(s)"), + &error); if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) return; self = NM_SUPPLICANT_INTERFACE (user_data); priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - if (variant && g_variant_is_of_type (variant, G_VARIANT_TYPE ("(s)"))) { + if (variant) { g_variant_get (variant, "(&s)", &data); if (strstr (data, "ProbeRequest")) priv->ap_support = AP_SUPPORT_YES; @@ -493,41 +482,59 @@ iface_check_ap_mode_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_d iface_check_ready (self); } -#define MATCH_SIGNAL(s, n, v, t) (!strcmp (s, n) && g_variant_is_of_type (v, t)) - static void -signal_cb (GDBusProxy *proxy, - const gchar *sender, - const gchar *signal, - GVariant *args, - gpointer user_data) +wpas_iface_scan_done (GDBusProxy *proxy, + gboolean success, + gpointer user_data) { NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data); NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - const char *path, *field, *message; - gboolean success; - if (MATCH_SIGNAL (signal, "ScanDone", args, G_VARIANT_TYPE ("(b)"))) { - /* Cache last scan completed time */ + /* Cache last scan completed time */ + priv->last_scan = nm_utils_get_monotonic_timestamp_s (); + + g_signal_emit (self, signals[SCAN_DONE], 0, success); +} + +static void +wpas_iface_bss_added (GDBusProxy *proxy, + const char *path, + GVariant *props, + gpointer user_data) +{ + NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data); + NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); + + if (priv->scanning) priv->last_scan = nm_utils_get_monotonic_timestamp_s (); - g_variant_get (args, "(b)", &success); - g_signal_emit (self, signals[SCAN_DONE], 0, success); - } else if (MATCH_SIGNAL (signal, "BSSAdded", args, G_VARIANT_TYPE ("(oa{sv})"))) { - if (priv->scanning) - priv->last_scan = nm_utils_get_monotonic_timestamp_s (); + handle_new_bss (self, path); +} - g_variant_get (args, "(&oa{sv})", &path, NULL); - handle_new_bss (self, path); - } else if (MATCH_SIGNAL (signal, "BSSRemoved", args, G_VARIANT_TYPE ("(o)"))) { - g_variant_get (args, "(&o)", &path); - g_signal_emit (self, signals[BSS_REMOVED], 0, path); - g_hash_table_remove (priv->bss_proxies, path); - } else if (MATCH_SIGNAL (signal, "NetworkRequest", args, G_VARIANT_TYPE ("(oss)"))) { - g_variant_get (args, "(&o&s&s)", &path, &field, &message); - if (priv->has_credreq && priv->net_path && !g_strcmp0 (path, priv->net_path)) - g_signal_emit (self, signals[CREDENTIALS_REQUEST], 0, field, message); - } +static void +wpas_iface_bss_removed (GDBusProxy *proxy, + const char *path, + gpointer user_data) +{ + NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data); + NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); + + g_signal_emit (self, signals[BSS_REMOVED], 0, path); + g_hash_table_remove (priv->bss_proxies, path); +} + +static void +wpas_iface_network_request (GDBusProxy *proxy, + const char *path, + const char *field, + const char *message, + gpointer user_data) +{ + NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data); + NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); + + if (priv->has_credreq && priv->net_path && !g_strcmp0 (path, priv->net_path)) + g_signal_emit (self, signals[CREDENTIALS_REQUEST], 0, field, message); } static void @@ -602,7 +609,14 @@ on_iface_proxy_acquired (GDBusProxy *proxy, GAsyncResult *result, gpointer user_ self = NM_SUPPLICANT_INTERFACE (user_data); priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - g_signal_connect (priv->iface_proxy, "g-signal", G_CALLBACK (signal_cb), self); + _nm_dbus_signal_connect (priv->iface_proxy, "ScanDone", G_VARIANT_TYPE ("(b)"), + G_CALLBACK (wpas_iface_scan_done), self); + _nm_dbus_signal_connect (priv->iface_proxy, "BSSAdded", G_VARIANT_TYPE ("(oa{sv})"), + G_CALLBACK (wpas_iface_bss_added), self); + _nm_dbus_signal_connect (priv->iface_proxy, "BSSRemoved", G_VARIANT_TYPE ("(o)"), + G_CALLBACK (wpas_iface_bss_removed), self); + _nm_dbus_signal_connect (priv->iface_proxy, "NetworkRequest", G_VARIANT_TYPE ("(oss)"), + G_CALLBACK (wpas_iface_network_request), self); /* Check whether NetworkReply and AP mode are supported */ priv->ready_count = 1; @@ -666,19 +680,20 @@ interface_get_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) NMSupplicantInterfacePrivate *priv; gs_unref_variant GVariant *variant = NULL; gs_free_error GError *error = NULL; - char *path; + const char *path; - variant = g_dbus_proxy_call_finish (proxy, result, &error); + variant = _nm_dbus_proxy_call_finish (proxy, result, + G_VARIANT_TYPE ("(o)"), + &error); if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) return; self = NM_SUPPLICANT_INTERFACE (user_data); priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - if (variant && g_variant_is_of_type (variant, G_VARIANT_TYPE ("(o)"))) { - g_variant_get (variant, "(o)", &path); + if (variant) { + g_variant_get (variant, "(&o)", &path); interface_add_done (self, path); - g_free (path); } else { nm_log_err (LOGD_SUPPLICANT, "(%s): error getting interface: %s", priv->dev, error->message); set_state (self, NM_SUPPLICANT_INTERFACE_STATE_DOWN); @@ -692,20 +707,21 @@ interface_add_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) NMSupplicantInterfacePrivate *priv; gs_free_error GError *error = NULL; gs_unref_variant GVariant *variant = NULL; - char *path; + const char *path; - variant = g_dbus_proxy_call_finish (proxy, result, &error); + variant = _nm_dbus_proxy_call_finish (proxy, result, + G_VARIANT_TYPE ("(o)"), + &error); if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) return; self = NM_SUPPLICANT_INTERFACE (user_data); priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - if (variant && g_variant_is_of_type (variant, G_VARIANT_TYPE ("(o)"))) { - g_variant_get (variant, "(o)", &path); + if (variant) { + g_variant_get (variant, "(&o)", &path); interface_add_done (self, path); - g_free (path); - } else if (_dbus_error_has_name (error, WPAS_ERROR_EXISTS_ERROR)) { + } else if (_nm_dbus_error_has_name (error, WPAS_ERROR_EXISTS_ERROR)) { /* Interface already added, just get its object path */ g_dbus_proxy_call (priv->wpas_proxy, "GetInterface", @@ -963,19 +979,15 @@ add_network_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) const char *blob_name; GByteArray *blob_data; - reply = g_dbus_proxy_call_finish (proxy, result, &error); + reply = _nm_dbus_proxy_call_finish (proxy, result, + G_VARIANT_TYPE ("(o)"), + &error); if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) return; self = NM_SUPPLICANT_INTERFACE (user_data); priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - if (reply && !g_variant_is_of_type (reply, G_VARIANT_TYPE ("(o)"))) { - error = g_error_new (NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED, - "Unexpected AddNetwork reply type %s", - g_variant_get_type_string (reply)); - } - g_free (priv->net_path); priv->net_path = NULL; @@ -986,7 +998,6 @@ add_network_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) } g_variant_get (reply, "(o)", &priv->net_path); - g_assert (priv->net_path); /* Send blobs first; otherwise jump to selecting the network */ blobs = nm_supplicant_config_get_blobs (priv->cfg); diff --git a/src/vpn-manager/nm-vpn-connection.c b/src/vpn-manager/nm-vpn-connection.c index 57e0e2d21..02c39c30f 100644 --- a/src/vpn-manager/nm-vpn-connection.c +++ b/src/vpn-manager/nm-vpn-connection.c @@ -1580,44 +1580,74 @@ really_activate (NMVpnConnection *self, const char *username) _set_vpn_state (self, STATE_CONNECT, NM_VPN_CONNECTION_STATE_REASON_NONE, FALSE); } -#define MATCH_SIGNAL(s, n, v, t) (!strcmp (s, n) && g_variant_is_of_type (v, t)) +static void +failure_cb (GDBusProxy *proxy, + guint32 reason, + gpointer user_data) +{ + NMVpnConnection *self = NM_VPN_CONNECTION (user_data); + + plugin_failed (self, reason); +} static void -signal_cb (GDBusProxy *proxy, - const gchar *sender, - const gchar *signal, - GVariant *args, - gpointer user_data) +state_changed_cb (GDBusProxy *proxy, + guint32 new_service_state, + gpointer user_data) +{ + NMVpnConnection *self = NM_VPN_CONNECTION (user_data); + + plugin_state_changed (self, new_service_state); +} + +static void +secrets_required_cb (GDBusProxy *proxy, + const char *message, + const char **secrets, + gpointer user_data) +{ + NMVpnConnection *self = NM_VPN_CONNECTION (user_data); + + plugin_interactive_secrets_required (self, message, secrets); +} + +static void +config_cb (GDBusProxy *proxy, + GVariant *dict, + gpointer user_data) { NMVpnConnection *self = NM_VPN_CONNECTION (user_data); NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (self); - const char *message, **secrets; - gs_unref_variant GVariant *dict = NULL; - guint u32; - if (MATCH_SIGNAL (signal, "Failure", args, G_VARIANT_TYPE ("(u)"))) { - g_variant_get (args, "(u)", &u32); - plugin_failed (self, u32); - } else if (MATCH_SIGNAL (signal, "StateChanged", args, G_VARIANT_TYPE ("(u)"))) { - g_variant_get (args, "(u)", &u32); - plugin_state_changed (self, u32); - } else if (MATCH_SIGNAL (signal, "SecretsRequired", args, G_VARIANT_TYPE ("(sas)"))) { - g_variant_get (args, "(&s^a&s)", &message, &secrets); - plugin_interactive_secrets_required (self, message, secrets); - g_free (secrets); - } else if (priv->vpn_state >= STATE_NEED_AUTH) { - /* Only list to these signals during and after connection */ - if (MATCH_SIGNAL (signal, "Config", args, G_VARIANT_TYPE ("(a{sv})"))) { - g_variant_get (args, "(@a{sv})", &dict); - nm_vpn_connection_config_get (self, dict); - } else if (MATCH_SIGNAL (signal, "Ip4Config", args, G_VARIANT_TYPE ("(a{sv})"))) { - g_variant_get (args, "(@a{sv})", &dict); - nm_vpn_connection_ip4_config_get (self, dict); - } else if (MATCH_SIGNAL (signal, "Ip6Config", args, G_VARIANT_TYPE ("(a{sv})"))) { - g_variant_get (args, "(@a{sv})", &dict); - nm_vpn_connection_ip6_config_get (self, dict); - } - } + /* Only list to this signals during and after connection */ + if (priv->vpn_state >= STATE_NEED_AUTH) + nm_vpn_connection_config_get (self, dict); +} + +static void +ip4_config_cb (GDBusProxy *proxy, + GVariant *dict, + gpointer user_data) +{ + NMVpnConnection *self = NM_VPN_CONNECTION (user_data); + NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (self); + + /* Only list to this signals during and after connection */ + if (priv->vpn_state >= STATE_NEED_AUTH) + nm_vpn_connection_ip4_config_get (self, dict); +} + +static void +ip6_config_cb (GDBusProxy *proxy, + GVariant *dict, + gpointer user_data) +{ + NMVpnConnection *self = NM_VPN_CONNECTION (user_data); + NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (self); + + /* Only list to this signals during and after connection */ + if (priv->vpn_state >= STATE_NEED_AUTH) + nm_vpn_connection_ip6_config_get (self, dict); } static void @@ -1648,7 +1678,18 @@ on_proxy_acquired (GObject *object, GAsyncResult *result, gpointer user_data) } priv->proxy = proxy; - g_signal_connect (priv->proxy, "g-signal", G_CALLBACK (signal_cb), self); + _nm_dbus_signal_connect (priv->proxy, "Failure", G_VARIANT_TYPE ("(u)"), + G_CALLBACK (failure_cb), self); + _nm_dbus_signal_connect (priv->proxy, "StateChanged", G_VARIANT_TYPE ("(u)"), + G_CALLBACK (state_changed_cb), self); + _nm_dbus_signal_connect (priv->proxy, "SecretsRequired", G_VARIANT_TYPE ("(sas)"), + G_CALLBACK (secrets_required_cb), self); + _nm_dbus_signal_connect (priv->proxy, "Config", G_VARIANT_TYPE ("(a{sv})"), + G_CALLBACK (config_cb), self); + _nm_dbus_signal_connect (priv->proxy, "Ip4Config", G_VARIANT_TYPE ("(a{sv})"), + G_CALLBACK (ip4_config_cb), self); + _nm_dbus_signal_connect (priv->proxy, "Ip6Config", G_VARIANT_TYPE ("(a{sv})"), + G_CALLBACK (ip6_config_cb), self); _set_vpn_state (self, STATE_NEED_AUTH, NM_VPN_CONNECTION_STATE_REASON_NONE, FALSE); @@ -1810,7 +1851,7 @@ plugin_need_secrets_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_d gs_free_error GError *error = NULL; const char *setting_name; - reply = g_dbus_proxy_call_finish (proxy, result, &error); + reply = _nm_dbus_proxy_call_finish (proxy, result, G_VARIANT_TYPE ("(s)"), &error); if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) return;