socks5_protocol_async/protocol/
address.rs1use super::constant;
2use super::shared_internal::*;
3use failure::Error;
4use futures_io::{AsyncRead, AsyncWrite};
5use futures_util::{AsyncReadExt, AsyncWriteExt};
6
7#[derive(Debug, Clone, PartialEq, Eq)]
8pub enum Address {
9 IPv4([u8; 4]),
10 IPv6([u8; 16]),
11 DomainName(Vec<u8>),
12}
13
14impl Address {
15 pub async fn read<AR>(reader: &mut AR) -> Result<Self, Error>
16 where
17 AR: AsyncRead + Unpin,
18 {
19 let address_type = read_u8(reader).await?;
20 match address_type {
21 constant::address_type::IPV4 => {
22 let mut buf = [0u8; 4];
23 reader.read_exact(buf.as_mut()).await?;
24 Ok(Address::IPv4(buf))
25 }
26 constant::address_type::IPV6 => {
27 let mut buf = [0u8; 16];
28 reader.read_exact(buf.as_mut()).await?;
29 Ok(Address::IPv6(buf))
30 }
31 constant::address_type::DOMAIN_NAME => {
32 let len = read_u8(reader).await?;
33 let v = read_vec(reader, len as usize).await?;
34 Ok(Address::DomainName(v))
35 }
36 _ => Err(crate::error::InvalidAddressTypeError(address_type))?,
37 }
38 }
39
40 pub async fn write<AW>(&self, writer: &mut AW) -> std::io::Result<()>
41 where
42 AW: AsyncWrite + Unpin,
43 {
44 match self {
45 Address::IPv4(val) => {
46 let head = [constant::address_type::IPV4];
47 writer.write_all(&head).await?;
48 writer.write_all(val).await?;
49 Ok(())
50 }
51 Address::IPv6(val) => {
52 let head = [constant::address_type::IPV6];
53 writer.write_all(&head).await?;
54 writer.write_all(val).await?;
55 Ok(())
56 }
57 Address::DomainName(val) => {
58 let head = [constant::address_type::DOMAIN_NAME, val.len() as u8];
59 writer.write_all(&head).await?;
60 writer.write_all(val).await?;
61 Ok(())
62 }
63 }
64 }
65}
66
67#[cfg(test)]
68mod test {
69 use super::*;
70 use crate::test_util::*;
71 use futures_util::io::Cursor;
72
73 #[test]
74 fn read_invalid_type() {
75 let mut reader = Cursor::new(&[0x2]);
76 let future = Address::read(&mut reader);
77 let result = extract_future_output(future);
78 let err = result.unwrap_err();
79 let err = err
80 .downcast::<crate::error::InvalidAddressTypeError>()
81 .unwrap();
82 assert_eq!(err, crate::error::InvalidAddressTypeError(0x2));
83 }
84
85 #[test]
86 fn read_ipv4_ok() {
87 let mut reader = Cursor::new(&[constant::address_type::IPV4, 127, 0, 0, 1]);
88 let future = Address::read(&mut reader);
89 let result = extract_future_output(future);
90 assert_eq!(result.unwrap(), Address::IPv4([127, 0, 0, 1]));
91 }
92
93 #[test]
94 fn read_ipv6_ok() {
95 let mut reader = Cursor::new(&[
96 constant::address_type::IPV6,
97 1,
98 0,
99 0,
100 0,
101 0,
102 0,
103 0,
104 0,
105 0,
106 0,
107 0,
108 0,
109 0,
110 0,
111 0,
112 0xFF,
113 ]);
114 let future = Address::read(&mut reader);
115 let result = extract_future_output(future);
116 assert_eq!(
117 result.unwrap(),
118 Address::IPv6([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF])
119 );
120 }
121
122 #[test]
123 fn read_domain_name_ok() {
124 let mut reader = Cursor::new(&[
125 constant::address_type::DOMAIN_NAME,
126 11,
127 'e' as u8,
128 'x' as u8,
129 'a' as u8,
130 'm' as u8,
131 'p' as u8,
132 'l' as u8,
133 'e' as u8,
134 '.' as u8,
135 'c' as u8,
136 'o' as u8,
137 'm' as u8,
138 ]);
139 let future = Address::read(&mut reader);
140 let result = extract_future_output(future);
141 assert_eq!(
142 result.unwrap(),
143 Address::DomainName("example.com".as_bytes().to_vec())
144 );
145 }
146
147 #[test]
148 fn write_ipv4_ok() {
149 let mut writer = [0u8; 1 + 4];
150 let mut writer = Cursor::new(&mut writer[..]);
151 let res = Address::IPv4([127, 0, 0, 1]);
152 let future = res.write(&mut writer);
153 let result = extract_future_output(future);
154 assert_eq!(result.unwrap(), ());
155 assert_eq!(writer.into_inner(), [0x1, 127, 0, 0, 1])
156 }
157
158 #[test]
159 fn write_ipv6_ok() {
160 let mut writer = [0u8; 1 + 16];
161 let mut writer = Cursor::new(&mut writer[..]);
162 let res = Address::IPv6([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF]);
163 let future = res.write(&mut writer);
164 let result = extract_future_output(future);
165 assert_eq!(result.unwrap(), ());
166 assert_eq!(
167 writer.into_inner(),
168 [0x4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF]
169 )
170 }
171
172 #[test]
173 fn write_domain_name_ok() {
174 let mut writer = [0u8; 1 + 1 + 11];
175 let mut writer = Cursor::new(&mut writer[..]);
176 let res = Address::DomainName("example.com".as_bytes().to_vec());
177 let future = res.write(&mut writer);
178 let result = extract_future_output(future);
179 assert_eq!(result.unwrap(), ());
180 assert_eq!(
181 writer.into_inner(),
182 [
183 0x3, 11, 'e' as u8, 'x' as u8, 'a' as u8, 'm' as u8, 'p' as u8, 'l' as u8,
184 'e' as u8, '.' as u8, 'c' as u8, 'o' as u8, 'm' as u8,
185 ]
186 )
187 }
188}