diff options
author | Aleksander Morgado <aleksander@aleksander.es> | 2016-08-07 13:31:41 +0200 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2016-10-12 11:29:52 +0200 |
commit | 26d0d718f7834348146ab9e040051f7a538f04f0 (patch) | |
tree | cc4864393d33ea369a6f0627b8d645a570d4b472 /src | |
parent | 467b3c57f01b37dbcec8d32a449654aac40f90d0 (diff) |
base-bearer: new periodic monitoring of connection status
Diffstat (limited to 'src')
-rw-r--r-- | src/mm-base-bearer.c | 80 | ||||
-rw-r--r-- | src/mm-base-bearer.h | 11 |
2 files changed, 85 insertions, 6 deletions
diff --git a/src/mm-base-bearer.c b/src/mm-base-bearer.c index 12b1d531..e4234ea7 100644 --- a/src/mm-base-bearer.c +++ b/src/mm-base-bearer.c @@ -14,7 +14,7 @@ * Copyright (C) 2009 - 2011 Red Hat, Inc. * Copyright (C) 2011 Google, Inc. * Copyright (C) 2015 Azimut Electronics - * Copyright (C) 2011 - 2015 Aleksander Morgado <aleksander@aleksander.es> + * Copyright (C) 2011 - 2016 Aleksander Morgado <aleksander@aleksander.es> */ #include <config.h> @@ -46,6 +46,8 @@ #define BEARER_STATS_UPDATE_TIMEOUT 30 +#define BEARER_CONNECTION_MONITOR_TIMEOUT 5 + G_DEFINE_TYPE (MMBaseBearer, mm_base_bearer, MM_GDBUS_TYPE_BEARER_SKELETON) typedef enum { @@ -87,6 +89,9 @@ struct _MMBaseBearerPrivate { /* handler id for the disconnect + cancel connect request */ gulong disconnect_signal_handler; + /* Connection status monitoring */ + guint connection_monitor_id; + /*-- 3GPP specific --*/ guint deferred_3gpp_unregistration_id; /* Reason if 3GPP connection is forbidden */ @@ -136,6 +141,63 @@ mm_base_bearer_export (MMBaseBearer *self) /*****************************************************************************/ static void +connection_monitor_stop (MMBaseBearer *self) +{ + if (self->priv->connection_monitor_id) { + g_source_remove (self->priv->connection_monitor_id); + self->priv->connection_monitor_id = 0; + } +} + +static void +load_connection_status_ready (MMBaseBearer *self, + GAsyncResult *res) +{ + GError *error = NULL; + MMBearerConnectionStatus status; + + status = MM_BASE_BEARER_GET_CLASS (self)->load_connection_status_finish (self, res, &error); + if (status == MM_BEARER_CONNECTION_STATUS_UNKNOWN) { + mm_warn ("checking if connected failed: %s", error->message); + g_error_free (error); + return; + } + + /* Report connection or disconnection */ + g_assert (status == MM_BEARER_CONNECTION_STATUS_CONNECTED || status == MM_BEARER_CONNECTION_STATUS_DISCONNECTED); + mm_dbg ("connection status loaded: %s", mm_bearer_connection_status_get_string (status)); + mm_base_bearer_report_connection_status (self, status); +} + +static gboolean +connection_monitor_cb (MMBaseBearer *self) +{ + /* If the implementation knows how to update stat values, run it */ + MM_BASE_BEARER_GET_CLASS (self)->load_connection_status ( + self, + (GAsyncReadyCallback)load_connection_status_ready, + NULL); + return G_SOURCE_CONTINUE; +} + +static void +connection_monitor_start (MMBaseBearer *self) +{ + /* If not implemented, don't schedule anything */ + if (!MM_BASE_BEARER_GET_CLASS (self)->load_connection_status || + !MM_BASE_BEARER_GET_CLASS (self)->load_connection_status_finish) + return; + + /* Schedule */ + g_assert (!self->priv->connection_monitor_id); + self->priv->connection_monitor_id = g_timeout_add_seconds (BEARER_CONNECTION_MONITOR_TIMEOUT, + (GSourceFunc) connection_monitor_cb, + self); +} + +/*****************************************************************************/ + +static void bearer_update_interface_stats (MMBaseBearer *self) { mm_gdbus_bearer_set_stats ( @@ -262,6 +324,8 @@ bearer_update_status (MMBaseBearer *self, bearer_reset_interface_status (self); /* Stop statistics */ bearer_stats_stop (self); + /* Stop connection monitoring */ + connection_monitor_stop (self); } } @@ -284,6 +348,9 @@ bearer_update_status_connected (MMBaseBearer *self, /* Start statistics */ bearer_stats_start (self); + /* Start connection monitor, if supported */ + connection_monitor_start (self); + /* Update the property value */ self->priv->status = MM_BEARER_STATUS_CONNECTED; g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_STATUS]); @@ -1100,15 +1167,15 @@ static void report_connection_status (MMBaseBearer *self, MMBearerConnectionStatus status) { - /* The only status expected at this point is DISCONNECTED. - * No other status should have been given to the generic implementation - * of report_connection_status (it would be an error). + /* The only status expected at this point is DISCONNECTED or CONNECTED, + * although here we just process the DISCONNECTED one. */ - g_assert (status == MM_BEARER_CONNECTION_STATUS_DISCONNECTED); + g_assert (status == MM_BEARER_CONNECTION_STATUS_CONNECTED || status == MM_BEARER_CONNECTION_STATUS_DISCONNECTED); /* In the generic bearer implementation we just need to reset the * interface status */ - bearer_update_status (self, MM_BEARER_STATUS_DISCONNECTED); + if (status == MM_BEARER_CONNECTION_STATUS_DISCONNECTED) + bearer_update_status (self, MM_BEARER_STATUS_DISCONNECTED); } void @@ -1264,6 +1331,7 @@ dispose (GObject *object) { MMBaseBearer *self = MM_BASE_BEARER (object); + connection_monitor_stop (self); bearer_stats_stop (self); g_clear_object (&self->priv->stats); diff --git a/src/mm-base-bearer.h b/src/mm-base-bearer.h index 58954d40..1e020dc6 100644 --- a/src/mm-base-bearer.h +++ b/src/mm-base-bearer.h @@ -101,6 +101,17 @@ struct _MMBaseBearerClass { GAsyncResult *res, GError **error); + /* Monitor connection status: + * NOTE: only CONNECTED or DISCONNECTED should be reported here; this method + * is used to poll for connection status once the connection has been + * established */ + void (* load_connection_status) (MMBaseBearer *bearer, + GAsyncReadyCallback callback, + gpointer user_data); + MMBearerConnectionStatus (* load_connection_status_finish) (MMBaseBearer *bearer, + GAsyncResult *res, + GError **error); + /* Reload statistics */ void (* reload_stats) (MMBaseBearer *bearer, GAsyncReadyCallback callback, |