huawei: port disconnect_3gpp to use GTask

This commit is contained in:
Ben Chan
2017-08-01 13:32:08 -07:00
committed by Aleksander Morgado
parent abf9d36183
commit 1ada2d23a5

View File

@@ -551,22 +551,17 @@ typedef enum {
} Disconnect3gppContextStep; } Disconnect3gppContextStep;
typedef struct { typedef struct {
MMBroadbandBearerHuawei *self;
MMBaseModem *modem; MMBaseModem *modem;
MMPortSerialAt *primary; MMPortSerialAt *primary;
GSimpleAsyncResult *result;
Disconnect3gppContextStep step; Disconnect3gppContextStep step;
guint check_count; guint check_count;
guint failed_ndisstatqry_count; guint failed_ndisstatqry_count;
} Disconnect3gppContext; } Disconnect3gppContext;
static void static void
disconnect_3gpp_context_complete_and_free (Disconnect3gppContext *ctx) disconnect_3gpp_context_free (Disconnect3gppContext *ctx)
{ {
g_simple_async_result_complete (ctx->result);
g_object_unref (ctx->result);
g_object_unref (ctx->primary); g_object_unref (ctx->primary);
g_object_unref (ctx->self);
g_object_unref (ctx->modem); g_object_unref (ctx->modem);
g_slice_free (Disconnect3gppContext, ctx); g_slice_free (Disconnect3gppContext, ctx);
} }
@@ -576,25 +571,25 @@ disconnect_3gpp_finish (MMBroadbandBearer *self,
GAsyncResult *res, GAsyncResult *res,
GError **error) GError **error)
{ {
return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error); return g_task_propagate_boolean (G_TASK (res), error);
} }
static void disconnect_3gpp_context_step (Disconnect3gppContext *ctx); static void disconnect_3gpp_context_step (GTask *task);
static gboolean static gboolean
disconnect_retry_ndisstatqry_check_cb (MMBroadbandBearerHuawei *self) disconnect_retry_ndisstatqry_check_cb (MMBroadbandBearerHuawei *self)
{ {
Disconnect3gppContext *ctx; GTask *task;
/* Recover context */ /* Recover context */
ctx = self->priv->disconnect_pending; task = self->priv->disconnect_pending;
g_assert (ctx != NULL); g_assert (task != NULL);
/* Balance refcount */ /* Balance refcount */
g_object_unref (self); g_object_unref (self);
/* Retry same step */ /* Retry same step */
disconnect_3gpp_context_step (ctx); disconnect_3gpp_context_step (task);
return G_SOURCE_REMOVE; return G_SOURCE_REMOVE;
} }
@@ -603,6 +598,7 @@ disconnect_ndisstatqry_check_ready (MMBaseModem *modem,
GAsyncResult *res, GAsyncResult *res,
MMBroadbandBearerHuawei *self) MMBroadbandBearerHuawei *self)
{ {
GTask *task;
Disconnect3gppContext *ctx; Disconnect3gppContext *ctx;
const gchar *response; const gchar *response;
GError *error = NULL; GError *error = NULL;
@@ -611,8 +607,10 @@ disconnect_ndisstatqry_check_ready (MMBaseModem *modem,
gboolean ipv6_available = FALSE; gboolean ipv6_available = FALSE;
gboolean ipv6_connected = FALSE; gboolean ipv6_connected = FALSE;
ctx = self->priv->disconnect_pending; task = self->priv->disconnect_pending;
g_assert (ctx != NULL); g_assert (task != NULL);
ctx = g_task_get_task_data (task);
/* Balance refcount */ /* Balance refcount */
g_object_unref (self); g_object_unref (self);
@@ -635,7 +633,7 @@ disconnect_ndisstatqry_check_ready (MMBaseModem *modem,
if (ipv4_available && !ipv4_connected) { if (ipv4_available && !ipv4_connected) {
/* Success! */ /* Success! */
ctx->step++; ctx->step++;
disconnect_3gpp_context_step (ctx); disconnect_3gpp_context_step (task);
return; return;
} }
@@ -650,42 +648,51 @@ disconnect_ndisdup_ready (MMBaseModem *modem,
GAsyncResult *res, GAsyncResult *res,
MMBroadbandBearerHuawei *self) MMBroadbandBearerHuawei *self)
{ {
GTask *task;
Disconnect3gppContext *ctx; Disconnect3gppContext *ctx;
GError *error = NULL; GError *error = NULL;
ctx = self->priv->disconnect_pending; task = self->priv->disconnect_pending;
g_assert (ctx != NULL); g_assert (task != NULL);
ctx = g_task_get_task_data (task);
/* Balance refcount */ /* Balance refcount */
g_object_unref (self); g_object_unref (self);
if (!mm_base_modem_at_command_full_finish (modem, res, &error)) { if (!mm_base_modem_at_command_full_finish (modem, res, &error)) {
/* Clear context */ /* Clear task */
self->priv->disconnect_pending = NULL; self->priv->disconnect_pending = NULL;
g_simple_async_result_take_error (ctx->result, error); g_task_return_error (task, error);
disconnect_3gpp_context_complete_and_free (ctx); g_object_unref (task);
return; return;
} }
/* Go to next step */ /* Go to next step */
ctx->step++; ctx->step++;
disconnect_3gpp_context_step (ctx); disconnect_3gpp_context_step (task);
} }
static void static void
disconnect_3gpp_context_step (Disconnect3gppContext *ctx) disconnect_3gpp_context_step (GTask *task)
{ {
MMBroadbandBearerHuawei *self;
Disconnect3gppContext *ctx;
self = g_task_get_source_object (task);
ctx = g_task_get_task_data (task);
switch (ctx->step) { switch (ctx->step) {
case DISCONNECT_3GPP_CONTEXT_STEP_FIRST: case DISCONNECT_3GPP_CONTEXT_STEP_FIRST:
/* Store the context */ /* Store the task */
ctx->self->priv->disconnect_pending = ctx; self->priv->disconnect_pending = task;
/* We ignore any pending network-initiated disconnection in order to prevent it /* We ignore any pending network-initiated disconnection in order to prevent it
* from interfering with the client-initiated disconnection, as we would like to * from interfering with the client-initiated disconnection, as we would like to
* proceed with the latter anyway. */ * proceed with the latter anyway. */
if (ctx->self->priv->network_disconnect_pending_id != 0) { if (self->priv->network_disconnect_pending_id != 0) {
g_source_remove (ctx->self->priv->network_disconnect_pending_id); g_source_remove (self->priv->network_disconnect_pending_id);
ctx->self->priv->network_disconnect_pending_id = 0; self->priv->network_disconnect_pending_id = 0;
} }
ctx->step++; ctx->step++;
@@ -700,31 +707,31 @@ disconnect_3gpp_context_step (Disconnect3gppContext *ctx)
FALSE, FALSE,
NULL, NULL,
(GAsyncReadyCallback)disconnect_ndisdup_ready, (GAsyncReadyCallback)disconnect_ndisdup_ready,
g_object_ref (ctx->self)); g_object_ref (self));
return; return;
case DISCONNECT_3GPP_CONTEXT_STEP_NDISSTATQRY: case DISCONNECT_3GPP_CONTEXT_STEP_NDISSTATQRY:
/* If too many retries (1s of wait between the retries), failed */ /* If too many retries (1s of wait between the retries), failed */
if (ctx->check_count > 60) { if (ctx->check_count > 60) {
/* Clear context */ /* Clear task */
ctx->self->priv->disconnect_pending = NULL; self->priv->disconnect_pending = NULL;
g_simple_async_result_set_error (ctx->result, g_task_return_new_error (task,
MM_MOBILE_EQUIPMENT_ERROR, MM_MOBILE_EQUIPMENT_ERROR,
MM_MOBILE_EQUIPMENT_ERROR_NETWORK_TIMEOUT, MM_MOBILE_EQUIPMENT_ERROR_NETWORK_TIMEOUT,
"Disconnection attempt timed out"); "Disconnection attempt timed out");
disconnect_3gpp_context_complete_and_free (ctx); g_object_unref (task);
return; return;
} }
/* Give up if too many unexpected responses to NIDSSTATQRY are encountered. */ /* Give up if too many unexpected responses to NIDSSTATQRY are encountered. */
if (ctx->failed_ndisstatqry_count > 10) { if (ctx->failed_ndisstatqry_count > 10) {
/* Clear context */ /* Clear task */
ctx->self->priv->disconnect_pending = NULL; self->priv->disconnect_pending = NULL;
g_simple_async_result_set_error (ctx->result, g_task_return_new_error (task,
MM_MOBILE_EQUIPMENT_ERROR, MM_MOBILE_EQUIPMENT_ERROR,
MM_MOBILE_EQUIPMENT_ERROR_NOT_SUPPORTED, MM_MOBILE_EQUIPMENT_ERROR_NOT_SUPPORTED,
"Disconnection attempt not supported."); "Disconnection attempt not supported.");
disconnect_3gpp_context_complete_and_free (ctx); g_object_unref (task);
return; return;
} }
@@ -738,21 +745,21 @@ disconnect_3gpp_context_step (Disconnect3gppContext *ctx)
FALSE, FALSE,
NULL, NULL,
(GAsyncReadyCallback)disconnect_ndisstatqry_check_ready, (GAsyncReadyCallback)disconnect_ndisstatqry_check_ready,
g_object_ref (ctx->self)); g_object_ref (self));
return; return;
case DISCONNECT_3GPP_CONTEXT_STEP_LAST: case DISCONNECT_3GPP_CONTEXT_STEP_LAST:
/* Clear context */ /* Clear task */
ctx->self->priv->disconnect_pending = NULL; self->priv->disconnect_pending = NULL;
/* Set data port as result */ /* Set data port as result */
g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); g_task_return_boolean (task, TRUE);
disconnect_3gpp_context_complete_and_free (ctx); g_object_unref (task);
return; return;
} }
} }
static void static void
disconnect_3gpp (MMBroadbandBearer *self, disconnect_3gpp (MMBroadbandBearer *_self,
MMBroadbandModem *modem, MMBroadbandModem *modem,
MMPortSerialAt *primary, MMPortSerialAt *primary,
MMPortSerialAt *secondary, MMPortSerialAt *secondary,
@@ -761,27 +768,27 @@ disconnect_3gpp (MMBroadbandBearer *self,
GAsyncReadyCallback callback, GAsyncReadyCallback callback,
gpointer user_data) gpointer user_data)
{ {
MMBroadbandBearerHuawei *self = MM_BROADBAND_BEARER_HUAWEI (_self);
Disconnect3gppContext *ctx; Disconnect3gppContext *ctx;
GTask *task;
g_assert (primary != NULL); g_assert (primary != NULL);
ctx = g_slice_new0 (Disconnect3gppContext); ctx = g_slice_new0 (Disconnect3gppContext);
ctx->self = g_object_ref (self);
ctx->modem = MM_BASE_MODEM (g_object_ref (modem)); ctx->modem = MM_BASE_MODEM (g_object_ref (modem));
ctx->result = g_simple_async_result_new (G_OBJECT (self),
callback,
user_data,
disconnect_3gpp);
ctx->step = DISCONNECT_3GPP_CONTEXT_STEP_FIRST; ctx->step = DISCONNECT_3GPP_CONTEXT_STEP_FIRST;
g_assert (ctx->self->priv->connect_pending == NULL); g_assert (self->priv->connect_pending == NULL);
g_assert (ctx->self->priv->disconnect_pending == NULL); g_assert (self->priv->disconnect_pending == NULL);
/* Get correct dial port to use */ /* Get correct dial port to use */
ctx->primary = get_dial_port (MM_BROADBAND_MODEM_HUAWEI (ctx->modem), data, primary); ctx->primary = get_dial_port (MM_BROADBAND_MODEM_HUAWEI (ctx->modem), data, primary);
task = g_task_new (self, NULL, callback, user_data);
g_task_set_task_data (task, ctx, (GDestroyNotify)disconnect_3gpp_context_free);
/* Start! */ /* Start! */
disconnect_3gpp_context_step (ctx); disconnect_3gpp_context_step (task);
} }
/*****************************************************************************/ /*****************************************************************************/