aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@aleksander.es>2021-12-11 15:06:42 +0100
committerAleksander Morgado <aleksander@aleksander.es>2021-12-13 09:35:28 +0000
commit029ea68ce4924dc235d7f3e91f48ec744dd78c1f (patch)
treeb0e1e9be0af3163572439b3f6cb8d2b03797fc9d
parent9fc3d15d29678585b2a120f944ec765dcbbf3293 (diff)
base-bearer: make sure 'ReloadStatsSupported' is set before transitioning to 'Connected'
By the time we report the bearer as 'Connected', the DBus client should also be able to know right away the value of 'ReloadStatsSupported', instead of needing to wait for it to be updated asynchronously. This logic adds one additional step in the generic connection sequence for this purpose, which is run after the modem is connected but before we report the state change via DBus.
-rw-r--r--introspection/org.freedesktop.ModemManager1.Bearer.xml10
-rw-r--r--src/mm-base-bearer.c198
2 files changed, 118 insertions, 90 deletions
diff --git a/introspection/org.freedesktop.ModemManager1.Bearer.xml b/introspection/org.freedesktop.ModemManager1.Bearer.xml
index de306a61..07cab833 100644
--- a/introspection/org.freedesktop.ModemManager1.Bearer.xml
+++ b/introspection/org.freedesktop.ModemManager1.Bearer.xml
@@ -381,7 +381,15 @@
<!--
ReloadStatsSupported:
- Indicates whether or not the bearer support getting rx and tx bytes statistics.
+ Indicates whether reloading ongoing statistics is supported or not.
+
+ This property applies exclusively to the statistics that are queried from
+ the modem periodically; i.e. "rx-bytes", "tx-bytes", "uplink-speed" and
+ "downlink-speed".
+
+ The property is initialized to a fixed value as soon as the first
+ connection attempt has successfully finished. Reading this value before
+ the first successful connection attempt will always report %FALSE.
Since: 1.20
-->
diff --git a/src/mm-base-bearer.c b/src/mm-base-bearer.c
index 344a5e78..cd6365ac 100644
--- a/src/mm-base-bearer.c
+++ b/src/mm-base-bearer.c
@@ -390,25 +390,6 @@ bearer_stats_stop (MMBaseBearer *self)
}
static void
-reload_stats_supported_ready (MMBaseBearer *self,
- GAsyncResult *res)
-{
- GError *error = NULL;
- guint64 rx_bytes = 0;
- guint64 tx_bytes = 0;
-
- MM_BASE_BEARER_GET_CLASS (self)->reload_stats_finish (self, &rx_bytes, &tx_bytes, res, &error);
- if (!error) {
- mm_obj_info (self, "reloading stats is supported by the device");
- self->priv->reload_stats_supported = TRUE;
- mm_gdbus_bearer_set_reload_stats_supported (MM_GDBUS_BEARER (self), self->priv->reload_stats_supported);
- } else {
- mm_obj_info (self, "reloading stats is not supported by the device");
- g_clear_error (&error);
- }
-}
-
-static void
reload_stats_ready (MMBaseBearer *self,
GAsyncResult *res)
{
@@ -589,15 +570,6 @@ bearer_update_status_connected (MMBaseBearer *self,
self->priv->status = MM_BEARER_STATUS_CONNECTED;
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_STATUS]);
- /* Check that reload statistics is supported by the device */
- if (MM_BASE_BEARER_GET_CLASS (self)->reload_stats &&
- MM_BASE_BEARER_GET_CLASS (self)->reload_stats_finish) {
- MM_BASE_BEARER_GET_CLASS (self)->reload_stats (
- self,
- (GAsyncReadyCallback)reload_stats_supported_ready,
- NULL);
- }
-
/* Start statistics */
bearer_stats_start (self, uplink_speed, downlink_speed);
@@ -864,23 +836,46 @@ reset_signal_handlers (MMBaseBearer *self)
/* CONNECT */
gboolean
-mm_base_bearer_connect_finish (MMBaseBearer *self,
- GAsyncResult *res,
- GError **error)
+mm_base_bearer_connect_finish (MMBaseBearer *self,
+ GAsyncResult *res,
+ GError **error)
{
return g_task_propagate_boolean (G_TASK (res), error);
}
static void
+connect_succeeded (MMBaseBearer *self,
+ GTask *task)
+{
+ MMBearerConnectResult *result;
+
+ result = g_task_get_task_data (task);
+
+ /* Update bearer and interface status */
+ bearer_update_status_connected (
+ self,
+ mm_port_get_device (mm_bearer_connect_result_peek_data (result)),
+ mm_bearer_connect_result_get_multiplexed (result),
+ mm_bearer_connect_result_get_profile_id (result),
+ mm_bearer_connect_result_peek_ipv4_config (result),
+ mm_bearer_connect_result_peek_ipv6_config (result),
+ mm_bearer_connect_result_get_uplink_speed (result),
+ mm_bearer_connect_result_get_downlink_speed (result));
+
+ g_clear_object (&self->priv->connect_cancellable);
+
+ g_task_return_boolean (task, TRUE);
+ g_object_unref (task);
+}
+
+static void
disconnect_after_cancel_ready (MMBaseBearer *self,
GAsyncResult *res)
{
- GError *error = NULL;
+ g_autoptr(GError) error = NULL;
- if (!MM_BASE_BEARER_GET_CLASS (self)->disconnect_finish (self, res, &error)) {
+ if (!MM_BASE_BEARER_GET_CLASS (self)->disconnect_finish (self, res, &error))
mm_obj_warn (self, "error disconnecting: %s; will assume disconnected anyway", error->message);
- g_error_free (error);
- }
else
mm_obj_dbg (self, "disconnected bearer '%s'", self->priv->path);
@@ -893,13 +888,72 @@ disconnect_after_cancel_ready (MMBaseBearer *self,
}
static void
+connect_failed (MMBaseBearer *self,
+ GTask *task,
+ GError *error)
+{
+ /* Update failed attempts */
+ mm_bearer_stats_set_failed_attempts (self->priv->stats,
+ mm_bearer_stats_get_failed_attempts (self->priv->stats) + 1);
+ bearer_update_interface_stats (self);
+
+ /* Update reported connection error before the status update */
+ bearer_update_connection_error (self, error);
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+ bearer_update_status (self, MM_BEARER_STATUS_DISCONNECTING);
+ MM_BASE_BEARER_GET_CLASS (self)->disconnect (self,
+ (GAsyncReadyCallback)disconnect_after_cancel_ready,
+ NULL);
+ } else
+ bearer_update_status (self, MM_BEARER_STATUS_DISCONNECTED);
+
+ g_clear_object (&self->priv->connect_cancellable);
+
+ g_task_return_error (task, error);
+ g_object_unref (task);
+}
+
+static gboolean
+connect_check_cancel (MMBaseBearer *self,
+ GTask *task)
+{
+ GError *error = NULL;
+
+ if (!g_cancellable_is_cancelled (self->priv->connect_cancellable))
+ return FALSE;
+
+ mm_obj_dbg (self, "connected, but need to disconnect");
+ error = g_error_new (G_IO_ERROR, G_IO_ERROR_CANCELLED,
+ "Bearer got connected, but had to disconnect after cancellation request");
+ connect_failed (self, task, error);
+ return TRUE;
+}
+
+static void
+reload_stats_supported_ready (MMBaseBearer *self,
+ GAsyncResult *res,
+ GTask *task)
+{
+ if (MM_BASE_BEARER_GET_CLASS (self)->reload_stats_finish (self, NULL, NULL, res, NULL)) {
+ mm_obj_info (self, "reloading stats is supported by the device");
+ self->priv->reload_stats_supported = TRUE;
+ mm_gdbus_bearer_set_reload_stats_supported (MM_GDBUS_BEARER (self), self->priv->reload_stats_supported);
+ } else
+ mm_obj_info (self, "reloading stats is not supported by the device");
+
+ if (connect_check_cancel (self, task))
+ return;
+
+ connect_succeeded (self, task);
+}
+
+static void
connect_ready (MMBaseBearer *self,
GAsyncResult *res,
- GTask *task)
+ GTask *task)
{
- GError *error = NULL;
- gboolean launch_disconnect = FALSE;
- MMBearerConnectResult *result;
+ GError *error = NULL;
+ g_autoptr(MMBearerConnectResult) result = NULL;
/* NOTE: connect() implementations *MUST* handle cancellations themselves */
result = MM_BASE_BEARER_GET_CLASS (self)->connect_finish (self, res, &error);
@@ -907,63 +961,29 @@ connect_ready (MMBaseBearer *self,
mm_obj_warn (self, "connection attempt #%u failed: %s",
mm_bearer_stats_get_attempts (self->priv->stats),
error->message);
-
- /* Update failed attempts */
- mm_bearer_stats_set_failed_attempts (self->priv->stats,
- mm_bearer_stats_get_failed_attempts (self->priv->stats) + 1);
- bearer_update_interface_stats (self);
-
- if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
- /* Will launch disconnection */
- launch_disconnect = TRUE;
- } else {
- /* Update reported connection error before the status update */
- bearer_update_connection_error (self, error);
- bearer_update_status (self, MM_BEARER_STATUS_DISCONNECTED);
- }
+ connect_failed (self, task, error);
+ return;
}
+
/* Handle cancellations detected after successful connection */
- else if (g_cancellable_is_cancelled (self->priv->connect_cancellable)) {
- mm_obj_dbg (self, "connected, but need to disconnect");
- mm_bearer_connect_result_unref (result);
- error = g_error_new (G_IO_ERROR, G_IO_ERROR_CANCELLED,
- "Bearer got connected, but had to disconnect after cancellation request");
- launch_disconnect = TRUE;
- }
- else {
- mm_obj_dbg (self, "connected");
+ if (connect_check_cancel (self, task))
+ return;
- /* Update bearer and interface status */
- bearer_update_status_connected (
- self,
- mm_port_get_device (mm_bearer_connect_result_peek_data (result)),
- mm_bearer_connect_result_get_multiplexed (result),
- mm_bearer_connect_result_get_profile_id (result),
- mm_bearer_connect_result_peek_ipv4_config (result),
- mm_bearer_connect_result_peek_ipv6_config (result),
- mm_bearer_connect_result_get_uplink_speed (result),
- mm_bearer_connect_result_get_downlink_speed (result));
- mm_bearer_connect_result_unref (result);
- }
+ mm_obj_dbg (self, "connected");
+ g_task_set_task_data (task, g_steal_pointer (&result), (GDestroyNotify)mm_bearer_connect_result_unref);
- if (launch_disconnect) {
- /* Update reported connection error before the status update */
- bearer_update_connection_error (self, error);
- bearer_update_status (self, MM_BEARER_STATUS_DISCONNECTING);
- MM_BASE_BEARER_GET_CLASS (self)->disconnect (
+ /* Check that reload statistics is supported by the device; we can only do this while
+ * connected. */
+ if (MM_BASE_BEARER_GET_CLASS (self)->reload_stats &&
+ MM_BASE_BEARER_GET_CLASS (self)->reload_stats_finish) {
+ MM_BASE_BEARER_GET_CLASS (self)->reload_stats (
self,
- (GAsyncReadyCallback)disconnect_after_cancel_ready,
- NULL);
+ (GAsyncReadyCallback)reload_stats_supported_ready,
+ task);
+ return;
}
- g_clear_object (&self->priv->connect_cancellable);
-
- if (error)
- g_task_return_error (task, error);
- else
- g_task_return_boolean (task, TRUE);
-
- g_object_unref (task);
+ connect_succeeded (self, task);
}
void