77 lines
3.5 KiB
Rust
77 lines
3.5 KiB
Rust
//! 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<T: std::str::FromStr>(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,
|
|
}
|
|
}
|