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/rdp.rs | |
| download | tesseras-dht-9821aabf0b50d2487b07502d3d2cd89e7d62bdbe.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/rdp.rs')
| -rw-r--r-- | examples/rdp.rs | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/examples/rdp.rs b/examples/rdp.rs new file mode 100644 index 0000000..319c779 --- /dev/null +++ b/examples/rdp.rs @@ -0,0 +1,147 @@ +//! RDP reliable transport example (equivalent to example5.cpp). +//! +//! Two nodes: server listens, client connects, sends +//! data, server receives it. +//! +//! Usage: +//! cargo run --example rdp + +use std::time::Duration; +use tesseras_dht::Node; +use tesseras_dht::nat::NatState; +use tesseras_dht::rdp::RdpState; + +const RDP_PORT: u16 = 5000; + +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(); + + // Create two nodes + let mut server = Node::bind(0).expect("bind server"); + server.set_nat_state(NatState::Global); + let server_addr = server.local_addr().unwrap(); + let server_id = *server.id(); + println!("Server: {} @ {server_addr}", server.id_hex()); + + let mut client = Node::bind(0).expect("bind client"); + client.set_nat_state(NatState::Global); + println!("Client: {}", client.id_hex()); + + // Client joins server so they know each other + client.join("127.0.0.1", server_addr.port()).expect("join"); + + // Poll to exchange routing info + for _ in 0..10 { + server.poll().ok(); + client.poll().ok(); + std::thread::sleep(Duration::from_millis(20)); + } + println!("Client knows {} peers", client.routing_table_size()); + + // Server listens on RDP port + let _listen = server.rdp_listen(RDP_PORT).expect("listen"); + println!("Server listening on RDP port {RDP_PORT}"); + + // Client connects + let desc = client + .rdp_connect(0, &server_id, RDP_PORT) + .expect("connect"); + println!("Client state: {:?}", client.rdp_state(desc).unwrap()); + + // Poll to complete handshake + for _ in 0..10 { + server.poll().ok(); + client.poll().ok(); + std::thread::sleep(Duration::from_millis(20)); + } + + println!( + "Client state after handshake: {:?}", + client.rdp_state(desc).unwrap_or(RdpState::Closed) + ); + + // Send data if connection is open + match client.rdp_state(desc) { + Ok(RdpState::Open) => { + for i in 0..3u16 { + let msg = format!("hello {i}"); + match client.rdp_send(desc, msg.as_bytes()) { + Ok(n) => println!("Sent: '{msg}' ({n} bytes)"), + Err(e) => println!("Send error: {e}"), + } + } + + // Poll to deliver + for _ in 0..10 { + server.poll().ok(); + client.poll().ok(); + std::thread::sleep(Duration::from_millis(20)); + } + + // Server reads received data + println!("\n--- Server reading ---"); + let server_status = server.rdp_status(); + for s in &server_status { + if s.state == RdpState::Open { + let mut buf = [0u8; 256]; + loop { + match server.rdp_recv(s.sport as i32 + 1, &mut buf) { + Ok(0) => break, + Ok(n) => { + let msg = String::from_utf8_lossy(&buf[..n]); + println!("Server received: '{msg}'"); + } + Err(_) => break, + } + } + } + } + // Try reading from desc 2 (server-side accepted desc) + let mut buf = [0u8; 256]; + for attempt_desc in 1..=5 { + loop { + match server.rdp_recv(attempt_desc, &mut buf) { + Ok(0) => break, + Ok(n) => { + let msg = String::from_utf8_lossy(&buf[..n]); + println!("Server desc={attempt_desc}: '{msg}'"); + } + Err(_) => break, + } + } + } + } + Ok(state) => { + println!("Connection not open: {state:?}"); + } + Err(e) => { + println!("Descriptor error: {e}"); + } + } + + // Show status + println!("\n--- RDP Status ---"); + for s in &client.rdp_status() { + println!(" state={:?} dport={} sport={}", s.state, s.dport, s.sport); + } + + // Cleanup + client.rdp_close(desc); + + println!("\n--- Done ---"); + println!("Server: {server}"); + println!("Client: {client}"); +} |