sysopt.rs 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. use super::{Clash, Verge};
  2. use crate::{log_if_err, utils::sysopt::SysProxyConfig};
  3. use anyhow::{bail, Result};
  4. use auto_launch::{AutoLaunch, AutoLaunchBuilder};
  5. // use parking_lot::Mutex;
  6. use std::sync::Arc;
  7. use tauri::{async_runtime::Mutex, utils::platform::current_exe};
  8. pub struct Sysopt {
  9. /// current system proxy setting
  10. cur_sysproxy: Option<SysProxyConfig>,
  11. /// record the original system proxy
  12. /// recover it when exit
  13. old_sysproxy: Option<SysProxyConfig>,
  14. /// helps to auto launch the app
  15. auto_launch: Option<AutoLaunch>,
  16. /// record whether the guard async is running or not
  17. guard_state: Arc<Mutex<bool>>,
  18. }
  19. impl Sysopt {
  20. pub fn new() -> Sysopt {
  21. Sysopt {
  22. cur_sysproxy: None,
  23. old_sysproxy: None,
  24. auto_launch: None,
  25. guard_state: Arc::new(Mutex::new(false)),
  26. }
  27. }
  28. /// init the sysproxy
  29. pub fn init_sysproxy(&mut self, port: Option<String>, verge: &Verge) {
  30. if let Some(port) = port {
  31. let enable = verge.enable_system_proxy.clone().unwrap_or(false);
  32. self.old_sysproxy = match SysProxyConfig::get_sys() {
  33. Ok(proxy) => Some(proxy),
  34. Err(_) => None,
  35. };
  36. let bypass = verge.system_proxy_bypass.clone();
  37. let sysproxy = SysProxyConfig::new(enable, port, bypass);
  38. if enable {
  39. if let Err(err) = sysproxy.set_sys() {
  40. log::error!("failed to set system proxy for `{err}`");
  41. }
  42. }
  43. self.cur_sysproxy = Some(sysproxy);
  44. }
  45. // launchs the system proxy guard
  46. self.guard_proxy();
  47. }
  48. /// update the system proxy
  49. /// when the verge config is changed
  50. pub fn update_sysproxy(&mut self, enable: Option<bool>, bypass: Option<String>) -> Result<()> {
  51. let sysproxy = self.cur_sysproxy.take();
  52. if sysproxy.is_none() {
  53. bail!("unhandle error for sysproxy is none");
  54. }
  55. let mut sysproxy = sysproxy.unwrap();
  56. if let Some(enable) = enable {
  57. sysproxy.enable = enable;
  58. }
  59. if let Some(bypass) = bypass {
  60. sysproxy.bypass = bypass;
  61. }
  62. self.cur_sysproxy = Some(sysproxy);
  63. if self.cur_sysproxy.as_ref().unwrap().set_sys().is_err() {
  64. bail!("failed to set system proxy");
  65. }
  66. Ok(())
  67. }
  68. /// reset the sysproxy
  69. pub fn reset_sysproxy(&mut self) {
  70. if let Some(sysproxy) = self.old_sysproxy.take() {
  71. match sysproxy.set_sys() {
  72. Ok(_) => self.cur_sysproxy = None,
  73. Err(_) => log::error!("failed to reset proxy"),
  74. }
  75. }
  76. }
  77. /// get current proxy
  78. pub fn get_sysproxy(&self) -> Result<Option<SysProxyConfig>> {
  79. Ok(self.cur_sysproxy.clone())
  80. }
  81. /// init the auto launch
  82. pub fn init_launch(&mut self, enable: Option<bool>) -> Result<()> {
  83. let app_exe = current_exe().unwrap();
  84. let app_exe = dunce::canonicalize(app_exe).unwrap();
  85. let app_name = app_exe.file_stem().unwrap().to_str().unwrap();
  86. let app_path = app_exe.as_os_str().to_str().unwrap();
  87. // fix issue #26
  88. #[cfg(target_os = "windows")]
  89. let app_path = format!("\"{app_path}\"");
  90. #[cfg(target_os = "windows")]
  91. let app_path = app_path.as_str();
  92. let auto = AutoLaunchBuilder::new()
  93. .set_app_name(app_name)
  94. .set_app_path(app_path)
  95. .build();
  96. if let Some(enable) = enable {
  97. // fix issue #26
  98. if enable {
  99. auto.enable()?;
  100. }
  101. }
  102. self.auto_launch = Some(auto);
  103. Ok(())
  104. }
  105. /// update the startup
  106. pub fn update_launch(&mut self, enable: Option<bool>) -> Result<()> {
  107. if enable.is_none() {
  108. return Ok(());
  109. }
  110. let enable = enable.unwrap();
  111. let auto_launch = self.auto_launch.as_ref().unwrap();
  112. match enable {
  113. true => auto_launch.enable()?,
  114. false => auto_launch.disable()?,
  115. };
  116. Ok(())
  117. }
  118. /// launch a system proxy guard
  119. /// read config from file directly
  120. pub fn guard_proxy(&self) {
  121. use tokio::time::{sleep, Duration};
  122. let guard_state = self.guard_state.clone();
  123. tauri::async_runtime::spawn(async move {
  124. // if it is running, exit
  125. let mut state = guard_state.lock().await;
  126. if *state {
  127. return;
  128. }
  129. *state = true;
  130. drop(state);
  131. // default duration is 10s
  132. let mut wait_secs = 10u64;
  133. loop {
  134. sleep(Duration::from_secs(wait_secs)).await;
  135. let verge = Verge::new();
  136. let enable_proxy = verge.enable_system_proxy.unwrap_or(false);
  137. let enable_guard = verge.enable_proxy_guard.unwrap_or(false);
  138. let guard_duration = verge.proxy_guard_duration.unwrap_or(10);
  139. // update duration
  140. wait_secs = guard_duration;
  141. // stop loop
  142. if !enable_guard || !enable_proxy {
  143. break;
  144. }
  145. log::debug!("try to guard the system proxy");
  146. let clash = Clash::new();
  147. match &clash.info.port {
  148. Some(port) => {
  149. let bypass = verge.system_proxy_bypass.clone();
  150. let sysproxy = SysProxyConfig::new(true, port.clone(), bypass);
  151. log_if_err!(sysproxy.set_sys());
  152. }
  153. None => log::error!("failed to parse clash port"),
  154. }
  155. }
  156. let mut state = guard_state.lock().await;
  157. *state = false;
  158. });
  159. }
  160. }