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/main.rs b/src/main.rs index 8a097f1..668c738 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,10 +1,11 @@ mod generator; +mod reader; mod render; use std::{ collections::{HashMap, hash_map::Entry}, io::Write, - path::PathBuf, + path::{Path, PathBuf}, }; /// Generate configuration for local Reticulum networks @@ -16,6 +17,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, @@ -35,13 +39,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 { + 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." + ); + generator::generate(cli.nodes, cli.proba, &mut rng) + }; let mut ports = HashMap::new(); let mut port: u16 = 42000; @@ -49,6 +57,7 @@ fn main() { #[cfg(feature = "render")] if let Some(out_svg) = &cli.render { + let mut rng = rand::thread_rng(); render::render_to_svg(cli.nodes, &edges, out_svg, &mut rng); } diff --git a/src/reader.rs b/src/reader.rs new file mode 100644 index 0000000..8d2ebba --- /dev/null +++ b/src/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 +}