libp2p_swarm/
behaviour.rs

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
21mod either;
22mod external_addresses;
23mod listen_addresses;
24mod peer_addresses;
25pub mod toggle;
26
27use std::task::{Context, Poll};
28
29pub use external_addresses::ExternalAddresses;
30use libp2p_core::{
31    transport::{ListenerId, PortUse},
32    ConnectedPoint, Endpoint, Multiaddr,
33};
34use libp2p_identity::PeerId;
35pub use listen_addresses::ListenAddresses;
36pub use peer_addresses::PeerAddresses;
37
38use crate::{
39    connection::ConnectionId, dial_opts::DialOpts, listen_opts::ListenOpts, ConnectionDenied,
40    ConnectionError, ConnectionHandler, DialError, ListenError, THandler, THandlerInEvent,
41    THandlerOutEvent,
42};
43
44/// A [`NetworkBehaviour`] defines the behaviour of the local node on the network.
45///
46/// In contrast to [`Transport`](libp2p_core::Transport) which defines **how** to send bytes on the
47/// network, [`NetworkBehaviour`] defines **what** bytes to send and **to whom**.
48///
49/// Each protocol (e.g. `libp2p-ping`, `libp2p-identify` or `libp2p-kad`) implements
50/// [`NetworkBehaviour`]. Multiple implementations of [`NetworkBehaviour`] can be composed into a
51/// hierarchy of [`NetworkBehaviour`]s where parent implementations delegate to child
52/// implementations. Finally the root of the [`NetworkBehaviour`] hierarchy is passed to
53/// [`Swarm`](crate::Swarm) where it can then control the behaviour of the local node on a libp2p
54/// network.
55///
56/// # Hierarchy of [`NetworkBehaviour`]
57///
58/// To compose multiple [`NetworkBehaviour`] implementations into a single [`NetworkBehaviour`]
59/// implementation, potentially building a multi-level hierarchy of [`NetworkBehaviour`]s, one can
60/// use one of the [`NetworkBehaviour`] combinators, and/or use the [`NetworkBehaviour`] derive
61/// macro.
62///
63/// ## Combinators
64///
65/// [`NetworkBehaviour`] combinators wrap one or more [`NetworkBehaviour`] implementations and
66/// implement [`NetworkBehaviour`] themselves. Example is the
67/// [`Toggle`](crate::behaviour::toggle::Toggle) [`NetworkBehaviour`].
68///
69/// ``` rust
70/// # use libp2p_swarm::dummy;
71/// # use libp2p_swarm::behaviour::toggle::Toggle;
72/// let my_behaviour = dummy::Behaviour;
73/// let my_toggled_behaviour = Toggle::from(Some(my_behaviour));
74/// ```
75///
76/// ## Custom [`NetworkBehaviour`] with the Derive Macro
77///
78/// One can derive [`NetworkBehaviour`] for a custom `struct` via the `#[derive(NetworkBehaviour)]`
79/// proc macro re-exported by the `libp2p` crate. The macro generates a delegating `trait`
80/// implementation for the custom `struct`. Each [`NetworkBehaviour`] trait method is simply
81/// delegated to each `struct` member in the order the `struct` is defined. For example for
82/// [`NetworkBehaviour::poll`] it will first poll the first `struct` member until it returns
83/// [`Poll::Pending`] before moving on to later members.
84///
85/// Events ([`NetworkBehaviour::ToSwarm`]) returned by each `struct` member are wrapped in a new
86/// `enum` event, with an `enum` variant for each `struct` member. Users can define this event
87/// `enum` themselves and provide the name to the derive macro via `#[behaviour(to_swarm =
88/// "MyCustomOutEvent")]`. If the user does not specify an `to_swarm`, the derive macro generates
89/// the event definition itself, naming it `<STRUCT_NAME>Event`.
90///
91/// The aforementioned conversion of each of the event types generated by the struct members to the
92/// custom `to_swarm` is handled by [`From`] implementations which the user needs to define in
93/// addition to the event `enum` itself.
94///
95/// ``` rust
96/// # use libp2p_identify as identify;
97/// # use libp2p_ping as ping;
98/// # use libp2p_swarm_derive::NetworkBehaviour;
99/// #[derive(NetworkBehaviour)]
100/// #[behaviour(to_swarm = "Event")]
101/// # #[behaviour(prelude = "libp2p_swarm::derive_prelude")]
102/// struct MyBehaviour {
103///     identify: identify::Behaviour,
104///     ping: ping::Behaviour,
105/// }
106///
107/// enum Event {
108///     Identify(identify::Event),
109///     Ping(ping::Event),
110/// }
111///
112/// impl From<identify::Event> for Event {
113///     fn from(event: identify::Event) -> Self {
114///         Self::Identify(event)
115///     }
116/// }
117///
118/// impl From<ping::Event> for Event {
119///     fn from(event: ping::Event) -> Self {
120///         Self::Ping(event)
121///     }
122/// }
123/// ```
124pub trait NetworkBehaviour: 'static {
125    /// Handler for all the protocols the network behaviour supports.
126    type ConnectionHandler: ConnectionHandler;
127
128    /// Event generated by the `NetworkBehaviour` and that the swarm will report back.
129    type ToSwarm: Send + 'static;
130
131    /// Callback that is invoked for every new inbound connection.
132    ///
133    /// At this point in the connection lifecycle, only the remote's and our local address are
134    /// known. We have also already allocated a [`ConnectionId`].
135    ///
136    /// Any error returned from this function will immediately abort the dial attempt.
137    fn handle_pending_inbound_connection(
138        &mut self,
139        _connection_id: ConnectionId,
140        _local_addr: &Multiaddr,
141        _remote_addr: &Multiaddr,
142    ) -> Result<(), ConnectionDenied> {
143        Ok(())
144    }
145
146    /// Callback that is invoked for every established inbound connection.
147    ///
148    /// This is invoked once another peer has successfully dialed us.
149    ///
150    /// At this point, we have verified their [`PeerId`] and we know, which particular [`Multiaddr`]
151    /// succeeded in the dial. In order to actually use this connection, this function must
152    /// return a [`ConnectionHandler`]. Returning an error will immediately close the
153    /// connection.
154    ///
155    /// Note when any composed behaviour returns an error the connection will be closed and a
156    /// [`FromSwarm::ListenFailure`] event will be emitted.
157    fn handle_established_inbound_connection(
158        &mut self,
159        _connection_id: ConnectionId,
160        peer: PeerId,
161        local_addr: &Multiaddr,
162        remote_addr: &Multiaddr,
163    ) -> Result<THandler<Self>, ConnectionDenied>;
164
165    /// Callback that is invoked for every outbound connection attempt.
166    ///
167    /// We have access to:
168    ///
169    /// - The [`PeerId`], if known. Remember that we can dial without a [`PeerId`].
170    /// - All addresses passed to [`DialOpts`] are passed in here too.
171    /// - The effective [`Role`](Endpoint) of this peer in the dial attempt. Typically, this is set
172    ///   to [`Endpoint::Dialer`] except if we are attempting a hole-punch.
173    /// - The [`ConnectionId`] identifying the future connection resulting from this dial, if
174    ///   successful.
175    ///
176    /// Note that the addresses returned from this function are only used for dialing if
177    /// [`WithPeerIdWithAddresses::extend_addresses_through_behaviour`](crate::dial_opts::WithPeerIdWithAddresses::extend_addresses_through_behaviour)
178    /// is set.
179    ///
180    /// Any error returned from this function will immediately abort the dial attempt.
181    fn handle_pending_outbound_connection(
182        &mut self,
183        _connection_id: ConnectionId,
184        _maybe_peer: Option<PeerId>,
185        _addresses: &[Multiaddr],
186        _effective_role: Endpoint,
187    ) -> Result<Vec<Multiaddr>, ConnectionDenied> {
188        Ok(vec![])
189    }
190
191    /// Callback that is invoked for every established outbound connection.
192    ///
193    /// This is invoked once we have successfully dialed a peer.
194    /// At this point, we have verified their [`PeerId`] and we know, which particular [`Multiaddr`]
195    /// succeeded in the dial. In order to actually use this connection, this function must
196    /// return a [`ConnectionHandler`]. Returning an error will immediately close the
197    /// connection.
198    ///
199    /// Note when any composed behaviour returns an error the connection will be closed and a
200    /// [`FromSwarm::DialFailure`] event will be emitted.
201    fn handle_established_outbound_connection(
202        &mut self,
203        _connection_id: ConnectionId,
204        peer: PeerId,
205        addr: &Multiaddr,
206        role_override: Endpoint,
207        port_use: PortUse,
208    ) -> Result<THandler<Self>, ConnectionDenied>;
209
210    /// Informs the behaviour about an event from the [`Swarm`](crate::Swarm).
211    fn on_swarm_event(&mut self, event: FromSwarm);
212
213    /// Informs the behaviour about an event generated by the [`ConnectionHandler`]
214    /// dedicated to the peer identified by `peer_id`. for the behaviour.
215    ///
216    /// The [`PeerId`] is guaranteed to be in a connected state. In other words,
217    /// [`FromSwarm::ConnectionEstablished`] has previously been received with this [`PeerId`].
218    fn on_connection_handler_event(
219        &mut self,
220        _peer_id: PeerId,
221        _connection_id: ConnectionId,
222        _event: THandlerOutEvent<Self>,
223    );
224
225    /// Polls for things that swarm should do.
226    ///
227    /// This API mimics the API of the `Stream` trait. The method may register the current task in
228    /// order to wake it up at a later point in time.
229    fn poll(&mut self, cx: &mut Context<'_>)
230        -> Poll<ToSwarm<Self::ToSwarm, THandlerInEvent<Self>>>;
231}
232
233/// A command issued from a [`NetworkBehaviour`] for the [`Swarm`].
234///
235/// [`Swarm`]: super::Swarm
236#[derive(Debug)]
237#[non_exhaustive]
238pub enum ToSwarm<TOutEvent, TInEvent> {
239    /// Instructs the `Swarm` to return an event when it is being polled.
240    GenerateEvent(TOutEvent),
241
242    /// Instructs the swarm to start a dial.
243    ///
244    /// On success, [`NetworkBehaviour::on_swarm_event`] with `ConnectionEstablished` is invoked.
245    /// On failure, [`NetworkBehaviour::on_swarm_event`] with `DialFailure` is invoked.
246    ///
247    /// [`DialOpts`] provides access to the [`ConnectionId`] via [`DialOpts::connection_id`].
248    /// This [`ConnectionId`] will be used throughout the connection's lifecycle to associate
249    /// events with it. This allows a [`NetworkBehaviour`] to identify a connection that
250    /// resulted out of its own dial request.
251    Dial { opts: DialOpts },
252
253    /// Instructs the [`Swarm`](crate::Swarm) to listen on the provided address.
254    ListenOn { opts: ListenOpts },
255
256    /// Instructs the [`Swarm`](crate::Swarm) to remove the listener.
257    RemoveListener { id: ListenerId },
258
259    /// Instructs the `Swarm` to send an event to the handler dedicated to a
260    /// connection with a peer.
261    ///
262    /// If the `Swarm` is connected to the peer, the message is delivered to the
263    /// [`ConnectionHandler`] instance identified by the peer ID and connection ID.
264    ///
265    /// If the specified connection no longer exists, the event is silently dropped.
266    ///
267    /// Typically the connection ID given is the same as the one passed to
268    /// [`NetworkBehaviour::on_connection_handler_event`], i.e. whenever the behaviour wishes to
269    /// respond to a request on the same connection (and possibly the same
270    /// substream, as per the implementation of [`ConnectionHandler`]).
271    ///
272    /// Note that even if the peer is currently connected, connections can get closed
273    /// at any time and thus the event may not reach a handler.
274    NotifyHandler {
275        /// The peer for whom a [`ConnectionHandler`] should be notified.
276        peer_id: PeerId,
277        /// The options w.r.t. which connection handler to notify of the event.
278        handler: NotifyHandler,
279        /// The event to send.
280        event: TInEvent,
281    },
282
283    /// Reports a **new** candidate for an external address to the [`Swarm`](crate::Swarm).
284    ///
285    /// The emphasis on a **new** candidate is important.
286    /// Protocols MUST take care to only emit a candidate once per "source".
287    /// For example, the observed address of a TCP connection does not change throughout its
288    /// lifetime. Thus, only one candidate should be emitted per connection.
289    ///
290    /// This makes the report frequency of an address a meaningful data-point for consumers of this
291    /// event. This address will be shared with all [`NetworkBehaviour`]s via
292    /// [`FromSwarm::NewExternalAddrCandidate`].
293    ///
294    /// This address could come from a variety of sources:
295    /// - A protocol such as identify obtained it from a remote.
296    /// - The user provided it based on configuration.
297    /// - We made an educated guess based on one of our listen addresses.
298    NewExternalAddrCandidate(Multiaddr),
299
300    /// Indicates to the [`Swarm`](crate::Swarm) that the provided address is confirmed to be
301    /// externally reachable.
302    ///
303    /// This is intended to be issued in response to a [`FromSwarm::NewExternalAddrCandidate`] if
304    /// we are indeed externally reachable on this address. This address will be shared with
305    /// all [`NetworkBehaviour`]s via [`FromSwarm::ExternalAddrConfirmed`].
306    ExternalAddrConfirmed(Multiaddr),
307
308    /// Indicates to the [`Swarm`](crate::Swarm) that we are no longer externally reachable under
309    /// the provided address.
310    ///
311    /// This expires an address that was earlier confirmed via [`ToSwarm::ExternalAddrConfirmed`].
312    /// This address will be shared with all [`NetworkBehaviour`]s via
313    /// [`FromSwarm::ExternalAddrExpired`].
314    ExternalAddrExpired(Multiaddr),
315
316    /// Instructs the `Swarm` to initiate a graceful close of one or all connections with the given
317    /// peer.
318    ///
319    /// Closing a connection via [`ToSwarm::CloseConnection`] will poll
320    /// [`ConnectionHandler::poll_close`] to completion. In most cases, stopping to "use" a
321    /// connection is enough to have it closed. The keep-alive algorithm will close a
322    /// connection automatically once all [`ConnectionHandler`]s are idle.
323    ///
324    /// Use this command if you want to close a connection _despite_ it still being in use by one
325    /// or more handlers.
326    CloseConnection {
327        /// The peer to disconnect.
328        peer_id: PeerId,
329        /// Whether to close a specific or all connections to the given peer.
330        connection: CloseConnection,
331    },
332
333    /// Reports external address of a remote peer to the [`Swarm`](crate::Swarm) and through that
334    /// to other [`NetworkBehaviour`]s.
335    NewExternalAddrOfPeer { peer_id: PeerId, address: Multiaddr },
336}
337
338impl<TOutEvent, TInEventOld> ToSwarm<TOutEvent, TInEventOld> {
339    /// Map the handler event.
340    pub fn map_in<TInEventNew>(
341        self,
342        f: impl FnOnce(TInEventOld) -> TInEventNew,
343    ) -> ToSwarm<TOutEvent, TInEventNew> {
344        match self {
345            ToSwarm::GenerateEvent(e) => ToSwarm::GenerateEvent(e),
346            ToSwarm::Dial { opts } => ToSwarm::Dial { opts },
347            ToSwarm::ListenOn { opts } => ToSwarm::ListenOn { opts },
348            ToSwarm::RemoveListener { id } => ToSwarm::RemoveListener { id },
349            ToSwarm::NotifyHandler {
350                peer_id,
351                handler,
352                event,
353            } => ToSwarm::NotifyHandler {
354                peer_id,
355                handler,
356                event: f(event),
357            },
358            ToSwarm::CloseConnection {
359                peer_id,
360                connection,
361            } => ToSwarm::CloseConnection {
362                peer_id,
363                connection,
364            },
365            ToSwarm::NewExternalAddrCandidate(addr) => ToSwarm::NewExternalAddrCandidate(addr),
366            ToSwarm::ExternalAddrConfirmed(addr) => ToSwarm::ExternalAddrConfirmed(addr),
367            ToSwarm::ExternalAddrExpired(addr) => ToSwarm::ExternalAddrExpired(addr),
368            ToSwarm::NewExternalAddrOfPeer {
369                address: addr,
370                peer_id,
371            } => ToSwarm::NewExternalAddrOfPeer {
372                address: addr,
373                peer_id,
374            },
375        }
376    }
377}
378
379impl<TOutEvent, THandlerIn> ToSwarm<TOutEvent, THandlerIn> {
380    /// Map the event the swarm will return.
381    pub fn map_out<E>(self, f: impl FnOnce(TOutEvent) -> E) -> ToSwarm<E, THandlerIn> {
382        match self {
383            ToSwarm::GenerateEvent(e) => ToSwarm::GenerateEvent(f(e)),
384            ToSwarm::Dial { opts } => ToSwarm::Dial { opts },
385            ToSwarm::ListenOn { opts } => ToSwarm::ListenOn { opts },
386            ToSwarm::RemoveListener { id } => ToSwarm::RemoveListener { id },
387            ToSwarm::NotifyHandler {
388                peer_id,
389                handler,
390                event,
391            } => ToSwarm::NotifyHandler {
392                peer_id,
393                handler,
394                event,
395            },
396            ToSwarm::NewExternalAddrCandidate(addr) => ToSwarm::NewExternalAddrCandidate(addr),
397            ToSwarm::ExternalAddrConfirmed(addr) => ToSwarm::ExternalAddrConfirmed(addr),
398            ToSwarm::ExternalAddrExpired(addr) => ToSwarm::ExternalAddrExpired(addr),
399            ToSwarm::CloseConnection {
400                peer_id,
401                connection,
402            } => ToSwarm::CloseConnection {
403                peer_id,
404                connection,
405            },
406            ToSwarm::NewExternalAddrOfPeer {
407                address: addr,
408                peer_id,
409            } => ToSwarm::NewExternalAddrOfPeer {
410                address: addr,
411                peer_id,
412            },
413        }
414    }
415}
416
417/// The options w.r.t. which connection handler to notify of an event.
418#[derive(Debug, Clone)]
419pub enum NotifyHandler {
420    /// Notify a particular connection handler.
421    One(ConnectionId),
422    /// Notify an arbitrary connection handler.
423    Any,
424}
425
426/// The options which connections to close.
427#[derive(Debug, Clone, Default)]
428pub enum CloseConnection {
429    /// Disconnect a particular connection.
430    One(ConnectionId),
431    /// Disconnect all connections.
432    #[default]
433    All,
434}
435
436/// Enumeration with the list of the possible events
437/// to pass to [`on_swarm_event`](NetworkBehaviour::on_swarm_event).
438#[derive(Debug, Clone, Copy)]
439#[non_exhaustive]
440pub enum FromSwarm<'a> {
441    /// Informs the behaviour about a newly established connection to a peer.
442    ConnectionEstablished(ConnectionEstablished<'a>),
443    /// Informs the behaviour about a closed connection to a peer.
444    ///
445    /// This event is always paired with an earlier
446    /// [`FromSwarm::ConnectionEstablished`] with the same peer ID, connection ID
447    /// and endpoint.
448    ConnectionClosed(ConnectionClosed<'a>),
449    /// Informs the behaviour that the [`ConnectedPoint`] of an existing
450    /// connection has changed.
451    AddressChange(AddressChange<'a>),
452    /// Informs the behaviour that the dial to a known
453    /// or unknown node failed.
454    DialFailure(DialFailure<'a>),
455    /// Informs the behaviour that an error
456    /// happened on an incoming connection during its initial handshake.
457    ///
458    /// This can include, for example, an error during the handshake of the encryption layer, or
459    /// the connection unexpectedly closed.
460    ListenFailure(ListenFailure<'a>),
461    /// Informs the behaviour that a new listener was created.
462    NewListener(NewListener),
463    /// Informs the behaviour that we have started listening on a new multiaddr.
464    NewListenAddr(NewListenAddr<'a>),
465    /// Informs the behaviour that a multiaddr
466    /// we were listening on has expired,
467    /// which means that we are no longer listening on it.
468    ExpiredListenAddr(ExpiredListenAddr<'a>),
469    /// Informs the behaviour that a listener experienced an error.
470    ListenerError(ListenerError<'a>),
471    /// Informs the behaviour that a listener closed.
472    ListenerClosed(ListenerClosed<'a>),
473    /// Informs the behaviour that we have discovered a new candidate for an external address for
474    /// us.
475    NewExternalAddrCandidate(NewExternalAddrCandidate<'a>),
476    /// Informs the behaviour that an external address of the local node was confirmed.
477    ExternalAddrConfirmed(ExternalAddrConfirmed<'a>),
478    /// Informs the behaviour that an external address of the local node expired, i.e. is no-longer
479    /// confirmed.
480    ExternalAddrExpired(ExternalAddrExpired<'a>),
481    /// Informs the behaviour that we have discovered a new external address for a remote peer.
482    NewExternalAddrOfPeer(NewExternalAddrOfPeer<'a>),
483}
484
485/// [`FromSwarm`] variant that informs the behaviour about a newly established connection to a peer.
486#[derive(Debug, Clone, Copy)]
487pub struct ConnectionEstablished<'a> {
488    pub peer_id: PeerId,
489    pub connection_id: ConnectionId,
490    pub endpoint: &'a ConnectedPoint,
491    pub failed_addresses: &'a [Multiaddr],
492    pub other_established: usize,
493}
494
495/// [`FromSwarm`] variant that informs the behaviour about a closed connection to a peer.
496///
497/// This event is always paired with an earlier
498/// [`FromSwarm::ConnectionEstablished`] with the same peer ID, connection ID
499/// and endpoint.
500#[derive(Debug, Clone, Copy)]
501pub struct ConnectionClosed<'a> {
502    pub peer_id: PeerId,
503    pub connection_id: ConnectionId,
504    pub endpoint: &'a ConnectedPoint,
505    pub cause: Option<&'a ConnectionError>,
506    pub remaining_established: usize,
507}
508
509/// [`FromSwarm`] variant that informs the behaviour that the [`ConnectedPoint`] of an existing
510/// connection has changed.
511#[derive(Debug, Clone, Copy)]
512pub struct AddressChange<'a> {
513    pub peer_id: PeerId,
514    pub connection_id: ConnectionId,
515    pub old: &'a ConnectedPoint,
516    pub new: &'a ConnectedPoint,
517}
518
519/// [`FromSwarm`] variant that informs the behaviour that the dial to a known
520/// or unknown node failed.
521#[derive(Debug, Clone, Copy)]
522pub struct DialFailure<'a> {
523    pub peer_id: Option<PeerId>,
524    pub error: &'a DialError,
525    pub connection_id: ConnectionId,
526}
527
528/// [`FromSwarm`] variant that informs the behaviour that an error
529/// happened on an incoming connection during its initial handshake.
530///
531/// This can include, for example, an error during the handshake of the encryption layer, or the
532/// connection unexpectedly closed.
533#[derive(Debug, Clone, Copy)]
534pub struct ListenFailure<'a> {
535    pub local_addr: &'a Multiaddr,
536    pub send_back_addr: &'a Multiaddr,
537    pub error: &'a ListenError,
538    pub connection_id: ConnectionId,
539    pub peer_id: Option<PeerId>,
540}
541
542/// [`FromSwarm`] variant that informs the behaviour that a new listener was created.
543#[derive(Debug, Clone, Copy)]
544pub struct NewListener {
545    pub listener_id: ListenerId,
546}
547
548/// [`FromSwarm`] variant that informs the behaviour
549/// that we have started listening on a new multiaddr.
550#[derive(Debug, Clone, Copy)]
551pub struct NewListenAddr<'a> {
552    pub listener_id: ListenerId,
553    pub addr: &'a Multiaddr,
554}
555
556/// [`FromSwarm`] variant that informs the behaviour that a multiaddr
557/// we were listening on has expired,
558/// which means that we are no longer listening on it.
559#[derive(Debug, Clone, Copy)]
560pub struct ExpiredListenAddr<'a> {
561    pub listener_id: ListenerId,
562    pub addr: &'a Multiaddr,
563}
564
565/// [`FromSwarm`] variant that informs the behaviour that a listener experienced an error.
566#[derive(Debug, Clone, Copy)]
567pub struct ListenerError<'a> {
568    pub listener_id: ListenerId,
569    pub err: &'a (dyn std::error::Error + 'static),
570}
571
572/// [`FromSwarm`] variant that informs the behaviour that a listener closed.
573#[derive(Debug, Clone, Copy)]
574pub struct ListenerClosed<'a> {
575    pub listener_id: ListenerId,
576    pub reason: Result<(), &'a std::io::Error>,
577}
578
579/// [`FromSwarm`] variant that informs the behaviour about a new candidate for an external address
580/// for us.
581#[derive(Debug, Clone, Copy)]
582pub struct NewExternalAddrCandidate<'a> {
583    pub addr: &'a Multiaddr,
584}
585
586/// [`FromSwarm`] variant that informs the behaviour that an external address was confirmed.
587#[derive(Debug, Clone, Copy)]
588pub struct ExternalAddrConfirmed<'a> {
589    pub addr: &'a Multiaddr,
590}
591
592/// [`FromSwarm`] variant that informs the behaviour that an external address was removed.
593#[derive(Debug, Clone, Copy)]
594pub struct ExternalAddrExpired<'a> {
595    pub addr: &'a Multiaddr,
596}
597
598/// [`FromSwarm`] variant that informs the behaviour that a new external address for a remote peer
599/// was detected.
600#[derive(Clone, Copy, Debug)]
601pub struct NewExternalAddrOfPeer<'a> {
602    pub peer_id: PeerId,
603    pub addr: &'a Multiaddr,
604}