use crossbeam::channel::{unbounded, Receiver, Sender};
use p2p::{bytes::Bytes, context::SessionContext, multiaddr::Multiaddr, ProtocolId, SessionId};
use std::collections::HashMap;
pub struct SharedState {
session_manager: HashMap<
SessionId,
(
SessionContext,
HashMap<ProtocolId, (Sender<Bytes>, Receiver<Bytes>)>,
),
>,
}
impl SharedState {
pub fn new() -> Self {
Self {
session_manager: HashMap::new(),
}
}
pub fn add_session(&mut self, session: SessionContext) {
self.session_manager
.entry(session.id)
.or_insert_with(|| (session.clone(), HashMap::new()));
}
pub fn remove_session(&mut self, session_id: &SessionId) -> Option<SessionContext> {
self.session_manager
.remove(session_id)
.map(|(session, _mailbox)| session)
}
pub fn get_session(&self, address: &Multiaddr) -> Option<SessionContext> {
for (session, _) in self.session_manager.values() {
if &session.address == address {
return Some(session.clone());
}
}
None
}
pub fn add_protocol(&mut self, session: &SessionContext, protocol_id: ProtocolId) {
let (protocol_mailbox_sender, protocol_mailbox_receiver) = unbounded::<Bytes>();
self.session_manager
.entry(session.id)
.or_insert_with(|| (session.clone(), HashMap::new()))
.1
.insert(
protocol_id,
(protocol_mailbox_sender, protocol_mailbox_receiver),
);
}
pub fn remove_protocol(&mut self, session_id: &SessionId, protocol_id: &ProtocolId) {
let _ = self
.session_manager
.get_mut(session_id)
.map(|(_session, mailbox)| mailbox.remove(protocol_id));
}
pub fn get_protocol_sender(
&self,
session_id: &SessionId,
protocol_id: &ProtocolId,
) -> Option<Sender<Bytes>> {
self.session_manager
.get(session_id)
.and_then(|(_, mailbox)| {
mailbox
.get(protocol_id)
.map(|(sender, _receiver)| sender.clone())
})
}
pub fn get_protocol_receiver(
&self,
session_id: &SessionId,
protocol_id: &ProtocolId,
) -> Option<Receiver<Bytes>> {
self.session_manager
.get(session_id)
.and_then(|(_, mailbox)| {
mailbox
.get(protocol_id)
.map(|(_sender, receiver)| receiver.clone())
})
}
pub fn get_opened_protocol_ids(&self, session_id: &SessionId) -> Option<Vec<ProtocolId>> {
self.session_manager
.get(session_id)
.map(|(_session, mailbox)| mailbox.keys().cloned().collect())
}
pub fn get_sessions(&self) -> Vec<&SessionContext> {
self.session_manager
.values()
.map(|(session, _)| session)
.collect()
}
}