111 lines
3.3 KiB
Rust
111 lines
3.3 KiB
Rust
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::<SocketAddr>().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<Item = String>,
|
|
flag: &'static str,
|
|
) -> Result<String, String> {
|
|
args.next()
|
|
.ok_or_else(|| format!("{flag} requires a value"))
|
|
}
|
|
|
|
fn parse_u64(flag: &'static str, value: &str) -> Result<u64, String> {
|
|
value
|
|
.parse::<u64>()
|
|
.map_err(|e| format!("{flag}: invalid value: {e}"))
|
|
}
|
|
|
|
fn parse_u32(flag: &'static str, value: &str) -> Result<u32, String> {
|
|
value
|
|
.parse::<u32>()
|
|
.map_err(|e| format!("{flag}: invalid value: {e}"))
|
|
}
|
|
|
|
fn print_usage() {
|
|
eprintln!(
|
|
"\
|
|
pfs-tftp (server)
|
|
|
|
USAGE:
|
|
pfs-tftp [OPTIONS]
|
|
|
|
OPTIONS:
|
|
--bind <IP:PORT> Bind address (default: 0.0.0.0:6969)
|
|
--root <DIR> Root directory (default: .)
|
|
--allow-write Enable WRQ (default: disabled)
|
|
--overwrite Allow overwriting existing files (default: disabled)
|
|
--timeout-ms <MILLIS> Packet timeout (default: 5000)
|
|
--retries <N> Retransmit attempts (default: 5)
|
|
--dally-timeout-ms <MILLIS>Wait time for duplicate final DATA (default: timeout)
|
|
--dally-retries <N> Dally attempts (default: 2)
|
|
--help, -h Show this help
|
|
"
|
|
);
|
|
}
|