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}