1use std::{
2 collections::HashMap,
3 error::Error as StdError,
4};
5
6use async_trait::async_trait;
7use tokio::task::JoinHandle;
8use url::Url;
9
10use crate::{
11 prelude::{
12 EdgeInfo,
13 EndpointInfo,
14 TunnelCloser,
15 TunnelInfo,
16 },
17 session::RpcError,
18 Tunnel,
19};
20
21pub struct Forwarder<T> {
25 pub(crate) join: JoinHandle<Result<(), Box<dyn StdError + Send + Sync>>>,
26 pub(crate) inner: T,
27}
28
29impl<T> Forwarder<T> {
30 pub fn join(&mut self) -> &mut JoinHandle<Result<(), Box<dyn StdError + Send + Sync>>> {
32 &mut self.join
33 }
34}
35
36#[async_trait]
37impl<T> TunnelCloser for Forwarder<T>
38where
39 T: TunnelCloser + Send,
40{
41 async fn close(&mut self) -> Result<(), RpcError> {
42 self.inner.close().await
43 }
44}
45
46impl<T> TunnelInfo for Forwarder<T>
47where
48 T: TunnelInfo,
49{
50 fn id(&self) -> &str {
51 self.inner.id()
52 }
53
54 fn forwards_to(&self) -> &str {
55 self.inner.forwards_to()
56 }
57
58 fn metadata(&self) -> &str {
59 self.inner.metadata()
60 }
61}
62
63impl<T> EndpointInfo for Forwarder<T>
64where
65 T: EndpointInfo,
66{
67 fn proto(&self) -> &str {
68 self.inner.proto()
69 }
70
71 fn url(&self) -> &str {
72 self.inner.url()
73 }
74}
75
76impl<T> EdgeInfo for Forwarder<T>
77where
78 T: EdgeInfo,
79{
80 fn labels(&self) -> &HashMap<String, String> {
81 self.inner.labels()
82 }
83}
84
85pub(crate) fn forward<T>(mut listener: T, info: T, to_url: Url) -> Result<Forwarder<T>, RpcError>
86where
87 T: Tunnel + Send + 'static,
88 <T as Tunnel>::Conn: crate::tunnel_ext::ConnExt,
89{
90 let handle =
91 tokio::spawn(
92 async move { Ok(crate::tunnel_ext::forward_tunnel(&mut listener, to_url).await?) },
93 );
94
95 Ok(Forwarder {
96 join: handle,
97 inner: info,
98 })
99}