diff --git a/README.md b/README.md index 40f5f5a..4a5c0e4 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,16 @@ Path found, destination <0e1fb61e3b38e332868b331740642f41> is 4 hops away via <1 For now, UDP ports are allocated to links in order from `42000` to `65535`. +The graph can also be read from a text file listing edges, using option `-G `. An edge is a space-separated list of two node indices. Separation can be any whitespace character. Example: + +``` +0 1 +1 2 +2 0 +1 3 +3 4 +``` + ## License [Support me via LiberaPay](https://liberapay.com/tuxmain/donate) diff --git a/mitm.py b/mitm.py new file mode 100644 index 0000000..e69de29 diff --git a/src/generator.rs b/src/graph_generator.rs similarity index 100% rename from src/generator.rs rename to src/graph_generator.rs diff --git a/src/graph_reader.rs b/src/graph_reader.rs new file mode 100644 index 0000000..8d2ebba --- /dev/null +++ b/src/graph_reader.rs @@ -0,0 +1,20 @@ +use std::{ + io::{BufRead, BufReader}, + path::Path, +}; + +pub fn read_graph_file(path: &Path) -> Vec<(usize, usize)> { + let file = std::fs::OpenOptions::new().read(true).open(path).unwrap(); + let reader = BufReader::new(file); + let mut edges = Vec::new(); + for line in reader.lines() { + let line = line.unwrap(); + let mut cols = line.split_whitespace(); + if let (Some(n1), Some(n2)) = (cols.next(), cols.next()) { + if let (Ok(n1), Ok(n2)) = (n1.parse(), n2.parse()) { + edges.push((n1, n2)); + } + } + } + edges +} diff --git a/src/render.rs b/src/graph_render.rs similarity index 100% rename from src/render.rs rename to src/graph_render.rs diff --git a/src/main.rs b/src/main.rs index 8583e48..caa11a3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,14 +1,14 @@ -mod generator; -mod render; -mod udp; +mod graph_generator; +mod graph_reader; +mod graph_render; +mod traffic_generator; use std::{ - collections::{hash_map::Entry, HashMap}, io::Write, net::Ipv4Addr, path::{PathBuf, Path}, os::{unix::net::{SocketAddr, UnixStream}, linux::net::SocketAddrExt} + collections::{HashMap, hash_map::Entry}, + io::Write, + path::{Path, PathBuf}, }; -use rand::Rng; -use reticulum::{encode::Encode, sign::FixedKeys, packet::Packet, TestInf}; - /// Generate configuration for local Reticulum networks #[derive(argp::FromArgs)] struct Cli { @@ -18,6 +18,9 @@ struct Cli { /// Generate graph and create Reticulum configs #[argp(switch, short = 'g', long = "gen")] generate: bool, + /// Read graph file instead of generating random (one edge per line, node numbers separated by space) + #[argp(option, short = 'G')] + graph: Option, /// Number of nodes #[argp(option, short = 'n', default = "5")] nodes: usize, @@ -37,13 +40,17 @@ fn main() { let cli: Cli = argp::parse_args_or_exit(argp::DEFAULT); if cli.generate { - let mut rng = rand::thread_rng(); + let edges = if let Some(graph_file) = cli.graph { + graph_reader::read_graph_file(Path::new(&graph_file)) + } else { + let mut rng = rand::thread_rng(); - assert!( - cli.proba >= 0.0 && cli.proba <= 1.0, - "Probability should be between 0 and 1." - ); - let edges = generator::generate(cli.nodes, cli.proba, &mut rng); + assert!( + cli.proba >= 0.0 && cli.proba <= 1.0, + "Probability should be between 0 and 1." + ); + graph_generator::generate(cli.nodes, cli.proba, &mut rng) + }; let mut ports = HashMap::new(); let mut port: u16 = 42000; @@ -51,7 +58,8 @@ fn main() { #[cfg(feature = "render")] if let Some(out_svg) = &cli.render { - render::render_to_svg(cli.nodes, &edges, out_svg, &mut rng); + let mut rng = rand::thread_rng(); + graph_render::render_to_svg(cli.nodes, &edges, out_svg, &mut rng); } let dir = PathBuf::from(&cli.dir); @@ -134,7 +142,6 @@ forward_port = {} } if cli.run { - let mut rng = rand::thread_rng(); let mut children = Vec::new(); for node in std::fs::read_dir(cli.dir).unwrap() { match node { @@ -151,31 +158,34 @@ forward_port = {} } } } + std::thread::sleep(std::time::Duration::from_secs(4)); - let mut socket = UnixStream::connect_addr(&SocketAddr::from_abstract_name(b"rns/n0").unwrap()).unwrap(); - let mut socket2 = UnixStream::connect_addr(&SocketAddr::from_abstract_name(b"rns/n1").unwrap()).unwrap(); + traffic_generator::generate_traffic(cli.nodes); + + /*let mut socket = UnixStream::connect_addr(&SocketAddr::from_abstract_name(b"rns/n1").unwrap()).unwrap(); + let mut socket2 = UnixStream::connect_addr(&SocketAddr::from_abstract_name(b"rns/n2").unwrap()).unwrap(); let (identity, secret, sk) = reticulum::identity::Identity::generate(&mut rng); let keys = FixedKeys::new(secret, sk); let dest = reticulum::destination::Destination::single_in(&identity, "synthesis", "idontknow"); - let announce = dest.announce_rnd(&mut rng, None, &keys); + let announce = dest.announce_rnd(&mut rng, Some(b"hello"), &keys); let mut announce_buf = Vec::new(); - announce.encode(&mut announce_buf); + announce_buf.push(b'~'); let packet = Packet::::from_announce(announce); - dbg!(&packet); + //dbg!(&packet); packet.encode(&mut announce_buf); - dbg!(&announce_buf); + announce_buf.push(b'~'); + //dbg!(&announce_buf); socket.write_all(&announce_buf).unwrap(); - let dest_out = reticulum::destination::Destination::plain_out("synthesis", "idonknow"); + socket.flush().unwrap(); + let dest_out = reticulum::destination::Destination::plain_out("synthesis", "idontknow"); let req = reticulum::path_request::PathRequest::new(dest.hash(), &dest_out, None, None); let mut req_buf = Vec::new(); + req_buf.push(b'~'); Packet::::from_path_request(req).encode(&mut req_buf); + req_buf.push(b'~'); std::thread::sleep(std::time::Duration::from_secs(4)); - socket2.write_all(&req_buf).unwrap(); - /*loop { - let mut buf = Vec::new(); - dbg!(socket2.re(&mut buf)).ok(); - dbg!(buf); - }*/ + socket2.write_all(&req_buf).unwrap();*/ + for mut child in children { child.wait().ok(); } diff --git a/src/traffic_generator.rs b/src/traffic_generator.rs new file mode 100644 index 0000000..3990ccc --- /dev/null +++ b/src/traffic_generator.rs @@ -0,0 +1,56 @@ +use reticulum::{ + TestInf, destination::Destination, encode::Encode, identity::Identity, packet::Packet, + sign::FixedKeys, +}; +use std::{ + io::Write, + os::{ + linux::net::SocketAddrExt, + unix::net::{SocketAddr, UnixStream}, + }, +}; + +pub fn generate_traffic(nodes: usize) { + let mut rng = rand::thread_rng(); + + let mut sockets: Vec<_> = (0..nodes) + .map(|i| { + UnixStream::connect_addr( + &SocketAddr::from_abstract_name(format!("rns/n{i}").as_bytes()).unwrap(), + ) + .unwrap() + }) + .collect(); + + let identities: Vec<_> = (0..nodes) + .map(|_i| { + let (identity, secret, sk) = Identity::generate(&mut rng); + (identity, FixedKeys::new(secret, sk)) + }) + .collect(); + + let destinations: Vec<_> = identities + .iter() + .map(|(identity, keys)| { + ( + Destination::single_in(&identity, "synthesis", "idontknow"), + keys, + ) + }) + .collect(); + + for (((destination, keys), _identity), socket) in destinations + .iter() + .zip(identities.iter()) + .zip(sockets.iter_mut()) + { + let announce = destination.announce_rnd(&mut rng, Some(b"hello"), *keys); + let mut announce_buf = Vec::new(); + announce_buf.push(b'~'); + let packet = Packet::::from_announce(announce); + packet.encode(&mut announce_buf); + announce_buf.push(b'~'); + socket.write_all(&announce_buf).unwrap(); + socket.flush().unwrap(); + } +} diff --git a/src/udp.rs b/src/udp.rs deleted file mode 100644 index a062a84..0000000 --- a/src/udp.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub struct UdpInterface { - -} \ No newline at end of file