socks_lib/v5/
address.rs

1use std::io;
2use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
3use std::sync::LazyLock;
4
5use bytes::{Buf, BufMut, Bytes, BytesMut};
6
7use crate::io::{AsyncRead, AsyncReadExt};
8
9/// # Address
10///
11/// ```text
12///  +------+----------+----------+
13///  | ATYP | DST.ADDR | DST.PORT |
14///  +------+----------+----------+
15///  |  1   | Variable |    2     |
16///  +------+----------+----------+
17/// ```
18///
19/// ## DST.ADDR BND.ADDR
20///   In an address field (DST.ADDR, BND.ADDR), the ATYP field specifies
21///   the type of address contained within the field:
22///   
23/// o ATYP: X'01'
24///   the address is a version-4 IP address, with a length of 4 octets
25///   
26/// o ATYP: X'03'
27///   the address field contains a fully-qualified domain name.  The first
28///   octet of the address field contains the number of octets of name that
29///   follow, there is no terminating NUL octet.
30///   
31/// o ATYP: X'04'  
32///   the address is a version-6 IP address, with a length of 16 octets.
33///
34#[derive(Debug, Clone, PartialEq)]
35pub enum Address {
36    IPv4(SocketAddrV4),
37    IPv6(SocketAddrV6),
38    Domain(Domain, u16),
39}
40
41static UNSPECIFIED_ADDRESS: LazyLock<Address> =
42    LazyLock::new(|| Address::IPv4(SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, 0)));
43
44#[rustfmt::skip]
45impl Address {
46    pub const PORT_LENGTH:         usize = 2;
47    pub const IPV4_ADDRESS_LENGTH: usize = 4;
48    pub const IPV6_ADDRESS_LENGTH: usize = 16;
49
50    pub const SOCKS5_ADDRESS_TYPE_IPV4:        u8 = 0x01;
51    pub const SOCKS5_ADDRESS_TYPE_DOMAIN_NAME: u8 = 0x03;
52    pub const SOCKS5_ADDRESS_TYPE_IPV6:        u8 = 0x04;
53}
54
55impl Address {
56    #[inline]
57    pub fn unspecified() -> &'static Self {
58        &UNSPECIFIED_ADDRESS
59    }
60
61    pub async fn from_async_read<R: AsyncRead + Unpin>(reader: &mut R) -> io::Result<Self> {
62        let address_type = reader.read_u8().await?;
63
64        match address_type {
65            Self::SOCKS5_ADDRESS_TYPE_IPV4 => {
66                let mut buf = [0u8; Self::IPV4_ADDRESS_LENGTH + Self::PORT_LENGTH];
67                reader.read_exact(&mut buf).await?;
68
69                let ip = Ipv4Addr::new(buf[0], buf[1], buf[2], buf[3]);
70                let port = u16::from_be_bytes([buf[4], buf[5]]);
71
72                Ok(Address::IPv4(SocketAddrV4::new(ip, port)))
73            }
74
75            Self::SOCKS5_ADDRESS_TYPE_IPV6 => {
76                let mut buf = [0u8; Self::IPV6_ADDRESS_LENGTH + Self::PORT_LENGTH];
77                reader.read_exact(&mut buf).await?;
78
79                let ip = Ipv6Addr::from([
80                    buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8], buf[9],
81                    buf[10], buf[11], buf[12], buf[13], buf[14], buf[15],
82                ]);
83                let port = u16::from_be_bytes([buf[16], buf[17]]);
84
85                Ok(Address::IPv6(SocketAddrV6::new(ip, port, 0, 0)))
86            }
87
88            Self::SOCKS5_ADDRESS_TYPE_DOMAIN_NAME => {
89                let domain_len = reader.read_u8().await? as usize;
90
91                let mut buf = vec![0u8; domain_len + Self::PORT_LENGTH];
92                reader.read_exact(&mut buf).await?;
93
94                let domain = Bytes::copy_from_slice(&buf[..domain_len]);
95                let port = u16::from_be_bytes([buf[domain_len], buf[domain_len + 1]]);
96
97                Ok(Address::Domain(Domain(domain), port))
98            }
99
100            n => Err(io::Error::new(
101                io::ErrorKind::InvalidData,
102                format!("Invalid address type: {}", n),
103            )),
104        }
105    }
106
107    pub fn from_bytes<B: Buf>(buf: &mut B) -> io::Result<Self> {
108        if buf.remaining() < 1 {
109            return Err(io::Error::new(
110                io::ErrorKind::InvalidData,
111                "Insufficient data for address",
112            ));
113        }
114
115        let address_type = buf.get_u8();
116
117        match address_type {
118            Self::SOCKS5_ADDRESS_TYPE_IPV4 => {
119                if buf.remaining() < Self::IPV4_ADDRESS_LENGTH + Self::PORT_LENGTH {
120                    return Err(io::Error::new(
121                        io::ErrorKind::InvalidData,
122                        "Insufficient data for IPv4 address",
123                    ));
124                }
125
126                let mut ip = [0u8; Self::IPV4_ADDRESS_LENGTH];
127                buf.copy_to_slice(&mut ip);
128
129                let port = buf.get_u16();
130
131                Ok(Address::IPv4(SocketAddrV4::new(Ipv4Addr::from(ip), port)))
132            }
133
134            Self::SOCKS5_ADDRESS_TYPE_IPV6 => {
135                if buf.remaining() < Self::IPV6_ADDRESS_LENGTH + Self::PORT_LENGTH {
136                    return Err(io::Error::new(
137                        io::ErrorKind::InvalidData,
138                        "Insufficient data for IPv6 address",
139                    ));
140                }
141
142                let mut ip = [0u8; Self::IPV6_ADDRESS_LENGTH];
143                buf.copy_to_slice(&mut ip);
144
145                let port = buf.get_u16();
146
147                Ok(Address::IPv6(SocketAddrV6::new(
148                    Ipv6Addr::from(ip),
149                    port,
150                    0,
151                    0,
152                )))
153            }
154
155            Self::SOCKS5_ADDRESS_TYPE_DOMAIN_NAME => {
156                if buf.remaining() < 1 {
157                    return Err(io::Error::new(
158                        io::ErrorKind::InvalidData,
159                        "Insufficient data for domain length",
160                    ));
161                }
162
163                let domain_len = buf.get_u8() as usize;
164
165                if buf.remaining() < domain_len + Self::PORT_LENGTH {
166                    return Err(io::Error::new(
167                        io::ErrorKind::InvalidData,
168                        "Insufficient data for domain name",
169                    ));
170                }
171
172                let mut domain = vec![0u8; domain_len];
173                buf.copy_to_slice(&mut domain);
174
175                let port = buf.get_u16();
176
177                Ok(Address::Domain(Domain(Bytes::from(domain)), port))
178            }
179
180            n => Err(io::Error::new(
181                io::ErrorKind::InvalidData,
182                format!("Invalid address type: {}", n),
183            )),
184        }
185    }
186
187    #[inline]
188    pub fn to_bytes(&self) -> Bytes {
189        let mut bytes = BytesMut::new();
190
191        match self {
192            Self::Domain(domain, port) => {
193                let domain_bytes = domain.as_bytes();
194                bytes.put_u8(Self::SOCKS5_ADDRESS_TYPE_DOMAIN_NAME);
195                bytes.put_u8(domain_bytes.len() as u8);
196                bytes.extend_from_slice(domain_bytes);
197                bytes.extend_from_slice(&port.to_be_bytes());
198            }
199            Self::IPv4(addr) => {
200                bytes.put_u8(Self::SOCKS5_ADDRESS_TYPE_IPV4);
201                bytes.extend_from_slice(&addr.ip().octets());
202                bytes.extend_from_slice(&addr.port().to_be_bytes());
203            }
204            Self::IPv6(addr) => {
205                bytes.put_u8(Self::SOCKS5_ADDRESS_TYPE_IPV6);
206                bytes.extend_from_slice(&addr.ip().octets());
207                bytes.extend_from_slice(&addr.port().to_be_bytes());
208            }
209        }
210
211        bytes.freeze()
212    }
213
214    #[inline]
215    pub fn port(&self) -> u16 {
216        match self {
217            Self::IPv4(addr) => addr.port(),
218            Self::IPv6(addr) => addr.port(),
219            Self::Domain(_, port) => *port,
220        }
221    }
222
223    pub async fn to_socket_addr(self) -> io::Result<SocketAddr> {
224        use tokio::net::lookup_host;
225
226        match self {
227            Address::IPv4(addr) => Ok(SocketAddr::V4(addr)),
228            Address::IPv6(addr) => Ok(SocketAddr::V6(addr)),
229            Address::Domain(domain, port) => {
230                let domain = domain.format_as_str();
231
232                lookup_host((domain, port))
233                    .await?
234                    .next()
235                    .ok_or(io::Error::other(format!(
236                        "Failed to resolve domain {}",
237                        domain
238                    )))
239            }
240        }
241    }
242}
243
244impl From<SocketAddr> for Address {
245    #[inline]
246    fn from(value: SocketAddr) -> Self {
247        match value {
248            SocketAddr::V4(addr) => Self::IPv4(addr),
249            SocketAddr::V6(addr) => Self::IPv6(addr),
250        }
251    }
252}
253
254impl std::fmt::Display for Address {
255    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
256        let value = match self {
257            Self::Domain(domain, port) => format!("{}:{}", domain.format_as_str(), port),
258            Self::IPv4(addr) => addr.to_string(),
259            Self::IPv6(addr) => addr.to_string(),
260        };
261
262        write!(f, "{value}")
263    }
264}
265
266impl TryFrom<&str> for Address {
267    type Error = io::Error;
268
269    #[inline]
270    fn try_from(value: &str) -> Result<Self, Self::Error> {
271        use std::str::FromStr;
272
273        if let Ok(ipv4_addr) = SocketAddrV4::from_str(value) {
274            return Ok(Address::IPv4(ipv4_addr));
275        }
276
277        if let Ok(addr) = SocketAddrV6::from_str(value) {
278            return Ok(Address::IPv6(addr));
279        }
280
281        if let Some((domain, port_str)) = value.rsplit_once(':') {
282            if let Ok(port) = port_str.parse::<u16>() {
283                if !domain.is_empty() {
284                    return Ok(Address::Domain(Domain::try_from(domain)?, port));
285                }
286            }
287        }
288
289        Err(io::Error::new(
290            io::ErrorKind::InvalidInput,
291            format!("Invalid address format: {}", value),
292        ))
293    }
294}
295
296impl TryFrom<String> for Address {
297    type Error = io::Error;
298
299    #[inline]
300    fn try_from(value: String) -> Result<Self, Self::Error> {
301        Address::try_from(value.as_str())
302    }
303}
304
305// ===== Domain =====
306#[derive(Debug, Clone, PartialEq)]
307pub struct Domain(Bytes);
308
309impl Domain {
310    const MAX_LENGTH: usize = 254;
311
312    #[inline]
313    pub fn from_bytes(bytes: Bytes) -> io::Result<Self> {
314        if bytes.is_empty() {
315            return Err(io::Error::new(
316                io::ErrorKind::InvalidData,
317                "Domain is empty",
318            ));
319        }
320
321        let domain_str = std::str::from_utf8(&bytes)
322            .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
323
324        if domain_str.len() > Self::MAX_LENGTH {
325            return Err(io::Error::new(
326                io::ErrorKind::InvalidData,
327                "Punycode domain exceeds maximum length",
328            ));
329        }
330
331        Ok(Self(bytes))
332    }
333
334    #[inline]
335    pub fn from_string(value: String) -> io::Result<Self> {
336        Self::from_bytes(value.into())
337    }
338
339    #[inline]
340    pub fn format_as_str(&self) -> &str {
341        use std::str::from_utf8;
342
343        from_utf8(&self.0).expect("Invalid UTF-8")
344    }
345
346    #[inline]
347    pub fn as_bytes(&self) -> &Bytes {
348        &self.0
349    }
350
351    #[inline]
352    pub fn len(&self) -> usize {
353        self.0.len()
354    }
355
356    #[inline]
357    pub fn is_empty(&self) -> bool {
358        self.0.is_empty()
359    }
360}
361
362impl From<Domain> for Bytes {
363    #[inline]
364    fn from(value: Domain) -> Self {
365        value.0
366    }
367}
368
369impl From<Domain> for Vec<u8> {
370    #[inline]
371    fn from(value: Domain) -> Self {
372        value.0.to_vec()
373    }
374}
375
376impl TryFrom<&[u8]> for Domain {
377    type Error = io::Error;
378
379    #[inline]
380    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
381        Self::from_bytes(Bytes::copy_from_slice(value))
382    }
383}
384
385impl TryFrom<&str> for Domain {
386    type Error = io::Error;
387
388    #[inline]
389    fn try_from(value: &str) -> Result<Self, Self::Error> {
390        Self::from_bytes(Bytes::copy_from_slice(value.as_bytes()))
391    }
392}
393
394impl TryFrom<String> for Domain {
395    type Error = io::Error;
396
397    #[inline]
398    fn try_from(value: String) -> Result<Self, Self::Error> {
399        Self::from_string(value)
400    }
401}
402
403impl TryFrom<Bytes> for Domain {
404    type Error = io::Error;
405
406    #[inline]
407    fn try_from(value: Bytes) -> Result<Self, Self::Error> {
408        Self::from_bytes(value)
409    }
410}
411
412impl AsRef<[u8]> for Domain {
413    #[inline]
414    fn as_ref(&self) -> &[u8] {
415        self.as_bytes()
416    }
417}
418
419#[cfg(test)]
420mod tests {
421    use tokio::io::BufReader;
422
423    use super::*;
424
425    use std::{
426        io::Cursor,
427        net::{Ipv4Addr, Ipv6Addr},
428    };
429
430    #[test]
431    fn test_ipv4_serialization() {
432        let addr = Address::IPv4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080));
433        let bytes = addr.to_bytes();
434        let mut buf = &bytes[..];
435        let parsed = Address::from_bytes(&mut buf).unwrap();
436        assert_eq!(addr, parsed);
437    }
438
439    #[test]
440    fn test_ipv6_serialization() {
441        let addr = Address::IPv6(SocketAddrV6::new(Ipv6Addr::LOCALHOST, 8080, 0, 0));
442        let bytes = addr.to_bytes();
443        let mut buf = &bytes[..];
444        let parsed = Address::from_bytes(&mut buf).unwrap();
445        assert_eq!(addr, parsed);
446    }
447
448    #[test]
449    fn test_domain_serialization() {
450        let domain = Domain::try_from("example.com").unwrap();
451        let addr = Address::Domain(domain, 8080);
452        let bytes = addr.to_bytes();
453        let mut buf = &bytes[..];
454
455        let parsed = Address::from_bytes(&mut buf).unwrap();
456
457        if let Address::Domain(d, p) = parsed {
458            assert_eq!(d.format_as_str(), "example.com");
459            assert_eq!(p, 8080);
460        } else {
461            panic!("Parsed address is not Domain type");
462        }
463    }
464
465    #[test]
466    fn test_invalid_atyp() {
467        let mut buf = bytes::BytesMut::new();
468        buf.put_u8(0x04);
469        let mut buf = buf.freeze();
470        let result = Address::from_bytes(&mut buf);
471        assert!(result.is_err());
472    }
473
474    #[test]
475    fn test_domain_too_long() {
476        let result = Domain::try_from(vec![b'a'; 255].as_slice());
477        assert!(result.is_err())
478    }
479
480    #[tokio::test]
481    async fn test_domain_resolution() {
482        let domain = Domain::try_from("localhost").unwrap();
483        let addr = Address::Domain(domain, 8080);
484        let socket_addr = addr.to_socket_addr().await.unwrap();
485        assert!(socket_addr.port() == 8080);
486    }
487
488    #[test]
489    fn test_domain_utf8_error() {
490        let result = Domain::from_bytes(Bytes::copy_from_slice(vec![0xff, 0xfe].as_slice()));
491        assert!(result.is_err())
492    }
493
494    #[test]
495    fn test_socket_addr_conversion() {
496        let socket_v4 = SocketAddrV4::new(Ipv4Addr::LOCALHOST, 8080);
497        let addr: Address = SocketAddr::V4(socket_v4).into();
498        assert!(matches!(addr, Address::IPv4(_)));
499
500        let socket_v6 = SocketAddrV6::new(Ipv6Addr::LOCALHOST, 8080, 0, 0);
501        let addr: Address = SocketAddr::V6(socket_v6).into();
502        assert!(matches!(addr, Address::IPv6(_)));
503    }
504
505    #[tokio::test]
506    async fn test_address_unspecified() {
507        let unspecified = Address::unspecified();
508        match unspecified {
509            Address::IPv4(addr) => {
510                assert_eq!(addr.ip(), &Ipv4Addr::UNSPECIFIED);
511                assert_eq!(addr.port(), 0);
512            }
513            _ => panic!("Unspecified address should be IPv4"),
514        }
515    }
516
517    #[tokio::test]
518    async fn test_address_from_socket_addr_ipv4() {
519        let socket = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080));
520        let address = Address::from(socket);
521
522        match address {
523            Address::IPv4(addr) => {
524                assert_eq!(addr.ip().octets(), [127, 0, 0, 1]);
525                assert_eq!(addr.port(), 8080);
526            }
527            _ => panic!("Should be IPv4 address"),
528        }
529    }
530
531    #[tokio::test]
532    async fn test_address_from_socket_addr_ipv6() {
533        let socket = SocketAddr::V6(SocketAddrV6::new(
534            Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1),
535            8080,
536            0,
537            0,
538        ));
539        let address = Address::from(socket);
540
541        match address {
542            Address::IPv6(addr) => {
543                assert_eq!(
544                    addr.ip().octets(),
545                    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
546                );
547                assert_eq!(addr.port(), 8080);
548            }
549            _ => panic!("Should be IPv6 address"),
550        }
551    }
552
553    #[tokio::test]
554    async fn test_address_to_bytes_ipv4() {
555        let addr = Address::IPv4(SocketAddrV4::new(Ipv4Addr::new(192, 168, 1, 1), 80));
556        let bytes = addr.to_bytes();
557
558        assert_eq!(bytes[0], Address::SOCKS5_ADDRESS_TYPE_IPV4);
559        assert_eq!(bytes[1..5], [192, 168, 1, 1]);
560        assert_eq!(bytes[5..7], [0, 80]); // Port 80 in big-endian
561    }
562
563    #[tokio::test]
564    async fn test_address_to_bytes_ipv6() {
565        let addr = Address::IPv6(SocketAddrV6::new(
566            Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1),
567            443,
568            0,
569            0,
570        ));
571        let bytes = addr.to_bytes();
572
573        assert_eq!(bytes[0], Address::SOCKS5_ADDRESS_TYPE_IPV6);
574        assert_eq!(
575            bytes[1..17],
576            [0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
577        );
578        assert_eq!(bytes[17..19], [1, 187]); // Port 443 in big-endian
579    }
580
581    #[tokio::test]
582    async fn test_address_to_bytes_domain() {
583        let domain = Domain(Bytes::from("example.com"));
584        let addr = Address::Domain(domain, 8080);
585        let bytes = addr.to_bytes();
586
587        assert_eq!(bytes[0], Address::SOCKS5_ADDRESS_TYPE_DOMAIN_NAME);
588        assert_eq!(bytes[1], 11); // Length of "example.com"
589        assert_eq!(&bytes[2..13], b"example.com");
590        assert_eq!(bytes[13..15], [31, 144]); // Port 8080 in big-endian
591    }
592
593    #[tokio::test]
594    async fn test_address_from_bytes_ipv4() {
595        let mut buffer = BytesMut::new();
596        buffer.put_u8(Address::SOCKS5_ADDRESS_TYPE_IPV4);
597        buffer.put_slice(&[192, 168, 1, 1]); // IP
598        buffer.put_u16(80); // Port
599
600        let mut bytes = buffer.freeze();
601        let addr = Address::from_bytes(&mut bytes).unwrap();
602
603        match addr {
604            Address::IPv4(socket_addr) => {
605                assert_eq!(socket_addr.ip().octets(), [192, 168, 1, 1]);
606                assert_eq!(socket_addr.port(), 80);
607            }
608            _ => panic!("Should be IPv4 address"),
609        }
610    }
611
612    #[tokio::test]
613    async fn test_address_from_bytes_ipv6() {
614        let mut buffer = BytesMut::new();
615        buffer.put_u8(Address::SOCKS5_ADDRESS_TYPE_IPV6);
616        buffer.put_slice(&[0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]); // IPv6
617        buffer.put_u16(443); // Port
618
619        let mut bytes = buffer.freeze();
620        let addr = Address::from_bytes(&mut bytes).unwrap();
621
622        match addr {
623            Address::IPv6(socket_addr) => {
624                assert_eq!(
625                    socket_addr.ip().octets(),
626                    [0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
627                );
628                assert_eq!(socket_addr.port(), 443);
629            }
630            _ => panic!("Should be IPv6 address"),
631        }
632    }
633
634    #[tokio::test]
635    async fn test_address_from_bytes_domain() {
636        let mut buffer = BytesMut::new();
637        buffer.put_u8(Address::SOCKS5_ADDRESS_TYPE_DOMAIN_NAME);
638        buffer.put_u8(11); // Length of domain name
639        buffer.put_slice(b"example.com"); // Domain name
640        buffer.put_u16(8080); // Port
641
642        let mut bytes = buffer.freeze();
643        let addr = Address::from_bytes(&mut bytes).unwrap();
644
645        match addr {
646            Address::Domain(domain, port) => {
647                assert_eq!(**domain.as_bytes(), *b"example.com");
648                assert_eq!(port, 8080);
649            }
650            _ => panic!("Should be domain address"),
651        }
652    }
653
654    #[tokio::test]
655    async fn test_address_from_async_read_ipv4() {
656        let mut buffer = BytesMut::new();
657        buffer.put_u8(Address::SOCKS5_ADDRESS_TYPE_IPV4);
658        buffer.put_slice(&[192, 168, 1, 1]); // IP
659        buffer.put_u16(80); // Port
660
661        let bytes = buffer.freeze();
662        let mut cursor = Cursor::new(bytes);
663        let mut reader = BufReader::new(&mut cursor);
664
665        let addr = Address::from_async_read(&mut reader).await.unwrap();
666
667        match addr {
668            Address::IPv4(socket_addr) => {
669                assert_eq!(socket_addr.ip().octets(), [192, 168, 1, 1]);
670                assert_eq!(socket_addr.port(), 80);
671            }
672            _ => panic!("Should be IPv4 address"),
673        }
674    }
675
676    #[tokio::test]
677    async fn test_address_from_async_read_ipv6() {
678        let mut buffer = BytesMut::new();
679        buffer.put_u8(Address::SOCKS5_ADDRESS_TYPE_IPV6);
680        buffer.put_slice(&[0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]); // IPv6
681        buffer.put_u16(443); // Port
682
683        let bytes = buffer.freeze();
684        let mut cursor = Cursor::new(bytes);
685        let mut reader = BufReader::new(&mut cursor);
686
687        let addr = Address::from_async_read(&mut reader).await.unwrap();
688
689        match addr {
690            Address::IPv6(socket_addr) => {
691                assert_eq!(
692                    socket_addr.ip().octets(),
693                    [0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
694                );
695                assert_eq!(socket_addr.port(), 443);
696            }
697            _ => panic!("Should be IPv6 address"),
698        }
699    }
700
701    #[tokio::test]
702    async fn test_address_from_async_read_domain() {
703        let mut buffer = BytesMut::new();
704        buffer.put_u8(Address::SOCKS5_ADDRESS_TYPE_DOMAIN_NAME);
705        buffer.put_u8(11); // Length of domain name
706        buffer.put_slice(b"example.com"); // Domain name
707        buffer.put_u16(8080); // Port
708
709        let bytes = buffer.freeze();
710        let mut cursor = Cursor::new(bytes);
711        let mut reader = BufReader::new(&mut cursor);
712
713        let addr = Address::from_async_read(&mut reader).await.unwrap();
714
715        match addr {
716            Address::Domain(domain, port) => {
717                assert_eq!(**domain.as_bytes(), *b"example.com");
718                assert_eq!(port, 8080);
719            }
720            _ => panic!("Should be domain address"),
721        }
722    }
723
724    #[tokio::test]
725    async fn test_address_from_bytes_invalid_type() {
726        let mut buffer = BytesMut::new();
727        buffer.put_u8(0xFF); // Invalid address type
728
729        let mut bytes = buffer.freeze();
730        let result = Address::from_bytes(&mut bytes);
731
732        assert!(result.is_err());
733    }
734
735    #[tokio::test]
736    async fn test_address_from_bytes_insufficient_data() {
737        // IPv4 with incomplete data
738        let mut buffer = BytesMut::new();
739        buffer.put_u8(Address::SOCKS5_ADDRESS_TYPE_IPV4);
740        buffer.put_slice(&[192, 168]); // Incomplete IP
741
742        let mut bytes = buffer.freeze();
743        let result = Address::from_bytes(&mut bytes);
744
745        assert!(result.is_err());
746    }
747
748    #[tokio::test]
749    async fn test_address_port() {
750        let addr1 = Address::IPv4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080));
751        assert_eq!(addr1.port(), 8080);
752
753        let addr2 = Address::IPv6(SocketAddrV6::new(
754            Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1),
755            443,
756            0,
757            0,
758        ));
759        assert_eq!(addr2.port(), 443);
760
761        let addr3 = Address::Domain(Domain(Bytes::from("example.com")), 80);
762        assert_eq!(addr3.port(), 80);
763    }
764
765    #[tokio::test]
766    async fn test_address_format_as_string() {
767        let addr1 = Address::IPv4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080));
768        assert_eq!(addr1.to_string(), "127.0.0.1:8080");
769
770        let addr2 = Address::IPv6(SocketAddrV6::new(
771            Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1),
772            443,
773            0,
774            0,
775        ));
776        assert_eq!(addr2.to_string(), "[::1]:443");
777
778        // This test assumes Domain::domain_str() returns Ok with the domain string
779        let addr3 = Address::Domain(Domain(Bytes::from("example.com")), 80);
780        assert_eq!(addr3.to_string(), "example.com:80");
781    }
782}