aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--plugins/icera/mm-broadband-bearer-icera.c103
1 files changed, 76 insertions, 27 deletions
diff --git a/plugins/icera/mm-broadband-bearer-icera.c b/plugins/icera/mm-broadband-bearer-icera.c
index f2b60926..ba64aa90 100644
--- a/plugins/icera/mm-broadband-bearer-icera.c
+++ b/plugins/icera/mm-broadband-bearer-icera.c
@@ -504,6 +504,7 @@ typedef struct {
GCancellable *cancellable;
GSimpleAsyncResult *result;
guint authentication_retries;
+ GError *saved_error;
} Dial3gppContext;
static Dial3gppContext *
@@ -612,20 +613,31 @@ connect_timed_out_cb (MMBroadbandBearerIcera *self)
{
Dial3gppContext *ctx;
- /* Recover context and remove cancellation */
+ /* Recover context and remove it from the private info */
ctx = self->priv->connect_pending;
+ self->priv->connect_pending = NULL;
- g_cancellable_disconnect (ctx->cancellable,
- self->priv->connect_cancellable_id);
+ /* Remove cancellation, if found */
+ if (self->priv->connect_cancellable_id) {
+ g_cancellable_disconnect (ctx->cancellable,
+ self->priv->connect_cancellable_id);
+ self->priv->connect_cancellable_id = 0;
+ }
- self->priv->connect_pending = NULL;
+ /* Cleanup timeout ID */
self->priv->connect_pending_id = 0;
- self->priv->connect_cancellable_id = 0;
- g_simple_async_result_set_error (ctx->result,
- MM_MOBILE_EQUIPMENT_ERROR,
- MM_MOBILE_EQUIPMENT_ERROR_NETWORK_TIMEOUT,
- "Connection attempt timed out");
+ /* If we were cancelled, prefer that error */
+ if (ctx->saved_error) {
+ g_simple_async_result_take_error (ctx->result, ctx->saved_error);
+ ctx->saved_error = NULL;
+ } else
+ g_simple_async_result_set_error (ctx->result,
+ MM_MOBILE_EQUIPMENT_ERROR,
+ MM_MOBILE_EQUIPMENT_ERROR_NETWORK_TIMEOUT,
+ "Connection attempt timed out");
+
+ /* It's probably pointless to try to reset this here, but anyway... */
connect_reset (ctx);
return FALSE;
@@ -635,22 +647,23 @@ static void
connect_cancelled_cb (GCancellable *cancellable,
MMBroadbandBearerIcera *self)
{
- GError *error = NULL;
Dial3gppContext *ctx;
- /* Recover context and remove timeout */
+ /* Recover context but DON'T remove it from the private info */
ctx = self->priv->connect_pending;
- g_source_remove (self->priv->connect_pending_id);
-
- self->priv->connect_pending = NULL;
- self->priv->connect_pending_id = 0;
+ /* Remove the cancellable
+ * NOTE: we shouldn't remove the timeout yet. We still need to wait
+ * to get connected before running the explicit connection reset */
+ g_cancellable_disconnect (ctx->cancellable,
+ self->priv->connect_cancellable_id);
self->priv->connect_cancellable_id = 0;
- g_assert (dial_3gpp_context_set_error_if_cancelled (ctx, &error));
+ /* Store cancelled error */
+ g_assert (dial_3gpp_context_set_error_if_cancelled (ctx, &ctx->saved_error));
- g_simple_async_result_take_error (ctx->result, error);
- connect_reset (ctx);
+ /* We cannot reset right here, we need to wait for the connection
+ * attempt to finish */
}
static void
@@ -693,7 +706,7 @@ report_connect_status (MMBroadbandBearerIcera *self,
{
Dial3gppContext *ctx;
- /* Recover context */
+ /* Recover context and remove it from the private info */
ctx = self->priv->connect_pending;
self->priv->connect_pending = NULL;
@@ -711,13 +724,26 @@ report_connect_status (MMBroadbandBearerIcera *self,
switch (status) {
case MM_BROADBAND_BEARER_ICERA_CONNECTION_STATUS_UNKNOWN:
- g_warn_if_reached ();
break;
case MM_BROADBAND_BEARER_ICERA_CONNECTION_STATUS_CONNECTED:
if (!ctx)
+ /* We may get this if the timeout for the connection attempt is
+ * reached before the unsolicited response. We should probably
+ * keep the CID around to request explicit disconnection in this
+ * case. */
break;
+ /* If we wanted to get cancelled before, do it now */
+ if (ctx->saved_error) {
+ /* Keep error */
+ g_simple_async_result_take_error (ctx->result, ctx->saved_error);
+ ctx->saved_error = NULL;
+ /* Cancel connection */
+ connect_reset (ctx);
+ return;
+ }
+
g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
dial_3gpp_context_complete_and_free (ctx);
return;
@@ -726,6 +752,15 @@ report_connect_status (MMBroadbandBearerIcera *self,
if (!ctx)
break;
+ /* If we wanted to get cancelled before and now we couldn't connect,
+ * use the cancelled error and return */
+ if (ctx->saved_error) {
+ g_simple_async_result_take_error (ctx->result, ctx->saved_error);
+ ctx->saved_error = NULL;
+ dial_3gpp_context_complete_and_free (ctx);
+ return;
+ }
+
/* Try to gather additional info about the connection failure */
mm_base_modem_at_command_full (
ctx->modem,
@@ -741,17 +776,29 @@ report_connect_status (MMBroadbandBearerIcera *self,
case MM_BROADBAND_BEARER_ICERA_CONNECTION_STATUS_DISCONNECTED:
if (ctx) {
+ /* If we wanted to get cancelled before and now we couldn't connect,
+ * use the cancelled error and return */
+ if (ctx->saved_error) {
+ g_simple_async_result_take_error (ctx->result, ctx->saved_error);
+ ctx->saved_error = NULL;
+ dial_3gpp_context_complete_and_free (ctx);
+ return;
+ }
+
g_simple_async_result_set_error (ctx->result,
MM_CORE_ERROR,
MM_CORE_ERROR_FAILED,
"Call setup failed");
dial_3gpp_context_complete_and_free (ctx);
- } else {
- /* Just ensure we mark ourselves as being disconnected... */
- mm_bearer_report_disconnection (MM_BEARER (self));
+ return;
}
- break;
+
+ /* Just ensure we mark ourselves as being disconnected... */
+ mm_bearer_report_disconnection (MM_BEARER (self));
+ return;
}
+
+ g_warn_if_reached ();
}
static void
@@ -787,13 +834,15 @@ activate_ready (MMBaseModem *modem,
}
/* We will now setup a timeout and keep the context in the bearer's private.
- * Reports of modem being connected will arrive via unsolicited messages. */
+ * Reports of modem being connected will arrive via unsolicited messages.
+ * This timeout should be long enough. Actually... ideally should never get
+ * reached. */
self->priv->connect_pending_id = g_timeout_add_seconds (60,
(GSourceFunc)connect_timed_out_cb,
self);
- /* From now on, if we get cancelled, we'll need to run the connection
- * reset ourselves just in case */
+ /* From now on, if we get cancelled, we'll still need to wait for the connection
+ * attempt to finish before resetting it */
self->priv->connect_cancellable_id = g_cancellable_connect (ctx->cancellable,
G_CALLBACK (connect_cancelled_cb),
self,