Remake desktop

Optimize change proxy

Optimize network check

Fix fallback issues

Optimize lots of details
This commit is contained in:
chen08209
2024-12-03 21:47:12 +08:00
parent 4b32a096dd
commit ece8a48181
96 changed files with 5869 additions and 2378 deletions

1313
services/helper/Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,23 @@
[package]
name = "helper"
version = "0.1.0"
edition = "2021"
[[bin]]
name = "helper"
path = "src/main.rs"
[dependencies]
windows-service = { version = "0.7.0", optional = true }
tokio = { version = "1", features = ["full"] }
anyhow = "1.0.93"
warp = "0.3.7"
serde = { version = "1.0.215", features = ["derive"] }
once_cell = "1.20.2"
[profile.release]
panic = "abort"
codegen-units = 1
lto = true
opt-level = "s"

View File

@@ -0,0 +1,20 @@
#[cfg(not(all(feature = "windows-service", target_os = "windows")))]
use tokio::runtime::Runtime;
#[cfg(not(all(feature = "windows-service", target_os = "windows")))]
use crate::service::hub::run_service;
mod service;
#[cfg(all(feature = "windows-service", target_os = "windows"))]
pub fn main() -> windows_service::Result<()> {
service::windows::main()
}
#[cfg(not(all(feature = "windows-service", target_os = "windows")))]
fn main() {
if let Ok(rt) = Runtime::new() {
rt.block_on(async {
let _ = run_service().await;
});
}
}

View File

@@ -0,0 +1,110 @@
use std::collections::VecDeque;
use std::{io, thread};
use std::io::BufRead;
use std::process::{Command, Stdio};
use std::sync::{Arc, Mutex};
use warp::{Filter, Reply};
use serde::{Deserialize, Serialize};
use once_cell::sync::Lazy;
const LISTEN_PORT: u16 = 47890;
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct StartParams {
pub path: String,
pub arg: String,
}
static LOGS: Lazy<Arc<Mutex<VecDeque<String>>>> = Lazy::new(|| Arc::new(Mutex::new(VecDeque::with_capacity(100))));
static PROCESS: Lazy<Arc<Mutex<Option<std::process::Child>>>> = Lazy::new(|| Arc::new(Mutex::new(None)));
fn start(start_params: StartParams) -> impl Reply {
stop();
let mut process = PROCESS.lock().unwrap();
match Command::new(&start_params.path)
.stderr(Stdio::piped())
.arg(&start_params.arg)
.spawn()
{
Ok(child) => {
*process = Some(child);
if let Some(ref mut child) = *process {
let stderr = child.stderr.take().unwrap();
let reader = io::BufReader::new(stderr);
thread::spawn(move || {
for line in reader.lines() {
match line {
Ok(output) => {
log_message(output);
}
Err(_) => {
break;
}
}
}
});
}
"".to_string()
}
Err(e) => {
log_message(e.to_string());
e.to_string()
}
}
}
fn stop() -> impl Reply {
let mut process = PROCESS.lock().unwrap();
if let Some(mut child) = process.take() {
let _ = child.kill();
let _ = child.wait();
}
*process = None;
"".to_string()
}
fn log_message(message: String) {
let mut log_buffer = LOGS.lock().unwrap();
if log_buffer.len() == 100 {
log_buffer.pop_front();
}
log_buffer.push_back(format!("{}\n", message));
}
fn get_logs() -> impl Reply {
let log_buffer = LOGS.lock().unwrap();
let value = log_buffer.iter().cloned().collect::<Vec<String>>().join("\n");
warp::reply::with_header(value, "Content-Type", "text/plain")
}
pub async fn run_service() -> anyhow::Result<()> {
let api_ping = warp::get()
.and(warp::path("ping"))
.map(|| "2024125");
let api_start = warp::post()
.and(warp::path("start"))
.and(warp::body::json())
.map(|start_params: StartParams| {
start(start_params)
});
let api_stop = warp::post()
.and(warp::path("stop"))
.map(|| stop());
let api_logs = warp::get()
.and(warp::path("logs"))
.map(|| get_logs());
warp::serve(
api_ping
.or(api_start)
.or(api_stop)
.or(api_logs)
)
.run(([127, 0, 0, 1], LISTEN_PORT))
.await;
Ok(())
}

View File

@@ -0,0 +1,8 @@
pub mod hub;
#[cfg(all(feature = "windows-service", target_os = "windows"))]
pub mod windows;

View File

@@ -0,0 +1,67 @@
use crate::service::hub::run_service;
use std::ffi::OsString;
use std::time::Duration;
use tokio::runtime::Runtime;
use windows_service::{
define_windows_service,
service::{
ServiceControl, ServiceControlAccept, ServiceExitCode, ServiceState, ServiceStatus,
ServiceType,
},
service_control_handler::{self, ServiceControlHandlerResult},
service_dispatcher, Result,
};
const SERVICE_NAME: &str = "FlClashHelperService";
const SERVICE_TYPE: ServiceType = ServiceType::OWN_PROCESS;
pub fn main() -> Result<()> {
start_service()
}
pub fn start_service() -> Result<()> {
service_dispatcher::start(SERVICE_NAME, serveice)
}
define_windows_service!(serveice, service_main);
pub fn service_main(_arguments: Vec<OsString>) {
if let Ok(rt) = Runtime::new() {
rt.block_on(async {
let _ = run_windows_service().await;
});
}
}
async fn run_windows_service() -> anyhow::Result<()> {
let status_handle = service_control_handler::register(
SERVICE_NAME,
move |event| -> ServiceControlHandlerResult {
match event {
ServiceControl::Interrogate => ServiceControlHandlerResult::NoError,
ServiceControl::Stop => std::process::exit(0),
_ => ServiceControlHandlerResult::NotImplemented,
}
},
)?;
status_handle.set_service_status(ServiceStatus {
service_type: SERVICE_TYPE,
current_state: ServiceState::Running,
controls_accepted: ServiceControlAccept::STOP,
exit_code: ServiceExitCode::Win32(0),
checkpoint: 0,
wait_hint: Duration::default(),
process_id: None,
})?;
run_service().await
}