diff options
author | Aleksander Morgado <aleksander@lanedo.com> | 2012-07-20 12:24:13 +0200 |
---|---|---|
committer | Aleksander Morgado <aleksander@lanedo.com> | 2012-08-06 20:07:26 +0200 |
commit | 63a45f808260f3138b595bf9b250d2a212cb83d4 (patch) | |
tree | aa2a7ab7920490ec3ced9a27890ef82ea15e4a90 | |
parent | d065dd572b3abb5e76467abe1140bf2010fe6fbb (diff) |
hso: avoid trying to use an already freed context
In the connection sequence, we keep the context in the private info of the
Bearer object, so that we can complete and free it when we receive OWANCALL
unsolicited messages. Now, the reply of the OWANCALL itself may get processed
as an unsolicited message, so effectively we're processing and finishing the
connection/disconnection context *before* we process the reply of the AT
command.
This patch ensures that we do not try to re-use the connection context after it
has been processed by the unsolicited messages handler.
-rw-r--r-- | plugins/option/mm-broadband-bearer-hso.c | 48 |
1 files changed, 33 insertions, 15 deletions
diff --git a/plugins/option/mm-broadband-bearer-hso.c b/plugins/option/mm-broadband-bearer-hso.c index 561c11fc..0d163024 100644 --- a/plugins/option/mm-broadband-bearer-hso.c +++ b/plugins/option/mm-broadband-bearer-hso.c @@ -332,7 +332,7 @@ mm_broadband_bearer_hso_report_connection_status (MMBroadbandBearerHso *self, self->priv->connect_pending_id = 0; } - if (self->priv->connect_cancellable_id) { + if (ctx && self->priv->connect_cancellable_id) { g_cancellable_disconnect (ctx->cancellable, self->priv->connect_cancellable_id); self->priv->connect_cancellable_id = 0; @@ -456,10 +456,24 @@ connect_cancelled_cb (GCancellable *cancellable, static void activate_ready (MMBaseModem *modem, GAsyncResult *res, - Dial3gppContext *ctx) + MMBroadbandBearerHso *self) { + Dial3gppContext *ctx; GError *error = NULL; + /* Try to recover the connection context. If none found, it means the + * context was already completed and we have nothing else to do. */ + ctx = self->priv->connect_pending; + + if (!ctx) { + mm_dbg ("Connection context was finished already by an unsolicited message"); + + /* Run _finish() to finalize the async call, even if we don't care + * the result */ + mm_base_modem_at_command_full_finish (modem, res, NULL); + return; + } + /* From now on, if we get cancelled, we'll need to run the connection * reset ourselves just in case */ @@ -471,13 +485,13 @@ activate_ready (MMBaseModem *modem, /* We will now setup a timeout so that we don't wait forever to get the * connection on */ - ctx->self->priv->connect_pending_id = g_timeout_add_seconds (30, - (GSourceFunc)connect_timed_out_cb, - ctx->self); - ctx->self->priv->connect_cancellable_id = g_cancellable_connect (ctx->cancellable, - G_CALLBACK (connect_cancelled_cb), - ctx->self, - NULL); + self->priv->connect_pending_id = g_timeout_add_seconds (30, + (GSourceFunc)connect_timed_out_cb, + self); + self->priv->connect_cancellable_id = g_cancellable_connect (ctx->cancellable, + G_CALLBACK (connect_cancelled_cb), + self, + NULL); } static void authenticate (Dial3gppContext *ctx); @@ -503,6 +517,15 @@ authenticate_ready (MMBaseModem *modem, /* Store which auth command worked, for next attempts */ ctx->self->priv->auth_idx = ctx->auth_idx; + /* The unsolicited response to AT_OWANCALL may come before the OK does. + * We will keep the connection context in the bearer private data so + * that it is accessible from the unsolicited message handler. Note + * also that we do NOT pass the ctx to the GAsyncReadyCallback, as it + * may not be valid any more when the callback is called (it may be + * already completed in the unsolicited handling) */ + g_assert (ctx->self->priv->connect_pending == NULL); + ctx->self->priv->connect_pending = ctx; + /* Success, activate the PDP context and start the data session */ command = g_strdup_printf ("AT_OWANCALL=%d,1,1", ctx->cid); @@ -513,13 +536,8 @@ authenticate_ready (MMBaseModem *modem, FALSE, NULL, /* cancellable */ (GAsyncReadyCallback)activate_ready, - ctx); + ctx->self); /* we pass the bearer object! */ g_free (command); - - /* We will now keep the context in the bearer's private. - * Reports of modem being connected will arrive via unsolicited messages. */ - g_assert (ctx->self->priv->connect_pending == NULL); - ctx->self->priv->connect_pending = ctx; } const gchar *auth_commands[] = { |