mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-06-28 09:11:34 +00:00
* Allow multiple connections per peer in libp2p-core. Instead of trying to enforce a single connection per peer, which involves quite a bit of additional complexity e.g. to prioritise simultaneously opened connections and can have other undesirable consequences [1], we now make multiple connections per peer a feature. The gist of these changes is as follows: The concept of a "node" with an implicit 1-1 correspondence to a connection has been replaced with the "first-class" concept of a "connection". The code from `src/nodes` has moved (with varying degrees of modification) to `src/connection`. A `HandledNode` has become a `Connection`, a `NodeHandler` a `ConnectionHandler`, the `CollectionStream` was the basis for the new `connection::Pool`, and so forth. Conceptually, a `Network` contains a `connection::Pool` which in turn internally employs the `connection::Manager` for handling the background `connection::manager::Task`s, one per connection, as before. These are all considered implementation details. On the public API, `Peer`s are managed as before through the `Network`, except now the API has changed with the shift of focus to (potentially multiple) connections per peer. The `NetworkEvent`s have accordingly also undergone changes. The Swarm APIs remain largely unchanged, except for the fact that `inject_replaced` is no longer called. It may now practically happen that multiple `ProtocolsHandler`s are associated with a single `NetworkBehaviour`, one per connection. If implementations of `NetworkBehaviour` rely somehow on communicating with exactly one `ProtocolsHandler`, this may cause issues, but it is unlikely. [1]: https://github.com/paritytech/substrate/issues/4272 * Fix intra-rustdoc links. * Update core/src/connection/pool.rs Co-Authored-By: Max Inden <mail@max-inden.de> * Address some review feedback and fix doc links. * Allow responses to be sent on the same connection. * Remove unnecessary remainders of inject_replaced. * Update swarm/src/behaviour.rs Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Update swarm/src/lib.rs Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Update core/src/connection/manager.rs Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Update core/src/connection/manager.rs Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Update core/src/connection/pool.rs Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Incorporate more review feedback. * Move module declaration below imports. * Update core/src/connection/manager.rs Co-Authored-By: Toralf Wittner <tw@dtex.org> * Update core/src/connection/manager.rs Co-Authored-By: Toralf Wittner <tw@dtex.org> * Simplify as per review. * Fix rustoc link. * Add try_notify_handler and simplify. * Relocate DialingConnection and DialingAttempt. For better visibility constraints. * Small cleanup. * Small cleanup. More robust EstablishedConnectionIter. * Clarify semantics of `DialingPeer::connect`. * Don't call inject_disconnected on InvalidPeerId. To preserve the previous behavior and ensure calls to `inject_disconnected` are always paired with calls to `inject_connected`. * Provide public ConnectionId constructor. Mainly needed for testing purposes, e.g. in substrate. * Move the established connection limit check to the right place. * Clean up connection error handling. Separate connection errors into those occuring during connection setup or upon rejecting a newly established connection (the `PendingConnectionError`) and those errors occurring on previously established connections, i.e. for which a `ConnectionEstablished` event has been emitted by the connection pool earlier. * Revert change in log level and clarify an invariant. * Remove inject_replaced entirely. * Allow notifying all connection handlers. Thereby simplify by introducing a new enum `NotifyHandler`, used with a single constructor `NetworkBehaviourAction::NotifyHandler`. * Finishing touches. Small API simplifications and code deduplication. Some more useful debug logging. Co-authored-by: Max Inden <mail@max-inden.de> Co-authored-by: Pierre Krieger <pierre.krieger1708@gmail.com> Co-authored-by: Toralf Wittner <tw@dtex.org>
116 lines
4.1 KiB
Rust
116 lines
4.1 KiB
Rust
// 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.
|
|
|
|
use crate::connection::ConnectionLimit;
|
|
use crate::transport::TransportError;
|
|
use std::{io, fmt};
|
|
|
|
/// Errors that can occur in the context of an established `Connection`.
|
|
#[derive(Debug)]
|
|
pub enum ConnectionError<THandlerErr> {
|
|
/// An I/O error occurred on the connection.
|
|
// TODO: Eventually this should also be a custom error?
|
|
IO(io::Error),
|
|
|
|
/// The connection handler produced an error.
|
|
Handler(THandlerErr),
|
|
}
|
|
|
|
impl<THandlerErr> fmt::Display
|
|
for ConnectionError<THandlerErr>
|
|
where
|
|
THandlerErr: fmt::Display,
|
|
{
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
match self {
|
|
ConnectionError::IO(err) =>
|
|
write!(f, "Connection error: I/O error: {}", err),
|
|
ConnectionError::Handler(err) =>
|
|
write!(f, "Connection error: Handler error: {}", err),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<THandlerErr> std::error::Error
|
|
for ConnectionError<THandlerErr>
|
|
where
|
|
THandlerErr: std::error::Error + 'static,
|
|
{
|
|
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
|
match self {
|
|
ConnectionError::IO(err) => Some(err),
|
|
ConnectionError::Handler(err) => Some(err),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Errors that can occur in the context of a pending `Connection`.
|
|
#[derive(Debug)]
|
|
pub enum PendingConnectionError<TTransErr> {
|
|
/// An error occurred while negotiating the transport protocol(s).
|
|
Transport(TransportError<TTransErr>),
|
|
|
|
/// The peer identity obtained on the connection did not
|
|
/// match the one that was expected or is otherwise invalid.
|
|
InvalidPeerId,
|
|
|
|
/// The pending connection was successfully negotiated but dropped
|
|
/// because the connection limit for a peer has been reached.
|
|
ConnectionLimit(ConnectionLimit),
|
|
|
|
/// An I/O error occurred on the connection.
|
|
// TODO: Eventually this should also be a custom error?
|
|
IO(io::Error),
|
|
}
|
|
|
|
impl<TTransErr> fmt::Display
|
|
for PendingConnectionError<TTransErr>
|
|
where
|
|
TTransErr: fmt::Display,
|
|
{
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
match self {
|
|
PendingConnectionError::IO(err) =>
|
|
write!(f, "Pending connection: I/O error: {}", err),
|
|
PendingConnectionError::Transport(err) =>
|
|
write!(f, "Pending connection: Transport error: {}", err),
|
|
PendingConnectionError::InvalidPeerId =>
|
|
write!(f, "Pending connection: Invalid peer ID."),
|
|
PendingConnectionError::ConnectionLimit(l) =>
|
|
write!(f, "Pending connection: Connection limit: {}.", l)
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<TTransErr> std::error::Error
|
|
for PendingConnectionError<TTransErr>
|
|
where
|
|
TTransErr: std::error::Error + 'static
|
|
{
|
|
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
|
match self {
|
|
PendingConnectionError::IO(err) => Some(err),
|
|
PendingConnectionError::Transport(err) => Some(err),
|
|
PendingConnectionError::InvalidPeerId => None,
|
|
PendingConnectionError::ConnectionLimit(..) => None,
|
|
}
|
|
}
|
|
}
|