// Copyright 2018 Parity Technologies (UK) Ltd. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. //! Network events and associated information. use crate::{ Multiaddr, connection::{ ConnectionId, ConnectedPoint, ConnectionError, ConnectionHandler, Connected, EstablishedConnection, IntoConnectionHandler, ListenerId, PendingConnectionError, }, transport::Transport, }; use std::{fmt, num::NonZeroU32}; /// Event that can happen on the `Network`. pub enum NetworkEvent<'a, TTrans, TInEvent, TOutEvent, THandler, TConnInfo, TPeerId> where TTrans: Transport, THandler: IntoConnectionHandler, { /// One of the listeners gracefully closed. ListenerClosed { /// The listener ID that closed. listener_id: ListenerId, /// The addresses that the listener was listening on. addresses: Vec, /// Reason for the closure. Contains `Ok(())` if the stream produced `None`, or `Err` /// if the stream produced an error. reason: Result<(), TTrans::Error>, }, /// One of the listeners reported a non-fatal error. ListenerError { /// The listener that errored. listener_id: ListenerId, /// The listener error. error: TTrans::Error }, /// One of the listeners is now listening on an additional address. NewListenerAddress { /// The listener that is listening on the new address. listener_id: ListenerId, /// The new address the listener is now also listening on. listen_addr: Multiaddr }, /// One of the listeners is no longer listening on some address. ExpiredListenerAddress { /// The listener that is no longer listening on some address. listener_id: ListenerId, /// The expired address. listen_addr: Multiaddr }, /// A new connection arrived on a listener. /// /// To accept the connection, see [`Network::accept`](crate::Network::accept). IncomingConnection { /// The listener who received the connection. listener_id: ListenerId, /// The pending incoming connection. connection: IncomingConnection, }, /// An error happened on a connection during its initial handshake. /// /// This can include, for example, an error during the handshake of the encryption layer, or /// the connection unexpectedly closed. IncomingConnectionError { /// Local connection address. local_addr: Multiaddr, /// Address used to send back data to the remote. send_back_addr: Multiaddr, /// The error that happened. error: PendingConnectionError, }, /// A new connection to a peer has been established. ConnectionEstablished { /// The newly established connection. connection: EstablishedConnection<'a, TInEvent, TConnInfo>, /// The total number of established connections to the same peer, /// including the one that has just been opened. num_established: NonZeroU32, }, /// An established connection to a peer has been closed. /// /// A connection may close if /// /// * it encounters an error, which includes the connection being /// closed by the remote. In this case `error` is `Some`. /// * it was actively closed by [`EstablishedConnection::start_close`], /// i.e. a successful, orderly close. In this case `error` is `None`. /// * it was actively closed by [`super::peer::ConnectedPeer::disconnect`] or /// [`super::peer::DialingPeer::disconnect`], i.e. dropped without an /// orderly close. In this case `error` is `None`. /// ConnectionClosed { /// The ID of the connection that encountered an error. id: ConnectionId, /// Information about the connection that encountered the error. connected: Connected, /// The error that occurred. error: Option::Error>>, /// The remaining number of established connections to the same peer. num_established: u32, }, /// A dialing attempt to an address of a peer failed. DialError { /// The number of remaining dialing attempts. attempts_remaining: u32, /// Id of the peer we were trying to dial. peer_id: TPeerId, /// The multiaddr we failed to reach. multiaddr: Multiaddr, /// The error that happened. error: PendingConnectionError, }, /// Failed to reach a peer that we were trying to dial. UnknownPeerDialError { /// The multiaddr we failed to reach. multiaddr: Multiaddr, /// The error that happened. error: PendingConnectionError, }, /// An established connection produced an event. ConnectionEvent { /// The connection on which the event occurred. connection: EstablishedConnection<'a, TInEvent, TConnInfo>, /// Event that was produced by the node. event: TOutEvent, }, /// An established connection has changed its address. AddressChange { /// The connection whose address has changed. connection: EstablishedConnection<'a, TInEvent, TConnInfo>, /// New endpoint of this connection. new_endpoint: ConnectedPoint, /// Old endpoint of this connection. old_endpoint: ConnectedPoint, }, } impl fmt::Debug for NetworkEvent<'_, TTrans, TInEvent, TOutEvent, THandler, TConnInfo, TPeerId> where TInEvent: fmt::Debug, TOutEvent: fmt::Debug, TTrans: Transport, TTrans::Error: fmt::Debug, THandler: IntoConnectionHandler, ::Error: fmt::Debug, TConnInfo: fmt::Debug, TPeerId: fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { match self { NetworkEvent::NewListenerAddress { listener_id, listen_addr } => { f.debug_struct("NewListenerAddress") .field("listener_id", listener_id) .field("listen_addr", listen_addr) .finish() } NetworkEvent::ExpiredListenerAddress { listener_id, listen_addr } => { f.debug_struct("ExpiredListenerAddress") .field("listener_id", listener_id) .field("listen_addr", listen_addr) .finish() } NetworkEvent::ListenerClosed { listener_id, addresses, reason } => { f.debug_struct("ListenerClosed") .field("listener_id", listener_id) .field("addresses", addresses) .field("reason", reason) .finish() } NetworkEvent::ListenerError { listener_id, error } => { f.debug_struct("ListenerError") .field("listener_id", listener_id) .field("error", error) .finish() } NetworkEvent::IncomingConnection { connection, .. } => { f.debug_struct("IncomingConnection") .field("local_addr", &connection.local_addr) .field("send_back_addr", &connection.send_back_addr) .finish() } NetworkEvent::IncomingConnectionError { local_addr, send_back_addr, error } => { f.debug_struct("IncomingConnectionError") .field("local_addr", local_addr) .field("send_back_addr", send_back_addr) .field("error", error) .finish() } NetworkEvent::ConnectionEstablished { connection, .. } => { f.debug_struct("ConnectionEstablished") .field("connection", connection) .finish() } NetworkEvent::ConnectionClosed { id, connected, error, .. } => { f.debug_struct("ConnectionClosed") .field("id", id) .field("connected", connected) .field("error", error) .finish() } NetworkEvent::DialError { attempts_remaining, peer_id, multiaddr, error } => { f.debug_struct("DialError") .field("attempts_remaining", attempts_remaining) .field("peer_id", peer_id) .field("multiaddr", multiaddr) .field("error", error) .finish() } NetworkEvent::UnknownPeerDialError { multiaddr, error, .. } => { f.debug_struct("UnknownPeerDialError") .field("multiaddr", multiaddr) .field("error", error) .finish() } NetworkEvent::ConnectionEvent { connection, event } => { f.debug_struct("ConnectionEvent") .field("connection", connection) .field("event", event) .finish() } NetworkEvent::AddressChange { connection, new_endpoint, old_endpoint } => { f.debug_struct("AddressChange") .field("connection", connection) .field("new_endpoint", new_endpoint) .field("old_endpoint", old_endpoint) .finish() } } } } /// A pending incoming connection produced by a listener. pub struct IncomingConnection { /// The connection upgrade. pub(crate) upgrade: TUpgrade, /// Local connection address. pub local_addr: Multiaddr, /// Address used to send back data to the remote. pub send_back_addr: Multiaddr, }