use crate::common::{authentication::Keychain, Backup, ConnectionId}; use std::collections::HashMap; use tokio::sync::{mpsc, oneshot, RwLock}; use tokio::task::JoinHandle; /// Contains all top-level state for the server pub struct ServerState { /// Mapping of connection ids to their tasks. pub connections: RwLock>>, /// Mapping of connection ids to (OTP, backup) pub keychain: Keychain>, } impl ServerState { pub fn new() -> Self { Self { connections: RwLock::new(HashMap::new()), keychain: Keychain::new(), } } } impl Default for ServerState { fn default() -> Self { Self::new() } } pub struct ConnectionState { shutdown_tx: oneshot::Sender<()>, task: JoinHandle, mpsc::Receiver)>>, } impl ConnectionState { /// Creates new state with appropriate channels, returning /// (shutdown receiver, channel sender, state). #[allow(clippy::type_complexity)] pub fn channel() -> ( oneshot::Receiver<()>, oneshot::Sender<(mpsc::Sender, mpsc::Receiver)>, Self, ) { let (shutdown_tx, shutdown_rx) = oneshot::channel(); let (channel_tx, channel_rx) = oneshot::channel(); ( shutdown_rx, channel_tx, Self { shutdown_tx, task: tokio::spawn(async move { match channel_rx.await { Ok(x) => Some(x), Err(_) => None, } }), }, ) } pub fn is_finished(&self) -> bool { self.task.is_finished() } pub async fn shutdown_and_wait(self) -> Option<(mpsc::Sender, mpsc::Receiver)> { let _ = self.shutdown_tx.send(()); self.task.await.unwrap() } }