diff options
author | Thomas Haller <thaller@redhat.com> | 2019-09-21 14:59:59 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2019-09-21 14:59:59 +0200 |
commit | bf8118b8290d498f71068d9b77628cf7cb668400 (patch) | |
tree | 0d6bd7ab84d6777ba291fdcd4ebbcd8b4d195624 | |
parent | e1cda0150ca9f78b19967542234227cbf1853b18 (diff) | |
parent | 30ce0079a8ab4570914531572e761bb691a9cf4a (diff) | |
download | NetworkManager-bf8118b8290d498f71068d9b77628cf7cb668400.tar.gz |
libnm: merge branch 'th/libnm-dbus-rework-1'
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/merge_requests/258
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | libnm/nm-dbus-helpers.c | 57 | ||||
-rw-r--r-- | libnm/nm-dbus-helpers.h | 11 | ||||
-rw-r--r-- | libnm/nm-device.c | 5 | ||||
-rw-r--r-- | libnm/nm-manager.c | 34 | ||||
-rw-r--r-- | libnm/nm-secret-agent-old.c | 28 | ||||
-rw-r--r-- | shared/meson.build | 1 | ||||
-rw-r--r-- | shared/nm-glib-aux/nm-macros-internal.h | 14 | ||||
-rw-r--r-- | shared/nm-glib-aux/nm-ref-string.c | 187 | ||||
-rw-r--r-- | shared/nm-glib-aux/nm-ref-string.h | 52 |
10 files changed, 275 insertions, 116 deletions
diff --git a/Makefile.am b/Makefile.am index f863b29f34..48e0cd55df 100644 --- a/Makefile.am +++ b/Makefile.am @@ -373,6 +373,8 @@ shared_nm_glib_aux_libnm_glib_aux_la_SOURCES = \ shared/nm-glib-aux/nm-obj.h \ shared/nm-glib-aux/nm-random-utils.c \ shared/nm-glib-aux/nm-random-utils.h \ + shared/nm-glib-aux/nm-ref-string.c \ + shared/nm-glib-aux/nm-ref-string.h \ shared/nm-glib-aux/nm-secret-utils.c \ shared/nm-glib-aux/nm-secret-utils.h \ shared/nm-glib-aux/nm-shared-utils.c \ diff --git a/libnm/nm-dbus-helpers.c b/libnm/nm-dbus-helpers.c index 84312d2c31..978d5e2a82 100644 --- a/libnm/nm-dbus-helpers.c +++ b/libnm/nm-dbus-helpers.c @@ -26,63 +26,6 @@ _nm_dbus_bus_type (void) return nm_bus; } -GDBusConnection * -_nm_dbus_new_connection (GCancellable *cancellable, GError **error) -{ - return g_bus_get_sync (_nm_dbus_bus_type (), cancellable, error); -} - -static void -new_connection_async_got_system (GObject *source, GAsyncResult *result, gpointer user_data) -{ - GSimpleAsyncResult *simple = user_data; - GDBusConnection *connection; - GError *error = NULL; - - connection = g_bus_get_finish (result, &error); - if (connection) - g_simple_async_result_set_op_res_gpointer (simple, connection, g_object_unref); - else - g_simple_async_result_take_error (simple, error); - - g_simple_async_result_complete (simple); - g_object_unref (simple); -} - -void -_nm_dbus_new_connection_async (GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GSimpleAsyncResult *simple; - - simple = g_simple_async_result_new (NULL, callback, user_data, _nm_dbus_new_connection_async); - if (cancellable) - g_simple_async_result_set_check_cancellable (simple, cancellable); - - g_bus_get (_nm_dbus_bus_type (), - cancellable, - new_connection_async_got_system, simple); -} - -GDBusConnection * -_nm_dbus_new_connection_finish (GAsyncResult *result, - GError **error) -{ - GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result); - - if (g_simple_async_result_propagate_error (simple, error)) - return NULL; - - return g_object_ref (g_simple_async_result_get_op_res_gpointer (simple)); -} - -gboolean -_nm_dbus_is_connection_private (GDBusConnection *connection) -{ - return g_dbus_connection_get_unique_name (connection) == NULL; -} - /* D-Bus has an upper limit on number of Match rules and it's rather easy * to hit as the proxy likes to add one for each object. Let's remove the Match * rule the proxy added and ensure a less granular rule is present instead. diff --git a/libnm/nm-dbus-helpers.h b/libnm/nm-dbus-helpers.h index 381f35f68d..42e67e1c65 100644 --- a/libnm/nm-dbus-helpers.h +++ b/libnm/nm-dbus-helpers.h @@ -14,17 +14,6 @@ GBusType _nm_dbus_bus_type (void); -GDBusConnection *_nm_dbus_new_connection (GCancellable *cancellable, - GError **error); - -void _nm_dbus_new_connection_async (GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); -GDBusConnection *_nm_dbus_new_connection_finish (GAsyncResult *result, - GError **error); - -gboolean _nm_dbus_is_connection_private (GDBusConnection *connection); - void _nm_dbus_proxy_replace_match (GDBusProxy *proxy); void _nm_dbus_bind_properties (gpointer object, diff --git a/libnm/nm-device.c b/libnm/nm-device.c index 49a929fa85..f6663fbd23 100644 --- a/libnm/nm-device.c +++ b/libnm/nm-device.c @@ -444,11 +444,6 @@ set_property (GObject *object, gboolean b; switch (prop_id) { - case PROP_MANAGED: - b = g_value_get_boolean (value); - if (priv->managed != b) - nm_device_set_managed (NM_DEVICE (object), b); - break; case PROP_AUTOCONNECT: b = g_value_get_boolean (value); if (priv->autoconnect != b) diff --git a/libnm/nm-manager.c b/libnm/nm-manager.c index b4111cd040..00ecdccbef 100644 --- a/libnm/nm-manager.c +++ b/libnm/nm-manager.c @@ -369,26 +369,6 @@ update_permissions (NMManager *self, GVariant *permissions) g_list_free (keys); } -static gboolean -get_permissions_sync (NMManager *self, GError **error) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - GVariant *permissions; - - if (nmdbus_manager_call_get_permissions_sync (priv->proxy, - &permissions, - NULL, error)) { - update_permissions (self, permissions); - g_variant_unref (permissions); - return TRUE; - } else { - if (error && *error) - g_dbus_error_strip_remote_error (*error); - update_permissions (self, NULL); - return FALSE; - } -} - static void get_permissions_reply (GObject *object, GAsyncResult *result, @@ -1756,19 +1736,25 @@ constructed (GObject *object) static gboolean init_sync (GInitable *initable, GCancellable *cancellable, GError **error) { - NMManager *manager = NM_MANAGER (initable); - GError *local_error = NULL; + NMManager *self = NM_MANAGER (initable); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + gs_free_error GError *local_error = NULL; + gs_unref_variant GVariant *permissions = NULL; if (!nm_manager_parent_initable_iface->init (initable, cancellable, error)) { /* Never happens. */ g_return_val_if_reached (FALSE); } - if (!get_permissions_sync (manager, &local_error)) { + if (!nmdbus_manager_call_get_permissions_sync (priv->proxy, + &permissions, + NULL, + &local_error)) { + g_dbus_error_strip_remote_error (local_error); g_warning ("Unable to get permissions: %s\n", local_error->message); - g_error_free (local_error); } + update_permissions (self, permissions); return TRUE; } diff --git a/libnm/nm-secret-agent-old.c b/libnm/nm-secret-agent-old.c index 39742c0ea1..3c08987a97 100644 --- a/libnm/nm-secret-agent-old.c +++ b/libnm/nm-secret-agent-old.c @@ -47,7 +47,6 @@ typedef struct { bool registered:1; bool registering:1; - bool private_bus:1; bool session_bus:1; bool auto_register:1; bool suppress_auto:1; @@ -141,12 +140,6 @@ verify_sender (NMSecretAgentOld *self, g_return_val_if_fail (context != NULL, FALSE); - /* Private bus connection is always to NetworkManager, which is always - * UID 0. - */ - if (priv->private_bus) - return TRUE; - /* Verify that the sender is the same as NetworkManager's bus name owner. */ owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (priv->manager_proxy)); @@ -451,8 +444,6 @@ check_nm_running (NMSecretAgentOld *self, GError **error) NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); gs_free char *owner = NULL; - if (priv->private_bus) - return TRUE; owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (priv->manager_proxy)); if (owner) return TRUE; @@ -981,14 +972,10 @@ init_common (NMSecretAgentOld *self) { NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); - priv->private_bus = _nm_dbus_is_connection_private (priv->bus); - - if (priv->private_bus == FALSE) { - priv->session_bus = _nm_dbus_bus_type () == G_BUS_TYPE_SESSION; + priv->session_bus = _nm_dbus_bus_type () == G_BUS_TYPE_SESSION; - g_signal_connect (priv->manager_proxy, "notify::g-name-owner", - G_CALLBACK (name_owner_changed), self); - } + g_signal_connect (priv->manager_proxy, "notify::g-name-owner", + G_CALLBACK (name_owner_changed), self); } typedef struct { @@ -1052,7 +1039,7 @@ init_async_got_bus (GObject *initable, GAsyncResult *result, gpointer user_data) NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (init_data->self); GError *error = NULL; - priv->bus = _nm_dbus_new_connection_finish (result, &error); + priv->bus = g_bus_get_finish (result, &error); if (!priv->bus) { init_async_complete (init_data, error); return; @@ -1150,7 +1137,7 @@ init_sync (GInitable *initable, GCancellable *cancellable, GError **error) NMSecretAgentOld *self = NM_SECRET_AGENT_OLD (initable); NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); - priv->bus = _nm_dbus_new_connection (cancellable, error); + priv->bus = g_bus_get_sync (_nm_dbus_bus_type (), cancellable, error); if (!priv->bus) return FALSE; @@ -1193,7 +1180,10 @@ init_async (GAsyncInitable *initable, int io_priority, if (cancellable) g_simple_async_result_set_check_cancellable (init_data->simple, cancellable); - _nm_dbus_new_connection_async (cancellable, init_async_got_bus, init_data); + g_bus_get (_nm_dbus_bus_type (), + cancellable, + init_async_got_bus, + init_data); } static gboolean diff --git a/shared/meson.build b/shared/meson.build index d542804eb4..aa10f792f8 100644 --- a/shared/meson.build +++ b/shared/meson.build @@ -185,6 +185,7 @@ shared_nm_glib_aux = static_library( 'nm-glib-aux/nm-json-aux.c', 'nm-glib-aux/nm-keyfile-aux.c', 'nm-glib-aux/nm-random-utils.c', + 'nm-glib-aux/nm-ref-string.c', 'nm-glib-aux/nm-secret-utils.c', 'nm-glib-aux/nm-shared-utils.c', 'nm-glib-aux/nm-time-utils.c'), diff --git a/shared/nm-glib-aux/nm-macros-internal.h b/shared/nm-glib-aux/nm-macros-internal.h index 619625942b..5c3b06717e 100644 --- a/shared/nm-glib-aux/nm-macros-internal.h +++ b/shared/nm-glib-aux/nm-macros-internal.h @@ -1975,4 +1975,18 @@ nm_close (int fd) #define NM_PID_T_INVAL ((pid_t) -1) +/*****************************************************************************/ + +NM_AUTO_DEFINE_FCN_VOID0 (GMutex *, _nm_auto_unlock_g_mutex, g_mutex_unlock) + +#define nm_auto_unlock_g_mutex nm_auto (_nm_auto_unlock_g_mutex) + +#define _NM_G_MUTEX_LOCKED(lock, uniq) \ + nm_auto_unlock_g_mutex GMutex *NM_UNIQ_T(nm_lock, uniq) = (lock) + +#define NM_G_MUTEX_LOCKED(lock) \ + _NM_G_MUTEX_LOCKED (lock, NM_UNIQ) + +/*****************************************************************************/ + #endif /* __NM_MACROS_INTERNAL_H__ */ diff --git a/shared/nm-glib-aux/nm-ref-string.c b/shared/nm-glib-aux/nm-ref-string.c new file mode 100644 index 0000000000..6259758c9e --- /dev/null +++ b/shared/nm-glib-aux/nm-ref-string.c @@ -0,0 +1,187 @@ +// SPDX-License-Identifier: LGPL-2.1+ + +#include "nm-default.h" + +#include "nm-ref-string.h" + +/*****************************************************************************/ + +typedef struct { + NMRefString r; + volatile int ref_count; + char str_data[]; +} RefString; + +G_LOCK_DEFINE_STATIC (gl_lock); +static GHashTable *gl_hash; + +/* the first field of NMRefString is a pointer to the NUL terminated string. + * This also allows to compare strings with nm_pstr_equal(), although, pointer + * equality might be better. */ +G_STATIC_ASSERT (G_STRUCT_OFFSET (NMRefString, str) == 0); +G_STATIC_ASSERT (G_STRUCT_OFFSET (RefString, r) == 0); +G_STATIC_ASSERT (G_STRUCT_OFFSET (RefString, r.str) == 0); + +/*****************************************************************************/ + +static guint +_ref_string_hash (gconstpointer ptr) +{ + const RefString *a = ptr; + NMHashState h; + + nm_hash_init (&h, 1463435489u); + nm_hash_update (&h, a->r.str, a->r.len); + return nm_hash_complete (&h); +} + +static gboolean +_ref_string_equal (gconstpointer pa, gconstpointer pb) +{ + const RefString *a = pa; + const RefString *b = pb; + + return a->r.len == b->r.len + && memcmp (a->r.str, b->r.str, a->r.len) == 0; +} + +/*****************************************************************************/ + +static void +_ASSERT (const RefString *rstr0) +{ + int r; + + nm_assert (rstr0); + + G_LOCK (gl_lock); + r = g_atomic_int_get (&rstr0->ref_count); + + nm_assert (r > 0); + nm_assert (r < G_MAXINT); + + nm_assert (rstr0 == g_hash_table_lookup (gl_hash, rstr0)); + G_UNLOCK (gl_lock); +} + +/** + * nm_ref_string_new_len: + * @cstr: the string to intern. Must contain @len bytes. + * If @len is zero, @cstr may be %NULL. Note that it is + * accetable that the string contains a NUL character + * within the first @len bytes. That is, the string is + * not treated as a NUL terminated string, but as binary. + * Also, contrary to strncpy(), this will read all the + * first @len bytes. It won't stop at the first NUL. + * @len: the length of the string (usually there is no NUL character + * within the first @len bytes, but that would be acceptable as well + * to add binary data). + * + * Note that the resulting NMRefString instance will always be NUL terminated + * (at position @len). + * + * Note that NMRefString are always interned/deduplicated. If such a string + * already exists, the existing instance will be refered and returned. + * + * + * Since all NMRefString are shared and interned, you may use + * pointer equality to compare them. Note that if a NMRefString contains + * a NUL character (meaning, if + * + * strlen (nm_ref_string_get_str (str)) != nm_ref_string_get_len (str) + * + * ), then pointer in-equality does not mean that the NUL terminated strings + * are also unequal. In other words, for strings that contain NUL characters, + * + * if (str1 != str2) + * assert (!nm_streq0 (nm_ref_string_get_str (str1), nm_ref_string_get_str (str2))); + * + * might not hold! + * + * + * NMRefString is thread-safe. + * + * Returns: (transfer full): the interned string. This is + * never %NULL, but note that %NULL is also a valid NMRefString. + * The result must be unrefed with nm_ref_string_unref(). + */ +NMRefString * +nm_ref_string_new_len (const char *cstr, gsize len) +{ + RefString *rstr0; + + G_LOCK (gl_lock); + + if (G_UNLIKELY (!gl_hash)) { + gl_hash = g_hash_table_new_full (_ref_string_hash, _ref_string_equal, g_free, NULL); + rstr0 = NULL; + } else { + NMRefString rr_lookup = { + .len = len, + .str = cstr, + }; + + rstr0 = g_hash_table_lookup (gl_hash, &rr_lookup); + } + + if (rstr0) { + nm_assert (({ + int r = g_atomic_int_get (&rstr0->ref_count); + + (r >= 0 && r < G_MAXINT); + })); + g_atomic_int_inc (&rstr0->ref_count); + } else { + rstr0 = g_malloc (sizeof (RefString) + 1 + len); + rstr0->ref_count = 1; + *((gsize *) rstr0->r.len) = len; + *((const char **) rstr0->r.str) = rstr0->str_data; + if (len > 0) + memcpy (rstr0->str_data, cstr, len); + rstr0->str_data[len] = '\0'; + + if (!g_hash_table_add (gl_hash, rstr0)) + nm_assert_not_reached (); + } + + G_UNLOCK (gl_lock); + + return &rstr0->r; +} + +NMRefString * +nm_ref_string_ref (NMRefString *rstr) +{ + RefString *const rstr0 = (RefString *) rstr; + + if (!rstr) + return NULL; + + _ASSERT (rstr0); + + g_atomic_int_inc (&rstr0->ref_count); + return &rstr0->r; +} + +void +_nm_ref_string_unref_non_null (NMRefString *rstr) +{ + RefString *const rstr0 = (RefString *) rstr; + + _ASSERT (rstr0); + + if (G_LIKELY (!g_atomic_int_dec_and_test (&rstr0->ref_count))) + return; + + G_LOCK (gl_lock); + + /* in the fast-path above, we already decremented the ref-count to zero. + * We need recheck that the ref-count is still zero. */ + + if (g_atomic_int_get (&rstr0->ref_count) == 0) + g_hash_table_remove (gl_hash, rstr0); + + G_UNLOCK (gl_lock); +} + +/*****************************************************************************/ diff --git a/shared/nm-glib-aux/nm-ref-string.h b/shared/nm-glib-aux/nm-ref-string.h new file mode 100644 index 0000000000..2a0b072df8 --- /dev/null +++ b/shared/nm-glib-aux/nm-ref-string.h @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: LGPL-2.1+ + +#ifndef __NM_REF_STRING_H__ +#define __NM_REF_STRING_H__ + +/*****************************************************************************/ + +typedef struct { + const char *const str; + const gsize len; +} NMRefString; + +/*****************************************************************************/ + +NMRefString *nm_ref_string_new_len (const char *cstr, gsize len); + +static inline NMRefString * +nm_ref_string_new (const char *cstr) +{ + return cstr + ? nm_ref_string_new_len (cstr, strlen (cstr)) + : NULL; +} + +NMRefString *nm_ref_string_ref (NMRefString *rstr); +void _nm_ref_string_unref_non_null (NMRefString *rstr); + +static inline void +nm_ref_string_unref (NMRefString *rstr) +{ + if (rstr) + _nm_ref_string_unref_non_null (rstr); +} + +NM_AUTO_DEFINE_FCN_VOID0 (NMRefString *, _nm_auto_ref_string, _nm_ref_string_unref_non_null) +#define nm_auto_ref_string nm_auto(_nm_auto_ref_string) + +/*****************************************************************************/ + +static inline const char * +nm_ref_string_get_str (NMRefString *rstr) +{ + return rstr ? rstr->str : NULL; +} + +static inline gsize +nm_ref_string_get_len (NMRefString *rstr) +{ + return rstr ? rstr->len : 0u; +} + +#endif /* __NM_REF_STRING_H__ */ |