p2p.rs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2023 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,
  21. };
  22. use async_std::sync::{Arc, Mutex};
  23. use futures::{select, stream::FuturesUnordered, try_join, FutureExt, StreamExt, TryFutureExt};
  24. use log::{debug, error, warn};
  25. use rand::Rng;
  26. use serde_json::json;
  27. use smol::Executor;
  28. use url::Url;
  29. use crate::{
  30. system::{Subscriber, SubscriberPtr, Subscription},
  31. util::async_util::sleep,
  32. Result,
  33. };
  34. use super::{
  35. message::Message,
  36. protocol::{register_default_protocols, ProtocolRegistry},
  37. session::{InboundSession, ManualSession, OutboundSession, SeedSyncSession, Session},
  38. Channel, ChannelPtr, Hosts, HostsPtr, Settings, SettingsPtr,
  39. };
  40. /// List of channels that are awaiting connection.
  41. pub type PendingChannels = Mutex<HashSet<Url>>;
  42. /// List of connected channels.
  43. pub type ConnectedChannels = Mutex<HashMap<Url, Arc<Channel>>>;
  44. /// Atomic pointer to p2p interface.
  45. pub type P2pPtr = Arc<P2p>;
  46. enum P2pState {
  47. // The p2p object has been created but not yet started.
  48. Open,
  49. // We are performing the initial seed session
  50. Start,
  51. // Seed session finished, but not yet running
  52. Started,
  53. // p2p is running and the network is active.
  54. Run,
  55. }
  56. impl fmt::Display for P2pState {
  57. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  58. write!(
  59. f,
  60. "{}",
  61. match self {
  62. Self::Open => "open",
  63. Self::Start => "start",
  64. Self::Started => "started",
  65. Self::Run => "run",
  66. }
  67. )
  68. }
  69. }
  70. /// Top level peer-to-peer networking interface.
  71. pub struct P2p {
  72. pending: PendingChannels,
  73. channels: ConnectedChannels,
  74. channel_subscriber: SubscriberPtr<Result<ChannelPtr>>,
  75. // Used both internally and externally
  76. stop_subscriber: SubscriberPtr<()>,
  77. hosts: HostsPtr,
  78. protocol_registry: ProtocolRegistry,
  79. // We keep a reference to the sessions used for get info
  80. session_manual: Mutex<Option<Arc<ManualSession>>>,
  81. session_inbound: Mutex<Option<Arc<InboundSession>>>,
  82. session_outbound: Mutex<Option<Arc<OutboundSession>>>,
  83. state: Mutex<P2pState>,
  84. settings: SettingsPtr,
  85. /// Flag to check if on discovery mode
  86. discovery: Mutex<bool>,
  87. }
  88. impl P2p {
  89. /// Initialize a new p2p network.
  90. ///
  91. /// Initializes all sessions and protocols. Adds the protocols to the protocol registry, along
  92. /// with a bitflag session selector that includes or excludes sessions from seed, version, and
  93. /// address protocols.
  94. ///
  95. /// Creates a weak pointer to self that is used by all sessions to access the p2p parent class.
  96. pub async fn new(settings: Settings) -> Arc<Self> {
  97. let settings = Arc::new(settings);
  98. let self_ = Arc::new(Self {
  99. pending: Mutex::new(HashSet::new()),
  100. channels: Mutex::new(HashMap::new()),
  101. channel_subscriber: Subscriber::new(),
  102. stop_subscriber: Subscriber::new(),
  103. hosts: Hosts::new(settings.localnet),
  104. protocol_registry: ProtocolRegistry::new(),
  105. session_manual: Mutex::new(None),
  106. session_inbound: Mutex::new(None),
  107. session_outbound: Mutex::new(None),
  108. state: Mutex::new(P2pState::Open),
  109. settings,
  110. discovery: Mutex::new(false),
  111. });
  112. let parent = Arc::downgrade(&self_);
  113. *self_.session_manual.lock().await = Some(ManualSession::new(parent.clone()));
  114. *self_.session_inbound.lock().await = Some(InboundSession::new(parent.clone()).await);
  115. *self_.session_outbound.lock().await = Some(OutboundSession::new(parent));
  116. register_default_protocols(self_.clone()).await;
  117. self_
  118. }
  119. // ANCHOR: get_info
  120. pub async fn get_info(&self) -> serde_json::Value {
  121. // Building ext_addr_vec string
  122. let mut ext_addr_vec = vec![];
  123. for ext_addr in &self.settings.external_addr {
  124. ext_addr_vec.push(ext_addr.as_ref().to_string());
  125. }
  126. json!({
  127. "external_addr": format!("{:?}", ext_addr_vec),
  128. "session_manual": self.session_manual().await.get_info().await,
  129. "session_inbound": self.session_inbound().await.get_info().await,
  130. "session_outbound": self.session_outbound().await.get_info().await,
  131. "state": self.state.lock().await.to_string(),
  132. })
  133. }
  134. // ANCHOR_END: get_info
  135. /// Invoke startup and seeding sequence. Call from constructing thread.
  136. // ANCHOR: start
  137. pub async fn start(self: Arc<Self>, executor: Arc<Executor<'_>>) -> Result<()> {
  138. debug!(target: "net::p2p::start()", "P2p::start() [BEGIN]");
  139. *self.state.lock().await = P2pState::Start;
  140. // Start seed session
  141. let seed = SeedSyncSession::new(Arc::downgrade(&self));
  142. // This will block until all seed queries have finished
  143. seed.start(executor.clone()).await?;
  144. *self.state.lock().await = P2pState::Started;
  145. debug!(target: "net::p2p::start()", "P2p::start() [END]");
  146. Ok(())
  147. }
  148. // ANCHOR_END: start
  149. pub async fn session_manual(&self) -> Arc<ManualSession> {
  150. self.session_manual.lock().await.as_ref().unwrap().clone()
  151. }
  152. pub async fn session_inbound(&self) -> Arc<InboundSession> {
  153. self.session_inbound.lock().await.as_ref().unwrap().clone()
  154. }
  155. pub async fn session_outbound(&self) -> Arc<OutboundSession> {
  156. self.session_outbound.lock().await.as_ref().unwrap().clone()
  157. }
  158. /// Runs the network. Starts inbound, outbound and manual sessions.
  159. /// Waits for a stop signal and stops the network if received.
  160. // ANCHOR: run
  161. pub async fn run(self: Arc<Self>, executor: Arc<Executor<'_>>) -> Result<()> {
  162. debug!(target: "net::p2p::run()", "P2p::run() [BEGIN]");
  163. *self.state.lock().await = P2pState::Run;
  164. let manual = self.session_manual().await;
  165. for peer in &self.settings.peers {
  166. manual.clone().connect(peer, executor.clone()).await;
  167. }
  168. let inbound = self.session_inbound().await;
  169. inbound.clone().start(executor.clone()).await?;
  170. let outbound = self.session_outbound().await;
  171. outbound.clone().start(executor.clone()).await?;
  172. let stop_sub = self.subscribe_stop().await;
  173. // Wait for stop signal
  174. stop_sub.receive().await;
  175. // Stop the sessions
  176. manual.stop().await;
  177. inbound.stop().await;
  178. outbound.stop().await;
  179. debug!(target: "net::p2p::run()", "P2p::run() [END]");
  180. Ok(())
  181. }
  182. // ANCHOR_END: run
  183. /// Wait for outbound connections to be established.
  184. pub async fn wait_for_outbound(self: Arc<Self>, executor: Arc<Executor<'_>>) -> Result<()> {
  185. debug!(target: "net::p2p::wait_for_outbound()", "P2p::wait_for_outbound() [BEGIN]");
  186. // To verify that the network needs initialization, we check if we have seeds or peers configured,
  187. // and have configured outbound slots.
  188. if !(self.settings.seeds.is_empty() && self.settings.peers.is_empty()) &&
  189. self.settings.outbound_connections > 0
  190. {
  191. debug!(target: "net::p2p::wait_for_outbound()", "P2p::wait_for_outbound(): seeds are configured, waiting for outbound initialization...");
  192. // Retrieve P2P network settings;
  193. let settings = self.settings();
  194. // Retrieve our own inbound addresses
  195. let self_inbound_addr = &settings.external_addr;
  196. // Retrieve timeout config
  197. let timeout = settings.connect_timeout_seconds as u64;
  198. // Retrieve outbound addresses to connect to (including manual peers)
  199. let peers = &settings.peers;
  200. let outbound = &self.hosts().load_all().await;
  201. // Enable manual channel subscriber notifications
  202. self.session_manual().await.clone().enable_notify().await;
  203. // Retrieve manual channel subscriber ptr
  204. let manual_sub =
  205. self.session_manual.lock().await.as_ref().unwrap().subscribe_channel().await;
  206. // Enable outbound channel subscriber notifications
  207. self.session_outbound().await.clone().enable_notify().await;
  208. // Retrieve outbound channel subscriber ptr
  209. let outbound_sub =
  210. self.session_outbound.lock().await.as_ref().unwrap().subscribe_channel().await;
  211. // Create tasks for peers and outbound
  212. let peers_task = Self::outbound_addr_loop(
  213. self_inbound_addr,
  214. timeout,
  215. self.subscribe_stop().await,
  216. peers,
  217. manual_sub,
  218. executor.clone(),
  219. );
  220. let outbound_task = Self::outbound_addr_loop(
  221. self_inbound_addr,
  222. timeout,
  223. self.subscribe_stop().await,
  224. outbound,
  225. outbound_sub,
  226. executor,
  227. );
  228. // Wait for both tasks completion
  229. try_join!(peers_task, outbound_task)?;
  230. // Disable manual channel subscriber notifications
  231. self.session_manual().await.disable_notify().await;
  232. // Disable outbound channel subscriber notifications
  233. self.session_outbound().await.disable_notify().await;
  234. }
  235. debug!(target: "net::p2p::wait_for_outbound()", "P2p::wait_for_outbound() [END]");
  236. Ok(())
  237. }
  238. // Wait for the process for each of the provided addresses, excluding our own inbound addresses
  239. async fn outbound_addr_loop(
  240. self_inbound_addr: &[Url],
  241. timeout: u64,
  242. stop_sub: Subscription<()>,
  243. addrs: &Vec<Url>,
  244. subscriber: Subscription<Result<ChannelPtr>>,
  245. executor: Arc<Executor<'_>>,
  246. ) -> Result<()> {
  247. // Process addresses
  248. for addr in addrs {
  249. if self_inbound_addr.contains(addr) {
  250. continue
  251. }
  252. // Wait for address to be processed.
  253. // We use a timeout to eliminate the following cases:
  254. // 1. Network timeout
  255. // 2. Thread reaching the receiver after peer has signal it
  256. let (timeout_s, timeout_r) = smol::channel::unbounded::<()>();
  257. executor
  258. .spawn(async move {
  259. sleep(timeout).await;
  260. timeout_s.send(()).await.unwrap_or(());
  261. })
  262. .detach();
  263. select! {
  264. msg = subscriber.receive().fuse() => {
  265. if let Err(e) = msg {
  266. warn!(
  267. target: "net::p2p::outbound_addr_loop()",
  268. "P2p::wait_for_outbound(): Outbound connection failed [{}]: {}",
  269. addr, e
  270. );
  271. }
  272. },
  273. _ = stop_sub.receive().fuse() => debug!(target: "net::p2p::outbound_addr_loop()", "P2p::wait_for_outbound(): stop signal received!"),
  274. _ = timeout_r.recv().fuse() => {
  275. warn!(target: "net::p2p::outbound_addr_loop()", "P2p::wait_for_outbound(): Timeout on outbound connection: {}", addr);
  276. continue
  277. },
  278. }
  279. }
  280. Ok(())
  281. }
  282. // ANCHOR: stop
  283. pub async fn stop(&self) {
  284. self.stop_subscriber.notify(()).await
  285. }
  286. // ANCHOR_END: stop
  287. /// Broadcasts a message concurrently across all channels.
  288. // ANCHOR: broadcast
  289. pub async fn broadcast<M: Message + Clone>(&self, message: M) -> Result<()> {
  290. let chans = self.channels.lock().await;
  291. let iter = chans.values();
  292. let mut futures = FuturesUnordered::new();
  293. for channel in iter {
  294. futures.push(channel.send(message.clone()).map_err(|e| {
  295. format!(
  296. "P2P::broadcast: Broadcasting message to {} failed: {}",
  297. channel.address(),
  298. e
  299. )
  300. }));
  301. }
  302. if futures.is_empty() {
  303. error!(target: "net::p2p::broadcast()", "P2P::broadcast: No connected channels found");
  304. return Ok(())
  305. }
  306. while let Some(entry) = futures.next().await {
  307. if let Err(e) = entry {
  308. error!(target: "net::p2p::broadcast()", "{}", e);
  309. }
  310. }
  311. Ok(())
  312. }
  313. // ANCHOR_END: broadcast
  314. /// Broadcasts a message concurrently across all channels.
  315. /// Excludes channels provided in `exclude_list`.
  316. pub async fn broadcast_with_exclude<M: Message + Clone>(
  317. &self,
  318. message: M,
  319. exclude_list: &[Url],
  320. ) -> Result<()> {
  321. let chans = self.channels.lock().await;
  322. let iter = chans.values();
  323. let mut futures = FuturesUnordered::new();
  324. for channel in iter {
  325. if !exclude_list.contains(&channel.address()) {
  326. futures.push(channel.send(message.clone()).map_err(|e| {
  327. format!(
  328. "P2P::broadcast_with_exclude: Broadcasting message to {} failed: {}",
  329. channel.address(),
  330. e
  331. )
  332. }));
  333. }
  334. }
  335. if futures.is_empty() {
  336. error!(target: "net::p2p::broadcast_with_exclude()", "P2P::broadcast_with_exclude: No connected channels found");
  337. return Ok(())
  338. }
  339. while let Some(entry) = futures.next().await {
  340. if let Err(e) = entry {
  341. error!(target: "net::p2p::broadcast_with_exclude()", "{}", e);
  342. }
  343. }
  344. Ok(())
  345. }
  346. /// Add channel address to the list of connected channels.
  347. pub async fn store(&self, channel: ChannelPtr) {
  348. self.channels.lock().await.insert(channel.address(), channel.clone());
  349. self.channel_subscriber.notify(Ok(channel)).await;
  350. }
  351. /// Remove a channel from the list of connected channels.
  352. pub async fn remove(&self, channel: ChannelPtr) {
  353. self.channels.lock().await.remove(&channel.address());
  354. }
  355. /// Check whether a channel is stored in the list of connected channels.
  356. /// If key is not contained, we also check if we are connected with a different transport.
  357. pub async fn exists(&self, addr: &Url) -> Result<bool> {
  358. let channels = self.channels.lock().await;
  359. if channels.contains_key(addr) {
  360. return Ok(true)
  361. }
  362. let mut addr = addr.clone();
  363. for transport in &self.settings.outbound_transports {
  364. addr.set_scheme(&transport.to_scheme())?;
  365. if channels.contains_key(&addr) {
  366. return Ok(true)
  367. }
  368. }
  369. Ok(false)
  370. }
  371. /// Add a channel to the list of pending channels.
  372. pub async fn add_pending(&self, addr: Url) -> bool {
  373. self.pending.lock().await.insert(addr)
  374. }
  375. /// Remove a channel from the list of pending channels.
  376. pub async fn remove_pending(&self, addr: &Url) {
  377. self.pending.lock().await.remove(addr);
  378. }
  379. /// Return the number of connected channels.
  380. pub async fn connections_count(&self) -> usize {
  381. self.channels.lock().await.len()
  382. }
  383. /// Return an atomic pointer to the default network settings.
  384. pub fn settings(&self) -> SettingsPtr {
  385. self.settings.clone()
  386. }
  387. /// Return an atomic pointer to the list of hosts.
  388. pub fn hosts(&self) -> HostsPtr {
  389. self.hosts.clone()
  390. }
  391. pub fn protocol_registry(&self) -> &ProtocolRegistry {
  392. &self.protocol_registry
  393. }
  394. /// Subscribe to a channel.
  395. pub async fn subscribe_channel(&self) -> Subscription<Result<ChannelPtr>> {
  396. self.channel_subscriber.clone().subscribe().await
  397. }
  398. /// Subscribe to a stop signal.
  399. pub async fn subscribe_stop(&self) -> Subscription<()> {
  400. self.stop_subscriber.clone().subscribe().await
  401. }
  402. /// Retrieve channels
  403. pub fn channels(&self) -> &ConnectedChannels {
  404. &self.channels
  405. }
  406. /// Try to start discovery mode.
  407. /// Returns false if already on discovery mode.
  408. pub async fn start_discovery(self: Arc<Self>) -> bool {
  409. if *self.discovery.lock().await {
  410. return false
  411. }
  412. *self.discovery.lock().await = true;
  413. true
  414. }
  415. /// Stops discovery mode.
  416. pub async fn stop_discovery(self: Arc<Self>) {
  417. *self.discovery.lock().await = false;
  418. }
  419. /// Retrieves a random connected channel, exluding seeds
  420. pub async fn random_channel(self: Arc<Self>) -> Option<Arc<Channel>> {
  421. let mut channels_map = self.channels().lock().await.clone();
  422. channels_map.retain(|c, _| !self.settings.seeds.contains(c));
  423. let mut values = channels_map.values();
  424. if values.len() == 0 {
  425. return None
  426. }
  427. Some(values.nth(rand::thread_rng().gen_range(0..values.len())).unwrap().clone())
  428. }
  429. }