hyper_util/client/legacy/connect/proxy/socks/
mod.rs1mod v5;
2pub use v5::{SocksV5, SocksV5Error};
3
4mod v4;
5pub use v4::{SocksV4, SocksV4Error};
6
7use pin_project_lite::pin_project;
8use std::future::Future;
9use std::pin::Pin;
10use std::task::{Context, Poll};
11
12use bytes::BytesMut;
13
14use hyper::rt::Read;
15
16#[derive(Debug)]
17pub enum SocksError<C> {
18 Inner(C),
19 Io(std::io::Error),
20
21 DnsFailure,
22 MissingHost,
23 MissingPort,
24
25 V4(SocksV4Error),
26 V5(SocksV5Error),
27
28 Parsing(ParsingError),
29 Serialize(SerializeError),
30}
31
32#[derive(Debug)]
33pub enum ParsingError {
34 Incomplete,
35 WouldOverflow,
36 Other,
37}
38
39#[derive(Debug)]
40pub enum SerializeError {
41 WouldOverflow,
42}
43
44async fn read_message<T, M, C>(mut conn: &mut T, buf: &mut BytesMut) -> Result<M, SocksError<C>>
45where
46 T: Read + Unpin,
47 M: for<'a> TryFrom<&'a mut BytesMut, Error = ParsingError>,
48{
49 let mut tmp = [0; 513];
50
51 loop {
52 let n = crate::rt::read(&mut conn, &mut tmp).await?;
53 buf.extend_from_slice(&tmp[..n]);
54
55 match M::try_from(buf) {
56 Err(ParsingError::Incomplete) => {
57 if n == 0 {
58 if buf.spare_capacity_mut().is_empty() {
59 return Err(SocksError::Parsing(ParsingError::WouldOverflow));
60 } else {
61 return Err(std::io::Error::new(
62 std::io::ErrorKind::UnexpectedEof,
63 "unexpected eof",
64 )
65 .into());
66 }
67 }
68 }
69 Err(err) => return Err(err.into()),
70 Ok(res) => return Ok(res),
71 }
72 }
73}
74
75impl<C> std::fmt::Display for SocksError<C> {
76 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
77 f.write_str("SOCKS error: ")?;
78
79 match self {
80 Self::Inner(_) => f.write_str("failed to create underlying connection"),
81 Self::Io(_) => f.write_str("io error during SOCKS handshake"),
82
83 Self::DnsFailure => f.write_str("could not resolve to acceptable address type"),
84 Self::MissingHost => f.write_str("missing destination host"),
85 Self::MissingPort => f.write_str("missing destination port"),
86
87 Self::Parsing(_) => f.write_str("failed parsing server response"),
88 Self::Serialize(_) => f.write_str("failed serialize request"),
89
90 Self::V4(e) => e.fmt(f),
91 Self::V5(e) => e.fmt(f),
92 }
93 }
94}
95
96impl<C: std::fmt::Debug + std::fmt::Display> std::error::Error for SocksError<C> {}
97
98impl<C> From<std::io::Error> for SocksError<C> {
99 fn from(err: std::io::Error) -> Self {
100 Self::Io(err)
101 }
102}
103
104impl<C> From<ParsingError> for SocksError<C> {
105 fn from(err: ParsingError) -> Self {
106 Self::Parsing(err)
107 }
108}
109
110impl<C> From<SerializeError> for SocksError<C> {
111 fn from(err: SerializeError) -> Self {
112 Self::Serialize(err)
113 }
114}
115
116impl<C> From<SocksV4Error> for SocksError<C> {
117 fn from(err: SocksV4Error) -> Self {
118 Self::V4(err)
119 }
120}
121
122impl<C> From<SocksV5Error> for SocksError<C> {
123 fn from(err: SocksV5Error) -> Self {
124 Self::V5(err)
125 }
126}
127
128pin_project! {
129 #[must_use = "futures do nothing unless polled"]
135 #[allow(missing_debug_implementations)]
136 pub struct Handshaking<F, T, E> {
137 #[pin]
138 fut: BoxHandshaking<T, E>,
139 _marker: std::marker::PhantomData<F>
140 }
141}
142
143type BoxHandshaking<T, E> = Pin<Box<dyn Future<Output = Result<T, SocksError<E>>> + Send>>;
144
145impl<F, T, E> Future for Handshaking<F, T, E>
146where
147 F: Future<Output = Result<T, E>>,
148{
149 type Output = Result<T, SocksError<E>>;
150
151 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
152 self.project().fut.poll(cx)
153 }
154}