aboutsummaryrefslogtreecommitdiffstats
path: root/examples/rdp.rs
diff options
context:
space:
mode:
authormurilo ijanc2026-03-24 15:04:03 -0300
committermurilo ijanc2026-03-24 15:04:03 -0300
commit9821aabf0b50d2487b07502d3d2cd89e7d62bdbe (patch)
tree53da095ff90cc755bac3d4bf699172b5e8cd07d6 /examples/rdp.rs
downloadtesseras-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/rdp.rs')
-rw-r--r--examples/rdp.rs147
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}");
+}