1
- //! TODO(matheus23) docs
1
+ //! Tools for spawning an accept loop that routes incoming requests to the right protocol.
2
+ //!
3
+ //! ## Example
4
+ //!
5
+ //! ```no_run
6
+ //! # use std::sync::Arc;
7
+ //! # use anyhow::Result;
8
+ //! # use futures_lite::future::Boxed as BoxedFuture;
9
+ //! # use iroh::{endpoint::Connecting, protocol::{ProtocolHandler, Router}, Endpoint, NodeAddr};
10
+ //! #
11
+ //! # async fn test_compile() -> Result<()> {
12
+ //! let endpoint = Endpoint::builder().discovery_n0().bind().await?;
13
+ //!
14
+ //! let router = Router::builder(endpoint)
15
+ //! .accept(ALPN.to_vec(), Arc::new(Echo))
16
+ //! .spawn()
17
+ //! .await?;
18
+ //! # Ok(())
19
+ //! # }
20
+ //!
21
+ //! // The protocol definition:
22
+ //! #[derive(Debug, Clone)]
23
+ //! struct Echo;
24
+ //!
25
+ //! impl ProtocolHandler for Echo {
26
+ //! fn accept(self: Arc<Self>, connecting: Connecting) -> BoxedFuture<Result<()>> {
27
+ //! Box::pin(async move {
28
+ //! let connection = connecting.await?;
29
+ //! let (mut send, mut recv) = connection.accept_bi().await?;
30
+ //!
31
+ //! // Echo any bytes received back directly.
32
+ //! let bytes_sent = tokio::io::copy(&mut recv, &mut send).await?;
33
+ //!
34
+ //! send.finish()?;
35
+ //! connection.closed().await;
36
+ //!
37
+ //! Ok(())
38
+ //! })
39
+ //! }
40
+ //! }
41
+ //! ```
2
42
use std:: { any:: Any , collections:: BTreeMap , sync:: Arc } ;
3
43
4
44
use anyhow:: { anyhow, Result } ;
@@ -14,7 +54,39 @@ use tracing::{debug, error, warn};
14
54
15
55
use crate :: { endpoint:: Connecting , Endpoint } ;
16
56
17
- /// TODO(matheus23): docs
57
+ /// The built router.
58
+ ///
59
+ /// Construct this using [`Router::builder`].
60
+ ///
61
+ /// When dropped, this will abort listening the tasks, so make sure to store it.
62
+ ///
63
+ /// Even with this abort-on-drop behaviour, it's recommended to call and await
64
+ /// [`Router::shutdown`] before ending the process.
65
+ ///
66
+ /// As an example for graceful shutdown, e.g. for tests or CLI tools,
67
+ /// wait for [`tokio::signal::ctrl_c()`]:
68
+ ///
69
+ /// ```no_run
70
+ /// # use std::sync::Arc;
71
+ /// # use anyhow::Result;
72
+ /// # use futures_lite::future::Boxed as BoxedFuture;
73
+ /// # use iroh::{endpoint::Connecting, protocol::ProtocolHandler, router::Router, Endpoint, NodeAddr};
74
+ /// #
75
+ /// # async fn test_compile() -> Result<()> {
76
+ /// let endpoint = Endpoint::builder().discovery_n0().bind().await?;
77
+ ///
78
+ /// let router = Router::builder(endpoint)
79
+ /// // .accept(ALPN.to_vec(), <something>)
80
+ /// .spawn()
81
+ /// .await?;
82
+ ///
83
+ /// // wait until the user wants to
84
+ /// tokio::signal::ctrl_c().await?;
85
+ /// router.shutdown().await?;
86
+ /// # Ok(())
87
+ /// # }
88
+ ///
89
+ /// ```
18
90
#[ derive( Clone , Debug ) ]
19
91
pub struct Router {
20
92
endpoint : Endpoint ,
@@ -31,7 +103,7 @@ pub struct Router {
31
103
32
104
type JoinErrToStr = Box < dyn Fn ( JoinError ) -> String + Send + Sync + ' static > ;
33
105
34
- /// TODO(matheus23): docs
106
+ /// Builder for creating a [`Router`] for accepting protocols.
35
107
#[ derive( Debug ) ]
36
108
pub struct RouterBuilder {
37
109
endpoint : Endpoint ,
@@ -46,7 +118,7 @@ pub struct RouterBuilder {
46
118
///
47
119
/// Implement this trait on a struct that should handle incoming connections.
48
120
/// The protocol handler must then be registered on the node for an ALPN protocol with
49
- /// [`crate::router ::RouterBuilder::accept`].
121
+ /// [`crate::protocol ::RouterBuilder::accept`].
50
122
pub trait ProtocolHandler : Send + Sync + IntoArcAny + std:: fmt:: Debug + ' static {
51
123
/// Handle an incoming connection.
52
124
///
@@ -63,7 +135,7 @@ pub trait ProtocolHandler: Send + Sync + IntoArcAny + std::fmt::Debug + 'static
63
135
///
64
136
/// This trait has a blanket implementation so there is no need to implement this yourself.
65
137
pub trait IntoArcAny {
66
- /// TODO(matheus23): docs
138
+ /// Casts `Arc<Self>` into `Arc<dyn Any + Send + Sync>`.
67
139
fn into_arc_any ( self : Arc < Self > ) -> Arc < dyn Any + Send + Sync > ;
68
140
}
69
141
@@ -111,7 +183,7 @@ impl ProtocolMap {
111
183
}
112
184
113
185
impl Router {
114
- /// TODO(matheus23): docs
186
+ /// Creates a new [`Router`] using given [`Endpoint`].
115
187
pub fn builder ( endpoint : Endpoint ) -> RouterBuilder {
116
188
RouterBuilder :: new ( endpoint)
117
189
}
@@ -124,12 +196,15 @@ impl Router {
124
196
self . protocols . get_typed ( alpn)
125
197
}
126
198
127
- /// TODO(matheus23): docs
199
+ /// Returns the [`Endpoint`] stored in this router.
128
200
pub fn endpoint ( & self ) -> & Endpoint {
129
201
& self . endpoint
130
202
}
131
203
132
- /// TODO(matheus23): docs
204
+ /// Shuts down the accept loop cleanly.
205
+ ///
206
+ /// If some [`ProtocolHandler`] paniced in the accept loop, this will propagate
207
+ /// that panic into the result here.
133
208
pub async fn shutdown ( self ) -> Result < ( ) > {
134
209
// Trigger shutdown of the main run task by activating the cancel token.
135
210
self . cancel_token . cancel ( ) ;
@@ -142,15 +217,16 @@ impl Router {
142
217
}
143
218
144
219
impl RouterBuilder {
145
- /// TODO(matheus23): docs
220
+ /// Creates a new router builder using given [`Endpoint`].
146
221
pub fn new ( endpoint : Endpoint ) -> Self {
147
222
Self {
148
223
endpoint,
149
224
protocols : ProtocolMap :: default ( ) ,
150
225
}
151
226
}
152
227
153
- /// TODO(matheus23): docs
228
+ /// Configures the router to accept the [`ProtocolHandler`] when receiving a connection
229
+ /// with this `alpn`.
154
230
pub fn accept ( mut self , alpn : impl AsRef < [ u8 ] > , handler : Arc < dyn ProtocolHandler > ) -> Self {
155
231
self . protocols . insert ( alpn. as_ref ( ) . to_vec ( ) , handler) ;
156
232
self
@@ -169,7 +245,7 @@ impl RouterBuilder {
169
245
self . protocols . get_typed ( alpn)
170
246
}
171
247
172
- /// TODO(matheus23): docs
248
+ /// Spawns an accept loop and returns a handle to it encapsulated as the [`Router`].
173
249
pub async fn spawn ( self ) -> Result < Router > {
174
250
// Update the endpoint with our alpns.
175
251
let alpns = self
0 commit comments