mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-06-25 07:41:34 +00:00
feat(swarm): allow NetworkBehaviour
s to create and remove listeners
This extends `ToSwarm` to add `ToSwarm::ListenOn` and `ToSwarm::RemoveListener`, which allows creating and removing listeners from a `NetworkBehaviour`. Resolves https://github.com/libp2p/rust-libp2p/issues/3291. Pull-Request: #3292.
This commit is contained in:
@ -28,6 +28,7 @@ pub use listen_addresses::ListenAddresses;
|
||||
|
||||
use crate::connection::ConnectionId;
|
||||
use crate::dial_opts::DialOpts;
|
||||
use crate::listen_opts::ListenOpts;
|
||||
use crate::{
|
||||
ConnectionDenied, ConnectionHandler, DialError, ListenError, THandler, THandlerInEvent,
|
||||
THandlerOutEvent,
|
||||
@ -250,6 +251,12 @@ pub enum ToSwarm<TOutEvent, TInEvent> {
|
||||
/// This allows a [`NetworkBehaviour`] to identify a connection that resulted out of its own dial request.
|
||||
Dial { opts: DialOpts },
|
||||
|
||||
/// Instructs the [`Swarm`](crate::Swarm) to listen on the provided address.
|
||||
ListenOn { opts: ListenOpts },
|
||||
|
||||
/// Instructs the [`Swarm`](crate::Swarm) to remove the listener.
|
||||
RemoveListener { id: ListenerId },
|
||||
|
||||
/// Instructs the `Swarm` to send an event to the handler dedicated to a
|
||||
/// connection with a peer.
|
||||
///
|
||||
@ -324,6 +331,8 @@ impl<TOutEvent, TInEventOld> ToSwarm<TOutEvent, TInEventOld> {
|
||||
match self {
|
||||
ToSwarm::GenerateEvent(e) => ToSwarm::GenerateEvent(e),
|
||||
ToSwarm::Dial { opts } => ToSwarm::Dial { opts },
|
||||
ToSwarm::ListenOn { opts } => ToSwarm::ListenOn { opts },
|
||||
ToSwarm::RemoveListener { id } => ToSwarm::RemoveListener { id },
|
||||
ToSwarm::NotifyHandler {
|
||||
peer_id,
|
||||
handler,
|
||||
@ -353,6 +362,8 @@ impl<TOutEvent, THandlerIn> ToSwarm<TOutEvent, THandlerIn> {
|
||||
match self {
|
||||
ToSwarm::GenerateEvent(e) => ToSwarm::GenerateEvent(f(e)),
|
||||
ToSwarm::Dial { opts } => ToSwarm::Dial { opts },
|
||||
ToSwarm::ListenOn { opts } => ToSwarm::ListenOn { opts },
|
||||
ToSwarm::RemoveListener { id } => ToSwarm::RemoveListener { id },
|
||||
ToSwarm::NotifyHandler {
|
||||
peer_id,
|
||||
handler,
|
||||
|
@ -68,6 +68,7 @@ pub mod dial_opts;
|
||||
pub mod dummy;
|
||||
pub mod handler;
|
||||
pub mod keep_alive;
|
||||
mod listen_opts;
|
||||
|
||||
/// Bundles all symbols required for the [`libp2p_swarm_derive::NetworkBehaviour`] macro.
|
||||
#[doc(hidden)]
|
||||
@ -121,6 +122,7 @@ pub use handler::{
|
||||
};
|
||||
#[cfg(feature = "macros")]
|
||||
pub use libp2p_swarm_derive::NetworkBehaviour;
|
||||
pub use listen_opts::ListenOpts;
|
||||
pub use stream::Stream;
|
||||
pub use stream_protocol::{InvalidProtocol, StreamProtocol};
|
||||
|
||||
@ -370,12 +372,9 @@ where
|
||||
/// Listeners report their new listening addresses as [`SwarmEvent::NewListenAddr`].
|
||||
/// 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>> {
|
||||
let id = ListenerId::next();
|
||||
self.transport.listen_on(id, addr)?;
|
||||
self.behaviour
|
||||
.on_swarm_event(FromSwarm::NewListener(behaviour::NewListener {
|
||||
listener_id: id,
|
||||
}));
|
||||
let opts = ListenOpts::new(addr);
|
||||
let id = opts.listener_id();
|
||||
self.add_listener(opts)?;
|
||||
Ok(id)
|
||||
}
|
||||
|
||||
@ -542,6 +541,28 @@ where
|
||||
self.confirmed_external_addr.iter()
|
||||
}
|
||||
|
||||
fn add_listener(&mut self, opts: ListenOpts) -> Result<(), TransportError<io::Error>> {
|
||||
let addr = opts.address();
|
||||
let listener_id = opts.listener_id();
|
||||
|
||||
if let Err(e) = self.transport.listen_on(listener_id, addr.clone()) {
|
||||
self.behaviour
|
||||
.on_swarm_event(FromSwarm::ListenerError(behaviour::ListenerError {
|
||||
listener_id,
|
||||
err: &e,
|
||||
}));
|
||||
|
||||
return Err(e);
|
||||
}
|
||||
|
||||
self.behaviour
|
||||
.on_swarm_event(FromSwarm::NewListener(behaviour::NewListener {
|
||||
listener_id,
|
||||
}));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Add a **confirmed** external address for the local node.
|
||||
///
|
||||
/// This function should only be called with addresses that are guaranteed to be reachable.
|
||||
@ -1014,6 +1035,13 @@ where
|
||||
});
|
||||
}
|
||||
}
|
||||
ToSwarm::ListenOn { opts } => {
|
||||
// Error is dispatched internally, safe to ignore.
|
||||
let _ = self.add_listener(opts);
|
||||
}
|
||||
ToSwarm::RemoveListener { id } => {
|
||||
self.remove_listener(id);
|
||||
}
|
||||
ToSwarm::NotifyHandler {
|
||||
peer_id,
|
||||
handler,
|
||||
|
33
swarm/src/listen_opts.rs
Normal file
33
swarm/src/listen_opts.rs
Normal file
@ -0,0 +1,33 @@
|
||||
use crate::ListenerId;
|
||||
use libp2p_core::Multiaddr;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ListenOpts {
|
||||
id: ListenerId,
|
||||
address: Multiaddr,
|
||||
}
|
||||
|
||||
impl ListenOpts {
|
||||
pub fn new(address: Multiaddr) -> ListenOpts {
|
||||
ListenOpts {
|
||||
id: ListenerId::next(),
|
||||
address,
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the [`ListenerId`] of this listen attempt
|
||||
pub fn listener_id(&self) -> ListenerId {
|
||||
self.id
|
||||
}
|
||||
|
||||
/// Get the [`Multiaddr`] that is being listened on
|
||||
pub fn address(&self) -> &Multiaddr {
|
||||
&self.address
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Multiaddr> for ListenOpts {
|
||||
fn from(addr: Multiaddr) -> Self {
|
||||
ListenOpts::new(addr)
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user