mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-06-15 02:51:25 +00:00
Multiple connections per peer (#1440)
* 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>
This commit is contained in:
102
core/src/lib.rs
102
core/src/lib.rs
@ -43,15 +43,14 @@ mod keys_proto {
|
||||
pub use multiaddr;
|
||||
pub type Negotiated<T> = futures::compat::Compat01As03<multistream_select::Negotiated<futures::compat::Compat<T>>>;
|
||||
|
||||
use std::{future::Future, pin::Pin};
|
||||
|
||||
mod peer_id;
|
||||
mod translation;
|
||||
|
||||
pub mod connection;
|
||||
pub mod either;
|
||||
pub mod identity;
|
||||
pub mod muxing;
|
||||
pub mod nodes;
|
||||
pub mod network;
|
||||
pub mod transport;
|
||||
pub mod upgrade;
|
||||
|
||||
@ -62,101 +61,10 @@ pub use identity::PublicKey;
|
||||
pub use transport::Transport;
|
||||
pub use translation::address_translation;
|
||||
pub use upgrade::{InboundUpgrade, OutboundUpgrade, UpgradeInfo, UpgradeError, ProtocolName};
|
||||
pub use nodes::ConnectionInfo;
|
||||
pub use connection::{Connected, Endpoint, ConnectedPoint, ConnectionInfo};
|
||||
pub use network::Network;
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum Endpoint {
|
||||
/// The socket comes from a dialer.
|
||||
Dialer,
|
||||
/// The socket comes from a listener.
|
||||
Listener,
|
||||
}
|
||||
|
||||
impl std::ops::Not for Endpoint {
|
||||
type Output = Endpoint;
|
||||
|
||||
fn not(self) -> Self::Output {
|
||||
match self {
|
||||
Endpoint::Dialer => Endpoint::Listener,
|
||||
Endpoint::Listener => Endpoint::Dialer
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Endpoint {
|
||||
/// Is this endpoint a dialer?
|
||||
pub fn is_dialer(self) -> bool {
|
||||
if let Endpoint::Dialer = self {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// Is this endpoint a listener?
|
||||
pub fn is_listener(self) -> bool {
|
||||
if let Endpoint::Listener = self {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// How we connected to a node.
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum ConnectedPoint {
|
||||
/// We dialed the node.
|
||||
Dialer {
|
||||
/// Multiaddress that was successfully dialed.
|
||||
address: Multiaddr,
|
||||
},
|
||||
/// We received the node.
|
||||
Listener {
|
||||
/// Local connection address.
|
||||
local_addr: Multiaddr,
|
||||
/// Stack of protocols used to send back data to the remote.
|
||||
send_back_addr: Multiaddr,
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&'_ ConnectedPoint> for Endpoint {
|
||||
fn from(endpoint: &'_ ConnectedPoint) -> Endpoint {
|
||||
endpoint.to_endpoint()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ConnectedPoint> for Endpoint {
|
||||
fn from(endpoint: ConnectedPoint) -> Endpoint {
|
||||
endpoint.to_endpoint()
|
||||
}
|
||||
}
|
||||
|
||||
impl ConnectedPoint {
|
||||
/// Turns the `ConnectedPoint` into the corresponding `Endpoint`.
|
||||
pub fn to_endpoint(&self) -> Endpoint {
|
||||
match self {
|
||||
ConnectedPoint::Dialer { .. } => Endpoint::Dialer,
|
||||
ConnectedPoint::Listener { .. } => Endpoint::Listener
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if we are `Dialer`.
|
||||
pub fn is_dialer(&self) -> bool {
|
||||
match self {
|
||||
ConnectedPoint::Dialer { .. } => true,
|
||||
ConnectedPoint::Listener { .. } => false
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if we are `Listener`.
|
||||
pub fn is_listener(&self) -> bool {
|
||||
match self {
|
||||
ConnectedPoint::Dialer { .. } => false,
|
||||
ConnectedPoint::Listener { .. } => true
|
||||
}
|
||||
}
|
||||
}
|
||||
use std::{future::Future, pin::Pin};
|
||||
|
||||
/// Implemented on objects that can run a `Future` in the background.
|
||||
///
|
||||
|
Reference in New Issue
Block a user