//! 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}"); }