Files
sovereign_browser_rust/src/net_services.rs
T

126 lines
3.5 KiB
Rust

//! Network services management (Tor, FIPS, etc.)
//!
//! Port of `net_services.c` / `net_services.h` from the C project.
use std::sync::Mutex;
use once_cell::sync::Lazy;
/// Network service status.
#[derive(Debug, Clone, PartialEq)]
#[allow(dead_code)]
pub enum ServiceStatus {
Stopped,
Starting,
Running,
Error(String),
}
/// Network services state.
static G_NET_SERVICES: Lazy<Mutex<NetServicesState>> = Lazy::new(|| Mutex::new(NetServicesState::default()));
struct NetServicesState {
tor_status: ServiceStatus,
fips_status: ServiceStatus,
}
impl Default for NetServicesState {
fn default() -> Self {
NetServicesState {
tor_status: ServiceStatus::Stopped,
fips_status: ServiceStatus::Stopped,
}
}
}
/// Initialize network services.
pub fn net_services_init() {
let mut state = G_NET_SERVICES.lock().unwrap();
state.tor_status = ServiceStatus::Stopped;
state.fips_status = ServiceStatus::Stopped;
}
/// Get Tor status.
pub fn net_services_get_tor_status() -> ServiceStatus {
let state = G_NET_SERVICES.lock().unwrap();
state.tor_status.clone()
}
/// Get FIPS status.
pub fn net_services_get_fips_status() -> ServiceStatus {
let state = G_NET_SERVICES.lock().unwrap();
state.fips_status.clone()
}
/// Start Tor.
pub fn net_services_start_tor() -> Result<(), Box<dyn std::error::Error>> {
let mut state = G_NET_SERVICES.lock().unwrap();
state.tor_status = ServiceStatus::Starting;
// TODO: actually start Tor
state.tor_status = ServiceStatus::Running;
println!("[net] Tor started");
Ok(())
}
/// Stop Tor.
pub fn net_services_stop_tor() {
let mut state = G_NET_SERVICES.lock().unwrap();
state.tor_status = ServiceStatus::Stopped;
println!("[net] Tor stopped");
}
/// Start FIPS.
pub fn net_services_start_fips() -> Result<(), Box<dyn std::error::Error>> {
let mut state = G_NET_SERVICES.lock().unwrap();
state.fips_status = ServiceStatus::Starting;
// TODO: actually start FIPS
state.fips_status = ServiceStatus::Running;
println!("[net] FIPS started");
Ok(())
}
/// Stop FIPS.
pub fn net_services_stop_fips() {
let mut state = G_NET_SERVICES.lock().unwrap();
state.fips_status = ServiceStatus::Stopped;
println!("[net] FIPS stopped");
}
/// Get the Tor SOCKS proxy endpoint.
///
/// Returns the SOCKS5 endpoint (e.g. "socks5h://127.0.0.1:9050") if Tor
/// is available, or None if Tor is not running. The "socks5h" prefix
/// tells the proxy to perform DNS resolution through Tor (remote DNS),
/// which is required for .onion hostnames.
///
/// Checks both the internal service status AND whether the SOCKS port
/// is actually reachable (e.g. a system Tor daemon started outside the
/// browser).
pub fn net_services_get_tor_socks_endpoint() -> Option<String> {
{
let state = G_NET_SERVICES.lock().unwrap();
if state.tor_status == ServiceStatus::Running {
return Some("socks5h://127.0.0.1:9050".to_string());
}
}
// Check if a system Tor is listening on the default SOCKS port.
if tor_socks_port_available() {
Some("socks5h://127.0.0.1:9050".to_string())
} else {
None
}
}
/// Check if Tor's SOCKS port (9050) is accepting connections.
fn tor_socks_port_available() -> bool {
use std::net::TcpStream;
use std::time::Duration;
match TcpStream::connect_timeout(
&"127.0.0.1:9050".parse().unwrap(),
Duration::from_millis(300),
) {
Ok(_) => true,
Err(_) => false,
}
}