diff options
author | Aleksander Morgado <aleksander@aleksander.es> | 2021-05-17 21:33:32 +0200 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2021-05-23 01:22:07 +0200 |
commit | de6b1324cb80413e552806f75c70be72cc41e933 (patch) | |
tree | 8f20a6bfc9a1ae4f4288e11a77aa54d1d178d8ce /libmm-glib/mm-bearer.c | |
parent | ff45d292ee75b0e49c3de3677211218445659884 (diff) |
api,bearer: new 'ConnectionError' property
This new property will provide detailed information about the failed
connection attempt, or about the network initiated disconnection. The
property will be cleared only if a new connection attempt is
triggered, and so it can be used to investigate why a given attempt
failed without needing to be the one who triggered the attempt (e.g.
so that failures in NetworkManager-triggered connection attempts can
be investigated looking at the DBus API).
The property is built as a (ss) tuple, but the libmm-glib interface
provides methods to read this property as a GError.
Diffstat (limited to 'libmm-glib/mm-bearer.c')
-rw-r--r-- | libmm-glib/mm-bearer.c | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/libmm-glib/mm-bearer.c b/libmm-glib/mm-bearer.c index 1c6a1cdd..cc50244c 100644 --- a/libmm-glib/mm-bearer.c +++ b/libmm-glib/mm-bearer.c @@ -22,6 +22,7 @@ */ #include "mm-helpers.h" +#include "mm-common-helpers.h" #include "mm-bearer.h" /** @@ -58,6 +59,11 @@ struct _MMBearerPrivate { GMutex stats_mutex; guint stats_id; MMBearerStats *stats; + + /* Connection error */ + GMutex connection_error_mutex; + guint connection_error_id; + GError *connection_error; }; /*****************************************************************************/ @@ -757,6 +763,116 @@ mm_bearer_peek_stats (MMBearer *self) /*****************************************************************************/ +static void +connection_error_updated (MMBearer *self, + GParamSpec *pspec) +{ + g_mutex_lock (&self->priv->connection_error_mutex); + { + GVariant *tuple; + + g_clear_error (&self->priv->connection_error); + + tuple = mm_gdbus_bearer_get_connection_error (MM_GDBUS_BEARER (self)); + if (tuple) { + g_autoptr(GError) error = NULL; + + self->priv->connection_error = mm_common_error_from_tuple (tuple, &error); + if (error) + g_warning ("Invalid bearer connection error update received: %s", error->message); + } + } + g_mutex_unlock (&self->priv->connection_error_mutex); +} + +static void +ensure_internal_connection_error (MMBearer *self, + GError **dup) +{ + g_mutex_lock (&self->priv->connection_error_mutex); + { + /* If this is the first time ever asking for the object, setup the + * update listener and the initial object, if any. */ + if (!self->priv->connection_error_id) { + g_autoptr(GVariant) tuple = NULL; + + tuple = mm_gdbus_bearer_dup_connection_error (MM_GDBUS_BEARER (self)); + if (tuple) { + g_autoptr(GError) error = NULL; + + self->priv->connection_error = mm_common_error_from_tuple (tuple, &error); + if (error) + g_warning ("Invalid bearer connection error: %s", error->message); + } + + /* No need to clear this signal connection when freeing self */ + self->priv->connection_error_id = + g_signal_connect (self, + "notify::connection-error", + G_CALLBACK (connection_error_updated), + NULL); + } + + if (dup && self->priv->connection_error) + *dup = g_error_copy (self->priv->connection_error); + } + g_mutex_unlock (&self->priv->connection_error_mutex); +} + +/** + * mm_bearer_get_connection_error: + * @self: A #MMBearer. + * + * Gets a #GError specifying the connection error details, if any. + * + * <warning>The values reported by @self are not updated when the values in the + * interface change. Instead, the client is expected to call + * mm_bearer_get_connection_error() again to get a new #GError with the + * new values.</warning> + * + * Returns: (transfer full): A #GError that must be freed with + * g_error_free() or %NULL if none. + * + * Since: 1.18 + */ +GError * +mm_bearer_get_connection_error (MMBearer *self) +{ + GError *error = NULL; + + g_return_val_if_fail (MM_IS_BEARER (self), NULL); + + ensure_internal_connection_error (self, &error); + return error; +} + +/** + * mm_bearer_peek_connection_error: + * @self: A #MMBearer. + * + * Gets a #GError specifying the connection error details, if any. + * + * <warning>The returned value is only valid until the property changes so + * it is only safe to use this function on the thread where + * @self was constructed. Use mm_bearer_get_connection_error() if on another + * thread.</warning> + * + * Returns: (transfer none): A #GError, or %NULL if none. Do not + * free the returned value, it belongs to @self. + * + * Since: 1.18 + */ +GError * +mm_bearer_peek_connection_error (MMBearer *self) +{ + g_return_val_if_fail (MM_IS_BEARER (self), NULL); + + ensure_internal_connection_error (self, NULL); + return self->priv->connection_error; +} + +/*****************************************************************************/ + /** * mm_bearer_connect_finish: * @self: A #MMBearer. @@ -932,6 +1048,7 @@ mm_bearer_init (MMBearer *self) g_mutex_init (&self->priv->ipv6_config_mutex); g_mutex_init (&self->priv->properties_mutex); g_mutex_init (&self->priv->stats_mutex); + g_mutex_init (&self->priv->connection_error_mutex); } static void @@ -943,6 +1060,7 @@ finalize (GObject *object) g_mutex_clear (&self->priv->ipv6_config_mutex); g_mutex_clear (&self->priv->properties_mutex); g_mutex_clear (&self->priv->stats_mutex); + g_mutex_clear (&self->priv->connection_error_mutex); G_OBJECT_CLASS (mm_bearer_parent_class)->finalize (object); } @@ -956,6 +1074,7 @@ dispose (GObject *object) g_clear_object (&self->priv->ipv6_config); g_clear_object (&self->priv->properties); g_clear_object (&self->priv->stats); + g_clear_error (&self->priv->connection_error); G_OBJECT_CLASS (mm_bearer_parent_class)->dispose (object); } |