feat(transport): allow ListenerId to be user-controlled

`Transport::listen_on` is an asynchronous operation. It returns immediately but the actual process of establishing a listening socket happens as part of `Transport::poll` which will return one or more `TransportEvent`s related to a particular `listen_on` call.

Currently, `listen_on` returns a `ListenerId` which allows the user of the `Transport` interface to correlate the events with a particular `listen_on` call. This "user" is the `Swarm` runtime. Currently, a user of libp2p establishes a new listening socket by talking to the `Swarm::listen_on` interface and it is not possible to do the same thing via the `NetworkBehaviour` trait.

Within the `NetworkBehaviour` trait, we emit _commands_ to the `Swarm` like `ToSwarm::Dial`. These commands don't have a "return value" like a synchronous function does and thus, if we were to add a `ToSwarm::ListenOn` command, it could not receive the `ListenerId` from the `Transport`.

To fix this and to be consistent with our [coding guidelines](https://github.com/libp2p/rust-libp2p/blob/master/docs/coding-guidelines.md#allow-correlating-asynchronous-responses-to-their-requests) we change the interface of `Transport::listen_on` to require the user to pass in a `ListenerId`. This will allow us to construct a command in a `NetworkBehaviour` that remembers this ID which enables precise tracking of which events containing a `ListenerId` correlate which a particular `listen_on` command.

This is especially important in the context of listening on wildcard addresses like `0.0.0.0` because we end up binding to multiple network interfaces and thus emit multiple events for a single `listen_on` call.

Pull-Request: #3567.
This commit is contained in:
Darius Clark 2023-05-14 05:42:51 -04:00 committed by GitHub
parent 9e625881d5
commit 5b32c8a0d2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 289 additions and 133 deletions

View File

@ -1,11 +1,15 @@
## 0.40.0 - unreleased ## 0.40.0 - unreleased
- Allow `ListenerId` to be user-controlled, i.e. to be provided on `Transport::listen_on`.
See [PR 3567].
- Raise MSRV to 1.65. - Raise MSRV to 1.65.
See [PR 3715]. See [PR 3715].
- Remove deprecated symbols related to upgrades. - Remove deprecated symbols related to upgrades.
See [PR 3867]. See [PR 3867].
[PR 3567]: https://github.com/libp2p/rust-libp2p/pull/3567
[PR 3715]: https://github.com/libp2p/rust-libp2p/pull/3715 [PR 3715]: https://github.com/libp2p/rust-libp2p/pull/3715
[PR 3867]: https://github.com/libp2p/rust-libp2p/pull/3867 [PR 3867]: https://github.com/libp2p/rust-libp2p/pull/3867

View File

@ -154,14 +154,18 @@ where
} }
} }
fn listen_on(&mut self, addr: Multiaddr) -> Result<ListenerId, TransportError<Self::Error>> { fn listen_on(
&mut self,
id: ListenerId,
addr: Multiaddr,
) -> Result<(), TransportError<Self::Error>> {
use TransportError::*; use TransportError::*;
match self { match self {
Either::Left(a) => a.listen_on(addr).map_err(|e| match e { Either::Left(a) => a.listen_on(id, addr).map_err(|e| match e {
MultiaddrNotSupported(addr) => MultiaddrNotSupported(addr), MultiaddrNotSupported(addr) => MultiaddrNotSupported(addr),
Other(err) => Other(Either::Left(err)), Other(err) => Other(Either::Left(err)),
}), }),
Either::Right(b) => b.listen_on(addr).map_err(|e| match e { Either::Right(b) => b.listen_on(id, addr).map_err(|e| match e {
MultiaddrNotSupported(addr) => MultiaddrNotSupported(addr), MultiaddrNotSupported(addr) => MultiaddrNotSupported(addr),
Other(err) => Other(Either::Right(err)), Other(err) => Other(Either::Right(err)),
}), }),

View File

@ -31,6 +31,7 @@ use std::{
error::Error, error::Error,
fmt, fmt,
pin::Pin, pin::Pin,
sync::atomic::{AtomicUsize, Ordering},
task::{Context, Poll}, task::{Context, Poll},
}; };
@ -55,6 +56,8 @@ pub use self::memory::MemoryTransport;
pub use self::optional::OptionalTransport; pub use self::optional::OptionalTransport;
pub use self::upgrade::Upgrade; pub use self::upgrade::Upgrade;
static NEXT_LISTENER_ID: AtomicUsize = AtomicUsize::new(1);
/// A transport provides connection-oriented communication between two peers /// A transport provides connection-oriented communication between two peers
/// through ordered streams of data (i.e. connections). /// through ordered streams of data (i.e. connections).
/// ///
@ -109,8 +112,12 @@ pub trait Transport {
/// obtained from [dialing](Transport::dial). /// obtained from [dialing](Transport::dial).
type Dial: Future<Output = Result<Self::Output, Self::Error>>; type Dial: Future<Output = Result<Self::Output, Self::Error>>;
/// Listens on the given [`Multiaddr`] for inbound connections. /// Listens on the given [`Multiaddr`] for inbound connections with a provided [`ListenerId`].
fn listen_on(&mut self, addr: Multiaddr) -> Result<ListenerId, TransportError<Self::Error>>; fn listen_on(
&mut self,
id: ListenerId,
addr: Multiaddr,
) -> Result<(), TransportError<Self::Error>>;
/// Remove a listener. /// Remove a listener.
/// ///
@ -241,18 +248,25 @@ pub trait Transport {
/// The ID of a single listener. /// The ID of a single listener.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct ListenerId(u64); pub struct ListenerId(usize);
impl ListenerId { impl ListenerId {
#[deprecated(note = "Renamed to ` ListenerId::next`.")]
#[allow(clippy::new_without_default)]
/// Creates a new `ListenerId`. /// Creates a new `ListenerId`.
pub fn new() -> Self { pub fn new() -> Self {
ListenerId(rand::random()) ListenerId::next()
} }
}
impl Default for ListenerId { /// Creates a new `ListenerId`.
fn default() -> Self { pub fn next() -> Self {
Self::new() ListenerId(NEXT_LISTENER_ID.fetch_add(1, Ordering::SeqCst))
}
#[deprecated(note = "Use ` ListenerId::next` instead.")]
#[allow(clippy::should_implement_trait)]
pub fn default() -> Self {
Self::next()
} }
} }

View File

@ -54,9 +54,13 @@ where
type ListenerUpgrade = AndThenFuture<T::ListenerUpgrade, C, F>; type ListenerUpgrade = AndThenFuture<T::ListenerUpgrade, C, F>;
type Dial = AndThenFuture<T::Dial, C, F>; type Dial = AndThenFuture<T::Dial, C, F>;
fn listen_on(&mut self, addr: Multiaddr) -> Result<ListenerId, TransportError<Self::Error>> { fn listen_on(
&mut self,
id: ListenerId,
addr: Multiaddr,
) -> Result<(), TransportError<Self::Error>> {
self.transport self.transport
.listen_on(addr) .listen_on(id, addr)
.map_err(|err| err.map(Either::Left)) .map_err(|err| err.map(Either::Left))
} }

View File

@ -52,7 +52,11 @@ type Dial<O> = Pin<Box<dyn Future<Output = io::Result<O>> + Send>>;
type ListenerUpgrade<O> = Pin<Box<dyn Future<Output = io::Result<O>> + Send>>; type ListenerUpgrade<O> = Pin<Box<dyn Future<Output = io::Result<O>> + Send>>;
trait Abstract<O> { trait Abstract<O> {
fn listen_on(&mut self, addr: Multiaddr) -> Result<ListenerId, TransportError<io::Error>>; fn listen_on(
&mut self,
id: ListenerId,
addr: Multiaddr,
) -> Result<(), TransportError<io::Error>>;
fn remove_listener(&mut self, id: ListenerId) -> bool; fn remove_listener(&mut self, id: ListenerId) -> bool;
fn dial(&mut self, addr: Multiaddr) -> Result<Dial<O>, TransportError<io::Error>>; fn dial(&mut self, addr: Multiaddr) -> Result<Dial<O>, TransportError<io::Error>>;
fn dial_as_listener(&mut self, addr: Multiaddr) -> Result<Dial<O>, TransportError<io::Error>>; fn dial_as_listener(&mut self, addr: Multiaddr) -> Result<Dial<O>, TransportError<io::Error>>;
@ -70,8 +74,12 @@ where
T::Dial: Send + 'static, T::Dial: Send + 'static,
T::ListenerUpgrade: Send + 'static, T::ListenerUpgrade: Send + 'static,
{ {
fn listen_on(&mut self, addr: Multiaddr) -> Result<ListenerId, TransportError<io::Error>> { fn listen_on(
Transport::listen_on(self, addr).map_err(|e| e.map(box_err)) &mut self,
id: ListenerId,
addr: Multiaddr,
) -> Result<(), TransportError<io::Error>> {
Transport::listen_on(self, id, addr).map_err(|e| e.map(box_err))
} }
fn remove_listener(&mut self, id: ListenerId) -> bool { fn remove_listener(&mut self, id: ListenerId) -> bool {
@ -123,8 +131,12 @@ impl<O> Transport for Boxed<O> {
type ListenerUpgrade = ListenerUpgrade<O>; type ListenerUpgrade = ListenerUpgrade<O>;
type Dial = Dial<O>; type Dial = Dial<O>;
fn listen_on(&mut self, addr: Multiaddr) -> Result<ListenerId, TransportError<Self::Error>> { fn listen_on(
self.inner.listen_on(addr) &mut self,
id: ListenerId,
addr: Multiaddr,
) -> Result<(), TransportError<Self::Error>> {
self.inner.listen_on(id, addr)
} }
fn remove_listener(&mut self, id: ListenerId) -> bool { fn remove_listener(&mut self, id: ListenerId) -> bool {

View File

@ -46,13 +46,17 @@ where
type ListenerUpgrade = EitherFuture<A::ListenerUpgrade, B::ListenerUpgrade>; type ListenerUpgrade = EitherFuture<A::ListenerUpgrade, B::ListenerUpgrade>;
type Dial = EitherFuture<A::Dial, B::Dial>; type Dial = EitherFuture<A::Dial, B::Dial>;
fn listen_on(&mut self, addr: Multiaddr) -> Result<ListenerId, TransportError<Self::Error>> { fn listen_on(
let addr = match self.0.listen_on(addr) { &mut self,
id: ListenerId,
addr: Multiaddr,
) -> Result<(), TransportError<Self::Error>> {
let addr = match self.0.listen_on(id, addr) {
Err(TransportError::MultiaddrNotSupported(addr)) => addr, Err(TransportError::MultiaddrNotSupported(addr)) => addr,
res => return res.map_err(|err| err.map(Either::Left)), res => return res.map_err(|err| err.map(Either::Left)),
}; };
let addr = match self.1.listen_on(addr) { let addr = match self.1.listen_on(id, addr) {
Err(TransportError::MultiaddrNotSupported(addr)) => addr, Err(TransportError::MultiaddrNotSupported(addr)) => addr,
res => return res.map_err(|err| err.map(Either::Right)), res => return res.map_err(|err| err.map(Either::Right)),
}; };

View File

@ -59,7 +59,11 @@ impl<TOut> Transport for DummyTransport<TOut> {
type ListenerUpgrade = futures::future::Pending<Result<Self::Output, io::Error>>; type ListenerUpgrade = futures::future::Pending<Result<Self::Output, io::Error>>;
type Dial = futures::future::Pending<Result<Self::Output, io::Error>>; type Dial = futures::future::Pending<Result<Self::Output, io::Error>>;
fn listen_on(&mut self, addr: Multiaddr) -> Result<ListenerId, TransportError<Self::Error>> { fn listen_on(
&mut self,
_id: ListenerId,
addr: Multiaddr,
) -> Result<(), TransportError<Self::Error>> {
Err(TransportError::MultiaddrNotSupported(addr)) Err(TransportError::MultiaddrNotSupported(addr))
} }

View File

@ -276,8 +276,12 @@ impl<T: crate::Transport + Unpin> crate::Transport for Transport<T> {
type ListenerUpgrade = <T as crate::Transport>::ListenerUpgrade; type ListenerUpgrade = <T as crate::Transport>::ListenerUpgrade;
type Dial = <T as crate::Transport>::Dial; type Dial = <T as crate::Transport>::Dial;
fn listen_on(&mut self, addr: Multiaddr) -> Result<ListenerId, TransportError<Self::Error>> { fn listen_on(
self.inner.listen_on(addr) &mut self,
id: ListenerId,
addr: Multiaddr,
) -> Result<(), TransportError<Self::Error>> {
self.inner.listen_on(id, addr)
} }
fn remove_listener(&mut self, id: ListenerId) -> bool { fn remove_listener(&mut self, id: ListenerId) -> bool {

View File

@ -61,8 +61,12 @@ where
type ListenerUpgrade = MapFuture<T::ListenerUpgrade, F>; type ListenerUpgrade = MapFuture<T::ListenerUpgrade, F>;
type Dial = MapFuture<T::Dial, F>; type Dial = MapFuture<T::Dial, F>;
fn listen_on(&mut self, addr: Multiaddr) -> Result<ListenerId, TransportError<Self::Error>> { fn listen_on(
self.transport.listen_on(addr) &mut self,
id: ListenerId,
addr: Multiaddr,
) -> Result<(), TransportError<Self::Error>> {
self.transport.listen_on(id, addr)
} }
fn remove_listener(&mut self, id: ListenerId) -> bool { fn remove_listener(&mut self, id: ListenerId) -> bool {

View File

@ -50,9 +50,15 @@ where
type ListenerUpgrade = MapErrListenerUpgrade<T, F>; type ListenerUpgrade = MapErrListenerUpgrade<T, F>;
type Dial = MapErrDial<T, F>; type Dial = MapErrDial<T, F>;
fn listen_on(&mut self, addr: Multiaddr) -> Result<ListenerId, TransportError<Self::Error>> { fn listen_on(
&mut self,
id: ListenerId,
addr: Multiaddr,
) -> Result<(), TransportError<Self::Error>> {
let map = self.map.clone(); let map = self.map.clone();
self.transport.listen_on(addr).map_err(|err| err.map(map)) self.transport
.listen_on(id, addr)
.map_err(|err| err.map(map))
} }
fn remove_listener(&mut self, id: ListenerId) -> bool { fn remove_listener(&mut self, id: ListenerId) -> bool {

View File

@ -179,7 +179,11 @@ impl Transport for MemoryTransport {
type ListenerUpgrade = Ready<Result<Self::Output, Self::Error>>; type ListenerUpgrade = Ready<Result<Self::Output, Self::Error>>;
type Dial = DialFuture; type Dial = DialFuture;
fn listen_on(&mut self, addr: Multiaddr) -> Result<ListenerId, TransportError<Self::Error>> { fn listen_on(
&mut self,
id: ListenerId,
addr: Multiaddr,
) -> Result<(), TransportError<Self::Error>> {
let port = if let Ok(port) = parse_memory_addr(&addr) { let port = if let Ok(port) = parse_memory_addr(&addr) {
port port
} else { } else {
@ -191,7 +195,6 @@ impl Transport for MemoryTransport {
None => return Err(TransportError::Other(MemoryTransportError::Unreachable)), None => return Err(TransportError::Other(MemoryTransportError::Unreachable)),
}; };
let id = ListenerId::new();
let listener = Listener { let listener = Listener {
id, id,
port, port,
@ -201,7 +204,7 @@ impl Transport for MemoryTransport {
}; };
self.listeners.push_back(Box::pin(listener)); self.listeners.push_back(Box::pin(listener));
Ok(id) Ok(())
} }
fn remove_listener(&mut self, id: ListenerId) -> bool { fn remove_listener(&mut self, id: ListenerId) -> bool {
@ -457,30 +460,40 @@ mod tests {
let addr_1: Multiaddr = "/memory/1639174018481".parse().unwrap(); let addr_1: Multiaddr = "/memory/1639174018481".parse().unwrap();
let addr_2: Multiaddr = "/memory/8459375923478".parse().unwrap(); let addr_2: Multiaddr = "/memory/8459375923478".parse().unwrap();
let listener_id_1 = transport.listen_on(addr_1.clone()).unwrap(); let listener_id_1 = ListenerId::next();
transport.listen_on(listener_id_1, addr_1.clone()).unwrap();
assert!( assert!(
transport.remove_listener(listener_id_1), transport.remove_listener(listener_id_1),
"Listener doesn't exist." "Listener doesn't exist."
); );
let listener_id_2 = transport.listen_on(addr_1.clone()).unwrap(); let listener_id_2 = ListenerId::next();
let listener_id_3 = transport.listen_on(addr_2.clone()).unwrap(); transport.listen_on(listener_id_2, addr_1.clone()).unwrap();
let listener_id_3 = ListenerId::next();
transport.listen_on(listener_id_3, addr_2.clone()).unwrap();
assert!(transport.listen_on(addr_1.clone()).is_err()); assert!(transport
assert!(transport.listen_on(addr_2.clone()).is_err()); .listen_on(ListenerId::next(), addr_1.clone())
.is_err());
assert!(transport
.listen_on(ListenerId::next(), addr_2.clone())
.is_err());
assert!( assert!(
transport.remove_listener(listener_id_2), transport.remove_listener(listener_id_2),
"Listener doesn't exist." "Listener doesn't exist."
); );
assert!(transport.listen_on(addr_1).is_ok()); assert!(transport.listen_on(ListenerId::next(), addr_1).is_ok());
assert!(transport.listen_on(addr_2.clone()).is_err()); assert!(transport
.listen_on(ListenerId::next(), addr_2.clone())
.is_err());
assert!( assert!(
transport.remove_listener(listener_id_3), transport.remove_listener(listener_id_3),
"Listener doesn't exist." "Listener doesn't exist."
); );
assert!(transport.listen_on(addr_2).is_ok()); assert!(transport.listen_on(ListenerId::next(), addr_2).is_ok());
} }
#[test] #[test]
@ -489,8 +502,11 @@ mod tests {
assert!(transport assert!(transport
.dial("/memory/810172461024613".parse().unwrap()) .dial("/memory/810172461024613".parse().unwrap())
.is_err()); .is_err());
let _listener = transport transport
.listen_on("/memory/810172461024613".parse().unwrap()) .listen_on(
ListenerId::next(),
"/memory/810172461024613".parse().unwrap(),
)
.unwrap(); .unwrap();
assert!(transport assert!(transport
.dial("/memory/810172461024613".parse().unwrap()) .dial("/memory/810172461024613".parse().unwrap())
@ -504,7 +520,8 @@ mod tests {
let mut transport = MemoryTransport::default().boxed(); let mut transport = MemoryTransport::default().boxed();
futures::executor::block_on(async { futures::executor::block_on(async {
let listener_id = transport.listen_on(addr.clone()).unwrap(); let listener_id = ListenerId::next();
transport.listen_on(listener_id, addr.clone()).unwrap();
let reported_addr = transport let reported_addr = transport
.select_next_some() .select_next_some()
.await .await
@ -539,7 +556,7 @@ mod tests {
let mut t1 = MemoryTransport::default().boxed(); let mut t1 = MemoryTransport::default().boxed();
let listener = async move { let listener = async move {
t1.listen_on(t1_addr.clone()).unwrap(); t1.listen_on(ListenerId::next(), t1_addr.clone()).unwrap();
let upgrade = loop { let upgrade = loop {
let event = t1.select_next_some().await; let event = t1.select_next_some().await;
if let Some(upgrade) = event.into_incoming() { if let Some(upgrade) = event.into_incoming() {
@ -577,7 +594,9 @@ mod tests {
let mut listener_transport = MemoryTransport::default().boxed(); let mut listener_transport = MemoryTransport::default().boxed();
let listener = async move { let listener = async move {
listener_transport.listen_on(listener_addr.clone()).unwrap(); listener_transport
.listen_on(ListenerId::next(), listener_addr.clone())
.unwrap();
loop { loop {
if let TransportEvent::Incoming { send_back_addr, .. } = if let TransportEvent::Incoming { send_back_addr, .. } =
listener_transport.select_next_some().await listener_transport.select_next_some().await
@ -614,7 +633,9 @@ mod tests {
let mut listener_transport = MemoryTransport::default().boxed(); let mut listener_transport = MemoryTransport::default().boxed();
let listener = async move { let listener = async move {
listener_transport.listen_on(listener_addr.clone()).unwrap(); listener_transport
.listen_on(ListenerId::next(), listener_addr.clone())
.unwrap();
loop { loop {
if let TransportEvent::Incoming { send_back_addr, .. } = if let TransportEvent::Incoming { send_back_addr, .. } =
listener_transport.select_next_some().await listener_transport.select_next_some().await

View File

@ -60,9 +60,13 @@ where
type ListenerUpgrade = T::ListenerUpgrade; type ListenerUpgrade = T::ListenerUpgrade;
type Dial = T::Dial; type Dial = T::Dial;
fn listen_on(&mut self, addr: Multiaddr) -> Result<ListenerId, TransportError<Self::Error>> { fn listen_on(
&mut self,
id: ListenerId,
addr: Multiaddr,
) -> Result<(), TransportError<Self::Error>> {
if let Some(inner) = self.0.as_mut() { if let Some(inner) = self.0.as_mut() {
inner.listen_on(addr) inner.listen_on(id, addr)
} else { } else {
Err(TransportError::MultiaddrNotSupported(addr)) Err(TransportError::MultiaddrNotSupported(addr))
} }

View File

@ -85,9 +85,13 @@ where
type ListenerUpgrade = Timeout<InnerTrans::ListenerUpgrade>; type ListenerUpgrade = Timeout<InnerTrans::ListenerUpgrade>;
type Dial = Timeout<InnerTrans::Dial>; type Dial = Timeout<InnerTrans::Dial>;
fn listen_on(&mut self, addr: Multiaddr) -> Result<ListenerId, TransportError<Self::Error>> { fn listen_on(
&mut self,
id: ListenerId,
addr: Multiaddr,
) -> Result<(), TransportError<Self::Error>> {
self.inner self.inner
.listen_on(addr) .listen_on(id, addr)
.map_err(|err| err.map(TransportTimeoutError::Other)) .map_err(|err| err.map(TransportTimeoutError::Other))
} }

View File

@ -350,8 +350,12 @@ where
self.0.dial_as_listener(addr) self.0.dial_as_listener(addr)
} }
fn listen_on(&mut self, addr: Multiaddr) -> Result<ListenerId, TransportError<Self::Error>> { fn listen_on(
self.0.listen_on(addr) &mut self,
id: ListenerId,
addr: Multiaddr,
) -> Result<(), TransportError<Self::Error>> {
self.0.listen_on(id, addr)
} }
fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> { fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
@ -429,9 +433,13 @@ where
}) })
} }
fn listen_on(&mut self, addr: Multiaddr) -> Result<ListenerId, TransportError<Self::Error>> { fn listen_on(
&mut self,
id: ListenerId,
addr: Multiaddr,
) -> Result<(), TransportError<Self::Error>> {
self.inner self.inner
.listen_on(addr) .listen_on(id, addr)
.map_err(|err| err.map(TransportUpgradeError::Transport)) .map_err(|err| err.map(TransportUpgradeError::Transport))
} }

View File

@ -19,7 +19,7 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
use futures::prelude::*; use futures::prelude::*;
use libp2p_core::transport::{MemoryTransport, Transport}; use libp2p_core::transport::{ListenerId, MemoryTransport, Transport};
use libp2p_core::upgrade::{self, InboundUpgrade, OutboundUpgrade, UpgradeInfo}; use libp2p_core::upgrade::{self, InboundUpgrade, OutboundUpgrade, UpgradeInfo};
use libp2p_identity as identity; use libp2p_identity as identity;
use libp2p_mplex::MplexConfig; use libp2p_mplex::MplexConfig;
@ -102,7 +102,9 @@ fn upgrade_pipeline() {
let listen_addr1 = Multiaddr::from(Protocol::Memory(random::<u64>())); let listen_addr1 = Multiaddr::from(Protocol::Memory(random::<u64>()));
let listen_addr2 = listen_addr1.clone(); let listen_addr2 = listen_addr1.clone();
listener_transport.listen_on(listen_addr1).unwrap(); listener_transport
.listen_on(ListenerId::next(), listen_addr1)
.unwrap();
let server = async move { let server = async move {
loop { loop {

View File

@ -27,6 +27,7 @@ use futures::future::poll_fn;
use futures::prelude::*; use futures::prelude::*;
use futures::{channel::oneshot, future::join}; use futures::{channel::oneshot, future::join};
use libp2p_core::muxing::StreamMuxerExt; use libp2p_core::muxing::StreamMuxerExt;
use libp2p_core::transport::ListenerId;
use libp2p_core::{multiaddr::multiaddr, muxing, transport, upgrade, Multiaddr, Transport}; use libp2p_core::{multiaddr::multiaddr, muxing, transport, upgrade, Multiaddr, Transport};
use libp2p_identity as identity; use libp2p_identity as identity;
use libp2p_identity::PeerId; use libp2p_identity::PeerId;
@ -100,7 +101,9 @@ fn run(
payload: &Vec<u8>, payload: &Vec<u8>,
listen_addr: &Multiaddr, listen_addr: &Multiaddr,
) { ) {
receiver_trans.listen_on(listen_addr.clone()).unwrap(); receiver_trans
.listen_on(ListenerId::next(), listen_addr.clone())
.unwrap();
let (addr_sender, addr_receiver) = oneshot::channel(); let (addr_sender, addr_receiver) = oneshot::channel();
let mut addr_sender = Some(addr_sender); let mut addr_sender = Some(addr_sender);
let payload_len = payload.len(); let payload_len = payload.len();

View File

@ -88,7 +88,7 @@ mod tests {
use futures::StreamExt; use futures::StreamExt;
use libp2p_core::{ use libp2p_core::{
multiaddr::multiaddr, multiaddr::multiaddr,
transport::{memory::MemoryTransport, Transport}, transport::{memory::MemoryTransport, ListenerId, Transport},
}; };
use rand::{thread_rng, Rng}; use rand::{thread_rng, Rng};
use std::time::Duration; use std::time::Duration;
@ -97,7 +97,7 @@ mod tests {
fn ping_pong() { fn ping_pong() {
let mem_addr = multiaddr![Memory(thread_rng().gen::<u64>())]; let mem_addr = multiaddr![Memory(thread_rng().gen::<u64>())];
let mut transport = MemoryTransport::new().boxed(); let mut transport = MemoryTransport::new().boxed();
transport.listen_on(mem_addr).unwrap(); transport.listen_on(ListenerId::next(), mem_addr).unwrap();
let listener_addr = transport let listener_addr = transport
.select_next_some() .select_next_some()

View File

@ -70,7 +70,7 @@ use thiserror::Error;
/// 3. Listen for incoming relayed connections via specific relay. /// 3. Listen for incoming relayed connections via specific relay.
/// ///
/// ``` /// ```
/// # use libp2p_core::{Multiaddr, multiaddr::{Protocol}, Transport, PeerId}; /// # use libp2p_core::{Multiaddr, multiaddr::{Protocol}, transport::ListenerId, Transport, PeerId};
/// # use libp2p_core::transport::memory::MemoryTransport; /// # use libp2p_core::transport::memory::MemoryTransport;
/// # use libp2p_core::transport::choice::OrTransport; /// # use libp2p_core::transport::choice::OrTransport;
/// # use libp2p_relay as relay; /// # use libp2p_relay as relay;
@ -85,7 +85,7 @@ use thiserror::Error;
/// .with(Protocol::Memory(40)) // Relay address. /// .with(Protocol::Memory(40)) // Relay address.
/// .with(Protocol::P2p(relay_id.into())) // Relay peer id. /// .with(Protocol::P2p(relay_id.into())) // Relay peer id.
/// .with(Protocol::P2pCircuit); // Signal to listen via remote relay node. /// .with(Protocol::P2pCircuit); // Signal to listen via remote relay node.
/// transport.listen_on(relay_addr).unwrap(); /// transport.listen_on(ListenerId::next(), relay_addr).unwrap();
/// ``` /// ```
pub struct Transport { pub struct Transport {
to_behaviour: mpsc::Sender<TransportToBehaviourMsg>, to_behaviour: mpsc::Sender<TransportToBehaviourMsg>,
@ -111,7 +111,11 @@ impl libp2p_core::Transport for Transport {
type ListenerUpgrade = Ready<Result<Self::Output, Self::Error>>; type ListenerUpgrade = Ready<Result<Self::Output, Self::Error>>;
type Dial = BoxFuture<'static, Result<Connection, Error>>; type Dial = BoxFuture<'static, Result<Connection, Error>>;
fn listen_on(&mut self, addr: Multiaddr) -> Result<ListenerId, TransportError<Self::Error>> { fn listen_on(
&mut self,
listener_id: ListenerId,
addr: Multiaddr,
) -> Result<(), TransportError<Self::Error>> {
let (relay_peer_id, relay_addr) = match parse_relayed_multiaddr(addr)? { let (relay_peer_id, relay_addr) = match parse_relayed_multiaddr(addr)? {
RelayedMultiaddr { RelayedMultiaddr {
relay_peer_id: None, relay_peer_id: None,
@ -138,7 +142,6 @@ impl libp2p_core::Transport for Transport {
to_listener, to_listener,
}); });
let listener_id = ListenerId::new();
let listener = Listener { let listener = Listener {
listener_id, listener_id,
queued_events: Default::default(), queued_events: Default::default(),
@ -146,7 +149,7 @@ impl libp2p_core::Transport for Transport {
is_closed: false, is_closed: false,
}; };
self.listeners.push(listener); self.listeners.push(listener);
Ok(listener_id) Ok(())
} }
fn remove_listener(&mut self, id: ListenerId) -> bool { fn remove_listener(&mut self, id: ListenerId) -> bool {

View File

@ -34,7 +34,7 @@ impl ListenAddresses {
mod tests { mod tests {
use super::*; use super::*;
use crate::dummy; use crate::dummy;
use libp2p_core::multiaddr::Protocol; use libp2p_core::{multiaddr::Protocol, transport::ListenerId};
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
#[test] #[test]
@ -62,14 +62,14 @@ mod tests {
fn new_listen_addr() -> FromSwarm<'static, dummy::ConnectionHandler> { fn new_listen_addr() -> FromSwarm<'static, dummy::ConnectionHandler> {
FromSwarm::NewListenAddr(NewListenAddr { FromSwarm::NewListenAddr(NewListenAddr {
listener_id: Default::default(), listener_id: ListenerId::next(),
addr: &MEMORY_ADDR, addr: &MEMORY_ADDR,
}) })
} }
fn expired_listen_addr() -> FromSwarm<'static, dummy::ConnectionHandler> { fn expired_listen_addr() -> FromSwarm<'static, dummy::ConnectionHandler> {
FromSwarm::ExpiredListenAddr(ExpiredListenAddr { FromSwarm::ExpiredListenAddr(ExpiredListenAddr {
listener_id: Default::default(), listener_id: ListenerId::next(),
addr: &MEMORY_ADDR, addr: &MEMORY_ADDR,
}) })
} }

View File

@ -474,7 +474,8 @@ where
/// Listeners report their new listening addresses as [`SwarmEvent::NewListenAddr`]. /// Listeners report their new listening addresses as [`SwarmEvent::NewListenAddr`].
/// Depending on the underlying transport, one listener may have multiple listening addresses. /// Depending on the underlying transport, one listener may have multiple listening addresses.
pub fn listen_on(&mut self, addr: Multiaddr) -> Result<ListenerId, TransportError<io::Error>> { pub fn listen_on(&mut self, addr: Multiaddr) -> Result<ListenerId, TransportError<io::Error>> {
let id = self.transport.listen_on(addr)?; let id = ListenerId::next();
self.transport.listen_on(id, addr)?;
self.behaviour self.behaviour
.on_swarm_event(FromSwarm::NewListener(behaviour::NewListener { .on_swarm_event(FromSwarm::NewListener(behaviour::NewListener {
listener_id: id, listener_id: id,
@ -2222,7 +2223,9 @@ mod tests {
let mut transports = Vec::new(); let mut transports = Vec::new();
for _ in 0..num_listen_addrs { for _ in 0..num_listen_addrs {
let mut transport = transport::MemoryTransport::default().boxed(); let mut transport = transport::MemoryTransport::default().boxed();
transport.listen_on("/memory/0".parse().unwrap()).unwrap(); transport
.listen_on(ListenerId::next(), "/memory/0".parse().unwrap())
.unwrap();
match transport.select_next_some().await { match transport.select_next_some().await {
TransportEvent::NewAddress { listen_addr, .. } => { TransportEvent::NewAddress { listen_addr, .. } => {

View File

@ -198,10 +198,14 @@ where
BoxFuture<'static, Result<Self::Output, Self::Error>>, BoxFuture<'static, Result<Self::Output, Self::Error>>,
>; >;
fn listen_on(&mut self, addr: Multiaddr) -> Result<ListenerId, TransportError<Self::Error>> { fn listen_on(
&mut self,
id: ListenerId,
addr: Multiaddr,
) -> Result<(), TransportError<Self::Error>> {
self.inner self.inner
.lock() .lock()
.listen_on(addr) .listen_on(id, addr)
.map_err(|e| e.map(DnsErr::Transport)) .map_err(|e| e.map(DnsErr::Transport))
} }
@ -599,8 +603,9 @@ mod tests {
fn listen_on( fn listen_on(
&mut self, &mut self,
_: ListenerId,
_: Multiaddr, _: Multiaddr,
) -> Result<ListenerId, TransportError<Self::Error>> { ) -> Result<(), TransportError<Self::Error>> {
unreachable!() unreachable!()
} }

View File

@ -32,7 +32,7 @@
//! # fn main() -> std::io::Result<()> { //! # fn main() -> std::io::Result<()> {
//! # //! #
//! use libp2p_quic as quic; //! use libp2p_quic as quic;
//! use libp2p_core::{Multiaddr, Transport}; //! use libp2p_core::{Multiaddr, Transport, transport::ListenerId};
//! //!
//! let keypair = libp2p_identity::Keypair::generate_ed25519(); //! let keypair = libp2p_identity::Keypair::generate_ed25519();
//! let quic_config = quic::Config::new(&keypair); //! let quic_config = quic::Config::new(&keypair);
@ -40,7 +40,7 @@
//! let mut quic_transport = quic::async_std::Transport::new(quic_config); //! let mut quic_transport = quic::async_std::Transport::new(quic_config);
//! //!
//! let addr = "/ip4/127.0.0.1/udp/12345/quic-v1".parse().expect("address should be valid"); //! let addr = "/ip4/127.0.0.1/udp/12345/quic-v1".parse().expect("address should be valid");
//! quic_transport.listen_on(addr).expect("listen error."); //! quic_transport.listen_on(ListenerId::next(), addr).expect("listen error.");
//! # //! #
//! # Ok(()) //! # Ok(())
//! # } //! # }

View File

@ -98,10 +98,13 @@ impl<P: Provider> Transport for GenTransport<P> {
type ListenerUpgrade = Connecting; type ListenerUpgrade = Connecting;
type Dial = BoxFuture<'static, Result<Self::Output, Self::Error>>; type Dial = BoxFuture<'static, Result<Self::Output, Self::Error>>;
fn listen_on(&mut self, addr: Multiaddr) -> Result<ListenerId, TransportError<Self::Error>> { fn listen_on(
&mut self,
listener_id: ListenerId,
addr: Multiaddr,
) -> Result<(), TransportError<Self::Error>> {
let (socket_addr, version) = multiaddr_to_socketaddr(&addr, self.support_draft_29) let (socket_addr, version) = multiaddr_to_socketaddr(&addr, self.support_draft_29)
.ok_or(TransportError::MultiaddrNotSupported(addr))?; .ok_or(TransportError::MultiaddrNotSupported(addr))?;
let listener_id = ListenerId::new();
let listener = Listener::new( let listener = Listener::new(
listener_id, listener_id,
socket_addr, socket_addr,
@ -120,7 +123,7 @@ impl<P: Provider> Transport for GenTransport<P> {
// New outbound connections will use the bidirectional (listener) endpoint. // New outbound connections will use the bidirectional (listener) endpoint.
self.dialer.remove(&socket_addr.ip().into()); self.dialer.remove(&socket_addr.ip().into());
Ok(listener_id) Ok(())
} }
fn remove_listener(&mut self, id: ListenerId) -> bool { fn remove_listener(&mut self, id: ListenerId) -> bool {
@ -772,8 +775,9 @@ mod test {
// Run test twice to check that there is no unexpected behaviour if `Transport.listener` // Run test twice to check that there is no unexpected behaviour if `Transport.listener`
// is temporarily empty. // is temporarily empty.
for _ in 0..2 { for _ in 0..2 {
let id = transport let id = ListenerId::next();
.listen_on("/ip4/0.0.0.0/udp/0/quic-v1".parse().unwrap()) transport
.listen_on(id, "/ip4/0.0.0.0/udp/0/quic-v1".parse().unwrap())
.unwrap(); .unwrap();
// Copy channel to use it later. // Copy channel to use it later.
@ -866,8 +870,11 @@ mod test {
.await; .await;
// Start listening so that the dialer and driver are dropped. // Start listening so that the dialer and driver are dropped.
let _ = transport transport
.listen_on("/ip4/0.0.0.0/udp/0/quic-v1".parse().unwrap()) .listen_on(
ListenerId::next(),
"/ip4/0.0.0.0/udp/0/quic-v1".parse().unwrap(),
)
.unwrap(); .unwrap();
assert!(!transport.dialer.contains_key(&SocketFamily::Ipv4)); assert!(!transport.dialer.contains_key(&SocketFamily::Ipv4));

View File

@ -115,9 +115,10 @@ async fn wrapped_with_delay() {
fn listen_on( fn listen_on(
&mut self, &mut self,
id: ListenerId,
addr: Multiaddr, addr: Multiaddr,
) -> Result<ListenerId, TransportError<Self::Error>> { ) -> Result<(), TransportError<Self::Error>> {
self.0.lock().unwrap().listen_on(addr) self.0.lock().unwrap().listen_on(id, addr)
} }
fn remove_listener(&mut self, id: ListenerId) -> bool { fn remove_listener(&mut self, id: ListenerId) -> bool {
@ -327,7 +328,10 @@ async fn draft_29_support() {
let (_, mut d_transport) = let (_, mut d_transport) =
create_transport::<quic::tokio::Provider>(|cfg| cfg.support_draft_29 = false); create_transport::<quic::tokio::Provider>(|cfg| cfg.support_draft_29 = false);
assert!(matches!( assert!(matches!(
d_transport.listen_on("/ip4/127.0.0.1/udp/0/quic".parse().unwrap()), d_transport.listen_on(
ListenerId::next(),
"/ip4/127.0.0.1/udp/0/quic".parse().unwrap()
),
Err(TransportError::MultiaddrNotSupported(_)) Err(TransportError::MultiaddrNotSupported(_))
)); ));
let d_quic_v1_addr = start_listening(&mut d_transport, "/ip4/127.0.0.1/udp/0/quic-v1").await; let d_quic_v1_addr = start_listening(&mut d_transport, "/ip4/127.0.0.1/udp/0/quic-v1").await;
@ -509,7 +513,9 @@ fn create_transport<P: Provider>(
} }
async fn start_listening(transport: &mut Boxed<(PeerId, StreamMuxerBox)>, addr: &str) -> Multiaddr { async fn start_listening(transport: &mut Boxed<(PeerId, StreamMuxerBox)>, addr: &str) -> Multiaddr {
transport.listen_on(addr.parse().unwrap()).unwrap(); transport
.listen_on(ListenerId::next(), addr.parse().unwrap())
.unwrap();
match transport.next().await { match transport.next().await {
Some(TransportEvent::NewAddress { listen_addr, .. }) => listen_addr, Some(TransportEvent::NewAddress { listen_addr, .. }) => listen_addr,
e => panic!("{e:?}"), e => panic!("{e:?}"),

View File

@ -1,5 +1,6 @@
use futures::channel::oneshot; use futures::channel::oneshot;
use futures::StreamExt; use futures::StreamExt;
use libp2p_core::transport::ListenerId;
use libp2p_core::Transport; use libp2p_core::Transport;
use libp2p_quic as quic; use libp2p_quic as quic;
use std::time::Duration; use std::time::Duration;
@ -23,7 +24,10 @@ async fn connected_peers() -> (quic::Connection, quic::Connection) {
let mut listener = new_transport().boxed(); let mut listener = new_transport().boxed();
listener listener
.listen_on("/ip4/127.0.0.1/udp/0/quic-v1".parse().unwrap()) .listen_on(
ListenerId::next(),
"/ip4/127.0.0.1/udp/0/quic-v1".parse().unwrap(),
)
.unwrap(); .unwrap();
let listen_address = listener.next().await.unwrap().into_new_address().unwrap(); let listen_address = listener.next().await.unwrap().into_new_address().unwrap();

View File

@ -248,7 +248,7 @@ impl Config {
/// let listen_addr2: Multiaddr = "/ip4/127.0.0.1/tcp/9002".parse().unwrap(); /// let listen_addr2: Multiaddr = "/ip4/127.0.0.1/tcp/9002".parse().unwrap();
/// ///
/// let mut tcp1 = libp2p_tcp::async_io::Transport::new(libp2p_tcp::Config::new().port_reuse(true)).boxed(); /// let mut tcp1 = libp2p_tcp::async_io::Transport::new(libp2p_tcp::Config::new().port_reuse(true)).boxed();
/// tcp1.listen_on( listen_addr1.clone()).expect("listener"); /// tcp1.listen_on(ListenerId::next(), listen_addr1.clone()).expect("listener");
/// match tcp1.select_next_some().await { /// match tcp1.select_next_some().await {
/// TransportEvent::NewAddress { listen_addr, .. } => { /// TransportEvent::NewAddress { listen_addr, .. } => {
/// println!("Listening on {:?}", listen_addr); /// println!("Listening on {:?}", listen_addr);
@ -259,7 +259,7 @@ impl Config {
/// } /// }
/// ///
/// let mut tcp2 = libp2p_tcp::async_io::Transport::new(libp2p_tcp::Config::new().port_reuse(true)).boxed(); /// let mut tcp2 = libp2p_tcp::async_io::Transport::new(libp2p_tcp::Config::new().port_reuse(true)).boxed();
/// tcp2.listen_on( listen_addr2).expect("listener"); /// tcp2.listen_on(ListenerId::next(), listen_addr2).expect("listener");
/// match tcp2.select_next_some().await { /// match tcp2.select_next_some().await {
/// TransportEvent::NewAddress { listen_addr, .. } => { /// TransportEvent::NewAddress { listen_addr, .. } => {
/// println!("Listening on {:?}", listen_addr); /// println!("Listening on {:?}", listen_addr);
@ -437,19 +437,22 @@ where
type Dial = Pin<Box<dyn Future<Output = Result<Self::Output, Self::Error>> + Send>>; type Dial = Pin<Box<dyn Future<Output = Result<Self::Output, Self::Error>> + Send>>;
type ListenerUpgrade = Ready<Result<Self::Output, Self::Error>>; type ListenerUpgrade = Ready<Result<Self::Output, Self::Error>>;
fn listen_on(&mut self, addr: Multiaddr) -> Result<ListenerId, TransportError<Self::Error>> { fn listen_on(
&mut self,
id: ListenerId,
addr: Multiaddr,
) -> Result<(), TransportError<Self::Error>> {
let socket_addr = if let Ok(sa) = multiaddr_to_socketaddr(addr.clone()) { let socket_addr = if let Ok(sa) = multiaddr_to_socketaddr(addr.clone()) {
sa sa
} else { } else {
return Err(TransportError::MultiaddrNotSupported(addr)); return Err(TransportError::MultiaddrNotSupported(addr));
}; };
let id = ListenerId::new();
log::debug!("listening on {}", socket_addr); log::debug!("listening on {}", socket_addr);
let listener = self let listener = self
.do_listen(id, socket_addr) .do_listen(id, socket_addr)
.map_err(TransportError::Other)?; .map_err(TransportError::Other)?;
self.listeners.push(listener); self.listeners.push(listener);
Ok(id) Ok(())
} }
fn remove_listener(&mut self, id: ListenerId) -> bool { fn remove_listener(&mut self, id: ListenerId) -> bool {
@ -916,7 +919,7 @@ mod tests {
async fn listener<T: Provider>(addr: Multiaddr, mut ready_tx: mpsc::Sender<Multiaddr>) { async fn listener<T: Provider>(addr: Multiaddr, mut ready_tx: mpsc::Sender<Multiaddr>) {
let mut tcp = Transport::<T>::default().boxed(); let mut tcp = Transport::<T>::default().boxed();
tcp.listen_on(addr).unwrap(); tcp.listen_on(ListenerId::next(), addr).unwrap();
loop { loop {
match tcp.select_next_some().await { match tcp.select_next_some().await {
TransportEvent::NewAddress { listen_addr, .. } => { TransportEvent::NewAddress { listen_addr, .. } => {
@ -985,7 +988,7 @@ mod tests {
async fn listener<T: Provider>(addr: Multiaddr, mut ready_tx: mpsc::Sender<Multiaddr>) { async fn listener<T: Provider>(addr: Multiaddr, mut ready_tx: mpsc::Sender<Multiaddr>) {
let mut tcp = Transport::<T>::default().boxed(); let mut tcp = Transport::<T>::default().boxed();
tcp.listen_on(addr).unwrap(); tcp.listen_on(ListenerId::next(), addr).unwrap();
loop { loop {
match tcp.select_next_some().await { match tcp.select_next_some().await {
@ -1058,7 +1061,7 @@ mod tests {
port_reuse_rx: oneshot::Receiver<Protocol<'_>>, port_reuse_rx: oneshot::Receiver<Protocol<'_>>,
) { ) {
let mut tcp = Transport::<T>::new(Config::new()).boxed(); let mut tcp = Transport::<T>::new(Config::new()).boxed();
tcp.listen_on(addr).unwrap(); tcp.listen_on(ListenerId::next(), addr).unwrap();
loop { loop {
match tcp.select_next_some().await { match tcp.select_next_some().await {
TransportEvent::NewAddress { listen_addr, .. } => { TransportEvent::NewAddress { listen_addr, .. } => {
@ -1093,7 +1096,7 @@ mod tests {
) { ) {
let dest_addr = ready_rx.next().await.unwrap(); let dest_addr = ready_rx.next().await.unwrap();
let mut tcp = Transport::<T>::new(Config::new().port_reuse(true)); let mut tcp = Transport::<T>::new(Config::new().port_reuse(true));
tcp.listen_on(addr).unwrap(); tcp.listen_on(ListenerId::next(), addr).unwrap();
match poll_fn(|cx| Pin::new(&mut tcp).poll(cx)).await { match poll_fn(|cx| Pin::new(&mut tcp).poll(cx)).await {
TransportEvent::NewAddress { .. } => { TransportEvent::NewAddress { .. } => {
// Check that tcp and listener share the same port reuse SocketAddr // Check that tcp and listener share the same port reuse SocketAddr
@ -1161,7 +1164,7 @@ mod tests {
async fn listen_twice<T: Provider>(addr: Multiaddr) { async fn listen_twice<T: Provider>(addr: Multiaddr) {
let mut tcp = Transport::<T>::new(Config::new().port_reuse(true)); let mut tcp = Transport::<T>::new(Config::new().port_reuse(true));
tcp.listen_on(addr).unwrap(); tcp.listen_on(ListenerId::next(), addr).unwrap();
match poll_fn(|cx| Pin::new(&mut tcp).poll(cx)).await { match poll_fn(|cx| Pin::new(&mut tcp).poll(cx)).await {
TransportEvent::NewAddress { TransportEvent::NewAddress {
listen_addr: addr1, .. listen_addr: addr1, ..
@ -1176,7 +1179,7 @@ mod tests {
assert_eq!(port_reuse_tcp, port_reuse_listener1); assert_eq!(port_reuse_tcp, port_reuse_listener1);
// Listen on the same address a second time. // Listen on the same address a second time.
tcp.listen_on(addr1.clone()).unwrap(); tcp.listen_on(ListenerId::next(), addr1.clone()).unwrap();
match poll_fn(|cx| Pin::new(&mut tcp).poll(cx)).await { match poll_fn(|cx| Pin::new(&mut tcp).poll(cx)).await {
TransportEvent::NewAddress { TransportEvent::NewAddress {
listen_addr: addr2, .. listen_addr: addr2, ..
@ -1215,7 +1218,7 @@ mod tests {
async fn listen<T: Provider>(addr: Multiaddr) -> Multiaddr { async fn listen<T: Provider>(addr: Multiaddr) -> Multiaddr {
let mut tcp = Transport::<T>::default().boxed(); let mut tcp = Transport::<T>::default().boxed();
tcp.listen_on(addr).unwrap(); tcp.listen_on(ListenerId::next(), addr).unwrap();
tcp.select_next_some() tcp.select_next_some()
.await .await
.into_new_address() .into_new_address()
@ -1252,13 +1255,13 @@ mod tests {
#[cfg(feature = "async-io")] #[cfg(feature = "async-io")]
{ {
let mut tcp = async_io::Transport::default(); let mut tcp = async_io::Transport::default();
assert!(tcp.listen_on(addr.clone()).is_err()); assert!(tcp.listen_on(ListenerId::next(), addr.clone()).is_err());
} }
#[cfg(feature = "tokio")] #[cfg(feature = "tokio")]
{ {
let mut tcp = tokio::Transport::default(); let mut tcp = tokio::Transport::default();
assert!(tcp.listen_on(addr).is_err()); assert!(tcp.listen_on(ListenerId::next(), addr).is_err());
} }
} }
@ -1320,8 +1323,8 @@ mod tests {
async fn cycle_listeners<T: Provider>() -> bool { async fn cycle_listeners<T: Provider>() -> bool {
let mut tcp = Transport::<T>::default().boxed(); let mut tcp = Transport::<T>::default().boxed();
let listener_id = tcp let listener_id = ListenerId::next();
.listen_on("/ip4/127.0.0.1/tcp/0".parse().unwrap()) tcp.listen_on(listener_id, "/ip4/127.0.0.1/tcp/0".parse().unwrap())
.unwrap(); .unwrap();
tcp.remove_listener(listener_id) tcp.remove_listener(listener_id)
} }

View File

@ -32,14 +32,15 @@ use std::task::{Context, Poll};
/// ///
/// ```rust /// ```rust
/// # use libp2p_tcp as tcp; /// # use libp2p_tcp as tcp;
/// # use libp2p_core::Transport; /// # use libp2p_core::{Transport, transport::ListenerId};
/// # use futures::future; /// # use futures::future;
/// # use std::pin::Pin; /// # use std::pin::Pin;
/// # /// #
/// # #[async_std::main] /// # #[async_std::main]
/// # async fn main() { /// # async fn main() {
/// let mut transport = tcp::async_io::Transport::new(tcp::Config::default()); /// let mut transport = tcp::async_io::Transport::new(tcp::Config::default());
/// let id = transport.listen_on("/ip4/127.0.0.1/tcp/0".parse().unwrap()).unwrap(); /// let id = ListenerId::next();
/// transport.listen_on(id, "/ip4/127.0.0.1/tcp/0".parse().unwrap()).unwrap();
/// ///
/// let addr = future::poll_fn(|cx| Pin::new(&mut transport).poll(cx)).await.into_new_address().unwrap(); /// let addr = future::poll_fn(|cx| Pin::new(&mut transport).poll(cx)).await.into_new_address().unwrap();
/// ///

View File

@ -36,14 +36,14 @@ use std::task::{Context, Poll};
/// ///
/// ```rust /// ```rust
/// # use libp2p_tcp as tcp; /// # use libp2p_tcp as tcp;
/// # use libp2p_core::Transport; /// # use libp2p_core::{Transport, transport::ListenerId};
/// # use futures::future; /// # use futures::future;
/// # use std::pin::Pin; /// # use std::pin::Pin;
/// # /// #
/// # #[tokio::main] /// # #[tokio::main]
/// # async fn main() { /// # async fn main() {
/// let mut transport = tcp::tokio::Transport::new(tcp::Config::default()); /// let mut transport = tcp::tokio::Transport::new(tcp::Config::default());
/// let id = transport.listen_on("/ip4/127.0.0.1/tcp/0".parse().unwrap()).unwrap(); /// let id = transport.listen_on(ListenerId::next(), "/ip4/127.0.0.1/tcp/0".parse().unwrap()).unwrap();
/// ///
/// let addr = future::poll_fn(|cx| Pin::new(&mut transport).poll(cx)).await.into_new_address().unwrap(); /// let addr = future::poll_fn(|cx| Pin::new(&mut transport).poll(cx)).await.into_new_address().unwrap();
/// ///

View File

@ -93,10 +93,10 @@ macro_rules! codegen {
fn listen_on( fn listen_on(
&mut self, &mut self,
id: ListenerId,
addr: Multiaddr, addr: Multiaddr,
) -> Result<ListenerId, TransportError<Self::Error>> { ) -> Result<(), TransportError<Self::Error>> {
if let Ok(path) = multiaddr_to_path(&addr) { if let Ok(path) = multiaddr_to_path(&addr) {
let id = ListenerId::new();
let listener = $build_listener(path) let listener = $build_listener(path)
.map_err(Err) .map_err(Err)
.map_ok(move |listener| { .map_ok(move |listener| {
@ -138,7 +138,7 @@ macro_rules! codegen {
.try_flatten_stream() .try_flatten_stream()
.boxed(); .boxed();
self.listeners.push_back((id, listener)); self.listeners.push_back((id, listener));
Ok(id) Ok(())
} else { } else {
Err(TransportError::MultiaddrNotSupported(addr)) Err(TransportError::MultiaddrNotSupported(addr))
} }
@ -260,6 +260,7 @@ mod tests {
use futures::{channel::oneshot, prelude::*}; use futures::{channel::oneshot, prelude::*};
use libp2p_core::{ use libp2p_core::{
multiaddr::{Multiaddr, Protocol}, multiaddr::{Multiaddr, Protocol},
transport::ListenerId,
Transport, Transport,
}; };
use std::{self, borrow::Cow, path::Path}; use std::{self, borrow::Cow, path::Path};
@ -292,7 +293,7 @@ mod tests {
async_std::task::spawn(async move { async_std::task::spawn(async move {
let mut transport = UdsConfig::new().boxed(); let mut transport = UdsConfig::new().boxed();
transport.listen_on(addr).unwrap(); transport.listen_on(ListenerId::next(), addr).unwrap();
let listen_addr = transport let listen_addr = transport
.select_next_some() .select_next_some()
@ -328,7 +329,7 @@ mod tests {
let mut uds = UdsConfig::new(); let mut uds = UdsConfig::new();
let addr = "/unix//foo/bar".parse::<Multiaddr>().unwrap(); let addr = "/unix//foo/bar".parse::<Multiaddr>().unwrap();
assert!(uds.listen_on(addr).is_err()); assert!(uds.listen_on(ListenerId::next(), addr).is_err());
} }
#[test] #[test]

View File

@ -198,7 +198,11 @@ impl Transport for ExtTransport {
type ListenerUpgrade = Ready<Result<Self::Output, Self::Error>>; type ListenerUpgrade = Ready<Result<Self::Output, Self::Error>>;
type Dial = Dial; type Dial = Dial;
fn listen_on(&mut self, addr: Multiaddr) -> Result<ListenerId, TransportError<Self::Error>> { fn listen_on(
&mut self,
listener_id: ListenerId,
addr: Multiaddr,
) -> Result<(), TransportError<Self::Error>> {
let iter = self.inner.listen_on(&addr.to_string()).map_err(|err| { let iter = self.inner.listen_on(&addr.to_string()).map_err(|err| {
if is_not_supported_error(&err) { if is_not_supported_error(&err) {
TransportError::MultiaddrNotSupported(addr) TransportError::MultiaddrNotSupported(addr)
@ -206,7 +210,6 @@ impl Transport for ExtTransport {
TransportError::Other(JsErr::from(err)) TransportError::Other(JsErr::from(err))
} }
})?; })?;
let listener_id = ListenerId::new();
let listen = Listen { let listen = Listen {
listener_id, listener_id,
iterator: SendWrapper::new(iter), iterator: SendWrapper::new(iter),
@ -215,7 +218,7 @@ impl Transport for ExtTransport {
is_closed: false, is_closed: false,
}; };
self.listeners.push(listen); self.listeners.push(listen);
Ok(listener_id) Ok(())
} }
fn remove_listener(&mut self, id: ListenerId) -> bool { fn remove_listener(&mut self, id: ListenerId) -> bool {

View File

@ -80,9 +80,11 @@ impl libp2p_core::Transport for Transport {
type ListenerUpgrade = BoxFuture<'static, Result<Self::Output, Self::Error>>; type ListenerUpgrade = BoxFuture<'static, Result<Self::Output, Self::Error>>;
type Dial = BoxFuture<'static, Result<Self::Output, Self::Error>>; type Dial = BoxFuture<'static, Result<Self::Output, Self::Error>>;
fn listen_on(&mut self, addr: Multiaddr) -> Result<ListenerId, TransportError<Self::Error>> { fn listen_on(
let id = ListenerId::new(); &mut self,
id: ListenerId,
addr: Multiaddr,
) -> Result<(), TransportError<Self::Error>> {
let socket_addr = let socket_addr =
parse_webrtc_listen_addr(&addr).ok_or(TransportError::MultiaddrNotSupported(addr))?; parse_webrtc_listen_addr(&addr).ok_or(TransportError::MultiaddrNotSupported(addr))?;
let udp_mux = UDPMuxNewAddr::listen_on(socket_addr) let udp_mux = UDPMuxNewAddr::listen_on(socket_addr)
@ -93,7 +95,7 @@ impl libp2p_core::Transport for Transport {
.map_err(|e| TransportError::Other(Error::Io(e)))?, .map_err(|e| TransportError::Other(Error::Io(e)))?,
); );
Ok(id) Ok(())
} }
fn remove_listener(&mut self, id: ListenerId) -> bool { fn remove_listener(&mut self, id: ListenerId) -> bool {
@ -596,8 +598,12 @@ mod tests {
// Run test twice to check that there is no unexpected behaviour if `QuicTransport.listener` // Run test twice to check that there is no unexpected behaviour if `QuicTransport.listener`
// is temporarily empty. // is temporarily empty.
for _ in 0..2 { for _ in 0..2 {
let listener = transport let listener = ListenerId::next();
.listen_on("/ip4/0.0.0.0/udp/0/webrtc-direct".parse().unwrap()) transport
.listen_on(
listener,
"/ip4/0.0.0.0/udp/0/webrtc-direct".parse().unwrap(),
)
.unwrap(); .unwrap();
match poll_fn(|cx| Pin::new(&mut transport).as_mut().poll(cx)).await { match poll_fn(|cx| Pin::new(&mut transport).as_mut().poll(cx)).await {
TransportEvent::NewAddress { TransportEvent::NewAddress {

View File

@ -23,7 +23,7 @@ use futures::future::{BoxFuture, Either};
use futures::stream::StreamExt; use futures::stream::StreamExt;
use futures::{future, ready, AsyncReadExt, AsyncWriteExt, FutureExt, SinkExt}; use futures::{future, ready, AsyncReadExt, AsyncWriteExt, FutureExt, SinkExt};
use libp2p_core::muxing::{StreamMuxerBox, StreamMuxerExt}; use libp2p_core::muxing::{StreamMuxerBox, StreamMuxerExt};
use libp2p_core::transport::{Boxed, TransportEvent}; use libp2p_core::transport::{Boxed, ListenerId, TransportEvent};
use libp2p_core::{Multiaddr, Transport}; use libp2p_core::{Multiaddr, Transport};
use libp2p_identity::PeerId; use libp2p_identity::PeerId;
use libp2p_webrtc as webrtc; use libp2p_webrtc as webrtc;
@ -81,7 +81,9 @@ fn create_transport() -> (PeerId, Boxed<(PeerId, StreamMuxerBox)>) {
} }
async fn start_listening(transport: &mut Boxed<(PeerId, StreamMuxerBox)>, addr: &str) -> Multiaddr { async fn start_listening(transport: &mut Boxed<(PeerId, StreamMuxerBox)>, addr: &str) -> Multiaddr {
transport.listen_on(addr.parse().unwrap()).unwrap(); transport
.listen_on(ListenerId::next(), addr.parse().unwrap())
.unwrap();
match transport.next().await { match transport.next().await {
Some(TransportEvent::NewAddress { listen_addr, .. }) => listen_addr, Some(TransportEvent::NewAddress { listen_addr, .. }) => listen_addr,
e => panic!("{e:?}"), e => panic!("{e:?}"),

View File

@ -122,7 +122,11 @@ where
type ListenerUpgrade = BoxFuture<'static, Result<Self::Output, Self::Error>>; type ListenerUpgrade = BoxFuture<'static, Result<Self::Output, Self::Error>>;
type Dial = BoxFuture<'static, Result<Self::Output, Self::Error>>; type Dial = BoxFuture<'static, Result<Self::Output, Self::Error>>;
fn listen_on(&mut self, addr: Multiaddr) -> Result<ListenerId, TransportError<Self::Error>> { fn listen_on(
&mut self,
id: ListenerId,
addr: Multiaddr,
) -> Result<(), TransportError<Self::Error>> {
let mut inner_addr = addr.clone(); let mut inner_addr = addr.clone();
let proto = match inner_addr.pop() { let proto = match inner_addr.pop() {
Some(p @ Protocol::Wss(_)) => { Some(p @ Protocol::Wss(_)) => {
@ -139,10 +143,10 @@ where
return Err(TransportError::MultiaddrNotSupported(addr)); return Err(TransportError::MultiaddrNotSupported(addr));
} }
}; };
match self.transport.lock().listen_on(inner_addr) { match self.transport.lock().listen_on(id, inner_addr) {
Ok(id) => { Ok(()) => {
self.listener_protos.insert(id, proto); self.listener_protos.insert(id, proto);
Ok(id) Ok(())
} }
Err(e) => Err(e.map(Error::Transport)), Err(e) => Err(e.map(Error::Transport)),
} }

View File

@ -64,7 +64,7 @@ use std::{
/// ///
/// ``` /// ```
/// # use futures::future; /// # use futures::future;
/// # use libp2p_core::Transport; /// # use libp2p_core::{transport::ListenerId, Transport};
/// # use libp2p_dns as dns; /// # use libp2p_dns as dns;
/// # use libp2p_tcp as tcp; /// # use libp2p_tcp as tcp;
/// # use libp2p_websocket as websocket; /// # use libp2p_websocket as websocket;
@ -83,7 +83,7 @@ use std::{
/// let cert = websocket::tls::Certificate::new(rcgen_cert.serialize_der().unwrap()); /// let cert = websocket::tls::Certificate::new(rcgen_cert.serialize_der().unwrap());
/// transport.set_tls_config(websocket::tls::Config::new(priv_key, vec![cert]).unwrap()); /// transport.set_tls_config(websocket::tls::Config::new(priv_key, vec![cert]).unwrap());
/// ///
/// let id = transport.listen_on("/ip4/127.0.0.1/tcp/0/wss".parse().unwrap()).unwrap(); /// let id = transport.listen_on(ListenerId::next(), "/ip4/127.0.0.1/tcp/0/wss".parse().unwrap()).unwrap();
/// ///
/// let addr = future::poll_fn(|cx| Pin::new(&mut transport).poll(cx)).await.into_new_address().unwrap(); /// let addr = future::poll_fn(|cx| Pin::new(&mut transport).poll(cx)).await.into_new_address().unwrap();
/// println!("Listening on {addr}"); /// println!("Listening on {addr}");
@ -95,7 +95,7 @@ use std::{
/// ///
/// ``` /// ```
/// # use futures::future; /// # use futures::future;
/// # use libp2p_core::Transport; /// # use libp2p_core::{transport::ListenerId, Transport};
/// # use libp2p_dns as dns; /// # use libp2p_dns as dns;
/// # use libp2p_tcp as tcp; /// # use libp2p_tcp as tcp;
/// # use libp2p_websocket as websocket; /// # use libp2p_websocket as websocket;
@ -108,7 +108,7 @@ use std::{
/// tcp::async_io::Transport::new(tcp::Config::default()), /// tcp::async_io::Transport::new(tcp::Config::default()),
/// ); /// );
/// ///
/// let id = transport.listen_on("/ip4/127.0.0.1/tcp/0/ws".parse().unwrap()).unwrap(); /// let id = transport.listen_on(ListenerId::next(), "/ip4/127.0.0.1/tcp/0/ws".parse().unwrap()).unwrap();
/// ///
/// let addr = future::poll_fn(|cx| Pin::new(&mut transport).poll(cx)).await.into_new_address().unwrap(); /// let addr = future::poll_fn(|cx| Pin::new(&mut transport).poll(cx)).await.into_new_address().unwrap();
/// println!("Listening on {addr}"); /// println!("Listening on {addr}");
@ -195,8 +195,12 @@ where
type ListenerUpgrade = MapFuture<InnerFuture<T::Output, T::Error>, WrapperFn<T::Output>>; type ListenerUpgrade = MapFuture<InnerFuture<T::Output, T::Error>, WrapperFn<T::Output>>;
type Dial = MapFuture<InnerFuture<T::Output, T::Error>, WrapperFn<T::Output>>; type Dial = MapFuture<InnerFuture<T::Output, T::Error>, WrapperFn<T::Output>>;
fn listen_on(&mut self, addr: Multiaddr) -> Result<ListenerId, TransportError<Self::Error>> { fn listen_on(
self.transport.listen_on(addr) &mut self,
id: ListenerId,
addr: Multiaddr,
) -> Result<(), TransportError<Self::Error>> {
self.transport.listen_on(id, addr)
} }
fn remove_listener(&mut self, id: ListenerId) -> bool { fn remove_listener(&mut self, id: ListenerId) -> bool {
@ -293,7 +297,7 @@ where
mod tests { mod tests {
use super::WsConfig; use super::WsConfig;
use futures::prelude::*; use futures::prelude::*;
use libp2p_core::{multiaddr::Protocol, Multiaddr, Transport}; use libp2p_core::{multiaddr::Protocol, transport::ListenerId, Multiaddr, Transport};
use libp2p_identity::PeerId; use libp2p_identity::PeerId;
use libp2p_tcp as tcp; use libp2p_tcp as tcp;
@ -315,7 +319,9 @@ mod tests {
async fn connect(listen_addr: Multiaddr) { async fn connect(listen_addr: Multiaddr) {
let mut ws_config = new_ws_config().boxed(); let mut ws_config = new_ws_config().boxed();
ws_config.listen_on(listen_addr).expect("listener"); ws_config
.listen_on(ListenerId::next(), listen_addr)
.expect("listener");
let addr = ws_config let addr = ws_config
.next() .next()