aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGrant Erickson <gerickson@nuovations.com>2023-12-21 14:34:13 -0800
committerMarcel Holtmann <marcel@holtmann.org>2023-12-23 13:19:19 +0100
commite150216ca71940fdbf6745a3e9be40ec0e850a30 (patch)
treeda6d2d235de60b81e9dd46343e2f027125ca4041
parentd5945f59269292a33bc7052524690dc0c85d745c (diff)
downloadconnman-e150216ca71940fdbf6745a3e9be40ec0e850a30.tar.gz
service: Introduce and use online check 'active' state.
This introduces a per-IP configuration online check 'active' state member that tracks whether an online check is active / in-flight. Even with commit 864e48f34e8c ("service: Leverage '__connman_wispr_cancel'.") it remains too easy to inadvertently schedule more outstanding online checks for a service than desired (ideally, there should be one each for IPv4 and IPv6, to the extent they are "connected"). This is all the more so when 'EnableOnlineToReadyTransition' is asserted / online check mode is continuous. Rather than scheduling redundant online check, the 'active' state is now used to enable the return of -EALREADY when it is asserted from functions capable of initiating and scheduling an online check.
-rw-r--r--src/service.c92
1 files changed, 92 insertions, 0 deletions
diff --git a/src/service.c b/src/service.c
index 5077e3fb2..669337ab6 100644
--- a/src/service.c
+++ b/src/service.c
@@ -93,6 +93,8 @@ struct connman_stats_counter {
*
*/
struct online_check_state {
+ bool active;
+
/**
* The current GLib main loop timer identifier.
*
@@ -1690,6 +1692,79 @@ static bool check_proxy_setup(struct connman_service *service)
return false;
}
+static bool online_check_is_active(const struct connman_service *service,
+ enum connman_ipconfig_type type)
+{
+ bool do_ipv4 = false, do_ipv6 = false;
+ bool active = false;
+
+ DBG("service %p (%s) type %d (%s)",
+ service, connman_service_get_identifier(service),
+ type, __connman_ipconfig_type2string(type));
+
+ if (!service)
+ goto done;
+
+ if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
+ do_ipv4 = true;
+ else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
+ do_ipv6 = true;
+ else if (type == CONNMAN_IPCONFIG_TYPE_ALL)
+ do_ipv4 = do_ipv6 = true;
+ else
+ goto done;
+
+ active = (do_ipv4 && service->online_check_state_ipv4.active) ||
+ (do_ipv6 && service->online_check_state_ipv6.active);
+
+ DBG("active? %u", active);
+
+ done:
+ return active;
+}
+
+static void online_check_active_set_value(struct connman_service *service,
+ enum connman_ipconfig_type type,
+ bool active)
+{
+ bool do_ipv4 = false, do_ipv6 = false;
+
+ DBG("service %p (%s) type %d (%s) active? %u",
+ service, connman_service_get_identifier(service),
+ type, __connman_ipconfig_type2string(type),
+ active);
+
+ if (!service)
+ return;
+
+ if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
+ do_ipv4 = true;
+ else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
+ do_ipv6 = true;
+ else if (type == CONNMAN_IPCONFIG_TYPE_ALL)
+ do_ipv4 = do_ipv6 = true;
+ else
+ return;
+
+ if (do_ipv4)
+ service->online_check_state_ipv4.active = active;
+
+ if (do_ipv6)
+ service->online_check_state_ipv6.active = active;
+}
+
+static void online_check_active_set(struct connman_service *service,
+ enum connman_ipconfig_type type)
+{
+ online_check_active_set_value(service, type, true);
+}
+
+static void online_check_active_clear(struct connman_service *service,
+ enum connman_ipconfig_type type)
+{
+ online_check_active_set_value(service, type, false);
+}
+
/**
* @brief
* Compute a Fibonacci online check timeout based on the specified
@@ -1858,6 +1933,10 @@ static void cancel_online_check(struct connman_service *service,
*/
connman_service_unref(service);
}
+
+ /* Mark the online check state as inactive. */
+
+ online_check_active_clear(service, type);
}
/**
@@ -1917,6 +1996,8 @@ static bool online_check_is_enabled_check(
* @retval -EINVAL If @a service is null or @a type is invalid.
* @retval -EPERM If online checks are disabled via
* configuration.
+ * @retval -EALREADY If online checks are already active for @a
+ * service.
*
* @sa cancel_online_check
* @sa complete_online_check
@@ -2379,6 +2460,8 @@ static void complete_online_check(struct connman_service *service,
if (reschedule)
reschedule_online_check(service, type, online_check_state);
+ else
+ online_check_active_clear(service, type);
}
/**
@@ -2443,6 +2526,8 @@ static int start_wispr_if_connected(struct connman_service *service)
*
* @retval 0 If successful.
* @retval -EINVAL If @a service is null or @a type is invalid.
+ * @retval -EALREADY If online checks are already active for @a
+ * service.
*
* @sa cancel_online_check
* @sa start_online_check
@@ -2469,6 +2554,9 @@ int __connman_service_wispr_start(struct connman_service *service,
return -EINVAL;
}
+ if (online_check_is_active(service, type))
+ return -EALREADY;
+
if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
service->online_check_state_ipv4.interval =
online_check_initial_interval;
@@ -2479,6 +2567,10 @@ int __connman_service_wispr_start(struct connman_service *service,
__connman_wispr_start(service, type,
online_check_connect_timeout_ms, complete_online_check);
+ /* Mark the online check state as active. */
+
+ online_check_active_set(service, type);
+
return 0;
}