122 lines
4.6 KiB
Rust
122 lines
4.6 KiB
Rust
use super::{CoreManager, RunningMode};
|
|
use crate::{
|
|
AsyncHandler,
|
|
config::Config,
|
|
core::{handle, logger::ClashLogger, service},
|
|
logging,
|
|
process::CommandChildGuard,
|
|
utils::{
|
|
dirs,
|
|
init::sidecar_writer,
|
|
logging::{SharedWriter, Type, write_sidecar_log},
|
|
},
|
|
};
|
|
use anyhow::Result;
|
|
use compact_str::CompactString;
|
|
use flexi_logger::DeferredNow;
|
|
use log::Level;
|
|
use std::collections::VecDeque;
|
|
use tauri_plugin_shell::ShellExt;
|
|
|
|
impl CoreManager {
|
|
pub async fn get_clash_logs(&self) -> Result<VecDeque<CompactString>> {
|
|
match self.get_running_mode() {
|
|
RunningMode::Service => service::get_clash_logs_by_service().await,
|
|
RunningMode::Sidecar => Ok(ClashLogger::global().get_logs().clone()),
|
|
RunningMode::NotRunning => Ok(VecDeque::new()),
|
|
}
|
|
}
|
|
|
|
pub(super) async fn start_core_by_sidecar(&self) -> Result<()> {
|
|
logging!(info, Type::Core, "Starting core in sidecar mode");
|
|
|
|
let config_file = Config::generate_file(crate::config::ConfigType::Run).await?;
|
|
let app_handle = handle::Handle::app_handle();
|
|
let clash_core = Config::verge().await.latest_ref().get_valid_clash_core();
|
|
let config_dir = dirs::app_home_dir()?;
|
|
|
|
let (mut rx, child) = app_handle
|
|
.shell()
|
|
.sidecar(&clash_core)?
|
|
.args([
|
|
"-d",
|
|
dirs::path_to_str(&config_dir)?,
|
|
"-f",
|
|
dirs::path_to_str(&config_file)?,
|
|
])
|
|
.spawn()?;
|
|
|
|
let pid = child.pid();
|
|
logging!(trace, Type::Core, "Sidecar started with PID: {}", pid);
|
|
|
|
{
|
|
let mut state = self.state.lock();
|
|
state.child_sidecar = Some(CommandChildGuard::new(child));
|
|
state.running_mode = RunningMode::Sidecar;
|
|
}
|
|
|
|
let shared_writer: SharedWriter =
|
|
std::sync::Arc::new(tokio::sync::Mutex::new(sidecar_writer().await?));
|
|
|
|
AsyncHandler::spawn(|| async move {
|
|
while let Some(event) = rx.recv().await {
|
|
match event {
|
|
tauri_plugin_shell::process::CommandEvent::Stdout(line)
|
|
| tauri_plugin_shell::process::CommandEvent::Stderr(line) => {
|
|
let mut now = DeferredNow::default();
|
|
let message = CompactString::from(String::from_utf8_lossy(&line).as_ref());
|
|
let w = shared_writer.lock().await;
|
|
write_sidecar_log(w, &mut now, Level::Error, &message);
|
|
ClashLogger::global().append_log(message);
|
|
}
|
|
tauri_plugin_shell::process::CommandEvent::Terminated(term) => {
|
|
let mut now = DeferredNow::default();
|
|
let message = if let Some(code) = term.code {
|
|
CompactString::from(format!("Process terminated with code: {}", code))
|
|
} else if let Some(signal) = term.signal {
|
|
CompactString::from(format!("Process terminated by signal: {}", signal))
|
|
} else {
|
|
CompactString::from("Process terminated")
|
|
};
|
|
let w = shared_writer.lock().await;
|
|
write_sidecar_log(w, &mut now, Level::Info, &message);
|
|
ClashLogger::global().clear_logs();
|
|
break;
|
|
}
|
|
_ => {}
|
|
}
|
|
}
|
|
});
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub(super) fn stop_core_by_sidecar(&self) -> Result<()> {
|
|
logging!(info, Type::Core, "Stopping sidecar");
|
|
|
|
let mut state = self.state.lock();
|
|
if let Some(child) = state.child_sidecar.take() {
|
|
let pid = child.pid();
|
|
drop(child);
|
|
logging!(trace, Type::Core, "Sidecar stopped (PID: {:?})", pid);
|
|
}
|
|
state.running_mode = RunningMode::NotRunning;
|
|
Ok(())
|
|
}
|
|
|
|
pub(super) async fn start_core_by_service(&self) -> Result<()> {
|
|
logging!(info, Type::Core, "Starting core in service mode");
|
|
let config_file = Config::generate_file(crate::config::ConfigType::Run).await?;
|
|
service::run_core_by_service(&config_file).await?;
|
|
self.set_running_mode(RunningMode::Service);
|
|
Ok(())
|
|
}
|
|
|
|
pub(super) async fn stop_core_by_service(&self) -> Result<()> {
|
|
logging!(info, Type::Core, "Stopping service");
|
|
service::stop_core_by_service().await?;
|
|
self.set_running_mode(RunningMode::NotRunning);
|
|
Ok(())
|
|
}
|
|
}
|