aboutsummaryrefslogtreecommitdiffstats
path: root/examples/dgram.rs
diff options
context:
space:
mode:
Diffstat (limited to 'examples/dgram.rs')
-rw-r--r--examples/dgram.rs100
1 files changed, 100 insertions, 0 deletions
diff --git a/examples/dgram.rs b/examples/dgram.rs
new file mode 100644
index 0000000..ab25e78
--- /dev/null
+++ b/examples/dgram.rs
@@ -0,0 +1,100 @@
+//! 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<Mutex<Vec<String>>> = Arc::new(Mutex::new(Vec::new()));
+ let received2: Arc<Mutex<Vec<String>>> = 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");
+}