diff --git a/src-tauri/src/cmd/network.rs b/src-tauri/src/cmd/network.rs index c0dedfde..9ccea946 100644 --- a/src-tauri/src/cmd/network.rs +++ b/src-tauri/src/cmd/network.rs @@ -1,7 +1,5 @@ use super::CmdResult; use crate::cmd::StringifyErr; -use crate::core::{EventDrivenProxyManager, async_proxy_query::AsyncProxyQuery}; -use crate::process::AsyncHandler; use crate::{logging, utils::logging::Type}; use network_interface::NetworkInterface; use serde_yaml_ng::Mapping; @@ -11,23 +9,23 @@ use serde_yaml_ng::Mapping; pub async fn get_sys_proxy() -> CmdResult { logging!(debug, Type::Network, "异步获取系统代理配置"); - let current = AsyncProxyQuery::get_system_proxy().await; + let sys_proxy = sysproxy::Sysproxy::get_system_proxy().stringify_err()?; let mut map = Mapping::new(); - map.insert("enable".into(), current.enable.into()); + map.insert("enable".into(), sys_proxy.enable.into()); map.insert( "server".into(), - format!("{}:{}", current.host, current.port).into(), + format!("{}:{}", sys_proxy.host, sys_proxy.port).into(), ); - map.insert("bypass".into(), current.bypass.into()); + map.insert("bypass".into(), sys_proxy.bypass.into()); logging!( debug, Type::Network, "返回系统代理配置: enable={}, {}:{}", - current.enable, - current.host, - current.port + sys_proxy.enable, + sys_proxy.host, + sys_proxy.port ); Ok(map) } @@ -37,24 +35,18 @@ pub async fn get_sys_proxy() -> CmdResult { pub async fn get_auto_proxy() -> CmdResult { logging!(debug, Type::Network, "开始获取自动代理配置(事件驱动)"); - let proxy_manager = EventDrivenProxyManager::global(); - - let current = proxy_manager.get_auto_proxy_cached().await; - // 异步请求更新,立即返回缓存数据 - AsyncHandler::spawn(move || async move { - let _ = proxy_manager.get_auto_proxy_async().await; - }); + let auto_proxy = sysproxy::Autoproxy::get_auto_proxy().stringify_err()?; let mut map = Mapping::new(); - map.insert("enable".into(), current.enable.into()); - map.insert("url".into(), current.url.clone().into()); + map.insert("enable".into(), auto_proxy.enable.into()); + map.insert("url".into(), auto_proxy.url.clone().into()); logging!( debug, Type::Network, "返回自动代理配置(缓存): enable={}, url={}", - current.enable, - current.url + auto_proxy.enable, + auto_proxy.url ); Ok(map) } diff --git a/src-tauri/src/constants.rs b/src-tauri/src/constants.rs index 3195ea40..07dc1bdf 100644 --- a/src-tauri/src/constants.rs +++ b/src-tauri/src/constants.rs @@ -1,7 +1,6 @@ use std::time::Duration; pub mod network { - pub const DEFAULT_PROXY_HOST: &str = "127.0.0.1"; pub const DEFAULT_EXTERNAL_CONTROLLER: &str = "127.0.0.1:9097"; pub mod ports { @@ -27,9 +26,6 @@ pub mod bypass { #[cfg(target_os = "linux")] pub const DEFAULT: &str = "localhost,127.0.0.1,192.168.0.0/16,10.0.0.0/8,172.16.0.0/12,172.29.0.0/16,::1"; - - #[cfg(target_os = "macos")] - pub const DEFAULT: &str = "127.0.0.1,192.168.0.0/16,10.0.0.0/8,172.16.0.0/12,172.29.0.0/16,localhost,*.local,*.crashlytics.com,"; } pub mod timing { diff --git a/src-tauri/src/core/async_proxy_query.rs b/src-tauri/src/core/async_proxy_query.rs deleted file mode 100644 index c9e31c67..00000000 --- a/src-tauri/src/core/async_proxy_query.rs +++ /dev/null @@ -1,562 +0,0 @@ -#[cfg(target_os = "windows")] -use crate::process::AsyncHandler; -use crate::{logging, utils::logging::Type}; -use anyhow::Result; -use serde::{Deserialize, Serialize}; -use tokio::time::{Duration, timeout}; - -#[cfg(target_os = "linux")] -use anyhow::anyhow; -#[cfg(not(target_os = "windows"))] -use tokio::process::Command; - -#[derive(Debug, Clone, Serialize, Deserialize, Default)] -pub struct AsyncAutoproxy { - pub enable: bool, - pub url: String, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct AsyncSysproxy { - pub enable: bool, - pub host: String, - pub port: u16, - pub bypass: String, -} - -impl Default for AsyncSysproxy { - fn default() -> Self { - Self { - enable: false, - host: "127.0.0.1".into(), - port: 7897, - bypass: String::new(), - } - } -} - -pub struct AsyncProxyQuery; - -impl AsyncProxyQuery { - /// 异步获取自动代理配置(PAC) - pub async fn get_auto_proxy() -> AsyncAutoproxy { - match timeout(Duration::from_secs(3), Self::get_auto_proxy_impl()).await { - Ok(Ok(proxy)) => { - logging!( - debug, - Type::Network, - "异步获取自动代理成功: enable={}, url={}", - proxy.enable, - proxy.url - ); - proxy - } - Ok(Err(e)) => { - logging!(warn, Type::Network, "Warning: 异步获取自动代理失败: {e}"); - AsyncAutoproxy::default() - } - Err(_) => { - logging!(warn, Type::Network, "Warning: 异步获取自动代理超时"); - AsyncAutoproxy::default() - } - } - } - - /// 异步获取系统代理配置 - pub async fn get_system_proxy() -> AsyncSysproxy { - match timeout(Duration::from_secs(3), Self::get_system_proxy_impl()).await { - Ok(Ok(proxy)) => { - logging!( - debug, - Type::Network, - "异步获取系统代理成功: enable={}, {}:{}", - proxy.enable, - proxy.host, - proxy.port - ); - proxy - } - Ok(Err(e)) => { - logging!(warn, Type::Network, "Warning: 异步获取系统代理失败: {e}"); - AsyncSysproxy::default() - } - Err(_) => { - logging!(warn, Type::Network, "Warning: 异步获取系统代理超时"); - AsyncSysproxy::default() - } - } - } - - #[cfg(target_os = "windows")] - async fn get_auto_proxy_impl() -> Result { - // Windows: 从注册表读取PAC配置 - AsyncHandler::spawn_blocking(move || -> Result { - Self::get_pac_config_from_registry() - }) - .await? - } - - #[cfg(target_os = "windows")] - fn get_pac_config_from_registry() -> Result { - use std::ptr; - use winapi::shared::minwindef::{DWORD, HKEY}; - use winapi::um::winnt::{KEY_READ, REG_DWORD, REG_SZ}; - use winapi::um::winreg::{HKEY_CURRENT_USER, RegCloseKey, RegOpenKeyExW, RegQueryValueExW}; - - unsafe { - let key_path = "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\0" - .encode_utf16() - .collect::>(); - - let mut hkey: HKEY = ptr::null_mut(); - let result = - RegOpenKeyExW(HKEY_CURRENT_USER, key_path.as_ptr(), 0, KEY_READ, &mut hkey); - - if result != 0 { - logging!(debug, Type::Network, "无法打开注册表项"); - return Ok(AsyncAutoproxy::default()); - } - - // 1. 检查自动配置是否启用 (AutoConfigURL 存在且不为空即表示启用) - let auto_config_url_name = "AutoConfigURL\0".encode_utf16().collect::>(); - let mut url_buffer = vec![0u16; 1024]; - let mut url_buffer_size: DWORD = (url_buffer.len() * 2) as DWORD; - let mut url_value_type: DWORD = 0; - - let url_query_result = RegQueryValueExW( - hkey, - auto_config_url_name.as_ptr(), - ptr::null_mut(), - &mut url_value_type, - url_buffer.as_mut_ptr() as *mut u8, - &mut url_buffer_size, - ); - - let mut pac_url = String::new(); - if url_query_result == 0 && url_value_type == REG_SZ && url_buffer_size > 0 { - let end_pos = url_buffer - .iter() - .position(|&x| x == 0) - .unwrap_or(url_buffer.len()); - pac_url = String::from_utf16_lossy(&url_buffer[..end_pos]); - logging!(debug, Type::Network, "从注册表读取到PAC URL: {pac_url}"); - } - - // 2. 检查自动检测设置是否启用 - let auto_detect_name = "AutoDetect\0".encode_utf16().collect::>(); - let mut auto_detect: DWORD = 0; - let mut detect_buffer_size: DWORD = 4; - let mut detect_value_type: DWORD = 0; - - let detect_query_result = RegQueryValueExW( - hkey, - auto_detect_name.as_ptr(), - ptr::null_mut(), - &mut detect_value_type, - &mut auto_detect as *mut DWORD as *mut u8, - &mut detect_buffer_size, - ); - - RegCloseKey(hkey); - - // PAC 启用的条件:AutoConfigURL 不为空,或 AutoDetect 被启用 - let pac_enabled = !pac_url.is_empty() - || (detect_query_result == 0 && detect_value_type == REG_DWORD && auto_detect != 0); - - if pac_enabled { - logging!( - debug, - Type::Network, - "PAC配置启用: URL={pac_url}, AutoDetect={auto_detect}" - ); - - if pac_url.is_empty() && auto_detect != 0 { - pac_url = "auto-detect".into(); - } - - Ok(AsyncAutoproxy { - enable: true, - url: pac_url, - }) - } else { - logging!(debug, Type::Network, "PAC配置未启用"); - Ok(AsyncAutoproxy::default()) - } - } - } - - #[cfg(target_os = "macos")] - async fn get_auto_proxy_impl() -> Result { - // macOS: 使用 scutil --proxy 命令 - let output = Command::new("scutil").args(["--proxy"]).output().await?; - - if !output.status.success() { - return Ok(AsyncAutoproxy::default()); - } - - let stdout = String::from_utf8_lossy(&output.stdout); - crate::logging!( - debug, - crate::utils::logging::Type::Network, - "scutil output: {stdout}" - ); - - let mut pac_enabled = false; - let mut pac_url = String::new(); - - // 解析 scutil 输出 - for line in stdout.lines() { - let line = line.trim(); - if line.contains("ProxyAutoConfigEnable") && line.contains("1") { - pac_enabled = true; - } else if line.contains("ProxyAutoConfigURLString") { - // 正确解析包含冒号的URL - // 格式: "ProxyAutoConfigURLString : http://127.0.0.1:11233/commands/pac" - if let Some(colon_pos) = line.find(" : ") { - pac_url = line[colon_pos + 3..].trim().into(); - } - } - } - - crate::logging!( - debug, - crate::utils::logging::Type::Network, - "解析结果: pac_enabled={pac_enabled}, pac_url={pac_url}" - ); - - Ok(AsyncAutoproxy { - enable: pac_enabled && !pac_url.is_empty(), - url: pac_url, - }) - } - - #[cfg(target_os = "linux")] - async fn get_auto_proxy_impl() -> Result { - // Linux: 检查环境变量和GNOME设置 - - // 首先检查环境变量 - if let Ok(auto_proxy) = std::env::var("auto_proxy") - && !auto_proxy.is_empty() - { - return Ok(AsyncAutoproxy { - enable: true, - url: auto_proxy, - }); - } - - // 尝试使用 gsettings 获取 GNOME 代理设置 - let output = Command::new("gsettings") - .args(["get", "org.gnome.system.proxy", "mode"]) - .output() - .await; - - if let Ok(output) = output - && output.status.success() - { - let mode: String = String::from_utf8_lossy(&output.stdout).trim().into(); - if mode.contains("auto") { - // 获取 PAC URL - let pac_output = Command::new("gsettings") - .args(["get", "org.gnome.system.proxy", "autoconfig-url"]) - .output() - .await; - - if let Ok(pac_output) = pac_output - && pac_output.status.success() - { - let pac_url: String = String::from_utf8_lossy(&pac_output.stdout) - .trim() - .trim_matches('\'') - .trim_matches('"') - .into(); - - if !pac_url.is_empty() { - return Ok(AsyncAutoproxy { - enable: true, - url: pac_url, - }); - } - } - } - } - - Ok(AsyncAutoproxy::default()) - } - - #[cfg(target_os = "windows")] - async fn get_system_proxy_impl() -> Result { - // Windows: 使用注册表直接读取代理设置 - AsyncHandler::spawn_blocking(move || -> Result { - Self::get_system_proxy_from_registry() - }) - .await? - } - - #[cfg(target_os = "windows")] - fn get_system_proxy_from_registry() -> Result { - use std::ptr; - use winapi::shared::minwindef::{DWORD, HKEY}; - use winapi::um::winnt::{KEY_READ, REG_DWORD, REG_SZ}; - use winapi::um::winreg::{HKEY_CURRENT_USER, RegCloseKey, RegOpenKeyExW, RegQueryValueExW}; - - unsafe { - let key_path = "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\0" - .encode_utf16() - .collect::>(); - - let mut hkey: HKEY = ptr::null_mut(); - let result = - RegOpenKeyExW(HKEY_CURRENT_USER, key_path.as_ptr(), 0, KEY_READ, &mut hkey); - - if result != 0 { - return Ok(AsyncSysproxy::default()); - } - - // 检查代理是否启用 - let proxy_enable_name = "ProxyEnable\0".encode_utf16().collect::>(); - let mut proxy_enable: DWORD = 0; - let mut buffer_size: DWORD = 4; - let mut value_type: DWORD = 0; - - let enable_result = RegQueryValueExW( - hkey, - proxy_enable_name.as_ptr(), - ptr::null_mut(), - &mut value_type, - &mut proxy_enable as *mut DWORD as *mut u8, - &mut buffer_size, - ); - - if enable_result != 0 || value_type != REG_DWORD || proxy_enable == 0 { - RegCloseKey(hkey); - return Ok(AsyncSysproxy::default()); - } - - // 读取代理服务器设置 - let proxy_server_name = "ProxyServer\0".encode_utf16().collect::>(); - let mut buffer = vec![0u16; 1024]; - let mut buffer_size: DWORD = (buffer.len() * 2) as DWORD; - let mut value_type: DWORD = 0; - - let server_result = RegQueryValueExW( - hkey, - proxy_server_name.as_ptr(), - ptr::null_mut(), - &mut value_type, - buffer.as_mut_ptr() as *mut u8, - &mut buffer_size, - ); - - let mut proxy_server = String::new(); - if server_result == 0 && value_type == REG_SZ && buffer_size > 0 { - let end_pos = buffer.iter().position(|&x| x == 0).unwrap_or(buffer.len()); - proxy_server = String::from_utf16_lossy(&buffer[..end_pos]); - } - - // 读取代理绕过列表 - let proxy_override_name = "ProxyOverride\0".encode_utf16().collect::>(); - let mut bypass_buffer = vec![0u16; 1024]; - let mut bypass_buffer_size: DWORD = (bypass_buffer.len() * 2) as DWORD; - let mut bypass_value_type: DWORD = 0; - - let override_result = RegQueryValueExW( - hkey, - proxy_override_name.as_ptr(), - ptr::null_mut(), - &mut bypass_value_type, - bypass_buffer.as_mut_ptr() as *mut u8, - &mut bypass_buffer_size, - ); - - let mut bypass_list = String::new(); - if override_result == 0 && bypass_value_type == REG_SZ && bypass_buffer_size > 0 { - let end_pos = bypass_buffer - .iter() - .position(|&x| x == 0) - .unwrap_or(bypass_buffer.len()); - bypass_list = String::from_utf16_lossy(&bypass_buffer[..end_pos]); - } - - RegCloseKey(hkey); - - if !proxy_server.is_empty() { - // 解析服务器地址和端口 - let (host, port) = if let Some(colon_pos) = proxy_server.rfind(':') { - let host = proxy_server[..colon_pos].into(); - let port = proxy_server[colon_pos + 1..].parse::().unwrap_or(8080); - (host, port) - } else { - (proxy_server, 8080) - }; - - logging!( - debug, - Type::Network, - "从注册表读取到代理设置: {host}:{port}, bypass: {bypass_list}" - ); - - Ok(AsyncSysproxy { - enable: true, - host, - port, - bypass: bypass_list, - }) - } else { - Ok(AsyncSysproxy::default()) - } - } - } - - #[cfg(target_os = "macos")] - async fn get_system_proxy_impl() -> Result { - let output = Command::new("scutil").args(["--proxy"]).output().await?; - - if !output.status.success() { - return Ok(AsyncSysproxy::default()); - } - - let stdout = String::from_utf8_lossy(&output.stdout); - logging!(debug, Type::Network, "scutil proxy output: {stdout}"); - - let mut http_enabled = false; - let mut http_host = String::new(); - let mut http_port = 8080u16; - let mut exceptions: Vec = Vec::new(); - - for line in stdout.lines() { - let line = line.trim(); - if line.contains("HTTPEnable") && line.contains("1") { - http_enabled = true; - } else if line.contains("HTTPProxy") && !line.contains("Port") { - if let Some(host_part) = line.split(':').nth(1) { - http_host = host_part.trim().into(); - } - } else if line.contains("HTTPPort") { - if let Some(port_part) = line.split(':').nth(1) - && let Ok(port) = port_part.trim().parse::() - { - http_port = port; - } - } else if line.contains("ExceptionsList") { - // 解析异常列表 - if let Some(list_part) = line.split(':').nth(1) { - let list = list_part.trim(); - if !list.is_empty() { - exceptions.push(list.into()); - } - } - } - } - - Ok(AsyncSysproxy { - enable: http_enabled && !http_host.is_empty(), - host: http_host, - port: http_port, - bypass: exceptions.join(","), - }) - } - - #[cfg(target_os = "linux")] - async fn get_system_proxy_impl() -> Result { - // Linux: 检查环境变量和桌面环境设置 - - // 首先检查环境变量 - if let Ok(http_proxy) = std::env::var("http_proxy") - && let Ok(proxy_info) = Self::parse_proxy_url(&http_proxy) - { - return Ok(proxy_info); - } - - if let Ok(https_proxy) = std::env::var("https_proxy") - && let Ok(proxy_info) = Self::parse_proxy_url(&https_proxy) - { - return Ok(proxy_info); - } - - // 尝试使用 gsettings 获取 GNOME 代理设置 - let mode_output = Command::new("gsettings") - .args(["get", "org.gnome.system.proxy", "mode"]) - .output() - .await; - - if let Ok(mode_output) = mode_output - && mode_output.status.success() - { - let mode: String = String::from_utf8_lossy(&mode_output.stdout).trim().into(); - if mode.contains("manual") { - // 获取HTTP代理设置 - let host_result = Command::new("gsettings") - .args(["get", "org.gnome.system.proxy.http", "host"]) - .output() - .await; - - let port_result = Command::new("gsettings") - .args(["get", "org.gnome.system.proxy.http", "port"]) - .output() - .await; - - if let (Ok(host_output), Ok(port_output)) = (host_result, port_result) - && host_output.status.success() - && port_output.status.success() - { - let host: String = String::from_utf8_lossy(&host_output.stdout) - .trim() - .trim_matches('\'') - .trim_matches('"') - .into(); - - let port = String::from_utf8_lossy(&port_output.stdout) - .trim() - .parse::() - .unwrap_or(8080); - - if !host.is_empty() { - return Ok(AsyncSysproxy { - enable: true, - host, - port, - bypass: String::new(), - }); - } - } - } - } - - Ok(AsyncSysproxy::default()) - } - - #[cfg(target_os = "linux")] - fn parse_proxy_url(proxy_url: &str) -> Result { - // 解析形如 "http://proxy.example.com:8080" 的URL - let url = proxy_url.trim(); - - // 移除协议前缀 - let url = if let Some(stripped) = url.strip_prefix("http://") { - stripped - } else if let Some(stripped) = url.strip_prefix("https://") { - stripped - } else { - url - }; - - // 解析主机和端口 - let (host, port) = if let Some(colon_pos) = url.rfind(':') { - let host: String = url[..colon_pos].into(); - let port = url[colon_pos + 1..].parse::().unwrap_or(8080); - (host, port) - } else { - (url.into(), 8080) - }; - - if host.is_empty() { - return Err(anyhow!("无效的代理URL")); - } - - Ok(AsyncSysproxy { - enable: true, - host, - port, - bypass: std::env::var("no_proxy").unwrap_or_default(), - }) - } -} diff --git a/src-tauri/src/core/event_driven_proxy.rs b/src-tauri/src/core/event_driven_proxy.rs deleted file mode 100644 index 18a6f155..00000000 --- a/src-tauri/src/core/event_driven_proxy.rs +++ /dev/null @@ -1,548 +0,0 @@ -use std::sync::Arc; -use tokio::sync::RwLock; -use tokio::sync::{mpsc, oneshot}; -use tokio::time::{Duration, sleep, timeout}; -use tokio_stream::{StreamExt, wrappers::UnboundedReceiverStream}; - -use crate::config::{Config, IVerge}; -use crate::core::{async_proxy_query::AsyncProxyQuery, handle}; -use crate::process::AsyncHandler; -use crate::{logging, utils::logging::Type}; -use once_cell::sync::Lazy; -use smartstring::alias::String; -use sysproxy::{Autoproxy, Sysproxy}; - -#[derive(Debug, Clone)] -pub enum ProxyEvent { - /// 配置变更事件 - ConfigChanged, - /// 应用启动事件 - AppStarted, - /// 应用关闭事件 - AppStopping, -} - -#[derive(Debug, Clone)] -pub struct ProxyState { - pub sys_enabled: bool, - pub pac_enabled: bool, - pub auto_proxy: Autoproxy, - pub sys_proxy: Sysproxy, - pub last_updated: std::time::Instant, - pub is_healthy: bool, -} - -impl Default for ProxyState { - fn default() -> Self { - Self { - sys_enabled: false, - pac_enabled: false, - auto_proxy: Autoproxy { - enable: false, - url: "".into(), - }, - sys_proxy: Sysproxy { - enable: false, - host: "127.0.0.1".into(), - port: 7897, - bypass: "".into(), - }, - last_updated: std::time::Instant::now(), - is_healthy: true, - } - } -} - -pub struct EventDrivenProxyManager { - state: Arc>, - event_sender: mpsc::UnboundedSender, - query_sender: mpsc::UnboundedSender, -} - -#[derive(Debug)] -pub struct QueryRequest { - response_tx: oneshot::Sender, -} - -// 配置结构体移到外部 -struct ProxyConfig { - sys_enabled: bool, - pac_enabled: bool, - guard_enabled: bool, - guard_duration: u64, -} - -static PROXY_MANAGER: Lazy = Lazy::new(EventDrivenProxyManager::new); - -impl EventDrivenProxyManager { - pub fn global() -> &'static EventDrivenProxyManager { - &PROXY_MANAGER - } - - fn new() -> Self { - let state = Arc::new(RwLock::new(ProxyState::default())); - let (event_tx, event_rx) = mpsc::unbounded_channel(); - let (query_tx, query_rx) = mpsc::unbounded_channel(); - - let state_clone = Arc::clone(&state); - AsyncHandler::spawn(move || Self::start_event_loop(state_clone, event_rx, query_rx)); - - Self { - state, - event_sender: event_tx, - query_sender: query_tx, - } - } - - /// 获取自动代理配置(缓存) - pub async fn get_auto_proxy_cached(&self) -> Autoproxy { - self.state.read().await.auto_proxy.clone() - } - - /// 异步获取最新的自动代理配置 - pub async fn get_auto_proxy_async(&self) -> Autoproxy { - let (tx, rx) = oneshot::channel(); - let query = QueryRequest { response_tx: tx }; - - if self.query_sender.send(query).is_err() { - logging!(error, Type::Network, "发送查询请求失败,返回缓存数据"); - return self.get_auto_proxy_cached().await; - } - - match timeout(Duration::from_secs(5), rx).await { - Ok(Ok(result)) => result, - _ => { - logging!(warn, Type::Network, "Warning: 查询超时,返回缓存数据"); - self.get_auto_proxy_cached().await - } - } - } - - /// 通知配置变更 - pub fn notify_config_changed(&self) { - self.send_event(ProxyEvent::ConfigChanged); - } - - /// 通知应用启动 - pub fn notify_app_started(&self) { - self.send_event(ProxyEvent::AppStarted); - } - - /// 通知应用即将关闭 - pub fn notify_app_stopping(&self) { - self.send_event(ProxyEvent::AppStopping); - } - - fn send_event(&self, event: ProxyEvent) { - if let Err(e) = self.event_sender.send(event) { - logging!(error, Type::Network, "发送代理事件失败: {e}"); - } - } - - pub async fn start_event_loop( - state: Arc>, - event_rx: mpsc::UnboundedReceiver, - query_rx: mpsc::UnboundedReceiver, - ) { - logging!(info, Type::Network, "事件驱动代理管理器启动"); - - // 将 mpsc 接收器包装成 Stream,避免每次循环创建 future - let mut event_stream = UnboundedReceiverStream::new(event_rx); - let mut query_stream = UnboundedReceiverStream::new(query_rx); - - // 初始化定时器,用于周期性检查代理设置 - let config = Self::get_proxy_config().await; - let mut guard_interval = tokio::time::interval(Duration::from_secs(config.guard_duration)); - // 防止首次立即触发 - guard_interval.tick().await; - - loop { - tokio::select! { - Some(event) = event_stream.next() => { - logging!(debug, Type::Network, "处理代理事件: {event:?}"); - let event_clone = event.clone(); // 保存一份副本用于后续检查 - Self::handle_event(&state, event).await; - - // 检查是否是配置变更事件,如果是,则可能需要更新定时器 - if matches!(event_clone, ProxyEvent::ConfigChanged | ProxyEvent::AppStarted) { - let new_config = Self::get_proxy_config().await; - // 重新设置定时器间隔 - guard_interval = tokio::time::interval(Duration::from_secs(new_config.guard_duration)); - // 防止首次立即触发 - guard_interval.tick().await; - } - } - Some(query) = query_stream.next() => { - let result = Self::handle_query(&state).await; - let _ = query.response_tx.send(result); - } - _ = guard_interval.tick() => { - // 定时检查代理设置 - let config = Self::get_proxy_config().await; - if config.guard_enabled && config.sys_enabled { - logging!(debug, Type::Network, "定时检查代理设置"); - Self::check_and_restore_proxy(&state).await; - } - } - else => { - // 两个通道都关闭时退出 - logging!(info, Type::Network, "事件或查询通道关闭,代理管理器停止"); - break; - } - } - } - } - - async fn handle_event(state: &Arc>, event: ProxyEvent) { - match event { - ProxyEvent::ConfigChanged => { - Self::update_proxy_config(state).await; - } - ProxyEvent::AppStarted => { - Self::initialize_proxy_state(state).await; - } - ProxyEvent::AppStopping => { - logging!(info, Type::Network, "清理代理状态"); - Self::update_state_timestamp(state, |s| { - s.sys_enabled = false; - s.pac_enabled = false; - s.is_healthy = false; - }) - .await; - } - } - } - - async fn handle_query(state: &Arc>) -> Autoproxy { - let auto_proxy = Self::get_auto_proxy_with_timeout().await; - - Self::update_state_timestamp(state, |s| { - s.auto_proxy = auto_proxy.clone(); - }) - .await; - - auto_proxy - } - - async fn initialize_proxy_state(state: &Arc>) { - logging!(info, Type::Network, "初始化代理状态"); - - let config = Self::get_proxy_config().await; - let auto_proxy = Self::get_auto_proxy_with_timeout().await; - let sys_proxy = Self::get_sys_proxy_with_timeout().await; - - Self::update_state_timestamp(state, |s| { - s.sys_enabled = config.sys_enabled; - s.pac_enabled = config.pac_enabled; - s.auto_proxy = auto_proxy; - s.sys_proxy = sys_proxy; - s.is_healthy = true; - }) - .await; - - logging!( - info, - Type::Network, - "代理状态初始化完成: sys={}, pac={}", - config.sys_enabled, - config.pac_enabled - ); - } - - async fn update_proxy_config(state: &Arc>) { - logging!(debug, Type::Network, "更新代理配置"); - - let config = Self::get_proxy_config().await; - - Self::update_state_timestamp(state, |s| { - s.sys_enabled = config.sys_enabled; - s.pac_enabled = config.pac_enabled; - }) - .await; - - if config.guard_enabled && config.sys_enabled { - Self::check_and_restore_proxy(state).await; - } - } - - async fn check_and_restore_proxy(state: &Arc>) { - if handle::Handle::global().is_exiting() { - logging!(debug, Type::Network, "应用正在退出,跳过系统代理守卫检查"); - return; - } - let (sys_enabled, pac_enabled) = { - let s = state.read().await; - (s.sys_enabled, s.pac_enabled) - }; - - if !sys_enabled { - return; - } - - logging!(debug, Type::Network, "检查代理状态"); - - if pac_enabled { - Self::check_and_restore_pac_proxy(state).await; - } else { - Self::check_and_restore_sys_proxy(state).await; - } - } - - async fn check_and_restore_pac_proxy(state: &Arc>) { - if handle::Handle::global().is_exiting() { - logging!(debug, Type::Network, "应用正在退出,跳过PAC代理恢复检查"); - return; - } - - let current = Self::get_auto_proxy_with_timeout().await; - let expected = Self::get_expected_pac_config().await; - - Self::update_state_timestamp(state, |s| { - s.auto_proxy = current.clone(); - }) - .await; - - if !current.enable || current.url != expected.url { - logging!(info, Type::Network, "PAC代理设置异常,正在恢复..."); - if let Err(e) = Self::restore_pac_proxy(&expected.url).await { - logging!(error, Type::Network, "恢复PAC代理失败: {}", e); - } - - sleep(Duration::from_millis(500)).await; - let restored = Self::get_auto_proxy_with_timeout().await; - - Self::update_state_timestamp(state, |s| { - s.is_healthy = restored.enable && restored.url == expected.url; - s.auto_proxy = restored; - }) - .await; - } - } - - async fn check_and_restore_sys_proxy(state: &Arc>) { - if handle::Handle::global().is_exiting() { - logging!(debug, Type::Network, "应用正在退出,跳过系统代理恢复检查"); - return; - } - - let current = Self::get_sys_proxy_with_timeout().await; - let expected = Self::get_expected_sys_proxy().await; - - Self::update_state_timestamp(state, |s| { - s.sys_proxy = current.clone(); - }) - .await; - - if !current.enable || current.host != expected.host || current.port != expected.port { - logging!(info, Type::Network, "系统代理设置异常,正在恢复..."); - if let Err(e) = Self::restore_sys_proxy(&expected).await { - logging!(error, Type::Network, "恢复系统代理失败: {}", e); - } - - sleep(Duration::from_millis(500)).await; - let restored = Self::get_sys_proxy_with_timeout().await; - - Self::update_state_timestamp(state, |s| { - s.is_healthy = restored.enable - && restored.host == expected.host - && restored.port == expected.port; - s.sys_proxy = restored; - }) - .await; - } - } - - async fn get_auto_proxy_with_timeout() -> Autoproxy { - let async_proxy = AsyncProxyQuery::get_auto_proxy().await; - - // 转换为兼容的结构 - Autoproxy { - enable: async_proxy.enable, - url: async_proxy.url, - } - } - - async fn get_sys_proxy_with_timeout() -> Sysproxy { - let async_proxy = AsyncProxyQuery::get_system_proxy().await; - - // 转换为兼容的结构 - Sysproxy { - enable: async_proxy.enable, - host: async_proxy.host, - port: async_proxy.port, - bypass: async_proxy.bypass, - } - } - - // 统一的状态更新方法 - async fn update_state_timestamp(state: &Arc>, update_fn: F) - where - F: FnOnce(&mut ProxyState), - { - let mut state_guard = state.write().await; - update_fn(&mut state_guard); - state_guard.last_updated = std::time::Instant::now(); - } - - async fn get_proxy_config() -> ProxyConfig { - let (sys_enabled, pac_enabled, guard_enabled, guard_duration) = { - let verge_config = Config::verge().await; - let verge = verge_config.latest_ref(); - ( - verge.enable_system_proxy.unwrap_or(false), - verge.proxy_auto_config.unwrap_or(false), - verge.enable_proxy_guard.unwrap_or(false), - verge.proxy_guard_duration.unwrap_or(30), // 默认30秒 - ) - }; - ProxyConfig { - sys_enabled, - pac_enabled, - guard_enabled, - guard_duration, - } - } - - async fn get_expected_pac_config() -> Autoproxy { - let proxy_host = { - let verge_config = Config::verge().await; - let verge = verge_config.latest_ref(); - verge - .proxy_host - .clone() - .unwrap_or_else(|| "127.0.0.1".into()) - }; - let pac_port = IVerge::get_singleton_port(); - Autoproxy { - enable: true, - url: format!("http://{proxy_host}:{pac_port}/commands/pac"), - } - } - - async fn get_expected_sys_proxy() -> Sysproxy { - use crate::constants::network; - - let (verge_mixed_port, proxy_host) = { - let verge_config = Config::verge().await; - let verge_ref = verge_config.latest_ref(); - (verge_ref.verge_mixed_port, verge_ref.proxy_host.clone()) - }; - - let default_port = { - let clash_config = Config::clash().await; - clash_config.latest_ref().get_mixed_port() - }; - - let port = verge_mixed_port.unwrap_or(default_port); - let host = proxy_host - .unwrap_or_else(|| network::DEFAULT_PROXY_HOST.into()) - .into(); - - Sysproxy { - enable: true, - host, - port, - bypass: Self::get_bypass_config().await.into(), - } - } - - async fn get_bypass_config() -> String { - use crate::constants::bypass; - - let verge_config = Config::verge().await; - let verge = verge_config.latest_ref(); - let use_default = verge.use_default_bypass.unwrap_or(true); - let custom = verge.system_proxy_bypass.as_deref().unwrap_or(""); - - match (use_default, custom.is_empty()) { - (_, true) => bypass::DEFAULT.into(), - (true, false) => format!("{},{}", bypass::DEFAULT, custom).into(), - (false, false) => custom.into(), - } - } - - #[cfg(target_os = "windows")] - async fn restore_pac_proxy(expected_url: &str) -> Result<(), anyhow::Error> { - if handle::Handle::global().is_exiting() { - logging!(debug, Type::Network, "应用正在退出,跳过PAC代理恢复"); - return Ok(()); - } - Self::execute_sysproxy_command(&["pac", expected_url]).await - } - - #[allow(clippy::unused_async)] - #[cfg(not(target_os = "windows"))] - async fn restore_pac_proxy(expected_url: &str) -> Result<(), anyhow::Error> { - { - let new_autoproxy = Autoproxy { - enable: true, - url: expected_url.to_string(), - }; - // logging_error!(Type::System, true, new_autoproxy.set_auto_proxy()); - new_autoproxy - .set_auto_proxy() - .map_err(|e| anyhow::anyhow!("Failed to set auto proxy: {}", e)) - } - } - - #[cfg(target_os = "windows")] - async fn restore_sys_proxy(expected: &Sysproxy) -> Result<(), anyhow::Error> { - if handle::Handle::global().is_exiting() { - logging!(debug, Type::Network, "应用正在退出,跳过系统代理恢复"); - return Ok(()); - } - let address = format!("{}:{}", expected.host, expected.port); - Self::execute_sysproxy_command(&["global", &address, &expected.bypass]).await - } - - #[allow(clippy::unused_async)] - #[cfg(not(target_os = "windows"))] - async fn restore_sys_proxy(expected: &Sysproxy) -> Result<(), anyhow::Error> { - { - // logging_error!(Type::System, true, expected.set_system_proxy()); - expected - .set_system_proxy() - .map_err(|e| anyhow::anyhow!("Failed to set system proxy: {}", e)) - } - } - - #[cfg(target_os = "windows")] - async fn execute_sysproxy_command(args: &[&str]) -> Result<(), anyhow::Error> { - if handle::Handle::global().is_exiting() { - logging!( - debug, - Type::Network, - "应用正在退出,取消调用 sysproxy.exe,参数: {:?}", - args - ); - return Ok(()); - } - - use crate::utils::dirs; - #[allow(unused_imports)] // creation_flags必须 - use std::os::windows::process::CommandExt; - use tokio::process::Command; - - let binary_path = match dirs::service_path() { - Ok(path) => path, - Err(e) => { - logging!(error, Type::Network, "获取服务路径失败: {e}"); - return Err(e); - } - }; - - let sysproxy_exe = binary_path.with_file_name("sysproxy.exe"); - if !sysproxy_exe.exists() { - logging!(error, Type::Network, "sysproxy.exe 不存在"); - } - anyhow::ensure!(sysproxy_exe.exists(), "sysproxy.exe does not exist"); - - let _output = Command::new(sysproxy_exe) - .args(args) - .creation_flags(0x08000000) // CREATE_NO_WINDOW - 隐藏窗口 - .output() - .await?; - - Ok(()) - } -} diff --git a/src-tauri/src/core/mod.rs b/src-tauri/src/core/mod.rs index 6bdb2418..9dc57879 100644 --- a/src-tauri/src/core/mod.rs +++ b/src-tauri/src/core/mod.rs @@ -1,6 +1,4 @@ -pub mod async_proxy_query; pub mod backup; -pub mod event_driven_proxy; pub mod handle; pub mod hotkey; pub mod logger; @@ -13,4 +11,4 @@ pub mod tray; pub mod validate; pub mod win_uwp; -pub use self::{event_driven_proxy::EventDrivenProxyManager, manager::CoreManager, timer::Timer}; +pub use self::{manager::CoreManager, timer::Timer}; diff --git a/src-tauri/src/core/sysopt.rs b/src-tauri/src/core/sysopt.rs index c24d8be9..719ada71 100644 --- a/src-tauri/src/core/sysopt.rs +++ b/src-tauri/src/core/sysopt.rs @@ -2,7 +2,7 @@ use crate::utils::autostart as startup_shortcut; use crate::{ config::{Config, IVerge}, - core::{EventDrivenProxyManager, handle::Handle}, + core::handle::Handle, logging, logging_error, singleton_lazy, utils::logging::Type, }; @@ -100,15 +100,6 @@ impl Sysopt { self.initialed.load(Ordering::SeqCst) } - pub fn init_guard_sysproxy(&self) -> Result<()> { - // 使用事件驱动代理管理器 - let proxy_manager = EventDrivenProxyManager::global(); - proxy_manager.notify_app_started(); - - logging!(info, Type::Core, "已启用事件驱动代理守卫"); - Ok(()) - } - /// init the sysproxy pub async fn update_sysproxy(&self) -> Result<()> { self.initialed.store(true, Ordering::SeqCst); @@ -161,8 +152,6 @@ impl Sysopt { if !sys_enable { sys.set_system_proxy()?; auto.set_auto_proxy()?; - let proxy_manager = EventDrivenProxyManager::global(); - proxy_manager.notify_config_changed(); return Ok(()); } @@ -171,8 +160,6 @@ impl Sysopt { auto.enable = true; sys.set_system_proxy()?; auto.set_auto_proxy()?; - let proxy_manager = EventDrivenProxyManager::global(); - proxy_manager.notify_config_changed(); return Ok(()); } @@ -181,8 +168,6 @@ impl Sysopt { sys.enable = true; auto.set_auto_proxy()?; sys.set_system_proxy()?; - let proxy_manager = EventDrivenProxyManager::global(); - proxy_manager.notify_config_changed(); return Ok(()); } } @@ -190,8 +175,6 @@ impl Sysopt { { if !sys_enable { let result = self.reset_sysproxy().await; - let proxy_manager = EventDrivenProxyManager::global(); - proxy_manager.notify_config_changed(); return result; } @@ -206,8 +189,6 @@ impl Sysopt { execute_sysproxy_command(args).await?; } - let proxy_manager = EventDrivenProxyManager::global(); - proxy_manager.notify_config_changed(); Ok(()) } diff --git a/src-tauri/src/feat/window.rs b/src-tauri/src/feat/window.rs index a23a41f2..f470a31e 100644 --- a/src-tauri/src/feat/window.rs +++ b/src-tauri/src/feat/window.rs @@ -1,5 +1,4 @@ use crate::config::Config; -use crate::core::event_driven_proxy::EventDrivenProxyManager; use crate::core::{CoreManager, handle, sysopt}; use crate::utils; use crate::utils::window_manager::WindowManager; @@ -24,7 +23,6 @@ pub async fn quit() { // 获取应用句柄并设置退出标志 let app_handle = handle::Handle::app_handle(); handle::Handle::global().set_is_exiting(); - EventDrivenProxyManager::global().notify_app_stopping(); logging!(info, Type::System, "开始异步清理资源"); let cleanup_result = clean_async().await; diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index c6db41c0..2c0a5407 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -18,7 +18,7 @@ use crate::utils::linux; #[cfg(target_os = "macos")] use crate::utils::window_manager::WindowManager; use crate::{ - core::{EventDrivenProxyManager, handle, hotkey}, + core::{handle, hotkey}, process::AsyncHandler, utils::{resolve, server}, }; @@ -429,7 +429,6 @@ pub fn run() { let handle = core::handle::Handle::global(); if !handle.is_exiting() { handle.set_is_exiting(); - EventDrivenProxyManager::global().notify_app_stopping(); feat::clean(); } } diff --git a/src-tauri/src/utils/resolve/mod.rs b/src-tauri/src/utils/resolve/mod.rs index cb0989b1..05762897 100644 --- a/src-tauri/src/utils/resolve/mod.rs +++ b/src-tauri/src/utils/resolve/mod.rs @@ -54,7 +54,6 @@ pub fn resolve_setup_async() { init_service_manager().await; init_core_manager().await; init_system_proxy().await; - AsyncHandler::spawn_blocking(init_system_proxy_guard); }); let tray_init = async { @@ -168,10 +167,6 @@ pub(super) async fn init_system_proxy() { ); } -pub(super) fn init_system_proxy_guard() { - logging_error!(Type::Setup, sysopt::Sysopt::global().init_guard_sysproxy()); -} - pub(super) async fn refresh_tray_menu() { logging_error!(Type::Setup, Tray::global().update_part().await); }