Initial commit

This commit is contained in:
Pascal Engélibert 2025-10-11 11:36:42 +02:00
commit 0e85a3ddb1
7 changed files with 1263 additions and 0 deletions

137
src/main.rs Normal file
View file

@ -0,0 +1,137 @@
use std::{
collections::{HashMap, hash_map::Entry},
io::Write,
path::PathBuf,
};
/// Generate configuration for local Reticulum networks
#[derive(argp::FromArgs)]
struct Cli {
/// Directory of Reticulum configs
#[argp(option, short = 'd', default = "String::from(\"/tmp/\")")]
dir: String,
/// Generate graph and create Reticulum configs
#[argp(switch, short = 'g', long = "gen")]
generate: bool,
/// Number of nodes
#[argp(option, short = 'n', default = "5")]
nodes: usize,
/// Probability of edge
#[argp(option, short = 'p', default = "0.5")]
proba: f32,
/// Start the Reticulum nodes
#[argp(switch, short = 'r')]
run: bool,
}
fn main() {
let cli: Cli = argp::parse_args_or_exit(argp::DEFAULT);
if cli.generate {
let graph = graphrs::generators::random::fast_gnp_random_graph(
cli.nodes as _,
cli.proba as _,
false,
None,
)
.unwrap();
let mut ports = HashMap::new();
let mut port: u16 = 42000;
assert!(graph.number_of_edges() < 65535 - port as usize);
let dir = PathBuf::from(&cli.dir);
std::fs::DirBuilder::new()
.recursive(true)
.create(&dir)
.unwrap();
for node in 0..cli.nodes {
let node_dir = dir.join(format!("n{node}"));
std::fs::DirBuilder::new()
.recursive(true)
.create(&node_dir)
.unwrap();
let mut config = std::fs::OpenOptions::new()
.write(true)
.truncate(true)
.create(true)
.open(node_dir.join("config"))
.unwrap();
config
.write_all(
format!(
"[reticulum]
enable_transport = true
share_instance = true
instance_name = n{node}
panic_on_interface_error = true
[logging]
loglevel = 4
[interfaces]
"
)
.as_bytes(),
)
.unwrap();
for edge in graph.get_edges_for_node(node as _).unwrap() {
let key = if edge.u < edge.v {
(edge.u, edge.v)
} else {
(edge.v, edge.u)
};
let mut edge_ports = (port, port + 1);
match ports.entry(key) {
Entry::Vacant(entry) => {
entry.insert((port + 1, port));
port += 2;
}
Entry::Occupied(entry) => {
edge_ports = *entry.get();
}
}
config
.write_all(
format!(
"[[e{}_{}]]
type = UDPInterface
enabled = true
listen_ip = 127.0.0.1
listen_port = {}
forward_ip = 127.0.0.1
forward_port = {}
",
edge.u, edge.v, edge_ports.0, edge_ports.1
)
.as_bytes(),
)
.unwrap();
}
config.flush().unwrap();
}
}
if cli.run {
let mut children = Vec::new();
for node in std::fs::read_dir(cli.dir).unwrap() {
match node {
Err(e) => eprintln!("Error opening directory: {e:?}"),
Ok(node) => {
match std::process::Command::new("rnsd")
.arg("--config")
.arg(node.path())
.spawn()
{
Err(e) => eprintln!("Error starting node `{:?}`: {:?}", node.path(), e),
Ok(handle) => children.push(handle),
}
}
}
}
for mut child in children {
child.wait().ok();
}
}
}