feat: add single instance enforcement with TCP socket lock
Add single instance check using TCP listener on 127.0.0.1:53190 to prevent multiple application instances. Move AppState initialization into setup closure to include single_instance_lock field. Remove window close prevention and focus restoration handlers. Make main window non-resizable and non-maximizable.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
mod tunnel_manager;
|
||||
|
||||
use std::{fs, path::PathBuf, sync::Mutex};
|
||||
use std::{fs, net::TcpListener, path::PathBuf, sync::Mutex};
|
||||
|
||||
use base64::{engine::general_purpose::STANDARD, Engine as _};
|
||||
use rand_core::OsRng;
|
||||
@@ -15,9 +15,11 @@ use x25519_dalek::{PublicKey, StaticSecret};
|
||||
|
||||
const PROFILE_NAME: &str = "NexaVPN";
|
||||
const MAIN_WINDOW_LABEL: &str = "main";
|
||||
const SINGLE_INSTANCE_ADDR: &str = "127.0.0.1:53190";
|
||||
|
||||
struct AppState {
|
||||
session: Mutex<Option<SessionState>>,
|
||||
single_instance_lock: TcpListener,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
@@ -362,12 +364,6 @@ fn ensure_app_dir(app: &AppHandle) -> Result<PathBuf, String> {
|
||||
Ok(dir)
|
||||
}
|
||||
|
||||
fn restore_window(window: &Window) {
|
||||
let _ = window.show();
|
||||
let _ = window.unminimize();
|
||||
let _ = window.set_focus();
|
||||
}
|
||||
|
||||
fn restore_webview_window(window: &WebviewWindow) {
|
||||
let _ = window.show();
|
||||
let _ = window.unminimize();
|
||||
@@ -382,6 +378,9 @@ fn hide_main_window(window: &Window) {
|
||||
pub fn run() {
|
||||
tauri::Builder::default()
|
||||
.setup(|app| {
|
||||
let single_instance_lock = TcpListener::bind(SINGLE_INSTANCE_ADDR)
|
||||
.map_err(|_| format!("{} is already running.", app.package_info().name))?;
|
||||
|
||||
let open_item = MenuItemBuilder::with_id("open", "Open NexaVPN").build(app)?;
|
||||
let quit_item = MenuItemBuilder::with_id("quit", "Quit NexaVPN").build(app)?;
|
||||
let menu = MenuBuilder::new(app).items(&[&open_item, &quit_item]).build()?;
|
||||
@@ -418,24 +417,20 @@ pub fn run() {
|
||||
})
|
||||
.build(app)?;
|
||||
|
||||
app.manage(AppState {
|
||||
session: Mutex::new(None),
|
||||
single_instance_lock,
|
||||
});
|
||||
|
||||
Ok(())
|
||||
})
|
||||
.manage(AppState {
|
||||
session: Mutex::new(None),
|
||||
})
|
||||
.on_window_event(|window, event| match event {
|
||||
WindowEvent::CloseRequested { api, .. } => {
|
||||
api.prevent_close();
|
||||
hide_main_window(window);
|
||||
}
|
||||
WindowEvent::CloseRequested { .. } => {}
|
||||
WindowEvent::Resized(_) => {
|
||||
if window.is_minimized().unwrap_or(false) {
|
||||
hide_main_window(window);
|
||||
}
|
||||
}
|
||||
WindowEvent::Focused(true) => {
|
||||
restore_window(window);
|
||||
}
|
||||
_ => {}
|
||||
})
|
||||
.invoke_handler(tauri::generate_handler![load_state, clear_session, enroll_device, sync_profile, connect_tunnel, disconnect_tunnel, tunnel_status])
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
"title": "NexaVPN",
|
||||
"width": 1120,
|
||||
"height": 760,
|
||||
"resizable": true
|
||||
"resizable": false,
|
||||
"maximizable": false
|
||||
}
|
||||
],
|
||||
"security": {
|
||||
|
||||
Reference in New Issue
Block a user