Skip to content

Commit 2efb1d3

Browse files
committed
Return a sequence of Multiaddrs in listen_on.
This is part of the proposed changes to the `Transport` trait as outlined in [1]. To allow transport implementations to listen on multiple addresses we now report all those addresses as a sequence of multi-addresses instead of supporting only a single one. Instead of making `Transport::listen_on` return a generic iterator a concrete type `MultiaddrSeq` is introduced to support non-emptiness. [1]: libp2p#794 (comment)
1 parent 603c7be commit 2efb1d3

31 files changed

+394
-181
lines changed

core/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ pub use multiaddr;
6464
pub use multistream_select::Negotiated;
6565

6666
mod keys_proto;
67+
mod multiaddrs;
6768
mod peer_id;
6869

6970
#[cfg(test)]
@@ -79,6 +80,7 @@ pub mod transport;
7980
pub mod upgrade;
8081

8182
pub use self::multiaddr::Multiaddr;
83+
pub use self::multiaddrs::{MultiaddrSeq, MultiAddrIter, MultiAddrIterMut, IntoMultiAddrIter};
8284
pub use self::muxing::StreamMuxer;
8385
pub use self::peer_id::PeerId;
8486
pub use self::protocols_handler::{ProtocolsHandler, ProtocolsHandlerEvent};

core/src/multiaddrs.rs

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
// Copyright 2019 Parity Technologies (UK) Ltd.
2+
//
3+
// Permission is hereby granted, free of charge, to any person obtaining a
4+
// copy of this software and associated documentation files (the "Software"),
5+
// to deal in the Software without restriction, including without limitation
6+
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
7+
// and/or sell copies of the Software, and to permit persons to whom the
8+
// Software is furnished to do so, subject to the following conditions:
9+
//
10+
// The above copyright notice and this permission notice shall be included in
11+
// all copies or substantial portions of the Software.
12+
//
13+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
14+
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18+
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
19+
// DEALINGS IN THE SOFTWARE.
20+
21+
use multiaddr::Multiaddr;
22+
use smallvec::SmallVec;
23+
use std::{fmt, iter, slice};
24+
25+
/// A non-empty sequence of [`Multiaddr`]s.
26+
#[derive(Clone, Debug, PartialEq, Eq)]
27+
pub struct MultiaddrSeq {
28+
head: Multiaddr,
29+
tail: SmallVec<[Multiaddr; 4]>
30+
}
31+
32+
impl fmt::Display for MultiaddrSeq {
33+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
34+
f.debug_list().entries(self.iter()).finish()
35+
}
36+
}
37+
38+
impl MultiaddrSeq {
39+
/// Create a one-element multi-address sequence.
40+
pub fn singleton(a: Multiaddr) -> Self {
41+
MultiaddrSeq { head: a, tail: SmallVec::new() }
42+
}
43+
44+
/// Get the number of addresses in this sequence.
45+
pub fn len(&self) -> usize {
46+
1 + self.tail.len()
47+
}
48+
49+
/// Get a reference to the first [`Multiaddr`] of this sequence.
50+
pub fn head(&self) -> &Multiaddr {
51+
&self.head
52+
}
53+
54+
/// Get a reference to a [`Multiaddr`] by index.
55+
pub fn get(&self, pos: usize) -> Option<&Multiaddr> {
56+
if pos == 0 {
57+
return Some(&self.head)
58+
}
59+
self.tail.get(pos)
60+
}
61+
62+
/// Get a unique reference to a [`Multiaddr`] by index.
63+
pub fn get_mut(&mut self, pos: usize) -> Option<&mut Multiaddr> {
64+
if pos == 0 {
65+
return Some(&mut self.head)
66+
}
67+
self.tail.get_mut(pos)
68+
}
69+
70+
/// Add a [`Multiaddr`] to the end of this sequence.
71+
pub fn push(&mut self, a: Multiaddr) {
72+
self.tail.push(a)
73+
}
74+
75+
/// Remove and return the last [`Multiaddr`] of this sequence.
76+
///
77+
/// This removes all but the first [`Multiaddr`] from this sequence.
78+
pub fn pop(&mut self) -> Option<Multiaddr> {
79+
self.tail.pop()
80+
}
81+
82+
/// Replace the first element with the given [`Multiaddr`].
83+
pub fn replace_head(&mut self, a: Multiaddr) {
84+
self.head = a
85+
}
86+
87+
/// Create an [`Iterator`] over all [`Multiaddr`] of this sequence.
88+
pub fn iter(&self) -> MultiAddrIter {
89+
MultiAddrIter {
90+
inner: std::iter::once(&self.head).chain(self.tail.iter())
91+
}
92+
}
93+
94+
/// Create a mutable [`Iterator`] over all [`Multiaddr`] of this sequence.
95+
pub fn iter_mut(&mut self) -> MultiAddrIterMut {
96+
MultiAddrIterMut {
97+
inner: std::iter::once(&mut self.head).chain(self.tail.iter_mut())
98+
}
99+
}
100+
}
101+
102+
impl IntoIterator for MultiaddrSeq {
103+
type Item = Multiaddr;
104+
type IntoIter = IntoMultiAddrIter;
105+
106+
fn into_iter(self) -> Self::IntoIter {
107+
IntoMultiAddrIter {
108+
inner: std::iter::once(self.head).chain(self.tail.into_iter())
109+
}
110+
}
111+
}
112+
113+
/// [`Iterator`] implementation returning references to each [`Multiaddr`] in order.
114+
pub struct MultiAddrIter<'a> {
115+
inner: iter::Chain<iter::Once<&'a Multiaddr>, slice::Iter<'a, Multiaddr>>
116+
}
117+
118+
impl<'a> iter::Iterator for MultiAddrIter<'a> {
119+
type Item = &'a Multiaddr;
120+
121+
fn next(&mut self) -> Option<Self::Item> {
122+
self.inner.next()
123+
}
124+
}
125+
126+
/// [`Iterator`] implementation returning unique references to each [`Multiaddr`] in order.
127+
pub struct MultiAddrIterMut<'a> {
128+
inner: iter::Chain<iter::Once<&'a mut Multiaddr>, slice::IterMut<'a, Multiaddr>>
129+
}
130+
131+
impl<'a> iter::Iterator for MultiAddrIterMut<'a> {
132+
type Item = &'a mut Multiaddr;
133+
134+
fn next(&mut self) -> Option<Self::Item> {
135+
self.inner.next()
136+
}
137+
}
138+
139+
/// [`Iterator`] implementation returning [`Multiaddr`]eses in order.
140+
pub struct IntoMultiAddrIter {
141+
inner: iter::Chain<iter::Once<Multiaddr>, smallvec::IntoIter<[Multiaddr; 4]>>
142+
}
143+
144+
impl iter::Iterator for IntoMultiAddrIter {
145+
type Item = Multiaddr;
146+
147+
fn next(&mut self) -> Option<Self::Item> {
148+
self.inner.next()
149+
}
150+
}
151+
152+
/// Convert from [`Multiaddr`] to [`MultiaddrSeq`].
153+
impl From<Multiaddr> for MultiaddrSeq {
154+
fn from(x: Multiaddr) -> Self {
155+
MultiaddrSeq::singleton(x)
156+
}
157+
}
158+

0 commit comments

Comments
 (0)