diff options
| author | murilo ijanc | 2026-03-24 15:04:03 -0300 |
|---|---|---|
| committer | murilo ijanc | 2026-03-24 15:04:03 -0300 |
| commit | 9821aabf0b50d2487b07502d3d2cd89e7d62bdbe (patch) | |
| tree | 53da095ff90cc755bac3d4bf699172b5e8cd07d6 /examples/network.rs | |
| download | tesseras-dht-e908bc01403f4b8ef2a65fa6be43716fd1c6e003.tar.gz | |
Initial commitv0.1.0
NAT-aware Kademlia DHT library for peer-to-peer networks.
Features:
- Distributed key-value storage (iterative FIND_NODE, FIND_VALUE, STORE)
- NAT traversal via DTUN hole-punching and proxy relay
- Reliable Datagram Protocol (RDP) with 7-state connection machine
- Datagram transport with automatic fragmentation/reassembly
- Ed25519 packet authentication
- 256-bit node IDs (Ed25519 public keys)
- Rate limiting, ban list, and eclipse attack mitigation
- Persistence and metrics
- OpenBSD and Linux support
Diffstat (limited to 'examples/network.rs')
| -rw-r--r-- | examples/network.rs | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/examples/network.rs b/examples/network.rs new file mode 100644 index 0000000..be3e0ef --- /dev/null +++ b/examples/network.rs @@ -0,0 +1,86 @@ +//! Multi-node network example (equivalent to example2.cpp). +//! +//! Creates N nodes on localhost, joins them recursively +//! via the first node, then prints state periodically. +//! +//! Usage: +//! cargo run --example network +//! RUST_LOG=debug cargo run --example network + +use std::time::{Duration, Instant}; +use tesseras_dht::Node; +use tesseras_dht::nat::NatState; + +const NUM_NODES: usize = 20; +const POLL_ROUNDS: usize = 30; + +fn main() { + env_logger::Builder::from_env( + env_logger::Env::default().default_filter_or("info"), + ) + .format(|buf, record| { + use std::io::Write; + writeln!( + buf, + "{} [{}] {}", + record.level(), + record.target(), + record.args() + ) + }) + .init(); + + println!("Creating {NUM_NODES} nodes..."); + let start = Instant::now(); + + // Create bootstrap node + let mut nodes: Vec<Node> = Vec::new(); + let bootstrap = Node::bind(0).expect("bind bootstrap"); + let bootstrap_port = bootstrap.local_addr().unwrap().port(); + println!("Bootstrap: {} @ port {bootstrap_port}", bootstrap.id_hex()); + nodes.push(bootstrap); + + // Create and join remaining nodes + for i in 1..NUM_NODES { + let mut node = Node::bind(0).expect("bind node"); + node.set_nat_state(NatState::Global); + node.join("127.0.0.1", bootstrap_port).expect("join"); + println!("Node {i}: {} joined", &node.id_hex()[..8]); + nodes.push(node); + } + nodes[0].set_nat_state(NatState::Global); + + println!("\nAll {NUM_NODES} nodes created in {:?}", start.elapsed()); + + // Poll all nodes to exchange messages + println!("\nPolling {POLL_ROUNDS} rounds..."); + for round in 0..POLL_ROUNDS { + for node in nodes.iter_mut() { + node.poll().ok(); + } + std::thread::sleep(Duration::from_millis(50)); + + if (round + 1) % 10 == 0 { + let sizes: Vec<usize> = + nodes.iter().map(|n| n.routing_table_size()).collect(); + let avg = sizes.iter().sum::<usize>() / sizes.len(); + let max = sizes.iter().max().unwrap(); + println!( + " Round {}: avg routing table = {avg}, max = {max}", + round + 1 + ); + } + } + + // Print final state + println!("\n--- Final state ---"); + for (i, node) in nodes.iter().enumerate() { + println!( + "Node {i}: {} | rt={} peers={} storage={}", + &node.id_hex()[..8], + node.routing_table_size(), + node.peer_count(), + node.storage_count(), + ); + } +} |