proxy_stream/
address.rs

1use std::net::SocketAddr;
2
3use crate::error::ProxyStreamError;
4
5#[derive(Debug, Clone)]
6pub enum DestinationAddress {
7    Domain(String, u16),
8    Ip(SocketAddr),
9}
10
11impl DestinationAddress {
12    pub fn to_bytes(&self) -> Vec<u8> {
13        match self {
14            DestinationAddress::Domain(domain, port) => {
15                [domain.as_bytes(), port.to_be_bytes().as_ref()].concat()
16            }
17            DestinationAddress::Ip(addr) => match addr {
18                SocketAddr::V4(addr) => {
19                    [&addr.ip().octets(), addr.port().to_be_bytes().as_ref()].concat()
20                }
21                SocketAddr::V6(addr) => {
22                    [&addr.ip().octets(), addr.port().to_be_bytes().as_ref()].concat()
23                }
24            },
25        }
26    }
27    pub fn from_bytes(buf: &[u8], ip: bool) -> Result<Self, ProxyStreamError> {
28        if buf.len() < 3 {
29            return Err(ProxyStreamError::InvalidAddress);
30        }
31        if ip {
32            let port = u16::from_be_bytes([buf[buf.len() - 2], buf[buf.len() - 1]]);
33            let ip = match buf.len() {
34                6 => {
35                    let mut octets = [0; 4];
36                    octets.copy_from_slice(&buf[0..4]);
37                    SocketAddr::V4(std::net::SocketAddrV4::new(
38                        std::net::Ipv4Addr::new(octets[0], octets[1], octets[2], octets[3]),
39                        port,
40                    ))
41                }
42                18 => {
43                    let mut octets = [0; 16];
44                    octets.copy_from_slice(&buf[0..16]);
45                    SocketAddr::V6(std::net::SocketAddrV6::new(
46                        std::net::Ipv6Addr::new(
47                            u16::from_be_bytes([octets[0], octets[1]]),
48                            u16::from_be_bytes([octets[2], octets[3]]),
49                            u16::from_be_bytes([octets[4], octets[5]]),
50                            u16::from_be_bytes([octets[6], octets[7]]),
51                            u16::from_be_bytes([octets[8], octets[9]]),
52                            u16::from_be_bytes([octets[10], octets[11]]),
53                            u16::from_be_bytes([octets[12], octets[13]]),
54                            u16::from_be_bytes([octets[14], octets[15]]),
55                        ),
56                        port,
57                        0,
58                        0,
59                    ))
60                }
61                _ => return Err(ProxyStreamError::InvalidAddress),
62            };
63            Ok(DestinationAddress::Ip(ip))
64        } else {
65            let port = u16::from_be_bytes([buf[buf.len() - 2], buf[buf.len() - 1]]);
66            let domain = String::from_utf8_lossy(&buf[0..buf.len() - 2]).to_string();
67            Ok(DestinationAddress::Domain(domain, port))
68        }
69    }
70}
71
72impl Default for DestinationAddress {
73    fn default() -> Self {
74        DestinationAddress::Ip(SocketAddr::from(([0, 0, 0, 0], 0)))
75    }
76}
77pub trait ToSocketDestination {
78    fn to_destination_address(&self) -> Result<DestinationAddress, ProxyStreamError>;
79}
80
81impl ToSocketDestination for SocketAddr {
82    fn to_destination_address(&self) -> Result<DestinationAddress, ProxyStreamError> {
83        Ok(DestinationAddress::Ip(*self))
84    }
85}
86
87impl ToSocketDestination for &str {
88    fn to_destination_address(&self) -> Result<DestinationAddress, ProxyStreamError> {
89        if let Ok(ip) = self.parse::<SocketAddr>() {
90            return Ok(DestinationAddress::Ip(ip));
91        }
92        self.rsplit_once(':')
93            .and_then(|(domain, port)| {
94                port.parse::<u16>()
95                    .ok()
96                    .map(|port| DestinationAddress::Domain(domain.to_string(), port))
97            })
98            .ok_or(ProxyStreamError::InvalidAddress)
99    }
100}
101
102impl From<&DestinationAddress> for (String, u16) {
103    fn from(value: &DestinationAddress) -> Self {
104        match value {
105            DestinationAddress::Domain(domain, port) => (domain.to_owned(), *port),
106            DestinationAddress::Ip(addr) => match addr {
107                SocketAddr::V4(addr) => (addr.ip().to_string(), addr.port()),
108                SocketAddr::V6(addr) => (addr.ip().to_string(), addr.port()),
109            },
110        }
111    }
112}