darkfi/net/protocol/
protocol_registry.rs1use smol::{
20 future::{Boxed, Future},
21 lock::Mutex,
22};
23use tracing::debug;
24
25use super::{
26 super::{channel::ChannelPtr, p2p::P2pPtr, session::SessionBitFlag},
27 protocol_base::ProtocolBasePtr,
28};
29
30type Constructor = Box<dyn Fn(ChannelPtr, P2pPtr) -> Boxed<ProtocolBasePtr> + Send + Sync>;
31
32#[derive(Default)]
33pub struct ProtocolRegistry {
34 constructors: Mutex<Vec<(SessionBitFlag, Constructor)>>,
35}
36
37impl ProtocolRegistry {
38 pub fn new() -> Self {
40 Self::default()
41 }
42
43 pub async fn register<C, F>(&self, session_flags: SessionBitFlag, constructor: C)
45 where
46 C: 'static + Fn(ChannelPtr, P2pPtr) -> F + Send + Sync,
47 F: 'static + Future<Output = ProtocolBasePtr> + Send,
48 {
49 let constructor =
50 move |channel, p2p| Box::pin(constructor(channel, p2p)) as Boxed<ProtocolBasePtr>;
51
52 self.constructors.lock().await.push((session_flags, Box::new(constructor)));
53 }
54
55 pub async fn attach(
56 &self,
57 selector_id: SessionBitFlag,
58 channel: ChannelPtr,
59 p2p: P2pPtr,
60 ) -> Vec<ProtocolBasePtr> {
61 let mut protocols = vec![];
62
63 for (session_flags, construct) in self.constructors.lock().await.iter() {
64 if selector_id & session_flags == 0 {
66 debug!(
67 target: "net::protocol_registry",
68 "Skipping protocol attach [selector_id={selector_id:#b}, session_flags={session_flags:#b}]",
69 );
70 continue
71 }
72
73 let protocol = construct(channel.clone(), p2p.clone()).await;
74 debug!(target: "net::protocol_registry", "Attached {}", protocol.name());
75 protocols.push(protocol);
76 }
77
78 protocols
79 }
80}