From 013dc5f4b5b8fa63bc6395b8088b4cb5fe4d17fd Mon Sep 17 00:00:00 2001 From: GyDi Date: Mon, 27 Dec 2021 02:29:28 +0800 Subject: [PATCH] feat: enhance system proxy setting --- src-tauri/resources/verge_tmp.yaml | 1 + src-tauri/src/cmds/some.rs | 24 +++++++-- src-tauri/src/config/verge.rs | 3 ++ src-tauri/src/events/state.rs | 5 +- src-tauri/src/main.rs | 46 +++++------------ src-tauri/src/utils/mod.rs | 1 + src-tauri/src/utils/resolve.rs | 80 ++++++++++++++++++++++++++++++ src-tauri/src/utils/sysopt.rs | 14 +++++- 8 files changed, 134 insertions(+), 40 deletions(-) create mode 100644 src-tauri/src/utils/resolve.rs diff --git a/src-tauri/resources/verge_tmp.yaml b/src-tauri/resources/verge_tmp.yaml index 7ba6e28..39b754b 100644 --- a/src-tauri/resources/verge_tmp.yaml +++ b/src-tauri/resources/verge_tmp.yaml @@ -3,3 +3,4 @@ theme_mode: light enable_self_startup: false enable_system_proxy: false +system_proxy_bypass: localhost;127.*;10.*;172.16.*;172.17.*;172.18.*;172.19.*;172.20.*;172.21.*;172.22.*;172.23.*;172.24.*;172.25.*;172.26.*;172.27.*;172.28.*;172.29.*;172.30.*;172.31.*;192.168.*; diff --git a/src-tauri/src/cmds/some.rs b/src-tauri/src/cmds/some.rs index 49ff1c2..cd76bef 100644 --- a/src-tauri/src/cmds/some.rs +++ b/src-tauri/src/cmds/some.rs @@ -7,7 +7,7 @@ use crate::{ utils::{ clash::run_clash_bin, config::{read_clash, save_clash, save_verge}, - sysopt::{get_proxy_config, set_proxy_config, SysProxyConfig}, + sysopt::{get_proxy_config, set_proxy_config, SysProxyConfig, DEFAULT_BYPASS}, }, }; use serde_yaml::Mapping; @@ -53,12 +53,21 @@ pub fn patch_clash_config(payload: Mapping) -> Result<(), String> { /// set the system proxy /// Tips: only support windows now #[tauri::command] -pub fn set_sys_proxy(enable: bool, clash_info: State<'_, ClashInfoState>) -> Result<(), String> { +pub fn set_sys_proxy( + enable: bool, + clash_info: State<'_, ClashInfoState>, + verge_lock: State<'_, VergeConfLock>, +) -> Result<(), String> { let clash_info = match clash_info.0.lock() { Ok(arc) => arc.clone(), _ => return Err(format!("can not get clash info")), }; + let verge_info = match verge_lock.0.lock() { + Ok(arc) => arc.clone(), + _ => return Err(format!("can not get verge info")), + }; + let port = match clash_info.controller { Some(ctrl) => ctrl.port, None => None, @@ -70,9 +79,9 @@ pub fn set_sys_proxy(enable: bool, clash_info: State<'_, ClashInfoState>) -> Res let config = if enable { let server = format!("127.0.0.1:{}", port.unwrap()); - // todo - let bypass = String::from("localhost;127.*;10.*;172.16.*;172.17.*;172.18.*;172.19.*;172.20.*;172.21.*;172.22.*;172.23.*;172.24.*;172.25.*;172.26.*;172.27.*;172.28.*;172.29.*;172.30.*;172.31.*;192.168.*;"); - + let bypass = verge_info + .system_proxy_bypass + .unwrap_or(String::from(DEFAULT_BYPASS)); SysProxyConfig { enable, server, @@ -112,6 +121,7 @@ pub fn get_verge_config(verge_lock: State<'_, VergeConfLock>) -> Result, + + /// set system proxy bypass + pub system_proxy_bypass: Option, } diff --git a/src-tauri/src/events/state.rs b/src-tauri/src/events/state.rs index 67a91fa..bcdd54e 100644 --- a/src-tauri/src/events/state.rs +++ b/src-tauri/src/events/state.rs @@ -1,7 +1,7 @@ use std::sync::{Arc, Mutex}; use super::emit::ClashInfoPayload; -use crate::config::VergeConfig; +use crate::{config::VergeConfig, utils::sysopt::SysProxyConfig}; #[derive(Default)] pub struct ClashInfoState(pub Arc>); @@ -11,3 +11,6 @@ pub struct ProfileLock(pub Mutex); #[derive(Default)] pub struct VergeConfLock(pub Arc>); + +#[derive(Default)] +pub struct SomthingState(pub Arc>>); diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index ff3d3aa..ef465ad 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -12,19 +12,14 @@ mod utils; use crate::{ events::state, - utils::{ - clash::put_clash_profile, - config::read_verge, - server::{check_singleton, embed_server}, - }, + utils::{resolve, server}, }; -use std::sync::{Arc, Mutex}; use tauri::{ api, CustomMenuItem, Manager, SystemTray, SystemTrayEvent, SystemTrayMenu, SystemTrayMenuItem, }; fn main() -> std::io::Result<()> { - if check_singleton().is_err() { + if server::check_singleton().is_err() { println!("app exists"); return Ok(()); } @@ -35,44 +30,28 @@ fn main() -> std::io::Result<()> { .add_item(CustomMenuItem::new("quit", "退出").accelerator("CmdOrControl+Q")); tauri::Builder::default() - .setup(|app| { - // a simple http server - embed_server(&app.handle()); - - // init app config - utils::init::init_app(app.package_info()); - // run clash sidecar - let info = utils::clash::run_clash_bin(&app.handle()); - // update the profile - let info_copy = info.clone(); - tauri::async_runtime::spawn(async move { - match put_clash_profile(&info_copy).await { - Ok(_) => {} - Err(err) => log::error!("failed to put config for `{}`", err), - }; - }); - - app.manage(state::VergeConfLock(Arc::new(Mutex::new(read_verge())))); - app.manage(state::ClashInfoState(Arc::new(Mutex::new(info)))); - app.manage(state::ProfileLock::default()); - Ok(()) - }) + .manage(state::VergeConfLock::default()) + .manage(state::ClashInfoState::default()) + .manage(state::SomthingState::default()) + .manage(state::ProfileLock::default()) + .setup(|app| Ok(resolve::resolve_setup(app))) .system_tray(SystemTray::new().with_menu(menu)) - .on_system_tray_event(move |app, event| match event { + .on_system_tray_event(move |app_handle, event| match event { SystemTrayEvent::MenuItemClick { id, .. } => match id.as_str() { "open_window" => { - let window = app.get_window("main").unwrap(); + let window = app_handle.get_window("main").unwrap(); window.show().unwrap(); window.set_focus().unwrap(); } "quit" => { api::process::kill_children(); - app.exit(0); + resolve::resolve_reset(app_handle); + app_handle.exit(0); } _ => {} }, SystemTrayEvent::LeftClick { .. } => { - let window = app.get_window("main").unwrap(); + let window = app_handle.get_window("main").unwrap(); window.show().unwrap(); window.set_focus().unwrap(); } @@ -104,6 +83,7 @@ fn main() -> std::io::Result<()> { api.prevent_exit(); } tauri::Event::Exit => { + resolve::resolve_reset(app_handle); api::process::kill_children(); } _ => {} diff --git a/src-tauri/src/utils/mod.rs b/src-tauri/src/utils/mod.rs index 9794a2c..3a09fe4 100644 --- a/src-tauri/src/utils/mod.rs +++ b/src-tauri/src/utils/mod.rs @@ -5,5 +5,6 @@ pub mod clash; pub mod config; pub mod fetch; pub mod init; +pub mod resolve; pub mod server; pub mod sysopt; diff --git a/src-tauri/src/utils/resolve.rs b/src-tauri/src/utils/resolve.rs new file mode 100644 index 0000000..4a13d05 --- /dev/null +++ b/src-tauri/src/utils/resolve.rs @@ -0,0 +1,80 @@ +use super::{clash, config, init, server, sysopt}; +use crate::events::state; +use tauri::{App, AppHandle, Manager}; + +/// handle something when start app +pub fn resolve_setup(app: &App) { + // setup a simple http server for singleton + server::embed_server(&app.handle()); + + // init app config + init::init_app(app.package_info()); + + // run clash sidecar + let info = clash::run_clash_bin(&app.handle()); + + // update the profile + let info_ = info.clone(); + tauri::async_runtime::spawn(async move { + if let Err(err) = clash::put_clash_profile(&info_).await { + log::error!("failed to put config for `{}`", err); + }; + }); + + // resolve the verge config - enable system proxy + let mut original: Option = None; + let verge = config::read_verge(); + let enable = verge.enable_system_proxy.unwrap_or(false); + + if enable && info.controller.is_some() { + if let Ok(original_conf) = sysopt::get_proxy_config() { + original = Some(original_conf) + }; + let ctl = info.controller.clone().unwrap(); + if ctl.port.is_some() { + let server = format!("127.0.0.1:{}", ctl.port.unwrap()); + let bypass = verge + .system_proxy_bypass + .clone() + .unwrap_or(String::from(sysopt::DEFAULT_BYPASS)); + let config = sysopt::SysProxyConfig { + enable, + server, + bypass, + }; + if let Err(err) = sysopt::set_proxy_config(&config) { + log::error!("can not set system proxy for `{}`", err); + } + } + } + // update state + let verge_state = app.state::(); + let mut verge_arc = verge_state.0.lock().unwrap(); + *verge_arc = verge; + + let clash_state = app.state::(); + let mut clash_arc = clash_state.0.lock().unwrap(); + *clash_arc = info; + + let some_state = app.state::(); + let mut some_arc = some_state.0.lock().unwrap(); + *some_arc = original; +} + +/// reset system proxy +pub fn resolve_reset(app_handle: &AppHandle) { + let state = app_handle.try_state::(); + if state.is_none() { + return; + } + match state.unwrap().0.lock() { + Ok(arc) => { + if arc.is_some() { + if let Err(err) = sysopt::set_proxy_config(arc.as_ref().unwrap()) { + log::error!("failed to reset proxy for `{}`", err); + } + } + } + _ => {} + }; +} diff --git a/src-tauri/src/utils/sysopt.rs b/src-tauri/src/utils/sysopt.rs index 6e487cb..46250e3 100644 --- a/src-tauri/src/utils/sysopt.rs +++ b/src-tauri/src/utils/sysopt.rs @@ -1,13 +1,25 @@ use serde::{Deserialize, Serialize}; use std::io; -#[derive(Debug, Deserialize, Serialize)] +#[derive(Debug, Deserialize, Serialize, Clone)] pub struct SysProxyConfig { pub enable: bool, pub server: String, pub bypass: String, } +impl Default for SysProxyConfig { + fn default() -> Self { + SysProxyConfig { + enable: false, + server: String::from(""), + bypass: String::from(""), + } + } +} + +pub static DEFAULT_BYPASS: &str = "localhost;127.*;10.*;172.16.*;172.17.*;172.18.*;172.19.*;172.20.*;172.21.*;172.22.*;172.23.*;172.24.*;172.25.*;172.26.*;172.27.*;172.28.*;172.29.*;172.30.*;172.31.*;192.168.*;"; + #[cfg(target_os = "windows")] mod win { use super::*;