mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-06-13 01:51:23 +00:00
Rework the transport upgrade API. (#1240)
* Rework the transport upgrade API. ALthough transport upgrades must follow a specific pattern in order fot the resulting transport to be usable with a `Network` or `Swarm`, that pattern is currently not well reflected in the transport upgrade API. Rather, transport upgrades are rather laborious and involve non-trivial code duplication. This commit introduces a `transport::upgrade::Builder` that is obtained from `Transport::upgrade`. The `Builder` encodes the previously implicit rules for transport upgrades: 1. Authentication upgrades must happen first. 2. Any number of upgrades may follow. 3. A multiplexer upgrade must happen last. Since multiplexing is the last (regular) transport upgrade (because that upgrade yields a `StreamMuxer` which is no longer a `AsyncRead` / `AsyncWrite` resource, which the upgrade process is based on), the upgrade starts with `Transport::upgrade` and ends with `Builder::multiplex`, which drops back down to the `Transport`, providing a fluent API. Authentication and multiplexer upgrades must furthermore adhere to a minimal contract w.r.t their outputs: 1. An authentication upgrade is given an (async) I/O resource `C` and must produce a pair `(I, D)` where `I: ConnectionInfo` and `D` is a new (async) I/O resource `D`. 2. A multiplexer upgrade is given an (async) I/O resource `C` and must produce a `M: StreamMuxer`. To that end, two changes to the `secio` and `noise` protocols have been made: 1. The `secio` upgrade now outputs a pair of `(PeerId, SecioOutput)`. The former implements `ConnectionInfo` and the latter `AsyncRead` / `AsyncWrite`, fulfilling the `Builder` contract. 2. A new `NoiseAuthenticated` upgrade has been added that wraps around any noise upgrade (i.e. `NoiseConfig`) and has an output of `(PeerId, NoiseOutput)`, i.e. it checks if the `RemoteIdentity` from the handshake output is an `IdentityKey`, failing if that is not the case. This is the standard upgrade procedure one wants for integrating noise with libp2p-core/swarm. * Cleanup * Add a new integration test. * Add missing license.
This commit is contained in:
28
src/lib.rs
28
src/lib.rs
@ -82,15 +82,15 @@
|
||||
//! *upgraded*. Upgrading a transport is the process of negotiating an additional protocol
|
||||
//! with the remote, mediated through a negotiation protocol called [`multistream-select`].
|
||||
//!
|
||||
//! Example ([`secio`] Protocol Upgrade):
|
||||
//! Example ([`secio`] + [`yamux`] Protocol Upgrade):
|
||||
//!
|
||||
//! ```rust
|
||||
//! # #[cfg(all(not(any(target_os = "emscripten", target_os = "unknown")), feature = "libp2p-secio"))] {
|
||||
//! use libp2p::{Transport, tcp::TcpConfig, secio::SecioConfig, identity::Keypair};
|
||||
//! use libp2p::{Transport, tcp::TcpConfig, secio::SecioConfig, identity::Keypair, yamux};
|
||||
//! let tcp = TcpConfig::new();
|
||||
//! let secio_upgrade = SecioConfig::new(Keypair::generate_ed25519());
|
||||
//! let tcp_secio = tcp.with_upgrade(secio_upgrade);
|
||||
//! // let _ = tcp_secio.dial(...);
|
||||
//! let secio = SecioConfig::new(Keypair::generate_ed25519());
|
||||
//! let yamux = yamux::Config::default();
|
||||
//! let transport = tcp.upgrade().authenticate(secio).multiplex(yamux);
|
||||
//! # }
|
||||
//! ```
|
||||
//! In this example, `tcp_secio` is a new [`Transport`] that negotiates the secio protocol
|
||||
@ -222,7 +222,6 @@ pub use self::simple::SimpleProtocol;
|
||||
pub use self::swarm::Swarm;
|
||||
pub use self::transport_ext::TransportExt;
|
||||
|
||||
use futures::prelude::*;
|
||||
use std::{error, io, time::Duration};
|
||||
|
||||
/// Builds a `Transport` that supports the most commonly-used protocols that libp2p supports.
|
||||
@ -245,18 +244,11 @@ pub fn build_tcp_ws_secio_mplex_yamux(keypair: identity::Keypair)
|
||||
-> impl Transport<Output = (PeerId, impl core::muxing::StreamMuxer<OutboundSubstream = impl Send, Substream = impl Send, Error = impl Into<io::Error>> + Send + Sync), Error = impl error::Error + Send, Listener = impl Send, Dial = impl Send, ListenerUpgrade = impl Send> + Clone
|
||||
{
|
||||
CommonTransport::new()
|
||||
.with_upgrade(secio::SecioConfig::new(keypair))
|
||||
.and_then(move |output, endpoint| {
|
||||
let peer_id = output.remote_key.into_peer_id();
|
||||
let peer_id2 = peer_id.clone();
|
||||
let upgrade = core::upgrade::SelectUpgrade::new(yamux::Config::default(), mplex::MplexConfig::new())
|
||||
// TODO: use a single `.map` instead of two maps
|
||||
.map_inbound(move |muxer| (peer_id, muxer))
|
||||
.map_outbound(move |muxer| (peer_id2, muxer));
|
||||
core::upgrade::apply(output.stream, upgrade, endpoint)
|
||||
.map(|(id, muxer)| (id, core::muxing::StreamMuxerBox::new(muxer)))
|
||||
})
|
||||
.with_timeout(Duration::from_secs(20))
|
||||
.upgrade()
|
||||
.authenticate(secio::SecioConfig::new(keypair))
|
||||
.multiplex(core::upgrade::SelectUpgrade::new(yamux::Config::default(), mplex::MplexConfig::new()))
|
||||
.map(|(peer, muxer), _| (peer, core::muxing::StreamMuxerBox::new(muxer)))
|
||||
.timeout(Duration::from_secs(20))
|
||||
}
|
||||
|
||||
/// Implementation of `Transport` that supports the most common protocols.
|
||||
|
Reference in New Issue
Block a user