feat(swarm): make stream uprade errors more ergonomic

The currently provided `ConnectionHandlerUpgrErr` is very hard to use. Not only does it have a long name, it also features 3 levels of nesting which results in a lot of boilerplate. Last but not least, it exposes `multistream-select` as a dependency to all protocols.

We fix all of the above by renaming the type to `StreamUpgradeError` and flattening out its interface. Unrecoverable errors during protocol selection are hidden within the `Io` variant.

Related: #3759.

Pull-Request: #3882.
This commit is contained in:
Thomas Eizinger
2023-05-08 10:55:17 +02:00
committed by GitHub
parent 0e36c7c072
commit 81c424ea9e
23 changed files with 234 additions and 300 deletions

View File

@ -30,15 +30,15 @@ use futures::io::AsyncWriteExt;
use futures::stream::{FuturesUnordered, StreamExt};
use futures_timer::Delay;
use instant::Instant;
use libp2p_core::{upgrade, ConnectedPoint, Multiaddr};
use libp2p_core::{ConnectedPoint, Multiaddr};
use libp2p_identity::PeerId;
use libp2p_swarm::handler::{
ConnectionEvent, DialUpgradeError, FullyNegotiatedInbound, FullyNegotiatedOutbound,
ListenUpgradeError,
};
use libp2p_swarm::{
ConnectionHandler, ConnectionHandlerEvent, ConnectionHandlerUpgrErr, ConnectionId, KeepAlive,
NegotiatedSubstream, SubstreamProtocol,
ConnectionHandler, ConnectionHandlerEvent, ConnectionId, KeepAlive, NegotiatedSubstream,
StreamUpgradeError, SubstreamProtocol,
};
use std::collections::VecDeque;
use std::fmt;
@ -203,7 +203,7 @@ pub enum Event {
src_connection_id: ConnectionId,
inbound_circuit_req: inbound_hop::CircuitReq,
status: proto::Status,
error: ConnectionHandlerUpgrErr<outbound_stop::CircuitFailedReason>,
error: StreamUpgradeError<outbound_stop::CircuitFailedReason>,
},
/// An inbound circuit has closed.
CircuitClosed {
@ -347,7 +347,7 @@ pub struct Handler {
/// A pending fatal error that results in the connection being closed.
pending_error: Option<
ConnectionHandlerUpgrErr<
StreamUpgradeError<
Either<inbound_hop::FatalUpgradeError, outbound_stop::FatalUpgradeError>,
>,
>,
@ -471,9 +471,7 @@ impl Handler {
<Self as ConnectionHandler>::InboundProtocol,
>,
) {
self.pending_error = Some(ConnectionHandlerUpgrErr::Upgrade(
upgrade::UpgradeError::Apply(Either::Left(error)),
));
self.pending_error = Some(StreamUpgradeError::Apply(Either::Left(error)));
}
fn on_dial_upgrade_error(
@ -487,33 +485,23 @@ impl Handler {
>,
) {
let (non_fatal_error, status) = match error {
ConnectionHandlerUpgrErr::Timeout => (
ConnectionHandlerUpgrErr::Timeout,
StreamUpgradeError::Timeout => (
StreamUpgradeError::Timeout,
proto::Status::CONNECTION_FAILED,
),
ConnectionHandlerUpgrErr::Upgrade(upgrade::UpgradeError::Select(
upgrade::NegotiationError::Failed,
)) => {
StreamUpgradeError::NegotiationFailed => {
// The remote has previously done a reservation. Doing a reservation but not
// supporting the stop protocol is pointless, thus disconnecting.
self.pending_error = Some(ConnectionHandlerUpgrErr::Upgrade(
upgrade::UpgradeError::Select(upgrade::NegotiationError::Failed),
));
self.pending_error = Some(StreamUpgradeError::NegotiationFailed);
return;
}
ConnectionHandlerUpgrErr::Upgrade(upgrade::UpgradeError::Select(
upgrade::NegotiationError::ProtocolError(e),
)) => {
self.pending_error = Some(ConnectionHandlerUpgrErr::Upgrade(
upgrade::UpgradeError::Select(upgrade::NegotiationError::ProtocolError(e)),
));
StreamUpgradeError::Io(e) => {
self.pending_error = Some(StreamUpgradeError::Io(e));
return;
}
ConnectionHandlerUpgrErr::Upgrade(upgrade::UpgradeError::Apply(error)) => match error {
StreamUpgradeError::Apply(error) => match error {
outbound_stop::UpgradeError::Fatal(error) => {
self.pending_error = Some(ConnectionHandlerUpgrErr::Upgrade(
upgrade::UpgradeError::Apply(Either::Right(error)),
));
self.pending_error = Some(StreamUpgradeError::Apply(Either::Right(error)));
return;
}
outbound_stop::UpgradeError::CircuitFailed(error) => {
@ -525,10 +513,7 @@ impl Handler {
proto::Status::PERMISSION_DENIED
}
};
(
ConnectionHandlerUpgrErr::Upgrade(upgrade::UpgradeError::Apply(error)),
status,
)
(StreamUpgradeError::Apply(error), status)
}
},
};
@ -563,7 +548,7 @@ type Futures<T> = FuturesUnordered<BoxFuture<'static, T>>;
impl ConnectionHandler for Handler {
type InEvent = In;
type OutEvent = Event;
type Error = ConnectionHandlerUpgrErr<
type Error = StreamUpgradeError<
Either<inbound_hop::FatalUpgradeError, outbound_stop::FatalUpgradeError>,
>;
type InboundProtocol = inbound_hop::Upgrade;