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.
This commit is contained in:
@@ -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
|
||||
-->
|
||||
|
@@ -389,25 +389,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_ready (MMBaseBearer *self,
|
||||
GAsyncResult *res,
|
||||
GTask *task)
|
||||
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;
|
||||
gboolean launch_disconnect = FALSE;
|
||||
MMBearerConnectResult *result;
|
||||
|
||||
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)
|
||||
{
|
||||
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 (
|
||||
mm_obj_dbg (self, "connected");
|
||||
g_task_set_task_data (task, g_steal_pointer (&result), (GDestroyNotify)mm_bearer_connect_result_unref);
|
||||
|
||||
/* 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,
|
||||
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);
|
||||
(GAsyncReadyCallback)reload_stats_supported_ready,
|
||||
task);
|
||||
return;
|
||||
}
|
||||
|
||||
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 (
|
||||
self,
|
||||
(GAsyncReadyCallback)disconnect_after_cancel_ready,
|
||||
NULL);
|
||||
}
|
||||
|
||||
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
|
||||
|
Reference in New Issue
Block a user