mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-11-15 15:32:21 +08:00
fix(tun): make the TUN switch reflect what the Core actually runs
The switch read enable_tun_mode while the Core was given enable_tun_mode && !session_suppression, so falling back to Sidecar left it showing a TUN that was not running, with nothing to write the flag back. Drop the session flag: the stored preference is the only truth, re-checked at startup and written off when the conditions for it are not met, and the switch renders it against current capability.
This commit is contained in:
@@ -320,15 +320,34 @@ impl CoreManager {
|
||||
defer! {
|
||||
self.finish_config_update();
|
||||
}
|
||||
// Lock order is config then lifecycle. disable_tun_and_persist commits the shared Verge
|
||||
// draft without claiming it, so without this it can commit another transaction's staged patch.
|
||||
let config_write = Config::lock_config_write().await;
|
||||
let _life = self.lifecycle_lock.lock().await;
|
||||
let status = SERVICE_MANAGER.current().await;
|
||||
let mode = self.get_running_mode();
|
||||
if !can_allow_sidecar_for_session(&mode, &status) {
|
||||
anyhow::bail!("Sidecar continuation is not allowed from {mode:?} / {status:?}");
|
||||
}
|
||||
Config::suppress_tun_for_session().await;
|
||||
Config::generate().await?;
|
||||
SERVICE_MANAGER.allow_sidecar_for_session()?;
|
||||
// Settling on Sidecar is what makes the verdict final, so ask only once it is recorded.
|
||||
// Elevation alone carries TUN on Sidecar; a Sidecar that cannot must write it off.
|
||||
let prepared = async {
|
||||
let tun_enabled = Config::verge().await.latest_arc().enable_tun_mode.unwrap_or(false);
|
||||
if crate::core::runstate::RUN_STATE
|
||||
.state()
|
||||
.tun_should_be_disabled(tun_enabled)
|
||||
{
|
||||
Config::disable_tun_and_persist().await?;
|
||||
}
|
||||
Config::generate().await
|
||||
}
|
||||
.await;
|
||||
drop(config_write);
|
||||
if let Err(error) = prepared {
|
||||
SERVICE_MANAGER.withdraw_sidecar_allowance();
|
||||
return Err(error);
|
||||
}
|
||||
// Drop the guard last so an earlier failure cannot leave a running Sidecar unguarded.
|
||||
proxy_control::stop_guard().await;
|
||||
let result = async {
|
||||
@@ -360,6 +379,8 @@ impl CoreManager {
|
||||
defer! {
|
||||
self.finish_config_update();
|
||||
}
|
||||
// Lock order is config then lifecycle, for the unclaimed draft write below.
|
||||
let _config_write = Config::lock_config_write().await;
|
||||
let _life = self.lifecycle_lock.lock().await;
|
||||
|
||||
self.controlled_stop_core_inner().await?;
|
||||
@@ -371,7 +392,14 @@ impl CoreManager {
|
||||
.await
|
||||
},
|
||||
|| async {
|
||||
Config::disable_tun_and_persist().await?;
|
||||
// Must be asked after the uninstall: until then the Service still makes TUN capable.
|
||||
let tun_enabled = Config::verge().await.latest_arc().enable_tun_mode.unwrap_or(false);
|
||||
if crate::core::runstate::RUN_STATE
|
||||
.state()
|
||||
.tun_should_be_disabled(tun_enabled)
|
||||
{
|
||||
Config::disable_tun_and_persist().await?;
|
||||
}
|
||||
Config::generate().await
|
||||
},
|
||||
|| async {
|
||||
@@ -597,8 +625,7 @@ impl CoreManager {
|
||||
#[cfg(target_os = "windows")]
|
||||
self.wait_for_service_if_needed().await;
|
||||
|
||||
let service_required = Config::verge().await.latest_arc().enable_tun_mode.unwrap_or(false)
|
||||
&& !Config::tun_suppressed_for_session();
|
||||
let service_required = Config::verge().await.latest_arc().enable_tun_mode.unwrap_or(false);
|
||||
if service_required
|
||||
&& matches!(SERVICE_MANAGER.current().await, ServiceStatus::NotInstalled)
|
||||
&& SERVICE_MANAGER.require_install_for_session().is_err()
|
||||
@@ -645,8 +672,9 @@ impl CoreManager {
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::time::Instant;
|
||||
|
||||
// An accepted Sidecar is the user's decision for this session, not a wait for the Service.
|
||||
let needs_service = Config::verge().await.latest_arc().enable_tun_mode.unwrap_or(false)
|
||||
&& !Config::tun_suppressed_for_session();
|
||||
&& !crate::core::runstate::RUN_STATE.state().sidecar_allowed;
|
||||
if !needs_service {
|
||||
return;
|
||||
}
|
||||
@@ -701,6 +729,10 @@ impl CoreManager {
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
async fn try_handoff_sidecar_to_service(&self) -> HandoffOutcome {
|
||||
// Before probing: a probe reply records an observation, which clears sidecar_allowed.
|
||||
if crate::core::runstate::RUN_STATE.state().sidecar_allowed {
|
||||
return HandoffOutcome::Done;
|
||||
}
|
||||
if !Self::refresh_service_readiness_for_handoff().await {
|
||||
return HandoffOutcome::NotReady;
|
||||
}
|
||||
@@ -717,7 +749,7 @@ impl CoreManager {
|
||||
|
||||
if !matches!(*self.get_running_mode(), RunningMode::Sidecar)
|
||||
|| !Config::verge().await.latest_arc().enable_tun_mode.unwrap_or(false)
|
||||
|| Config::tun_suppressed_for_session()
|
||||
|| crate::core::runstate::RUN_STATE.state().sidecar_allowed
|
||||
{
|
||||
return HandoffOutcome::Done;
|
||||
}
|
||||
|
||||
@@ -95,7 +95,7 @@ impl RunState {
|
||||
!matches!(self.health, ServiceHealth::Unknown) && !self.op_in_flight && !self.service_needs_attention()
|
||||
}
|
||||
|
||||
/// Present-but-broken services remain in the repair flow rather than suppressing TUN.
|
||||
/// Present-but-broken services remain in the repair flow rather than being disabled here.
|
||||
#[must_use]
|
||||
pub const fn startup_tun_should_be_disabled(&self, tun_enabled: bool) -> bool {
|
||||
matches!(self.health, ServiceHealth::NotInstalled) && self.tun_should_be_disabled(tun_enabled)
|
||||
|
||||
@@ -1327,7 +1327,6 @@ impl ServiceManager {
|
||||
RUN_STATE.perform(action).await?;
|
||||
if !matches!(action, PendingAction::Uninstall) {
|
||||
wait_for_service_ipc().await?;
|
||||
Config::restore_tun_for_session().await;
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
|
||||
@@ -63,7 +63,7 @@ pub struct Tray {
|
||||
|
||||
impl TrayState {
|
||||
async fn get_tray_icon(verge: &IVerge) -> (bool, Cow<'_, [u8]>) {
|
||||
let tun_mode = verge.enable_tun_mode.unwrap_or(false);
|
||||
let tun_mode = verge.enable_tun_mode.unwrap_or(false) && crate::core::runstate::RUN_STATE.state().tun_capable();
|
||||
let system_mode = verge.enable_system_proxy.unwrap_or(false);
|
||||
let kind = if tun_mode {
|
||||
IconKind::Tun
|
||||
@@ -284,7 +284,7 @@ impl Tray {
|
||||
|
||||
let verge = Config::verge().await.latest_arc();
|
||||
let system_proxy = verge.enable_system_proxy.unwrap_or(false);
|
||||
let tun_mode = verge.enable_tun_mode.unwrap_or(false);
|
||||
let tun_mode = verge.enable_tun_mode.unwrap_or(false) && crate::core::runstate::RUN_STATE.state().tun_capable();
|
||||
|
||||
let switch_str = |flag: bool| {
|
||||
if flag { "on" } else { "off" }
|
||||
|
||||
Reference in New Issue
Block a user