doh_client/remote/
host.rs

1#[cfg(feature = "http-proxy")]
2use super::try_http_proxy_connect;
3use super::{try_http2_connect, try_tcp_connect, try_tls_connect};
4#[cfg(feature = "socks5")]
5use super::{try_socks5_connect, try_socks5h_connect};
6use crate::DohResult;
7use bytes::Bytes;
8use h2::client::SendRequest;
9use std::fmt::{Display, Formatter, Result};
10use std::sync::Arc;
11use tokio_rustls::rustls::ClientConfig;
12
13pub enum Host {
14    Direct(String, u16),
15    #[cfg(feature = "socks5")]
16    Socks5(
17        String,
18        u16,
19        Option<(String, String)>,
20        Vec<std::net::SocketAddr>,
21    ),
22    #[cfg(feature = "socks5")]
23    Socks5h(String, u16, Option<(String, String)>, String, u16),
24    #[cfg(feature = "http-proxy")]
25    HttpProxy(String, u16, Option<(String, String)>, String, u16),
26    #[cfg(feature = "http-proxy")]
27    HttpsProxy(
28        String,
29        u16,
30        Option<(String, String)>,
31        String,
32        u16,
33        Arc<ClientConfig>,
34        String,
35    ),
36}
37
38impl Host {
39    pub(super) async fn connect(
40        &mut self,
41        client_config: &Arc<ClientConfig>,
42        domain: &str,
43    ) -> DohResult<SendRequest<Bytes>> {
44        match self {
45            Host::Direct(remote_host, remote_port) => {
46                let tcp_connection = try_tcp_connect(remote_host, *remote_port).await?;
47                let tls_connection = try_tls_connect(tcp_connection, client_config, domain).await?;
48                let http2_connection = try_http2_connect(tls_connection).await?;
49                Ok(http2_connection)
50            }
51            #[cfg(feature = "socks5")]
52            Host::Socks5(proxy_host, proxy_port, credentials, remote_addrs) => {
53                let tcp_connection =
54                    try_socks5_connect(proxy_host, *proxy_port, remote_addrs, credentials).await?;
55                let tls_connection = try_tls_connect(tcp_connection, client_config, domain).await?;
56                let http2_connection = try_http2_connect(tls_connection).await?;
57                Ok(http2_connection)
58            }
59            #[cfg(feature = "socks5")]
60            Host::Socks5h(proxy_host, proxy_port, credentials, remote_host, remote_port) => {
61                let tcp_connection = try_socks5h_connect(
62                    proxy_host,
63                    *proxy_port,
64                    remote_host,
65                    *remote_port,
66                    credentials,
67                )
68                .await?;
69                let tls_connection = try_tls_connect(tcp_connection, client_config, domain).await?;
70                let http2_connection = try_http2_connect(tls_connection).await?;
71                Ok(http2_connection)
72            }
73            #[cfg(feature = "http-proxy")]
74            Host::HttpProxy(proxy_host, proxy_port, credentials, remote_host, remote_port) => {
75                let mut tcp_connection = try_tcp_connect(proxy_host, *proxy_port).await?;
76                try_http_proxy_connect(&mut tcp_connection, remote_host, *remote_port, credentials)
77                    .await?;
78                let tls_connection = try_tls_connect(tcp_connection, client_config, domain).await?;
79                let http2_connection = try_http2_connect(tls_connection).await?;
80                Ok(http2_connection)
81            }
82            #[cfg(feature = "http-proxy")]
83            Host::HttpsProxy(
84                proxy_host,
85                proxy_port,
86                credentials,
87                remote_host,
88                remote_port,
89                https_client_config,
90                https_domain,
91            ) => {
92                let tcp_connection = try_tcp_connect(proxy_host, *proxy_port).await?;
93                let mut tls_connection =
94                    try_tls_connect(tcp_connection, https_client_config, https_domain).await?;
95                try_http_proxy_connect(&mut tls_connection, remote_host, *remote_port, credentials)
96                    .await?;
97                let tls_connection = try_tls_connect(tls_connection, client_config, domain).await?;
98                let http2_connection = try_http2_connect(tls_connection).await?;
99                Ok(http2_connection)
100            }
101        }
102    }
103}
104
105impl Display for Host {
106    fn fmt(&self, f: &mut Formatter) -> Result {
107        match self {
108            Host::Direct(remote_host, remote_port) => write!(f, "{}:{}", remote_host, remote_port),
109            #[cfg(feature = "socks5")]
110            Host::Socks5(proxy_host, proxy_port, _, remote_addrs) => {
111                write!(
112                    f,
113                    "{}:{} via socks5 {:?}",
114                    proxy_host, proxy_port, remote_addrs
115                )
116            }
117            #[cfg(feature = "socks5")]
118            Host::Socks5h(proxy_host, proxy_port, _, remote_host, remote_port) => {
119                write!(
120                    f,
121                    "{}:{} via socks5h {}:{}",
122                    proxy_host, proxy_port, remote_host, remote_port
123                )
124            }
125            #[cfg(feature = "http-proxy")]
126            Host::HttpProxy(proxy_host, proxy_port, _, remote_host, remote_port) => {
127                write!(
128                    f,
129                    "{}:{} via http {}:{}",
130                    proxy_host, proxy_port, remote_host, remote_port
131                )
132            }
133            #[cfg(feature = "http-proxy")]
134            Host::HttpsProxy(proxy_host, proxy_port, _, remote_host, remote_port, _, _) => {
135                write!(
136                    f,
137                    "{}:{} via https {}:{}",
138                    proxy_host, proxy_port, remote_host, remote_port
139                )
140            }
141        }
142    }
143}