store.rs 65 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2024 Dyne.org foundation
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Affero General Public License as
  7. * published by the Free Software Foundation, either version 3 of the
  8. * License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. use std::{
  19. collections::{HashMap, HashSet},
  20. fmt, fs,
  21. fs::File,
  22. sync::Arc,
  23. time::{Instant, UNIX_EPOCH},
  24. };
  25. use log::{debug, error, info, trace, warn};
  26. use rand::{prelude::IteratorRandom, rngs::OsRng, Rng};
  27. use smol::lock::RwLock;
  28. use url::Url;
  29. use super::super::{settings::SettingsPtr, ChannelPtr};
  30. use crate::{
  31. system::{Subscriber, SubscriberPtr, Subscription},
  32. util::{
  33. file::{load_file, save_file},
  34. path::expand_path,
  35. },
  36. Error, Result,
  37. };
  38. /// Atomic pointer to hosts object
  39. pub type HostsPtr = Arc<Hosts>;
  40. /// Keeps track of hosts and their current state. Prevents race conditions
  41. /// where multiple threads are simultaenously trying to change the state of
  42. /// a given host.
  43. pub type HostRegistry = RwLock<HashMap<Url, HostState>>;
  44. /// HostState is a set of mutually exclusive states that can be Pending,
  45. /// Connected, Disconnected or Refining. The state is `None` when the
  46. /// corresponding host has been removed from the HostRegistry.
  47. ///
  48. /// +----------+
  49. /// +-- | refining | --+
  50. /// | +----------+ |
  51. /// | |
  52. /// v v
  53. /// +---------+ +-----------+ +------+
  54. /// | pending | -> | connected | -> | None |
  55. /// +---------+ +-----------+ +------+
  56. /// | ^
  57. /// | |
  58. /// | +-------------+ |
  59. /// +-----> | downgrading | ------+
  60. /// +-------------+
  61. ///
  62. #[derive(Clone, Debug)]
  63. pub enum HostState {
  64. /// Hosts that are being connected to in Outbound and Manual Session.
  65. Pending,
  66. /// Hosts that have been successfully connected to.
  67. Connected(ChannelPtr),
  68. /// Hosts that we have repeatedly failed to connect to, and that are being
  69. /// removed from the anchorlist and whitelist and added to the greylist.
  70. Downgrading,
  71. /// Hosts that are migrating from the greylist to the whitelist or being
  72. /// removed from the greylist, as defined in `refinery.rs`.
  73. Refining,
  74. }
  75. impl HostState {
  76. // Try to change state to Downgrading. Only possible if this
  77. // connection is pending i.e. if we are trying to connect to this
  78. // host.
  79. fn try_downgrade(&self) -> Result<Self> {
  80. match self {
  81. HostState::Pending => Ok(HostState::Downgrading),
  82. HostState::Connected(_) => Err(Error::StateBlocked(self.to_string())),
  83. HostState::Downgrading => Err(Error::StateBlocked(self.to_string())),
  84. HostState::Refining => Err(Error::StateBlocked(self.to_string())),
  85. }
  86. }
  87. // Try to change state to Refining. Only possible if we are not yet
  88. // tracking this host in the HostRegistry.
  89. fn try_refine(&self) -> Result<Self> {
  90. match self {
  91. HostState::Pending => Err(Error::StateBlocked(self.to_string())),
  92. HostState::Connected(_) => Err(Error::StateBlocked(self.to_string())),
  93. HostState::Downgrading => Err(Error::StateBlocked(self.to_string())),
  94. HostState::Refining => Err(Error::StateBlocked(self.to_string())),
  95. }
  96. }
  97. // Try to change state to Connected. Possible if this peer is
  98. // currently Pending or being Refined. The latter is necessary since
  99. // the refinery process requires us to establish a connection to
  100. // a peer.
  101. fn try_connect(&self, channel: ChannelPtr) -> Result<Self> {
  102. match self {
  103. HostState::Pending => Ok(HostState::Connected(channel)),
  104. HostState::Connected(_) => Err(Error::StateBlocked(self.to_string())),
  105. HostState::Downgrading => Err(Error::StateBlocked(self.to_string())),
  106. HostState::Refining => Ok(HostState::Connected(channel)),
  107. }
  108. }
  109. // Try to change state to Pending. Only possible if we are not yet
  110. // tracking this host in the HostRegistry.
  111. fn try_pending(&self) -> Result<Self> {
  112. match self {
  113. HostState::Pending => Err(Error::StateBlocked(self.to_string())),
  114. HostState::Connected(_) => Err(Error::StateBlocked(self.to_string())),
  115. HostState::Downgrading => Err(Error::StateBlocked(self.to_string())),
  116. HostState::Refining => Err(Error::StateBlocked(self.to_string())),
  117. }
  118. }
  119. }
  120. impl fmt::Display for HostState {
  121. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  122. fmt::Debug::fmt(self, f)
  123. }
  124. }
  125. // An array containing all possible local host strings
  126. // TODO: This could perhaps be more exhaustive?
  127. pub const LOCAL_HOST_STRS: [&str; 2] = ["localhost", "localhost.localdomain"];
  128. const WHITELIST_MAX_LEN: usize = 5000;
  129. const GREYLIST_MAX_LEN: usize = 2000;
  130. /// Manages a store of network addresses
  131. // TODO: Test the performance overhead of using vectors for white/grey/anchor lists.
  132. // TODO: Check whether anchorlist has a max size in Monero.
  133. // TODO: we can probably clean up a lot of the repetitive code in this module.
  134. pub struct Hosts {
  135. /// Intermediary node list that is periodically probed and updated to whitelist.
  136. pub greylist: RwLock<Vec<(Url, u64)>>,
  137. /// Recently seen hosts. Shared with other nodes.
  138. pub whitelist: RwLock<Vec<(Url, u64)>>,
  139. /// Nodes to which we have already been able to establish a connection.
  140. pub anchorlist: RwLock<Vec<(Url, u64)>>,
  141. /// Subscriber for notifications of new channels
  142. channel_subscriber: SubscriberPtr<Result<ChannelPtr>>,
  143. /// Set of stored addresses that are quarantined.
  144. /// We quarantine peers we've been unable to connect to, but we keep them
  145. /// around so we can potentially try them again, up to n tries. This should
  146. /// be helpful in order to self-heal the p2p connections in case we have an
  147. /// Internet interrupt (goblins unplugging cables)
  148. quarantine: RwLock<HashMap<Url, usize>>,
  149. /// A registry that tracks hosts and their current state.
  150. registry: HostRegistry,
  151. /// Peers on the blacklist are considered hostile and can neither be connected to
  152. /// nor establish connections to us for the duration of the program.
  153. blacklist: RwLock<HashSet<String>>,
  154. /// Subscriber listening for store updates
  155. store_subscriber: SubscriberPtr<usize>,
  156. /// Pointer to configured P2P settings
  157. settings: SettingsPtr,
  158. }
  159. impl Hosts {
  160. /// Create a new hosts list>
  161. pub fn new(settings: SettingsPtr) -> HostsPtr {
  162. Arc::new(Self {
  163. greylist: RwLock::new(Vec::new()),
  164. whitelist: RwLock::new(Vec::new()),
  165. anchorlist: RwLock::new(Vec::new()),
  166. channel_subscriber: Subscriber::new(),
  167. quarantine: RwLock::new(HashMap::new()),
  168. registry: RwLock::new(HashMap::new()),
  169. blacklist: RwLock::new(HashSet::new()),
  170. store_subscriber: Subscriber::new(),
  171. settings,
  172. })
  173. }
  174. /// Try to update the registry. If the host already exists, try to update its state.
  175. /// Otherwise add the host to the registry along with its state.
  176. pub async fn try_update_registry(&self, addr: Url, new_state: HostState) -> Result<HostState> {
  177. let mut registry = self.registry.write().await;
  178. if registry.contains_key(&addr) {
  179. let current_state = registry.get(&addr).unwrap().clone();
  180. debug!(target: "store::try_update_registry()",
  181. "Attempting to update addr={} current_state={}, new_state={}",
  182. addr, current_state, new_state.to_string());
  183. let result: Result<HostState> = match new_state {
  184. HostState::Pending => current_state.try_pending(),
  185. HostState::Connected(c) => current_state.try_connect(c),
  186. HostState::Downgrading => current_state.try_downgrade(),
  187. HostState::Refining => current_state.try_refine(),
  188. };
  189. if let Ok(state) = &result {
  190. registry.insert(addr.clone(), state.clone());
  191. }
  192. result
  193. } else {
  194. // We don't know this peer. We can safely update the state.
  195. registry.insert(addr.clone(), new_state.clone());
  196. Ok(new_state)
  197. }
  198. }
  199. pub async fn check_address(&self, hosts: Vec<(Url, u64)>) -> Option<(Url, u64)> {
  200. // Try to find an unused host in the set.
  201. for (host, last_seen) in hosts {
  202. debug!(target: "store::check_address()", "Starting checks");
  203. if let Err(_) = self.try_update_registry(host.clone(), HostState::Pending).await {
  204. continue
  205. }
  206. debug!(
  207. target: "store::check_address()",
  208. "Found valid host {}",
  209. host
  210. );
  211. return Some((host.clone(), last_seen))
  212. }
  213. None
  214. }
  215. /// Remove a host from the HostRegistry. Must be called after downgrade(), when the refinery
  216. /// process fails, or when a channel stops. Prevents hosts from getting trapped in the
  217. /// HostState logical machinery.
  218. pub async fn remove(&self, addr: &Url) {
  219. debug!(target: "store", "remove() Removing {} from HostRegistry", addr);
  220. self.registry.write().await.remove(addr);
  221. }
  222. /// Returns the list of connected channels.
  223. pub async fn channels(&self) -> Vec<ChannelPtr> {
  224. let registry = self.registry.read().await;
  225. let mut channels = Vec::new();
  226. for (_, value) in registry.iter() {
  227. if let HostState::Connected(c) = value {
  228. channels.push(c.clone());
  229. }
  230. }
  231. channels
  232. }
  233. /// Retrieve a random connected channel
  234. pub async fn random_channel(&self) -> ChannelPtr {
  235. let channels = self.channels().await;
  236. let position = rand::thread_rng().gen_range(0..channels.len());
  237. channels[position].clone()
  238. }
  239. /// Add a channel to the set of connected channels
  240. pub async fn store(&self, channel: ChannelPtr) -> Result<()> {
  241. let address = channel.address().clone();
  242. if let Err(e) =
  243. self.try_update_registry(address.clone(), HostState::Connected(channel.clone())).await
  244. {
  245. return Err(e)
  246. }
  247. self.channel_subscriber.notify(Ok(channel)).await;
  248. Ok(())
  249. }
  250. /// Loops through greylist addresses to find an outbound address that we can
  251. /// connect to. Check whether the address is valid by making sure it isn't
  252. /// our own inbound address, then checks whether it is already connected
  253. /// (exists) or connecting (pending).
  254. /// Lastly adds matching address to the pending list.
  255. pub async fn greylist_fetch_address(&self, transports: &[String]) -> Vec<(Url, u64)> {
  256. trace!(target: "store", "greylist_fetch_address() [START]");
  257. // Collect hosts
  258. let mut hosts = vec![];
  259. // If transport mixing is enabled, then for example we're allowed to
  260. // use tor:// to connect to tcp:// and tor+tls:// to connect to tcp+tls://.
  261. // However, **do not** mix tor:// and tcp+tls://, nor tor+tls:// and tcp://.
  262. let transport_mixing = self.settings.transport_mixing;
  263. macro_rules! mix_transport {
  264. ($a:expr, $b:expr) => {
  265. if transports.contains(&$a.to_string()) && transport_mixing {
  266. let mut a_to_b =
  267. self.greylist_fetch_with_schemes(&[$b.to_string()], None).await;
  268. for (addr, last_seen) in a_to_b.iter_mut() {
  269. addr.set_scheme($a).unwrap();
  270. hosts.push((addr.clone(), last_seen.clone()));
  271. }
  272. }
  273. };
  274. }
  275. mix_transport!("tor", "tcp");
  276. mix_transport!("tor+tls", "tcp+tls");
  277. mix_transport!("nym", "tcp");
  278. mix_transport!("nym+tls", "tcp+tls");
  279. // And now the actual requested transports
  280. for (addr, last_seen) in self.greylist_fetch_with_schemes(transports, None).await {
  281. hosts.push((addr, last_seen));
  282. }
  283. hosts
  284. }
  285. /// Loops through whitelist addresses to find an outbound address that we can
  286. /// connect to. Check whether the address is valid by making sure it isn't
  287. /// our own inbound address, then checks whether it is already connected
  288. /// (exists) or connecting (pending).
  289. /// Lastly adds matching address to the pending list.
  290. pub async fn whitelist_fetch_address(&self, transports: &[String]) -> Vec<(Url, u64)> {
  291. trace!(target: "store", "whitelist_fetch_address() [START]");
  292. // Collect hosts
  293. let mut hosts = vec![];
  294. // If transport mixing is enabled, then for example we're allowed to
  295. // use tor:// to connect to tcp:// and tor+tls:// to connect to tcp+tls://.
  296. // However, **do not** mix tor:// and tcp+tls://, nor tor+tls:// and tcp://.
  297. let transport_mixing = self.settings.transport_mixing;
  298. macro_rules! mix_transport {
  299. ($a:expr, $b:expr) => {
  300. if transports.contains(&$a.to_string()) && transport_mixing {
  301. let mut a_to_b =
  302. self.whitelist_fetch_with_schemes(&[$b.to_string()], None).await;
  303. for (addr, last_seen) in a_to_b.iter_mut() {
  304. addr.set_scheme($a).unwrap();
  305. hosts.push((addr.clone(), last_seen.clone()));
  306. }
  307. }
  308. };
  309. }
  310. mix_transport!("tor", "tcp");
  311. mix_transport!("tor+tls", "tcp+tls");
  312. mix_transport!("nym", "tcp");
  313. mix_transport!("nym+tls", "tcp+tls");
  314. // And now the actual requested transports
  315. for (addr, last_seen) in self.whitelist_fetch_with_schemes(transports, None).await {
  316. hosts.push((addr, last_seen));
  317. }
  318. trace!(target: "store::whitelist_fetch_address()",
  319. "Grabbed hosts, length: {}", hosts.len());
  320. hosts
  321. }
  322. /// Loops through anchorlist addresses to find an outbound address that we can
  323. /// connect to. Check whether the address is valid by making sure it isn't
  324. /// our own inbound address, then checks whether it is already connected
  325. /// (exists) or connecting (pending).
  326. /// Lastly adds matching address to the pending list.
  327. pub async fn anchorlist_fetch_address(&self, transports: &[String]) -> Vec<(Url, u64)> {
  328. trace!(target: "store", "anchorlist_fetch_address() [START]");
  329. // Collect hosts
  330. let mut hosts = vec![];
  331. // If transport mixing is enabled, then for example we're allowed to
  332. // use tor:// to connect to tcp:// and tor+tls:// to connect to tcp+tls://.
  333. // However, **do not** mix tor:// and tcp+tls://, nor tor+tls:// and tcp://.
  334. let transport_mixing = self.settings.transport_mixing;
  335. macro_rules! mix_transport {
  336. ($a:expr, $b:expr) => {
  337. if transports.contains(&$a.to_string()) && transport_mixing {
  338. let mut a_to_b =
  339. self.anchorlist_fetch_with_schemes(&[$b.to_string()], None).await;
  340. for (addr, last_seen) in a_to_b.iter_mut() {
  341. addr.set_scheme($a).unwrap();
  342. hosts.push((addr.clone(), last_seen.clone()));
  343. }
  344. }
  345. };
  346. }
  347. mix_transport!("tor", "tcp");
  348. mix_transport!("tor+tls", "tcp+tls");
  349. mix_transport!("nym", "tcp");
  350. mix_transport!("nym+tls", "tcp+tls");
  351. // And now the actual requested transports
  352. for (addr, last_seen) in self.anchorlist_fetch_with_schemes(transports, None).await {
  353. hosts.push((addr, last_seen));
  354. }
  355. trace!(target: "store::anchorlist_fetch_address()",
  356. "Grabbed hosts, length: {}", hosts.len());
  357. hosts
  358. }
  359. /// Upgrade a connection to the anchorlist. Called after a connection has been successfully
  360. /// established in Outbound and Manual sessions.
  361. pub async fn upgrade_host(&self, addr: &Url) {
  362. let last_seen = UNIX_EPOCH.elapsed().unwrap().as_secs();
  363. self.anchorlist_store_or_update(&[(addr.clone(), last_seen)]).await;
  364. }
  365. /// Downgrade a host to greylist. If the host is on the anchorlist or whitelist, remove it.
  366. /// If it's already on the greylist we can't do anything here.
  367. pub async fn downgrade_host(&self, addr: &Url, last_seen: u64) {
  368. if let Err(_) = self.try_update_registry(addr.clone(), HostState::Downgrading).await {
  369. return
  370. }
  371. debug!(target: "store::downgrade_host", "Downgrading host {}", addr);
  372. if self.greylist_contains(addr).await {
  373. warn!(target: "store::downgrade_host",
  374. "Cannot downgrade a host that is already on the greylist! {}", addr);
  375. }
  376. if self.anchorlist_contains(addr).await {
  377. debug!(target: "store::downgrade_host", "Removing from anchorlist {}", addr);
  378. let index = self
  379. .get_anchorlist_index_at_addr(addr.clone())
  380. .await
  381. .expect("Expected anchorlist index to exist");
  382. self.anchorlist_remove(addr, index).await;
  383. self.greylist_store_or_update(&[(addr.clone(), last_seen)]).await;
  384. }
  385. if self.whitelist_contains(addr).await {
  386. debug!(target: "store::downgrade_host", "Removing from whitelist {}", addr);
  387. let index = self
  388. .get_whitelist_index_at_addr(addr.clone())
  389. .await
  390. .expect("Expected whitelist index to exist");
  391. self.whitelist_remove(addr, index).await;
  392. self.greylist_store_or_update(&[(addr.clone(), last_seen)]).await;
  393. }
  394. // Remove this entry from HostRegistry to avoid this host getting
  395. // stuck in the Downgrading state.
  396. self.remove(&addr).await;
  397. }
  398. /// Stores an address on the greylist or updates its last_seen field if we already
  399. /// have the address.
  400. pub async fn greylist_store_or_update(&self, addrs: &[(Url, u64)]) {
  401. trace!(target: "store::greylist_store_or_update()", "[START]");
  402. // Filter addresses before writing to the greylist.
  403. let filtered_addrs = self.filter_addresses(addrs).await;
  404. let filtered_addrs_len = filtered_addrs.len();
  405. if filtered_addrs.is_empty() {
  406. debug!(target: "store::greylist_store_or_update()", "Filtered out all addresses");
  407. }
  408. for (addr, last_seen) in filtered_addrs {
  409. if !self.greylist_contains(&addr).await {
  410. debug!(target: "store::greylist_store_or_update()",
  411. "We do not have this entry in the hostlist. Adding to store...");
  412. self.greylist_store(addr.clone(), last_seen).await;
  413. } else {
  414. debug!(target: "store::greylist_store_or_update()",
  415. "We have this entry in the greylist. Updating last seen...");
  416. let index = self
  417. .get_greylist_index_at_addr(addr.clone())
  418. .await
  419. .expect("Expected greylist entry to exist");
  420. debug!(target: "store::greylist_store_or_update()",
  421. "Selected index, updating last seen...");
  422. self.greylist_update_last_seen(&addr, last_seen, index).await;
  423. self.store_subscriber.notify(filtered_addrs_len).await;
  424. }
  425. }
  426. }
  427. /// Stores an address on the whitelist or updates its last_seen field if we already
  428. /// have the address.
  429. pub async fn whitelist_store_or_update(&self, addrs: &[(Url, u64)]) {
  430. trace!(target: "store::whitelist_store_or_update()", "[START]");
  431. // No address filtering for whitelist (whitelist is created from greylist)
  432. for (addr, last_seen) in addrs {
  433. if !self.whitelist_contains(addr).await {
  434. debug!(target: "store::whitelist_store_or_update()",
  435. "We do not have this entry in the whitelist. Adding to store...");
  436. self.whitelist_store(addr.clone(), *last_seen).await;
  437. } else {
  438. debug!(target: "store::whitelist_store_or_update()",
  439. "We have this entry in the whitelist. Updating last seen...");
  440. let index = self
  441. .get_whitelist_index_at_addr(addr.clone())
  442. .await
  443. .expect("Expected whitelist entry to exist");
  444. self.whitelist_update_last_seen(addr, *last_seen, index).await;
  445. }
  446. }
  447. }
  448. /// Stores an address on the anchorlist or updates its last_seen field if we already
  449. /// have the address.
  450. pub async fn anchorlist_store_or_update(&self, addrs: &[(Url, u64)]) {
  451. trace!(target: "store::anchor_store_or_update()", "[START]");
  452. // No address filtering for anchorlist (contains addresses we have already connected to)
  453. for (addr, last_seen) in addrs {
  454. if !self.anchorlist_contains(addr).await {
  455. debug!(target: "store::anchorlist_store_or_update()",
  456. "We do not have this entry in the whitelist. Adding to store...");
  457. self.anchorlist_store(addr.clone(), *last_seen).await;
  458. } else {
  459. debug!(target: "store::anchorlist_store_or_update()",
  460. "We have this entry in the anchorlist. Updating last seen...");
  461. let index = self
  462. .get_anchorlist_index_at_addr(addr.clone())
  463. .await
  464. .expect("Expected anchorlist entry to exist");
  465. self.anchorlist_update_last_seen(addr, *last_seen, index).await;
  466. }
  467. }
  468. }
  469. /// Append host to the greylist. Called on learning of a new peer.
  470. pub async fn greylist_store(&self, addr: Url, last_seen: u64) {
  471. trace!(target: "store::greylist_store()", "hosts::greylist_store() [START]");
  472. let mut greylist = self.greylist.write().await;
  473. // Remove oldest element if the greylist reaches max size.
  474. if greylist.len() == GREYLIST_MAX_LEN {
  475. let last_entry = greylist.pop().unwrap();
  476. debug!(target: "store::greylist_store()", "Greylist reached max size. Removed {:?}", last_entry);
  477. }
  478. debug!(target: "store::greylist_store()", "Inserting {}", addr);
  479. greylist.push((addr, last_seen));
  480. // Sort the list by last_seen.
  481. greylist.sort_by_key(|entry| entry.1);
  482. greylist.reverse();
  483. trace!(target: "store::greylist_store()", "[END]");
  484. }
  485. /// Append host to the whitelist. Called after a successful interaction with an online peer.
  486. pub async fn whitelist_store(&self, addr: Url, last_seen: u64) {
  487. trace!(target: "store::whitelist_store()", "[START]");
  488. let mut whitelist = self.whitelist.write().await;
  489. // Remove oldest element if the whitelist reaches max size.
  490. if whitelist.len() == WHITELIST_MAX_LEN {
  491. let last_entry = whitelist.pop().unwrap();
  492. debug!(target: "store::whitelist_store()", "Whitelist reached max size. Removed {:?}", last_entry);
  493. }
  494. trace!(target: "store::whitelist_store()", "Inserting {}. Last seen {:?}", addr, last_seen);
  495. whitelist.push((addr, last_seen));
  496. // Sort the list by last_seen.
  497. whitelist.sort_by_key(|entry| entry.1);
  498. whitelist.reverse();
  499. trace!(target: "store::whitelist_store()", "[END]");
  500. }
  501. /// Append host to the anchorlist. Called after we have successfully established a connection
  502. /// to a peer.
  503. pub async fn anchorlist_store(&self, addr: Url, last_seen: u64) {
  504. trace!(target: "store::anchorlist_store()", "[START]");
  505. let mut anchorlist = self.anchorlist.write().await;
  506. trace!(target: "store::anchorlist_store()", "Inserting {}", addr);
  507. anchorlist.push((addr, last_seen));
  508. // Sort the list by last_seen.
  509. anchorlist.sort_by_key(|entry| entry.1);
  510. anchorlist.reverse();
  511. trace!(target: "store::anchorlist_store()", "[END]");
  512. }
  513. /// Update the last_seen field of a peer on the greylist.
  514. pub async fn greylist_update_last_seen(&self, addr: &Url, last_seen: u64, index: usize) {
  515. trace!(target: "store::greylist_update_last_seen()", "[START]");
  516. let mut greylist = self.greylist.write().await;
  517. greylist[index] = (addr.clone(), last_seen);
  518. // Sort the list by last_seen.
  519. greylist.sort_by_key(|entry| entry.1);
  520. greylist.reverse();
  521. trace!(target: "store::greylist_update_last_seen()", "[END]");
  522. }
  523. /// Update the last_seen field of a peer on the whitelist.
  524. pub async fn whitelist_update_last_seen(&self, addr: &Url, last_seen: u64, index: usize) {
  525. trace!(target: "store::whitelist_update_last_seen()", "[START]");
  526. let mut whitelist = self.whitelist.write().await;
  527. whitelist[index] = (addr.clone(), last_seen);
  528. // Sort the list by last_seen.
  529. whitelist.sort_by_key(|entry| entry.1);
  530. whitelist.reverse();
  531. trace!(target: "store::whitelist_update_last_seen()", "[END]");
  532. }
  533. /// Update the last_seen field of a peer on the anchorlist.
  534. pub async fn anchorlist_update_last_seen(&self, addr: &Url, last_seen: u64, index: usize) {
  535. trace!(target: "store::anchorlist_update_last_seen()", "[START]");
  536. let mut anchorlist = self.anchorlist.write().await;
  537. anchorlist[index] = (addr.clone(), last_seen);
  538. // Sort the list by last_seen.
  539. anchorlist.sort_by_key(|entry| entry.1);
  540. anchorlist.reverse();
  541. trace!(target: "store::anchorlist_update_last_seen()", "[END]");
  542. }
  543. /// Remove an entry from the greylist.
  544. pub async fn greylist_remove(&self, addr: &Url, index: usize) {
  545. debug!(target: "store::greylist_remove", "Removing peer {} from greylist", addr);
  546. self.greylist.write().await.remove(index);
  547. }
  548. /// Remove an entry from the whitelist.
  549. pub async fn whitelist_remove(&self, addr: &Url, index: usize) {
  550. debug!(target: "store::whitelist_remove", "Removing peer {} from whitelist", addr);
  551. self.whitelist.write().await.remove(index);
  552. }
  553. /// Remove an entry from the anchorlist.
  554. pub async fn anchorlist_remove(&self, addr: &Url, index: usize) {
  555. debug!(target: "store::anchorlist_remove", "Removing peer {} from anchorlist", addr);
  556. self.anchorlist.write().await.remove(index);
  557. }
  558. pub async fn subscribe_store(&self) -> Result<Subscription<usize>> {
  559. let sub = self.store_subscriber.clone().subscribe().await;
  560. Ok(sub)
  561. }
  562. // Verify whether a URL is local.
  563. // NOTE: This function is stateless and not specific to
  564. // `Hosts`. For this reason, it might make more sense
  565. // to move this function to a more appropriate location
  566. // in the codebase.
  567. /// Check whether a URL is local host
  568. pub async fn is_local_host(&self, url: Url) -> bool {
  569. // Reject Urls without host strings.
  570. if url.host_str().is_none() {
  571. return false
  572. }
  573. // We do this hack in order to parse IPs properly.
  574. // https://github.com/whatwg/url/issues/749
  575. let addr = Url::parse(&url.as_str().replace(url.scheme(), "http")).unwrap();
  576. // Filter private IP ranges
  577. match addr.host().unwrap() {
  578. url::Host::Ipv4(ip) => {
  579. if !ip.is_global() {
  580. return true
  581. }
  582. }
  583. url::Host::Ipv6(ip) => {
  584. if !ip.is_global() {
  585. return true
  586. }
  587. }
  588. url::Host::Domain(d) => {
  589. if LOCAL_HOST_STRS.contains(&d) {
  590. return true
  591. }
  592. }
  593. }
  594. false
  595. }
  596. /// Filter given addresses based on certain rulesets and validity.
  597. async fn filter_addresses(&self, addrs: &[(Url, u64)]) -> Vec<(Url, u64)> {
  598. trace!(target: "store::filter_addresses()", "Filtering addrs: {:?}", addrs);
  599. let mut ret = vec![];
  600. let localnet = self.settings.localnet;
  601. 'addr_loop: for (addr_, last_seen) in addrs {
  602. // Validate that the format is `scheme://host_str:port`
  603. if addr_.host_str().is_none() ||
  604. addr_.port().is_none() ||
  605. addr_.cannot_be_a_base() ||
  606. addr_.path_segments().is_some()
  607. {
  608. continue
  609. }
  610. if self.is_blacklist(addr_).await {
  611. warn!(target: "store::filter_addresses()", "Peer {} is blacklisted", addr_);
  612. continue
  613. }
  614. let host_str = addr_.host_str().unwrap();
  615. if !localnet {
  616. // Our own external addresses should never enter the hosts set.
  617. for ext in &self.settings.external_addrs {
  618. if host_str == ext.host_str().unwrap() {
  619. continue 'addr_loop
  620. }
  621. }
  622. }
  623. // On localnet, make sure ours ports don't enter the host set.
  624. for ext in &self.settings.external_addrs {
  625. if addr_.port() == ext.port() {
  626. continue 'addr_loop
  627. }
  628. }
  629. // We do this hack in order to parse IPs properly.
  630. // https://github.com/whatwg/url/issues/749
  631. let addr = Url::parse(&addr_.as_str().replace(addr_.scheme(), "http")).unwrap();
  632. // Filter non-global ranges if we're not allowing localnet.
  633. // Should never be allowed in production, so we don't really care
  634. // about some of them (e.g. 0.0.0.0, or broadcast, etc.).
  635. if !localnet && self.is_local_host(addr).await {
  636. continue
  637. }
  638. match addr_.scheme() {
  639. // Validate that the address is an actual onion.
  640. #[cfg(feature = "p2p-tor")]
  641. "tor" | "tor+tls" => {
  642. use std::str::FromStr;
  643. if tor_hscrypto::pk::HsId::from_str(host_str).is_err() {
  644. continue
  645. }
  646. trace!(target: "store::filter_addresses()", "[Tor] Valid: {}", host_str);
  647. }
  648. #[cfg(feature = "p2p-nym")]
  649. "nym" | "nym+tls" => continue, // <-- Temp skip
  650. #[cfg(feature = "p2p-tcp")]
  651. "tcp" | "tcp+tls" => {
  652. trace!(target: "store::filter_addresses()", "[TCP] Valid: {}", host_str);
  653. }
  654. _ => continue,
  655. }
  656. ret.push((addr_.clone(), *last_seen));
  657. }
  658. ret
  659. }
  660. /// Quarantine a peer.
  661. /// If they've been quarantined for more than a configured limit, downgrade to greylist.
  662. pub async fn quarantine(&self, addr: &Url, last_seen: u64) {
  663. debug!(target: "store::quarantine()", "Quarantining peer {}", addr);
  664. let timer = Instant::now();
  665. let mut q = self.quarantine.write().await;
  666. if let Some(retries) = q.get_mut(addr) {
  667. *retries += 1;
  668. debug!(target: "store::quarantine()", "Peer {} quarantined {} times", addr, retries);
  669. if *retries == self.settings.hosts_quarantine_limit {
  670. debug!(target: "store::quarantine()", "Reached quarantine limited after {:?}", timer.elapsed());
  671. debug!(target: "store::quarantine()", "Removing from hostlist {}", addr);
  672. drop(q);
  673. self.downgrade_host(addr, last_seen).await;
  674. }
  675. } else {
  676. debug!(target: "net::hosts::quarantine()", "Added peer {} to quarantine", addr);
  677. q.insert(addr.clone(), 0);
  678. }
  679. }
  680. /// Check if a given peer (URL) is in the set of blacklist hosts
  681. pub async fn is_blacklist(&self, peer: &Url) -> bool {
  682. // Skip lookup for UNIX sockets and localhost connections
  683. // as they should never belong to the blacklist.
  684. let Some(hostname) = peer.host_str() else { return false };
  685. if self.is_local_host(peer.clone()).await {
  686. return false
  687. }
  688. self.blacklist.read().await.contains(hostname)
  689. }
  690. /// Mark a peer as blacklist by adding it to the set of blacklist URLs.
  691. pub async fn blacklist(&self, peer: &Url) {
  692. // We ignore UNIX sockets here so we will just work
  693. // with stuff that has host_str().
  694. if let Some(hostname) = peer.host_str() {
  695. // Localhost connections should never enter the blacklist
  696. // This however allows any Tor and Nym connections.
  697. if self.is_local_host(peer.clone()).await {
  698. return
  699. }
  700. self.blacklist.write().await.insert(hostname.to_string());
  701. }
  702. }
  703. /// Unmark a blacklist peer
  704. pub async fn unblacklist(&self, peer: &Url) {
  705. if let Some(hostname) = peer.host_str() {
  706. self.blacklist.write().await.remove(hostname);
  707. }
  708. }
  709. /// Check if the greylist is empty.
  710. pub async fn is_empty_greylist(&self) -> bool {
  711. self.greylist.read().await.is_empty()
  712. }
  713. /// Check if the whitelist is empty.
  714. pub async fn is_empty_whitelist(&self) -> bool {
  715. self.whitelist.read().await.is_empty()
  716. }
  717. /// Check if the anchorlist is empty.
  718. pub async fn is_empty_anchorlist(&self) -> bool {
  719. self.anchorlist.read().await.is_empty()
  720. }
  721. /// Check if the hostlist is empty.
  722. pub async fn is_empty_hostlist(&self) -> bool {
  723. self.is_empty_greylist().await &&
  724. self.is_empty_whitelist().await &&
  725. self.is_empty_anchorlist().await
  726. }
  727. /// Check if host is in the greylist
  728. pub async fn greylist_contains(&self, addr: &Url) -> bool {
  729. self.greylist.read().await.iter().any(|(u, _t)| u == addr)
  730. }
  731. /// Check if host is in the whitelist
  732. pub async fn whitelist_contains(&self, addr: &Url) -> bool {
  733. self.whitelist.read().await.iter().any(|(u, _t)| u == addr)
  734. }
  735. /// Check if host is in the anchorlist
  736. pub async fn anchorlist_contains(&self, addr: &Url) -> bool {
  737. self.anchorlist.read().await.iter().any(|(u, _t)| u == addr)
  738. }
  739. /// Get the index for a given addr on the greylist.
  740. pub async fn get_greylist_index_at_addr(&self, addr: Url) -> Option<usize> {
  741. self.greylist.read().await.iter().position(|a| a.0 == addr)
  742. }
  743. /// Get the index for a given addr on the whitelist.
  744. pub async fn get_whitelist_index_at_addr(&self, addr: Url) -> Option<usize> {
  745. self.whitelist.read().await.iter().position(|a| a.0 == addr)
  746. }
  747. /// Get the index for a given addr on the anchorlist.
  748. pub async fn get_anchorlist_index_at_addr(&self, addr: Url) -> Option<usize> {
  749. self.anchorlist.read().await.iter().position(|a| a.0 == addr)
  750. }
  751. /// Get the entry for a given addr on the whitelist.
  752. pub async fn get_whitelist_entry_at_addr(&self, addr: &Url) -> Option<(Url, u64)> {
  753. self.whitelist
  754. .read()
  755. .await
  756. .iter()
  757. .find(|(url, _)| url == addr)
  758. .map(|(url, time)| (url.clone(), *time))
  759. }
  760. /// Get the entry for a given addr on the anchorlist.
  761. pub async fn get_anchorlist_entry_at_addr(&self, addr: &Url) -> Option<(Url, u64)> {
  762. self.anchorlist
  763. .read()
  764. .await
  765. .iter()
  766. .find(|(url, _)| url == addr)
  767. .map(|(url, time)| (url.clone(), *time))
  768. }
  769. /// Return all known whitelisted hosts
  770. pub async fn whitelist_fetch_all(&self) -> Vec<(Url, u64)> {
  771. self.whitelist.read().await.iter().cloned().collect()
  772. }
  773. /// Return all known greylisted hosts
  774. pub async fn greylist_fetch_all(&self) -> Vec<(Url, u64)> {
  775. self.greylist.read().await.iter().cloned().collect()
  776. }
  777. /// Return all known anchorlisted hosts
  778. pub async fn anchorlist_fetch_all(&self) -> Vec<(Url, u64)> {
  779. self.anchorlist.read().await.iter().cloned().collect()
  780. }
  781. /// Return all greylist and anchorlist hosts. Called on stop().
  782. /// Note: we do not return whitelist entries here since whitelist entries must go via the
  783. /// greylist refinery in the lifetime of the p2p network.
  784. pub async fn hostlist_fetch_safe(&self) -> HashMap<String, Vec<(Url, u64)>> {
  785. let mut hostlist = HashMap::new();
  786. hostlist.insert(
  787. "anchorlist".to_string(),
  788. self.anchorlist.read().await.iter().cloned().collect(),
  789. );
  790. hostlist
  791. .insert("greylist".to_string(), self.greylist.read().await.iter().cloned().collect());
  792. hostlist
  793. }
  794. /// Get up to n random peers from the whitelist.
  795. pub async fn whitelist_fetch_n_random(&self, n: u32) -> Vec<(Url, u64)> {
  796. let n = n as usize;
  797. if n == 0 {
  798. return vec![]
  799. }
  800. let addrs = self.whitelist.read().await;
  801. let urls = addrs.iter().choose_multiple(&mut OsRng, n.min(addrs.len()));
  802. urls.iter().map(|&url| url.clone()).collect()
  803. }
  804. /// Get a random peer from the greylist.
  805. pub async fn greylist_fetch_random(&self) -> ((Url, u64), usize) {
  806. let greylist = self.greylist.read().await;
  807. let position = rand::thread_rng().gen_range(0..greylist.len());
  808. let entry = &greylist[position];
  809. (entry.clone(), position)
  810. }
  811. /// Get a random peer from the whitelist.
  812. pub async fn whitelist_fetch_random(&self) -> ((Url, u64), usize) {
  813. let whitelist = self.whitelist.read().await;
  814. let position = rand::thread_rng().gen_range(0..whitelist.len());
  815. let entry = &whitelist[position];
  816. (entry.clone(), position)
  817. }
  818. /// Get the oldest entry from the whitelist.
  819. pub async fn whitelist_fetch_last(&self) -> ((Url, u64), usize) {
  820. let whitelist = self.whitelist.read().await;
  821. let position = whitelist.len() - 1;
  822. let entry = &whitelist[position];
  823. (entry.clone(), position)
  824. }
  825. /// Get a random greylist peer that matches the given transport schemes.
  826. pub async fn greylist_fetch_random_with_schemes(&self) -> Option<((Url, u64), usize)> {
  827. trace!(target: "store::greylist_fetch_random_with_schemes", "[START]");
  828. // Retrieve all peers corresponding to that transport schemes
  829. let schemes = &self.settings.allowed_transports;
  830. let greylist = self.greylist_fetch_with_schemes(schemes, None).await;
  831. if greylist.is_empty() {
  832. return None
  833. }
  834. let position = rand::thread_rng().gen_range(0..greylist.len());
  835. let entry = &greylist[position];
  836. Some((entry.clone(), position))
  837. }
  838. /// Get up to n random greylist peers. Schemes are not taken into account.
  839. pub async fn greylist_fetch_n_random(&self, n: u32) -> Vec<(Url, u64)> {
  840. trace!(target: "store::greylist_fetch_n_random", "[START]");
  841. let n = n as usize;
  842. if n == 0 {
  843. return vec![]
  844. }
  845. let mut hosts = vec![];
  846. let greylist = self.greylist.read().await;
  847. for (addr, last_seen) in greylist.iter() {
  848. hosts.push((addr.clone(), *last_seen));
  849. }
  850. if hosts.is_empty() {
  851. debug!(target: "store::greylist_fetch_n_random", "No greylist entries found!");
  852. return hosts
  853. }
  854. // Grab random ones
  855. let urls = hosts.iter().choose_multiple(&mut OsRng, n.min(hosts.len()));
  856. urls.iter().map(|&url| url.clone()).collect()
  857. }
  858. /// Get up to n random greylist peers that match the given transport schemes.
  859. pub async fn greylist_fetch_n_random_with_schemes(
  860. &self,
  861. schemes: &[String],
  862. n: u32,
  863. ) -> Vec<(Url, u64)> {
  864. let n = n as usize;
  865. if n == 0 {
  866. return vec![]
  867. }
  868. trace!(target: "store::greylist_fetch_n_random_with_schemes", "[START]");
  869. // Retrieve all peers corresponding to that transport schemes
  870. let hosts = self.greylist_fetch_with_schemes(schemes, None).await;
  871. if hosts.is_empty() {
  872. debug!(target: "store::greylist_fetch_n_random_with_schemes",
  873. "No such schemes found on greylist!");
  874. return hosts
  875. }
  876. // Grab random ones
  877. let urls = hosts.iter().choose_multiple(&mut OsRng, n.min(hosts.len()));
  878. urls.iter().map(|&url| url.clone()).collect()
  879. }
  880. /// Get up to n random whitelist peers that match the given transport schemes.
  881. pub async fn whitelist_fetch_n_random_with_schemes(
  882. &self,
  883. schemes: &[String],
  884. n: u32,
  885. ) -> Vec<(Url, u64)> {
  886. let n = n as usize;
  887. if n == 0 {
  888. return vec![]
  889. }
  890. trace!(target: "store::whitelist_fetch_n_random_with_schemes", "[START]");
  891. // Retrieve all peers corresponding to that transport schemes
  892. let hosts = self.whitelist_fetch_with_schemes(schemes, None).await;
  893. if hosts.is_empty() {
  894. debug!(target: "store::whitelist_fetch_n_random_with_schemes",
  895. "No such schemes found on whitelist!");
  896. return hosts
  897. }
  898. // Grab random ones
  899. let urls = hosts.iter().choose_multiple(&mut OsRng, n.min(hosts.len()));
  900. urls.iter().map(|&url| url.clone()).collect()
  901. }
  902. /// Get up to n random anchorlist peers that match the given transport schemes.
  903. pub async fn anchorlist_fetch_n_random_with_schemes(
  904. &self,
  905. schemes: &[String],
  906. n: u32,
  907. ) -> Vec<(Url, u64)> {
  908. let n = n as usize;
  909. if n == 0 {
  910. return vec![]
  911. }
  912. trace!(target: "store::anchorlist_fetch_n_random_with_schemes", "[START]");
  913. // Retrieve all peers corresponding to that transport schemes
  914. let hosts = self.anchorlist_fetch_with_schemes(schemes, None).await;
  915. if hosts.is_empty() {
  916. debug!(target: "store::anchorlist_fetch_n_random_with_schemes",
  917. "No such schemes found on anchorlist!");
  918. return hosts
  919. }
  920. // Grab random ones
  921. let urls = hosts.iter().choose_multiple(&mut OsRng, n.min(hosts.len()));
  922. urls.iter().map(|&url| url.clone()).collect()
  923. }
  924. /// Get up to limit peers that don't match the given transport schemes from the greylist.
  925. /// If limit was not provided, return all matching peers.
  926. pub async fn greylist_fetch_excluding_schemes(
  927. &self,
  928. schemes: &[String],
  929. limit: Option<usize>,
  930. ) -> Vec<(Url, u64)> {
  931. let greylist = self.greylist.read().await;
  932. let mut limit = match limit {
  933. Some(l) => l.min(greylist.len()),
  934. None => greylist.len(),
  935. };
  936. let mut ret = vec![];
  937. if limit == 0 {
  938. return ret
  939. }
  940. for (addr, last_seen) in greylist.iter() {
  941. if !schemes.contains(&addr.scheme().to_string()) {
  942. ret.push((addr.clone(), *last_seen));
  943. limit -= 1;
  944. if limit == 0 {
  945. return ret
  946. }
  947. }
  948. }
  949. if ret.is_empty() {
  950. debug!(target: "store::greylist_fetch_excluding_schemes",
  951. "No such schemes found on greylist!")
  952. }
  953. ret
  954. }
  955. /// Get up to limit peers that don't match the given transport schemes from the whitelist.
  956. /// If limit was not provided, return all matching peers.
  957. pub async fn whitelist_fetch_excluding_schemes(
  958. &self,
  959. schemes: &[String],
  960. limit: Option<usize>,
  961. ) -> Vec<(Url, u64)> {
  962. let addrs = self.whitelist.read().await;
  963. let mut limit = match limit {
  964. Some(l) => l.min(addrs.len()),
  965. None => addrs.len(),
  966. };
  967. let mut ret = vec![];
  968. if limit == 0 {
  969. return ret
  970. }
  971. for (addr, last_seen) in addrs.iter() {
  972. if !schemes.contains(&addr.scheme().to_string()) {
  973. ret.push((addr.clone(), *last_seen));
  974. limit -= 1;
  975. if limit == 0 {
  976. return ret
  977. }
  978. }
  979. }
  980. if ret.is_empty() {
  981. debug!(target: "store::whiteist_fetch_excluding_schemes",
  982. "No such schemes found on whitelist!")
  983. }
  984. ret
  985. }
  986. /// Get up to n random whitelisted peers that don't match the given transport schemes from the
  987. /// hosts set.
  988. pub async fn whitelist_fetch_n_random_excluding_schemes(
  989. &self,
  990. schemes: &[String],
  991. n: u32,
  992. ) -> Vec<(Url, u64)> {
  993. let n = n as usize;
  994. if n == 0 {
  995. return vec![]
  996. }
  997. trace!(target: "store::whitelist_fetch_excluding_schemes", "[START]");
  998. // Retrieve all peers not corresponding to that transport schemes
  999. let hosts = self.whitelist_fetch_excluding_schemes(schemes, None).await;
  1000. if hosts.is_empty() {
  1001. debug!(target: "store::whitelist_fetch_n_random_excluding_schemes",
  1002. "No such schemes found on whitelist!");
  1003. return hosts
  1004. }
  1005. // Grab random ones
  1006. let urls = hosts.iter().choose_multiple(&mut OsRng, n.min(hosts.len()));
  1007. urls.iter().map(|&url| url.clone()).collect()
  1008. }
  1009. /// Get up to limit peers that match the given transport schemes from the greylist.
  1010. /// If limit was not provided, return all matching peers.
  1011. async fn greylist_fetch_with_schemes(
  1012. &self,
  1013. schemes: &[String],
  1014. limit: Option<usize>,
  1015. ) -> Vec<(Url, u64)> {
  1016. trace!(target: "store::greylist_fetch_with_schemes", "[START]");
  1017. let greylist = self.greylist.read().await;
  1018. let mut limit = match limit {
  1019. Some(l) => l.min(greylist.len()),
  1020. None => greylist.len(),
  1021. };
  1022. let mut ret = vec![];
  1023. if limit == 0 {
  1024. return ret
  1025. }
  1026. for (addr, last_seen) in greylist.iter() {
  1027. if schemes.contains(&addr.scheme().to_string()) {
  1028. ret.push((addr.clone(), *last_seen));
  1029. limit -= 1;
  1030. if limit == 0 {
  1031. debug!(target: "store::greylist_fetch_with_schemes",
  1032. "Found matching scheme, returning {} grey addresses",
  1033. ret.len());
  1034. return ret
  1035. }
  1036. }
  1037. }
  1038. if ret.is_empty() {
  1039. debug!(target: "store::greylist_fetch_with_schemes",
  1040. "No such schemes found on greylist!")
  1041. }
  1042. trace!(target: "store::greylist_fetch_with_schemes", "END");
  1043. ret
  1044. }
  1045. /// Get up to limit peers that match the given transport schemes from the whitelist.
  1046. /// If limit was not provided, return all matching peers.
  1047. async fn whitelist_fetch_with_schemes(
  1048. &self,
  1049. schemes: &[String],
  1050. limit: Option<usize>,
  1051. ) -> Vec<(Url, u64)> {
  1052. trace!(target: "store::whitelist_fetch_with_schemes", "[START]");
  1053. let whitelist = self.whitelist.read().await;
  1054. let mut limit = match limit {
  1055. Some(l) => l.min(whitelist.len()),
  1056. None => whitelist.len(),
  1057. };
  1058. let mut ret = vec![];
  1059. if limit == 0 {
  1060. return ret
  1061. }
  1062. for (addr, last_seen) in whitelist.iter() {
  1063. if schemes.contains(&addr.scheme().to_string()) {
  1064. ret.push((addr.clone(), *last_seen));
  1065. limit -= 1;
  1066. if limit == 0 {
  1067. debug!(target: "store::whitelist_fetch_with_schemes",
  1068. "Found matching scheme, returning {} white addresses",
  1069. ret.len());
  1070. return ret
  1071. }
  1072. }
  1073. }
  1074. if ret.is_empty() {
  1075. debug!(target: "store::whitelist_fetch_with_schemes",
  1076. "No such schemes found on whitelist!")
  1077. }
  1078. trace!(target: "store::whitelist_fetch_with_schemes", "END");
  1079. ret
  1080. }
  1081. /// Get up to limit peers that match the given transport schemes from the anchorlist.
  1082. /// If limit was not provided, return all matching peers.
  1083. async fn anchorlist_fetch_with_schemes(
  1084. &self,
  1085. schemes: &[String],
  1086. limit: Option<usize>,
  1087. ) -> Vec<(Url, u64)> {
  1088. //trace!(target: "store::anchorlist_fetch_with_schemes", "[START]");
  1089. let anchorlist = self.anchorlist.read().await;
  1090. let mut limit = match limit {
  1091. Some(l) => l.min(anchorlist.len()),
  1092. None => anchorlist.len(),
  1093. };
  1094. let mut ret = vec![];
  1095. if limit == 0 {
  1096. return ret
  1097. }
  1098. for (addr, last_seen) in anchorlist.iter() {
  1099. if schemes.contains(&addr.scheme().to_string()) {
  1100. ret.push((addr.clone(), *last_seen));
  1101. limit -= 1;
  1102. if limit == 0 {
  1103. debug!(target: "store::anchorlist_fetch_with_schemes",
  1104. "Found matching scheme, returning {} anchor addresses",
  1105. ret.len());
  1106. return ret
  1107. }
  1108. }
  1109. }
  1110. if ret.is_empty() {
  1111. warn!(target: "store::anchorlist_fetch_with_schemes",
  1112. "No matching schemes found on anchorlist")
  1113. }
  1114. trace!(target: "store::anchorlist_fetch_with_schemes", "END");
  1115. ret
  1116. }
  1117. /// Load the hostlist from a file.
  1118. pub async fn load_hosts(&self) -> Result<()> {
  1119. let path = expand_path(&self.settings.hostlist)?;
  1120. if !path.exists() {
  1121. if let Some(parent) = path.parent() {
  1122. fs::create_dir_all(parent)?;
  1123. }
  1124. File::create(path.clone())?;
  1125. }
  1126. let contents = load_file(&path);
  1127. if let Err(e) = contents {
  1128. warn!(target: "store", "Failed retrieving saved hosts: {}", e);
  1129. return Ok(())
  1130. }
  1131. for line in contents.unwrap().lines() {
  1132. let data: Vec<&str> = line.split('\t').collect();
  1133. let url = match Url::parse(data[1]) {
  1134. Ok(u) => u,
  1135. Err(e) => {
  1136. debug!(target: "store", "load_hosts(): Skipping malformed URL {}", e);
  1137. continue
  1138. }
  1139. };
  1140. let last_seen = match data[2].parse::<u64>() {
  1141. Ok(t) => t,
  1142. Err(e) => {
  1143. debug!(target: "store", "load_hosts(): Skipping malformed last seen {}", e);
  1144. continue
  1145. }
  1146. };
  1147. match data[0] {
  1148. "greylist" => {
  1149. self.greylist_store(url, last_seen).await;
  1150. }
  1151. "whitelist" => {
  1152. self.whitelist_store(url, last_seen).await;
  1153. }
  1154. "anchorlist" => {
  1155. self.anchorlist_store(url, last_seen).await;
  1156. }
  1157. _ => {
  1158. debug!(target: "store", "load_hosts(): Malformed list name...");
  1159. }
  1160. }
  1161. }
  1162. Ok(())
  1163. }
  1164. /// Save the hostlist to a file. Whitelist gets written to the greylist to force
  1165. /// whitelist entries through the refinery on start.
  1166. pub async fn save_hosts(&self) -> Result<()> {
  1167. let path = expand_path(&self.settings.hostlist)?;
  1168. let mut tsv = String::new();
  1169. let mut whitelist = vec![];
  1170. // First gather all the whitelist entries we don't have in greylist.
  1171. for (url, last_seen) in self.whitelist_fetch_all().await {
  1172. if !self.greylist_contains(&url).await {
  1173. whitelist.push((url, last_seen))
  1174. }
  1175. }
  1176. // Collect the greylist and anchorlist entries, and append any whitelist entries to the
  1177. // greylist before saving.
  1178. for (name, mut list) in self.hostlist_fetch_safe().await {
  1179. if name == *"greylist".to_string() {
  1180. list.append(&mut whitelist)
  1181. }
  1182. for (url, last_seen) in list {
  1183. tsv.push_str(&format!("{}\t{}\t{}\n", name, url, last_seen));
  1184. }
  1185. }
  1186. if !tsv.eq("") {
  1187. info!(target: "store", "Saving hosts to: {:?}",
  1188. path);
  1189. if let Err(e) = save_file(&path, &tsv) {
  1190. error!(target: "store", "Failed saving hosts: {}", e);
  1191. }
  1192. }
  1193. Ok(())
  1194. }
  1195. }
  1196. #[cfg(test)]
  1197. mod tests {
  1198. use super::{
  1199. super::super::{settings::Settings, P2p},
  1200. *,
  1201. };
  1202. use crate::{net::hosts::refinery::ping_node, system::sleep};
  1203. use smol::Executor;
  1204. use std::{sync::Arc, time::UNIX_EPOCH};
  1205. #[test]
  1206. fn test_ping_node() {
  1207. smol::block_on(async {
  1208. let settings = Settings {
  1209. localnet: false,
  1210. external_addrs: vec![
  1211. Url::parse("tcp://foo.bar:123").unwrap(),
  1212. Url::parse("tcp://lol.cat:321").unwrap(),
  1213. ],
  1214. ..Default::default()
  1215. };
  1216. let ex = Arc::new(Executor::new());
  1217. let p2p = P2p::new(settings, ex.clone()).await;
  1218. let url = Url::parse("tcp://xeno.systems.wtf").unwrap();
  1219. println!("Pinging node...");
  1220. let task = ex.spawn(ping_node(url.clone(), p2p));
  1221. ex.run(task).await;
  1222. println!("Ping node complete!");
  1223. });
  1224. }
  1225. #[test]
  1226. fn test_is_local_host() {
  1227. smol::block_on(async {
  1228. let settings = Settings {
  1229. localnet: false,
  1230. external_addrs: vec![
  1231. Url::parse("tcp://foo.bar:123").unwrap(),
  1232. Url::parse("tcp://lol.cat:321").unwrap(),
  1233. ],
  1234. ..Default::default()
  1235. };
  1236. let hosts = Hosts::new(Arc::new(settings.clone()));
  1237. let local_hosts: Vec<Url> = vec![
  1238. Url::parse("tcp://localhost").unwrap(),
  1239. Url::parse("tcp://127.0.0.1").unwrap(),
  1240. Url::parse("tcp+tls://[::1]").unwrap(),
  1241. Url::parse("tcp://localhost.localdomain").unwrap(),
  1242. Url::parse("tcp://192.168.10.65").unwrap(),
  1243. ];
  1244. for host in local_hosts {
  1245. eprintln!("{}", host);
  1246. assert!(hosts.is_local_host(host).await);
  1247. }
  1248. let remote_hosts: Vec<Url> = vec![
  1249. Url::parse("https://dyne.org").unwrap(),
  1250. Url::parse("tcp://77.168.10.65:2222").unwrap(),
  1251. Url::parse("tcp://[2345:0425:2CA1:0000:0000:0567:5673:23b5]").unwrap(),
  1252. Url::parse("http://eweiibe6tdjsdprb4px6rqrzzcsi22m4koia44kc5pcjr7nec2rlxyad.onion")
  1253. .unwrap(),
  1254. ];
  1255. for host in remote_hosts {
  1256. assert!(!hosts.is_local_host(host).await)
  1257. }
  1258. });
  1259. }
  1260. #[test]
  1261. fn test_greylist_store() {
  1262. let last_seen = UNIX_EPOCH.elapsed().unwrap().as_secs();
  1263. smol::block_on(async {
  1264. let settings = Settings {
  1265. localnet: false,
  1266. external_addrs: vec![
  1267. Url::parse("tcp://foo.bar:123").unwrap(),
  1268. Url::parse("tcp://lol.cat:321").unwrap(),
  1269. ],
  1270. ..Default::default()
  1271. };
  1272. let hosts = Hosts::new(Arc::new(settings.clone()));
  1273. for addr in settings.external_addrs {
  1274. hosts.greylist_store(addr, last_seen).await;
  1275. }
  1276. assert!(!hosts.is_empty_greylist().await);
  1277. let local_hosts = vec![
  1278. Url::parse("tcp://localhost:3921").unwrap(),
  1279. Url::parse("tor://[::1]:21481").unwrap(),
  1280. Url::parse("tcp://192.168.10.65:311").unwrap(),
  1281. Url::parse("tcp+tls://0.0.0.0:2312").unwrap(),
  1282. Url::parse("tcp://255.255.255.255:2131").unwrap(),
  1283. ];
  1284. for host in &local_hosts {
  1285. hosts.greylist_store(host.clone(), last_seen).await;
  1286. }
  1287. assert!(!hosts.is_empty_greylist().await);
  1288. let remote_hosts = vec![
  1289. Url::parse("tcp://dark.fi:80").unwrap(),
  1290. Url::parse("tcp://http.cat:401").unwrap(),
  1291. Url::parse("tcp://foo.bar:111").unwrap(),
  1292. ];
  1293. for host in &remote_hosts {
  1294. hosts.greylist_store(host.clone(), last_seen).await;
  1295. }
  1296. assert!(hosts.greylist_contains(&remote_hosts[0]).await);
  1297. assert!(hosts.greylist_contains(&remote_hosts[1]).await);
  1298. assert!(hosts.greylist_contains(&remote_hosts[2]).await);
  1299. });
  1300. }
  1301. #[test]
  1302. fn test_whitelist_store() {
  1303. smol::block_on(async {
  1304. let settings = Settings {
  1305. localnet: false,
  1306. external_addrs: vec![
  1307. Url::parse("tcp://foo.bar:123").unwrap(),
  1308. Url::parse("tcp://lol.cat:321").unwrap(),
  1309. ],
  1310. ..Default::default()
  1311. };
  1312. let hosts = Hosts::new(Arc::new(settings.clone()));
  1313. assert!(hosts.is_empty_whitelist().await);
  1314. let url = Url::parse("tcp://dark.renaissance:333").unwrap();
  1315. let last_seen = UNIX_EPOCH.elapsed().unwrap().as_secs();
  1316. hosts.whitelist_store(url.clone(), last_seen).await;
  1317. assert!(!hosts.is_empty_whitelist().await);
  1318. assert!(hosts.whitelist_contains(&url).await);
  1319. });
  1320. }
  1321. #[test]
  1322. fn test_whitelist_get_last() {
  1323. smol::block_on(async {
  1324. let settings = Settings {
  1325. localnet: false,
  1326. external_addrs: vec![
  1327. Url::parse("tcp://foo.bar:123").unwrap(),
  1328. Url::parse("tcp://lol.cat:321").unwrap(),
  1329. ],
  1330. ..Default::default()
  1331. };
  1332. let hosts = Hosts::new(Arc::new(settings.clone()));
  1333. // Build up a hostlist
  1334. for i in 0..10 {
  1335. sleep(1).await;
  1336. let last_seen = UNIX_EPOCH.elapsed().unwrap().as_secs();
  1337. let url = Url::parse(&format!("tcp://whitelist{}:123", i)).unwrap();
  1338. hosts.whitelist_store(url.clone(), last_seen).await;
  1339. }
  1340. for (url, last_seen) in hosts.whitelist.read().await.iter() {
  1341. println!("{} {}", url, last_seen);
  1342. }
  1343. let (entry, _position) = hosts.whitelist_fetch_last().await;
  1344. println!("last entry: {} {}", entry.0, entry.1);
  1345. });
  1346. }
  1347. #[test]
  1348. fn test_hostlist_get_entry() {
  1349. smol::block_on(async {
  1350. let settings = Settings {
  1351. localnet: false,
  1352. external_addrs: vec![
  1353. Url::parse("tcp://foo.bar:123").unwrap(),
  1354. Url::parse("tcp://lol.cat:321").unwrap(),
  1355. ],
  1356. ..Default::default()
  1357. };
  1358. let hosts = Hosts::new(Arc::new(settings.clone()));
  1359. let url = Url::parse("tcp://dark.renaissance:333").unwrap();
  1360. let last_seen = UNIX_EPOCH.elapsed().unwrap().as_secs();
  1361. hosts.whitelist_store(url.clone(), last_seen).await;
  1362. hosts.anchorlist_store(url.clone(), last_seen).await;
  1363. assert!(hosts.get_whitelist_entry_at_addr(&url).await.is_some());
  1364. assert!(hosts.get_anchorlist_entry_at_addr(&url).await.is_some());
  1365. });
  1366. }
  1367. #[test]
  1368. fn test_remove() {
  1369. smol::block_on(async {
  1370. let settings = Settings {
  1371. outbound_connections: 8,
  1372. allowed_transports: vec!["tcp".to_string()],
  1373. ..Default::default()
  1374. };
  1375. let hosts = Hosts::new(Arc::new(settings.clone()));
  1376. let url = Url::parse("tcp://dark.renaissance:333").unwrap();
  1377. let last_seen = UNIX_EPOCH.elapsed().unwrap().as_secs();
  1378. hosts.whitelist_store(url.clone(), last_seen).await;
  1379. sleep(1).await;
  1380. let url = Url::parse("tcp://milady:333").unwrap();
  1381. let last_seen = UNIX_EPOCH.elapsed().unwrap().as_secs();
  1382. hosts.whitelist_store(url.clone(), last_seen).await;
  1383. sleep(1).await;
  1384. let url = Url::parse("tcp://king-ted:333").unwrap();
  1385. let last_seen = UNIX_EPOCH.elapsed().unwrap().as_secs();
  1386. hosts.whitelist_store(url.clone(), last_seen).await;
  1387. for (url, last_seen) in hosts.whitelist.read().await.iter() {
  1388. println!("{}, {}", url, last_seen);
  1389. }
  1390. let position = hosts.get_whitelist_index_at_addr(url.clone()).await.unwrap();
  1391. hosts.whitelist_remove(&url, position).await;
  1392. for (url, last_seen) in hosts.whitelist.read().await.iter() {
  1393. println!("{}, {}", url, last_seen);
  1394. }
  1395. });
  1396. }
  1397. #[test]
  1398. fn test_fetch_address() {
  1399. smol::block_on(async {
  1400. let mut hostlist = vec![];
  1401. let mut grey_urls = vec![];
  1402. let mut white_urls = vec![];
  1403. let mut anchor_urls = vec![];
  1404. let ex = Arc::new(Executor::new());
  1405. let settings = Settings {
  1406. outbound_connections: 8,
  1407. allowed_transports: vec!["tcp".to_string()],
  1408. ..Default::default()
  1409. };
  1410. let p2p = P2p::new(settings, ex.clone()).await;
  1411. let hosts = p2p.hosts();
  1412. // Build up a hostlist
  1413. for i in 0..5 {
  1414. let last_seen = UNIX_EPOCH.elapsed().unwrap().as_secs();
  1415. hosts
  1416. .anchorlist_store(
  1417. Url::parse(&format!("tcp://anchorlist{}:123", i)).unwrap(),
  1418. last_seen,
  1419. )
  1420. .await;
  1421. hosts
  1422. .whitelist_store(
  1423. Url::parse(&format!("tcp://whitelist{}:123", i)).unwrap(),
  1424. last_seen,
  1425. )
  1426. .await;
  1427. hosts
  1428. .greylist_store(
  1429. Url::parse(&format!("tcp://greylist{}:123", i)).unwrap(),
  1430. last_seen,
  1431. )
  1432. .await;
  1433. grey_urls
  1434. .push((Url::parse(&format!("tcp://greylist{}:123", i)).unwrap(), last_seen));
  1435. white_urls
  1436. .push((Url::parse(&format!("tcp://whitelist{}:123", i)).unwrap(), last_seen));
  1437. anchor_urls
  1438. .push((Url::parse(&format!("tcp://anchorlist{}:123", i)).unwrap(), last_seen));
  1439. }
  1440. assert!(!hosts.is_empty_anchorlist().await);
  1441. assert!(!hosts.is_empty_whitelist().await);
  1442. assert!(!hosts.is_empty_greylist().await);
  1443. let transports = &p2p.settings().allowed_transports;
  1444. let white_count =
  1445. p2p.settings().outbound_connections * p2p.settings().white_connection_percent / 100;
  1446. // Simulate the address selection logic found in outbound_session::fetch_address()
  1447. for i in 0..8 {
  1448. if i < p2p.settings().anchor_connection_count {
  1449. if !hosts.anchorlist_fetch_address(transports).await.is_empty() {
  1450. let addrs = hosts.anchorlist_fetch_address(transports).await;
  1451. hostlist.push(addrs);
  1452. }
  1453. if !hosts.whitelist_fetch_address(transports).await.is_empty() {
  1454. let addrs = hosts.whitelist_fetch_address(transports).await;
  1455. hostlist.push(addrs);
  1456. }
  1457. if !hosts.greylist_fetch_address(transports).await.is_empty() {
  1458. let addrs = hosts.greylist_fetch_address(transports).await;
  1459. hostlist.push(addrs);
  1460. }
  1461. } else if i < white_count {
  1462. if !hosts.whitelist_fetch_address(transports).await.is_empty() {
  1463. let addrs = hosts.whitelist_fetch_address(transports).await;
  1464. hostlist.push(addrs);
  1465. }
  1466. if !hosts.greylist_fetch_address(transports).await.is_empty() {
  1467. let addrs = hosts.greylist_fetch_address(transports).await;
  1468. hostlist.push(addrs);
  1469. }
  1470. } else if !hosts.greylist_fetch_address(transports).await.is_empty() {
  1471. let addrs = hosts.greylist_fetch_address(transports).await;
  1472. hostlist.push(addrs);
  1473. }
  1474. }
  1475. //// Check we're returning the correct addresses.
  1476. anchor_urls.sort();
  1477. white_urls.sort();
  1478. grey_urls.sort();
  1479. hostlist[0].sort();
  1480. hostlist[4].sort();
  1481. hostlist[7].sort();
  1482. assert!(anchor_urls == hostlist[0]);
  1483. assert!(white_urls == hostlist[4]);
  1484. assert!(grey_urls == hostlist[7]);
  1485. })
  1486. }
  1487. }