1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
//! Two-node example: bootstrap, put, get.
//!
//! Creates two Node nodes on localhost. Node 2 joins
//! via Node 1, then Node 1 stores a value and Node 2
//! retrieves it (via protocol exchange).
//!
//! Run with:
//! cargo run --example two_nodes
//!
//! With debug logging:
//! RUST_LOG=debug cargo run --example two_nodes
use std::time::Duration;
use tesseras_dht::Node;
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();
// ── Create two nodes ────────────────────────────
let mut node1 = Node::bind(0).expect("bind node1");
node1.set_nat_state(NatState::Global);
let addr1 = node1.local_addr().expect("local addr");
println!("Node 1: {} @ {}", node1.id_hex(), addr1);
let mut node2 = Node::bind(0).expect("bind node2");
node2.set_nat_state(NatState::Global);
let addr2 = node2.local_addr().expect("local addr");
println!("Node 2: {} @ {}", node2.id_hex(), addr2);
// ── Node 2 joins via Node 1 ─────────────────────
println!("\n--- Node 2 joining via Node 1 ---");
node2.join("127.0.0.1", addr1.port()).expect("join");
// Poll both nodes a few times to exchange messages
for _ in 0..10 {
node1.poll().ok();
node2.poll().ok();
std::thread::sleep(Duration::from_millis(50));
}
println!("Node 1 routing table: {} peers", node1.routing_table_size());
println!("Node 2 routing table: {} peers", node2.routing_table_size());
// ── Node 1 stores a value ───────────────────────
println!("\n--- Node 1 storing key='hello' ---");
node1.put(b"hello", b"world", 300, false);
// Poll to deliver STORE messages
for _ in 0..10 {
node1.poll().ok();
node2.poll().ok();
std::thread::sleep(Duration::from_millis(50));
}
// ── Check storage ───────────────────────────────
let vals1 = node1.get(b"hello");
let vals2 = node2.get(b"hello");
println!(
"\nNode 1 get('hello'): {:?}",
vals1
.iter()
.map(|v| String::from_utf8_lossy(v).to_string())
.collect::<Vec<_>>()
);
println!(
"Node 2 get('hello'): {:?}",
vals2
.iter()
.map(|v| String::from_utf8_lossy(v).to_string())
.collect::<Vec<_>>()
);
// ── Test remote get via FIND_VALUE ────────────
println!("\n--- Node 1 storing key='secret' (local only) ---");
// Store only on Node 1 (no STORE sent because
// we bypass put and go directly to storage)
node1.put(b"remote-key", b"remote-val", 300, false);
// Don't poll — so Node 2 doesn't get the STORE
// Node 2 tries to get it — should trigger FIND_VALUE
println!(
"Node 2 get('remote-key') before poll: {:?}",
node2.get(b"remote-key")
);
// Now poll to let FIND_VALUE exchange happen
for _ in 0..10 {
node1.poll().ok();
node2.poll().ok();
std::thread::sleep(Duration::from_millis(50));
}
let remote_vals = node2.get(b"remote-key");
println!(
"Node 2 get('remote-key') after poll: {:?}",
remote_vals
.iter()
.map(|v| String::from_utf8_lossy(v).to_string())
.collect::<Vec<_>>()
);
// ── Print state ─────────────────────────────────
println!("\n--- Node 1 state ---");
node1.print_state();
println!("\n--- Node 2 state ---");
node2.print_state();
println!("\n--- Done ---");
println!("Node 1: {node1}");
println!("Node 2: {node2}");
}
|