p2p.rs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. use async_std::sync::{Arc, Mutex};
  2. use std::fmt;
  3. use async_executor::Executor;
  4. use fxhash::{FxHashMap, FxHashSet};
  5. use log::debug;
  6. use serde_json::json;
  7. use url::Url;
  8. use crate::{
  9. system::{Subscriber, SubscriberPtr, Subscription},
  10. Result,
  11. };
  12. use super::{
  13. message::Message,
  14. protocol::{register_default_protocols, ProtocolRegistry},
  15. session::{InboundSession, ManualSession, OutboundSession, SeedSyncSession, Session},
  16. Channel, ChannelPtr, Hosts, HostsPtr, Settings, SettingsPtr,
  17. };
  18. /// List of channels that are awaiting connection.
  19. pub type PendingChannels = Mutex<FxHashSet<Url>>;
  20. /// List of connected channels.
  21. pub type ConnectedChannels = Mutex<fxhash::FxHashMap<Url, Arc<Channel>>>;
  22. /// Atomic pointer to p2p interface.
  23. pub type P2pPtr = Arc<P2p>;
  24. enum P2pState {
  25. // The p2p object has been created but not yet started.
  26. Open,
  27. // We are performing the initial seed session
  28. Start,
  29. // Seed session finished, but not yet running
  30. Started,
  31. // p2p is running and the network is active.
  32. Run,
  33. }
  34. impl fmt::Display for P2pState {
  35. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  36. write!(
  37. f,
  38. "{}",
  39. match self {
  40. Self::Open => "open",
  41. Self::Start => "start",
  42. Self::Started => "started",
  43. Self::Run => "run",
  44. }
  45. )
  46. }
  47. }
  48. /// Top level peer-to-peer networking interface.
  49. pub struct P2p {
  50. pending: PendingChannels,
  51. channels: ConnectedChannels,
  52. channel_subscriber: SubscriberPtr<Result<ChannelPtr>>,
  53. // Used both internally and externally
  54. stop_subscriber: SubscriberPtr<()>,
  55. hosts: HostsPtr,
  56. protocol_registry: ProtocolRegistry,
  57. // We keep a reference to the sessions used for get info
  58. session_manual: Mutex<Option<Arc<ManualSession>>>,
  59. session_inbound: Mutex<Option<Arc<InboundSession>>>,
  60. session_outbound: Mutex<Option<Arc<OutboundSession>>>,
  61. state: Mutex<P2pState>,
  62. settings: SettingsPtr,
  63. }
  64. impl P2p {
  65. /// Initialize a new p2p network.
  66. ///
  67. /// Initializes all sessions and protocols. Adds the protocols to the protocol registry, along
  68. /// with a bitflag session selector that includes or excludes sessions from seed, version, and
  69. /// address protocols.
  70. ///
  71. /// Creates a weak pointer to self that is used by all sessions to access the p2p parent class.
  72. pub async fn new(settings: Settings) -> Arc<Self> {
  73. let settings = Arc::new(settings);
  74. let self_ = Arc::new(Self {
  75. pending: Mutex::new(FxHashSet::default()),
  76. channels: Mutex::new(FxHashMap::default()),
  77. channel_subscriber: Subscriber::new(),
  78. stop_subscriber: Subscriber::new(),
  79. hosts: Hosts::new(),
  80. protocol_registry: ProtocolRegistry::new(),
  81. session_manual: Mutex::new(None),
  82. session_inbound: Mutex::new(None),
  83. session_outbound: Mutex::new(None),
  84. state: Mutex::new(P2pState::Open),
  85. settings,
  86. });
  87. let parent = Arc::downgrade(&self_);
  88. *self_.session_manual.lock().await = Some(ManualSession::new(parent.clone()));
  89. *self_.session_inbound.lock().await = Some(InboundSession::new(parent.clone()).await);
  90. *self_.session_outbound.lock().await = Some(OutboundSession::new(parent));
  91. register_default_protocols(self_.clone()).await;
  92. self_
  93. }
  94. pub async fn get_info(&self) -> serde_json::Value {
  95. // Building ext_addr_vec string
  96. let mut ext_addr_vec = vec![];
  97. for ext_addr in &self.settings.external_addr {
  98. ext_addr_vec.push(ext_addr.as_ref().to_string());
  99. }
  100. json!({
  101. "external_addr": format!("{:?}", ext_addr_vec),
  102. "session_manual": self.session_manual().await.get_info().await,
  103. "session_inbound": self.session_inbound().await.get_info().await,
  104. "session_outbound": self.session_outbound().await.get_info().await,
  105. "state": self.state.lock().await.to_string(),
  106. })
  107. }
  108. /// Invoke startup and seeding sequence. Call from constructing thread.
  109. pub async fn start(self: Arc<Self>, executor: Arc<Executor<'_>>) -> Result<()> {
  110. debug!(target: "net", "P2p::start() [BEGIN]");
  111. *self.state.lock().await = P2pState::Start;
  112. // Start seed session
  113. let seed = SeedSyncSession::new(Arc::downgrade(&self));
  114. // This will block until all seed queries have finished
  115. seed.start(executor.clone()).await?;
  116. *self.state.lock().await = P2pState::Started;
  117. debug!(target: "net", "P2p::start() [END]");
  118. Ok(())
  119. }
  120. pub async fn session_manual(&self) -> Arc<ManualSession> {
  121. self.session_manual.lock().await.as_ref().unwrap().clone()
  122. }
  123. pub async fn session_inbound(&self) -> Arc<InboundSession> {
  124. self.session_inbound.lock().await.as_ref().unwrap().clone()
  125. }
  126. pub async fn session_outbound(&self) -> Arc<OutboundSession> {
  127. self.session_outbound.lock().await.as_ref().unwrap().clone()
  128. }
  129. /// Runs the network. Starts inbound, outbound and manual sessions.
  130. /// Waits for a stop signal and stops the network if received.
  131. pub async fn run(self: Arc<Self>, executor: Arc<Executor<'_>>) -> Result<()> {
  132. debug!(target: "net", "P2p::run() [BEGIN]");
  133. *self.state.lock().await = P2pState::Run;
  134. let manual = self.session_manual().await;
  135. for peer in &self.settings.peers {
  136. manual.clone().connect(peer, executor.clone()).await;
  137. }
  138. let inbound = self.session_inbound().await;
  139. inbound.clone().start(executor.clone()).await?;
  140. let outbound = self.session_outbound().await;
  141. outbound.clone().start(executor.clone()).await?;
  142. let stop_sub = self.subscribe_stop().await;
  143. // Wait for stop signal
  144. stop_sub.receive().await;
  145. // Stop the sessions
  146. manual.stop().await;
  147. inbound.stop().await;
  148. outbound.stop().await;
  149. debug!(target: "net", "P2p::run() [END]");
  150. Ok(())
  151. }
  152. /// Wait for outbound connections to be established.
  153. pub async fn wait_for_outbound(self: Arc<Self>) -> Result<()> {
  154. debug!(target: "net", "P2p::wait_for_outbound() [BEGIN]");
  155. // To verify that the network needs initialization, we check if we have seeds or peers configured,
  156. // and have configured outbound slots.
  157. if !(self.settings.seeds.is_empty() && self.settings.peers.is_empty()) &&
  158. self.settings.outbound_connections > 0
  159. {
  160. debug!(target: "net", "P2p::wait_for_outbound(): seeds are configured, waiting for outbound initialization...");
  161. let self_inbound_addr = self.settings().external_addr.clone();
  162. let addrs = self.hosts().load_all().await;
  163. // Retrieve outbound channel subscriber ptr
  164. let outbound_sub =
  165. self.session_outbound.lock().await.as_ref().unwrap().subscribe_channel().await;
  166. // Wait for the result for each of the addresses, excluding our own inbound addresses
  167. for addr in addrs {
  168. if self_inbound_addr.contains(&addr) {
  169. continue
  170. }
  171. // Wait for address to be processed
  172. if let Err(e) = outbound_sub.receive().await {
  173. debug!(
  174. "P2p::wait_for_outbound(): Outbound connection failed [{}]: {}",
  175. &addr, e
  176. );
  177. }
  178. }
  179. }
  180. debug!(target: "net", "P2p::wait_for_outbound() [END]");
  181. Ok(())
  182. }
  183. pub async fn stop(&self) {
  184. self.stop_subscriber.notify(()).await
  185. }
  186. /// Broadcasts a message across all channels.
  187. pub async fn broadcast<M: Message + Clone>(&self, message: M) -> Result<()> {
  188. for channel in self.channels.lock().await.values() {
  189. channel.send(message.clone()).await?;
  190. }
  191. Ok(())
  192. }
  193. /// Broadcasts a message across all channels.
  194. /// exclude channels provided in exclude_list
  195. pub async fn broadcast_with_exclude<M: Message + Clone>(
  196. &self,
  197. message: M,
  198. exclude_list: &[Url],
  199. ) -> Result<()> {
  200. for channel in self.channels.lock().await.values() {
  201. if exclude_list.contains(&channel.address()) {
  202. continue
  203. }
  204. channel.send(message.clone()).await?;
  205. }
  206. Ok(())
  207. }
  208. /// Add channel address to the list of connected channels.
  209. pub async fn store(&self, channel: ChannelPtr) {
  210. self.channels.lock().await.insert(channel.address(), channel.clone());
  211. self.channel_subscriber.notify(Ok(channel)).await;
  212. }
  213. /// Remove a channel from the list of connected channels.
  214. pub async fn remove(&self, channel: ChannelPtr) {
  215. self.channels.lock().await.remove(&channel.address());
  216. }
  217. /// Check whether a channel is stored in the list of connected channels.
  218. pub async fn exists(&self, addr: &Url) -> bool {
  219. self.channels.lock().await.contains_key(addr)
  220. }
  221. /// Add a channel to the list of pending channels.
  222. pub async fn add_pending(&self, addr: Url) -> bool {
  223. self.pending.lock().await.insert(addr)
  224. }
  225. /// Remove a channel from the list of pending channels.
  226. pub async fn remove_pending(&self, addr: &Url) {
  227. self.pending.lock().await.remove(addr);
  228. }
  229. /// Return the number of connected channels.
  230. pub async fn connections_count(&self) -> usize {
  231. self.channels.lock().await.len()
  232. }
  233. /// Return an atomic pointer to the default network settings.
  234. pub fn settings(&self) -> SettingsPtr {
  235. self.settings.clone()
  236. }
  237. /// Return an atomic pointer to the list of hosts.
  238. pub fn hosts(&self) -> HostsPtr {
  239. self.hosts.clone()
  240. }
  241. pub fn protocol_registry(&self) -> &ProtocolRegistry {
  242. &self.protocol_registry
  243. }
  244. /// Subscribe to a channel.
  245. pub async fn subscribe_channel(&self) -> Subscription<Result<ChannelPtr>> {
  246. self.channel_subscriber.clone().subscribe().await
  247. }
  248. /// Subscribe to a stop signal.
  249. pub async fn subscribe_stop(&self) -> Subscription<()> {
  250. self.stop_subscriber.clone().subscribe().await
  251. }
  252. /// Retrieve channels
  253. pub fn channels(&self) -> &ConnectedChannels {
  254. &self.channels
  255. }
  256. }