libp2prs_multiaddr/
lib.rs

1///! Implementation of [multiaddr](https://github.com/jbenet/multiaddr) in Rust.
2pub use multihash;
3
4mod errors;
5mod onion_addr;
6pub mod protocol;
7
8#[cfg(feature = "url")]
9mod from_url;
10
11pub use self::errors::{Error, Result};
12pub use self::onion_addr::Onion3Addr;
13pub use self::protocol::Protocol;
14use serde::{
15    de::{self, Error as DeserializerError},
16    Deserialize, Deserializer, Serialize, Serializer,
17};
18use std::{
19    convert::TryFrom,
20    fmt, io,
21    iter::FromIterator,
22    net::{IpAddr, Ipv4Addr, Ipv6Addr},
23    result::Result as StdResult,
24    str::FromStr,
25    sync::Arc,
26};
27
28#[cfg(feature = "url")]
29pub use self::from_url::{from_url, from_url_lossy, FromUrlErr};
30static_assertions::const_assert! {
31    // This check is most certainly overkill right now, but done here
32    // anyway to ensure the `as u64` casts in this crate are safe.
33    std::mem::size_of::<usize>() <= std::mem::size_of::<u64>()
34}
35
36/// Representation of a Multiaddr.
37#[allow(clippy::rc_buffer)]
38#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Hash)]
39pub struct Multiaddr {
40    bytes: Arc<Vec<u8>>,
41}
42
43impl Multiaddr {
44    /// Create a new, empty multiaddress.
45    pub fn empty() -> Self {
46        Self {
47            bytes: Arc::new(Vec::new()),
48        }
49    }
50
51    /// Create a new, empty multiaddress with the given capacity.
52    pub fn with_capacity(n: usize) -> Self {
53        Self {
54            bytes: Arc::new(Vec::with_capacity(n)),
55        }
56    }
57
58    /// Return the length in bytes of this multiaddress.
59    pub fn len(&self) -> usize {
60        self.bytes.len()
61    }
62
63    /// Returns true if the length of this multiaddress is 0.
64    pub fn is_empty(&self) -> bool {
65        self.bytes.len() == 0
66    }
67
68    /// Return a copy of this [`Multiaddr`]'s byte representation.
69    pub fn to_vec(&self) -> Vec<u8> {
70        Vec::from(&self.bytes[..])
71    }
72
73    /// Adds an already-parsed address component to the end of this multiaddr.
74    ///
75    /// # Examples
76    ///
77    /// ```
78    /// use libp2prs_multiaddr::{Multiaddr, protocol::Protocol};
79    ///
80    /// let mut address: Multiaddr = "/ip4/127.0.0.1".parse().unwrap();
81    /// address.push(Protocol::Tcp(10000));
82    /// assert_eq!(address, "/ip4/127.0.0.1/tcp/10000".parse().unwrap());
83    /// ```
84    ///
85    pub fn push(&mut self, p: Protocol<'_>) {
86        let mut w = io::Cursor::<&mut Vec<u8>>::new(Arc::make_mut(&mut self.bytes));
87        w.set_position(w.get_ref().len() as u64);
88        p.write_bytes(&mut w).expect("Writing to a `io::Cursor<&mut Vec<u8>>` never fails.")
89    }
90
91    /// Pops the last `Protocol` of this multiaddr, or `None` if the multiaddr is empty.
92    /// ```
93    /// use libp2prs_multiaddr::{Multiaddr, protocol::Protocol};
94    ///
95    /// let mut address: Multiaddr = "/ip4/127.0.0.1/udt/sctp/5678".parse().unwrap();
96    ///
97    /// assert_eq!(address.pop().unwrap(), Protocol::Sctp(5678));
98    /// assert_eq!(address.pop().unwrap(), Protocol::Udt);
99    /// ```
100    ///
101    pub fn pop<'a>(&mut self) -> Option<Protocol<'a>> {
102        let mut slice = &self.bytes[..]; // the remaining multiaddr slice
103        if slice.is_empty() {
104            return None;
105        }
106        let protocol = loop {
107            let (p, s) = Protocol::from_bytes(slice).expect("`slice` is a valid `Protocol`.");
108            if s.is_empty() {
109                break p.acquire();
110            }
111            slice = s
112        };
113        let remaining_len = self.bytes.len() - slice.len();
114        Arc::make_mut(&mut self.bytes).truncate(remaining_len);
115        Some(protocol)
116    }
117
118    pub fn value_for_protocol(&self, code: u32) -> Option<String> {
119        let components = self.iter().collect::<Vec<_>>();
120        for comp in components.iter() {
121            if comp.get_key().is_ok() && comp.get_key().unwrap() == code {
122                return Some(comp.to_string());
123            }
124        }
125        None
126    }
127
128    pub fn is_loopback_addr(&self) -> bool {
129        let mut is_loopback = false;
130        let components = self.iter().collect::<Vec<_>>();
131        for comp in components.iter() {
132            match comp {
133                protocol::Protocol::Ip4(ipv4_addr) => {
134                    is_loopback = ipv4_addr.is_loopback();
135                }
136                protocol::Protocol::Ip6(ipv6_addr) => {
137                    is_loopback = ipv6_addr.is_loopback();
138                }
139                _ => {}
140            }
141        }
142        is_loopback
143    }
144
145    pub fn is_private_addr(&self) -> bool {
146        let mut is_private = false;
147        let components = self.iter().collect::<Vec<_>>();
148        for comp in components.iter() {
149            match comp {
150                protocol::Protocol::Ip4(ipv4_addr) => {
151                    is_private = ipv4_addr.is_private() || ipv4_addr.is_loopback() || ipv4_addr.is_link_local();
152                }
153                protocol::Protocol::Ip6(ipv6_addr) => {
154                    is_private = ipv6_addr.is_loopback();
155                    //TODO: unstable feature, ipv6_addr.is_unique_local()||ipv6_addr.is_unicast_link_local();
156                }
157                _ => {}
158            }
159        }
160        is_private
161    }
162
163    /// we don't consume FD's for relay addresses for now as they will be consumed when the Relay Transport actually dials the Relay server.
164    /// That dial call will also pass through this limiter with the address of the relay server i.e. non-relay address.
165    pub fn should_consume_fd(&self) -> bool {
166        let mut find = false;
167        for p in self.iter() {
168            if let Ok(key) = p.get_key() {
169                if key == protocol::UNIX || key == protocol::TCP {
170                    find = true;
171                }
172            }
173        }
174        find
175    }
176
177    /// Like [`Multiaddr::push`] but consumes `self`.
178    pub fn with(mut self, p: Protocol<'_>) -> Self {
179        let mut w = io::Cursor::<&mut Vec<u8>>::new(Arc::make_mut(&mut self.bytes));
180        w.set_position(w.get_ref().len() as u64);
181        p.write_bytes(&mut w).expect("Writing to a `io::Cursor<&mut Vec<u8>>` never fails.");
182        self
183    }
184
185    /// Returns the components of this multiaddress.
186    ///
187    /// # Example
188    ///
189    /// ```rust
190    /// use std::net::Ipv4Addr;
191    /// use libp2prs_multiaddr::{Multiaddr, protocol::Protocol};
192    ///
193    /// let address: Multiaddr = "/ip4/127.0.0.1/udt/sctp/5678".parse().unwrap();
194    ///
195    /// let components = address.iter().collect::<Vec<_>>();
196    /// assert_eq!(components[0], Protocol::Ip4(Ipv4Addr::new(127, 0, 0, 1)));
197    /// assert_eq!(components[1], Protocol::Udt);
198    /// assert_eq!(components[2], Protocol::Sctp(5678));
199    /// ```
200    ///
201    pub fn iter(&self) -> Iter<'_> {
202        Iter(&self.bytes)
203    }
204
205    /// Replace a [`Protocol`] at some position in this `Multiaddr`.
206    ///
207    /// The parameter `at` denotes the index of the protocol at which the function
208    /// `by` will be applied to the current protocol, returning an optional replacement.
209    ///
210    /// If `at` is out of bounds or `by` does not yield a replacement value,
211    /// `None` will be returned. Otherwise a copy of this `Multiaddr` with the
212    /// updated `Protocol` at position `at` will be returned.
213    pub fn replace<'a, F>(&self, at: usize, by: F) -> Option<Multiaddr>
214    where
215        F: FnOnce(&Protocol) -> Option<Protocol<'a>>,
216    {
217        let mut address = Multiaddr::with_capacity(self.len());
218        let mut fun = Some(by);
219        let mut replaced = false;
220
221        for (i, p) in self.iter().enumerate() {
222            if i == at {
223                let f = fun.take().expect("i == at only happens once");
224                if let Some(q) = f(&p) {
225                    address = address.with(q);
226                    replaced = true;
227                    continue;
228                }
229                return None;
230            }
231            address = address.with(p)
232        }
233
234        if replaced {
235            Some(address)
236        } else {
237            None
238        }
239    }
240}
241
242impl fmt::Debug for Multiaddr {
243    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
244        self.to_string().fmt(f)
245    }
246}
247
248impl fmt::Display for Multiaddr {
249    /// Convert a Multiaddr to a string
250    ///
251    /// # Example
252    ///
253    /// ```
254    /// use libp2prs_multiaddr::Multiaddr;
255    ///
256    /// let address: Multiaddr = "/ip4/127.0.0.1/udt".parse().unwrap();
257    /// assert_eq!(address.to_string(), "/ip4/127.0.0.1/udt");
258    /// ```
259    ///
260    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
261        for s in self.iter() {
262            s.to_string().fmt(f)?;
263        }
264        Ok(())
265    }
266}
267
268impl AsRef<[u8]> for Multiaddr {
269    fn as_ref(&self) -> &[u8] {
270        self.bytes.as_ref()
271    }
272}
273
274impl<'a> IntoIterator for &'a Multiaddr {
275    type Item = Protocol<'a>;
276    type IntoIter = Iter<'a>;
277
278    fn into_iter(self) -> Iter<'a> {
279        Iter(&self.bytes)
280    }
281}
282
283impl<'a> FromIterator<Protocol<'a>> for Multiaddr {
284    fn from_iter<T>(iter: T) -> Self
285    where
286        T: IntoIterator<Item = Protocol<'a>>,
287    {
288        let mut writer = Vec::new();
289        for cmp in iter {
290            cmp.write_bytes(&mut writer).expect("Writing to a `Vec` never fails.");
291        }
292        Multiaddr { bytes: Arc::new(writer) }
293    }
294}
295
296impl FromStr for Multiaddr {
297    type Err = Error;
298
299    fn from_str(input: &str) -> Result<Self> {
300        let mut writer = Vec::new();
301        let mut parts = input.split('/').peekable();
302
303        if Some("") != parts.next() {
304            // A multiaddr must start with `/`
305            return Err(Error::InvalidMultiaddr);
306        }
307
308        while parts.peek().is_some() {
309            let p = Protocol::from_str_parts(&mut parts)?;
310            p.write_bytes(&mut writer).expect("Writing to a `Vec` never fails.");
311        }
312
313        Ok(Multiaddr { bytes: Arc::new(writer) })
314    }
315}
316
317/// Iterator over `Multiaddr` [`Protocol`]s.
318pub struct Iter<'a>(&'a [u8]);
319
320impl<'a> Iterator for Iter<'a> {
321    type Item = Protocol<'a>;
322
323    fn next(&mut self) -> Option<Self::Item> {
324        if self.0.is_empty() {
325            return None;
326        }
327
328        let (p, next_data) = Protocol::from_bytes(self.0).expect("`Multiaddr` is known to be valid.");
329
330        self.0 = next_data;
331        Some(p)
332    }
333}
334
335impl<'a> From<Protocol<'a>> for Multiaddr {
336    fn from(p: Protocol<'a>) -> Multiaddr {
337        let mut w = Vec::new();
338        p.write_bytes(&mut w).expect("Writing to a `Vec` never fails.");
339        Multiaddr { bytes: Arc::new(w) }
340    }
341}
342
343impl From<IpAddr> for Multiaddr {
344    fn from(v: IpAddr) -> Multiaddr {
345        match v {
346            IpAddr::V4(a) => a.into(),
347            IpAddr::V6(a) => a.into(),
348        }
349    }
350}
351
352impl From<Ipv4Addr> for Multiaddr {
353    fn from(v: Ipv4Addr) -> Multiaddr {
354        Protocol::Ip4(v).into()
355    }
356}
357
358impl From<Ipv6Addr> for Multiaddr {
359    fn from(v: Ipv6Addr) -> Multiaddr {
360        Protocol::Ip6(v).into()
361    }
362}
363
364impl TryFrom<Vec<u8>> for Multiaddr {
365    type Error = Error;
366
367    fn try_from(v: Vec<u8>) -> Result<Self> {
368        // Check if the argument is a valid `Multiaddr` by reading its protocols.
369        let mut slice = &v[..];
370        while !slice.is_empty() {
371            let (_, s) = Protocol::from_bytes(slice)?;
372            slice = s
373        }
374        Ok(Multiaddr { bytes: Arc::new(v) })
375    }
376}
377
378impl TryFrom<String> for Multiaddr {
379    type Error = Error;
380
381    fn try_from(s: String) -> Result<Multiaddr> {
382        s.parse()
383    }
384}
385
386impl<'a> TryFrom<&'a str> for Multiaddr {
387    type Error = Error;
388
389    fn try_from(s: &'a str) -> Result<Multiaddr> {
390        s.parse()
391    }
392}
393
394impl Serialize for Multiaddr {
395    fn serialize<S>(&self, serializer: S) -> StdResult<S::Ok, S::Error>
396    where
397        S: Serializer,
398    {
399        if serializer.is_human_readable() {
400            serializer.serialize_str(&self.to_string())
401        } else {
402            serializer.serialize_bytes(self.as_ref())
403        }
404    }
405}
406
407impl<'de> Deserialize<'de> for Multiaddr {
408    fn deserialize<D>(deserializer: D) -> StdResult<Self, D::Error>
409    where
410        D: Deserializer<'de>,
411    {
412        struct Visitor {
413            is_human_readable: bool,
414        };
415
416        impl<'de> de::Visitor<'de> for Visitor {
417            type Value = Multiaddr;
418
419            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
420                formatter.write_str("multiaddress")
421            }
422            fn visit_seq<A: de::SeqAccess<'de>>(self, mut seq: A) -> StdResult<Self::Value, A::Error> {
423                let mut buf: Vec<u8> = Vec::with_capacity(seq.size_hint().unwrap_or(0));
424                while let Some(e) = seq.next_element()? {
425                    buf.push(e);
426                }
427                if self.is_human_readable {
428                    let s = String::from_utf8(buf).map_err(DeserializerError::custom)?;
429                    s.parse().map_err(DeserializerError::custom)
430                } else {
431                    Multiaddr::try_from(buf).map_err(DeserializerError::custom)
432                }
433            }
434            fn visit_str<E: de::Error>(self, v: &str) -> StdResult<Self::Value, E> {
435                v.parse().map_err(DeserializerError::custom)
436            }
437            fn visit_borrowed_str<E: de::Error>(self, v: &'de str) -> StdResult<Self::Value, E> {
438                self.visit_str(v)
439            }
440            fn visit_string<E: de::Error>(self, v: String) -> StdResult<Self::Value, E> {
441                self.visit_str(&v)
442            }
443            fn visit_bytes<E: de::Error>(self, v: &[u8]) -> StdResult<Self::Value, E> {
444                self.visit_byte_buf(v.into())
445            }
446            fn visit_borrowed_bytes<E: de::Error>(self, v: &'de [u8]) -> StdResult<Self::Value, E> {
447                self.visit_byte_buf(v.into())
448            }
449            fn visit_byte_buf<E: de::Error>(self, v: Vec<u8>) -> StdResult<Self::Value, E> {
450                Multiaddr::try_from(v).map_err(DeserializerError::custom)
451            }
452        }
453
454        if deserializer.is_human_readable() {
455            deserializer.deserialize_str(Visitor { is_human_readable: true })
456        } else {
457            deserializer.deserialize_bytes(Visitor { is_human_readable: false })
458        }
459    }
460}
461
462/// Easy way for a user to create a `Multiaddr`.
463///
464/// Example:
465///
466/// ```rust
467/// # use libp2prs_multiaddr::multiaddr;
468/// let addr = multiaddr!(Ip4([127, 0, 0, 1]), Tcp(10500u16));
469/// ```
470///
471/// Each element passed to `multiaddr!` should be a variant of the `Protocol` enum. The
472/// optional parameter is turned into the proper type with the `Into` trait.
473///
474/// For example, `Ip4([127, 0, 0, 1])` works because `Ipv4Addr` implements `From<[u8; 4]>`.
475#[macro_export]
476macro_rules! multiaddr {
477    ($($comp:ident $(($param:expr))*),+) => {
478        {
479            use std::iter;
480            let elem = iter::empty::<$crate::protocol::Protocol>();
481            $(
482                let elem = {
483                    let cmp = $crate::protocol::Protocol::$comp $(( $param.into() ))*;
484                    elem.chain(iter::once(cmp))
485                };
486            )+
487            elem.collect::<$crate::Multiaddr>()
488        }
489    }
490}