aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/mm-bearer-qmi.c97
1 files changed, 75 insertions, 22 deletions
diff --git a/src/mm-bearer-qmi.c b/src/mm-bearer-qmi.c
index 295b14fe..1bcb8a0a 100644
--- a/src/mm-bearer-qmi.c
+++ b/src/mm-bearer-qmi.c
@@ -39,6 +39,10 @@ G_DEFINE_TYPE (MMBearerQmi, mm_bearer_qmi, MM_TYPE_BASE_BEARER)
#define GLOBAL_PACKET_DATA_HANDLE 0xFFFFFFFF
struct _MMBearerQmiPrivate {
+ /* Cancellables available during a connection attempt */
+ GCancellable *ongoing_connect_user_cancellable;
+ GCancellable *ongoing_connect_network_cancellable;
+
/* State kept while connected */
MMPortQmi *qmi;
gboolean explicit_qmi_open;
@@ -504,9 +508,15 @@ complete_connect (GTask *task,
MMBearerConnectResult *result,
GError *error)
{
+ ConnectContext *ctx;
+
g_assert (result || error);
g_assert (!(result && error));
+ ctx = g_task_get_task_data (task);
+ g_clear_object (&ctx->self->priv->ongoing_connect_user_cancellable);
+ g_clear_object (&ctx->self->priv->ongoing_connect_network_cancellable);
+
if (error)
g_task_return_error (task, error);
else
@@ -1231,12 +1241,13 @@ qmi_port_open_ready (MMPortQmi *qmi,
static void
connect_context_step (GTask *task)
{
+ MMBearerQmi *self;
ConnectContext *ctx;
- GCancellable *cancellable;
- cancellable = g_task_get_cancellable (task);
+ self = g_task_get_source_object (task);
- if (g_cancellable_is_cancelled (cancellable)) {
+ g_assert (self->priv->ongoing_connect_user_cancellable);
+ if (g_cancellable_is_cancelled (self->priv->ongoing_connect_user_cancellable)) {
complete_connect (task,
NULL,
g_error_new (G_IO_ERROR,
@@ -1245,6 +1256,16 @@ connect_context_step (GTask *task)
return;
}
+ g_assert (self->priv->ongoing_connect_network_cancellable);
+ if (g_cancellable_is_cancelled (self->priv->ongoing_connect_network_cancellable)) {
+ complete_connect (task,
+ NULL,
+ g_error_new (MM_CORE_ERROR,
+ MM_CORE_ERROR_ABORTED,
+ "aborted by the network"));
+ return;
+ }
+
ctx = g_task_get_task_data (task);
switch (ctx->step) {
@@ -1263,7 +1284,7 @@ connect_context_step (GTask *task)
if (!mm_port_qmi_is_open (ctx->qmi)) {
mm_port_qmi_open (ctx->qmi,
TRUE,
- cancellable,
+ g_task_get_cancellable (task),
(GAsyncReadyCallback)qmi_port_open_ready,
task);
return;
@@ -1313,7 +1334,7 @@ connect_context_step (GTask *task)
mm_port_qmi_allocate_client (ctx->qmi,
QMI_SERVICE_WDS,
MM_PORT_QMI_FLAG_WDS_IPV4,
- cancellable,
+ g_task_get_cancellable (task),
(GAsyncReadyCallback)qmi_port_allocate_client_ready,
task);
return;
@@ -1336,7 +1357,7 @@ connect_context_step (GTask *task)
qmi_client_wds_set_ip_family (ctx->client_ipv4,
input,
10,
- cancellable,
+ g_task_get_cancellable (task),
(GAsyncReadyCallback)set_ip_family_ready,
task);
qmi_message_wds_set_ip_family_input_unref (input);
@@ -1355,7 +1376,7 @@ connect_context_step (GTask *task)
&ctx->packet_service_status_ipv4_indication_id);
setup_event_report_unsolicited_events (ctx->self,
ctx->client_ipv4,
- cancellable,
+ g_task_get_cancellable (task),
(GAsyncReadyCallback) connect_enable_indications_ipv4_ready,
task);
return;
@@ -1368,7 +1389,7 @@ connect_context_step (GTask *task)
qmi_client_wds_start_network (ctx->client_ipv4,
input,
45,
- cancellable,
+ g_task_get_cancellable (task),
(GAsyncReadyCallback)start_network_ready,
task);
qmi_message_wds_start_network_input_unref (input);
@@ -1412,7 +1433,7 @@ connect_context_step (GTask *task)
mm_port_qmi_allocate_client (ctx->qmi,
QMI_SERVICE_WDS,
MM_PORT_QMI_FLAG_WDS_IPV6,
- cancellable,
+ g_task_get_cancellable (task),
(GAsyncReadyCallback)qmi_port_allocate_client_ready,
task);
return;
@@ -1437,7 +1458,7 @@ connect_context_step (GTask *task)
qmi_client_wds_set_ip_family (ctx->client_ipv6,
input,
10,
- cancellable,
+ g_task_get_cancellable (task),
(GAsyncReadyCallback)set_ip_family_ready,
task);
qmi_message_wds_set_ip_family_input_unref (input);
@@ -1456,7 +1477,7 @@ connect_context_step (GTask *task)
&ctx->packet_service_status_ipv6_indication_id);
setup_event_report_unsolicited_events (ctx->self,
ctx->client_ipv6,
- cancellable,
+ g_task_get_cancellable (task),
(GAsyncReadyCallback) connect_enable_indications_ipv6_ready,
task);
return;
@@ -1469,7 +1490,7 @@ connect_context_step (GTask *task)
qmi_client_wds_start_network (ctx->client_ipv6,
input,
45,
- cancellable,
+ g_task_get_cancellable (task),
(GAsyncReadyCallback)start_network_ready,
task);
qmi_message_wds_start_network_input_unref (input);
@@ -1552,11 +1573,19 @@ connect_context_step (GTask *task)
}
static void
-_connect (MMBaseBearer *self,
+cancel_operation_cancellable (GCancellable *cancellable,
+ GCancellable *operation_cancellable)
+{
+ g_cancellable_cancel (operation_cancellable);
+}
+
+static void
+_connect (MMBaseBearer *_self,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
+ MMBearerQmi *self = MM_BEARER_QMI (_self);
MMBearerProperties *properties = NULL;
ConnectContext *ctx;
MMBaseModem *modem = NULL;
@@ -1565,6 +1594,7 @@ _connect (MMBaseBearer *self,
GError *error = NULL;
const gchar *apn;
GTask *task;
+ GCancellable *operation_cancellable = NULL;
g_object_get (self,
MM_BASE_BEARER_MODEM, &modem,
@@ -1598,7 +1628,7 @@ _connect (MMBaseBearer *self,
}
/* Check whether we have an APN */
- apn = mm_bearer_properties_get_apn (mm_base_bearer_peek_config (MM_BASE_BEARER (self)));
+ apn = mm_bearer_properties_get_apn (mm_base_bearer_peek_config (_self));
/* Is this a 3GPP only modem and no APN was given? If so, error */
if (mm_iface_modem_is_3gpp_only (MM_IFACE_MODEM (modem)) && !apn) {
@@ -1643,7 +1673,9 @@ _connect (MMBaseBearer *self,
MM_BASE_BEARER_CONFIG, &properties,
NULL);
- task = g_task_new (self, cancellable, callback, user_data);
+ operation_cancellable = g_cancellable_new ();
+ task = g_task_new (self, operation_cancellable, callback, user_data);
+ g_task_set_check_cancellable (task, FALSE);
g_task_set_task_data (task, ctx, (GDestroyNotify)connect_context_free);
if (properties) {
@@ -1659,7 +1691,7 @@ _connect (MMBaseBearer *self,
ip_family == MM_BEARER_IP_FAMILY_ANY) {
gchar *ip_family_str;
- ip_family = mm_base_bearer_get_default_ip_family (self);
+ ip_family = mm_base_bearer_get_default_ip_family (_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);
@@ -1718,10 +1750,27 @@ _connect (MMBaseBearer *self,
}
}
+ /* setup network cancellable */
+ g_assert (!self->priv->ongoing_connect_network_cancellable);
+ self->priv->ongoing_connect_network_cancellable = g_cancellable_new ();
+ g_cancellable_connect (self->priv->ongoing_connect_network_cancellable,
+ G_CALLBACK (cancel_operation_cancellable),
+ g_object_ref (operation_cancellable),
+ g_object_unref);
+
+ /* setup user cancellable */
+ g_assert (!self->priv->ongoing_connect_user_cancellable);
+ self->priv->ongoing_connect_user_cancellable = g_object_ref (cancellable);
+ g_cancellable_connect (self->priv->ongoing_connect_user_cancellable,
+ G_CALLBACK (cancel_operation_cancellable),
+ g_object_ref (operation_cancellable),
+ g_object_unref);
+
/* Run! */
connect_context_step (task);
out:
+ g_clear_object (&operation_cancellable);
g_clear_object (&qmi);
g_clear_object (&data);
g_clear_object (&modem);
@@ -2004,7 +2053,6 @@ disconnect (MMBaseBearer *_self,
ctx->packet_data_handle_ipv6 = self->priv->packet_data_handle_ipv6;
ctx->step = DISCONNECT_STEP_FIRST;
- task = g_task_new (self, NULL, callback, user_data);
g_task_set_task_data (task, ctx, (GDestroyNotify)disconnect_context_free);
/* Run! */
@@ -2014,15 +2062,20 @@ disconnect (MMBaseBearer *_self,
/*****************************************************************************/
static void
-report_connection_status (MMBaseBearer *self,
- MMBearerConnectionStatus status)
+report_connection_status (MMBaseBearer *_self,
+ MMBearerConnectionStatus status)
{
- if (status == MM_BEARER_CONNECTION_STATUS_DISCONNECTED)
+ MMBearerQmi *self = MM_BEARER_QMI (_self);
+
+ if (status == MM_BEARER_CONNECTION_STATUS_DISCONNECTED) {
+ /* Cancel any ongoing connection attempt */
+ g_cancellable_cancel (self->priv->ongoing_connect_network_cancellable);
/* Cleanup all connection related data */
- reset_bearer_connection (MM_BEARER_QMI (self), TRUE, TRUE);
+ reset_bearer_connection (self, TRUE, TRUE);
+ }
/* Chain up parent's report_connection_status() */
- MM_BASE_BEARER_CLASS (mm_bearer_qmi_parent_class)->report_connection_status (self, status);
+ MM_BASE_BEARER_CLASS (mm_bearer_qmi_parent_class)->report_connection_status (_self, status);
}
/*****************************************************************************/