Skip to main content

volans_core/multiaddr/
protocol.rs

1use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
2use std::{
3    borrow::Cow,
4    convert::From,
5    fmt,
6    io::{Cursor, Write},
7    net::{IpAddr, Ipv4Addr, Ipv6Addr},
8    str::FromStr,
9};
10use unsigned_varint::{decode, encode};
11
12use crate::{PeerId, multiaddr::Error};
13
14const DNS: u32 = 53;
15const DNS4: u32 = 54;
16const DNS6: u32 = 55;
17const HTTP: u32 = 480;
18const IP4: u32 = 4;
19const IP6: u32 = 41;
20const MEMORY: u32 = 777;
21const PEER: u32 = 421;
22const CIRCUIT: u32 = 290;
23const QUIC: u32 = 460;
24const TCP: u32 = 6;
25const TLS: u32 = 448;
26const UDP: u32 = 273;
27const UNIX: u32 = 400;
28const WS: u32 = 477;
29const SNI: u32 = 449;
30const PATH: u32 = 481;
31
32const PATH_SEGMENT_ENCODE_SET: &percent_encoding::AsciiSet = &percent_encoding::CONTROLS
33    .add(b'%')
34    .add(b'/')
35    .add(b'`')
36    .add(b'?')
37    .add(b'{')
38    .add(b'}')
39    .add(b' ')
40    .add(b'"')
41    .add(b'#')
42    .add(b'<')
43    .add(b'>')
44    .add(b':');
45
46#[derive(PartialEq, Eq, Clone, Debug)]
47#[non_exhaustive]
48pub enum Protocol<'a> {
49    Dns(Cow<'a, str>),
50    Dns4(Cow<'a, str>),
51    Dns6(Cow<'a, str>),
52
53    Ip4(Ipv4Addr),
54    Ip6(Ipv6Addr),
55    Unix,
56
57    Memory(u64),
58    Tcp(u16),
59    Udp(u16),
60
61    Tls,
62    Http,
63    Ws,
64    Quic,
65
66    Peer(PeerId),
67    Circuit,
68
69    Sni(Cow<'a, str>),
70    Path(Cow<'a, str>),
71}
72
73impl<'a> Protocol<'a> {
74    pub fn from_str_parts<I>(mut iter: I) -> Result<Self, Error>
75    where
76        I: Iterator<Item = &'a str>,
77    {
78        match iter.next().ok_or(Error::InvalidProtocol)? {
79            "dns" => {
80                let s = iter.next().ok_or(Error::InvalidProtocol)?;
81                Ok(Protocol::Dns(Cow::Borrowed(s)))
82            }
83            "dns4" => {
84                let s = iter.next().ok_or(Error::InvalidProtocol)?;
85                Ok(Protocol::Dns4(Cow::Borrowed(s)))
86            }
87            "dns6" => {
88                let s = iter.next().ok_or(Error::InvalidProtocol)?;
89                Ok(Protocol::Dns6(Cow::Borrowed(s)))
90            }
91            "ip4" => {
92                let s = iter.next().ok_or(Error::InvalidProtocol)?;
93                let addr = Ipv4Addr::from_str(s)?;
94                Ok(Protocol::Ip4(addr))
95            }
96            "ip6" => {
97                let s = iter.next().ok_or(Error::InvalidProtocol)?;
98                let addr = Ipv6Addr::from_str(s)?;
99                Ok(Protocol::Ip6(addr))
100            }
101            "unix" => Ok(Protocol::Unix),
102            "memory" => {
103                let s = iter.next().ok_or(Error::InvalidProtocol)?;
104                let port = s.parse::<u64>()?;
105                Ok(Protocol::Memory(port))
106            }
107            "tcp" => {
108                let s = iter.next().ok_or(Error::InvalidProtocol)?;
109                let port = s.parse::<u16>()?;
110                Ok(Protocol::Tcp(port))
111            }
112            "udp" => {
113                let s = iter.next().ok_or(Error::InvalidProtocol)?;
114                let port = s.parse::<u16>()?;
115                Ok(Protocol::Udp(port))
116            }
117            "tls" => Ok(Protocol::Tls),
118            "http" => Ok(Protocol::Http),
119            "ws" => Ok(Protocol::Ws),
120            "quic" => Ok(Protocol::Quic),
121            "peer" => {
122                let s = iter.next().ok_or(Error::InvalidProtocol)?;
123                Ok(Protocol::Peer(PeerId::from_str(s)?))
124            }
125            "circuit" => Ok(Protocol::Circuit),
126            "sni" => {
127                let s = iter.next().ok_or(Error::InvalidProtocol)?;
128                Ok(Protocol::Sni(Cow::Borrowed(s)))
129            }
130            "x-with-path" => {
131                let s = iter.next().ok_or(Error::InvalidProtocol)?;
132                let decoded = percent_encoding::percent_decode(s.as_bytes()).decode_utf8()?;
133                Ok(Protocol::Path(decoded))
134            }
135            unknown => Err(Error::UnknownProtocol(unknown.to_string())),
136        }
137    }
138
139    pub fn from_bytes(input: &'a [u8]) -> Result<(Self, &'a [u8]), Error> {
140        fn split_at(n: usize, input: &[u8]) -> Result<(&[u8], &[u8]), Error> {
141            if input.len() < n {
142                return Err(Error::DataLessThanLen);
143            }
144            Ok(input.split_at(n))
145        }
146        let (id, input) = decode::u32(input)?;
147        match id {
148            DNS => {
149                let (n, input) = decode::usize(input)?;
150                let (data, rest) = split_at(n, input)?;
151                Ok((Protocol::Dns(Cow::Borrowed(str::from_utf8(data)?)), rest))
152            }
153            DNS4 => {
154                let (n, input) = decode::usize(input)?;
155                let (data, rest) = split_at(n, input)?;
156                Ok((Protocol::Dns4(Cow::Borrowed(str::from_utf8(data)?)), rest))
157            }
158            DNS6 => {
159                let (n, input) = decode::usize(input)?;
160                let (data, rest) = split_at(n, input)?;
161                Ok((Protocol::Dns6(Cow::Borrowed(str::from_utf8(data)?)), rest))
162            }
163
164            IP4 => {
165                let (data, rest) = split_at(4, input)?;
166                Ok((
167                    Protocol::Ip4(Ipv4Addr::new(data[0], data[1], data[2], data[3])),
168                    rest,
169                ))
170            }
171            IP6 => {
172                let (data, rest) = split_at(16, input)?;
173                let mut rdr = Cursor::new(data);
174                let mut seg = [0_u16; 8];
175
176                for x in seg.iter_mut() {
177                    *x = rdr.read_u16::<BigEndian>()?;
178                }
179
180                let addr = Ipv6Addr::new(
181                    seg[0], seg[1], seg[2], seg[3], seg[4], seg[5], seg[6], seg[7],
182                );
183
184                Ok((Protocol::Ip6(addr), rest))
185            }
186            UNIX => Ok((Protocol::Unix, input)),
187            MEMORY => {
188                let (data, rest) = split_at(8, input)?;
189                let mut rdr = Cursor::new(data);
190                let num = rdr.read_u64::<BigEndian>()?;
191                Ok((Protocol::Memory(num), rest))
192            }
193            TCP => {
194                let (data, rest) = split_at(2, input)?;
195                let mut rdr = Cursor::new(data);
196                let num = rdr.read_u16::<BigEndian>()?;
197                Ok((Protocol::Tcp(num), rest))
198            }
199            UDP => {
200                let (data, rest) = split_at(2, input)?;
201                let mut rdr = Cursor::new(data);
202                let num = rdr.read_u16::<BigEndian>()?;
203                Ok((Protocol::Udp(num), rest))
204            }
205            TLS => Ok((Protocol::Tls, input)),
206            HTTP => Ok((Protocol::Http, input)),
207            WS => Ok((Protocol::Ws, input)),
208            QUIC => Ok((Protocol::Quic, input)),
209            PEER => {
210                let (data, rest) = split_at(32, input)?;
211                let peer_id = PeerId::try_from_slice(data)?;
212                Ok((Protocol::Peer(peer_id), rest))
213            }
214            CIRCUIT => Ok((Protocol::Circuit, input)),
215            SNI => {
216                let (n, input) = decode::usize(input)?;
217                let (data, rest) = split_at(n, input)?;
218                Ok((Protocol::Sni(Cow::Borrowed(str::from_utf8(data)?)), rest))
219            }
220            PATH => {
221                let (n, input) = decode::usize(input)?;
222                let (data, rest) = split_at(n, input)?;
223                Ok((Protocol::Path(Cow::Borrowed(str::from_utf8(data)?)), rest))
224            }
225            _ => Err(Error::UnknownProtocolId(id)),
226        }
227    }
228
229    pub fn write_bytes<W: Write>(&self, w: &mut W) -> Result<(), Error> {
230        let mut buf = encode::u32_buffer();
231        match self {
232            Protocol::Dns(cow) => {
233                w.write_all(encode::u32(DNS, &mut buf))?;
234                let bytes = cow.as_bytes();
235                w.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?;
236                w.write_all(bytes)?
237            }
238            Protocol::Dns4(cow) => {
239                w.write_all(encode::u32(DNS4, &mut buf))?;
240                let bytes = cow.as_bytes();
241                w.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?;
242                w.write_all(bytes)?
243            }
244            Protocol::Dns6(cow) => {
245                w.write_all(encode::u32(DNS6, &mut buf))?;
246                let bytes = cow.as_bytes();
247                w.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?;
248                w.write_all(bytes)?
249            }
250
251            Protocol::Ip4(addr) => {
252                w.write_all(encode::u32(IP4, &mut buf))?;
253                w.write_all(&addr.octets())?
254            }
255            Protocol::Ip6(addr) => {
256                w.write_all(encode::u32(IP6, &mut buf))?;
257                for &segment in &addr.segments() {
258                    w.write_u16::<BigEndian>(segment)?
259                }
260            }
261            Protocol::Unix => {
262                w.write_all(encode::u32(UNIX, &mut buf))?;
263            }
264
265            Protocol::Memory(port) => {
266                w.write_all(encode::u32(MEMORY, &mut buf))?;
267                w.write_u64::<BigEndian>(*port)?
268            }
269            Protocol::Tcp(port) => {
270                w.write_all(encode::u32(TCP, &mut buf))?;
271                w.write_u16::<BigEndian>(*port)?
272            }
273            Protocol::Udp(port) => {
274                w.write_all(encode::u32(UDP, &mut buf))?;
275                w.write_u16::<BigEndian>(*port)?
276            }
277
278            Protocol::Tls => {
279                w.write_all(encode::u32(TLS, &mut buf))?;
280            }
281            Protocol::Http => w.write_all(encode::u32(HTTP, &mut buf))?,
282            Protocol::Ws => {
283                w.write_all(encode::u32(WS, &mut buf))?;
284            }
285            Protocol::Quic => {
286                w.write_all(encode::u32(QUIC, &mut buf))?;
287            }
288
289            Protocol::Peer(p) => {
290                w.write_all(encode::u32(PEER, &mut buf))?;
291                w.write_all(p.as_bytes())?
292            }
293            Protocol::Circuit => {
294                w.write_all(encode::u32(CIRCUIT, &mut buf))?;
295            }
296
297            Protocol::Sni(cow) => {
298                w.write_all(encode::u32(SNI, &mut buf))?;
299                let bytes = cow.as_bytes();
300                w.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?;
301                w.write_all(bytes)?
302            }
303            Protocol::Path(cow) => {
304                w.write_all(encode::u32(PATH, &mut buf))?;
305                let bytes = cow.as_bytes();
306                w.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?;
307                w.write_all(bytes)?
308            }
309        }
310        Ok(())
311    }
312
313    pub fn acquire<'b>(self) -> Protocol<'b> {
314        match self {
315            Protocol::Dns(cow) => Protocol::Dns(Cow::Owned(cow.into_owned())),
316            Protocol::Dns4(cow) => Protocol::Dns4(Cow::Owned(cow.into_owned())),
317            Protocol::Dns6(cow) => Protocol::Dns6(Cow::Owned(cow.into_owned())),
318            Protocol::Http => Protocol::Http,
319            Protocol::Ip4(a) => Protocol::Ip4(a),
320            Protocol::Ip6(a) => Protocol::Ip6(a),
321            Protocol::Memory(a) => Protocol::Memory(a),
322            Protocol::Peer(a) => Protocol::Peer(a),
323            Protocol::Circuit => Protocol::Circuit,
324            Protocol::Quic => Protocol::Quic,
325            Protocol::Tcp(a) => Protocol::Tcp(a),
326            Protocol::Tls => Protocol::Tls,
327            Protocol::Udp(a) => Protocol::Udp(a),
328            Protocol::Unix => Protocol::Unix,
329            Protocol::Ws => Protocol::Ws,
330            Protocol::Sni(cow) => Protocol::Sni(Cow::Owned(cow.into_owned())),
331            Protocol::Path(cow) => Protocol::Path(Cow::Owned(cow.into_owned())),
332        }
333    }
334
335    pub fn tag(&self) -> &'static str {
336        match self {
337            Protocol::Dns(_) => "dns",
338            Protocol::Dns4(_) => "dns4",
339            Protocol::Dns6(_) => "dns6",
340            Protocol::Http => "http",
341            Protocol::Ip4(_) => "ip4",
342            Protocol::Ip6(_) => "ip6",
343            Protocol::Memory(_) => "memory",
344            Protocol::Peer(_) => "peer",
345            Protocol::Circuit => "circuit",
346            Protocol::Quic => "quic",
347            Protocol::Tcp(_) => "tcp",
348            Protocol::Tls => "tls",
349            Protocol::Udp(_) => "udp",
350            Protocol::Unix => "unix",
351            Protocol::Ws => "ws",
352            Protocol::Sni(_) => "sni",
353            Protocol::Path(_) => "x-with-path",
354        }
355    }
356}
357
358impl fmt::Display for Protocol<'_> {
359    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
360        write!(f, "/{}", self.tag())?;
361        match self {
362            Protocol::Dns(s) => write!(f, "/{s}"),
363            Protocol::Dns4(s) => write!(f, "/{s}"),
364            Protocol::Dns6(s) => write!(f, "/{s}"),
365            Protocol::Ip4(addr) => write!(f, "/{addr}"),
366            Protocol::Ip6(addr) => write!(f, "/{addr}"),
367            Protocol::Memory(port) => write!(f, "/{port}"),
368            Protocol::Peer(p) => write!(f, "/{p}"),
369            Protocol::Tcp(port) => write!(f, "/{port}"),
370            Protocol::Udp(port) => write!(f, "/{port}"),
371            Protocol::Sni(s) => write!(f, "/{s}"),
372            Protocol::Path(s) => {
373                let encoded =
374                    percent_encoding::percent_encode(s.as_bytes(), PATH_SEGMENT_ENCODE_SET);
375                write!(f, "/{encoded}")
376            }
377            _ => Ok(()),
378        }
379    }
380}
381
382impl From<IpAddr> for Protocol<'_> {
383    #[inline]
384    fn from(addr: IpAddr) -> Self {
385        match addr {
386            IpAddr::V4(addr) => Protocol::Ip4(addr),
387            IpAddr::V6(addr) => Protocol::Ip6(addr),
388        }
389    }
390}
391
392impl From<Ipv4Addr> for Protocol<'_> {
393    #[inline]
394    fn from(addr: Ipv4Addr) -> Self {
395        Protocol::Ip4(addr)
396    }
397}
398
399impl From<Ipv6Addr> for Protocol<'_> {
400    #[inline]
401    fn from(addr: Ipv6Addr) -> Self {
402        Protocol::Ip6(addr)
403    }
404}