feat: Windows stack (daemon, installer, GUI)
Components: - ostp-daemon: Windows Service with Named Pipe IPC - ostp-installer: Setup wizard with admin privileges - ostp-gui: Tauri dark theme UI (450x600) Features: - Background service management (OspabGuard) - IPC commands: CONNECT/DISCONNECT/STATUS - Firewall rules auto-configuration - Wintun driver placeholder (download from wintun.net) - Real-time stats display (upload/download/ping) Note: Requires wintun.dll download for full functionality
This commit is contained in:
39
ostp-gui/src/ipc.rs
Normal file
39
ostp-gui/src/ipc.rs
Normal file
@@ -0,0 +1,39 @@
|
||||
//! IPC communication with ostp-daemon via Named Pipe
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use std::io::{Read, Write};
|
||||
|
||||
const PIPE_NAME: &str = r"\\.\pipe\ostp-daemon";
|
||||
|
||||
pub async fn send_command(command: &str) -> Result<String> {
|
||||
#[cfg(windows)]
|
||||
{
|
||||
use std::fs::OpenOptions;
|
||||
use std::os::windows::fs::OpenOptionsExt;
|
||||
use winapi::um::winbase::FILE_FLAG_OVERLAPPED;
|
||||
|
||||
// Connect to Named Pipe
|
||||
let mut pipe = OpenOptions::new()
|
||||
.read(true)
|
||||
.write(true)
|
||||
.custom_flags(FILE_FLAG_OVERLAPPED)
|
||||
.open(PIPE_NAME)
|
||||
.context("Failed to connect to ostp-daemon. Is the service running?")?;
|
||||
|
||||
// Send command
|
||||
pipe.write_all(command.as_bytes())?;
|
||||
pipe.write_all(b"\n")?;
|
||||
pipe.flush()?;
|
||||
|
||||
// Read response
|
||||
let mut response = String::new();
|
||||
pipe.read_to_string(&mut response)?;
|
||||
|
||||
Ok(response.trim().to_string())
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
{
|
||||
anyhow::bail!("Named pipes are only supported on Windows");
|
||||
}
|
||||
}
|
||||
56
ostp-gui/src/main.rs
Normal file
56
ostp-gui/src/main.rs
Normal file
@@ -0,0 +1,56 @@
|
||||
//! OSTP GUI - Windows Client Interface
|
||||
//!
|
||||
//! Communicates with ostp-daemon via Named Pipe
|
||||
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||
|
||||
mod ipc;
|
||||
mod state;
|
||||
|
||||
use tauri::Manager;
|
||||
use state::AppState;
|
||||
|
||||
#[tauri::command]
|
||||
async fn connect_vpn(state: tauri::State<'_, AppState>) -> Result<String, String> {
|
||||
ipc::send_command("CONNECT")
|
||||
.await
|
||||
.map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn disconnect_vpn(state: tauri::State<'_, AppState>) -> Result<String, String> {
|
||||
ipc::send_command("DISCONNECT")
|
||||
.await
|
||||
.map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn get_status(state: tauri::State<'_, AppState>) -> Result<String, String> {
|
||||
ipc::send_command("STATUS")
|
||||
.await
|
||||
.map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn fetch_servers() -> Result<Vec<String>, String> {
|
||||
// TODO: Fetch from Master Node API
|
||||
Ok(vec![
|
||||
"RU - Moscow".to_string(),
|
||||
"US - New York".to_string(),
|
||||
"DE - Frankfurt".to_string(),
|
||||
])
|
||||
}
|
||||
|
||||
fn main() {
|
||||
tauri::Builder::default()
|
||||
.plugin(tauri_plugin_shell::init())
|
||||
.manage(AppState::new())
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
connect_vpn,
|
||||
disconnect_vpn,
|
||||
get_status,
|
||||
fetch_servers
|
||||
])
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
}
|
||||
37
ostp-gui/src/state.rs
Normal file
37
ostp-gui/src/state.rs
Normal file
@@ -0,0 +1,37 @@
|
||||
//! Application state management
|
||||
|
||||
use std::sync::{Arc, Mutex};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct ConnectionStatus {
|
||||
pub connected: bool,
|
||||
pub server: Option<String>,
|
||||
pub upload_speed: u64,
|
||||
pub download_speed: u64,
|
||||
pub ping: u32,
|
||||
}
|
||||
|
||||
impl Default for ConnectionStatus {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
connected: false,
|
||||
server: None,
|
||||
upload_speed: 0,
|
||||
download_speed: 0,
|
||||
ping: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct AppState {
|
||||
pub status: Arc<Mutex<ConnectionStatus>>,
|
||||
}
|
||||
|
||||
impl AppState {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
status: Arc::new(Mutex::new(ConnectionStatus::default())),
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user