distant_net/manager/server/
handler.rs1use std::future::Future;
2use std::io;
3
4use async_trait::async_trait;
5use distant_auth::Authenticator;
6
7use crate::client::UntypedClient;
8use crate::common::{Destination, Map};
9
10pub type BoxedLaunchHandler = Box<dyn LaunchHandler>;
11pub type BoxedConnectHandler = Box<dyn ConnectHandler>;
12
13#[async_trait]
22pub trait LaunchHandler: Send + Sync {
23 async fn launch(
24 &self,
25 destination: &Destination,
26 options: &Map,
27 authenticator: &mut dyn Authenticator,
28 ) -> io::Result<Destination>;
29}
30
31#[async_trait]
32impl<F, R> LaunchHandler for F
33where
34 F: Fn(&Destination, &Map, &mut dyn Authenticator) -> R + Send + Sync + 'static,
35 R: Future<Output = io::Result<Destination>> + Send + 'static,
36{
37 async fn launch(
38 &self,
39 destination: &Destination,
40 options: &Map,
41 authenticator: &mut dyn Authenticator,
42 ) -> io::Result<Destination> {
43 self(destination, options, authenticator).await
44 }
45}
46
47#[macro_export]
65macro_rules! boxed_launch_handler {
66 (|$destination:ident, $options:ident, $authenticator:ident| $(async)? $body:block) => {{
67 let x: $crate::manager::BoxedLaunchHandler = Box::new(
68 |$destination: &$crate::common::Destination,
69 $options: &$crate::common::Map,
70 $authenticator: &mut dyn $crate::auth::Authenticator| async { $body },
71 );
72 x
73 }};
74 (move |$destination:ident, $options:ident, $authenticator:ident| $(async)? $body:block) => {{
75 let x: $crate::manager::BoxedLaunchHandler = Box::new(
76 move |$destination: &$crate::common::Destination,
77 $options: &$crate::common::Map,
78 $authenticator: &mut dyn $crate::auth::Authenticator| async move { $body },
79 );
80 x
81 }};
82}
83
84#[async_trait]
92pub trait ConnectHandler: Send + Sync {
93 async fn connect(
94 &self,
95 destination: &Destination,
96 options: &Map,
97 authenticator: &mut dyn Authenticator,
98 ) -> io::Result<UntypedClient>;
99}
100
101#[async_trait]
102impl<F, R> ConnectHandler for F
103where
104 F: Fn(&Destination, &Map, &mut dyn Authenticator) -> R + Send + Sync + 'static,
105 R: Future<Output = io::Result<UntypedClient>> + Send + 'static,
106{
107 async fn connect(
108 &self,
109 destination: &Destination,
110 options: &Map,
111 authenticator: &mut dyn Authenticator,
112 ) -> io::Result<UntypedClient> {
113 self(destination, options, authenticator).await
114 }
115}
116
117#[macro_export]
135macro_rules! boxed_connect_handler {
136 (|$destination:ident, $options:ident, $authenticator:ident| $(async)? $body:block) => {{
137 let x: $crate::manager::BoxedConnectHandler = Box::new(
138 |$destination: &$crate::common::Destination,
139 $options: &$crate::common::Map,
140 $authenticator: &mut dyn $crate::auth::Authenticator| async { $body },
141 );
142 x
143 }};
144 (move |$destination:ident, $options:ident, $authenticator:ident| $(async)? $body:block) => {{
145 let x: $crate::manager::BoxedConnectHandler = Box::new(
146 move |$destination: &$crate::common::Destination,
147 $options: &$crate::common::Map,
148 $authenticator: &mut dyn $crate::auth::Authenticator| async move { $body },
149 );
150 x
151 }};
152}
153
154#[cfg(test)]
155mod tests {
156 use test_log::test;
157
158 use super::*;
159 use crate::common::FramedTransport;
160
161 #[inline]
162 fn test_destination() -> Destination {
163 "scheme://host:1234".parse().unwrap()
164 }
165
166 #[inline]
167 fn test_options() -> Map {
168 Map::default()
169 }
170
171 #[inline]
172 fn test_authenticator() -> impl Authenticator {
173 FramedTransport::pair(1).0
174 }
175
176 #[test(tokio::test)]
177 async fn boxed_launch_handler_should_generate_valid_boxed_launch_handler() {
178 let handler = boxed_launch_handler!(|_destination, _options, _authenticator| {
179 Err(io::Error::from(io::ErrorKind::Other))
180 });
181 assert_eq!(
182 handler
183 .launch(
184 &test_destination(),
185 &test_options(),
186 &mut test_authenticator()
187 )
188 .await
189 .unwrap_err()
190 .kind(),
191 io::ErrorKind::Other
192 );
193
194 let handler = boxed_launch_handler!(|_destination, _options, _authenticator| async {
195 Err(io::Error::from(io::ErrorKind::Other))
196 });
197 assert_eq!(
198 handler
199 .launch(
200 &test_destination(),
201 &test_options(),
202 &mut test_authenticator()
203 )
204 .await
205 .unwrap_err()
206 .kind(),
207 io::ErrorKind::Other
208 );
209
210 let handler = boxed_launch_handler!(move |_destination, _options, _authenticator| {
211 Err(io::Error::from(io::ErrorKind::Other))
212 });
213 assert_eq!(
214 handler
215 .launch(
216 &test_destination(),
217 &test_options(),
218 &mut test_authenticator()
219 )
220 .await
221 .unwrap_err()
222 .kind(),
223 io::ErrorKind::Other
224 );
225
226 let handler = boxed_launch_handler!(move |_destination, _options, _authenticator| async {
227 Err(io::Error::from(io::ErrorKind::Other))
228 });
229 assert_eq!(
230 handler
231 .launch(
232 &test_destination(),
233 &test_options(),
234 &mut test_authenticator()
235 )
236 .await
237 .unwrap_err()
238 .kind(),
239 io::ErrorKind::Other
240 );
241 }
242
243 #[test(tokio::test)]
244 async fn boxed_connect_handler_should_generate_valid_boxed_connect_handler() {
245 let handler = boxed_connect_handler!(|_destination, _options, _authenticator| {
246 Err(io::Error::from(io::ErrorKind::Other))
247 });
248 assert_eq!(
249 handler
250 .connect(
251 &test_destination(),
252 &test_options(),
253 &mut test_authenticator()
254 )
255 .await
256 .unwrap_err()
257 .kind(),
258 io::ErrorKind::Other
259 );
260
261 let handler = boxed_connect_handler!(|_destination, _options, _authenticator| async {
262 Err(io::Error::from(io::ErrorKind::Other))
263 });
264 assert_eq!(
265 handler
266 .connect(
267 &test_destination(),
268 &test_options(),
269 &mut test_authenticator()
270 )
271 .await
272 .unwrap_err()
273 .kind(),
274 io::ErrorKind::Other
275 );
276
277 let handler = boxed_connect_handler!(move |_destination, _options, _authenticator| {
278 Err(io::Error::from(io::ErrorKind::Other))
279 });
280 assert_eq!(
281 handler
282 .connect(
283 &test_destination(),
284 &test_options(),
285 &mut test_authenticator()
286 )
287 .await
288 .unwrap_err()
289 .kind(),
290 io::ErrorKind::Other
291 );
292
293 let handler = boxed_connect_handler!(move |_destination, _options, _authenticator| async {
294 Err(io::Error::from(io::ErrorKind::Other))
295 });
296 assert_eq!(
297 handler
298 .connect(
299 &test_destination(),
300 &test_options(),
301 &mut test_authenticator()
302 )
303 .await
304 .unwrap_err()
305 .kind(),
306 io::ErrorKind::Other
307 );
308 }
309}