lib.rs 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2026 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. sync::Arc,
  21. };
  22. use smol::lock::Mutex;
  23. use tracing::{debug, error, info};
  24. use darkfi::{
  25. net::settings::Settings,
  26. rpc::{
  27. jsonrpc::JsonSubscriber,
  28. server::{listen_and_serve, RequestHandler},
  29. settings::RpcSettings,
  30. },
  31. system::{ExecutorPtr, StoppableTask, StoppableTaskPtr},
  32. Error, Result,
  33. };
  34. /// JSON-RPC server methods
  35. mod rpc;
  36. /// P2P net protocols
  37. mod proto;
  38. use proto::{DamP2pHandler, DamP2pHandlerPtr};
  39. /// P2P network flooder
  40. mod flooder;
  41. use flooder::{DamFlooder, DamFlooderPtr};
  42. /// Atomic pointer to the Denial-of-service Analysis Multitool node
  43. pub type DamNodePtr = Arc<DamNode>;
  44. /// Structure representing a Denial-of-service Analysis Multitool node
  45. pub struct DamNode {
  46. /// P2P network protocols handler.
  47. p2p_handler: DamP2pHandlerPtr,
  48. /// A map of various subscribers exporting live info from the node
  49. subscribers: HashMap<&'static str, JsonSubscriber>,
  50. /// JSON-RPC connection tracker
  51. rpc_connections: Mutex<HashSet<StoppableTaskPtr>>,
  52. /// Network flooder
  53. flooder: DamFlooderPtr,
  54. }
  55. impl DamNode {
  56. pub async fn new(
  57. p2p_handler: DamP2pHandlerPtr,
  58. subscribers: HashMap<&'static str, JsonSubscriber>,
  59. flooder: DamFlooderPtr,
  60. ) -> DamNodePtr {
  61. Arc::new(Self {
  62. p2p_handler,
  63. subscribers,
  64. rpc_connections: Mutex::new(HashSet::new()),
  65. flooder,
  66. })
  67. }
  68. }
  69. /// Atomic pointer to the Denial-of-service Analysis Multitool daemon
  70. pub type DamdPtr = Arc<Damd>;
  71. /// Structure representing a Denial-of-service Analysis Multitool daemon
  72. pub struct Damd {
  73. /// Darkfi node instance
  74. node: DamNodePtr,
  75. /// `dnet` background task
  76. dnet_task: StoppableTaskPtr,
  77. /// JSON-RPC background task
  78. rpc_task: StoppableTaskPtr,
  79. }
  80. impl Damd {
  81. /// Initialize a Denial-of-service Analysis Multitool daemon.
  82. ///
  83. /// Generates a new `DamNode` for provided configuration,
  84. /// along with all the corresponding background tasks.
  85. pub async fn init(net_settings: &Settings, ex: &ExecutorPtr) -> Result<DamdPtr> {
  86. info!(target: "damd::Damd::init", "Initializing a Denial-of-service Analysis Multitool daemon...");
  87. // Initialize P2P network
  88. let p2p_handler = DamP2pHandler::init(net_settings, ex).await?;
  89. // Here we initialize various subscribers that can export live network data.
  90. let mut subscribers = HashMap::new();
  91. subscribers.insert("dnet", JsonSubscriber::new("dnet.subscribe_events"));
  92. subscribers.insert("foo", JsonSubscriber::new("protocols.subscribe_foo"));
  93. subscribers.insert("attack_foo", JsonSubscriber::new("protocols.subscribe_attack_foo"));
  94. subscribers.insert("bar", JsonSubscriber::new("protocols.subscribe_bar"));
  95. subscribers.insert("attack_bar", JsonSubscriber::new("protocols.subscribe_attack_bar"));
  96. // Initialize flooder
  97. let flooder = DamFlooder::init(&p2p_handler.p2p, ex);
  98. // Initialize node
  99. let node = DamNode::new(p2p_handler, subscribers, flooder).await;
  100. // Generate the background tasks
  101. let dnet_task = StoppableTask::new();
  102. let rpc_task = StoppableTask::new();
  103. info!(target: "damd::Damd::init", "Denial-of-service Analysis Multitool daemon initialized successfully!");
  104. Ok(Arc::new(Self { node, dnet_task, rpc_task }))
  105. }
  106. /// Start the Denial-of-service Analysis Multitool daemon in the given executor,
  107. /// using the provided JSON-RPC configuration.
  108. pub async fn start(&self, executor: &ExecutorPtr, rpc_settings: &RpcSettings) -> Result<()> {
  109. info!(target: "damd::Damd::start", "Starting Denial-of-service Analysis Multitool daemon...");
  110. // Start the `dnet` task
  111. info!(target: "damd::Damd::start", "Starting dnet subs task");
  112. let dnet_sub_ = self.node.subscribers.get("dnet").unwrap().clone();
  113. let p2p_ = self.node.p2p_handler.p2p.clone();
  114. self.dnet_task.clone().start(
  115. async move {
  116. let dnet_sub = p2p_.dnet_subscribe().await;
  117. loop {
  118. let event = dnet_sub.receive().await;
  119. debug!(target: "damd::Damd::dnet_task", "Got dnet event: {:?}", event);
  120. dnet_sub_.notify(vec![event.into()].into()).await;
  121. }
  122. },
  123. |res| async {
  124. match res {
  125. Ok(()) | Err(Error::DetachedTaskStopped) => { /* Do nothing */ }
  126. Err(e) => {
  127. error!(target: "damd::Damd::start", "Failed starting dnet subs task: {}", e)
  128. }
  129. }
  130. },
  131. Error::DetachedTaskStopped,
  132. executor.clone(),
  133. );
  134. // Start the JSON-RPC task
  135. info!(target: "damd::Damd::start", "Starting JSON-RPC server");
  136. let node_ = self.node.clone();
  137. self.rpc_task.clone().start(
  138. listen_and_serve(rpc_settings.clone(), self.node.clone(), None, executor.clone()),
  139. |res| async move {
  140. match res {
  141. Ok(()) | Err(Error::RpcServerStopped) => node_.stop_connections().await,
  142. Err(e) => error!(target: "damd::Damd::start", "Failed starting JSON-RPC server: {}", e),
  143. }
  144. },
  145. Error::RpcServerStopped,
  146. executor.clone(),
  147. );
  148. // Start the P2P network
  149. info!(target: "damd::Damd::start", "Starting P2P network");
  150. self.node.p2p_handler.clone().start(executor, &self.node.subscribers).await?;
  151. info!(target: "damd::Damd::start", "Denial-of-service Analysis Multitool daemon started successfully!");
  152. Ok(())
  153. }
  154. /// Stop the Denial-of-service Analysis Multitool daemon.
  155. pub async fn stop(&self) -> Result<()> {
  156. info!(target: "damd::Damd::stop", "Terminating Denial-of-service Analysis Multitool daemon...");
  157. // Stop the flooder
  158. info!(target: "damd::Damd::stop", "Stopping the flooder...");
  159. self.node.flooder.stop().await;
  160. // Stop the `dnet` node
  161. info!(target: "damd::Damd::stop", "Stopping dnet subs task...");
  162. self.dnet_task.stop().await;
  163. // Stop the JSON-RPC task
  164. info!(target: "damd::Damd::stop", "Stopping JSON-RPC server...");
  165. self.rpc_task.stop().await;
  166. // Stop the P2P network
  167. info!(target: "damd::Damd::stop", "Stopping P2P network protocols handler...");
  168. self.node.p2p_handler.stop().await;
  169. info!(target: "damd::Damd::stop", "Denial-of-service Analysis Multitool daemon terminated successfully!");
  170. Ok(())
  171. }
  172. }