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}