diff options
author | Aleksander Morgado <aleksander@aleksander.es> | 2021-12-11 15:06:42 +0100 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2021-12-13 09:35:28 +0000 |
commit | 029ea68ce4924dc235d7f3e91f48ec744dd78c1f (patch) | |
tree | b0e1e9be0af3163572439b3f6cb8d2b03797fc9d | |
parent | 9fc3d15d29678585b2a120f944ec765dcbbf3293 (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.xml | 10 | ||||
-rw-r--r-- | src/mm-base-bearer.c | 198 |
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 |