dust_devil_core/
socks5.rs1use std::{
5 io::{Error, ErrorKind},
6 net::{Ipv4Addr, Ipv6Addr},
7};
8
9use tokio::io::{AsyncRead, AsyncWrite};
10
11use crate::{
12 serialize::{ByteRead, ByteWrite, SmallReadString, SmallWriteString},
13 u8_repr_enum::U8ReprEnum,
14};
15
16#[derive(Debug, Clone, PartialEq, Eq)]
18pub enum SocksRequestAddress {
19 IPv4(Ipv4Addr),
20 IPv6(Ipv6Addr),
21 Domainname(String),
22}
23
24impl ByteWrite for SocksRequestAddress {
25 async fn write<W: AsyncWrite + Unpin + ?Sized>(&self, writer: &mut W) -> Result<(), Error> {
26 match self {
27 Self::IPv4(v4) => (4u8, v4).write(writer).await,
28 Self::IPv6(v6) => (6u8, v6).write(writer).await,
29 Self::Domainname(domainname) => (200u8, SmallWriteString(domainname)).write(writer).await,
30 }
31 }
32}
33
34impl ByteRead for SocksRequestAddress {
35 async fn read<R: AsyncRead + Unpin + ?Sized>(reader: &mut R) -> Result<Self, Error> {
36 match u8::read(reader).await? {
37 4 => Ok(SocksRequestAddress::IPv4(Ipv4Addr::read(reader).await?)),
38 6 => Ok(SocksRequestAddress::IPv6(Ipv6Addr::read(reader).await?)),
39 200 => Ok(SocksRequestAddress::Domainname(SmallReadString::read(reader).await?.0)),
40 _ => Err(Error::new(ErrorKind::InvalidData, "Invalid SocksRequestAddress type byte")),
41 }
42 }
43}
44
45pub struct SocksRequest {
47 pub destination: SocksRequestAddress,
48 pub port: u16,
49}
50
51impl SocksRequest {
52 pub fn new(destination: SocksRequestAddress, port: u16) -> Self {
53 Self { destination, port }
54 }
55
56 pub fn from_ipv4(ipv4: Ipv4Addr, port: u16) -> Self {
57 SocksRequest {
58 destination: SocksRequestAddress::IPv4(ipv4),
59 port,
60 }
61 }
62
63 pub fn from_ipv6(ipv6: Ipv6Addr, port: u16) -> Self {
64 SocksRequest {
65 destination: SocksRequestAddress::IPv6(ipv6),
66 port,
67 }
68 }
69
70 pub fn from_domainname(domainname: String, port: u16) -> Self {
71 SocksRequest {
72 destination: SocksRequestAddress::Domainname(domainname),
73 port,
74 }
75 }
76}
77
78impl ByteWrite for SocksRequest {
79 async fn write<W: AsyncWrite + Unpin + ?Sized>(&self, writer: &mut W) -> Result<(), Error> {
80 (&self.destination, self.port).write(writer).await
81 }
82}
83
84impl ByteRead for SocksRequest {
85 async fn read<R: AsyncRead + Unpin + ?Sized>(reader: &mut R) -> Result<Self, Error> {
86 Ok(SocksRequest::new(
87 SocksRequestAddress::read(reader).await?,
88 u16::read(reader).await?,
89 ))
90 }
91}
92
93#[repr(u8)]
95#[derive(Debug, Clone, Copy, PartialEq, Eq)]
96pub enum AuthMethod {
97 NoAuth = 0x00,
98 UsernameAndPassword = 0x02,
100}
101
102impl U8ReprEnum for AuthMethod {
103 fn from_u8(value: u8) -> Option<Self> {
104 match value {
105 0x00 => Some(AuthMethod::NoAuth),
106 0x02 => Some(AuthMethod::UsernameAndPassword),
108 _ => None,
109 }
110 }
111
112 fn into_u8(self) -> u8 {
113 self as u8
114 }
115}
116
117impl ByteWrite for AuthMethod {
118 async fn write<W: AsyncWrite + Unpin + ?Sized>(&self, writer: &mut W) -> Result<(), Error> {
119 self.into_u8().write(writer).await
120 }
121}
122
123impl ByteRead for AuthMethod {
124 async fn read<R: AsyncRead + Unpin + ?Sized>(reader: &mut R) -> Result<Self, Error> {
125 match Self::from_u8(u8::read(reader).await?) {
126 Some(value) => Ok(value),
127 None => Err(Error::new(ErrorKind::InvalidData, "Invalid AuthMethod type byte")),
128 }
129 }
130}
131
132impl AuthMethod {
133 pub const fn to_str(&self) -> &'static str {
135 match self {
136 Self::NoAuth => "noauth",
137 Self::UsernameAndPassword => "userpass",
138 }
139 }
140}
141
142impl std::fmt::Display for AuthMethod {
143 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
144 write!(f, "{}", self.to_str())
145 }
146}