// webrtc-peer --tunnel = ... [--origin ] [--port 0] [--host 127.0.0.1] // The loopback check's WebRTC guest (src/lib.rs): `cargo build --release` builds it. use std::collections::HashMap; use atlibs_host::Signal; const USAGE: &str = "usage: webrtc-peer --tunnel = ... [--origin ] [--port 0] [--host 127.0.0.1]"; fn parse(argv: &[String]) -> Result<(HashMap, std::net::IpAddr, u16, Option), String> { let (mut tunnels, mut host, mut port, mut origin) = (HashMap::new(), "127.0.0.1".to_string(), "0".to_string(), None); let mut it = argv.iter(); while let Some(flag) = it.next() { let mut value = || it.next().cloned().ok_or(format!("{flag} needs a value\n{USAGE}")); match flag.as_str() { "--tunnel" => { let t = value()?; let (tag, p) = t.split_once('=').ok_or(format!("--tunnel {t}: want ="))?; tunnels.insert(tag.to_string(), p.parse::().map_err(|e| format!("--tunnel {t}: {e}"))?); } "--host" => host = value()?, "--port" => port = value()?, "--origin" => origin = Some(value()?.trim_end_matches('/').to_string()), _ => return Err(USAGE.into()), } } if tunnels.is_empty() { return Err(USAGE.into()); } Ok((tunnels, host.parse().map_err(|e| format!("--host: {e}"))?, port.parse().map_err(|e| format!("--port: {e}"))?, origin)) } #[tokio::main(flavor = "current_thread")] async fn main() -> std::process::ExitCode { let argv: Vec = std::env::args().skip(1).collect(); let signal = Signal::new(); let stop = signal.clone(); tokio::spawn(async move { if tokio::signal::ctrl_c().await.is_ok() { stop.abort("aborted"); } }); let ran = match parse(&argv) { Ok((tunnels, host, port, origin)) => atlibs_webrtc::main(tunnels, host, port, origin, signal).await, Err(e) => Err(e), }; match ran { Ok(()) => std::process::ExitCode::SUCCESS, Err(e) => { eprintln!("{e}"); std::process::ExitCode::FAILURE } } }