aboutsummaryrefslogtreecommitdiff
path: root/src/mm-base-bearer.c
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 /src/mm-base-bearer.c
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.
Diffstat (limited to 'src/mm-base-bearer.c')
-rw-r--r--src/mm-base-bearer.c198
1 files changed, 109 insertions, 89 deletions
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