From: Aleksandar Mitev <shondll(a)yahoo.com>
The feature activates when online state is reached and performs
regular checks whether online state is still maintained by the
services (default every 5 minutes). In the case then the
online check fails the serice state is downgrated to READY
to give the chance for a switchover to another service.
---
src/service.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 69 insertions(+), 5 deletions(-)
diff --git a/src/service.c b/src/service.c
index 3202f26c..36a1911b 100644
--- a/src/service.c
+++ b/src/service.c
@@ -38,6 +38,7 @@
#include "connman.h"
#define CONNECT_TIMEOUT 120
+#define ONLINE_CHECK_REGULAR_INTERVAL 300 /* in seconds */
static DBusConnection *connection = NULL;
@@ -3440,17 +3441,23 @@ int __connman_service_reset_ipconfig(struct connman_service
*service,
#define ONLINE_CHECK_INITIAL_INTERVAL 1
#define ONLINE_CHECK_MAX_INTERVAL 12
-void __connman_service_wispr_start(struct connman_service *service,
+static void reset_online_recheck_interval(struct connman_service *service,
enum connman_ipconfig_type type)
{
- DBG("service %p type %s", service, __connman_ipconfig_type2string(type));
-
if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
service->online_check_interval_ipv4 =
ONLINE_CHECK_INITIAL_INTERVAL;
else
service->online_check_interval_ipv6 =
ONLINE_CHECK_INITIAL_INTERVAL;
+}
+
+void __connman_service_wispr_start(struct connman_service *service,
+ enum connman_ipconfig_type type)
+{
+ DBG("service %p type %s", service, __connman_ipconfig_type2string(type));
+
+ reset_online_recheck_interval(service, type);
__connman_wispr_start(service, type);
}
@@ -6039,18 +6046,58 @@ static gboolean redo_wispr_ipv6(gpointer user_data)
return FALSE;
}
+static int start_periodic_online_check(struct connman_service *service,
+ enum connman_ipconfig_type type)
+{
+ GSourceFunc redo_func;
+ guint retry_interval = ONLINE_CHECK_REGULAR_INTERVAL;
+
+ if (service->online_timeout != 0)
+ return 0;
+
+ if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
+ redo_func = redo_wispr_ipv4;
+ } else {
+ redo_func = redo_wispr_ipv6;
+ }
+ reset_online_recheck_interval(service, type);
+
+ DBG("service %p (%s) will be rechecked for internet connectivity in %ds",
+ service, service ? service->identifier : NULL, retry_interval);
+
+ service->online_timeout =
+ g_timeout_add_seconds(retry_interval, redo_func, connman_service_ref(service));
+
+ return 0;
+}
+
+static gboolean downgrade_state_handler(gpointer user_data)
+{
+ struct connman_service *service = user_data;
+
+ connman_warn("Downgrading service %s for online check did not pass",
+ service ? service->identifier : NULL);
+
+ downgrade_state(service);
+
+ return FALSE;
+}
+
int __connman_service_online_check_failed(struct connman_service *service,
enum connman_ipconfig_type type)
{
GSourceFunc redo_func;
int *interval;
+ enum connman_service_state curr_state;
if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
interval = &service->online_check_interval_ipv4;
redo_func = redo_wispr_ipv4;
+ curr_state = service->state_ipv4;
} else {
interval = &service->online_check_interval_ipv6;
redo_func = redo_wispr_ipv6;
+ curr_state = service->state_ipv6;
}
DBG("service %p type %s interval %d", service,
@@ -6059,11 +6106,18 @@ int __connman_service_online_check_failed(struct connman_service
*service,
service->online_timeout = g_timeout_add_seconds(*interval * *interval,
redo_func, connman_service_ref(service));
- /* Increment the interval for the next time, set a maximum timeout of
+ /*
+ * Increment the interval for the next time, set a maximum timeout of
* ONLINE_CHECK_MAX_INTERVAL * ONLINE_CHECK_MAX_INTERVAL seconds.
*/
if (*interval < ONLINE_CHECK_MAX_INTERVAL)
(*interval)++;
+ else {
+ if(curr_state == CONNMAN_SERVICE_STATE_ONLINE) {
+ g_idle_add(downgrade_state_handler, service);
+ return 0;
+ }
+ }
return EAGAIN;
}
@@ -6131,8 +6185,17 @@ int __connman_service_ipconfig_indicate_state(struct
connman_service *service,
}
/* Any change? */
- if (old_state == new_state)
+ if (old_state == new_state) {
+ /*
+ * continuous online check requires restart of the check
+ * at regular intervals
+ */
+ if (new_state == CONNMAN_SERVICE_STATE_ONLINE) {
+ start_periodic_online_check(service, type);
+ }
+
return -EALREADY;
+ }
DBG("service %p (%s) old state %d (%s) new state %d (%s) type %d (%s)",
service, service ? service->identifier : NULL,
@@ -6161,6 +6224,7 @@ int __connman_service_ipconfig_indicate_state(struct connman_service
*service,
set_mdns(service, service->mdns_config);
break;
case CONNMAN_SERVICE_STATE_ONLINE:
+ start_periodic_online_check(service, type);
break;
case CONNMAN_SERVICE_STATE_DISCONNECT:
if (service->state == CONNMAN_SERVICE_STATE_IDLE)
--
2.17.1