[PATCH] bearer-qmi: listen for Packet Service Status indication and handle disconnection
Diego López Montes
dlopezm at teltronic.es
Thu Apr 14 08:17:40 UTC 2016
Great job! I'm going to try it. I will report the results the tests as
soon as possible.
> Hook up to the WDS Packet Service Status indication, listen for
> disconnection events, and disconnect the bearer when we get one.
> ---
> src/mm-bearer-qmi.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 139 insertions(+)
>
> *** testing with dual-stack (IPV4V6) appreciated!
>
> diff --git a/src/mm-bearer-qmi.c b/src/mm-bearer-qmi.c
> index 74e74f7..e750bf2 100644
> --- a/src/mm-bearer-qmi.c
> +++ b/src/mm-bearer-qmi.c
> @@ -49,7 +49,11 @@ static GParamSpec *properties[PROP_LAST];
> struct _MMBearerQmiPrivate {
> /* State kept while connected */
> QmiClientWds *client_ipv4;
> + guint packet_service_status_ipv4_indication_id;
> +
> QmiClientWds *client_ipv6;
> + guint packet_service_status_ipv6_indication_id;
> +
> MMPort *data;
> guint32 packet_data_handle_ipv4;
> guint32 packet_data_handle_ipv6;
> @@ -214,17 +218,24 @@ reload_stats (MMBaseBearer *self,
> /*****************************************************************************/
> /* Connect */
>
> +static void common_setup_cleanup_unsolicited_events (MMBearerQmi *self,
> + QmiClientWds *client,
> + gboolean enable,
> + guint *indication_id);
> +
> typedef enum {
> CONNECT_STEP_FIRST,
> CONNECT_STEP_OPEN_QMI_PORT,
> CONNECT_STEP_IPV4,
> CONNECT_STEP_WDS_CLIENT_IPV4,
> CONNECT_STEP_IP_FAMILY_IPV4,
> + CONNECT_STEP_ENABLE_INDICATIONS_IPV4,
> CONNECT_STEP_START_NETWORK_IPV4,
> CONNECT_STEP_GET_CURRENT_SETTINGS_IPV4,
> CONNECT_STEP_IPV6,
> CONNECT_STEP_WDS_CLIENT_IPV6,
> CONNECT_STEP_IP_FAMILY_IPV6,
> + CONNECT_STEP_ENABLE_INDICATIONS_IPV6,
> CONNECT_STEP_START_NETWORK_IPV6,
> CONNECT_STEP_GET_CURRENT_SETTINGS_IPV6,
> CONNECT_STEP_LAST
> @@ -247,6 +258,7 @@ typedef struct {
> gboolean ipv4;
> gboolean running_ipv4;
> QmiClientWds *client_ipv4;
> + guint packet_service_status_ipv4_indication_id;
> guint32 packet_data_handle_ipv4;
> MMBearerIpConfig *ipv4_config;
> GError *error_ipv4;
> @@ -254,6 +266,7 @@ typedef struct {
> gboolean ipv6;
> gboolean running_ipv6;
> QmiClientWds *client_ipv6;
> + guint packet_service_status_ipv6_indication_id;
> guint32 packet_data_handle_ipv6;
> MMBearerIpConfig *ipv6_config;
> GError *error_ipv6;
> @@ -267,6 +280,20 @@ connect_context_complete_and_free (ConnectContext *ctx)
> g_free (ctx->apn);
> g_free (ctx->user);
> g_free (ctx->password);
> +
> + if (ctx->packet_service_status_ipv4_indication_id) {
> + common_setup_cleanup_unsolicited_events (ctx->self,
> + ctx->client_ipv4,
> + FALSE,
> + &ctx->packet_service_status_ipv4_indication_id);
> + }
> + if (ctx->packet_service_status_ipv6_indication_id) {
> + common_setup_cleanup_unsolicited_events (ctx->self,
> + ctx->client_ipv6,
> + FALSE,
> + &ctx->packet_service_status_ipv6_indication_id);
> + }
> +
> g_clear_error (&ctx->error_ipv4);
> g_clear_error (&ctx->error_ipv6);
> g_clear_object (&ctx->client_ipv4);
> @@ -745,6 +772,75 @@ set_ip_family_ready (QmiClientWds *client,
> }
>
> static void
> +packet_service_status_indication_cb (QmiClientWds *client,
> + QmiIndicationWdsPacketServiceStatusOutput *output,
> + MMBearerQmi *self)
> +{
> + QmiWdsConnectionStatus connection_status;
> +
> + if (qmi_indication_wds_packet_service_status_output_get_connection_status (
> + output,
> + &connection_status,
> + NULL,
> + NULL)) {
> + MMBearerConnectionStatus bearer_status = mm_base_bearer_get_status (MM_BASE_BEARER (self));
> +
> + if (connection_status == QMI_WDS_CONNECTION_STATUS_DISCONNECTED &&
> + bearer_status != MM_BEARER_CONNECTION_STATUS_DISCONNECTED &&
> + bearer_status != MM_BEARER_CONNECTION_STATUS_DISCONNECTING) {
> + QmiWdsCallEndReason cer;
> + QmiWdsVerboseCallEndReasonType verbose_cer_type;
> + gint16 verbose_cer_reason;
> +
> + if (qmi_indication_wds_packet_service_status_output_get_call_end_reason (
> + output,
> + &cer,
> + NULL))
> + mm_info ("bearer call end reason (%u): '%s'",
> + cer,
> + qmi_wds_call_end_reason_get_string (cer));
> +
> + if (qmi_indication_wds_packet_service_status_output_get_verbose_call_end_reason (
> + output,
> + &verbose_cer_type,
> + &verbose_cer_reason,
> + NULL))
> + mm_info ("bearer verbose call end reason (%u,%d): [%s] %s",
> + verbose_cer_type,
> + verbose_cer_reason,
> + qmi_wds_verbose_call_end_reason_type_get_string (verbose_cer_type),
> + qmi_wds_verbose_call_end_reason_get_string (verbose_cer_type, verbose_cer_reason));
> +
> + mm_base_bearer_report_connection_status (MM_BASE_BEARER (self), MM_BEARER_CONNECTION_STATUS_DISCONNECTED);
> + }
> + }
> +}
> +
> +static void
> +common_setup_cleanup_unsolicited_events (MMBearerQmi *self,
> + QmiClientWds *client,
> + gboolean enable,
> + guint *indication_id)
> +{
> + if (!client)
> + return;
> +
> + /* Connect/Disconnect "Packet Service Status" indications */
> + if (enable) {
> + g_assert (*indication_id == 0);
> + *indication_id =
> + g_signal_connect (client,
> + "packet-service-status",
> + G_CALLBACK (packet_service_status_indication_cb),
> + self);
> + } else {
> + g_assert (*indication_id != 0);
> + g_signal_handler_disconnect (client, *indication_id);
> + *indication_id = 0;
> + }
> +}
> +
> +static void
> qmi_port_allocate_client_ready (MMPortQmi *qmi,
> GAsyncResult *res,
> ConnectContext *ctx)
> @@ -887,6 +983,14 @@ connect_context_step (ConnectContext *ctx)
> /* Just fall down */
> ctx->step++;
>
> + case CONNECT_STEP_ENABLE_INDICATIONS_IPV4:
> + common_setup_cleanup_unsolicited_events (ctx->self,
> + ctx->client_ipv4,
> + TRUE,
> + &ctx->packet_service_status_ipv4_indication_id);
> + /* Just fall down */
> + ctx->step++;
> +
> case CONNECT_STEP_START_NETWORK_IPV4: {
> QmiMessageWdsStartNetworkInput *input;
>
> @@ -976,6 +1080,14 @@ connect_context_step (ConnectContext *ctx)
> /* Just fall down */
> ctx->step++;
>
> + case CONNECT_STEP_ENABLE_INDICATIONS_IPV6:
> + common_setup_cleanup_unsolicited_events (ctx->self,
> + ctx->client_ipv6,
> + TRUE,
> + &ctx->packet_service_status_ipv6_indication_id);
> + /* Just fall down */
> + ctx->step++;
> +
> case CONNECT_STEP_START_NETWORK_IPV6: {
> QmiMessageWdsStartNetworkInput *input;
>
> @@ -1016,6 +1128,8 @@ connect_context_step (ConnectContext *ctx)
> g_assert (ctx->self->priv->client_ipv4 == NULL);
> if (ctx->packet_data_handle_ipv4) {
> ctx->self->priv->packet_data_handle_ipv4 = ctx->packet_data_handle_ipv4;
> + ctx->self->priv->packet_service_status_ipv4_indication_id = ctx->packet_service_status_ipv4_indication_id;
> + ctx->packet_service_status_ipv4_indication_id = 0;
> ctx->self->priv->client_ipv4 = g_object_ref (ctx->client_ipv4);
> }
>
> @@ -1023,6 +1137,8 @@ connect_context_step (ConnectContext *ctx)
> g_assert (ctx->self->priv->client_ipv6 == NULL);
> if (ctx->packet_data_handle_ipv6) {
> ctx->self->priv->packet_data_handle_ipv6 = ctx->packet_data_handle_ipv6;
> + ctx->self->priv->packet_service_status_ipv6_indication_id = ctx->packet_service_status_ipv6_indication_id;
> + ctx->packet_service_status_ipv6_indication_id = 0;
> ctx->self->priv->client_ipv6 = g_object_ref (ctx->client_ipv6);
> }
>
> @@ -1357,6 +1473,11 @@ disconnect_context_step (DisconnectContext *ctx)
> if (ctx->packet_data_handle_ipv4) {
> QmiMessageWdsStopNetworkInput *input;
>
> + common_setup_cleanup_unsolicited_events (ctx->self,
> + ctx->client_ipv4,
> + FALSE,
> + &ctx->self->priv->packet_service_status_ipv4_indication_id);
> +
> input = qmi_message_wds_stop_network_input_new ();
> qmi_message_wds_stop_network_input_set_packet_data_handle (input, ctx->packet_data_handle_ipv4, NULL);
>
> @@ -1378,6 +1499,11 @@ disconnect_context_step (DisconnectContext *ctx)
> if (ctx->packet_data_handle_ipv6) {
> QmiMessageWdsStopNetworkInput *input;
>
> + common_setup_cleanup_unsolicited_events (ctx->self,
> + ctx->client_ipv6,
> + FALSE,
> + &ctx->self->priv->packet_service_status_ipv6_indication_id);
> +
> input = qmi_message_wds_stop_network_input_new ();
> qmi_message_wds_stop_network_input_set_packet_data_handle (input, ctx->packet_data_handle_ipv6, NULL);
>
> @@ -1544,6 +1670,19 @@ dispose (GObject *object)
> {
> MMBearerQmi *self = MM_BEARER_QMI (object);
>
> + if (self->priv->packet_service_status_ipv4_indication_id) {
> + common_setup_cleanup_unsolicited_events (self,
> + self->priv->client_ipv4,
> + FALSE,
> + &self->priv->packet_service_status_ipv4_indication_id);
> + }
> + if (self->priv->packet_service_status_ipv6_indication_id) {
> + common_setup_cleanup_unsolicited_events (self,
> + self->priv->client_ipv6,
> + FALSE,
> + &self->priv->packet_service_status_ipv6_indication_id);
> + }
> +
> g_clear_object (&self->priv->data);
> g_clear_object (&self->priv->client_ipv4);
> g_clear_object (&self->priv->client_ipv6);
> --
> 2.5.5
More information about the ModemManager-devel
mailing list