//! Datagram transport example (equivalent to example4.cpp). //! //! Creates two nodes and sends datagrams between them //! using the dgram callback API. //! //! Usage: //! cargo run --example dgram use std::sync::{Arc, Mutex}; use std::time::Duration; use tesseras_dht::Node; use tesseras_dht::id::NodeId; use tesseras_dht::nat::NatState; 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(); let mut node1 = Node::bind(0).expect("bind node1"); node1.set_nat_state(NatState::Global); let addr1 = node1.local_addr().unwrap(); let id1 = *node1.id(); let mut node2 = Node::bind(0).expect("bind node2"); node2.set_nat_state(NatState::Global); let addr2 = node2.local_addr().unwrap(); let id2 = *node2.id(); println!("Node 1: {} @ {addr1}", node1.id_hex()); println!("Node 2: {} @ {addr2}", node2.id_hex()); // Join node2 to node1 node2.join("127.0.0.1", addr1.port()).expect("join"); // Poll to establish routing for _ in 0..10 { node1.poll().ok(); node2.poll().ok(); std::thread::sleep(Duration::from_millis(50)); } // Set up dgram callbacks let received1: Arc>> = Arc::new(Mutex::new(Vec::new())); let received2: Arc>> = Arc::new(Mutex::new(Vec::new())); let r1 = received1.clone(); node1.set_dgram_callback(move |data: &[u8], from: &NodeId| { let msg = String::from_utf8_lossy(data).to_string(); println!("Node 1 received: '{msg}' from {from:?}"); r1.lock().unwrap().push(msg); }); let r2 = received2.clone(); node2.set_dgram_callback(move |data: &[u8], from: &NodeId| { let msg = String::from_utf8_lossy(data).to_string(); println!("Node 2 received: '{msg}' from {from:?}"); r2.lock().unwrap().push(msg); }); // Send datagrams println!("\n--- Sending datagrams ---"); node1.send_dgram(b"hello from node1", &id2); node2.send_dgram(b"hello from node2", &id1); // Poll to deliver for _ in 0..10 { node1.poll().ok(); node2.poll().ok(); std::thread::sleep(Duration::from_millis(50)); } // Note: actual dgram delivery requires the full // send queue → address resolution → send flow. // This example demonstrates the API; full delivery // is wired in integration. println!("\n--- Summary ---"); println!( "Node 1 received {} messages", received1.lock().unwrap().len() ); println!( "Node 2 received {} messages", received2.lock().unwrap().len() ); println!("Node 1 send queue pending: queued for delivery"); println!("Node 2 send queue pending: queued for delivery"); }