//! Standalone NetDesk native host engine. Captures the screen and serves //! viewers over the NetDesk protocol with the best available H.264 encoder and //! SendInput injection. Configured via environment: //! ND_HOST_ID (required) the id viewers connect to //! ND_PASSWORD (required) session password (never leaves this machine) //! ND_WS_URL default wss://netdesk.space/ws //! ND_NAME default "NetDesk (Rust)" //! ND_MONITOR default 0 //! ND_FPS default 60 //! ND_BITRATE default 8000000 fn main() -> anyhow::Result<()> { env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init(); #[cfg(windows)] { let host_id = std::env::var("ND_HOST_ID").map_err(|_| anyhow::anyhow!("set ND_HOST_ID"))?; let password = std::env::var("ND_PASSWORD").map_err(|_| anyhow::anyhow!("set ND_PASSWORD"))?; let cfg = netdesk_host::run::EngineConfig { ws_url: std::env::var("ND_WS_URL").unwrap_or_else(|_| "wss://netdesk.space/ws".into()), host_id, name: std::env::var("ND_NAME").unwrap_or_else(|_| "NetDesk (Rust)".into()), password, monitor: envnum("ND_MONITOR", 0), fps: envnum("ND_FPS", 60), bitrate: envnum("ND_BITRATE", 8_000_000), // Host-enforced permissions + approve-before-connect (see run.rs): // ND_PERM_INPUT / ND_PERM_CLIPBOARD / ND_PERM_FILES / ND_PERM_AUDIO // (default 1) and ND_APPROVE (default 0). perms: netdesk_core::host::HostPerms { input: envflag("ND_PERM_INPUT", true), clipboard: envflag("ND_PERM_CLIPBOARD", true), files: envflag("ND_PERM_FILES", true), audio: envflag("ND_PERM_AUDIO", true), }, approve: envflag("ND_APPROVE", false), totp_secret: std::env::var("ND_TOTP").unwrap_or_default(), // Encrypted direct-IP: ND_DIRECT_PORT makes the host listen on that // TCP port for a viewer that dials it directly (no relay); // ND_ALLOW_IPS is an optional CIDR allow-list. direct_port: std::env::var("ND_DIRECT_PORT").ok().and_then(|s| s.parse().ok()), allow_ips: std::env::var("ND_ALLOW_IPS").unwrap_or_default(), // ND_MAX_VIEWERS>1 allows multiple simultaneous direct-IP viewers // (1 controller + N observers of the one capture). max_viewers: std::env::var("ND_MAX_VIEWERS") .ok() .and_then(|s| s.parse().ok()) .unwrap_or(1) .max(1), }; let rt = tokio::runtime::Builder::new_multi_thread() .enable_all() .build()?; let handle = netdesk_host::run::EngineHandle::new(); rt.block_on(netdesk_host::run::run_engine(cfg, handle))?; } #[cfg(not(windows))] println!("engine is Windows-only"); Ok(()) } #[cfg(windows)] fn envnum(key: &str, default: T) -> T { std::env::var(key).ok().and_then(|s| s.parse().ok()).unwrap_or(default) } /// "1"/"true"/"yes" = true, "0"/"false"/"no" = false, unset = `default`. #[cfg(windows)] fn envflag(key: &str, default: bool) -> bool { match std::env::var(key).as_deref().map(str::trim) { Ok("1") | Ok("true") | Ok("yes") => true, Ok("0") | Ok("false") | Ok("no") => false, _ => default, } }