1use std::{fs, process};
2use nwep::{
3 Keypair,
4 server::{Router, ResponseWriter, Request, ServerBuilder},
5};
6
7const DEFAULT_KEY_FILE: &str = "server.key";
8const DEFAULT_ADDR: &str = "[::]:6937";
9
10fn load_or_generate_keypair(path: &str) -> Result<Keypair, Box<dyn std::error::Error>> {
11 match fs::read_to_string(path) {
12 Ok(contents) => {
13 let hex = contents.trim();
14 if hex.len() != 64 {
15 return Err(format!("invalid key file {path}: expected 64 hex chars").into());
16 }
17 let bytes: Vec<u8> = (0..32)
18 .map(|i| u8::from_str_radix(&hex[i * 2..i * 2 + 2], 16))
19 .collect::<Result<_, _>>()?;
20 let mut seed = [0u8; 32];
21 seed.copy_from_slice(&bytes);
22 Ok(Keypair::from_seed(&seed)?)
23 }
24 Err(e) if e.kind() == std::io::ErrorKind::NotFound => {
25 let kp = Keypair::generate()?;
26 let hex: String = kp.seed().iter().map(|b| format!("{b:02x}")).collect();
27 fs::write(path, format!("{hex}\n"))
28 .map_err(|e| format!("saving key file: {e}"))?;
29 Ok(kp)
30 }
31 Err(e) => Err(e.into()),
32 }
33}
34
35fn main() {
36 nwep::init().unwrap_or_else(|e| {
37 eprintln!("init: {e}");
38 process::exit(1);
39 });
40
41 let key_file = std::env::var("NWEP_KEY_FILE").unwrap_or_else(|_| DEFAULT_KEY_FILE.into());
42 let keypair = load_or_generate_keypair(&key_file).unwrap_or_else(|e| {
43 eprintln!("keypair: {e}");
44 process::exit(1);
45 });
46
47 let node_id = keypair.node_id().unwrap_or_else(|e| {
48 eprintln!("node_id: {e}");
49 process::exit(1);
50 });
51 eprintln!("node id: {node_id}");
52
53 let mut router = Router::new();
54 router.handle_func("/hello", |w: &mut ResponseWriter, _r: &Request| {
55 let _ = w.respond("ok", b"hello from nwep-rust");
56 });
57
58 let addr = std::env::args().nth(1).unwrap_or_else(|| DEFAULT_ADDR.into());
59
60 let (server, event_loop) = ServerBuilder::new(&addr, keypair)
61 .on_connect(|info| eprintln!("connected: {}", info.node_id))
62 .on_disconnect(|info, code| eprintln!("disconnected: {} (code {code})", info.node_id))
63 .build(router)
64 .unwrap_or_else(|e| {
65 eprintln!("server: {e}");
66 process::exit(1);
67 });
68
69 let url = server.url("/hello");
70 eprintln!("listening on {}", server.addr());
71 println!("{url}"); if let Err(e) = event_loop.run() {
74 eprintln!("server run: {e}");
75 process::exit(1);
76 }
77}