From a8f32ed7dfc9731f7c66519a82b8bf0bca032244 Mon Sep 17 00:00:00 2001 From: Denozordec Date: Tue, 10 Nov 2026 10:07:09 +0700 Subject: [PATCH] android: DNS chain diagnostics run at most once per 10 min instead of on every reconnect; Home probes every 30 s instead of 10 s; a DoT worker closes its TLS connection when it exits Co-Authored-By: Claude Fable 5.2 --- .../org/strongswan/android/logic/CharonVpnService.java | 10 ++++++++++ .../strongswan/android/logic/protection/SecureDns.kt | 6 +++++- .../org/strongswan/android/ui/compose/HomeViewModel.kt | 3 ++- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/logic/CharonVpnService.java b/src/frontends/android/app/src/main/java/org/strongswan/android/logic/CharonVpnService.java index cf1ef2874..061c9e0b5 100644 --- a/src/frontends/android/app/src/main/java/org/strongswan/android/logic/CharonVpnService.java +++ b/src/frontends/android/app/src/main/java/org/strongswan/android/logic/CharonVpnService.java @@ -1134,6 +1134,7 @@ public class CharonVpnService extends VpnService implements Runnable, VpnStateSe { return; } + sDnsDiagAt = SystemClock.elapsedRealtime(); mDiagExecutor.execute(() -> { try { @@ -1248,8 +1249,17 @@ public class CharonVpnService extends VpnService implements Runnable, VpnStateSe } } + /* a flapping tunnel must not repeat the probes (three lookups and a TCP + * connect per DoT address) on every reconnect: the radio pays for each */ + private static final long DNS_DIAG_MIN_GAP_MS = 10 * 60 * 1000; + private static volatile long sDnsDiagAt; + private void scheduleDnsDiagnostics() { + if (sDnsDiagAt != 0 && SystemClock.elapsedRealtime() - sDnsDiagAt < DNS_DIAG_MIN_GAP_MS) + { + return; + } mHandler.removeCallbacks(mDnsDiagRunnable); mHandler.postDelayed(mDnsDiagRunnable, DNS_DIAG_DELAY_MS); } diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/logic/protection/SecureDns.kt b/src/frontends/android/app/src/main/java/org/strongswan/android/logic/protection/SecureDns.kt index 03df8640e..b18243367 100644 --- a/src/frontends/android/app/src/main/java/org/strongswan/android/logic/protection/SecureDns.kt +++ b/src/frontends/android/app/src/main/java/org/strongswan/android/logic/protection/SecureDns.kt @@ -291,7 +291,11 @@ object SecureDns { val socket = DatagramSocket(InetSocketAddress(InetAddress.getByName("127.0.0.1"), 0)) val executor = ThreadPoolExecutor(WORKERS, WORKERS, 60, TimeUnit.SECONDS, ArrayBlockingQueue(256), - { r -> Thread(r, "SecureDns-worker").apply { isDaemon = true } }, ThreadPoolExecutor.DiscardPolicy()) + { r -> + /* a worker that times out or is shut down closes its DoT connection, + * otherwise the TLS socket lingers until the garbage collector finds it */ + Thread({ try { r.run() } finally { dot.get()?.close(); dot.remove() } }, "SecureDns-worker").apply { isDaemon = true } + }, ThreadPoolExecutor.DiscardPolicy()) executor.allowCoreThreadTimeOut(true) server = socket serverConfig = config diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/compose/HomeViewModel.kt b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/compose/HomeViewModel.kt index 2488597d3..3ea44b5b5 100644 --- a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/compose/HomeViewModel.kt +++ b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/compose/HomeViewModel.kt @@ -857,7 +857,8 @@ class HomeViewModel(app: Application) : AndroidViewModel(app), VpnStateService.V companion object { private const val TRAFFIC_POLL_MS = 1000L - private const val PROBE_INTERVAL_MS = 10_000L + /* 10 s kept the cellular radio out of its idle state for as long as Home was open */ + private const val PROBE_INTERVAL_MS = 30_000L private const val EXIT_REFRESH_MS = 60_000L private const val EXIT_TIMEOUT_MS = 5000 private const val FASTEST_TIMEOUT_MS = 1500