1use arrayref::array_ref;
2use byteorder::{BigEndian, ByteOrder};
3use bytes::{Buf, BufMut};
4use data_encoding::BASE32;
5use std::{
6 borrow::Cow,
7 fmt,
8 io::Cursor,
9 net::{IpAddr, Ipv4Addr, Ipv6Addr},
10 str::{self, FromStr},
11};
12
13use crate::{Onion3Addr, error::Error};
14
15const DNS4: u32 = 0x36;
16const DNS6: u32 = 0x37;
17const IP4: u32 = 0x04;
18const IP6: u32 = 0x29;
19const P2P: u32 = 0x01a5;
20const TCP: u32 = 0x06;
21const TLS: u32 = 0x01c0;
22const WS: u32 = 0x01dd;
23const WSS: u32 = 0x01de;
24const MEMORY: u32 = 0x0309;
25const ONION3: u32 = 0x01bd;
26
27const SHA256_CODE: u64 = 0x12;
28const SHA256_SIZE: u8 = 32;
29
30#[derive(PartialEq, Eq, Clone, Debug)]
32pub enum Protocol<'a> {
33 Dns4(Cow<'a, str>),
34 Dns6(Cow<'a, str>),
35 Ip4(Ipv4Addr),
36 Ip6(Ipv6Addr),
37 P2P(Cow<'a, [u8]>),
38 Tcp(u16),
39 Tls(Cow<'a, str>),
40 Ws,
41 Wss,
42 Memory(u64),
44 Onion3(Onion3Addr<'a>),
45}
46
47impl<'a> Protocol<'a> {
48 pub fn from_str_peek<T>(mut iter: T) -> Result<Self, Error>
55 where
56 T: Iterator<Item = &'a str>,
57 {
58 match iter.next().ok_or(Error::InvalidProtocolString)? {
59 "dns4" => {
60 let s = iter.next().ok_or(Error::InvalidProtocolString)?;
61 Ok(Protocol::Dns4(Cow::Borrowed(s)))
62 }
63 "dns6" => {
64 let s = iter.next().ok_or(Error::InvalidProtocolString)?;
65 Ok(Protocol::Dns6(Cow::Borrowed(s)))
66 }
67 "ip4" => {
68 let s = iter.next().ok_or(Error::InvalidProtocolString)?;
69 Ok(Protocol::Ip4(Ipv4Addr::from_str(s)?))
70 }
71 "ip6" => {
72 let s = iter.next().ok_or(Error::InvalidProtocolString)?;
73 Ok(Protocol::Ip6(Ipv6Addr::from_str(s)?))
74 }
75 "tls" => {
76 let s = iter.next().ok_or(Error::InvalidProtocolString)?;
77 Ok(Protocol::Tls(Cow::Borrowed(s)))
78 }
79 "p2p" => {
80 let s = iter.next().ok_or(Error::InvalidProtocolString)?;
81 let decoded = bs58::decode(s).into_vec()?;
82 check_p2p(decoded.as_slice())?;
83 Ok(Protocol::P2P(Cow::Owned(decoded)))
84 }
85 "tcp" => {
86 let s = iter.next().ok_or(Error::InvalidProtocolString)?;
87 Ok(Protocol::Tcp(s.parse()?))
88 }
89 "ws" => Ok(Protocol::Ws),
90 "wss" => Ok(Protocol::Wss),
91 "memory" => {
92 let s = iter.next().ok_or(Error::InvalidProtocolString)?;
93 Ok(Protocol::Memory(s.parse()?))
94 }
95 "onion3" => iter
96 .next()
97 .ok_or(Error::InvalidProtocolString)
98 .and_then(|s| read_onion3(&s.to_uppercase()))
99 .map(|(a, p)| Protocol::Onion3((a, p).into())),
100 _ => Err(Error::UnknownProtocolString),
101 }
102 }
103
104 pub fn from_bytes(input: &'a [u8]) -> Result<(Self, &'a [u8]), Error> {
107 use unsigned_varint::decode;
108 fn split_header(n: usize, input: &[u8]) -> Result<(&[u8], &[u8]), Error> {
109 if input.len() < n {
110 return Err(Error::DataLessThanLen);
111 }
112 Ok(input.split_at(n))
113 }
114
115 let (id, input) = decode::u32(input)?;
116 match id {
117 DNS4 => {
118 let (n, input) = decode::usize(input)?;
119 let (data, rest) = split_header(n, input)?;
120 Ok((Protocol::Dns4(Cow::Borrowed(str::from_utf8(data)?)), rest))
121 }
122 DNS6 => {
123 let (n, input) = decode::usize(input)?;
124 let (data, rest) = split_header(n, input)?;
125 Ok((Protocol::Dns6(Cow::Borrowed(str::from_utf8(data)?)), rest))
126 }
127 IP4 => {
128 let (data, rest) = split_header(4, input)?;
129 Ok((
130 Protocol::Ip4(Ipv4Addr::new(data[0], data[1], data[2], data[3])),
131 rest,
132 ))
133 }
134 IP6 => {
135 let (data, rest) = split_header(16, input)?;
136 let mut rdr = Cursor::new(data);
137 let mut seg = [0_u16; 8];
138
139 for x in seg.iter_mut() {
140 *x = rdr.get_u16();
141 }
142
143 let addr = Ipv6Addr::new(
144 seg[0], seg[1], seg[2], seg[3], seg[4], seg[5], seg[6], seg[7],
145 );
146
147 Ok((Protocol::Ip6(addr), rest))
148 }
149 TLS => {
150 let (n, input) = decode::usize(input)?;
151 let (data, rest) = split_header(n, input)?;
152 Ok((Protocol::Tls(Cow::Borrowed(str::from_utf8(data)?)), rest))
153 }
154 P2P => {
155 let (n, input) = decode::usize(input)?;
156 let (data, rest) = split_header(n, input)?;
157 check_p2p(data)?;
158 Ok((Protocol::P2P(Cow::Borrowed(data)), rest))
159 }
160 TCP => {
161 let (data, rest) = split_header(2, input)?;
162 let mut rdr = Cursor::new(data);
163 let num = rdr.get_u16();
164 Ok((Protocol::Tcp(num), rest))
165 }
166 WS => Ok((Protocol::Ws, input)),
167 WSS => Ok((Protocol::Wss, input)),
168 MEMORY => {
169 let (data, rest) = split_header(8, input)?;
170 let mut rdr = Cursor::new(data);
171 let num = rdr.get_u64();
172 Ok((Protocol::Memory(num), rest))
173 }
174 ONION3 => {
175 let (data, rest) = split_header(37, input)?;
176 let port = BigEndian::read_u16(&data[35..]);
177 Ok((
178 Protocol::Onion3((array_ref!(data, 0, 35), port).into()),
179 rest,
180 ))
181 }
182 _ => Err(Error::UnknownProtocolId(id)),
183 }
184 }
185
186 pub fn write_to_bytes<W: BufMut>(&self, w: &mut W) {
189 use unsigned_varint::encode;
190 let mut buf = encode::u32_buffer();
191 match self {
192 Protocol::Dns4(s) => {
193 w.put(encode::u32(DNS4, &mut buf));
194 let bytes = s.as_bytes();
195 w.put(encode::usize(bytes.len(), &mut encode::usize_buffer()));
196 w.put(bytes)
197 }
198 Protocol::Dns6(s) => {
199 w.put(encode::u32(DNS6, &mut buf));
200 let bytes = s.as_bytes();
201 w.put(encode::usize(bytes.len(), &mut encode::usize_buffer()));
202 w.put(bytes)
203 }
204 Protocol::Ip4(addr) => {
205 w.put(encode::u32(IP4, &mut buf));
206 w.put(&addr.octets()[..])
207 }
208 Protocol::Ip6(addr) => {
209 w.put(encode::u32(IP6, &mut buf));
210 for &segment in &addr.segments() {
211 w.put_u16(segment)
212 }
213 }
214 Protocol::Tcp(port) => {
215 w.put(encode::u32(TCP, &mut buf));
216 w.put_u16(*port)
217 }
218 Protocol::Tls(s) => {
219 w.put(encode::u32(TLS, &mut buf));
220 let bytes = s.as_bytes();
221 w.put(encode::usize(bytes.len(), &mut encode::usize_buffer()));
222 w.put(bytes)
223 }
224 Protocol::P2P(b) => {
225 w.put(encode::u32(P2P, &mut buf));
226 w.put(encode::usize(b.len(), &mut encode::usize_buffer()));
227 w.put(&b[..])
228 }
229 Protocol::Ws => w.put(encode::u32(WS, &mut buf)),
230 Protocol::Wss => w.put(encode::u32(WSS, &mut buf)),
231 Protocol::Memory(port) => {
232 w.put(encode::u32(MEMORY, &mut buf));
233 w.put_u64(*port)
234 }
235 Protocol::Onion3(addr) => {
236 w.put(encode::u32(ONION3, &mut buf));
237 w.put(addr.hash().as_ref());
238 w.put_u16(addr.port());
239 }
240 }
241 }
242
243 pub fn acquire<'b>(self) -> Protocol<'b> {
245 match self {
246 Protocol::Dns4(s) => Protocol::Dns4(Cow::Owned(s.into_owned())),
247 Protocol::Dns6(s) => Protocol::Dns6(Cow::Owned(s.into_owned())),
248 Protocol::Ip4(addr) => Protocol::Ip4(addr),
249 Protocol::Ip6(addr) => Protocol::Ip6(addr),
250 Protocol::Tcp(port) => Protocol::Tcp(port),
251 Protocol::Tls(s) => Protocol::Tls(Cow::Owned(s.into_owned())),
252 Protocol::P2P(s) => Protocol::P2P(Cow::Owned(s.into_owned())),
253 Protocol::Ws => Protocol::Ws,
254 Protocol::Wss => Protocol::Wss,
255 Protocol::Memory(a) => Protocol::Memory(a),
256 Protocol::Onion3(addr) => Protocol::Onion3(addr.acquire()),
257 }
258 }
259}
260
261impl fmt::Display for Protocol<'_> {
262 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
263 use self::Protocol::*;
264 match self {
265 Dns4(s) => write!(f, "/dns4/{}", s),
266 Dns6(s) => write!(f, "/dns6/{}", s),
267 Ip4(addr) => write!(f, "/ip4/{}", addr),
268 Ip6(addr) => write!(f, "/ip6/{}", addr),
269 P2P(c) => write!(f, "/p2p/{}", bs58::encode(c).into_string()),
270 Tcp(port) => write!(f, "/tcp/{}", port),
271 Tls(s) => write!(f, "/tls/{}", s),
272 Ws => write!(f, "/ws"),
273 Wss => write!(f, "/wss"),
274 Memory(port) => write!(f, "/memory/{}", port),
275 Onion3(addr) => {
276 write!(f, "/onion3/{}:{}", addr.hash_string(), addr.port())
277 }
278 }
279 }
280}
281
282impl From<IpAddr> for Protocol<'_> {
283 #[inline]
284 fn from(addr: IpAddr) -> Self {
285 match addr {
286 IpAddr::V4(addr) => Protocol::Ip4(addr),
287 IpAddr::V6(addr) => Protocol::Ip6(addr),
288 }
289 }
290}
291
292impl From<Ipv4Addr> for Protocol<'_> {
293 #[inline]
294 fn from(addr: Ipv4Addr) -> Self {
295 Protocol::Ip4(addr)
296 }
297}
298
299impl From<Ipv6Addr> for Protocol<'_> {
300 #[inline]
301 fn from(addr: Ipv6Addr) -> Self {
302 Protocol::Ip6(addr)
303 }
304}
305
306fn check_p2p(data: &[u8]) -> Result<(), Error> {
307 let (code, bytes) = unsigned_varint::decode::u64(data)?;
308
309 if code != SHA256_CODE {
310 return Err(Error::UnknownHash);
311 }
312
313 if bytes.len() != SHA256_SIZE as usize + 1 {
314 return Err(Error::UnknownHash);
315 }
316
317 if bytes[0] != SHA256_SIZE {
318 return Err(Error::UnknownHash);
319 }
320 Ok(())
321}
322
323macro_rules! read_onion_impl {
324 ($name:ident, $len:expr, $encoded_len:expr) => {
325 fn $name(s: &str) -> Result<([u8; $len], u16), Error> {
326 let mut parts = s.split(':');
327
328 let b32 = parts.next().ok_or(Error::InvalidMultiaddr)?;
330 if b32.len() != $encoded_len {
331 return Err(Error::InvalidMultiaddr);
332 }
333
334 let port = parts
336 .next()
337 .ok_or(Error::InvalidMultiaddr)
338 .and_then(|p| str::parse(p).map_err(From::from))?;
339
340 if port == 0 {
342 return Err(Error::InvalidMultiaddr);
343 }
344
345 if parts.next().is_some() {
347 return Err(Error::InvalidMultiaddr);
348 }
349
350 if $len
351 != BASE32
352 .decode_len(b32.len())
353 .map_err(|_| Error::InvalidMultiaddr)?
354 {
355 return Err(Error::InvalidMultiaddr);
356 }
357
358 let mut buf = [0u8; $len];
359 BASE32
360 .decode_mut(b32.as_bytes(), &mut buf)
361 .map_err(|_| Error::InvalidMultiaddr)?;
362
363 Ok((buf, port))
364 }
365 };
366}
367
368read_onion_impl!(read_onion3, 35, 56);