mirror of
https://github.com/yuezk/GlobalProtect-openconnect.git
synced 2025-05-20 07:26:58 -04:00
fix: disconnect VPN when sleep
This commit is contained in:
@@ -14,7 +14,7 @@ clap.workspace = true
|
||||
env_logger.workspace = true
|
||||
inquire = "0.6.2"
|
||||
log.workspace = true
|
||||
tokio.workspace = true
|
||||
tokio = { workspace = true, features = ["rt-multi-thread"] }
|
||||
sysinfo.workspace = true
|
||||
serde_json.workspace = true
|
||||
whoami.workspace = true
|
||||
|
@@ -7,7 +7,7 @@ use tempfile::NamedTempFile;
|
||||
|
||||
use crate::{
|
||||
connect::{ConnectArgs, ConnectHandler},
|
||||
disconnect::DisconnectHandler,
|
||||
disconnect::{DisconnectArgs, DisconnectHandler},
|
||||
launch_gui::{LaunchGuiArgs, LaunchGuiHandler},
|
||||
};
|
||||
|
||||
@@ -23,7 +23,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),
|
||||
}
|
||||
@@ -81,7 +81,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,
|
||||
}
|
||||
}
|
||||
|
@@ -84,11 +84,11 @@ pub(crate) struct ConnectArgs {
|
||||
#[arg(long, default_value = GP_USER_AGENT, help = "The user agent to use")]
|
||||
user_agent: String,
|
||||
|
||||
#[arg(long, default_value = "Linux")]
|
||||
#[arg(long, value_enum, default_value_t = ConnectArgs::default_os())]
|
||||
os: Os,
|
||||
|
||||
#[arg(long)]
|
||||
os_version: Option<String>,
|
||||
#[arg(long, default_value_t = ConnectArgs::default_os_version())]
|
||||
os_version: String,
|
||||
|
||||
#[arg(long, help = "Disable DTLS and ESP")]
|
||||
no_dtls: bool,
|
||||
@@ -110,12 +110,16 @@ pub(crate) struct ConnectArgs {
|
||||
}
|
||||
|
||||
impl ConnectArgs {
|
||||
fn os_version(&self) -> String {
|
||||
if let Some(os_version) = &self.os_version {
|
||||
return os_version.to_owned();
|
||||
fn default_os() -> Os {
|
||||
if cfg!(target_os = "macos") {
|
||||
Os::Mac
|
||||
} else {
|
||||
Os::Linux
|
||||
}
|
||||
}
|
||||
|
||||
match self.os {
|
||||
fn default_os_version() -> String {
|
||||
match ConnectArgs::default_os() {
|
||||
Os::Linux => format!("Linux {}", whoami::distro()),
|
||||
Os::Windows => String::from("Microsoft Windows 11 Pro , 64-bit"),
|
||||
Os::Mac => String::from("Apple Mac OS X 13.4.0"),
|
||||
@@ -142,7 +146,7 @@ impl<'a> ConnectHandler<'a> {
|
||||
GpParams::builder()
|
||||
.user_agent(&self.args.user_agent)
|
||||
.client_os(ClientOs::from(&self.args.os))
|
||||
.os_version(self.args.os_version())
|
||||
.os_version(self.args.os_version.clone())
|
||||
.ignore_tls_errors(self.shared_args.ignore_tls_errors)
|
||||
.certificate(self.args.certificate.clone())
|
||||
.sslkey(self.args.sslkey.clone())
|
||||
@@ -355,7 +359,7 @@ impl<'a> ConnectHandler<'a> {
|
||||
.saml_request(prelogin.saml_request())
|
||||
.user_agent(&self.args.user_agent)
|
||||
.os(self.args.os.as_str())
|
||||
.os_version(Some(&self.args.os_version()))
|
||||
.os_version(Some(&self.args.os_version))
|
||||
.hidpi(self.args.hidpi)
|
||||
.fix_openssl(self.shared_args.fix_openssl)
|
||||
.ignore_tls_errors(self.shared_args.ignore_tls_errors)
|
||||
|
@@ -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, ProcessExt, Signal, System, SystemExt};
|
||||
|
||||
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(())
|
||||
}
|
||||
|
Reference in New Issue
Block a user