1use std::error::Error;
2use std::fmt::{self, Display, Formatter};
3use std::net::{Ipv4Addr, Ipv6Addr};
4use std::str::FromStr;
5
6#[derive(Debug)]
7struct InvalidAddressType;
8
9impl Display for InvalidAddressType {
10 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
11 write!(f, "invalid address type")
12 }
13}
14
15impl Error for InvalidAddressType {}
16
17#[derive(Debug, PartialEq)]
18pub struct AddrInfo {
19 pub host: String,
20 pub port: u16,
21}
22
23impl AddrInfo {
24 pub fn from_buffer(buffer: &[u8]) -> Result<Self, Box<dyn Error>> {
25 match buffer.first() {
26 Some(&1) => {
27 let mut ip = [0; 4];
28 ip.copy_from_slice(&buffer[1..=4]);
29 let host = Ipv4Addr::from(ip).to_string();
30 let port = u16::from_be_bytes([buffer[buffer.len() - 2], buffer.last().copied().unwrap_or(0x00)]);
31 Ok(AddrInfo { host, port })
32 }
33
34 Some(&3) => {
35 let domain_length: usize = buffer[1] as usize;
36 let domain_end = 2 + domain_length;
38 let host: String = String::from_utf8_lossy(&buffer[2..domain_end]).to_string();
39 let port = u16::from_be_bytes([buffer[buffer.len() - 2], buffer.last().copied().unwrap_or(0x00)]);
40 Ok(AddrInfo { host, port })
42 }
43
44 Some(&4) => {
45 let mut ip = [0; 16];
46 ip.copy_from_slice(&buffer[1..=16]);
47 let host = Ipv6Addr::from(ip).to_string();
48 let port = u16::from_be_bytes([buffer[buffer.len() - 2], buffer.last().copied().unwrap_or(0x00)]);
49 Ok(AddrInfo { host, port })
50 }
51
52 _ => Err(Box::new(InvalidAddressType)),
53 }
54 }
55}
56
57pub fn build_socks5_buffer(host: &str, port: u16) -> Result<Vec<u8>, Box<dyn Error>> {
58 if let Ok(ipv4_host) = Ipv4Addr::from_str(host) {
59 Ok(vec![1].into_iter().chain(ipv4_host.octets().iter().copied()).chain(port.to_be_bytes().iter().copied()).collect())
60 } else if let Ok(ipv6_host) = Ipv6Addr::from_str(host) {
61 Ok(vec![4].into_iter().chain(ipv6_host.octets().iter().copied()).chain(port.to_be_bytes().iter().copied()).collect())
62 } else {
63 let domain_length = host.len();
64 let mut buffer = vec![3, domain_length as u8];
65 buffer.extend_from_slice(host.as_bytes());
66 buffer.extend_from_slice(&port.to_be_bytes());
67 Ok(buffer)
68 }
69}