Skip to content

Commit 38fe01f

Browse files
author
Roman S. Borschel
committed
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`.
1 parent c0b379b commit 38fe01f

File tree

20 files changed

+625
-349
lines changed

20 files changed

+625
-349
lines changed

core/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ pub use identity::PublicKey;
6060
pub use transport::Transport;
6161
pub use translation::address_translation;
6262
pub use upgrade::{InboundUpgrade, OutboundUpgrade, UpgradeInfo, UpgradeError, ProtocolName};
63+
pub use nodes::ConnectionInfo;
6364

6465
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
6566
pub enum Endpoint {

core/src/nodes/network.rs

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -782,9 +782,8 @@ where
782782
TTrans: Transport<Output = (TConnInfo, TMuxer)>,
783783
TTrans::Error: Send + 'static,
784784
TTrans::Dial: Send + 'static,
785-
TMuxer: StreamMuxer + Send + Sync + 'static,
785+
TMuxer: Send + Sync + 'static,
786786
TMuxer::OutboundSubstream: Send,
787-
TMuxer::Substream: Send,
788787
TInEvent: Send + 'static,
789788
TOutEvent: Send + 'static,
790789
TConnInfo: Send + 'static,
@@ -937,12 +936,10 @@ where
937936
TTrans: Transport<Output = (TConnInfo, TMuxer)>,
938937
TTrans::Dial: Send + 'static,
939938
TTrans::Error: Send + 'static,
940-
TMuxer: StreamMuxer + Send + Sync + 'static,
939+
TMuxer: Send + Sync + 'static,
941940
TMuxer::OutboundSubstream: Send,
942-
TMuxer::Substream: Send,
943941
TInEvent: Send + 'static,
944942
TOutEvent: Send + 'static,
945-
TConnInfo: Send + 'static,
946943
TPeerId: Send + 'static,
947944
{
948945
let reach_id = match self.transport().clone().dial(first.clone()) {
@@ -985,14 +982,12 @@ where
985982
TTrans::Error: Send + 'static,
986983
TTrans::Dial: Send + 'static,
987984
TTrans::ListenerUpgrade: Send + 'static,
988-
TMuxer: StreamMuxer + Send + Sync + 'static,
985+
TMuxer: Send + Sync + 'static,
989986
TMuxer::OutboundSubstream: Send,
990-
TMuxer::Substream: Send,
991987
TInEvent: Send + 'static,
992988
TOutEvent: Send + 'static,
993989
THandler: IntoNodeHandler<(TConnInfo, ConnectedPoint)> + Send + 'static,
994990
THandler::Handler: NodeHandler<Substream = Substream<TMuxer>, InEvent = TInEvent, OutEvent = TOutEvent, Error = THandlerErr> + Send + 'static,
995-
<THandler::Handler as NodeHandler>::OutboundOpenInfo: Send + 'static, // TODO: shouldn't be necessary
996991
THandlerErr: error::Error + Send + 'static,
997992
TConnInfo: Clone,
998993
TPeerId: AsRef<[u8]> + Send + 'static,
@@ -1151,7 +1146,6 @@ where
11511146
TTrans: Transport<Output = (TConnInfo, TMuxer)> + Clone,
11521147
TMuxer: StreamMuxer + Send + Sync + 'static,
11531148
TMuxer::OutboundSubstream: Send,
1154-
TMuxer::Substream: Send,
11551149
TInEvent: Send + 'static,
11561150
TOutEvent: Send + 'static,
11571151
TConnInfo: ConnectionInfo<PeerId = TPeerId> + Clone + Send + 'static,

core/src/transport/mod.rs

Lines changed: 58 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,11 @@
2525
//! any desired protocols. The rest of the module defines combinators for
2626
//! modifying a transport through composition with other transports or protocol upgrades.
2727
28-
use crate::{InboundUpgrade, OutboundUpgrade, ConnectedPoint};
28+
use crate::ConnectedPoint;
2929
use futures::prelude::*;
3030
use multiaddr::Multiaddr;
31-
use std::{error, fmt};
31+
use std::{error::Error, fmt};
3232
use std::time::Duration;
33-
use tokio_io::{AsyncRead, AsyncWrite};
3433

3534
pub mod and_then;
3635
pub mod boxed;
@@ -69,11 +68,7 @@ pub use self::upgrade::Upgrade;
6968
///
7069
/// Additional protocols can be layered on top of the connections established
7170
/// by a [`Transport`] through an upgrade mechanism that is initiated via
72-
/// [`with_upgrade`](Transport::with_upgrade) and optionally followed by further upgrades
73-
/// through chaining calls to [`with_upgrade`](Transport::with_upgrade) and
74-
/// [`and_then`](Transport::and_then). Thereby every upgrade yields a new [`Transport`]
75-
/// whose connection setup incorporates all earlier upgrades followed by the new upgrade,
76-
/// i.e. the order of the upgrades is significant.
71+
/// [`upgrade`](Transport::upgrade).
7772
///
7873
/// > **Note**: The methods of this trait use `self` and not `&self` or `&mut self`. In other
7974
/// > words, listening or dialing consumes the transport object. This has been designed
@@ -88,7 +83,7 @@ pub trait Transport {
8883
type Output;
8984

9085
/// An error that occurred during connection setup.
91-
type Error: error::Error;
86+
type Error: Error;
9287

9388
/// A stream of [`Output`](Transport::Output)s for inbound connections.
9489
///
@@ -127,104 +122,101 @@ pub trait Transport {
127122
where
128123
Self: Sized;
129124

130-
/// Turns this `Transport` into an abstract boxed transport.
131-
fn boxed(self) -> boxed::Boxed<Self::Output, Self::Error>
132-
where Self: Sized + Clone + Send + Sync + 'static,
133-
Self::Dial: Send + 'static,
134-
Self::Listener: Send + 'static,
135-
Self::ListenerUpgrade: Send + 'static,
136-
{
137-
boxed::boxed(self)
138-
}
139-
140125
/// Applies a function on the connections created by the transport.
141-
fn map<F, O>(self, map: F) -> map::Map<Self, F>
126+
fn map<F, O>(self, f: F) -> map::Map<Self, F>
142127
where
143128
Self: Sized,
144129
F: FnOnce(Self::Output, ConnectedPoint) -> O + Clone
145130
{
146-
map::Map::new(self, map)
131+
map::Map::new(self, f)
147132
}
148133

149134
/// Applies a function on the errors generated by the futures of the transport.
150-
fn map_err<F, TNewErr>(self, map_err: F) -> map_err::MapErr<Self, F>
135+
fn map_err<F, E>(self, f: F) -> map_err::MapErr<Self, F>
151136
where
152137
Self: Sized,
153-
F: FnOnce(Self::Error) -> TNewErr + Clone
138+
E: Error + 'static,
139+
F: FnOnce(Self::Error) -> E + Clone
154140
{
155-
map_err::MapErr::new(self, map_err)
141+
map_err::MapErr::new(self, f)
156142
}
157143

158-
/// Builds a new transport that falls back to another transport when
159-
/// encountering errors on dialing or listening for connections.
144+
/// Applies a function producing an asynchronous result to every connection
145+
/// created by this transport.
160146
///
161-
/// The returned transport will act like `self`, except that if `listen_on` or `dial`
162-
/// return an error then `other` will be tried.
163-
fn or_transport<T>(self, other: T) -> OrTransport<Self, T>
147+
/// This function can be used for ad-hoc protocol upgrades or
148+
/// for processing or adapting the output for following configurations.
149+
///
150+
/// For the high-level transport upgrade procedure, see [`Transport::upgrade`].
151+
fn and_then<C, F, O>(self, f: C) -> and_then::AndThen<Self, C>
164152
where
165153
Self: Sized,
154+
C: FnOnce(Self::Output, ConnectedPoint) -> F + Clone,
155+
F: IntoFuture<Item = O>,
156+
<F as IntoFuture>::Error: Error + 'static
166157
{
167-
OrTransport::new(self, other)
158+
and_then::AndThen::new(self, f)
168159
}
169160

170-
/// Wraps this transport inside an [`Upgrade`].
171-
///
172-
/// Whenever an inbound or outbound connection is established by this
173-
/// transport, the upgrade is applied on the current state of the
174-
/// connection (which may have already gone through previous upgrades)
175-
/// as an [`upgrade::InboundUpgrade`] or [`upgrade::OutboundUpgrade`],
176-
/// respectively.
177-
fn with_upgrade<U, O, E>(self, upgrade: U) -> Upgrade<Self, U>
178-
where
179-
Self: Sized,
180-
Self::Output: AsyncRead + AsyncWrite,
181-
U: InboundUpgrade<Self::Output, Output = O, Error = E>,
182-
U: OutboundUpgrade<Self::Output, Output = O, Error = E>
161+
/// Turns the transport into an abstract boxed (i.e. heap-allocated) transport.
162+
fn boxed(self) -> boxed::Boxed<Self::Output, Self::Error>
163+
where Self: Sized + Clone + Send + Sync + 'static,
164+
Self::Dial: Send + 'static,
165+
Self::Listener: Send + 'static,
166+
Self::ListenerUpgrade: Send + 'static,
183167
{
184-
Upgrade::new(self, upgrade)
168+
boxed::boxed(self)
185169
}
186170

187-
/// Applies a function producing an asynchronous result to every connection
188-
/// created by this transport.
171+
/// Adds a fallback transport that is used when encountering errors
172+
/// while establishing inbound or outbound connections.
189173
///
190-
/// This function can be used for ad-hoc protocol upgrades on a transport or
191-
/// for processing or adapting the output of an earlier upgrade before
192-
/// applying the next upgrade.
193-
fn and_then<C, F, O>(self, upgrade: C) -> and_then::AndThen<Self, C>
174+
/// The returned transport will act like `self`, except that if `listen_on` or `dial`
175+
/// return an error then `other` will be tried.
176+
fn or_transport<U>(self, other: U) -> OrTransport<Self, U>
194177
where
195178
Self: Sized,
196-
C: FnOnce(Self::Output, ConnectedPoint) -> F + Clone,
197-
F: IntoFuture<Item = O>
179+
U: Transport,
180+
<U as Transport>::Error: 'static
198181
{
199-
and_then::AndThen::new(self, upgrade)
182+
OrTransport::new(self, other)
200183
}
201184

202-
/// Adds a timeout to the connection setup (including upgrades) for all inbound
203-
/// and outbound connection attempts.
204-
fn with_timeout(self, timeout: Duration) -> timeout::TransportTimeout<Self>
185+
/// Adds a timeout to the connection setup (including upgrades) for all
186+
/// inbound and outbound connections established through the transport.
187+
fn timeout(self, timeout: Duration) -> timeout::TransportTimeout<Self>
205188
where
206-
Self: Sized,
189+
Self: Sized
207190
{
208191
timeout::TransportTimeout::new(self, timeout)
209192
}
210193

211194
/// Adds a timeout to the connection setup (including upgrades) for all outbound
212-
/// connection attempts.
213-
fn with_outbound_timeout(self, timeout: Duration) -> timeout::TransportTimeout<Self>
195+
/// connections established through the transport.
196+
fn outbound_timeout(self, timeout: Duration) -> timeout::TransportTimeout<Self>
214197
where
215-
Self: Sized,
198+
Self: Sized
216199
{
217200
timeout::TransportTimeout::with_outgoing_timeout(self, timeout)
218201
}
219202

220203
/// Adds a timeout to the connection setup (including upgrades) for all inbound
221-
/// connection attempts.
222-
fn with_inbound_timeout(self, timeout: Duration) -> timeout::TransportTimeout<Self>
204+
/// connections established through the transport.
205+
fn inbound_timeout(self, timeout: Duration) -> timeout::TransportTimeout<Self>
223206
where
224-
Self: Sized,
207+
Self: Sized
225208
{
226209
timeout::TransportTimeout::with_ingoing_timeout(self, timeout)
227210
}
211+
212+
/// Begins a series of protocol upgrades via an [`upgrade::Builder`].
213+
fn upgrade(self) -> upgrade::Builder<Self>
214+
where
215+
Self: Sized,
216+
Self::Error: 'static
217+
{
218+
upgrade::Builder::new(self)
219+
}
228220
}
229221

230222
/// Event produced by [`Transport::Listener`]s.
@@ -362,10 +354,10 @@ where TErr: fmt::Display,
362354
}
363355
}
364356

365-
impl<TErr> error::Error for TransportError<TErr>
366-
where TErr: error::Error + 'static,
357+
impl<TErr> Error for TransportError<TErr>
358+
where TErr: Error + 'static,
367359
{
368-
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
360+
fn source(&self) -> Option<&(dyn Error + 'static)> {
369361
match self {
370362
TransportError::MultiaddrNotSupported(_) => None,
371363
TransportError::Other(err) => Some(err),

0 commit comments

Comments
 (0)