use { crate::{ async_engine::SpawnedFuture, client::ClientCaps, state::State, utils::{copyhashmap::CopyHashMap, errorfmt::ErrorFmt, hash_map_ext::HashMapExt}, }, std::{ cell::Cell, fmt::{Display, Formatter}, rc::Rc, }, uapi::{OwnedFd, c}, }; #[derive(Default)] pub struct SecurityContextAcceptors { ids: AcceptorIds, acceptors: CopyHashMap>, } linear_ids!(AcceptorIds, AcceptorId, u64); struct Acceptor { id: AcceptorId, state: Rc, metadata: Rc, listen_fd: Rc, close_fd: Rc, caps: ClientCaps, listen_future: Cell>>, close_future: Cell>>, } #[derive(Default)] pub struct AcceptorMetadata { pub sandboxed: bool, pub sandbox_engine: Option, pub app_id: Option, pub instance_id: Option, } impl SecurityContextAcceptors { pub fn clear(&self) { for acceptor in self.acceptors.lock().drain_values() { acceptor.kill(); } } pub fn spawn( &self, state: &Rc, sandbox_engine: Option, app_id: Option, instance_id: Option, listen_fd: &Rc, close_fd: &Rc, caps: ClientCaps, ) { let acceptor = Rc::new(Acceptor { id: self.ids.next(), state: state.clone(), metadata: Rc::new(AcceptorMetadata { sandboxed: true, sandbox_engine, app_id, instance_id, }), listen_fd: listen_fd.clone(), close_fd: close_fd.clone(), caps, listen_future: Cell::new(None), close_future: Cell::new(None), }); log::info!("Creating security acceptor {acceptor}"); acceptor.listen_future.set(Some( state .eng .spawn("security accept", acceptor.clone().accept()), )); acceptor.close_future.set(Some( state .eng .spawn("security await close", acceptor.clone().close()), )); self.acceptors.set(acceptor.id, acceptor); } } impl Acceptor { fn kill(&self) { log::info!("Destroying security acceptor {self}"); self.listen_future.take(); self.close_future.take(); self.state .security_context_acceptors .acceptors .remove(&self.id); } async fn accept(self: Rc) { let s = &self.state; loop { let fd = match s.ring.accept(&self.listen_fd, c::SOCK_CLOEXEC).await { Ok(fd) => fd, Err(e) => { log::error!("Could not accept a client: {}", ErrorFmt(e)); break; } }; let id = s.clients.id(); if let Err(e) = s .clients .spawn(id, s, fd, self.caps, self.caps, &self.metadata) { log::error!("Could not spawn a client: {}", ErrorFmt(e)); break; } } self.kill(); } async fn close(self: Rc) { let _ = self.state.ring.poll(&self.close_fd, 0).await; self.kill(); } } impl Display for Acceptor { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { write!( f, "{}/{}/{}", self.metadata.sandbox_engine.as_deref().unwrap_or(""), self.metadata.app_id.as_deref().unwrap_or(""), self.metadata.instance_id.as_deref().unwrap_or(""), ) } }