Skip to main content

socks5_impl/protocol/
mod.rs

1mod address;
2mod command;
3pub mod handshake;
4mod proxy_parameters;
5mod reply;
6mod request;
7mod response;
8mod udp;
9
10pub use self::{
11    address::{Address, AddressType},
12    command::Command,
13    handshake::{
14        AuthMethod,
15        password_method::{self, UserKey},
16    },
17    proxy_parameters::{ProxyParameters, ProxyType},
18    reply::Reply,
19    request::Request,
20    response::Response,
21    udp::UdpHeader,
22};
23pub use ::bytes::BufMut;
24pub use ::url::Url;
25
26#[cfg(feature = "tokio")]
27use tokio::io::{AsyncRead, AsyncWrite, AsyncWriteExt};
28
29/// SOCKS protocol version, either 4 or 5
30#[repr(u8)]
31#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default)]
32pub enum Version {
33    V4 = 4,
34    #[default]
35    V5 = 5,
36}
37
38impl TryFrom<u8> for Version {
39    type Error = std::io::Error;
40
41    fn try_from(value: u8) -> std::io::Result<Self> {
42        match value {
43            4 => Ok(Version::V4),
44            5 => Ok(Version::V5),
45            _ => Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "invalid version")),
46        }
47    }
48}
49
50impl From<Version> for u8 {
51    fn from(v: Version) -> Self {
52        v as u8
53    }
54}
55
56impl std::fmt::Display for Version {
57    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
58        let v: u8 = (*self).into();
59        write!(f, "{v}")
60    }
61}
62
63pub trait StreamOperation {
64    fn retrieve_from_stream<R>(stream: &mut R) -> std::io::Result<Self>
65    where
66        R: std::io::Read,
67        Self: Sized;
68
69    fn write_to_stream<W: std::io::Write>(&self, w: &mut W) -> std::io::Result<()> {
70        let len = self.len();
71        let mut buf = bytes::BytesMut::with_capacity(len);
72        self.write_to_buf(&mut buf);
73        w.write_all(&buf)
74    }
75
76    fn write_to_buf<B: bytes::BufMut>(&self, buf: &mut B);
77
78    fn len(&self) -> usize;
79
80    fn is_empty(&self) -> bool {
81        self.len() == 0
82    }
83}
84
85#[cfg(feature = "tokio")]
86#[async_trait::async_trait]
87pub trait AsyncStreamOperation: StreamOperation {
88    async fn retrieve_from_async_stream<R>(r: &mut R) -> std::io::Result<Self>
89    where
90        R: AsyncRead + Unpin + Send + ?Sized,
91        Self: Sized;
92
93    async fn write_to_async_stream<W>(&self, w: &mut W) -> std::io::Result<()>
94    where
95        W: AsyncWrite + Unpin + Send + ?Sized,
96    {
97        let mut buf = bytes::BytesMut::with_capacity(self.len());
98        self.write_to_buf(&mut buf);
99        w.write_all(&buf).await
100    }
101}