proxy_stream/
lib.rs

1pub mod address;
2mod error;
3mod socks;
4
5use address::ToSocketDestination;
6use error::ProxyStreamError;
7use socks::{AuthMethod, InterruptedSocks5, Socks5};
8use tokio::io::{AsyncRead, AsyncWrite};
9
10pub trait AsyncSocket: AsyncRead + AsyncWrite + Unpin + Send + 'static {}
11impl<T> AsyncSocket for T where T: AsyncRead + AsyncWrite + Unpin + Send + 'static {}
12
13pub enum ProxyType {
14    SOCKS5,
15}
16pub struct ProxyStream {
17    proxy_type: ProxyType,
18}
19
20pub enum InterruptedStream {
21    Socks5(InterruptedSocks5),
22}
23
24impl InterruptedStream {
25    pub async fn serve(self, stream: impl AsyncSocket) -> Result<(), ProxyStreamError> {
26        match self {
27            InterruptedStream::Socks5(socks) => socks.serve(stream).await,
28        }
29    }
30    pub async fn connect(self) -> Result<impl AsyncSocket, ProxyStreamError> {
31        match self {
32            InterruptedStream::Socks5(socks) => socks.connect().await,
33        }
34    }
35    pub async fn replay_error(self, replay: ReplayError) -> Result<(), ProxyStreamError> {
36        match self {
37            InterruptedStream::Socks5(socks) => socks.replay_error(replay.into()).await,
38        }
39    }
40    pub fn addr(&self) -> &address::DestinationAddress {
41        match self {
42            InterruptedStream::Socks5(socks) => &socks.addr,
43        }
44    }
45    pub fn command(&self) -> Command {
46        match self {
47            InterruptedStream::Socks5(socks) => socks.command.into(),
48        }
49    }
50}
51#[derive(PartialEq)]
52pub enum Command {
53    Connect,
54    Bind,
55    UdpAssociate,
56}
57
58pub enum ReplayError {
59    GeneralSocksServerFailure,
60    ConnectionNotAllowedByRuleset,
61    NetworkUnreachable,
62    HostUnreachable,
63    ConnectionRefused,
64    TtlExpired,
65    CommandNotSupported,
66    AddressTypeNotSupported,
67}
68
69impl ProxyStream {
70    pub fn new(proxy_type: ProxyType) -> Self {
71        ProxyStream { proxy_type }
72    }
73    pub async fn accept(
74        &self,
75        stream: impl AsyncSocket,
76    ) -> Result<InterruptedStream, ProxyStreamError> {
77        match self.proxy_type {
78            ProxyType::SOCKS5 => {
79                let socks = Socks5::new(vec![AuthMethod::Noauth])?;
80                Ok(InterruptedStream::Socks5(socks.accept(stream).await?))
81            }
82        }
83    }
84    pub async fn connect(
85        &self,
86        stream: impl AsyncSocket,
87        addr: impl ToSocketDestination,
88    ) -> Result<impl AsyncSocket, ProxyStreamError> {
89        match self.proxy_type {
90            ProxyType::SOCKS5 => {
91                let socks = Socks5::new(vec![AuthMethod::Noauth])?;
92                socks.connect(stream, socks::Command::Connect, addr).await
93            }
94        }
95    }
96}