use std::any::Any;
use std::collections::BTreeMap;
use std::fmt;
use std::sync::Arc;
use anyhow::Result;
use futures_lite::future::Boxed as BoxedFuture;
use futures_util::future::join_all;
use iroh_net::endpoint::Connecting;
use tracing::debug;
pub trait ProtocolHandler: Send + Sync + IntoArcAny + fmt::Debug + 'static {
fn accept(self: Arc<Self>, conn: Connecting) -> BoxedFuture<Result<()>>;
fn shutdown(self: Arc<Self>) -> BoxedFuture<()> {
Box::pin(async move {})
}
}
pub trait IntoArcAny {
fn into_arc_any(self: Arc<Self>) -> Arc<dyn Any + Send + Sync>;
}
impl<T: Send + Sync + 'static> IntoArcAny for T {
fn into_arc_any(self: Arc<Self>) -> Arc<dyn Any + Send + Sync> {
self
}
}
#[derive(Debug, Clone, Default)]
pub(super) struct ProtocolMap(BTreeMap<&'static [u8], Arc<dyn ProtocolHandler>>);
impl ProtocolMap {
pub(super) fn get(&self, alpn: &[u8]) -> Option<Arc<dyn ProtocolHandler>> {
self.0.get(alpn).cloned()
}
pub(super) fn insert(&mut self, alpn: &'static [u8], handler: Arc<dyn ProtocolHandler>) {
self.0.insert(alpn, handler);
}
pub(super) fn alpns(&self) -> Vec<Vec<u8>> {
self.0.keys().map(|alpn| alpn.to_vec()).collect::<Vec<_>>()
}
pub(super) async fn shutdown(&self) {
let handlers = self.0.values().cloned().map(ProtocolHandler::shutdown);
debug!("await all handler shutdown handles");
join_all(handlers).await;
debug!("all handlers closed");
}
}
impl ProtocolHandler for iroh_gossip::net::Gossip {
fn accept(self: Arc<Self>, conn: Connecting) -> BoxedFuture<Result<()>> {
Box::pin(async move { self.handle_connection(conn.await?).await })
}
}