ngrok/
forwarder.rs

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
21/// An ngrok forwarder.
22///
23/// Represents a tunnel that is being forwarded to a URL.
24pub 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    /// Wait for the forwarding task to exit.
31    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}