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 TryFrom<&[u8]> for Domain {
363    type Error = io::Error;
364
365    #[inline]
366    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
367        Self::from_bytes(Bytes::copy_from_slice(value))
368    }
369}
370
371impl TryFrom<&str> for Domain {
372    type Error = io::Error;
373
374    #[inline]
375    fn try_from(value: &str) -> Result<Self, Self::Error> {
376        Self::from_bytes(Bytes::copy_from_slice(value.as_bytes()))
377    }
378}
379
380impl TryFrom<String> for Domain {
381    type Error = io::Error;
382
383    #[inline]
384    fn try_from(value: String) -> Result<Self, Self::Error> {
385        Self::from_string(value)
386    }
387}
388
389impl TryFrom<Bytes> for Domain {
390    type Error = io::Error;
391
392    #[inline]
393    fn try_from(value: Bytes) -> Result<Self, Self::Error> {
394        Self::from_bytes(value)
395    }
396}
397
398impl AsRef<[u8]> for Domain {
399    #[inline]
400    fn as_ref(&self) -> &[u8] {
401        self.as_bytes()
402    }
403}
404
405#[cfg(test)]
406mod tests {
407    use tokio::io::BufReader;
408
409    use super::*;
410
411    use std::{
412        io::Cursor,
413        net::{Ipv4Addr, Ipv6Addr},
414    };
415
416    #[test]
417    fn test_ipv4_serialization() {
418        let addr = Address::IPv4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080));
419        let bytes = addr.to_bytes();
420        let mut buf = &bytes[..];
421        let parsed = Address::from_bytes(&mut buf).unwrap();
422        assert_eq!(addr, parsed);
423    }
424
425    #[test]
426    fn test_ipv6_serialization() {
427        let addr = Address::IPv6(SocketAddrV6::new(Ipv6Addr::LOCALHOST, 8080, 0, 0));
428        let bytes = addr.to_bytes();
429        let mut buf = &bytes[..];
430        let parsed = Address::from_bytes(&mut buf).unwrap();
431        assert_eq!(addr, parsed);
432    }
433
434    #[test]
435    fn test_domain_serialization() {
436        let domain = Domain::try_from("example.com").unwrap();
437        let addr = Address::Domain(domain, 8080);
438        let bytes = addr.to_bytes();
439        let mut buf = &bytes[..];
440
441        let parsed = Address::from_bytes(&mut buf).unwrap();
442
443        if let Address::Domain(d, p) = parsed {
444            assert_eq!(d.format_as_str(), "example.com");
445            assert_eq!(p, 8080);
446        } else {
447            panic!("Parsed address is not Domain type");
448        }
449    }
450
451    #[test]
452    fn test_invalid_atyp() {
453        let mut buf = bytes::BytesMut::new();
454        buf.put_u8(0x04);
455        let mut buf = buf.freeze();
456        let result = Address::from_bytes(&mut buf);
457        assert!(result.is_err());
458    }
459
460    #[test]
461    fn test_domain_too_long() {
462        let result = Domain::try_from(vec![b'a'; 255].as_slice());
463        assert!(result.is_err())
464    }
465
466    #[tokio::test]
467    async fn test_domain_resolution() {
468        let domain = Domain::try_from("localhost").unwrap();
469        let addr = Address::Domain(domain, 8080);
470        let socket_addr = addr.to_socket_addr().await.unwrap();
471        assert!(socket_addr.port() == 8080);
472    }
473
474    #[test]
475    fn test_domain_utf8_error() {
476        let result = Domain::from_bytes(Bytes::copy_from_slice(vec![0xff, 0xfe].as_slice()));
477        assert!(result.is_err())
478    }
479
480    #[test]
481    fn test_socket_addr_conversion() {
482        let socket_v4 = SocketAddrV4::new(Ipv4Addr::LOCALHOST, 8080);
483        let addr: Address = SocketAddr::V4(socket_v4).into();
484        assert!(matches!(addr, Address::IPv4(_)));
485
486        let socket_v6 = SocketAddrV6::new(Ipv6Addr::LOCALHOST, 8080, 0, 0);
487        let addr: Address = SocketAddr::V6(socket_v6).into();
488        assert!(matches!(addr, Address::IPv6(_)));
489    }
490
491    #[tokio::test]
492    async fn test_address_unspecified() {
493        let unspecified = Address::unspecified();
494        match unspecified {
495            Address::IPv4(addr) => {
496                assert_eq!(addr.ip(), &Ipv4Addr::UNSPECIFIED);
497                assert_eq!(addr.port(), 0);
498            }
499            _ => panic!("Unspecified address should be IPv4"),
500        }
501    }
502
503    #[tokio::test]
504    async fn test_address_from_socket_addr_ipv4() {
505        let socket = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080));
506        let address = Address::from(socket);
507
508        match address {
509            Address::IPv4(addr) => {
510                assert_eq!(addr.ip().octets(), [127, 0, 0, 1]);
511                assert_eq!(addr.port(), 8080);
512            }
513            _ => panic!("Should be IPv4 address"),
514        }
515    }
516
517    #[tokio::test]
518    async fn test_address_from_socket_addr_ipv6() {
519        let socket = SocketAddr::V6(SocketAddrV6::new(
520            Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1),
521            8080,
522            0,
523            0,
524        ));
525        let address = Address::from(socket);
526
527        match address {
528            Address::IPv6(addr) => {
529                assert_eq!(
530                    addr.ip().octets(),
531                    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
532                );
533                assert_eq!(addr.port(), 8080);
534            }
535            _ => panic!("Should be IPv6 address"),
536        }
537    }
538
539    #[tokio::test]
540    async fn test_address_to_bytes_ipv4() {
541        let addr = Address::IPv4(SocketAddrV4::new(Ipv4Addr::new(192, 168, 1, 1), 80));
542        let bytes = addr.to_bytes();
543
544        assert_eq!(bytes[0], Address::SOCKS5_ADDRESS_TYPE_IPV4);
545        assert_eq!(bytes[1..5], [192, 168, 1, 1]);
546        assert_eq!(bytes[5..7], [0, 80]); // Port 80 in big-endian
547    }
548
549    #[tokio::test]
550    async fn test_address_to_bytes_ipv6() {
551        let addr = Address::IPv6(SocketAddrV6::new(
552            Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1),
553            443,
554            0,
555            0,
556        ));
557        let bytes = addr.to_bytes();
558
559        assert_eq!(bytes[0], Address::SOCKS5_ADDRESS_TYPE_IPV6);
560        assert_eq!(
561            bytes[1..17],
562            [0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
563        );
564        assert_eq!(bytes[17..19], [1, 187]); // Port 443 in big-endian
565    }
566
567    #[tokio::test]
568    async fn test_address_to_bytes_domain() {
569        let domain = Domain(Bytes::from("example.com"));
570        let addr = Address::Domain(domain, 8080);
571        let bytes = addr.to_bytes();
572
573        assert_eq!(bytes[0], Address::SOCKS5_ADDRESS_TYPE_DOMAIN_NAME);
574        assert_eq!(bytes[1], 11); // Length of "example.com"
575        assert_eq!(&bytes[2..13], b"example.com");
576        assert_eq!(bytes[13..15], [31, 144]); // Port 8080 in big-endian
577    }
578
579    #[tokio::test]
580    async fn test_address_from_bytes_ipv4() {
581        let mut buffer = BytesMut::new();
582        buffer.put_u8(Address::SOCKS5_ADDRESS_TYPE_IPV4);
583        buffer.put_slice(&[192, 168, 1, 1]); // IP
584        buffer.put_u16(80); // Port
585
586        let mut bytes = buffer.freeze();
587        let addr = Address::from_bytes(&mut bytes).unwrap();
588
589        match addr {
590            Address::IPv4(socket_addr) => {
591                assert_eq!(socket_addr.ip().octets(), [192, 168, 1, 1]);
592                assert_eq!(socket_addr.port(), 80);
593            }
594            _ => panic!("Should be IPv4 address"),
595        }
596    }
597
598    #[tokio::test]
599    async fn test_address_from_bytes_ipv6() {
600        let mut buffer = BytesMut::new();
601        buffer.put_u8(Address::SOCKS5_ADDRESS_TYPE_IPV6);
602        buffer.put_slice(&[0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]); // IPv6
603        buffer.put_u16(443); // Port
604
605        let mut bytes = buffer.freeze();
606        let addr = Address::from_bytes(&mut bytes).unwrap();
607
608        match addr {
609            Address::IPv6(socket_addr) => {
610                assert_eq!(
611                    socket_addr.ip().octets(),
612                    [0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
613                );
614                assert_eq!(socket_addr.port(), 443);
615            }
616            _ => panic!("Should be IPv6 address"),
617        }
618    }
619
620    #[tokio::test]
621    async fn test_address_from_bytes_domain() {
622        let mut buffer = BytesMut::new();
623        buffer.put_u8(Address::SOCKS5_ADDRESS_TYPE_DOMAIN_NAME);
624        buffer.put_u8(11); // Length of domain name
625        buffer.put_slice(b"example.com"); // Domain name
626        buffer.put_u16(8080); // Port
627
628        let mut bytes = buffer.freeze();
629        let addr = Address::from_bytes(&mut bytes).unwrap();
630
631        match addr {
632            Address::Domain(domain, port) => {
633                assert_eq!(**domain.as_bytes(), *b"example.com");
634                assert_eq!(port, 8080);
635            }
636            _ => panic!("Should be domain address"),
637        }
638    }
639
640    #[tokio::test]
641    async fn test_address_from_async_read_ipv4() {
642        let mut buffer = BytesMut::new();
643        buffer.put_u8(Address::SOCKS5_ADDRESS_TYPE_IPV4);
644        buffer.put_slice(&[192, 168, 1, 1]); // IP
645        buffer.put_u16(80); // Port
646
647        let bytes = buffer.freeze();
648        let mut cursor = Cursor::new(bytes);
649        let mut reader = BufReader::new(&mut cursor);
650
651        let addr = Address::from_async_read(&mut reader).await.unwrap();
652
653        match addr {
654            Address::IPv4(socket_addr) => {
655                assert_eq!(socket_addr.ip().octets(), [192, 168, 1, 1]);
656                assert_eq!(socket_addr.port(), 80);
657            }
658            _ => panic!("Should be IPv4 address"),
659        }
660    }
661
662    #[tokio::test]
663    async fn test_address_from_async_read_ipv6() {
664        let mut buffer = BytesMut::new();
665        buffer.put_u8(Address::SOCKS5_ADDRESS_TYPE_IPV6);
666        buffer.put_slice(&[0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]); // IPv6
667        buffer.put_u16(443); // Port
668
669        let bytes = buffer.freeze();
670        let mut cursor = Cursor::new(bytes);
671        let mut reader = BufReader::new(&mut cursor);
672
673        let addr = Address::from_async_read(&mut reader).await.unwrap();
674
675        match addr {
676            Address::IPv6(socket_addr) => {
677                assert_eq!(
678                    socket_addr.ip().octets(),
679                    [0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
680                );
681                assert_eq!(socket_addr.port(), 443);
682            }
683            _ => panic!("Should be IPv6 address"),
684        }
685    }
686
687    #[tokio::test]
688    async fn test_address_from_async_read_domain() {
689        let mut buffer = BytesMut::new();
690        buffer.put_u8(Address::SOCKS5_ADDRESS_TYPE_DOMAIN_NAME);
691        buffer.put_u8(11); // Length of domain name
692        buffer.put_slice(b"example.com"); // Domain name
693        buffer.put_u16(8080); // Port
694
695        let bytes = buffer.freeze();
696        let mut cursor = Cursor::new(bytes);
697        let mut reader = BufReader::new(&mut cursor);
698
699        let addr = Address::from_async_read(&mut reader).await.unwrap();
700
701        match addr {
702            Address::Domain(domain, port) => {
703                assert_eq!(**domain.as_bytes(), *b"example.com");
704                assert_eq!(port, 8080);
705            }
706            _ => panic!("Should be domain address"),
707        }
708    }
709
710    #[tokio::test]
711    async fn test_address_from_bytes_invalid_type() {
712        let mut buffer = BytesMut::new();
713        buffer.put_u8(0xFF); // Invalid address type
714
715        let mut bytes = buffer.freeze();
716        let result = Address::from_bytes(&mut bytes);
717
718        assert!(result.is_err());
719    }
720
721    #[tokio::test]
722    async fn test_address_from_bytes_insufficient_data() {
723        // IPv4 with incomplete data
724        let mut buffer = BytesMut::new();
725        buffer.put_u8(Address::SOCKS5_ADDRESS_TYPE_IPV4);
726        buffer.put_slice(&[192, 168]); // Incomplete IP
727
728        let mut bytes = buffer.freeze();
729        let result = Address::from_bytes(&mut bytes);
730
731        assert!(result.is_err());
732    }
733
734    #[tokio::test]
735    async fn test_address_port() {
736        let addr1 = Address::IPv4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080));
737        assert_eq!(addr1.port(), 8080);
738
739        let addr2 = Address::IPv6(SocketAddrV6::new(
740            Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1),
741            443,
742            0,
743            0,
744        ));
745        assert_eq!(addr2.port(), 443);
746
747        let addr3 = Address::Domain(Domain(Bytes::from("example.com")), 80);
748        assert_eq!(addr3.port(), 80);
749    }
750
751    #[tokio::test]
752    async fn test_address_format_as_string() {
753        let addr1 = Address::IPv4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080));
754        assert_eq!(addr1.to_string(), "127.0.0.1:8080");
755
756        let addr2 = Address::IPv6(SocketAddrV6::new(
757            Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1),
758            443,
759            0,
760            0,
761        ));
762        assert_eq!(addr2.to_string(), "[::1]:443");
763
764        // This test assumes Domain::domain_str() returns Ok with the domain string
765        let addr3 = Address::Domain(Domain(Bytes::from("example.com")), 80);
766        assert_eq!(addr3.to_string(), "example.com:80");
767    }
768}