mirror of
https://github.com/clash-verge-rev/clash-verge-rev
synced 2025-05-05 04:43:44 +08:00
refactor: logic optimization
This commit is contained in:
parent
ce7818c436
commit
c3cba03ac6
@ -185,7 +185,7 @@ pub async fn change_clash_core(clash_core: Option<String>) -> 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
|
||||
|
@ -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<Mutex<Option<CommandChild>>>,
|
||||
#[allow(unused)]
|
||||
use_service_mode: Arc<Mutex<bool>>,
|
||||
running: Arc<Mutex<bool>>,
|
||||
}
|
||||
|
||||
impl CoreManager {
|
||||
@ -25,19 +23,15 @@ impl CoreManager {
|
||||
static CORE_MANAGER: OnceCell<CoreManager> = 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();
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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");
|
||||
|
Loading…
x
Reference in New Issue
Block a user