use anyhow::{Context, Result}; use clap::Parser; use dosh::auth::{build_bootstrap, encode_bootstrap, load_or_create_server_secret}; use dosh::config::load_server_config; #[derive(Debug, Parser)] struct Args { #[arg(long, default_value_t = 1)] protocol: u8, #[arg(long)] nonce: String, #[arg(long, default_value = "default")] session: String, #[arg(long, default_value = "read-write")] mode: String, #[arg(long, default_value = "80x24")] size: String, #[arg(long, default_value = "dev")] client_version: String, #[arg(long)] udp_host: Option, } fn main() -> Result<()> { let args = Args::parse(); anyhow::ensure!(args.protocol == 1, "unsupported protocol {}", args.protocol); let config = load_server_config(None)?; let secret = load_or_create_server_secret(&config)?; let nonce = parse_nonce(&args.nonce)?; let size = parse_size(&args.size)?; let user = std::env::var("USER").unwrap_or_else(|_| "unknown".to_string()); let udp_host = args.udp_host.unwrap_or_else(|| "127.0.0.1".to_string()); let resp = build_bootstrap( &config, &secret, user, args.session, args.mode, size, nonce, udp_host, )?; println!("{}", encode_bootstrap(&resp)?); Ok(()) } fn parse_nonce(raw: &str) -> Result<[u8; 12]> { let bytes = base64::Engine::decode(&base64::engine::general_purpose::URL_SAFE_NO_PAD, raw) .context("decode nonce")?; anyhow::ensure!(bytes.len() == 12, "nonce must decode to 12 bytes"); let mut out = [0u8; 12]; out.copy_from_slice(&bytes); Ok(out) } fn parse_size(raw: &str) -> Result<(u16, u16)> { let (cols, rows) = raw.split_once('x').context("size must be COLSxROWS")?; Ok((cols.parse()?, rows.parse()?)) }