scatter_net/legacy/peer/methods/
select_peer_group.rs1use std::time::Duration;
2
3use n0_future::StreamExt;
4use tokio::time::sleep;
5
6use crate::{ErrorCode, Peer, PeerGroup, Terminate};
7
8impl Peer {
9 pub async fn select_peer_group(self) -> Result<PeerGroup, PeerSelectPeerGroupError> {
11 sleep(Duration::from_secs(1)).await;
12
13 let mut interaction = self.clone().begin_interaction().await?;
14 let time_start = chrono::Local::now();
15
16 interaction.send_packet(crate::Packet::Ping).await?;
17
18 let pong = interaction.next().await;
19 let time_end = chrono::Local::now();
20
21 if !matches!(pong, Some(Ok(crate::Packet::Pong))) {
22 self.terminate(
23 ErrorCode::PingPongFailed as u8,
24 &"Failed to play ping pong.",
25 );
26
27 eprintln!("Failed to play ping pong with {self}, received {pong:?}.");
28
29 return Err(PeerSelectPeerGroupError::PingPongFailed);
30 }
31
32 let rtt = (time_end - time_start).num_milliseconds().unsigned_abs();
33
34 let mut peer_group: Option<crate::PeerGroup> = None;
35
36 for g in self.net().get_peer_groups() {
37 if g.has_peer(&self) {
38 return Ok(g);
40 }
41
42 if !g.is_open() || rtt > g.get_rtt_cap_ms() {
43 continue;
45 }
46
47 if let Some(og) = peer_group {
48 if g.get_rtt_cap_ms() < og.get_rtt_cap_ms() {
49 peer_group = Some(g);
50 } else {
51 peer_group = Some(og);
52 }
53 } else {
54 peer_group = Some(g);
55 }
56 }
57
58 let node_id = self.node_id();
59
60 peer_group.map_or_else(
61 || {
62 eprintln!("Could not find a suitable PeerGroup for {node_id}");
63
64 Err(PeerSelectPeerGroupError::NoSuitablePeerGroup)
65 },
66 |peer_group| {
67 eprintln!("Peer {node_id} inserted into {peer_group}.");
68
69 peer_group.insert_peer(self);
70
71 Ok(peer_group)
72 },
73 )
74 }
75}
76
77#[derive(thiserror::Error, Debug)]
78pub enum PeerSelectPeerGroupError {
79 #[error(transparent)]
80 InteractionSendPacket(#[from] crate::InteractionSendPacketError),
81 #[error("Could not find a suitable PeerGroup.")]
82 NoSuitablePeerGroup,
83 #[error(transparent)]
84 PeerBeginInteraction(#[from] crate::PeerBeginInteractionError),
85 #[error("Peer did not respond to Packet::Ping with Packet::Pong.")]
86 PingPongFailed,
87}