ckb_network/peer_store/
addr_manager.rs1use crate::peer_store::{base_addr, types::AddrInfo};
3use p2p::{multiaddr::Multiaddr, utils::multiaddr_to_socketaddr};
4use rand::Rng;
5use std::collections::{HashMap, HashSet};
6
7#[derive(Default)]
9pub struct AddrManager {
10 next_id: u64,
11 addr_to_id: HashMap<Multiaddr, u64>,
12 id_to_info: HashMap<u64, AddrInfo>,
13 random_ids: Vec<u64>,
14}
15
16impl AddrManager {
17 pub fn add(&mut self, mut addr_info: AddrInfo) {
19 if let Some(&id) = self.addr_to_id.get(&addr_info.addr) {
20 let (exist_last_connected_at_ms, random_id_pos) = {
21 let info = self.id_to_info.get(&id).expect("must exists");
22 (info.last_connected_at_ms, info.random_id_pos)
23 };
24 if addr_info.last_connected_at_ms >= exist_last_connected_at_ms {
26 addr_info.random_id_pos = random_id_pos;
27 self.id_to_info.insert(id, addr_info);
28 }
29 return;
30 }
31
32 let id = self.next_id;
33 self.addr_to_id.insert(addr_info.addr.clone(), id);
34 addr_info.random_id_pos = self.random_ids.len();
35 self.id_to_info.insert(id, addr_info);
36 self.random_ids.push(id);
37 self.next_id += 1;
38 }
39
40 pub fn fetch_random<F>(&mut self, count: usize, filter: F) -> Vec<AddrInfo>
42 where
43 F: Fn(&AddrInfo) -> bool,
44 {
45 let mut duplicate_ips = HashSet::new();
46 let mut addr_infos = Vec::with_capacity(count);
47 let mut rng = rand::thread_rng();
48 let now_ms = ckb_systemtime::unix_time_as_millis();
49 for i in 0..self.random_ids.len() {
50 let j = rng.gen_range(i..self.random_ids.len());
53 self.swap_random_id(j, i);
54 let addr_info: AddrInfo = self.id_to_info[&self.random_ids[i]].to_owned();
55 match multiaddr_to_socketaddr(&addr_info.addr) {
56 Some(socket_addr) => {
57 let ip = socket_addr.ip();
58 let is_unique_ip = !duplicate_ips.contains(&ip);
59 let is_test_ip = ip.is_unspecified() || ip.is_loopback();
62 if (is_test_ip || is_unique_ip)
63 && addr_info.is_connectable(now_ms)
64 && filter(&addr_info)
65 {
66 duplicate_ips.insert(ip);
67 addr_infos.push(addr_info);
68 }
69 }
70 None => {
71 if addr_info.is_connectable(now_ms) && filter(&addr_info) {
72 addr_infos.push(addr_info);
73 }
74 }
75 }
76 if addr_infos.len() == count {
77 break;
78 }
79 }
80 addr_infos
81 }
82
83 pub fn count(&self) -> usize {
85 self.addr_to_id.len()
86 }
87
88 pub fn addrs_iter(&self) -> impl Iterator<Item = &AddrInfo> {
90 self.id_to_info.values()
91 }
92
93 pub fn remove(&mut self, addr: &Multiaddr) -> Option<AddrInfo> {
95 let base_addr = base_addr(addr);
96 self.addr_to_id.remove(&base_addr).and_then(|id| {
97 let random_id_pos = self.id_to_info.get(&id).expect("exists").random_id_pos;
98 self.swap_random_id(random_id_pos, self.random_ids.len() - 1);
100 self.random_ids.pop();
101 self.id_to_info.remove(&id)
102 })
103 }
104
105 pub fn get(&self, addr: &Multiaddr) -> Option<&AddrInfo> {
107 let base_addr = base_addr(addr);
108 self.addr_to_id
109 .get(&base_addr)
110 .and_then(|id| self.id_to_info.get(id))
111 }
112
113 pub fn get_mut(&mut self, addr: &Multiaddr) -> Option<&mut AddrInfo> {
115 let base_addr = base_addr(addr);
116 if let Some(id) = self.addr_to_id.get(&base_addr) {
117 self.id_to_info.get_mut(id)
118 } else {
119 None
120 }
121 }
122
123 fn swap_random_id(&mut self, i: usize, j: usize) {
126 if i == j {
127 return;
128 }
129 self.id_to_info
130 .get_mut(&self.random_ids[i])
131 .expect("exists")
132 .random_id_pos = j;
133 self.id_to_info
134 .get_mut(&self.random_ids[j])
135 .expect("exists")
136 .random_id_pos = i;
137 self.random_ids.swap(i, j);
138 }
139}