feat: system proxy guard

This commit is contained in:
GyDi 2022-02-20 18:53:21 +08:00
parent 0245baf1b6
commit e38dcd85ac
No known key found for this signature in database
GPG Key ID: 1C95E0D3467B3084
4 changed files with 110 additions and 32 deletions

View File

@ -260,7 +260,7 @@ pub fn get_verge_config(verge_state: State<'_, VergeState>) -> Result<VergeConfi
/// patch the verge config
/// this command only save the config and not responsible for other things
#[tauri::command]
pub async fn patch_verge_config(
pub fn patch_verge_config(
payload: VergeConfig,
verge_state: State<'_, VergeState>,
) -> Result<(), String> {

View File

@ -1,7 +1,11 @@
use crate::utils::{config, dirs, sysopt::SysProxyConfig};
use crate::{
core::Clash,
utils::{config, dirs, sysopt::SysProxyConfig},
};
use auto_launch::{AutoLaunch, AutoLaunchBuilder};
use serde::{Deserialize, Serialize};
use tauri::api::path::resource_dir;
use std::sync::Arc;
use tauri::{api::path::resource_dir, async_runtime::Mutex};
/// ### `verge.yaml` schema
#[derive(Default, Debug, Clone, Deserialize, Serialize)]
@ -22,6 +26,9 @@ pub struct VergeConfig {
/// set system proxy
pub enable_system_proxy: Option<bool>,
/// enable proxy guard
pub enable_proxy_guard: Option<bool>,
/// set system proxy bypass
pub system_proxy_bypass: Option<String>,
}
@ -53,6 +60,9 @@ pub struct Verge {
pub cur_sysproxy: Option<SysProxyConfig>,
pub auto_launch: Option<AutoLaunch>,
/// record whether the guard async is running or not
guard_state: Arc<Mutex<bool>>,
}
impl Default for Verge {
@ -68,6 +78,7 @@ impl Verge {
old_sysproxy: None,
cur_sysproxy: None,
auto_launch: None,
guard_state: Arc::new(Mutex::new(false)),
}
}
@ -92,6 +103,9 @@ impl Verge {
self.cur_sysproxy = Some(sysproxy);
}
// launchs the system proxy guard
Verge::guard_proxy(10, self.guard_state.clone());
}
/// reset the sysproxy
@ -154,10 +168,9 @@ impl Verge {
let auto_launch = self.auto_launch.clone().unwrap();
let result = if enable {
auto_launch.enable()
} else {
auto_launch.disable()
let result = match enable {
true => auto_launch.enable(),
false => auto_launch.disable(),
};
match result {
@ -169,24 +182,6 @@ impl Verge {
}
}
// fn guard_thread(&mut self) -> Result<(), String> {
// let sysproxy = self.cur_sysproxy.clone();
// use std::{thread, time};
// tauri::async_runtime::spawn(async move {
// if let Some(sysproxy) = sysproxy {
// sysproxy.set_sys();
// }
// let ten_millis = time::Duration::from_millis(10);
// let now = time::Instant::now();
// thread::sleep(ten_millis);
// });
// Ok(())
// }
/// patch verge config
/// There should be only one update at a time here
/// so call the save_file at the end is savely
@ -248,10 +243,75 @@ impl Verge {
self.config.system_proxy_bypass = Some(bypass);
}
// proxy guard
// only change it
if patch.enable_proxy_guard.is_some() {
self.config.enable_proxy_guard = patch.enable_proxy_guard;
}
// relaunch the guard
if patch.enable_system_proxy.is_some() || patch.enable_proxy_guard.is_some() {
Verge::guard_proxy(10, self.guard_state.clone());
}
self.config.save_file()
}
}
impl Verge {
/// launch a system proxy guard
/// read config from file directly
pub fn guard_proxy(wait_secs: u64, guard_state: Arc<Mutex<bool>>) {
use tokio::time::{sleep, Duration};
tauri::async_runtime::spawn(async move {
// if it is running, exit
let mut state = guard_state.lock().await;
if *state {
return;
}
*state = true;
std::mem::drop(state);
loop {
sleep(Duration::from_secs(wait_secs)).await;
log::debug!("[Guard]: heartbeat detection");
let verge = Verge::new();
let enable_proxy = verge.config.enable_system_proxy.unwrap_or(false);
let enable_guard = verge.config.enable_proxy_guard.unwrap_or(false);
// stop loop
if !enable_guard || !enable_proxy {
break;
}
log::info!("[Guard]: try to guard proxy");
let clash = Clash::new();
match &clash.info.port {
Some(port) => {
let bypass = verge.config.system_proxy_bypass.clone();
let sysproxy = SysProxyConfig::new(true, port.clone(), bypass);
if let Err(err) = sysproxy.set_sys() {
log::error!("[Guard]: {err}");
log::error!("[Guard]: fail to set system proxy");
}
}
None => log::error!("[Guard]: fail to parse clash port"),
}
}
let mut state = guard_state.lock().await;
*state = false;
});
}
}
// Get the target app_path
fn get_app_path(app_name: &str) -> String {
#[cfg(target_os = "linux")]

View File

@ -15,9 +15,10 @@ const SettingSystem = ({ onError }: Props) => {
const { data: vergeConfig } = useSWR("getVergeConfig", getVergeConfig);
const {
enable_auto_launch: startup = false,
enable_system_proxy: proxy = false,
system_proxy_bypass: bypass = "",
enable_auto_launch = false,
enable_system_proxy = false,
system_proxy_bypass = "",
enable_proxy_guard = false,
} = vergeConfig ?? {};
const onSwitchFormat = (_e: any, value: boolean) => value;
@ -30,7 +31,7 @@ const SettingSystem = ({ onError }: Props) => {
<SettingItem>
<ListItemText primary="Auto Launch" />
<GuardState
value={startup}
value={enable_auto_launch}
valueProps="checked"
onCatch={onError}
onFormat={onSwitchFormat}
@ -51,7 +52,7 @@ const SettingSystem = ({ onError }: Props) => {
}
/>
<GuardState
value={proxy}
value={enable_system_proxy}
valueProps="checked"
onCatch={onError}
onFormat={onSwitchFormat}
@ -65,11 +66,27 @@ const SettingSystem = ({ onError }: Props) => {
</GuardState>
</SettingItem>
{proxy && (
{enable_system_proxy && (
<SettingItem>
<ListItemText primary="Proxy Guard" />
<GuardState
value={enable_proxy_guard}
valueProps="checked"
onCatch={onError}
onFormat={onSwitchFormat}
onChange={(e) => onChangeData({ enable_proxy_guard: e })}
onGuard={(e) => patchVergeConfig({ enable_proxy_guard: e })}
>
<Switch edge="end" />
</GuardState>
</SettingItem>
)}
{enable_system_proxy && (
<SettingItem>
<ListItemText primary="Proxy Bypass" />
<GuardState
value={bypass ?? ""}
value={system_proxy_bypass ?? ""}
onCatch={onError}
onFormat={(e: any) => e.target.value}
onChange={(e) => onChangeData({ system_proxy_bypass: e })}

View File

@ -115,6 +115,7 @@ export namespace CmdType {
traffic_graph?: boolean;
enable_auto_launch?: boolean;
enable_system_proxy?: boolean;
enable_proxy_guard?: boolean;
system_proxy_bypass?: string;
}
}