1use bytes::{BufMut, BytesMut};
2
3use crate::v5::Address;
4
5#[derive(Debug, Clone)]
16pub enum Response<'a> {
17 Success(&'a Address),
18 GeneralFailure,
19 ConnectionNotAllowed,
20 NetworkUnreachable,
21 HostUnreachable,
22 ConnectionRefused,
23 TTLExpired,
24 CommandNotSupported,
25 AddressTypeNotSupported,
26 Unassigned(u8),
27}
28
29#[rustfmt::skip]
30impl Response<'_> {
31 const SOCKS5_REPLY_SUCCEEDED: u8 = 0x00;
32 const SOCKS5_REPLY_GENERAL_FAILURE: u8 = 0x01;
33 const SOCKS5_REPLY_CONNECTION_NOT_ALLOWED: u8 = 0x02;
34 const SOCKS5_REPLY_NETWORK_UNREACHABLE: u8 = 0x03;
35 const SOCKS5_REPLY_HOST_UNREACHABLE: u8 = 0x04;
36 const SOCKS5_REPLY_CONNECTION_REFUSED: u8 = 0x05;
37 const SOCKS5_REPLY_TTL_EXPIRED: u8 = 0x06;
38 const SOCKS5_REPLY_COMMAND_NOT_SUPPORTED: u8 = 0x07;
39 const SOCKS5_REPLY_ADDRESS_TYPE_NOT_SUPPORTED: u8 = 0x08;
40}
41
42impl Response<'_> {
43 #[inline]
44 pub fn to_bytes(&self) -> BytesMut {
45 let mut bytes = BytesMut::new();
46
47 let (reply, address) = match &self {
48 Self::GeneralFailure
49 | Self::ConnectionNotAllowed
50 | Self::NetworkUnreachable
51 | Self::HostUnreachable
52 | Self::ConnectionRefused
53 | Self::TTLExpired
54 | Self::CommandNotSupported
55 | Self::AddressTypeNotSupported => (self.as_u8(), Address::unspecified()),
56 Self::Unassigned(code) => (*code, Address::unspecified()),
57 Self::Success(address) => (self.as_u8(), *address),
58 };
59
60 bytes.put_u8(reply);
61 bytes.put_u8(0x00);
62 bytes.extend(address.to_bytes());
63
64 bytes
65 }
66
67 #[rustfmt::skip]
68 #[inline]
69 fn as_u8(&self) -> u8 {
70 match self {
71 Self::Success(_) => Self::SOCKS5_REPLY_SUCCEEDED,
72 Self::GeneralFailure => Self::SOCKS5_REPLY_GENERAL_FAILURE,
73 Self::ConnectionNotAllowed => Self::SOCKS5_REPLY_CONNECTION_NOT_ALLOWED,
74 Self::NetworkUnreachable => Self::SOCKS5_REPLY_NETWORK_UNREACHABLE,
75 Self::HostUnreachable => Self::SOCKS5_REPLY_HOST_UNREACHABLE,
76 Self::ConnectionRefused => Self::SOCKS5_REPLY_CONNECTION_REFUSED,
77 Self::TTLExpired => Self::SOCKS5_REPLY_TTL_EXPIRED,
78 Self::CommandNotSupported => Self::SOCKS5_REPLY_COMMAND_NOT_SUPPORTED,
79 Self::AddressTypeNotSupported => Self::SOCKS5_REPLY_ADDRESS_TYPE_NOT_SUPPORTED,
80 Self::Unassigned(code) => *code
81 }
82 }
83}