1use async_trait::async_trait;
2
3use crate::dht::types::Chord;
4use crate::dht::types::CorrectChord;
5use crate::dht::PeerRingAction;
6use crate::dht::TopoInfo;
7use crate::error::Error;
8use crate::error::Result;
9use crate::message::effects::PayloadRelayFunctor;
10use crate::message::types::ConnectNodeReport;
11use crate::message::types::ConnectNodeSend;
12use crate::message::types::FindSuccessorReport;
13use crate::message::types::FindSuccessorSend;
14use crate::message::types::Message;
15use crate::message::types::QueryForTopoInfoReport;
16use crate::message::types::QueryForTopoInfoSend;
17use crate::message::types::Then;
18use crate::message::FindSuccessorReportHandler;
19use crate::message::FindSuccessorThen;
20use crate::message::HandleMsg;
21use crate::message::MessageHandler;
22use crate::message::MessagePayload;
23
24#[cfg_attr(feature = "wasm", async_trait(?Send))]
26#[cfg_attr(not(feature = "wasm"), async_trait)]
27impl HandleMsg<QueryForTopoInfoSend> for MessageHandler {
28 async fn handle(&self, ctx: &MessagePayload, msg: &QueryForTopoInfoSend) -> Result<()> {
29 let info: TopoInfo = TopoInfo::try_from(self.dht.as_ref())?;
30 if msg.targets(self.dht.did) {
31 self.run_effects([PayloadRelayFunctor::send_report_message(
32 ctx,
33 Message::QueryForTopoInfoReport(msg.resp(info)),
34 )
35 .into()])
36 .await?
37 }
38 Ok(())
39 }
40}
41
42#[cfg_attr(feature = "wasm", async_trait(?Send))]
44#[cfg_attr(not(feature = "wasm"), async_trait)]
45impl HandleMsg<QueryForTopoInfoReport> for MessageHandler {
46 async fn handle(&self, _ctx: &MessagePayload, msg: &QueryForTopoInfoReport) -> Result<()> {
47 match msg.then {
48 <QueryForTopoInfoReport as Then>::Then::SyncSuccessor => {
49 for peer in msg.info.successors.iter() {
50 if self.transport.get_connection(*peer).is_some() {
51 self.join_dht(*peer).await?;
52 }
53 }
54 }
55 <QueryForTopoInfoReport as Then>::Then::Stabilization => {
56 let candidates = msg
59 .info
60 .predecessor
61 .into_iter()
62 .chain(msg.info.successors.iter().copied());
63 self.connect_dht_peers(candidates).await?;
64 let ev = self.dht.stabilize(msg.info.clone())?;
65 self.handle_dht_events(&ev).await?;
66 }
67 }
68 Ok(())
69 }
70}
71
72#[cfg_attr(feature = "wasm", async_trait(?Send))]
73#[cfg_attr(not(feature = "wasm"), async_trait)]
74impl HandleMsg<ConnectNodeSend> for MessageHandler {
75 async fn handle(&self, ctx: &MessagePayload, msg: &ConnectNodeSend) -> Result<()> {
76 if msg.network_id != self.transport.network_id {
77 return Ok(());
78 }
79
80 if ctx.should_forward_from(self.dht.did) {
81 self.run_effects([PayloadRelayFunctor::forward_payload(ctx, None).into()])
82 .await
83 } else {
84 let answer = self
85 .transport
86 .answer_remote_connection(
87 ctx.relay.try_origin_sender()?,
88 self.inner_callback(),
89 msg,
90 )
91 .await?;
92 self.run_effects([PayloadRelayFunctor::send_report_message(
93 ctx,
94 Message::ConnectNodeReport(answer),
95 )
96 .into()])
97 .await
98 }
99 }
100}
101
102#[cfg_attr(feature = "wasm", async_trait(?Send))]
103#[cfg_attr(not(feature = "wasm"), async_trait)]
104impl HandleMsg<ConnectNodeReport> for MessageHandler {
105 async fn handle(&self, ctx: &MessagePayload, msg: &ConnectNodeReport) -> Result<()> {
106 if ctx.should_forward_from(self.dht.did) {
107 self.run_effects([PayloadRelayFunctor::forward_payload(ctx, None).into()])
108 .await
109 } else {
110 self.transport
111 .accept_remote_connection(ctx.relay.try_origin_sender()?, msg)
112 .await
113 }
114 }
115}
116
117#[cfg_attr(feature = "wasm", async_trait(?Send))]
118#[cfg_attr(not(feature = "wasm"), async_trait)]
119impl HandleMsg<FindSuccessorSend> for MessageHandler {
120 async fn handle(&self, ctx: &MessagePayload, msg: &FindSuccessorSend) -> Result<()> {
121 match self.dht.find_successor(msg.did)? {
122 PeerRingAction::Some(did) => {
123 if msg.accepts_local_successor(self.dht.did) {
124 match &msg.then {
125 FindSuccessorThen::Report(handler) => {
126 self.run_effects([PayloadRelayFunctor::send_report_message(
127 ctx,
128 Message::FindSuccessorReport(FindSuccessorReport {
129 did,
130 handler: handler.clone(),
131 }),
132 )
133 .into()])
134 .await
135 }
136 }
137 } else {
138 self.run_effects([PayloadRelayFunctor::forward_payload(ctx, Some(did)).into()])
139 .await
140 }
141 }
142 PeerRingAction::RemoteAction(next, _) => {
143 self.run_effects([PayloadRelayFunctor::reset_destination(ctx, next).into()])
144 .await
145 }
146 act => Err(Error::unexpected_peer_ring_action(act)),
147 }
148 }
149}
150
151#[cfg_attr(feature = "wasm", async_trait(?Send))]
152#[cfg_attr(not(feature = "wasm"), async_trait)]
153impl HandleMsg<FindSuccessorReport> for MessageHandler {
154 async fn handle(&self, ctx: &MessagePayload, msg: &FindSuccessorReport) -> Result<()> {
155 if ctx.should_forward_from(self.dht.did) {
156 return self
157 .run_effects([PayloadRelayFunctor::forward_payload(ctx, None).into()])
158 .await;
159 }
160
161 match &msg.handler {
162 FindSuccessorReportHandler::FixFingerTable { index } => {
163 self.dht.apply_fixed_finger(*index, msg.did)?;
164 if msg.reports_remote_successor(self.dht.did) {
165 self.connect_dht_peer(msg.did).await?;
166 }
167 }
168 FindSuccessorReportHandler::Connect => {
169 if msg.reports_remote_successor(self.dht.did) {
170 self.connect_dht_peer(msg.did).await?;
171 }
172 }
173 _ => {}
174 }
175
176 Ok(())
177 }
178}
179
180#[cfg(not(feature = "wasm"))]
181#[cfg(test)]
182pub mod tests {
183 use tokio::time::sleep;
185 use tokio::time::Duration;
186
187 use super::*;
188 use crate::dht::successor::SuccessorReader;
189 use crate::ecc::tests::gen_ordered_keys;
190 use crate::ecc::SecretKey;
191 use crate::tests::default::assert_no_more_msg;
192 use crate::tests::default::prepare_node;
193 use crate::tests::default::wait_for_msgs;
194 use crate::tests::default::Node;
195 use crate::tests::manually_establish_connection;
196
197 #[tokio::test]
239 async fn test_triple_nodes_connection_1_2_3() -> Result<()> {
240 let keys = gen_ordered_keys(3);
241 let (key1, key2, key3) = (keys[0], keys[1], keys[2]);
242 test_triple_ordered_nodes_connection(key1, key2, key3).await?;
243 Ok(())
244 }
245
246 #[tokio::test]
248 async fn test_triple_nodes_connection_2_3_1() -> Result<()> {
249 let keys = gen_ordered_keys(3);
250 let (key1, key2, key3) = (keys[0], keys[1], keys[2]);
251 test_triple_ordered_nodes_connection(key2, key3, key1).await?;
252 Ok(())
253 }
254
255 #[tokio::test]
257 async fn test_triple_nodes_connection_3_1_2() -> Result<()> {
258 let keys = gen_ordered_keys(3);
259 let (key1, key2, key3) = (keys[0], keys[1], keys[2]);
260 test_triple_ordered_nodes_connection(key3, key1, key2).await?;
261 Ok(())
262 }
263
264 #[tokio::test]
284 async fn test_triple_nodes_connection_3_2_1() -> Result<()> {
285 let keys = gen_ordered_keys(3);
286 let (key1, key2, key3) = (keys[0], keys[1], keys[2]);
287 test_triple_desc_ordered_nodes_connection(key3, key2, key1).await?;
288 Ok(())
289 }
290
291 #[tokio::test]
293 async fn test_triple_nodes_connection_2_1_3() -> Result<()> {
294 let keys = gen_ordered_keys(3);
295 let (key1, key2, key3) = (keys[0], keys[1], keys[2]);
296 test_triple_desc_ordered_nodes_connection(key2, key1, key3).await?;
297 Ok(())
298 }
299
300 #[tokio::test]
302 async fn test_triple_nodes_connection_1_3_2() -> Result<()> {
303 let keys = gen_ordered_keys(3);
304 let (key1, key2, key3) = (keys[0], keys[1], keys[2]);
305 test_triple_desc_ordered_nodes_connection(key1, key3, key2).await?;
306 Ok(())
307 }
308
309 async fn test_triple_ordered_nodes_connection(
310 key1: SecretKey,
311 key2: SecretKey,
312 key3: SecretKey,
313 ) -> Result<(Node, Node, Node)> {
314 let node1 = prepare_node(key1).await;
315 let node2 = prepare_node(key2).await;
316 let node3 = prepare_node(key3).await;
317
318 println!("========================================");
319 println!("|| now we connect node1 and node2 ||");
320 println!("========================================");
321
322 manually_establish_connection(&node1.swarm, &node2.swarm).await;
323 wait_for_msgs([&node1, &node2, &node3]).await;
324 assert_no_more_msg([&node1, &node2, &node3]).await;
325
326 node1.assert_transports(vec![node2.did()]);
327 node2.assert_transports(vec![node1.did()]);
328 node3.assert_transports(vec![]);
329 assert_eq!(node1.dht().successors().list()?, vec![node2.did()]);
330 assert_eq!(node2.dht().successors().list()?, vec![node1.did()]);
331 assert_eq!(node3.dht().successors().list()?, vec![]);
332
333 println!("========================================");
334 println!("|| now we start join node3 to node2 ||");
335 println!("========================================");
336
337 manually_establish_connection(&node3.swarm, &node2.swarm).await;
338 wait_for_msgs([&node1, &node2, &node3]).await;
339 assert_no_more_msg([&node1, &node2, &node3]).await;
340
341 println!("=== Check state before connect via DHT ===");
342 node1.assert_transports(vec![node2.did()]);
343 node2.assert_transports(vec![node1.did(), node3.did()]);
344 node3.assert_transports(vec![node2.did()]);
345 assert_eq!(node1.dht().successors().list()?, vec![node2.did(),]);
346 assert_eq!(node2.dht().successors().list()?, vec![
347 node3.did(),
348 node1.did()
349 ]);
350 assert_eq!(node3.dht().successors().list()?, vec![node2.did()]);
351
352 println!("=============================================");
353 println!("|| now we connect node1 to node3 via DHT ||");
354 println!("=============================================");
355
356 assert!(node1.swarm.transport.get_connection(node3.did()).is_none());
358 assert_eq!(node1.dht().successors().max()?, node2.did());
360
361 node1.swarm.connect(node3.did()).await?;
362 wait_for_msgs([&node1, &node2, &node3]).await;
363 assert_no_more_msg([&node1, &node2, &node3]).await;
364
365 println!("=== Check state after connect via DHT ===");
366 node1.assert_transports(vec![node2.did(), node3.did()]);
367 node2.assert_transports(vec![node1.did(), node3.did()]);
368 node3.assert_transports(vec![node1.did(), node2.did()]);
369 assert_eq!(node1.dht().successors().list()?, vec![
370 node2.did(),
371 node3.did()
372 ]);
373 assert_eq!(node2.dht().successors().list()?, vec![
374 node3.did(),
375 node1.did()
376 ]);
377 assert_eq!(node3.dht().successors().list()?, vec![
378 node1.did(),
379 node2.did()
380 ]);
381
382 Ok((node1, node2, node3))
383 }
384
385 async fn test_triple_desc_ordered_nodes_connection(
386 key1: SecretKey,
387 key2: SecretKey,
388 key3: SecretKey,
389 ) -> Result<(Node, Node, Node)> {
390 let node1 = prepare_node(key1).await;
391 let node2 = prepare_node(key2).await;
392 let node3 = prepare_node(key3).await;
393
394 println!("========================================");
395 println!("|| now we connect node1 and node2 ||");
396 println!("========================================");
397
398 manually_establish_connection(&node1.swarm, &node2.swarm).await;
399 wait_for_msgs([&node1, &node2, &node3]).await;
400 assert_no_more_msg([&node1, &node2, &node3]).await;
401
402 assert_eq!(node1.dht().successors().list()?, vec![node2.did()]);
403 assert_eq!(node2.dht().successors().list()?, vec![node1.did()]);
404 assert_eq!(node3.dht().successors().list()?, vec![]);
405
406 println!("========================================");
407 println!("|| now we start join node3 to node2 ||");
408 println!("========================================");
409
410 manually_establish_connection(&node3.swarm, &node2.swarm).await;
411 wait_for_msgs([&node1, &node2, &node3]).await;
412 assert_no_more_msg([&node1, &node2, &node3]).await;
413
414 println!("=== Check state before connect via DHT ===");
415 node1.assert_transports(vec![node2.did()]);
416 node2.assert_transports(vec![node1.did(), node3.did()]);
417 node3.assert_transports(vec![node2.did()]);
418 assert_eq!(node1.dht().successors().list()?, vec![node2.did()]);
419 assert_eq!(node2.dht().successors().list()?, vec![
420 node1.did(),
421 node3.did()
422 ]);
423 assert_eq!(node3.dht().successors().list()?, vec![node2.did()]);
424
425 println!("=============================================");
426 println!("|| now we connect node1 to node3 via DHT ||");
427 println!("=============================================");
428
429 assert!(node1.swarm.transport.get_connection(node3.did()).is_none());
431 assert_eq!(node1.dht().successors().max()?, node2.did());
433
434 node1.swarm.connect(node3.did()).await?;
435 wait_for_msgs([&node1, &node2, &node3]).await;
436 assert_no_more_msg([&node1, &node2, &node3]).await;
437
438 println!("=== Check state after connect via DHT ===");
439 node1.assert_transports(vec![node2.did(), node3.did()]);
440 node2.assert_transports(vec![node1.did(), node3.did()]);
441 node3.assert_transports(vec![node1.did(), node2.did()]);
442 assert_eq!(node1.dht().successors().list()?, vec![
443 node3.did(),
444 node2.did()
445 ]);
446 assert_eq!(node2.dht().successors().list()?, vec![
447 node1.did(),
448 node3.did()
449 ]);
450 assert_eq!(node3.dht().successors().list()?, vec![
451 node2.did(),
452 node1.did()
453 ]);
454
455 Ok((node1, node2, node3))
456 }
457
458 #[tokio::test]
459 async fn test_fourth_node_connection() -> Result<()> {
460 let keys = gen_ordered_keys(4);
461 let (key1, key2, key3, key4) = (keys[0], keys[1], keys[2], keys[3]);
462 let (node1, node2, node3) = test_triple_ordered_nodes_connection(key1, key2, key3).await?;
463 let node4 = prepare_node(key4).await;
468
469 manually_establish_connection(&node4.swarm, &node2.swarm).await;
478 wait_until("node4 joined: DHT successors converged", || {
482 Ok(
483 node1.dht().successors().list()? == vec![node2.did(), node3.did(), node4.did()]
484 && node2.dht().successors().list()?
485 == vec![node3.did(), node4.did(), node1.did()]
486 && node3.dht().successors().list()? == vec![node1.did(), node2.did()]
487 && node4.dht().successors().list()? == vec![node1.did(), node2.did()],
488 )
489 })
490 .await?;
491
492 println!("=== Check state before connect via DHT ===");
493 node1.assert_transports(vec![node2.did(), node3.did(), node4.did()]);
494 node2.assert_transports(vec![node3.did(), node4.did(), node1.did()]);
495 node3.assert_transports(vec![node1.did(), node2.did()]);
496 node4.assert_transports(vec![node1.did(), node2.did()]);
498 assert_eq!(node1.dht().successors().list()?, vec![
499 node2.did(),
500 node3.did(),
501 node4.did(),
502 ]);
503 assert_eq!(node2.dht().successors().list()?, vec![
504 node3.did(),
505 node4.did(),
506 node1.did(),
507 ]);
508 assert_eq!(node3.dht().successors().list()?, vec![
509 node1.did(),
510 node2.did(),
511 ]);
512 assert_eq!(node4.dht().successors().list()?, vec![
513 node1.did(),
514 node2.did(),
515 ]);
516
517 println!("========================================");
518 println!("| test node4 connect node3 via dht |");
519 println!("========================================");
520 println!(
521 "node1.did(): {:?}, node2.did(): {:?}, node3.did(): {:?}, node4.did(): {:?}",
522 node1.did(),
523 node2.did(),
524 node3.did(),
525 node4.did(),
526 );
527 println!("==================================================");
528
529 node4.swarm.connect(node3.did()).await?;
530 wait_until("node4 connected node3: DHT successors converged", || {
533 Ok(
534 node1.dht().successors().list()? == vec![node2.did(), node3.did(), node4.did()]
535 && node2.dht().successors().list()?
536 == vec![node3.did(), node4.did(), node1.did()]
537 && node3.dht().successors().list()?
538 == vec![node4.did(), node1.did(), node2.did()]
539 && node4.dht().successors().list()?
540 == vec![node1.did(), node2.did(), node3.did()],
541 )
542 })
543 .await?;
544
545 println!("=== Check state after connect via DHT ===");
546 node1.assert_transports(vec![node2.did(), node3.did(), node4.did()]);
547 node2.assert_transports(vec![node3.did(), node4.did(), node1.did()]);
548 node3.assert_transports(vec![node4.did(), node1.did(), node2.did()]);
549 node4.assert_transports(vec![node1.did(), node2.did(), node3.did()]);
550 assert_eq!(node1.dht().successors().list()?, vec![
551 node2.did(),
552 node3.did(),
553 node4.did()
554 ]);
555 assert_eq!(node2.dht().successors().list()?, vec![
556 node3.did(),
557 node4.did(),
558 node1.did(),
559 ]);
560 assert_eq!(node3.dht().successors().list()?, vec![
561 node4.did(),
562 node1.did(),
563 node2.did(),
564 ]);
565 assert_eq!(node4.dht().successors().list()?, vec![
566 node1.did(),
567 node2.did(),
568 node3.did(),
569 ]);
570
571 Ok(())
572 }
573
574 async fn wait_until(msg: &str, mut cond: impl FnMut() -> Result<bool>) -> Result<()> {
582 for _ in 0..300 {
583 if cond()? {
584 return Ok(());
585 }
586 sleep(Duration::from_millis(200)).await;
587 }
588 Err(Error::InvalidMessage(format!("timeout waiting for: {msg}")))
589 }
590
591 #[tokio::test]
592 async fn test_finger_when_disconnect() -> Result<()> {
593 let key1 = SecretKey::random();
594 let key2 = SecretKey::random();
595
596 let node1 = prepare_node(key1).await;
597 let node2 = prepare_node(key2).await;
598
599 {
600 assert!(node1.dht().lock_finger()?.is_empty());
601 assert!(node1.dht().lock_finger()?.is_empty());
602 }
603
604 manually_establish_connection(&node1.swarm, &node2.swarm).await;
605
606 wait_until("node1 and node2 to join each other's DHT", || {
610 let finger1 = node1.dht().lock_finger()?.clone().clone_finger();
611 let finger2 = node2.dht().lock_finger()?.clone().clone_finger();
612 Ok(finger1.into_iter().any(|x| x == Some(node2.did()))
613 && finger2.into_iter().any(|x| x == Some(node1.did())))
614 })
615 .await?;
616
617 node1.assert_transports(vec![node2.did()]);
618 node2.assert_transports(vec![node1.did()]);
619
620 println!("===================================");
621 println!("| test disconnect node1 and node2 |");
622 println!("===================================");
623 node1.swarm.disconnect(node2.did()).await?;
624
625 wait_until("both sides to drop the connection", || {
629 Ok(node1.swarm.transport.get_connection(node2.did()).is_none()
630 && node2.swarm.transport.get_connection(node1.did()).is_none())
631 })
632 .await?;
633
634 node1.assert_transports(vec![]);
635 node2.assert_transports(vec![]);
636 {
637 let finger1 = node1.dht().lock_finger()?.clone().clone_finger();
638 let finger2 = node2.dht().lock_finger()?.clone().clone_finger();
639 assert!(finger1.into_iter().all(|x| x.is_none()));
640 assert!(finger2.into_iter().all(|x| x.is_none()));
641 }
642
643 Ok(())
644 }
645}