use emissary_core::router::Router; use emissary_core::{Config, Ntcp2Config, SamConfig, TransitConfig}; use emissary_util::reseeder::Reseeder; use emissary_util::runtime::tokio::Runtime as TokioRuntime; use emissary_util::storage::{Storage, StorageBundle}; use serde::{Deserialize, Serialize}; use std::future::Future; use std::path::PathBuf; use std::sync::Arc; use tokio::sync::Mutex; lazy_static::lazy_static! { pub static ref ROUTER: Arc>>> = Arc::new(Mutex::new(None)); } pub trait RouterUtils { fn config(&mut self) -> impl Future>> + Send; fn reseed(&mut self) -> impl Future>> + Send; fn start( self, ) -> impl Future, Box>> + Send; } #[derive(Debug, Deserialize, Serialize)] pub struct EmissaryConfig { pub storage: Option, pub auto_update: Option, pub http_proxy_port: Option, pub socks_proxy_port: Option, } pub struct Emissary { config: EmissaryConfig, storage: Option, storage_bundle: Option, } impl Emissary { pub fn new(config: EmissaryConfig) -> Self { Self { config, storage: None, storage_bundle: None, } } fn ensure_configured(&self) -> Result<(), Box> { if self.storage.is_none() || self.storage_bundle.is_none() { Err("Router not configured. Call `config()` first.".into()) } else { Ok(()) } } } impl RouterUtils for Emissary { async fn config(&mut self) -> Result<(), Box> { if self.config.storage.is_none() { self.config.storage = Some(PathBuf::from("/var/lib/mesk/router/")); } if self.config.auto_update.is_none() { self.config.auto_update = Some(true); } if self.config.http_proxy_port.is_none() { self.config.http_proxy_port = Some(4445); } if self.config.socks_proxy_port.is_none() { self.config.socks_proxy_port = Some(4446); } let storage = Storage::new(Some(self.config.storage.clone().unwrap())).await?; let bundle = storage.load().await; self.storage = Some(storage); self.storage_bundle = Some(bundle); Ok(()) } async fn reseed(&mut self) -> Result<(), Box> { self.ensure_configured()?; let storage = self.storage.as_ref().unwrap(); let mut bundle = self.storage_bundle.take().unwrap(); if bundle.routers.is_empty() { match Reseeder::reseed(None, false).await { Ok(reseed_routers) => { for info in reseed_routers { if let Err(e) = storage .store_router_info(info.name.to_string(), info.router_info.clone()) .await { println!("Failed to store reseeded router info: {}", e); } bundle.routers.push(info.router_info); } } Err(e) => { if bundle.routers.is_empty() { self.storage_bundle = Some(bundle); return Err(format!("Reseed failed and no routers available: {}", e).into()); } else { println!("Reseed failed, but using existing routers: {}", e); } } } } self.storage_bundle = Some(bundle); Ok(()) } async fn start(self) -> Result, Box> { let storage = self.storage.unwrap(); let bundle = self.storage_bundle.unwrap(); let config = Config { ntcp2: Some(Ntcp2Config { port: 25515, key: bundle.ntcp2_key, iv: bundle.ntcp2_iv, publish: true, host: None, }), samv3_config: Some(SamConfig { tcp_port: self.config.http_proxy_port.unwrap_or(4445), udp_port: self.config.socks_proxy_port.unwrap_or(4446), host: "127.0.0.1".to_string(), }), routers: bundle.routers, profiles: bundle.profiles, router_info: bundle.router_info, static_key: Some(bundle.static_key), signing_key: Some(bundle.signing_key), transit: Some(TransitConfig { max_tunnels: Some(1000), }), ..Default::default() }; let (router, _events, router_info) = Router::::new( config, None, // AddressBook Some(Arc::new(storage.clone())), ) .await .map_err(|e| format!("Router creation failed: {}", e))?; storage.store_local_router_info(router_info).await?; Ok(router) } }