use std::{fs, process};
use nwep::{
Keypair,
server::{Router, ResponseWriter, Request, ServerBuilder},
};
const DEFAULT_KEY_FILE: &str = "server.key";
const DEFAULT_ADDR: &str = "[::]:6937";
fn load_or_generate_keypair(path: &str) -> Result<Keypair, Box<dyn std::error::Error>> {
match fs::read_to_string(path) {
Ok(contents) => {
let hex = contents.trim();
if hex.len() != 64 {
return Err(format!("invalid key file {path}: expected 64 hex chars").into());
}
let bytes: Vec<u8> = (0..32)
.map(|i| u8::from_str_radix(&hex[i * 2..i * 2 + 2], 16))
.collect::<Result<_, _>>()?;
let mut seed = [0u8; 32];
seed.copy_from_slice(&bytes);
Ok(Keypair::from_seed(&seed)?)
}
Err(e) if e.kind() == std::io::ErrorKind::NotFound => {
let kp = Keypair::generate()?;
let hex: String = kp.seed().iter().map(|b| format!("{b:02x}")).collect();
fs::write(path, format!("{hex}\n"))
.map_err(|e| format!("saving key file: {e}"))?;
Ok(kp)
}
Err(e) => Err(e.into()),
}
}
fn main() {
nwep::init().unwrap_or_else(|e| {
eprintln!("init: {e}");
process::exit(1);
});
let key_file = std::env::var("NWEP_KEY_FILE").unwrap_or_else(|_| DEFAULT_KEY_FILE.into());
let keypair = load_or_generate_keypair(&key_file).unwrap_or_else(|e| {
eprintln!("keypair: {e}");
process::exit(1);
});
let node_id = keypair.node_id().unwrap_or_else(|e| {
eprintln!("node_id: {e}");
process::exit(1);
});
eprintln!("node id: {node_id}");
let mut router = Router::new();
router.handle_func("/hello", |w: &mut ResponseWriter, _r: &Request| {
let _ = w.respond("ok", b"hello from nwep-rust");
});
let addr = std::env::args().nth(1).unwrap_or_else(|| DEFAULT_ADDR.into());
let (server, event_loop) = ServerBuilder::new(&addr, keypair)
.on_connect(|info| eprintln!("connected: {}", info.node_id))
.on_disconnect(|info, code| eprintln!("disconnected: {} (code {code})", info.node_id))
.build(router)
.unwrap_or_else(|e| {
eprintln!("server: {e}");
process::exit(1);
});
let url = server.url("/hello");
eprintln!("listening on {}", server.addr());
println!("{url}");
if let Err(e) = event_loop.run() {
eprintln!("server run: {e}");
process::exit(1);
}
}