/ src / node_map.rs
node_map.rs
 1  use std::collections::HashMap;
 2  use std::sync::Arc;
 3  
 4  use iroh::PublicKey;
 5  use rand::Rng;
 6  use serde::{Deserialize, Serialize};
 7  use tokio::sync::RwLock;
 8  
 9  #[derive(Debug, Clone, Serialize, Deserialize)]
10  pub struct NodeInfo {
11      pub name: String,
12      pub id: PublicKey,
13  }
14  
15  #[derive(Clone)]
16  pub struct NodeMap {
17      inner: Arc<RwLock<HashMap<String, NodeInfo>>>,
18  }
19  
20  impl NodeMap {
21      /// Create a new node map containing only our own entry.
22      pub fn new(name: String, id: PublicKey) -> Self {
23          let mut map = HashMap::new();
24          map.insert(name.clone(), NodeInfo { name, id });
25          Self {
26              inner: Arc::new(RwLock::new(map)),
27          }
28      }
29  
30      /// Insert or update a node.
31      pub async fn insert(&self, node: NodeInfo) {
32          self.inner.write().await.insert(node.name.clone(), node);
33      }
34  
35      /// Pick a random node, optionally excluding one by public key.
36      pub async fn pick_random(&self, exclude: Option<&PublicKey>) -> Option<NodeInfo> {
37          let map = self.inner.read().await;
38          let candidates: Vec<_> = map
39              .values()
40              .filter(|n| exclude.is_none_or(|pk| n.id != *pk))
41              .collect();
42          if candidates.is_empty() {
43              None
44          } else {
45              let idx = rand::rng().random_range(0..candidates.len());
46              Some(candidates[idx].clone())
47          }
48      }
49  
50      /// Get a node by name.
51      pub async fn get(&self, name: &str) -> Option<NodeInfo> {
52          self.inner.read().await.get(name).cloned()
53      }
54  
55      /// Return all known nodes.
56      pub async fn list(&self) -> Vec<NodeInfo> {
57          self.inner.read().await.values().cloned().collect()
58      }
59  
60      /// Collect gossip candidate public keys, excluding `own_name`.
61      pub async fn gossip_candidates(
62          &self,
63          own_name: &str,
64          initial_peers: &[PublicKey],
65      ) -> Vec<PublicKey> {
66          let map = self.inner.read().await;
67          let mut keys: Vec<PublicKey> = Vec::new();
68  
69          // Add initial peers.
70          for pk in initial_peers {
71              keys.push(*pk);
72          }
73  
74          // Add all other known nodes not already in the list.
75          for node in map.values() {
76              if node.name == own_name {
77                  continue;
78              }
79              if keys.contains(&node.id) {
80                  continue;
81              }
82              keys.push(node.id);
83          }
84  
85          keys
86      }
87  }