From fe78e2d5cd8e141dfb79fe49a91b711dd70e1311 Mon Sep 17 00:00:00 2001 From: Slinetrac Date: Thu, 16 Oct 2025 15:09:17 +0800 Subject: [PATCH] fix(windows): wait for service readiness before enabling TUN --- src-tauri/src/core/core.rs | 85 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/src-tauri/src/core/core.rs b/src-tauri/src/core/core.rs index 229c841e..aa6b2592 100644 --- a/src-tauri/src/core/core.rs +++ b/src-tauri/src/core/core.rs @@ -944,7 +944,92 @@ impl CoreManager { (*guard).clone() } + #[cfg(target_os = "windows")] + async fn wait_for_service_ready_if_tun_enabled(&self) { + let require_service = Config::verge() + .await + .latest_ref() + .enable_tun_mode + .unwrap_or(false); + + if !require_service { + return; + } + + const MAX_ATTEMPTS: usize = 15; + const WAIT_INTERVAL_MS: u64 = 200; + + for attempt in 0..MAX_ATTEMPTS { + let mut manager = SERVICE_MANAGER.lock().await; + + if matches!(manager.current(), ServiceStatus::Ready) { + if attempt > 0 { + logging!( + info, + Type::Core, + "Service became ready for TUN after {} attempt(s)", + attempt + ); + } + return; + } + + if attempt == 0 { + logging!( + info, + Type::Core, + "TUN mode enabled but service not ready; waiting for service availability" + ); + } + + match manager.init().await { + Ok(_) => { + logging_error!(Type::Core, manager.refresh().await); + } + Err(err) => { + logging!( + debug, + Type::Core, + "Service connection attempt {} failed while waiting for TUN: {}", + attempt + 1, + err + ); + } + } + + if matches!(manager.current(), ServiceStatus::Ready) { + logging!( + info, + Type::Core, + "Service became ready for TUN after {} attempt(s)", + attempt + 1 + ); + return; + } + + drop(manager); + + if attempt + 1 == MAX_ATTEMPTS { + let total_wait_ms = (MAX_ATTEMPTS as u64) * WAIT_INTERVAL_MS; + logging!( + warn, + Type::Core, + "Service still not ready after waiting approximately {} ms; falling back to sidecar mode", + total_wait_ms + ); + break; + } + + sleep(Duration::from_millis(WAIT_INTERVAL_MS)).await; + } + } + + #[cfg(not(target_os = "windows"))] + async fn wait_for_service_ready_if_tun_enabled(&self) {} + pub async fn prestart_core(&self) -> Result<()> { + self.wait_for_service_ready_if_tun_enabled().await; + match SERVICE_MANAGER.lock().await.current() { ServiceStatus::Ready => { self.set_running_mode(RunningMode::Service);