1#![feature(io_error_more)]
2
3use crate::errors::{InvalidPackageKind, SocksError, SocksResult};
87use std::io::ErrorKind;
88use std::net::{IpAddr, Ipv4Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
89
90pub(crate) const SOCKS5_RSV_BYTE: u8 = 0x00;
91pub(crate) const SOCKS5_VERSION: u8 = 0x05;
92pub(crate) const SUB_NEG_VERSION: u8 = 0x01;
93
94pub(crate) const DEFAULT_SERVER_ADDR: SocketAddr =
95 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
96
97#[derive(Debug, Copy, Clone)]
98pub(crate) struct PrivateStruct;
99
100#[derive(Debug, PartialEq, Eq, Ord, PartialOrd, Hash, Copy, Clone)]
101pub(crate) struct AuthMethod(u8);
102
103impl AuthMethod {
104 pub const SKIP: AuthMethod = AuthMethod(0x00);
105 pub const PASS: AuthMethod = AuthMethod(0x02);
106 pub const FAIL: AuthMethod = AuthMethod(0xFF);
107}
108
109impl AuthMethod {
110 fn from_byte(byte: u8) -> SocksResult<AuthMethod> {
111 match byte {
112 0x00 => Ok(AuthMethod::SKIP),
113 0x02 => Ok(AuthMethod::PASS),
114 _ => Ok(AuthMethod(byte)),
115 }
116 }
117
118 pub fn to_byte(&self) -> u8 {
119 self.0
120 }
121}
122
123#[derive(Debug, Clone)]
124pub(crate) struct AuthMethods {
125 methods: Vec<AuthMethod>,
126 _private: PrivateStruct,
127}
128
129impl AuthMethods {
130 pub fn new() -> AuthMethods {
131 return AuthMethods {
132 methods: Vec::with_capacity(2),
133 _private: PrivateStruct,
134 };
135 }
136
137 pub fn insert(&mut self, method: AuthMethod) -> bool {
138 return match self.methods.binary_search(&method) {
139 Ok(_) => false,
140 Err(index) => {
141 self.methods.insert(index, method);
142 true
143 }
144 };
145 }
146
147 pub fn contains(&self, method: &AuthMethod) -> bool {
148 return self.methods.binary_search(method).is_ok();
149 }
150
151 pub fn len(&self) -> usize {
152 return self.methods.len();
153 }
154
155 pub fn iter(&self) -> std::slice::Iter<'_, AuthMethod> {
156 return self.methods.iter();
157 }
158}
159
160#[derive(Debug, PartialEq, Eq, Ord, PartialOrd, Hash, Copy, Clone)]
161pub(crate) struct RequestCmd(u8);
162
163impl RequestCmd {
164 pub const CONNECT: RequestCmd = RequestCmd(0x01);
165 pub const BIND: RequestCmd = RequestCmd(0x02);
166 pub const UDP: RequestCmd = RequestCmd(0x03);
167}
168
169impl RequestCmd {
170 fn from_byte(byte: u8) -> SocksResult<RequestCmd> {
171 match byte {
172 0x01 => Ok(RequestCmd::CONNECT),
173 0x02 => Ok(RequestCmd::BIND),
174 0x03 => Ok(RequestCmd::UDP),
175 _ => Err(SocksError::InvalidPackageErr(
176 InvalidPackageKind::InvalidRequestsCmd(byte),
177 )),
178 }
179 }
180
181 fn to_byte(&self) -> u8 {
182 self.0
183 }
184}
185
186#[derive(Debug, PartialEq, Eq, Ord, PartialOrd, Hash, Copy, Clone)]
187pub(crate) struct RepliesRep(u8);
188
189impl RepliesRep {
190 pub const SUCCESS: RepliesRep = RepliesRep(0x00);
191 pub const SOCKS_SERVER_FAILURE: RepliesRep = RepliesRep(0x01);
192 pub const NOT_ALLOWED_BY_RULESET: RepliesRep = RepliesRep(0x02);
193 pub const NETWORK_UNREACHABLE: RepliesRep = RepliesRep(0x03);
194 pub const HOST_UNREACHABLE: RepliesRep = RepliesRep(0x04);
195 pub const CONNECTION_REFUSED: RepliesRep = RepliesRep(0x05);
196 pub const TTL_EXPIRED: RepliesRep = RepliesRep(0x06);
197 pub const COMMAND_NOT_SUPPORTED: RepliesRep = RepliesRep(0x07);
198 pub const ADDR_TYPE_NOT_SUPPORTED: RepliesRep = RepliesRep(0x08);
199}
200
201impl RepliesRep {
202 fn message(&self) -> &'static str {
203 match self {
204 &RepliesRep::SUCCESS => "succeeded",
205 &RepliesRep::SOCKS_SERVER_FAILURE => "general SOCKS server failure",
206 &RepliesRep::NOT_ALLOWED_BY_RULESET => "connection not allowed by ruleset",
207 &RepliesRep::NETWORK_UNREACHABLE => "network unreachable",
208 &RepliesRep::HOST_UNREACHABLE => "host unreachable",
209 &RepliesRep::CONNECTION_REFUSED => "connection refused",
210 &RepliesRep::TTL_EXPIRED => "TTL expired",
211 &RepliesRep::COMMAND_NOT_SUPPORTED => "command not supported",
212 &RepliesRep::ADDR_TYPE_NOT_SUPPORTED => "address type not supported",
213 _ => "unassigned",
214 }
215 }
216}
217
218impl From<&std::io::Error> for RepliesRep {
219 fn from(value: &std::io::Error) -> Self {
220 match value.kind() {
221 ErrorKind::NetworkUnreachable
222 | ErrorKind::AddrNotAvailable
223 | ErrorKind::NetworkDown => RepliesRep::NETWORK_UNREACHABLE,
224 ErrorKind::HostUnreachable => RepliesRep::HOST_UNREACHABLE,
225 ErrorKind::ConnectionReset
226 | ErrorKind::ConnectionAborted
227 | ErrorKind::ConnectionRefused => RepliesRep::CONNECTION_REFUSED,
228 ErrorKind::TimedOut => RepliesRep::TTL_EXPIRED,
229 _ => RepliesRep::SOCKS_SERVER_FAILURE,
230 }
231 }
232}
233
234impl RepliesRep {
235 fn from_byte(byte: u8) -> SocksResult<RepliesRep> {
236 match byte {
237 0x00 => Ok(RepliesRep::SUCCESS),
238 0x01 => Ok(RepliesRep::SOCKS_SERVER_FAILURE),
239 0x02 => Ok(RepliesRep::NOT_ALLOWED_BY_RULESET),
240 0x03 => Ok(RepliesRep::NETWORK_UNREACHABLE),
241 0x04 => Ok(RepliesRep::HOST_UNREACHABLE),
242 0x05 => Ok(RepliesRep::CONNECTION_REFUSED),
243 0x06 => Ok(RepliesRep::TTL_EXPIRED),
244 0x07 => Ok(RepliesRep::COMMAND_NOT_SUPPORTED),
245 0x08 => Ok(RepliesRep::ADDR_TYPE_NOT_SUPPORTED),
246 _ => Ok(RepliesRep(byte)),
247 }
248 }
249
250 pub fn to_byte(&self) -> u8 {
251 self.0
252 }
253}
254
255#[derive(Debug)]
260pub enum SocksAddr {
261 IPV4(SocketAddrV4),
262 IPV6(SocketAddrV6),
263 Domain(String, u16),
264}
265
266impl SocksAddr {
267 pub const KIND_IPV4: u8 = 0x01;
269
270 pub const KIND_IPV6: u8 = 0x04;
272
273 pub const KIND_DOMAIN: u8 = 0x03;
275
276 pub const UNSPECIFIED_ADDR: SocksAddr =
277 SocksAddr::IPV4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080));
278}
279
280impl SocksAddr {
281 pub fn addr_type(&self) -> u8 {
282 match self {
283 SocksAddr::IPV4(_) => 0x01,
284 SocksAddr::IPV6(_) => 0x04,
285 SocksAddr::Domain(_, _) => 0x03,
286 }
287 }
288}
289
290pub trait ToSocksAddress {
292 fn to_socks_addr(self) -> SocksAddr;
294}
295
296impl ToSocksAddress for SocketAddrV4 {
297 fn to_socks_addr(self) -> SocksAddr {
298 return SocksAddr::IPV4(self);
299 }
300}
301
302impl ToSocksAddress for SocketAddrV6 {
303 fn to_socks_addr(self) -> SocksAddr {
304 return SocksAddr::IPV6(self);
305 }
306}
307
308impl ToSocksAddress for (String, u16) {
309 fn to_socks_addr(self) -> SocksAddr {
310 return SocksAddr::Domain(self.0, self.1);
311 }
312}
313
314impl ToSocksAddress for SocketAddr {
315 fn to_socks_addr(self) -> SocksAddr {
316 return match self {
317 SocketAddr::V4(addr) => SocksAddr::IPV4(addr),
318 SocketAddr::V6(addr) => SocksAddr::IPV6(addr),
319 };
320 }
321}
322
323pub(crate) fn is_invalid_username(username: &[u8]) -> bool {
324 return username.is_empty() || username.len() > 255;
325}
326
327pub(crate) fn is_invalid_password(password: &[u8]) -> bool {
328 return password.is_empty() || password.len() > 255;
329}
330
331pub mod client;
332pub mod errors;
333mod package;
334pub mod server;