1pub mod store;
2pub use store::{Error, Store};
3
4use std::cell::RefCell;
5use std::ops::{Deref, DerefMut};
6use std::{hash, net};
7
8use cyphernet::addr::HostName;
9use localtime::LocalTime;
10use nonempty::NonEmpty;
11
12use crate::collections::RandomMap;
13use crate::node::{Address, Alias, Penalty, UserAgent};
14use crate::prelude::Timestamp;
15use crate::{node, profile};
16
17#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
19#[serde(transparent)]
20pub struct AddressBook<K: hash::Hash + Eq, V> {
21 inner: RandomMap<K, V>,
22 #[serde(skip)]
23 rng: RefCell<fastrand::Rng>,
24}
25
26impl<K: hash::Hash + Eq, V> AddressBook<K, V> {
27 pub fn new(rng: fastrand::Rng) -> Self {
29 Self {
30 inner: RandomMap::with_hasher(rng.clone().into()),
31 rng: RefCell::new(rng),
32 }
33 }
34
35 pub fn sample(&self) -> Option<(&K, &V)> {
37 self.sample_with(|_, _| true)
38 }
39
40 pub fn sample_with(&self, mut predicate: impl FnMut(&K, &V) -> bool) -> Option<(&K, &V)> {
42 if let Some(pairs) = NonEmpty::from_vec(
43 self.inner
44 .iter()
45 .filter(|(k, v)| predicate(*k, *v))
46 .collect(),
47 ) {
48 let ix = self.rng.borrow_mut().usize(..pairs.len());
49 let pair = pairs[ix]; Some(pair)
52 } else {
53 None
54 }
55 }
56
57 pub fn with(self, rng: fastrand::Rng) -> Self {
59 Self {
60 inner: self.inner,
61 rng: RefCell::new(rng),
62 }
63 }
64}
65
66impl<K: hash::Hash + Eq + Ord + Copy, V> AddressBook<K, V> {
67 pub fn shuffled(&self) -> std::vec::IntoIter<(&K, &V)> {
69 let mut items = self.inner.iter().collect::<Vec<_>>();
70 items.sort_by_key(|(k, _)| *k);
71 self.rng.borrow_mut().shuffle(&mut items);
72
73 items.into_iter()
74 }
75
76 pub fn into_shuffled(self) -> impl Iterator<Item = (K, V)> {
78 let mut items = self.inner.into_iter().collect::<Vec<_>>();
79 items.sort_by_key(|(k, _)| *k);
80 self.rng.borrow_mut().shuffle(&mut items);
81
82 items.into_iter()
83 }
84
85 pub fn cycle(&self) -> impl Iterator<Item = &K> {
87 self.shuffled().map(|(k, _)| k).cycle()
88 }
89}
90
91impl<K: hash::Hash + Eq, V> FromIterator<(K, V)> for AddressBook<K, V> {
92 fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
93 let rng = profile::env::rng();
94 let mut inner = RandomMap::with_hasher(rng.clone().into());
95
96 for (k, v) in iter {
97 inner.insert(k, v);
98 }
99 Self {
100 inner,
101 rng: RefCell::new(rng),
102 }
103 }
104}
105
106impl<K: hash::Hash + Eq, V> Deref for AddressBook<K, V> {
107 type Target = RandomMap<K, V>;
108
109 fn deref(&self) -> &Self::Target {
110 &self.inner
111 }
112}
113
114impl<K: hash::Hash + Eq, V> DerefMut for AddressBook<K, V> {
115 fn deref_mut(&mut self) -> &mut Self::Target {
116 &mut self.inner
117 }
118}
119
120#[derive(Debug, Clone, PartialEq, Eq)]
122pub struct Node {
123 pub version: u8,
125 pub alias: Alias,
127 pub features: node::Features,
129 pub addrs: Vec<KnownAddress>,
131 pub pow: u32,
133 pub timestamp: Timestamp,
135 pub agent: UserAgent,
137 pub penalty: Penalty,
139 pub banned: bool,
141}
142
143#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
145#[serde(rename_all = "camelCase")]
146#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
147pub struct KnownAddress {
148 pub addr: Address,
150 pub source: Source,
152 pub last_success: Option<LocalTime>,
154 pub last_attempt: Option<LocalTime>,
156 pub banned: bool,
158}
159
160impl KnownAddress {
161 pub fn new(addr: Address, source: Source) -> Self {
163 Self {
164 addr,
165 source,
166 last_success: None,
167 last_attempt: None,
168 banned: false,
169 }
170 }
171}
172
173#[derive(Debug, Copy, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
175#[serde(rename_all = "camelCase")]
176#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
177pub enum Source {
178 Peer,
180 Bootstrap,
182 Imported,
185}
186
187impl std::fmt::Display for Source {
188 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
189 match self {
190 Self::Peer => write!(f, "Peer"),
191 Self::Bootstrap => write!(f, "Bootstrap"),
192 Self::Imported => write!(f, "Imported"),
193 }
194 }
195}
196
197#[repr(u8)]
199#[derive(Debug, Clone, Copy, PartialEq, Eq)]
200pub enum AddressType {
201 Ipv4 = 1,
202 Ipv6 = 2,
203 Dns = 3,
204 Onion = 4,
205}
206
207impl From<AddressType> for u8 {
208 fn from(other: AddressType) -> Self {
209 other as u8
210 }
211}
212
213impl From<&Address> for AddressType {
214 fn from(a: &Address) -> Self {
215 match a.host {
216 HostName::Ip(net::IpAddr::V4(_)) => AddressType::Ipv4,
217 HostName::Ip(net::IpAddr::V6(_)) => AddressType::Ipv6,
218 HostName::Dns(_) => AddressType::Dns,
219 HostName::Tor(_) => AddressType::Onion,
220 _ => todo!(), }
222 }
223}
224
225impl TryFrom<u8> for AddressType {
226 type Error = u8;
227
228 fn try_from(other: u8) -> Result<Self, Self::Error> {
229 match other {
230 1 => Ok(AddressType::Ipv4),
231 2 => Ok(AddressType::Ipv6),
232 3 => Ok(AddressType::Dns),
233 4 => Ok(AddressType::Onion),
234 _ => Err(other),
235 }
236 }
237}
238pub fn is_routable(addr: &net::IpAddr) -> bool {
240 match addr {
241 net::IpAddr::V4(addr) => ipv4_is_routable(addr),
242 net::IpAddr::V6(addr) => ipv6_is_routable(addr),
243 }
244}
245
246pub fn is_local(addr: &net::IpAddr) -> bool {
248 match addr {
249 net::IpAddr::V4(addr) => {
250 addr.is_private() || addr.is_loopback() || addr.is_link_local() || addr.is_unspecified()
251 }
252 net::IpAddr::V6(addr) => {
253 addr.is_loopback() || addr.is_unicast_link_local() || addr.is_unspecified()
254 }
255 }
256}
257
258fn ipv4_is_routable(addr: &net::Ipv4Addr) -> bool {
267 if *addr == net::Ipv4Addr::new(192, 0, 0, 9) {
269 return true;
270 }
271
272 if *addr == net::Ipv4Addr::new(192, 0, 0, 10) {
274 return true;
275 }
276
277 if addr.octets()[0] == 0 {
279 return false;
280 }
281
282 !addr.is_private()
283 && !addr.is_loopback()
284 && !addr.is_link_local()
285 && !addr.is_broadcast()
286 && !addr.is_documentation()
287}
288
289fn ipv6_is_routable(addr: &net::Ipv6Addr) -> bool {
298 !addr.is_loopback() && !addr.is_unicast_link_local() && !addr.is_unspecified()
299}