From c3cba03ac65b30b7ff451ba3cc083c57b3db9828 Mon Sep 17 00:00:00 2001 From: huzibaca Date: Fri, 27 Sep 2024 00:24:05 +0800 Subject: [PATCH] refactor: logic optimization --- src-tauri/src/cmds.rs | 2 +- src-tauri/src/core/core.rs | 197 ++++++++++++--------------------- src-tauri/src/feat.rs | 19 ++-- src-tauri/src/utils/resolve.rs | 2 +- 4 files changed, 86 insertions(+), 134 deletions(-) diff --git a/src-tauri/src/cmds.rs b/src-tauri/src/cmds.rs index cc79e760..9152151a 100644 --- a/src-tauri/src/cmds.rs +++ b/src-tauri/src/cmds.rs @@ -185,7 +185,7 @@ pub async fn change_clash_core(clash_core: Option) -> CmdResult { /// restart the sidecar #[tauri::command] pub async fn restart_sidecar() -> CmdResult { - wrap_err!(CoreManager::global().run_core().await) + wrap_err!(CoreManager::global().restart_core().await) } /// get the system proxy diff --git a/src-tauri/src/core/core.rs b/src-tauri/src/core/core.rs index c2b835d0..40d2b53b 100644 --- a/src-tauri/src/core/core.rs +++ b/src-tauri/src/core/core.rs @@ -4,20 +4,18 @@ use crate::log_err; use crate::utils::dirs; use anyhow::{bail, Result}; use once_cell::sync::OnceCell; -use parking_lot::Mutex; use serde_yaml::Mapping; use std::{sync::Arc, time::Duration}; use sysinfo::{ProcessRefreshKind, RefreshKind, System}; -use tauri_plugin_shell::process::{CommandChild, CommandEvent}; +use tauri_plugin_shell::process::CommandEvent; use tauri_plugin_shell::ShellExt; +use tokio::sync::Mutex; use tokio::time::sleep; #[derive(Debug)] pub struct CoreManager { - sidecar: Arc>>, - #[allow(unused)] - use_service_mode: Arc>, + running: Arc>, } impl CoreManager { @@ -25,19 +23,15 @@ impl CoreManager { static CORE_MANAGER: OnceCell = OnceCell::new(); CORE_MANAGER.get_or_init(|| CoreManager { - sidecar: Arc::new(Mutex::new(None)), - use_service_mode: Arc::new(Mutex::new(false)), + running: Arc::new(Mutex::new(false)), }) } - pub fn init(&self) -> Result<()> { - tauri::async_runtime::spawn(async { - log::trace!("run core start"); - // 启动clash - log_err!(Self::global().run_core().await); - log::trace!("run core end"); - }); - + pub async fn init(&self) -> Result<()> { + log::trace!("run core start"); + // 启动clash + log_err!(Self::global().start_core().await); + log::trace!("run core end"); Ok(()) } @@ -47,21 +41,7 @@ impl CoreManager { let config_path = dirs::path_to_str(&config_path)?; let clash_core = { Config::verge().latest().clash_core.clone() }; - let mut clash_core = clash_core.unwrap_or("verge-mihomo".into()); - - // compatibility - if clash_core.contains("clash") { - clash_core = "verge-mihomo".to_string(); - Config::verge().draft().patch_config(IVerge { - clash_core: Some("verge-mihomo".to_string()), - ..IVerge::default() - }); - Config::verge().apply(); - match Config::verge().data().save_file() { - Ok(_) => handle::Handle::refresh_verge(), - Err(err) => log::error!(target: "app", "{err}"), - } - } + let clash_core = clash_core.unwrap_or("verge-mihomo".into()); let test_dir = dirs::app_home_dir()?.join("test"); let test_dir = dirs::path_to_str(&test_dir)?; @@ -88,40 +68,54 @@ impl CoreManager { Ok(()) } - /// 启动核心 - pub async fn run_core(&self) -> Result<()> { - let config_path = Config::generate_file(ConfigType::Run)?; + /// 停止核心运行 + pub async fn stop_core(&self) -> Result<()> { + let mut running = self.running.lock().await; + if !*running { + log::debug!("core is not running"); + return Ok(()); + } + + let clash_core = { Config::verge().latest().clash_core.clone() }; + let clash_core = clash_core.unwrap_or("verge-mihomo".into()); // 关闭tun模式 let mut disable = Mapping::new(); let mut tun = Mapping::new(); tun.insert("enable".into(), false.into()); disable.insert("tun".into(), tun.into()); log::debug!(target: "app", "disable tun mode"); - let _ = clash_api::patch_configs(&disable).await; - - if *self.use_service_mode.lock() { - log::debug!(target: "app", "stop the core by service"); - log_err!(service::stop_core_by_service().await); - } else { - let system = System::new_with_specifics( - RefreshKind::new().with_processes(ProcessRefreshKind::everything()), - ); - let procs = system.processes_by_name("verge-mihomo"); - - for proc in procs { - log::debug!(target: "app", "kill all clash process"); - proc.kill(); - } - } + log_err!(clash_api::patch_configs(&disable).await); // 服务模式 - let enable = { Config::verge().latest().enable_service_mode }; - let enable = enable.unwrap_or(false); + let service_enable = { Config::verge().latest().enable_service_mode }; + let service_enable = service_enable.unwrap_or(false); + if service_enable { + log::debug!(target: "app", "stop the core by service"); + log_err!(service::stop_core_by_service().await); + return Ok(()); + } + kill_processes_by_name(clash_core.as_str()); + *running = false; - *self.use_service_mode.lock() = enable; + Ok(()) + } - if enable { + /// 启动核心 + pub async fn start_core(&self) -> Result<()> { + let mut running = self.running.lock().await; + if *running { + log::debug!("core is running"); + return Ok(()); + } + + let config_path = Config::generate_file(ConfigType::Run)?; + let clash_core = { Config::verge().latest().clash_core.clone() }; + let clash_core = clash_core.unwrap_or("verge-mihomo".into()); + // 服务模式 + let service_enable = { Config::verge().latest().enable_service_mode }; + let service_enable = service_enable.unwrap_or(false); + if service_enable { // 服务模式启动失败就直接运行sidecar log::debug!(target: "app", "try to run core in service mode"); @@ -131,27 +125,23 @@ impl CoreManager { } .await; match res { - Ok(_) => return Ok(()), + Ok(_) => { + return { + *running = true; + Ok(()) + } + } Err(err) => { - // 修改这个值,免得stop出错 - *self.use_service_mode.lock() = false; - log::error!(target: "app", "{err}"); + log::error!(target: "app start service err", "{err}"); } } } let app_dir = dirs::app_home_dir()?; let app_dir = dirs::path_to_str(&app_dir)?; - - let clash_core = { Config::verge().latest().clash_core.clone() }; - let clash_core = clash_core.unwrap_or("verge-mihomo".into()); - let config_path = dirs::path_to_str(&config_path)?; - let args = vec!["-d", app_dir, "-f", config_path]; - let app_handle = handle::Handle::global().app_handle().unwrap(); - let cmd = app_handle.shell().sidecar(clash_core)?; let (mut rx, _) = cmd.args(args).spawn()?; @@ -174,75 +164,21 @@ impl CoreManager { } CommandEvent::Terminated(_) => { log::info!(target: "app", "mihomo core terminated"); - let _ = CoreManager::global().recover_core(); break; } _ => {} } } }); - + *running = true; Ok(()) } /// 重启内核 - pub fn recover_core(&'static self) -> Result<()> { - // 服务模式不管 - if *self.use_service_mode.lock() { - return Ok(()); - } - - // 清空原来的sidecar值 - let _ = self.sidecar.lock().take(); - - tauri::async_runtime::spawn(async move { - // 6秒之后再查看服务是否正常 (时间随便搞的) - // terminated 可能是切换内核 (切换内核已经有500ms的延迟) - sleep(Duration::from_millis(6666)).await; - - if self.sidecar.lock().is_none() { - log::info!(target: "app", "recover clash core"); - - // 重新启动app - if let Err(err) = self.run_core().await { - log::error!(target: "app", "failed to recover clash core"); - log::error!(target: "app", "{err}"); - - let _ = self.recover_core(); - } - } - }); - - Ok(()) - } - - /// 停止核心运行 - pub async fn stop_core(&self) -> Result<()> { - // 关闭tun模式 - let mut disable = Mapping::new(); - let mut tun = Mapping::new(); - tun.insert("enable".into(), false.into()); - disable.insert("tun".into(), tun.into()); - log::debug!(target: "app", "disable tun mode"); - let _ = clash_api::patch_configs(&disable).await; - - if *self.use_service_mode.lock() { - log::debug!(target: "app", "stop the core by service"); - log_err!(service::stop_core_by_service().await); - return Ok(()); - } - - let mut sidecar = self.sidecar.lock(); - let _ = sidecar.take(); - - let system = System::new_with_specifics( - RefreshKind::new().with_processes(ProcessRefreshKind::everything()), - ); - let procs = system.processes_by_name("verge-mihomo"); - for proc in procs { - log::debug!(target: "app", "kill all clash process"); - proc.kill(); - } + pub async fn restart_core(&self) -> Result<()> { + // 重新启动app + self.stop_core().await?; + self.start_core().await?; Ok(()) } @@ -267,7 +203,7 @@ impl CoreManager { // 清掉旧日志 Logger::global().clear_log(); - match self.run_core().await { + match self.restart_core().await { Ok(_) => { Config::verge().apply(); Config::runtime().apply(); @@ -313,3 +249,16 @@ impl CoreManager { Ok(()) } } + +fn kill_processes_by_name(process_name: &str) { + let mut system = System::new_with_specifics( + RefreshKind::new().with_processes(ProcessRefreshKind::everything()), + ); + + system.refresh_processes(); + let procs = system.processes_by_name(process_name); + for proc in procs { + log::debug!(target: "app", "Killing process: {}", proc.name()); + proc.kill(); + } +} diff --git a/src-tauri/src/feat.rs b/src-tauri/src/feat.rs index 252a39f7..87c930ee 100644 --- a/src-tauri/src/feat.rs +++ b/src-tauri/src/feat.rs @@ -26,7 +26,7 @@ pub fn open_or_close_dashboard() { // 重启clash pub fn restart_clash_core() { tauri::async_runtime::spawn(async { - match CoreManager::global().run_core().await { + match CoreManager::global().restart_core().await { Ok(_) => { handle::Handle::refresh_clash(); handle::Handle::notice_message("set_config::ok", "ok"); @@ -112,7 +112,7 @@ pub async fn patch_clash(patch: Mapping) -> Result<()> { // 激活订阅 if patch.get("secret").is_some() || patch.get("external-controller").is_some() { Config::generate().await?; - CoreManager::global().run_core().await?; + CoreManager::global().restart_core().await?; handle::Handle::refresh_clash(); } @@ -141,6 +141,7 @@ pub async fn patch_clash(patch: Mapping) -> Result<()> { /// 一般都是一个个的修改 pub async fn patch_verge(patch: IVerge) -> Result<()> { Config::verge().draft().patch_config(patch.clone()); + let tun_mode = patch.enable_tun_mode; let auto_launch = patch.enable_auto_launch; let system_proxy = patch.enable_system_proxy; @@ -168,6 +169,7 @@ pub async fn patch_verge(patch: IVerge) -> Result<()> { let socks_port = patch.verge_socks_port; let http_enabled = patch.verge_http_enabled; let http_port = patch.verge_port; + let res = { let service_mode = patch.enable_service_mode; let mut generated = false; @@ -175,7 +177,7 @@ pub async fn patch_verge(patch: IVerge) -> Result<()> { log::debug!(target: "app", "change service mode to {}", service_mode.unwrap()); if !generated { Config::generate().await?; - CoreManager::global().run_core().await?; + CoreManager::global().restart_core().await?; generated = true; } } else if tun_mode.is_some() { @@ -184,14 +186,15 @@ pub async fn patch_verge(patch: IVerge) -> Result<()> { #[cfg(not(target_os = "windows"))] if (redir_enabled.is_some() || redir_port.is_some()) && !generated { Config::generate().await?; - CoreManager::global().run_core().await?; + CoreManager::global().restart_core().await?; generated = true; } + #[cfg(target_os = "linux")] if tproxy_enabled.is_some() || tproxy_port.is_some() { if !generated { Config::generate().await?; - CoreManager::global().run_core().await?; + CoreManager::global().restart_core().await?; generated = true; } } @@ -203,7 +206,7 @@ pub async fn patch_verge(patch: IVerge) -> Result<()> { && !generated { Config::generate().await?; - CoreManager::global().run_core().await?; + CoreManager::global().restart_core().await?; } if auto_launch.is_some() { sysopt::Sysopt::global().update_launch()?; @@ -243,11 +246,11 @@ pub async fn patch_verge(patch: IVerge) -> Result<()> { Ok(()) => { Config::verge().apply(); Config::verge().data().save_file()?; - Ok(()) + return Ok(()); } Err(err) => { Config::verge().discard(); - Err(err) + return Err(err); } } } diff --git a/src-tauri/src/utils/resolve.rs b/src-tauri/src/utils/resolve.rs index 3159ff0e..79291590 100644 --- a/src-tauri/src/utils/resolve.rs +++ b/src-tauri/src/utils/resolve.rs @@ -79,7 +79,7 @@ pub async fn resolve_setup(app: &mut App) { log_err!(Config::init_config().await); log::trace!("launch core"); - log_err!(CoreManager::global().init()); + log_err!(CoreManager::global().init().await); // setup a simple http server for singleton log::trace!("launch embed server");