Skip to content

Commit 8dfbc35

Browse files
feat(iroh): remove Arc requirements from ProtocolHandler (#3010)
## Breaking Changes - `iroh::protocol::ProtocolHandler::accept` now takes `&self` instead of `Arc<Self>` - `iroh::protocol::ProtocolHandler::shutdown` now takes `&self` instead of `Arc<Self>` - `iroh::protocol::RouterBuilder::accept` now takes `T: ProtocolHandler` instead of `Arc<dyn ProtocolHandler>` - `iroh::protocol::ProtocolMap` is now private
1 parent 79bf3c3 commit 8dfbc35

File tree

3 files changed

+42
-27
lines changed

3 files changed

+42
-27
lines changed

iroh/examples/echo.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66
//!
77
//! cargo run --example echo --features=examples
88
9-
use std::sync::Arc;
10-
119
use anyhow::Result;
1210
use futures_lite::future::Boxed as BoxedFuture;
1311
use iroh::{
@@ -60,10 +58,7 @@ async fn accept_side() -> Result<Router> {
6058
let endpoint = Endpoint::builder().discovery_n0().bind().await?;
6159

6260
// Build our protocol handler and add our protocol, identified by its ALPN, and spawn the node.
63-
let router = Router::builder(endpoint)
64-
.accept(ALPN, Arc::new(Echo))
65-
.spawn()
66-
.await?;
61+
let router = Router::builder(endpoint).accept(ALPN, Echo).spawn().await?;
6762

6863
Ok(router)
6964
}
@@ -76,7 +71,7 @@ impl ProtocolHandler for Echo {
7671
///
7772
/// The returned future runs on a newly spawned tokio task, so it can run as long as
7873
/// the connection lasts.
79-
fn accept(self: Arc<Self>, connecting: Connecting) -> BoxedFuture<Result<()>> {
74+
fn accept(&self, connecting: Connecting) -> BoxedFuture<Result<()>> {
8075
// We have to return a boxed future from the handler.
8176
Box::pin(async move {
8277
// Wait for the connection to be fully established.

iroh/examples/search.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,8 @@ impl ProtocolHandler for BlobSearch {
127127
///
128128
/// The returned future runs on a newly spawned tokio task, so it can run as long as
129129
/// the connection lasts.
130-
fn accept(self: Arc<Self>, connecting: Connecting) -> BoxedFuture<Result<()>> {
130+
fn accept(&self, connecting: Connecting) -> BoxedFuture<Result<()>> {
131+
let this = self.clone();
131132
// We have to return a boxed future from the handler.
132133
Box::pin(async move {
133134
// Wait for the connection to be fully established.
@@ -145,7 +146,7 @@ impl ProtocolHandler for BlobSearch {
145146

146147
// Now, we can perform the actual query on our local database.
147148
let query = String::from_utf8(query_bytes)?;
148-
let num_matches = self.query_local(&query).await;
149+
let num_matches = this.query_local(&query).await;
149150

150151
// We want to return a list of hashes. We do the simplest thing possible, and just send
151152
// one hash after the other. Because the hashes have a fixed size of 32 bytes, this is
@@ -167,11 +168,11 @@ impl ProtocolHandler for BlobSearch {
167168

168169
impl BlobSearch {
169170
/// Create a new protocol handler.
170-
pub fn new(endpoint: Endpoint) -> Arc<Self> {
171-
Arc::new(Self {
171+
pub fn new(endpoint: Endpoint) -> Self {
172+
Self {
172173
endpoint,
173174
blobs: Default::default(),
174-
})
175+
}
175176
}
176177

177178
/// Query a remote node, download all matching blobs and print the results.

iroh/src/protocol.rs

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,15 @@
33
//! ## Example
44
//!
55
//! ```no_run
6-
//! # use std::sync::Arc;
76
//! # use anyhow::Result;
87
//! # use futures_lite::future::Boxed as BoxedFuture;
98
//! # use iroh::{endpoint::Connecting, protocol::{ProtocolHandler, Router}, Endpoint, NodeAddr};
109
//! #
1110
//! # async fn test_compile() -> Result<()> {
1211
//! let endpoint = Endpoint::builder().discovery_n0().bind().await?;
1312
//!
14-
//! const ALPN: &[u8] = b"/my/alpn";
1513
//! let router = Router::builder(endpoint)
16-
//! .accept(&ALPN, Arc::new(Echo))
14+
//! .accept(b"/my/alpn", Echo)
1715
//! .spawn()
1816
//! .await?;
1917
//! # Ok(())
@@ -24,7 +22,7 @@
2422
//! struct Echo;
2523
//!
2624
//! impl ProtocolHandler for Echo {
27-
//! fn accept(self: Arc<Self>, connecting: Connecting) -> BoxedFuture<Result<()>> {
25+
//! fn accept(&self, connecting: Connecting) -> BoxedFuture<Result<()>> {
2826
//! Box::pin(async move {
2927
//! let connection = connecting.await?;
3028
//! let (mut send, mut recv) = connection.accept_bi().await?;
@@ -111,39 +109,59 @@ pub trait ProtocolHandler: Send + Sync + std::fmt::Debug + 'static {
111109
/// Handle an incoming connection.
112110
///
113111
/// This runs on a freshly spawned tokio task so this can be long-running.
114-
fn accept(self: Arc<Self>, conn: Connecting) -> BoxedFuture<Result<()>>;
112+
fn accept(&self, conn: Connecting) -> BoxedFuture<Result<()>>;
115113

116114
/// Called when the node shuts down.
117-
fn shutdown(self: Arc<Self>) -> BoxedFuture<()> {
115+
fn shutdown(&self) -> BoxedFuture<()> {
118116
Box::pin(async move {})
119117
}
120118
}
121119

120+
impl<T: ProtocolHandler> ProtocolHandler for Arc<T> {
121+
fn accept(&self, conn: Connecting) -> BoxedFuture<Result<()>> {
122+
self.as_ref().accept(conn)
123+
}
124+
125+
fn shutdown(&self) -> BoxedFuture<()> {
126+
self.as_ref().shutdown()
127+
}
128+
}
129+
130+
impl<T: ProtocolHandler> ProtocolHandler for Box<T> {
131+
fn accept(&self, conn: Connecting) -> BoxedFuture<Result<()>> {
132+
self.as_ref().accept(conn)
133+
}
134+
135+
fn shutdown(&self) -> BoxedFuture<()> {
136+
self.as_ref().shutdown()
137+
}
138+
}
139+
122140
/// A typed map of protocol handlers, mapping them from ALPNs.
123-
#[derive(Debug, Clone, Default)]
124-
pub struct ProtocolMap(BTreeMap<Vec<u8>, Arc<dyn ProtocolHandler>>);
141+
#[derive(Debug, Default)]
142+
pub(crate) struct ProtocolMap(BTreeMap<Vec<u8>, Box<dyn ProtocolHandler>>);
125143

126144
impl ProtocolMap {
127145
/// Returns the registered protocol handler for an ALPN as a [`Arc<dyn ProtocolHandler>`].
128-
pub fn get(&self, alpn: &[u8]) -> Option<Arc<dyn ProtocolHandler>> {
129-
self.0.get(alpn).cloned()
146+
pub(crate) fn get(&self, alpn: &[u8]) -> Option<&dyn ProtocolHandler> {
147+
self.0.get(alpn).map(|p| &**p)
130148
}
131149

132150
/// Inserts a protocol handler.
133-
pub fn insert(&mut self, alpn: Vec<u8>, handler: Arc<dyn ProtocolHandler>) {
151+
pub(crate) fn insert(&mut self, alpn: Vec<u8>, handler: Box<dyn ProtocolHandler>) {
134152
self.0.insert(alpn, handler);
135153
}
136154

137155
/// Returns an iterator of all registered ALPN protocol identifiers.
138-
pub fn alpns(&self) -> impl Iterator<Item = &Vec<u8>> {
156+
pub(crate) fn alpns(&self) -> impl Iterator<Item = &Vec<u8>> {
139157
self.0.keys()
140158
}
141159

142160
/// Shuts down all protocol handlers.
143161
///
144162
/// Calls and awaits [`ProtocolHandler::shutdown`] for all registered handlers concurrently.
145-
pub async fn shutdown(&self) {
146-
let handlers = self.0.values().cloned().map(ProtocolHandler::shutdown);
163+
pub(crate) async fn shutdown(&self) {
164+
let handlers = self.0.values().map(|p| p.shutdown());
147165
join_all(handlers).await;
148166
}
149167
}
@@ -201,7 +219,8 @@ impl RouterBuilder {
201219

202220
/// Configures the router to accept the [`ProtocolHandler`] when receiving a connection
203221
/// with this `alpn`.
204-
pub fn accept(mut self, alpn: impl AsRef<[u8]>, handler: Arc<dyn ProtocolHandler>) -> Self {
222+
pub fn accept<T: ProtocolHandler>(mut self, alpn: impl AsRef<[u8]>, handler: T) -> Self {
223+
let handler = Box::new(handler);
205224
self.protocols.insert(alpn.as_ref().to_vec(), handler);
206225
self
207226
}

0 commit comments

Comments
 (0)