protocol_generic.rs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2025 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::{clone::Clone, collections::HashMap, fmt::Debug, sync::Arc};
  19. use async_trait::async_trait;
  20. use smol::{
  21. channel::{Receiver, Sender},
  22. lock::RwLock,
  23. Executor,
  24. };
  25. use tracing::debug;
  26. use super::{
  27. super::{
  28. channel::ChannelPtr, message::Message, message_publisher::MessageSubscription,
  29. session::SessionBitFlag,
  30. },
  31. protocol_base::{ProtocolBase, ProtocolBasePtr},
  32. protocol_jobs_manager::{ProtocolJobsManager, ProtocolJobsManagerPtr},
  33. P2pPtr,
  34. };
  35. use crate::{
  36. system::{StoppableTask, StoppableTaskPtr},
  37. Error, Result,
  38. };
  39. /// Defines generic messages protocol action signal.
  40. #[derive(Debug)]
  41. pub enum ProtocolGenericAction<M> {
  42. /// Broadcast message to rest nodes
  43. Broadcast,
  44. /// Send provided response message to the node
  45. Response(M),
  46. /// Skip message broadcast
  47. Skip,
  48. /// Stop the channel entirely
  49. Stop,
  50. }
  51. pub type ProtocolGenericHandlerPtr<M, R> = Arc<ProtocolGenericHandler<M, R>>;
  52. /// Defines a handler for generic protocol messages, consisting
  53. /// of a message receiver, action signal senders mapped by each
  54. /// channel ID, and a stoppable task to run the handler in the
  55. /// background.
  56. pub struct ProtocolGenericHandler<M: Message + Clone, R: Message + Clone + Debug> {
  57. // Since smol channels close if all senders or all receivers
  58. // get dropped, we will keep one here to remain alive with the
  59. // handler.
  60. /// Message queue sender, passed to each P2P channel.
  61. sender: Sender<(u32, M)>,
  62. /// Message queue receiver listening for new messages
  63. /// from all channels.
  64. pub receiver: Receiver<(u32, M)>,
  65. /// Senders mapped by channel ID to propagate the
  66. /// action signal after a message retrieval.
  67. senders: RwLock<HashMap<u32, Sender<ProtocolGenericAction<R>>>>,
  68. /// Handler background task to run the messages listener
  69. /// function with.
  70. pub task: StoppableTaskPtr,
  71. }
  72. impl<M: Message + Clone, R: Message + Clone + Debug> ProtocolGenericHandler<M, R> {
  73. /// Generate a new ProtocolGenericHandler for the provided P2P
  74. /// instance. The handler also attaches its generic protocol.
  75. pub async fn new(
  76. p2p: &P2pPtr,
  77. name: &'static str,
  78. session: SessionBitFlag,
  79. ) -> ProtocolGenericHandlerPtr<M, R> {
  80. // Generate the message queue smol channel
  81. let (sender, receiver) = smol::channel::unbounded::<(u32, M)>();
  82. // Keep a map for all P2P channels senders
  83. let senders = RwLock::new(HashMap::new());
  84. // Create a new stoppable task
  85. let task = StoppableTask::new();
  86. // Create the handler
  87. let handler = Arc::new(Self { sender, receiver, senders, task });
  88. // Attach a generic protocol to the P2P insstance
  89. let _handler = handler.clone();
  90. p2p.protocol_registry()
  91. .register(session, move |channel, p2p| {
  92. let handler = _handler.clone();
  93. async move { ProtocolGeneric::init(channel, name, handler, p2p).await.unwrap() }
  94. })
  95. .await;
  96. handler
  97. }
  98. /// Registers a new channel sender to the handler map.
  99. /// Additionally, looks for stale(closed) channels and prunes then from it.
  100. async fn register_channel_sender(
  101. &self,
  102. channel: u32,
  103. sender: Sender<ProtocolGenericAction<R>>,
  104. ) {
  105. // Register the new channel sender
  106. let mut lock = self.senders.write().await;
  107. lock.insert(channel, sender);
  108. // Look for stale channels
  109. let mut stale = vec![];
  110. for (channel, sender) in lock.iter() {
  111. if sender.is_closed() {
  112. stale.push(*channel);
  113. }
  114. }
  115. // Prune stale channels
  116. for channel in stale {
  117. lock.remove(&channel);
  118. }
  119. drop(lock);
  120. }
  121. /// Sends provided protocol generic action to requested channel, if it exists.
  122. pub async fn send_action(&self, channel: u32, action: ProtocolGenericAction<R>) {
  123. debug!(
  124. target: "net::protocol_generic::ProtocolGenericHandler::send_action",
  125. "Sending action {action:?} to channel {channel}..."
  126. );
  127. // Grab the requested channel sender
  128. let mut lock = self.senders.write().await;
  129. let Some(sender) = lock.get(&channel) else {
  130. debug!(
  131. target: "net::protocol_generic::ProtocolGenericHandler::send_action",
  132. "Channel wasn't found."
  133. );
  134. drop(lock);
  135. return
  136. };
  137. // Send the provided action
  138. if let Err(e) = sender.send(action).await {
  139. debug!(
  140. target: "net::protocol_generic::ProtocolGenericHandler::send_action",
  141. "Channel {channel} send fail: {e}"
  142. );
  143. lock.remove(&channel);
  144. };
  145. drop(lock);
  146. }
  147. }
  148. /// Defines generic messages protocol.
  149. pub struct ProtocolGeneric<M: Message + Clone, R: Message + Clone + Debug> {
  150. /// The P2P channel message subcription
  151. msg_sub: MessageSubscription<M>,
  152. /// The generic message smol channel sender
  153. sender: Sender<(u32, M)>,
  154. /// Action signal smol channel receiver
  155. receiver: Receiver<ProtocolGenericAction<R>>,
  156. /// The P2P channel the protocol is serving
  157. channel: ChannelPtr,
  158. /// Pointer to the whole P2P instance
  159. p2p: P2pPtr,
  160. /// Pointer to the protocol job manager
  161. jobsman: ProtocolJobsManagerPtr,
  162. }
  163. impl<M: Message + Clone, R: Message + Clone + Debug> ProtocolGeneric<M, R> {
  164. /// Initialize a new generic protocol.
  165. pub async fn init(
  166. channel: ChannelPtr,
  167. name: &'static str,
  168. handler: ProtocolGenericHandlerPtr<M, R>,
  169. p2p: P2pPtr,
  170. ) -> Result<ProtocolBasePtr> {
  171. debug!(
  172. target: "net::protocol_generic::init",
  173. "Adding generic protocol for message {name} to the protocol registry"
  174. );
  175. // Add the message dispatcher
  176. let msg_subsystem = channel.message_subsystem();
  177. msg_subsystem.add_dispatch::<M>().await;
  178. msg_subsystem.add_dispatch::<R>().await;
  179. // Create the message subscription
  180. let msg_sub = channel.subscribe_msg::<M>().await?;
  181. // Create a new sender channel
  182. let (action_sender, receiver) = smol::channel::bounded(1);
  183. handler.register_channel_sender(channel.info.id, action_sender).await;
  184. Ok(Arc::new(Self {
  185. msg_sub,
  186. sender: handler.sender.clone(),
  187. receiver,
  188. channel: channel.clone(),
  189. p2p,
  190. jobsman: ProtocolJobsManager::new(name, channel),
  191. }))
  192. }
  193. /// Runs the message queue. We listen for the specified structure message,
  194. /// and when one is received, we send it to our smol channel. Afterwards,
  195. /// we wait for an action signal, specifying whether or not we should
  196. /// propagate the message to rest nodes or skip it.
  197. async fn handle_receive_message(self: Arc<Self>) -> Result<()> {
  198. debug!(
  199. target: "net::protocol_generic::handle_receive_message",
  200. "START"
  201. );
  202. let exclude_list = vec![self.channel.address().clone()];
  203. loop {
  204. // Wait for a new message
  205. let msg = match self.msg_sub.receive().await {
  206. Ok(m) => m,
  207. Err(e) => {
  208. debug!(
  209. target: "net::protocol_generic::handle_receive_message",
  210. "[{}] recv fail: {e}", self.jobsman.clone().name()
  211. );
  212. continue
  213. }
  214. };
  215. let msg_copy = (*msg).clone();
  216. // Send the message across the smol channel
  217. if let Err(e) = self.sender.send((self.channel.info.id, msg_copy.clone())).await {
  218. debug!(
  219. target: "net::protocol_generic::handle_receive_message",
  220. "[{}] sending to channel fail: {e}", self.jobsman.clone().name()
  221. );
  222. continue
  223. }
  224. // Wait for action signal
  225. let action = match self.receiver.recv().await {
  226. Ok(a) => a,
  227. Err(e) => {
  228. debug!(
  229. target: "net::protocol_generic::handle_receive_message",
  230. "[{}] action signal recv fail: {e}", self.jobsman.clone().name()
  231. );
  232. continue
  233. }
  234. };
  235. // Handle action signal
  236. match action {
  237. ProtocolGenericAction::Broadcast => {
  238. self.p2p.broadcast_with_exclude(&msg_copy, &exclude_list).await
  239. }
  240. ProtocolGenericAction::Response(r) => {
  241. if let Err(e) = self.channel.send(&r).await {
  242. debug!(
  243. target: "net::protocol_generic::handle_receive_message",
  244. "[{}] Channel send fail: {e}", self.jobsman.clone().name()
  245. )
  246. };
  247. }
  248. ProtocolGenericAction::Skip => {
  249. debug!(
  250. target: "net::protocol_generic::handle_receive_message",
  251. "[{}] Skip action signal received.", self.jobsman.clone().name()
  252. );
  253. }
  254. ProtocolGenericAction::Stop => {
  255. self.channel.stop().await;
  256. return Err(Error::ChannelStopped)
  257. }
  258. }
  259. }
  260. }
  261. }
  262. #[async_trait]
  263. impl<M: Message + Clone, R: Message + Clone + Debug> ProtocolBase for ProtocolGeneric<M, R> {
  264. async fn start(self: Arc<Self>, ex: Arc<Executor<'_>>) -> Result<()> {
  265. debug!(target: "net::protocol_generic::start", "START");
  266. self.jobsman.clone().start(ex.clone());
  267. self.jobsman.clone().spawn(self.clone().handle_receive_message(), ex).await;
  268. debug!(target: "net::protocol_generic::start", "END");
  269. Ok(())
  270. }
  271. fn name(&self) -> &'static str {
  272. self.jobsman.clone().name()
  273. }
  274. }