use std::{net::SocketAddr, path::PathBuf, time::Duration}; use pfs_tftp_sync::{Server, ServerConfig}; fn main() { match run() { Ok(()) => {} Err(e) => { eprintln!("{e}"); std::process::exit(2); } } } fn run() -> Result<(), String> { let mut cfg = ServerConfig::default(); let mut args = std::env::args().skip(1); while let Some(arg) = args.next() { match arg.as_str() { "--help" | "-h" => { print_usage(); return Ok(()); } "--bind" => { let value = next_value(&mut args, "--bind")?; cfg.bind = value.parse::().map_err(|e| format!("{e}"))?; } "--root" => { let value = next_value(&mut args, "--root")?; cfg.root = PathBuf::from(value); } "--allow-write" => cfg.allow_write = true, "--overwrite" => cfg.overwrite = true, "--timeout-ms" => { let value = next_value(&mut args, "--timeout-ms")?; cfg.timeout = Duration::from_millis(parse_u64("--timeout-ms", &value)?); } "--retries" => { let value = next_value(&mut args, "--retries")?; cfg.retries = parse_u32("--retries", &value)?; } "--dally-timeout-ms" => { let value = next_value(&mut args, "--dally-timeout-ms")?; cfg.dally_timeout = Duration::from_millis(parse_u64("--dally-timeout-ms", &value)?); } "--dally-retries" => { let value = next_value(&mut args, "--dally-retries")?; cfg.dally_retries = parse_u32("--dally-retries", &value)?; } other => return Err(format!("unknown argument: {other}")), } } eprintln!( "Serving TFTP on {} (root: {}, allow_write: {}, overwrite: {})", cfg.bind, cfg.root.display(), cfg.allow_write, cfg.overwrite ); Server::new(cfg) .serve() .map_err(|e| format!("server error: {e}"))?; Ok(()) } fn next_value( args: &mut impl Iterator, flag: &'static str, ) -> Result { args.next() .ok_or_else(|| format!("{flag} requires a value")) } fn parse_u64(flag: &'static str, value: &str) -> Result { value .parse::() .map_err(|e| format!("{flag}: invalid value: {e}")) } fn parse_u32(flag: &'static str, value: &str) -> Result { value .parse::() .map_err(|e| format!("{flag}: invalid value: {e}")) } fn print_usage() { eprintln!( "\ pfs-tftp (server) USAGE: pfs-tftp [OPTIONS] OPTIONS: --bind Bind address (default: 0.0.0.0:6969) --root Root directory (default: .) --allow-write Enable WRQ (default: disabled) --overwrite Allow overwriting existing files (default: disabled) --timeout-ms Packet timeout (default: 5000) --retries Retransmit attempts (default: 5) --dally-timeout-ms Wait time for duplicate final DATA (default: timeout) --dally-retries Dally attempts (default: 2) --help, -h Show this help " ); }