-
Notifications
You must be signed in to change notification settings - Fork 171
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
76 additions
and
48 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,58 @@ | ||
use std::{any::Any, fmt, sync::Arc}; | ||
use std::{ | ||
any::Any, | ||
collections::HashMap, | ||
fmt, | ||
sync::{Arc, RwLock}, | ||
}; | ||
|
||
use anyhow::Result; | ||
use futures_lite::future::Boxed as BoxedFuture; | ||
use iroh_net::endpoint::Connecting; | ||
|
||
/// Trait for iroh protocol handlers. | ||
pub trait Protocol: Send + Sync + Any + fmt::Debug + 'static { | ||
/// Return `self` as `dyn Any`. | ||
/// | ||
/// Implementations can simply return `self` here. | ||
fn as_arc_any(self: Arc<Self>) -> Arc<dyn Any + Send + Sync>; | ||
|
||
pub trait Protocol: Send + Sync + IntoArcAny + fmt::Debug + 'static { | ||
/// Handle an incoming connection. | ||
/// | ||
/// This runs on a freshly spawned tokio task so this can be long-running. | ||
fn handle_connection(self: Arc<Self>, conn: Connecting) -> BoxedFuture<Result<()>>; | ||
} | ||
|
||
/// Helper trait to facilite casting from `Arc<dyn T>` to `Arc<dyn Any>`. | ||
/// | ||
/// This trait has a blanket implementation so there is no need to implement this yourself. | ||
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 | ||
} | ||
} | ||
|
||
/// Map of registered protocol handlers. | ||
#[allow(clippy::type_complexity)] | ||
#[derive(Debug, Clone, Default)] | ||
pub struct ProtocolMap(Arc<RwLock<HashMap<&'static [u8], Arc<dyn Protocol>>>>); | ||
|
||
impl ProtocolMap { | ||
/// Returns the registered protocol handler for an ALPN as a concrete type. | ||
pub fn get<P: Protocol>(&self, alpn: &[u8]) -> Option<Arc<P>> { | ||
let protocols = self.0.read().unwrap(); | ||
let protocol: Arc<dyn Protocol> = protocols.get(alpn)?.clone(); | ||
let protocol_any: Arc<dyn Any + Send + Sync> = protocol.into_arc_any(); | ||
let protocol_ref = Arc::downcast(protocol_any).ok()?; | ||
Some(protocol_ref) | ||
} | ||
|
||
/// Returns the registered protocol handler for an ALPN as a `dyn Protocol`. | ||
pub fn get_any(&self, alpn: &[u8]) -> Option<Arc<dyn Protocol>> { | ||
let protocols = self.0.read().unwrap(); | ||
let protocol: Arc<dyn Protocol> = protocols.get(alpn)?.clone(); | ||
Some(protocol) | ||
} | ||
|
||
pub(super) fn insert(&self, alpn: &'static [u8], protocol: Arc<dyn Protocol>) { | ||
self.0.write().unwrap().insert(alpn, protocol); | ||
} | ||
} |