p2p.rs 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  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. Error, Result,
  11. };
  12. use super::{
  13. message::Message,
  14. protocol::{register_default_protocols, ProtocolRegistry},
  15. session::{InboundSession, ManualSession, OutboundSession, SeedSession, Session},
  16. Channel, ChannelPtr, Hosts, HostsPtr, Settings, SettingsPtr, Transport,
  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<T> = Mutex<fxhash::FxHashMap<Url, Arc<Channel<T>>>>;
  22. /// Atomic pointer to p2p interface.
  23. pub type P2pPtr<T> = Arc<P2p<T>>;
  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<T: Transport> {
  50. pending: PendingChannels,
  51. channels: ConnectedChannels<T>,
  52. channel_subscriber: SubscriberPtr<Result<ChannelPtr<T>>>,
  53. // Used both internally and externally
  54. stop_subscriber: SubscriberPtr<Error>,
  55. hosts: HostsPtr,
  56. protocol_registry: ProtocolRegistry<T>,
  57. // We keep a reference to the sessions used for get info
  58. session_manual: Mutex<Option<Arc<ManualSession<T>>>>,
  59. session_inbound: Mutex<Option<Arc<InboundSession<T>>>>,
  60. session_outbound: Mutex<Option<Arc<OutboundSession<T>>>>,
  61. state: Mutex<P2pState>,
  62. settings: SettingsPtr,
  63. }
  64. impl<T: Transport> P2p<T> {
  65. /// Create a new p2p network.
  66. pub async fn new(settings: Settings) -> Arc<Self> {
  67. let settings = Arc::new(settings);
  68. let self_ = Arc::new(Self {
  69. pending: Mutex::new(FxHashSet::default()),
  70. channels: Mutex::new(FxHashMap::default()),
  71. channel_subscriber: Subscriber::new(),
  72. stop_subscriber: Subscriber::new(),
  73. hosts: Hosts::new(),
  74. protocol_registry: ProtocolRegistry::new(),
  75. session_manual: Mutex::new(None),
  76. session_inbound: Mutex::new(None),
  77. session_outbound: Mutex::new(None),
  78. state: Mutex::new(P2pState::Open),
  79. settings,
  80. });
  81. let parent = Arc::downgrade(&self_);
  82. *self_.session_manual.lock().await = Some(ManualSession::new(parent.clone()));
  83. *self_.session_inbound.lock().await = Some(InboundSession::new(parent.clone()));
  84. *self_.session_outbound.lock().await = Some(OutboundSession::new(parent));
  85. register_default_protocols(self_.clone()).await;
  86. self_
  87. }
  88. pub async fn get_info(&self) -> serde_json::Value {
  89. let external_addr = self
  90. .settings
  91. .external_addr
  92. .as_ref()
  93. .map(|addr| serde_json::Value::from(addr.to_string()))
  94. .unwrap_or(serde_json::Value::Null);
  95. json!({
  96. "external_addr": external_addr,
  97. "session_manual": self.session_manual().await.get_info().await,
  98. "session_inbound": self.session_inbound().await.get_info().await,
  99. "session_outbound": self.session_outbound().await.get_info().await,
  100. "state": self.state.lock().await.to_string(),
  101. })
  102. }
  103. /// Invoke startup and seeding sequence. Call from constructing thread.
  104. pub async fn start(self: Arc<Self>, executor: Arc<Executor<'_>>) -> Result<()> {
  105. debug!(target: "net", "P2p::start() [BEGIN]");
  106. *self.state.lock().await = P2pState::Start;
  107. // Start seed session
  108. let seed = SeedSession::new(Arc::downgrade(&self));
  109. // This will block until all seed queries have finished
  110. seed.start(executor.clone()).await?;
  111. *self.state.lock().await = P2pState::Started;
  112. debug!(target: "net", "P2p::start() [END]");
  113. Ok(())
  114. }
  115. pub async fn session_manual(&self) -> Arc<ManualSession<T>> {
  116. self.session_manual.lock().await.as_ref().unwrap().clone()
  117. }
  118. pub async fn session_inbound(&self) -> Arc<InboundSession<T>> {
  119. self.session_inbound.lock().await.as_ref().unwrap().clone()
  120. }
  121. pub async fn session_outbound(&self) -> Arc<OutboundSession<T>> {
  122. self.session_outbound.lock().await.as_ref().unwrap().clone()
  123. }
  124. /// Synchronize the blockchain and then begin long running sessions,
  125. /// call after start() is invoked.
  126. pub async fn run(self: Arc<Self>, executor: Arc<Executor<'_>>) -> Result<()> {
  127. debug!(target: "net", "P2p::run() [BEGIN]");
  128. *self.state.lock().await = P2pState::Run;
  129. let manual = self.session_manual().await;
  130. for peer in &self.settings.peers {
  131. manual.clone().connect(peer, executor.clone()).await;
  132. }
  133. let inbound = self.session_inbound().await;
  134. inbound.clone().start(executor.clone()).await?;
  135. let outbound = self.session_outbound().await;
  136. outbound.clone().start(executor.clone()).await?;
  137. let stop_sub = self.subscribe_stop().await;
  138. // Wait for stop signal
  139. stop_sub.receive().await;
  140. // Stop the sessions
  141. manual.stop().await;
  142. inbound.stop().await;
  143. outbound.stop().await;
  144. debug!(target: "net", "P2p::run() [END]");
  145. Ok(())
  146. }
  147. /// Broadcasts a message across all channels.
  148. pub async fn broadcast<M: Message + Clone>(&self, message: M) -> Result<()> {
  149. for channel in self.channels.lock().await.values() {
  150. channel.send(message.clone()).await?;
  151. }
  152. Ok(())
  153. }
  154. /// Add channel address to the list of connected channels.
  155. pub async fn store(&self, channel: Arc<Channel<T>>) {
  156. self.channels.lock().await.insert(channel.address(), channel.clone());
  157. self.channel_subscriber.notify(Ok(channel)).await;
  158. }
  159. /// Remove a channel from the list of connected channels.
  160. pub async fn remove(&self, channel: Arc<Channel<T>>) {
  161. self.channels.lock().await.remove(&channel.address());
  162. }
  163. /// Check whether a channel is stored in the list of connected channels.
  164. pub async fn exists(&self, addr: &Url) -> bool {
  165. self.channels.lock().await.contains_key(addr)
  166. }
  167. /// Add a channel to the list of pending channels.
  168. pub async fn add_pending(&self, addr: Url) -> bool {
  169. self.pending.lock().await.insert(addr)
  170. }
  171. /// Remove a channel from the list of pending channels.
  172. pub async fn remove_pending(&self, addr: &Url) {
  173. self.pending.lock().await.remove(addr);
  174. }
  175. /// Return the number of connected channels.
  176. pub async fn connections_count(&self) -> usize {
  177. self.channels.lock().await.len()
  178. }
  179. /// Return an atomic pointer to the default network settings.
  180. pub fn settings(&self) -> SettingsPtr {
  181. self.settings.clone()
  182. }
  183. /// Return an atomic pointer to the list of hosts.
  184. pub fn hosts(&self) -> HostsPtr {
  185. self.hosts.clone()
  186. }
  187. pub fn protocol_registry(&self) -> &ProtocolRegistry<T> {
  188. &self.protocol_registry
  189. }
  190. /// Subscribe to a channel.
  191. pub async fn subscribe_channel(&self) -> Subscription<Result<ChannelPtr<T>>> {
  192. self.channel_subscriber.clone().subscribe().await
  193. }
  194. /// Subscribe to a stop signal.
  195. pub async fn subscribe_stop(&self) -> Subscription<Error> {
  196. self.stop_subscriber.clone().subscribe().await
  197. }
  198. }