hyper_util/client/legacy/connect/proxy/socks/
mod.rs

1mod v5;
2pub use v5::{SocksV5, SocksV5Error};
3
4mod v4;
5pub use v4::{SocksV4, SocksV4Error};
6
7use bytes::BytesMut;
8
9use hyper::rt::Read;
10
11#[derive(Debug)]
12pub enum SocksError<C> {
13    Inner(C),
14    Io(std::io::Error),
15
16    DnsFailure,
17    MissingHost,
18    MissingPort,
19
20    V4(SocksV4Error),
21    V5(SocksV5Error),
22
23    Parsing(ParsingError),
24    Serialize(SerializeError),
25}
26
27#[derive(Debug)]
28pub enum ParsingError {
29    Incomplete,
30    WouldOverflow,
31    Other,
32}
33
34#[derive(Debug)]
35pub enum SerializeError {
36    WouldOverflow,
37}
38
39async fn read_message<T, M, C>(mut conn: &mut T, buf: &mut BytesMut) -> Result<M, SocksError<C>>
40where
41    T: Read + Unpin,
42    M: for<'a> TryFrom<&'a mut BytesMut, Error = ParsingError>,
43{
44    let mut tmp = [0; 513];
45
46    loop {
47        let n = crate::rt::read(&mut conn, &mut tmp).await?;
48        buf.extend_from_slice(&tmp[..n]);
49
50        match M::try_from(buf) {
51            Err(ParsingError::Incomplete) => {
52                if n == 0 {
53                    if buf.spare_capacity_mut().len() == 0 {
54                        return Err(SocksError::Parsing(ParsingError::WouldOverflow));
55                    } else {
56                        return Err(std::io::Error::new(
57                            std::io::ErrorKind::UnexpectedEof,
58                            "unexpected eof",
59                        )
60                        .into());
61                    }
62                }
63            }
64            Err(err) => return Err(err.into()),
65            Ok(res) => return Ok(res),
66        }
67    }
68}
69
70impl<C> std::fmt::Display for SocksError<C> {
71    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
72        f.write_str("SOCKS error: ")?;
73
74        match self {
75            Self::Inner(_) => f.write_str("failed to create underlying connection"),
76            Self::Io(_) => f.write_str("io error during SOCKS handshake"),
77
78            Self::DnsFailure => f.write_str("could not resolve to acceptable address type"),
79            Self::MissingHost => f.write_str("missing destination host"),
80            Self::MissingPort => f.write_str("missing destination port"),
81
82            Self::Parsing(_) => f.write_str("failed parsing server response"),
83            Self::Serialize(_) => f.write_str("failed serialize request"),
84
85            Self::V4(e) => e.fmt(f),
86            Self::V5(e) => e.fmt(f),
87        }
88    }
89}
90
91impl<C: std::fmt::Debug + std::fmt::Display> std::error::Error for SocksError<C> {}
92
93impl<C> From<std::io::Error> for SocksError<C> {
94    fn from(err: std::io::Error) -> Self {
95        Self::Io(err)
96    }
97}
98
99impl<C> From<ParsingError> for SocksError<C> {
100    fn from(err: ParsingError) -> Self {
101        Self::Parsing(err)
102    }
103}
104
105impl<C> From<SerializeError> for SocksError<C> {
106    fn from(err: SerializeError) -> Self {
107        Self::Serialize(err)
108    }
109}
110
111impl<C> From<SocksV4Error> for SocksError<C> {
112    fn from(err: SocksV4Error) -> Self {
113        Self::V4(err)
114    }
115}
116
117impl<C> From<SocksV5Error> for SocksError<C> {
118    fn from(err: SocksV5Error) -> Self {
119        Self::V5(err)
120    }
121}