hyper_util/client/legacy/connect/proxy/socks/v4/
mod.rs1mod errors;
2pub use errors::*;
3
4mod messages;
5use messages::*;
6
7use std::net::{IpAddr, SocketAddr, SocketAddrV4, ToSocketAddrs};
8use std::task::{Context, Poll};
9
10use http::Uri;
11use hyper::rt::{Read, Write};
12use tower_service::Service;
13
14use bytes::BytesMut;
15
16use super::{Handshaking, SocksError};
17
18#[derive(Debug, Clone)]
24pub struct SocksV4<C> {
25 inner: C,
26 config: SocksConfig,
27}
28
29#[derive(Debug, Clone)]
30struct SocksConfig {
31 proxy: Uri,
32 local_dns: bool,
33}
34
35impl<C> SocksV4<C> {
36 pub fn new(proxy_dst: Uri, connector: C) -> Self {
45 Self {
46 inner: connector,
47 config: SocksConfig::new(proxy_dst),
48 }
49 }
50
51 pub fn local_dns(mut self, local_dns: bool) -> Self {
56 self.config.local_dns = local_dns;
57 self
58 }
59}
60
61impl SocksConfig {
62 pub fn new(proxy: Uri) -> Self {
63 Self {
64 proxy,
65 local_dns: false,
66 }
67 }
68
69 async fn execute<T, E>(self, mut conn: T, host: String, port: u16) -> Result<T, SocksError<E>>
70 where
71 T: Read + Write + Unpin,
72 {
73 let address = match host.parse::<IpAddr>() {
74 Ok(IpAddr::V6(_)) => return Err(SocksV4Error::IpV6.into()),
75 Ok(IpAddr::V4(ip)) => Address::Socket(SocketAddrV4::new(ip, port)),
76 Err(_) => {
77 if self.local_dns {
78 (host, port)
79 .to_socket_addrs()?
80 .find_map(|s| {
81 if let SocketAddr::V4(v4) = s {
82 Some(Address::Socket(v4))
83 } else {
84 None
85 }
86 })
87 .ok_or(SocksError::DnsFailure)?
88 } else {
89 Address::Domain(host, port)
90 }
91 }
92 };
93
94 let mut send_buf = BytesMut::with_capacity(1024);
95 let mut recv_buf = BytesMut::with_capacity(1024);
96
97 let req = Request(&address);
99 let n = req.write_to_buf(&mut send_buf)?;
100 crate::rt::write_all(&mut conn, &send_buf[..n]).await?;
101
102 let res: Response = super::read_message(&mut conn, &mut recv_buf).await?;
104 if res.0 == Status::Success {
105 Ok(conn)
106 } else {
107 Err(SocksV4Error::Command(res.0).into())
108 }
109 }
110}
111
112impl<C> Service<Uri> for SocksV4<C>
113where
114 C: Service<Uri>,
115 C::Future: Send + 'static,
116 C::Response: Read + Write + Unpin + Send + 'static,
117 C::Error: Send + 'static,
118{
119 type Response = C::Response;
120 type Error = SocksError<C::Error>;
121 type Future = Handshaking<C::Future, C::Response, C::Error>;
122
123 fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
124 self.inner.poll_ready(cx).map_err(SocksError::Inner)
125 }
126
127 fn call(&mut self, dst: Uri) -> Self::Future {
128 let config = self.config.clone();
129 let connecting = self.inner.call(config.proxy.clone());
130
131 let fut = async move {
132 let port = dst.port().map(|p| p.as_u16()).unwrap_or(443);
133 let host = dst.host().ok_or(SocksError::MissingHost)?.to_string();
134
135 let conn = connecting.await.map_err(SocksError::Inner)?;
136 config.execute(conn, host, port).await
137 };
138
139 Handshaking {
140 fut: Box::pin(fut),
141 _marker: Default::default(),
142 }
143 }
144}