huawei: port connect_3gpp to use GTask

This commit is contained in:
Ben Chan
2017-09-08 17:45:29 +02:00
committed by Aleksander Morgado
parent 1ada2d23a5
commit d6d52b95c7
+95 -89
View File
@@ -72,12 +72,9 @@ typedef enum {
} Connect3gppContextStep;
typedef struct {
MMBroadbandBearerHuawei *self;
MMBaseModem *modem;
MMPortSerialAt *primary;
MMPort *data;
GCancellable *cancellable;
GSimpleAsyncResult *result;
Connect3gppContextStep step;
guint check_count;
guint failed_ndisstatqry_count;
@@ -85,14 +82,9 @@ typedef struct {
} Connect3gppContext;
static void
connect_3gpp_context_complete_and_free (Connect3gppContext *ctx)
connect_3gpp_context_free (Connect3gppContext *ctx)
{
g_simple_async_result_complete_in_idle (ctx->result);
g_object_unref (ctx->cancellable);
g_object_unref (ctx->result);
g_object_unref (ctx->modem);
g_object_unref (ctx->self);
g_clear_object (&ctx->ipv4_config);
g_clear_object (&ctx->data);
@@ -106,25 +98,25 @@ connect_3gpp_finish (MMBroadbandBearer *self,
GAsyncResult *res,
GError **error)
{
if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
return NULL;
return mm_bearer_connect_result_ref (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res)));
return g_task_propagate_pointer (G_TASK (res), error);
}
static void connect_3gpp_context_step (Connect3gppContext *ctx);
static void connect_3gpp_context_step (GTask *task);
static void
connect_dhcp_check_ready (MMBaseModem *modem,
GAsyncResult *res,
MMBroadbandBearerHuawei *self)
{
GTask *task;
Connect3gppContext *ctx;
const gchar *response;
GError *error = NULL;
ctx = self->priv->connect_pending;
g_assert (ctx != NULL);
task = self->priv->connect_pending;
g_assert (task != NULL);
ctx = g_task_get_task_data (task);
/* Balance refcount */
g_object_unref (self);
@@ -189,23 +181,23 @@ connect_dhcp_check_ready (MMBaseModem *modem,
g_clear_error (&error);
ctx->step++;
connect_3gpp_context_step (ctx);
connect_3gpp_context_step (task);
}
static gboolean
connect_retry_ndisstatqry_check_cb (MMBroadbandBearerHuawei *self)
{
Connect3gppContext *ctx;
GTask *task;
/* Recover context */
ctx = self->priv->connect_pending;
g_assert (ctx != NULL);
task = self->priv->connect_pending;
g_assert (task != NULL);
/* Balance refcount */
g_object_unref (self);
/* Retry same step */
connect_3gpp_context_step (ctx);
connect_3gpp_context_step (task);
return G_SOURCE_REMOVE;
}
@@ -215,6 +207,7 @@ connect_ndisstatqry_check_ready (MMBaseModem *modem,
GAsyncResult *res,
MMBroadbandBearerHuawei *self)
{
GTask *task;
Connect3gppContext *ctx;
const gchar *response;
GError *error = NULL;
@@ -223,8 +216,10 @@ connect_ndisstatqry_check_ready (MMBaseModem *modem,
gboolean ipv6_available = FALSE;
gboolean ipv6_connected = FALSE;
ctx = self->priv->connect_pending;
g_assert (ctx != NULL);
task = self->priv->connect_pending;
g_assert (task != NULL);
ctx = g_task_get_task_data (task);
/* Balance refcount */
g_object_unref (self);
@@ -247,7 +242,7 @@ connect_ndisstatqry_check_ready (MMBaseModem *modem,
if (ipv4_available && ipv4_connected) {
/* Success! */
ctx->step++;
connect_3gpp_context_step (ctx);
connect_3gpp_context_step (task);
return;
}
@@ -262,26 +257,29 @@ connect_ndisdup_ready (MMBaseModem *modem,
GAsyncResult *res,
MMBroadbandBearerHuawei *self)
{
GTask *task;
Connect3gppContext *ctx;
GError *error = NULL;
ctx = self->priv->connect_pending;
g_assert (ctx != NULL);
task = self->priv->connect_pending;
g_assert (task != NULL);
ctx = g_task_get_task_data (task);
/* Balance refcount */
g_object_unref (self);
if (!mm_base_modem_at_command_full_finish (modem, res, &error)) {
/* Clear context */
/* Clear task */
self->priv->connect_pending = NULL;
g_simple_async_result_take_error (ctx->result, error);
connect_3gpp_context_complete_and_free (ctx);
g_task_return_error (task, error);
g_object_unref (task);
return;
}
/* Go to next step */
ctx->step++;
connect_3gpp_context_step (ctx);
connect_3gpp_context_step (task);
}
typedef enum {
@@ -310,12 +308,18 @@ huawei_parse_auth_type (MMBearerAllowedAuth mm_auth)
}
static void
connect_3gpp_context_step (Connect3gppContext *ctx)
connect_3gpp_context_step (GTask *task)
{
MMBroadbandBearerHuawei *self;
Connect3gppContext *ctx;
self = g_task_get_source_object (task);
ctx = g_task_get_task_data (task);
/* Check for cancellation */
if (g_cancellable_is_cancelled (ctx->cancellable)) {
/* Clear context */
ctx->self->priv->connect_pending = NULL;
if (g_cancellable_is_cancelled (g_task_get_cancellable (task))) {
/* Clear task */
self->priv->connect_pending = NULL;
/* If we already sent the connetion command, send the disconnection one */
if (ctx->step > CONNECT_3GPP_CONTEXT_STEP_NDISDUP)
@@ -329,29 +333,29 @@ connect_3gpp_context_step (Connect3gppContext *ctx)
NULL, /* Do not care the AT response */
NULL);
g_simple_async_result_set_error (ctx->result,
MM_CORE_ERROR,
MM_CORE_ERROR_CANCELLED,
"Huawei connection operation has been cancelled");
connect_3gpp_context_complete_and_free (ctx);
g_task_return_new_error (task,
MM_CORE_ERROR,
MM_CORE_ERROR_CANCELLED,
"Huawei connection operation has been cancelled");
g_object_unref (task);
return;
}
/* Network-initiated disconnect should not be outstanding at this point,
* because it interferes with the connect attempt.
*/
g_assert (ctx->self->priv->network_disconnect_pending_id == 0);
g_assert (self->priv->network_disconnect_pending_id == 0);
switch (ctx->step) {
case CONNECT_3GPP_CONTEXT_STEP_FIRST: {
MMBearerIpFamily ip_family;
ip_family = mm_bearer_properties_get_ip_type (mm_base_bearer_peek_config (MM_BASE_BEARER (ctx->self)));
ip_family = mm_bearer_properties_get_ip_type (mm_base_bearer_peek_config (MM_BASE_BEARER (self)));
if (ip_family == MM_BEARER_IP_FAMILY_NONE ||
ip_family == MM_BEARER_IP_FAMILY_ANY) {
gchar *ip_family_str;
ip_family = mm_base_bearer_get_default_ip_family (MM_BASE_BEARER (ctx->self));
ip_family = mm_base_bearer_get_default_ip_family (MM_BASE_BEARER (self));
ip_family_str = mm_bearer_ip_family_build_string_from_mask (ip_family);
mm_dbg ("No specific IP family requested, defaulting to %s",
ip_family_str);
@@ -359,16 +363,16 @@ connect_3gpp_context_step (Connect3gppContext *ctx)
}
if (ip_family != MM_BEARER_IP_FAMILY_IPV4) {
g_simple_async_result_set_error (ctx->result,
MM_CORE_ERROR,
MM_CORE_ERROR_UNSUPPORTED,
"Only IPv4 is supported by this modem");
connect_3gpp_context_complete_and_free (ctx);
g_task_return_new_error (task,
MM_CORE_ERROR,
MM_CORE_ERROR_UNSUPPORTED,
"Only IPv4 is supported by this modem");
g_object_unref (task);
return;
}
/* Store the context */
ctx->self->priv->connect_pending = ctx;
/* Store the task */
self->priv->connect_pending = task;
ctx->step++;
/* Fall down to the next step */
@@ -382,10 +386,10 @@ connect_3gpp_context_step (Connect3gppContext *ctx)
gint encoded_auth = MM_BEARER_HUAWEI_AUTH_UNKNOWN;
gchar *command;
apn = mm_bearer_properties_get_apn (mm_base_bearer_peek_config (MM_BASE_BEARER (ctx->self)));
user = mm_bearer_properties_get_user (mm_base_bearer_peek_config (MM_BASE_BEARER (ctx->self)));
passwd = mm_bearer_properties_get_password (mm_base_bearer_peek_config (MM_BASE_BEARER (ctx->self)));
auth = mm_bearer_properties_get_allowed_auth (mm_base_bearer_peek_config (MM_BASE_BEARER (ctx->self)));
apn = mm_bearer_properties_get_apn (mm_base_bearer_peek_config (MM_BASE_BEARER (self)));
user = mm_bearer_properties_get_user (mm_base_bearer_peek_config (MM_BASE_BEARER (self)));
passwd = mm_bearer_properties_get_password (mm_base_bearer_peek_config (MM_BASE_BEARER (self)));
auth = mm_bearer_properties_get_allowed_auth (mm_base_bearer_peek_config (MM_BASE_BEARER (self)));
encoded_auth = huawei_parse_auth_type (auth);
/* Default to no authentication if not specified */
@@ -415,7 +419,7 @@ connect_3gpp_context_step (Connect3gppContext *ctx)
FALSE,
NULL,
(GAsyncReadyCallback)connect_ndisdup_ready,
g_object_ref (ctx->self));
g_object_ref (self));
g_free (command);
return;
}
@@ -427,24 +431,24 @@ connect_3gpp_context_step (Connect3gppContext *ctx)
*/
if (ctx->check_count > 60) {
/* Clear context */
ctx->self->priv->connect_pending = NULL;
g_simple_async_result_set_error (ctx->result,
MM_MOBILE_EQUIPMENT_ERROR,
MM_MOBILE_EQUIPMENT_ERROR_NETWORK_TIMEOUT,
"Connection attempt timed out");
connect_3gpp_context_complete_and_free (ctx);
self->priv->connect_pending = NULL;
g_task_return_new_error (task,
MM_MOBILE_EQUIPMENT_ERROR,
MM_MOBILE_EQUIPMENT_ERROR_NETWORK_TIMEOUT,
"Connection attempt timed out");
g_object_unref (task);
return;
}
/* Give up if too many unexpected responses to NIDSSTATQRY are encountered. */
if (ctx->failed_ndisstatqry_count > 10) {
/* Clear context */
ctx->self->priv->connect_pending = NULL;
g_simple_async_result_set_error (ctx->result,
MM_MOBILE_EQUIPMENT_ERROR,
MM_MOBILE_EQUIPMENT_ERROR_NOT_SUPPORTED,
"Connection attempt not supported.");
connect_3gpp_context_complete_and_free (ctx);
self->priv->connect_pending = NULL;
g_task_return_new_error (task,
MM_MOBILE_EQUIPMENT_ERROR,
MM_MOBILE_EQUIPMENT_ERROR_NOT_SUPPORTED,
"Connection attempt not supported.");
g_object_unref (task);
return;
}
@@ -458,7 +462,7 @@ connect_3gpp_context_step (Connect3gppContext *ctx)
FALSE,
NULL,
(GAsyncReadyCallback)connect_ndisstatqry_check_ready,
g_object_ref (ctx->self));
g_object_ref (self));
return;
case CONNECT_3GPP_CONTEXT_STEP_IP_CONFIG:
@@ -470,26 +474,26 @@ connect_3gpp_context_step (Connect3gppContext *ctx)
FALSE,
NULL,
(GAsyncReadyCallback)connect_dhcp_check_ready,
g_object_ref (ctx->self));
g_object_ref (self));
return;
case CONNECT_3GPP_CONTEXT_STEP_LAST:
/* Clear context */
ctx->self->priv->connect_pending = NULL;
self->priv->connect_pending = NULL;
/* Setup result */
g_simple_async_result_set_op_res_gpointer (
ctx->result,
g_task_return_pointer (
task,
mm_bearer_connect_result_new (ctx->data, ctx->ipv4_config, NULL),
(GDestroyNotify)mm_bearer_connect_result_unref);
connect_3gpp_context_complete_and_free (ctx);
g_object_unref (task);
return;
}
}
static void
connect_3gpp (MMBroadbandBearer *self,
connect_3gpp (MMBroadbandBearer *_self,
MMBroadbandModem *modem,
MMPortSerialAt *primary,
MMPortSerialAt *secondary,
@@ -497,7 +501,9 @@ connect_3gpp (MMBroadbandBearer *self,
GAsyncReadyCallback callback,
gpointer user_data)
{
Connect3gppContext *ctx;
MMBroadbandBearerHuawei *self = MM_BROADBAND_BEARER_HUAWEI (_self);
Connect3gppContext *ctx;
GTask *task;
MMPort *data;
g_assert (primary != NULL);
@@ -505,39 +511,39 @@ connect_3gpp (MMBroadbandBearer *self,
/* We need a net data port */
data = mm_base_modem_peek_best_data_port (MM_BASE_MODEM (modem), MM_PORT_TYPE_NET);
if (!data) {
g_simple_async_report_error_in_idle (G_OBJECT (self),
callback,
user_data,
MM_CORE_ERROR,
MM_CORE_ERROR_NOT_FOUND,
"No valid data port found to launch connection");
g_task_report_new_error (self,
callback,
user_data,
connect_3gpp,
MM_CORE_ERROR,
MM_CORE_ERROR_NOT_FOUND,
"No valid data port found to launch connection");
return;
}
/* Setup connection context */
ctx = g_slice_new0 (Connect3gppContext);
ctx->self = g_object_ref (self);
ctx->modem = g_object_ref (modem);
ctx->data = g_object_ref (data);
ctx->result = g_simple_async_result_new (G_OBJECT (self),
callback,
user_data,
connect_3gpp);
ctx->cancellable = g_object_ref (cancellable);
ctx->step = CONNECT_3GPP_CONTEXT_STEP_FIRST;
g_assert (ctx->self->priv->connect_pending == NULL);
g_assert (ctx->self->priv->disconnect_pending == NULL);
g_assert (self->priv->connect_pending == NULL);
g_assert (self->priv->disconnect_pending == NULL);
/* Get correct dial port to use */
ctx->primary = get_dial_port (MM_BROADBAND_MODEM_HUAWEI (ctx->modem), ctx->data, primary);
/* Default to automatic/DHCP addressing */
ctx->ipv4_config = mm_bearer_ip_config_new ();
mm_bearer_ip_config_set_method (ctx->ipv4_config, MM_BEARER_IP_METHOD_DHCP);
task = g_task_new (self, NULL, callback, user_data);
g_task_set_task_data (task, ctx, (GDestroyNotify)connect_3gpp_context_free);
g_task_set_check_cancellable (task, FALSE);
/* Run! */
connect_3gpp_context_step (ctx);
connect_3gpp_context_step (task);
}
/*****************************************************************************/