fix: disconnect VPN when sleep

This commit is contained in:
Kevin Yue
2025-01-12 14:41:03 +08:00
parent ec85e857bc
commit 7e5e0069d7
21 changed files with 494 additions and 214 deletions

View File

@@ -16,7 +16,7 @@ clap.workspace = true
env_logger.workspace = true
inquire = "0.7"
log.workspace = true
tokio.workspace = true
tokio = { workspace = true, features = ["rt-multi-thread"] }
sysinfo.workspace = true
serde_json.workspace = true
whoami.workspace = true

View File

@@ -10,7 +10,7 @@ use tempfile::NamedTempFile;
use crate::{
connect::{ConnectArgs, ConnectHandler},
disconnect::DisconnectHandler,
disconnect::{DisconnectArgs, DisconnectHandler},
launch_gui::{LaunchGuiArgs, LaunchGuiHandler},
};
@@ -27,7 +27,7 @@ enum CliCommand {
#[command(about = "Connect to a portal server")]
Connect(Box<ConnectArgs>),
#[command(about = "Disconnect from the server")]
Disconnect,
Disconnect(DisconnectArgs),
#[command(about = "Launch the GUI")]
LaunchGui(LaunchGuiArgs),
}
@@ -102,7 +102,7 @@ impl Cli {
match &self.command {
CliCommand::Connect(args) => ConnectHandler::new(args, &shared_args).handle().await,
CliCommand::Disconnect => DisconnectHandler::new().handle(),
CliCommand::Disconnect(args) => DisconnectHandler::new(args).handle().await,
CliCommand::LaunchGui(args) => LaunchGuiHandler::new(args).handle().await,
}
}

View File

@@ -1,31 +1,63 @@
use crate::GP_CLIENT_LOCK_FILE;
use clap::Args;
use gpapi::utils::lock_file::gpservice_lock_info;
use log::{info, warn};
use std::fs;
use std::{fs, str::FromStr, thread, time::Duration};
use sysinfo::{Pid, Signal, System};
pub(crate) struct DisconnectHandler;
#[derive(Args)]
pub struct DisconnectArgs {
#[arg(
long,
required = false,
help = "The time in seconds to wait for the VPN connection to disconnect"
)]
wait: Option<u64>,
}
impl DisconnectHandler {
pub(crate) fn new() -> Self {
Self
pub struct DisconnectHandler<'a> {
args: &'a DisconnectArgs,
}
impl<'a> DisconnectHandler<'a> {
pub fn new(args: &'a DisconnectArgs) -> Self {
Self { args }
}
pub(crate) fn handle(&self) -> anyhow::Result<()> {
if fs::metadata(GP_CLIENT_LOCK_FILE).is_err() {
warn!("PID file not found, maybe the client is not running");
return Ok(());
pub async fn handle(&self) -> anyhow::Result<()> {
// Try to disconnect the CLI client
if let Ok(c) = fs::read_to_string(GP_CLIENT_LOCK_FILE) {
send_signal(c.trim(), Signal::Interrupt).unwrap_or_else(|err| {
warn!("Failed to send signal to client: {}", err);
});
};
// Try to disconnect the GUI service
if let Ok(c) = gpservice_lock_info().await {
send_signal(&c.pid.to_string(), Signal::User1).unwrap_or_else(|err| {
warn!("Failed to send signal to service: {}", err);
});
};
// sleep, to give the client and service time to disconnect
if let Some(wait) = self.args.wait {
thread::sleep(Duration::from_secs(wait));
}
let pid = fs::read_to_string(GP_CLIENT_LOCK_FILE)?;
let pid = pid.trim().parse::<usize>()?;
let s = System::new_all();
if let Some(process) = s.process(Pid::from(pid)) {
info!("Found process {}, killing...", pid);
if process.kill_with(Signal::Interrupt).is_none() {
warn!("Failed to kill process {}", pid);
}
}
Ok(())
}
}
fn send_signal(pid: &str, signal: Signal) -> anyhow::Result<()> {
let s = System::new_all();
let pid = Pid::from_str(pid)?;
if let Some(process) = s.process(pid) {
info!("Found process {}, sending signal...", pid);
if process.kill_with(signal).is_none() {
warn!("Failed to kill process {}", pid);
}
}
Ok(())
}