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
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 234 additions and 300 deletions

View File

@ -16,7 +16,7 @@ use libp2p::{
multiaddr::Protocol, multiaddr::Protocol,
noise, noise,
request_response::{self, ProtocolSupport, RequestId, ResponseChannel}, request_response::{self, ProtocolSupport, RequestId, ResponseChannel},
swarm::{ConnectionHandlerUpgrErr, NetworkBehaviour, Swarm, SwarmBuilder, SwarmEvent}, swarm::{NetworkBehaviour, StreamUpgradeError, Swarm, SwarmBuilder, SwarmEvent},
tcp, yamux, PeerId, Transport, tcp, yamux, PeerId, Transport,
}; };
@ -216,7 +216,7 @@ impl EventLoop {
async fn handle_event( async fn handle_event(
&mut self, &mut self,
event: SwarmEvent<ComposedEvent, Either<ConnectionHandlerUpgrErr<io::Error>, io::Error>>, event: SwarmEvent<ComposedEvent, Either<StreamUpgradeError<io::Error>, io::Error>>,
) { ) {
match event { match event {
SwarmEvent::Behaviour(ComposedEvent::Kademlia( SwarmEvent::Behaviour(ComposedEvent::Kademlia(

View File

@ -30,7 +30,7 @@ use libp2p_swarm::behaviour::{ConnectionClosed, ConnectionEstablished, DialFailu
use libp2p_swarm::dial_opts::{self, DialOpts}; use libp2p_swarm::dial_opts::{self, DialOpts};
use libp2p_swarm::{dummy, ConnectionDenied, ConnectionId, THandler, THandlerOutEvent}; use libp2p_swarm::{dummy, ConnectionDenied, ConnectionId, THandler, THandlerOutEvent};
use libp2p_swarm::{ use libp2p_swarm::{
ConnectionHandlerUpgrErr, ExternalAddresses, NetworkBehaviour, NotifyHandler, PollParameters, ExternalAddresses, NetworkBehaviour, NotifyHandler, PollParameters, StreamUpgradeError,
THandlerInEvent, ToSwarm, THandlerInEvent, ToSwarm,
}; };
use std::collections::{HashMap, HashSet, VecDeque}; use std::collections::{HashMap, HashSet, VecDeque};
@ -65,7 +65,7 @@ pub enum Error {
#[error("Failed to dial peer.")] #[error("Failed to dial peer.")]
Dial, Dial,
#[error("Failed to establish substream: {0}.")] #[error("Failed to establish substream: {0}.")]
Handler(ConnectionHandlerUpgrErr<Void>), Handler(StreamUpgradeError<Void>),
} }
pub struct Behaviour { pub struct Behaviour {

View File

@ -23,8 +23,7 @@
use libp2p_core::upgrade::DeniedUpgrade; use libp2p_core::upgrade::DeniedUpgrade;
use libp2p_swarm::handler::ConnectionEvent; use libp2p_swarm::handler::ConnectionEvent;
use libp2p_swarm::{ use libp2p_swarm::{
ConnectionHandler, ConnectionHandlerEvent, ConnectionHandlerUpgrErr, KeepAlive, ConnectionHandler, ConnectionHandlerEvent, KeepAlive, StreamUpgradeError, SubstreamProtocol,
SubstreamProtocol,
}; };
use std::task::{Context, Poll}; use std::task::{Context, Poll};
use void::Void; use void::Void;
@ -42,7 +41,7 @@ pub struct Handler {
impl ConnectionHandler for Handler { impl ConnectionHandler for Handler {
type InEvent = void::Void; type InEvent = void::Void;
type OutEvent = Event; type OutEvent = Event;
type Error = ConnectionHandlerUpgrErr<std::io::Error>; type Error = StreamUpgradeError<std::io::Error>;
type InboundProtocol = DeniedUpgrade; type InboundProtocol = DeniedUpgrade;
type OutboundProtocol = DeniedUpgrade; type OutboundProtocol = DeniedUpgrade;
type OutboundOpenInfo = Void; type OutboundOpenInfo = Void;

View File

@ -26,15 +26,14 @@ use futures::future;
use futures::future::{BoxFuture, FutureExt}; use futures::future::{BoxFuture, FutureExt};
use instant::Instant; use instant::Instant;
use libp2p_core::multiaddr::Multiaddr; use libp2p_core::multiaddr::Multiaddr;
use libp2p_core::upgrade::{DeniedUpgrade, NegotiationError, UpgradeError}; use libp2p_core::upgrade::DeniedUpgrade;
use libp2p_core::ConnectedPoint; use libp2p_core::ConnectedPoint;
use libp2p_swarm::handler::{ use libp2p_swarm::handler::{
ConnectionEvent, DialUpgradeError, FullyNegotiatedInbound, FullyNegotiatedOutbound, ConnectionEvent, DialUpgradeError, FullyNegotiatedInbound, FullyNegotiatedOutbound,
ListenUpgradeError, ListenUpgradeError,
}; };
use libp2p_swarm::{ use libp2p_swarm::{
ConnectionHandler, ConnectionHandlerEvent, ConnectionHandlerUpgrErr, KeepAlive, ConnectionHandler, ConnectionHandlerEvent, KeepAlive, StreamUpgradeError, SubstreamProtocol,
SubstreamProtocol,
}; };
use std::collections::VecDeque; use std::collections::VecDeque;
use std::fmt; use std::fmt;
@ -82,11 +81,11 @@ pub enum Event {
remote_addr: Multiaddr, remote_addr: Multiaddr,
}, },
InboundNegotiationFailed { InboundNegotiationFailed {
error: ConnectionHandlerUpgrErr<void::Void>, error: StreamUpgradeError<void::Void>,
}, },
InboundConnectNegotiated(Vec<Multiaddr>), InboundConnectNegotiated(Vec<Multiaddr>),
OutboundNegotiationFailed { OutboundNegotiationFailed {
error: ConnectionHandlerUpgrErr<void::Void>, error: StreamUpgradeError<void::Void>,
}, },
OutboundConnectNegotiated { OutboundConnectNegotiated {
remote_addrs: Vec<Multiaddr>, remote_addrs: Vec<Multiaddr>,
@ -127,7 +126,7 @@ pub struct Handler {
endpoint: ConnectedPoint, endpoint: ConnectedPoint,
/// A pending fatal error that results in the connection being closed. /// A pending fatal error that results in the connection being closed.
pending_error: Option< pending_error: Option<
ConnectionHandlerUpgrErr< StreamUpgradeError<
Either<protocol::inbound::UpgradeError, protocol::outbound::UpgradeError>, Either<protocol::inbound::UpgradeError, protocol::outbound::UpgradeError>,
>, >,
>, >,
@ -212,12 +211,10 @@ impl Handler {
<Self as ConnectionHandler>::InboundProtocol, <Self as ConnectionHandler>::InboundProtocol,
>, >,
) { ) {
self.pending_error = Some(ConnectionHandlerUpgrErr::Upgrade(UpgradeError::Apply( self.pending_error = Some(StreamUpgradeError::Apply(match error {
match error { Either::Left(e) => Either::Left(e),
Either::Left(e) => Either::Left(e), Either::Right(v) => void::unreachable(v),
Either::Right(v) => void::unreachable(v), }));
},
)));
} }
fn on_dial_upgrade_error( fn on_dial_upgrade_error(
@ -230,29 +227,27 @@ impl Handler {
self.keep_alive = KeepAlive::No; self.keep_alive = KeepAlive::No;
match error { match error {
ConnectionHandlerUpgrErr::Timeout => { StreamUpgradeError::Timeout => {
self.queued_events.push_back(ConnectionHandlerEvent::Custom( self.queued_events.push_back(ConnectionHandlerEvent::Custom(
Event::OutboundNegotiationFailed { Event::OutboundNegotiationFailed {
error: ConnectionHandlerUpgrErr::Timeout, error: StreamUpgradeError::Timeout,
}, },
)); ));
} }
ConnectionHandlerUpgrErr::Upgrade(UpgradeError::Select(NegotiationError::Failed)) => { StreamUpgradeError::NegotiationFailed => {
// The remote merely doesn't support the DCUtR protocol. // The remote merely doesn't support the DCUtR protocol.
// This is no reason to close the connection, which may // This is no reason to close the connection, which may
// successfully communicate with other protocols already. // successfully communicate with other protocols already.
self.queued_events.push_back(ConnectionHandlerEvent::Custom( self.queued_events.push_back(ConnectionHandlerEvent::Custom(
Event::OutboundNegotiationFailed { Event::OutboundNegotiationFailed {
error: ConnectionHandlerUpgrErr::Upgrade(UpgradeError::Select( error: StreamUpgradeError::NegotiationFailed,
NegotiationError::Failed,
)),
}, },
)); ));
} }
_ => { _ => {
// Anything else is considered a fatal error or misbehaviour of // Anything else is considered a fatal error or misbehaviour of
// the remote peer and results in closing the connection. // the remote peer and results in closing the connection.
self.pending_error = Some(error.map_upgrade_err(|e| e.map_err(Either::Right))); self.pending_error = Some(error.map_upgrade_err(Either::Right));
} }
} }
} }
@ -261,7 +256,7 @@ impl Handler {
impl ConnectionHandler for Handler { impl ConnectionHandler for Handler {
type InEvent = Command; type InEvent = Command;
type OutEvent = Event; type OutEvent = Event;
type Error = ConnectionHandlerUpgrErr< type Error = StreamUpgradeError<
Either<protocol::inbound::UpgradeError, protocol::outbound::UpgradeError>, Either<protocol::inbound::UpgradeError, protocol::outbound::UpgradeError>,
>; >;
type InboundProtocol = Either<protocol::inbound::Upgrade, DeniedUpgrade>; type InboundProtocol = Either<protocol::inbound::Upgrade, DeniedUpgrade>;
@ -352,9 +347,9 @@ impl ConnectionHandler for Handler {
)); ));
} }
Err(e) => { Err(e) => {
return Poll::Ready(ConnectionHandlerEvent::Close( return Poll::Ready(ConnectionHandlerEvent::Close(StreamUpgradeError::Apply(
ConnectionHandlerUpgrErr::Upgrade(UpgradeError::Apply(Either::Left(e))), Either::Left(e),
)) )))
} }
} }
} }

View File

@ -27,10 +27,10 @@ use futures::future::Either;
use futures::prelude::*; use futures::prelude::*;
use futures::StreamExt; use futures::StreamExt;
use instant::Instant; use instant::Instant;
use libp2p_core::upgrade::{DeniedUpgrade, NegotiationError, UpgradeError}; use libp2p_core::upgrade::DeniedUpgrade;
use libp2p_swarm::handler::{ use libp2p_swarm::handler::{
ConnectionEvent, ConnectionHandler, ConnectionHandlerEvent, ConnectionHandlerUpgrErr, ConnectionEvent, ConnectionHandler, ConnectionHandlerEvent, DialUpgradeError,
DialUpgradeError, FullyNegotiatedInbound, FullyNegotiatedOutbound, KeepAlive, FullyNegotiatedInbound, FullyNegotiatedOutbound, KeepAlive, StreamUpgradeError,
SubstreamProtocol, SubstreamProtocol,
}; };
use libp2p_swarm::NegotiatedSubstream; use libp2p_swarm::NegotiatedSubstream;
@ -526,20 +526,17 @@ impl ConnectionHandler for Handler {
handler.on_fully_negotiated_outbound(fully_negotiated_outbound) handler.on_fully_negotiated_outbound(fully_negotiated_outbound)
} }
ConnectionEvent::DialUpgradeError(DialUpgradeError { ConnectionEvent::DialUpgradeError(DialUpgradeError {
error: ConnectionHandlerUpgrErr::Timeout, error: StreamUpgradeError::Timeout,
.. ..
}) => { }) => {
log::debug!("Dial upgrade error: Protocol negotiation timeout"); log::debug!("Dial upgrade error: Protocol negotiation timeout");
} }
ConnectionEvent::DialUpgradeError(DialUpgradeError { ConnectionEvent::DialUpgradeError(DialUpgradeError {
error: ConnectionHandlerUpgrErr::Upgrade(UpgradeError::Apply(e)), error: StreamUpgradeError::Apply(e),
.. ..
}) => void::unreachable(e), }) => void::unreachable(e),
ConnectionEvent::DialUpgradeError(DialUpgradeError { ConnectionEvent::DialUpgradeError(DialUpgradeError {
error: error: StreamUpgradeError::NegotiationFailed,
ConnectionHandlerUpgrErr::Upgrade(UpgradeError::Select(
NegotiationError::Failed,
)),
.. ..
}) => { }) => {
// The protocol is not supported // The protocol is not supported
@ -551,10 +548,7 @@ impl ConnectionHandler for Handler {
}); });
} }
ConnectionEvent::DialUpgradeError(DialUpgradeError { ConnectionEvent::DialUpgradeError(DialUpgradeError {
error: error: StreamUpgradeError::Io(e),
ConnectionHandlerUpgrErr::Upgrade(UpgradeError::Select(
NegotiationError::ProtocolError(e),
)),
.. ..
}) => { }) => {
log::debug!("Protocol negotiation failed: {e}") log::debug!("Protocol negotiation failed: {e}")

View File

@ -25,8 +25,8 @@ use libp2p_identity::PeerId;
use libp2p_identity::PublicKey; use libp2p_identity::PublicKey;
use libp2p_swarm::behaviour::{ConnectionClosed, ConnectionEstablished, DialFailure, FromSwarm}; use libp2p_swarm::behaviour::{ConnectionClosed, ConnectionEstablished, DialFailure, FromSwarm};
use libp2p_swarm::{ use libp2p_swarm::{
AddressScore, ConnectionDenied, ConnectionHandlerUpgrErr, DialError, ExternalAddresses, AddressScore, ConnectionDenied, DialError, ExternalAddresses, ListenAddresses,
ListenAddresses, NetworkBehaviour, NotifyHandler, PollParameters, StreamProtocol, NetworkBehaviour, NotifyHandler, PollParameters, StreamProtocol, StreamUpgradeError,
THandlerInEvent, ToSwarm, THandlerInEvent, ToSwarm,
}; };
use libp2p_swarm::{ConnectionId, THandler, THandlerOutEvent}; use libp2p_swarm::{ConnectionId, THandler, THandlerOutEvent};
@ -492,7 +492,7 @@ pub enum Event {
/// The peer with whom the error originated. /// The peer with whom the error originated.
peer_id: PeerId, peer_id: PeerId,
/// The error that occurred. /// The error that occurred.
error: ConnectionHandlerUpgrErr<UpgradeError>, error: StreamUpgradeError<UpgradeError>,
}, },
} }

View File

@ -34,8 +34,8 @@ use libp2p_swarm::handler::{
ConnectionEvent, DialUpgradeError, FullyNegotiatedInbound, FullyNegotiatedOutbound, ConnectionEvent, DialUpgradeError, FullyNegotiatedInbound, FullyNegotiatedOutbound,
}; };
use libp2p_swarm::{ use libp2p_swarm::{
ConnectionHandler, ConnectionHandlerEvent, ConnectionHandlerUpgrErr, KeepAlive, ConnectionHandler, ConnectionHandlerEvent, KeepAlive, NegotiatedSubstream, StreamProtocol,
NegotiatedSubstream, StreamProtocol, SubstreamProtocol, StreamUpgradeError, SubstreamProtocol,
}; };
use log::warn; use log::warn;
use smallvec::SmallVec; use smallvec::SmallVec;
@ -111,7 +111,7 @@ pub enum Event {
/// We received a request for identification. /// We received a request for identification.
Identify, Identify,
/// Failed to identify the remote, or to reply to an identification request. /// Failed to identify the remote, or to reply to an identification request.
IdentificationError(ConnectionHandlerUpgrErr<UpgradeError>), IdentificationError(StreamUpgradeError<UpgradeError>),
} }
impl Handler { impl Handler {
@ -205,13 +205,7 @@ impl Handler {
<Self as ConnectionHandler>::OutboundProtocol, <Self as ConnectionHandler>::OutboundProtocol,
>, >,
) { ) {
use libp2p_core::upgrade::UpgradeError; let err = err.map_upgrade_err(|e| e.into_inner());
let err = err.map_upgrade_err(|e| match e {
UpgradeError::Select(e) => UpgradeError::Select(e),
UpgradeError::Apply(Either::Left(ioe)) => UpgradeError::Apply(ioe),
UpgradeError::Apply(Either::Right(ioe)) => UpgradeError::Apply(ioe),
});
self.events self.events
.push(ConnectionHandlerEvent::Custom(Event::IdentificationError( .push(ConnectionHandlerEvent::Custom(Event::IdentificationError(
err, err,
@ -317,9 +311,7 @@ impl ConnectionHandler for Handler {
Event::Identification(peer_id), Event::Identification(peer_id),
)), )),
Poll::Ready(Some(Err(err))) => Poll::Ready(ConnectionHandlerEvent::Custom( Poll::Ready(Some(Err(err))) => Poll::Ready(ConnectionHandlerEvent::Custom(
Event::IdentificationError(ConnectionHandlerUpgrErr::Upgrade( Event::IdentificationError(StreamUpgradeError::Apply(err)),
libp2p_core::upgrade::UpgradeError::Apply(err),
)),
)), )),
Poll::Ready(None) | Poll::Pending => Poll::Pending, Poll::Ready(None) | Poll::Pending => Poll::Pending,
} }

View File

@ -33,8 +33,8 @@ use libp2p_swarm::handler::{
ConnectionEvent, DialUpgradeError, FullyNegotiatedInbound, FullyNegotiatedOutbound, ConnectionEvent, DialUpgradeError, FullyNegotiatedInbound, FullyNegotiatedOutbound,
}; };
use libp2p_swarm::{ use libp2p_swarm::{
ConnectionHandler, ConnectionHandlerEvent, ConnectionHandlerUpgrErr, KeepAlive, ConnectionHandler, ConnectionHandlerEvent, KeepAlive, NegotiatedSubstream, StreamUpgradeError,
NegotiatedSubstream, SubstreamProtocol, SubstreamProtocol,
}; };
use log::trace; use log::trace;
use std::collections::VecDeque; use std::collections::VecDeque;
@ -325,7 +325,7 @@ pub enum KademliaHandlerEvent<TUserData> {
#[derive(Debug)] #[derive(Debug)]
pub enum KademliaHandlerQueryErr { pub enum KademliaHandlerQueryErr {
/// Error while trying to perform the query. /// Error while trying to perform the query.
Upgrade(ConnectionHandlerUpgrErr<io::Error>), Upgrade(StreamUpgradeError<io::Error>),
/// Received an answer that doesn't correspond to the request. /// Received an answer that doesn't correspond to the request.
UnexpectedMessage, UnexpectedMessage,
/// I/O error in the substream. /// I/O error in the substream.
@ -361,8 +361,8 @@ impl error::Error for KademliaHandlerQueryErr {
} }
} }
impl From<ConnectionHandlerUpgrErr<io::Error>> for KademliaHandlerQueryErr { impl From<StreamUpgradeError<io::Error>> for KademliaHandlerQueryErr {
fn from(err: ConnectionHandlerUpgrErr<io::Error>) -> Self { fn from(err: StreamUpgradeError<io::Error>) -> Self {
KademliaHandlerQueryErr::Upgrade(err) KademliaHandlerQueryErr::Upgrade(err)
} }
} }

View File

@ -28,8 +28,8 @@ use std::{
use libp2p_core::Multiaddr; use libp2p_core::Multiaddr;
use libp2p_identity::PeerId; use libp2p_identity::PeerId;
use libp2p_swarm::{ use libp2p_swarm::{
derive_prelude::ConnectionEstablished, ConnectionClosed, ConnectionHandlerUpgrErr, derive_prelude::ConnectionEstablished, ConnectionClosed, ConnectionId, FromSwarm,
ConnectionId, FromSwarm, NetworkBehaviour, NotifyHandler, PollParameters, THandlerInEvent, NetworkBehaviour, NotifyHandler, PollParameters, StreamUpgradeError, THandlerInEvent,
THandlerOutEvent, ToSwarm, THandlerOutEvent, ToSwarm,
}; };
use void::Void; use void::Void;
@ -41,7 +41,7 @@ use super::{RunId, RunParams, RunStats};
#[derive(Debug)] #[derive(Debug)]
pub struct Event { pub struct Event {
pub id: RunId, pub id: RunId,
pub result: Result<RunStats, ConnectionHandlerUpgrErr<Void>>, pub result: Result<RunStats, StreamUpgradeError<Void>>,
} }
#[derive(Default)] #[derive(Default)]

View File

@ -31,7 +31,7 @@ use libp2p_swarm::{
ConnectionEvent, DialUpgradeError, FullyNegotiatedInbound, FullyNegotiatedOutbound, ConnectionEvent, DialUpgradeError, FullyNegotiatedInbound, FullyNegotiatedOutbound,
ListenUpgradeError, ListenUpgradeError,
}, },
ConnectionHandler, ConnectionHandlerEvent, ConnectionHandlerUpgrErr, KeepAlive, StreamProtocol, ConnectionHandler, ConnectionHandlerEvent, KeepAlive, StreamProtocol, StreamUpgradeError,
SubstreamProtocol, SubstreamProtocol,
}; };
use void::Void; use void::Void;
@ -47,7 +47,7 @@ pub struct Command {
#[derive(Debug)] #[derive(Debug)]
pub struct Event { pub struct Event {
pub(crate) id: RunId, pub(crate) id: RunId,
pub(crate) result: Result<RunStats, ConnectionHandlerUpgrErr<Void>>, pub(crate) result: Result<RunStats, StreamUpgradeError<Void>>,
} }
pub struct Handler { pub struct Handler {

View File

@ -23,13 +23,12 @@ use futures::future::BoxFuture;
use futures::prelude::*; use futures::prelude::*;
use futures_timer::Delay; use futures_timer::Delay;
use libp2p_core::upgrade::ReadyUpgrade; use libp2p_core::upgrade::ReadyUpgrade;
use libp2p_core::{upgrade::NegotiationError, UpgradeError};
use libp2p_swarm::handler::{ use libp2p_swarm::handler::{
ConnectionEvent, DialUpgradeError, FullyNegotiatedInbound, FullyNegotiatedOutbound, ConnectionEvent, DialUpgradeError, FullyNegotiatedInbound, FullyNegotiatedOutbound,
}; };
use libp2p_swarm::{ use libp2p_swarm::{
ConnectionHandler, ConnectionHandlerEvent, ConnectionHandlerUpgrErr, KeepAlive, ConnectionHandler, ConnectionHandlerEvent, KeepAlive, NegotiatedSubstream, StreamProtocol,
NegotiatedSubstream, StreamProtocol, SubstreamProtocol, StreamUpgradeError, SubstreamProtocol,
}; };
use std::collections::VecDeque; use std::collections::VecDeque;
use std::{ use std::{
@ -238,14 +237,14 @@ impl Handler {
self.outbound = None; // Request a new substream on the next `poll`. self.outbound = None; // Request a new substream on the next `poll`.
let error = match error { let error = match error {
ConnectionHandlerUpgrErr::Upgrade(UpgradeError::Select(NegotiationError::Failed)) => { StreamUpgradeError::NegotiationFailed => {
debug_assert_eq!(self.state, State::Active); debug_assert_eq!(self.state, State::Active);
self.state = State::Inactive { reported: false }; self.state = State::Inactive { reported: false };
return; return;
} }
// Note: This timeout only covers protocol negotiation. // Note: This timeout only covers protocol negotiation.
ConnectionHandlerUpgrErr::Timeout => Failure::Timeout, StreamUpgradeError::Timeout => Failure::Timeout,
e => Failure::Other { error: Box::new(e) }, e => Failure::Other { error: Box::new(e) },
}; };

View File

@ -33,9 +33,8 @@ use libp2p_core::{ConnectedPoint, Endpoint, Multiaddr};
use libp2p_identity::PeerId; use libp2p_identity::PeerId;
use libp2p_swarm::behaviour::{ConnectionClosed, FromSwarm}; use libp2p_swarm::behaviour::{ConnectionClosed, FromSwarm};
use libp2p_swarm::{ use libp2p_swarm::{
dummy, ConnectionDenied, ConnectionHandlerUpgrErr, ConnectionId, ExternalAddresses, dummy, ConnectionDenied, ConnectionId, ExternalAddresses, NetworkBehaviour, NotifyHandler,
NetworkBehaviour, NotifyHandler, PollParameters, THandler, THandlerInEvent, THandlerOutEvent, PollParameters, StreamUpgradeError, THandler, THandlerInEvent, THandlerOutEvent, ToSwarm,
ToSwarm,
}; };
use std::collections::{hash_map, HashMap, HashSet, VecDeque}; use std::collections::{hash_map, HashMap, HashSet, VecDeque};
use std::num::NonZeroU32; use std::num::NonZeroU32;
@ -170,7 +169,7 @@ pub enum Event {
CircuitReqOutboundConnectFailed { CircuitReqOutboundConnectFailed {
src_peer_id: PeerId, src_peer_id: PeerId,
dst_peer_id: PeerId, dst_peer_id: PeerId,
error: ConnectionHandlerUpgrErr<outbound_stop::CircuitFailedReason>, error: StreamUpgradeError<outbound_stop::CircuitFailedReason>,
}, },
/// Accepting an inbound circuit request failed. /// Accepting an inbound circuit request failed.
CircuitReqAcceptFailed { CircuitReqAcceptFailed {

View File

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

View File

@ -39,9 +39,9 @@ use libp2p_identity::PeerId;
use libp2p_swarm::behaviour::{ConnectionClosed, ConnectionEstablished, FromSwarm}; use libp2p_swarm::behaviour::{ConnectionClosed, ConnectionEstablished, FromSwarm};
use libp2p_swarm::dial_opts::DialOpts; use libp2p_swarm::dial_opts::DialOpts;
use libp2p_swarm::{ use libp2p_swarm::{
dummy, ConnectionDenied, ConnectionHandler, ConnectionHandlerUpgrErr, ConnectionId, dummy, ConnectionDenied, ConnectionHandler, ConnectionId, DialFailure, NegotiatedSubstream,
DialFailure, NegotiatedSubstream, NetworkBehaviour, NotifyHandler, PollParameters, THandler, NetworkBehaviour, NotifyHandler, PollParameters, StreamUpgradeError, THandler, THandlerInEvent,
THandlerInEvent, THandlerOutEvent, ToSwarm, THandlerOutEvent, ToSwarm,
}; };
use std::collections::{hash_map, HashMap, VecDeque}; use std::collections::{hash_map, HashMap, VecDeque};
use std::io::{Error, ErrorKind, IoSlice}; use std::io::{Error, ErrorKind, IoSlice};
@ -64,7 +64,7 @@ pub enum Event {
relay_peer_id: PeerId, relay_peer_id: PeerId,
/// Indicates whether the request replaces an existing reservation. /// Indicates whether the request replaces an existing reservation.
renewal: bool, renewal: bool,
error: ConnectionHandlerUpgrErr<outbound_hop::ReservationFailedReason>, error: StreamUpgradeError<outbound_hop::ReservationFailedReason>,
}, },
OutboundCircuitEstablished { OutboundCircuitEstablished {
relay_peer_id: PeerId, relay_peer_id: PeerId,
@ -72,7 +72,7 @@ pub enum Event {
}, },
OutboundCircuitReqFailed { OutboundCircuitReqFailed {
relay_peer_id: PeerId, relay_peer_id: PeerId,
error: ConnectionHandlerUpgrErr<outbound_hop::CircuitFailedReason>, error: StreamUpgradeError<outbound_hop::CircuitFailedReason>,
}, },
/// An inbound circuit has been established. /// An inbound circuit has been established.
InboundCircuitEstablished { InboundCircuitEstablished {

View File

@ -29,15 +29,14 @@ use futures::stream::{FuturesUnordered, StreamExt};
use futures_timer::Delay; use futures_timer::Delay;
use instant::Instant; use instant::Instant;
use libp2p_core::multiaddr::Protocol; use libp2p_core::multiaddr::Protocol;
use libp2p_core::{upgrade, Multiaddr}; use libp2p_core::Multiaddr;
use libp2p_identity::PeerId; use libp2p_identity::PeerId;
use libp2p_swarm::handler::{ use libp2p_swarm::handler::{
ConnectionEvent, DialUpgradeError, FullyNegotiatedInbound, FullyNegotiatedOutbound, ConnectionEvent, DialUpgradeError, FullyNegotiatedInbound, FullyNegotiatedOutbound,
ListenUpgradeError, ListenUpgradeError,
}; };
use libp2p_swarm::{ use libp2p_swarm::{
ConnectionHandler, ConnectionHandlerEvent, ConnectionHandlerUpgrErr, KeepAlive, ConnectionHandler, ConnectionHandlerEvent, KeepAlive, StreamUpgradeError, SubstreamProtocol,
SubstreamProtocol,
}; };
use log::debug; use log::debug;
use std::collections::{HashMap, VecDeque}; use std::collections::{HashMap, VecDeque};
@ -85,12 +84,12 @@ pub enum Event {
ReservationReqFailed { ReservationReqFailed {
/// Indicates whether the request replaces an existing reservation. /// Indicates whether the request replaces an existing reservation.
renewal: bool, renewal: bool,
error: ConnectionHandlerUpgrErr<outbound_hop::ReservationFailedReason>, error: StreamUpgradeError<outbound_hop::ReservationFailedReason>,
}, },
/// An outbound circuit has been established. /// An outbound circuit has been established.
OutboundCircuitEstablished { limit: Option<protocol::Limit> }, OutboundCircuitEstablished { limit: Option<protocol::Limit> },
OutboundCircuitReqFailed { OutboundCircuitReqFailed {
error: ConnectionHandlerUpgrErr<outbound_hop::CircuitFailedReason>, error: StreamUpgradeError<outbound_hop::CircuitFailedReason>,
}, },
/// An inbound circuit has been established. /// An inbound circuit has been established.
InboundCircuitEstablished { InboundCircuitEstablished {
@ -112,7 +111,7 @@ pub struct Handler {
remote_addr: Multiaddr, remote_addr: Multiaddr,
/// A pending fatal error that results in the connection being closed. /// A pending fatal error that results in the connection being closed.
pending_error: Option< pending_error: Option<
ConnectionHandlerUpgrErr< StreamUpgradeError<
Either<inbound_stop::FatalUpgradeError, outbound_hop::FatalUpgradeError>, Either<inbound_stop::FatalUpgradeError, outbound_hop::FatalUpgradeError>,
>, >,
>, >,
@ -299,9 +298,7 @@ impl Handler {
<Self as ConnectionHandler>::InboundProtocol, <Self as ConnectionHandler>::InboundProtocol,
>, >,
) { ) {
self.pending_error = Some(ConnectionHandlerUpgrErr::Upgrade( self.pending_error = Some(StreamUpgradeError::Apply(Either::Left(error)));
upgrade::UpgradeError::Apply(Either::Left(error)),
));
} }
fn on_dial_upgrade_error( fn on_dial_upgrade_error(
@ -317,42 +314,25 @@ impl Handler {
match open_info { match open_info {
OutboundOpenInfo::Reserve { mut to_listener } => { OutboundOpenInfo::Reserve { mut to_listener } => {
let non_fatal_error = match error { let non_fatal_error = match error {
ConnectionHandlerUpgrErr::Timeout => ConnectionHandlerUpgrErr::Timeout, StreamUpgradeError::Timeout => StreamUpgradeError::Timeout,
ConnectionHandlerUpgrErr::Upgrade(upgrade::UpgradeError::Select( StreamUpgradeError::NegotiationFailed => StreamUpgradeError::NegotiationFailed,
upgrade::NegotiationError::Failed, StreamUpgradeError::Io(e) => {
)) => ConnectionHandlerUpgrErr::Upgrade(upgrade::UpgradeError::Select( self.pending_error = Some(StreamUpgradeError::Io(e));
upgrade::NegotiationError::Failed,
)),
ConnectionHandlerUpgrErr::Upgrade(upgrade::UpgradeError::Select(
upgrade::NegotiationError::ProtocolError(e),
)) => {
self.pending_error = Some(ConnectionHandlerUpgrErr::Upgrade(
upgrade::UpgradeError::Select(
upgrade::NegotiationError::ProtocolError(e),
),
));
return; return;
} }
ConnectionHandlerUpgrErr::Upgrade(upgrade::UpgradeError::Apply(error)) => { StreamUpgradeError::Apply(error) => match error {
match error { outbound_hop::UpgradeError::Fatal(error) => {
outbound_hop::UpgradeError::Fatal(error) => { self.pending_error =
self.pending_error = Some(ConnectionHandlerUpgrErr::Upgrade( Some(StreamUpgradeError::Apply(Either::Right(error)));
upgrade::UpgradeError::Apply(Either::Right(error)), return;
));
return;
}
outbound_hop::UpgradeError::ReservationFailed(error) => {
ConnectionHandlerUpgrErr::Upgrade(upgrade::UpgradeError::Apply(
error,
))
}
outbound_hop::UpgradeError::CircuitFailed(_) => {
unreachable!(
"Do not emitt `CircuitFailed` for outgoing reservation."
)
}
} }
} outbound_hop::UpgradeError::ReservationFailed(error) => {
StreamUpgradeError::Apply(error)
}
outbound_hop::UpgradeError::CircuitFailed(_) => {
unreachable!("Do not emitt `CircuitFailed` for outgoing reservation.")
}
},
}; };
if self.pending_error.is_none() { if self.pending_error.is_none() {
@ -379,42 +359,25 @@ impl Handler {
} }
OutboundOpenInfo::Connect { send_back } => { OutboundOpenInfo::Connect { send_back } => {
let non_fatal_error = match error { let non_fatal_error = match error {
ConnectionHandlerUpgrErr::Timeout => ConnectionHandlerUpgrErr::Timeout, StreamUpgradeError::Timeout => StreamUpgradeError::Timeout,
ConnectionHandlerUpgrErr::Upgrade(upgrade::UpgradeError::Select( StreamUpgradeError::NegotiationFailed => StreamUpgradeError::NegotiationFailed,
upgrade::NegotiationError::Failed, StreamUpgradeError::Io(e) => {
)) => ConnectionHandlerUpgrErr::Upgrade(upgrade::UpgradeError::Select( self.pending_error = Some(StreamUpgradeError::Io(e));
upgrade::NegotiationError::Failed,
)),
ConnectionHandlerUpgrErr::Upgrade(upgrade::UpgradeError::Select(
upgrade::NegotiationError::ProtocolError(e),
)) => {
self.pending_error = Some(ConnectionHandlerUpgrErr::Upgrade(
upgrade::UpgradeError::Select(
upgrade::NegotiationError::ProtocolError(e),
),
));
return; return;
} }
ConnectionHandlerUpgrErr::Upgrade(upgrade::UpgradeError::Apply(error)) => { StreamUpgradeError::Apply(error) => match error {
match error { outbound_hop::UpgradeError::Fatal(error) => {
outbound_hop::UpgradeError::Fatal(error) => { self.pending_error =
self.pending_error = Some(ConnectionHandlerUpgrErr::Upgrade( Some(StreamUpgradeError::Apply(Either::Right(error)));
upgrade::UpgradeError::Apply(Either::Right(error)), return;
));
return;
}
outbound_hop::UpgradeError::CircuitFailed(error) => {
ConnectionHandlerUpgrErr::Upgrade(upgrade::UpgradeError::Apply(
error,
))
}
outbound_hop::UpgradeError::ReservationFailed(_) => {
unreachable!(
"Do not emitt `ReservationFailed` for outgoing circuit."
)
}
} }
} outbound_hop::UpgradeError::CircuitFailed(error) => {
StreamUpgradeError::Apply(error)
}
outbound_hop::UpgradeError::ReservationFailed(_) => {
unreachable!("Do not emitt `ReservationFailed` for outgoing circuit.")
}
},
}; };
let _ = send_back.send(Err(())); let _ = send_back.send(Err(()));
@ -432,7 +395,7 @@ impl Handler {
impl ConnectionHandler for Handler { impl ConnectionHandler for Handler {
type InEvent = In; type InEvent = In;
type OutEvent = Event; type OutEvent = Event;
type Error = ConnectionHandlerUpgrErr< type Error = StreamUpgradeError<
Either<inbound_stop::FatalUpgradeError, outbound_hop::FatalUpgradeError>, Either<inbound_stop::FatalUpgradeError, outbound_hop::FatalUpgradeError>,
>; >;
type InboundProtocol = inbound_stop::Upgrade; type InboundProtocol = inbound_stop::Upgrade;

View File

@ -28,13 +28,12 @@ use crate::{RequestId, EMPTY_QUEUE_SHRINK_THRESHOLD};
use futures::{channel::oneshot, future::BoxFuture, prelude::*, stream::FuturesUnordered}; use futures::{channel::oneshot, future::BoxFuture, prelude::*, stream::FuturesUnordered};
use instant::Instant; use instant::Instant;
use libp2p_core::upgrade::{NegotiationError, UpgradeError};
use libp2p_swarm::handler::{ use libp2p_swarm::handler::{
ConnectionEvent, DialUpgradeError, FullyNegotiatedInbound, FullyNegotiatedOutbound, ConnectionEvent, DialUpgradeError, FullyNegotiatedInbound, FullyNegotiatedOutbound,
ListenUpgradeError, ListenUpgradeError,
}; };
use libp2p_swarm::{ use libp2p_swarm::{
handler::{ConnectionHandler, ConnectionHandlerEvent, ConnectionHandlerUpgrErr, KeepAlive}, handler::{ConnectionHandler, ConnectionHandlerEvent, KeepAlive, StreamUpgradeError},
SubstreamProtocol, SubstreamProtocol,
}; };
use smallvec::SmallVec; use smallvec::SmallVec;
@ -67,7 +66,7 @@ where
/// The current connection keep-alive. /// The current connection keep-alive.
keep_alive: KeepAlive, keep_alive: KeepAlive,
/// A pending fatal error that results in the connection being closed. /// A pending fatal error that results in the connection being closed.
pending_error: Option<ConnectionHandlerUpgrErr<io::Error>>, pending_error: Option<StreamUpgradeError<io::Error>>,
/// Queue of events to emit in `poll()`. /// Queue of events to emit in `poll()`.
pending_events: VecDeque<Event<TCodec>>, pending_events: VecDeque<Event<TCodec>>,
/// Outbound upgrades waiting to be emitted as an `OutboundSubstreamRequest`. /// Outbound upgrades waiting to be emitted as an `OutboundSubstreamRequest`.
@ -140,10 +139,10 @@ where
>, >,
) { ) {
match error { match error {
ConnectionHandlerUpgrErr::Timeout => { StreamUpgradeError::Timeout => {
self.pending_events.push_back(Event::OutboundTimeout(info)); self.pending_events.push_back(Event::OutboundTimeout(info));
} }
ConnectionHandlerUpgrErr::Upgrade(UpgradeError::Select(NegotiationError::Failed)) => { StreamUpgradeError::NegotiationFailed => {
// The remote merely doesn't support the protocol(s) we requested. // The remote merely doesn't support the protocol(s) we requested.
// This is no reason to close the connection, which may // This is no reason to close the connection, which may
// successfully communicate with other protocols already. // successfully communicate with other protocols already.
@ -166,9 +165,7 @@ where
<Self as ConnectionHandler>::InboundProtocol, <Self as ConnectionHandler>::InboundProtocol,
>, >,
) { ) {
self.pending_error = Some(ConnectionHandlerUpgrErr::Upgrade(UpgradeError::Apply( self.pending_error = Some(StreamUpgradeError::Apply(error));
error,
)));
} }
} }
@ -244,7 +241,7 @@ where
{ {
type InEvent = RequestProtocol<TCodec>; type InEvent = RequestProtocol<TCodec>;
type OutEvent = Event<TCodec>; type OutEvent = Event<TCodec>;
type Error = ConnectionHandlerUpgrErr<io::Error>; type Error = StreamUpgradeError<io::Error>;
type InboundProtocol = ResponseProtocol<TCodec>; type InboundProtocol = ResponseProtocol<TCodec>;
type OutboundProtocol = RequestProtocol<TCodec>; type OutboundProtocol = RequestProtocol<TCodec>;
type OutboundOpenInfo = RequestId; type OutboundOpenInfo = RequestId;

View File

@ -23,13 +23,20 @@
See changelog for `0.42` on how to migrate. See changelog for `0.42` on how to migrate.
See [PR 3884]. See [PR 3884].
- Remove `ConnectionHandlerUpgrErr::Timer` variant.
This variant was never constructed and thus dead code.
See [PR 3605].
- Flatten `ConnectionHandlerUpgrErr` and rename to `StreamUpgradeError`.
See [PR 3882].
[PR 3605]: https://github.com/libp2p/rust-libp2p/pull/3605
[PR 3715]: https://github.com/libp2p/rust-libp2p/pull/3715 [PR 3715]: https://github.com/libp2p/rust-libp2p/pull/3715
[PR 3746]: https://github.com/libp2p/rust-libp2p/pull/3746 [PR 3746]: https://github.com/libp2p/rust-libp2p/pull/3746
[PR 3865]: https://github.com/libp2p/rust-libp2p/pull/3865 [PR 3865]: https://github.com/libp2p/rust-libp2p/pull/3865
[PR 3886]: https://github.com/libp2p/rust-libp2p/pull/3886 [PR 3882]: https://github.com/libp2p/rust-libp2p/pull/3882
[PR 3884]: https://github.com/libp2p/rust-libp2p/pull/3884 [PR 3884]: https://github.com/libp2p/rust-libp2p/pull/3884
[PR 3605]: https://github.com/libp2p/rust-libp2p/pull/3605 [PR 3886]: https://github.com/libp2p/rust-libp2p/pull/3886
[PR 3746]: https://github.com/libp2p/rust-libp2p/pull/3746
## 0.42.2 ## 0.42.2

View File

@ -32,7 +32,7 @@ use crate::handler::{
FullyNegotiatedOutbound, ListenUpgradeError, FullyNegotiatedOutbound, ListenUpgradeError,
}; };
use crate::upgrade::{InboundUpgradeSend, OutboundUpgradeSend, SendWrapper}; use crate::upgrade::{InboundUpgradeSend, OutboundUpgradeSend, SendWrapper};
use crate::{ConnectionHandlerEvent, ConnectionHandlerUpgrErr, KeepAlive, SubstreamProtocol}; use crate::{ConnectionHandlerEvent, KeepAlive, StreamUpgradeError, SubstreamProtocol};
use futures::stream::FuturesUnordered; use futures::stream::FuturesUnordered;
use futures::FutureExt; use futures::FutureExt;
use futures::StreamExt; use futures::StreamExt;
@ -41,9 +41,11 @@ use instant::Instant;
use libp2p_core::connection::ConnectedPoint; use libp2p_core::connection::ConnectedPoint;
use libp2p_core::multiaddr::Multiaddr; use libp2p_core::multiaddr::Multiaddr;
use libp2p_core::muxing::{StreamMuxerBox, StreamMuxerEvent, StreamMuxerExt, SubstreamBox}; use libp2p_core::muxing::{StreamMuxerBox, StreamMuxerEvent, StreamMuxerExt, SubstreamBox};
use libp2p_core::upgrade::{InboundUpgradeApply, OutboundUpgradeApply}; use libp2p_core::upgrade;
use libp2p_core::upgrade::{
InboundUpgradeApply, NegotiationError, OutboundUpgradeApply, ProtocolError,
};
use libp2p_core::Endpoint; use libp2p_core::Endpoint;
use libp2p_core::{upgrade, UpgradeError};
use libp2p_identity::PeerId; use libp2p_identity::PeerId;
use std::future::Future; use std::future::Future;
use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::atomic::{AtomicUsize, Ordering};
@ -220,7 +222,7 @@ where
handler.on_connection_event(ConnectionEvent::DialUpgradeError( handler.on_connection_event(ConnectionEvent::DialUpgradeError(
DialUpgradeError { DialUpgradeError {
info, info,
error: ConnectionHandlerUpgrErr::Timeout, error: StreamUpgradeError::Timeout,
}, },
)); ));
continue; continue;
@ -273,23 +275,21 @@ where
)); ));
continue; continue;
} }
Poll::Ready(Some(( Poll::Ready(Some((info, Err(StreamUpgradeError::Apply(error))))) => {
info,
Err(ConnectionHandlerUpgrErr::Upgrade(UpgradeError::Apply(error))),
))) => {
handler.on_connection_event(ConnectionEvent::ListenUpgradeError( handler.on_connection_event(ConnectionEvent::ListenUpgradeError(
ListenUpgradeError { info, error }, ListenUpgradeError { info, error },
)); ));
continue; continue;
} }
Poll::Ready(Some(( Poll::Ready(Some((_, Err(StreamUpgradeError::Io(e))))) => {
_,
Err(ConnectionHandlerUpgrErr::Upgrade(UpgradeError::Select(e))),
))) => {
log::debug!("failed to upgrade inbound stream: {e}"); log::debug!("failed to upgrade inbound stream: {e}");
continue; continue;
} }
Poll::Ready(Some((_, Err(ConnectionHandlerUpgrErr::Timeout)))) => { Poll::Ready(Some((_, Err(StreamUpgradeError::NegotiationFailed)))) => {
log::debug!("no protocol could be agreed upon for inbound stream");
continue;
}
Poll::Ready(Some((_, Err(StreamUpgradeError::Timeout)))) => {
log::debug!("inbound stream upgrade timed out"); log::debug!("inbound stream upgrade timed out");
continue; continue;
} }
@ -488,11 +488,11 @@ impl<UserData, Upgrade> Unpin for SubstreamUpgrade<UserData, Upgrade> {}
impl<UserData, Upgrade, UpgradeOutput, TUpgradeError> Future for SubstreamUpgrade<UserData, Upgrade> impl<UserData, Upgrade, UpgradeOutput, TUpgradeError> Future for SubstreamUpgrade<UserData, Upgrade>
where where
Upgrade: Future<Output = Result<UpgradeOutput, UpgradeError<TUpgradeError>>> + Unpin, Upgrade: Future<Output = Result<UpgradeOutput, upgrade::UpgradeError<TUpgradeError>>> + Unpin,
{ {
type Output = ( type Output = (
UserData, UserData,
Result<UpgradeOutput, ConnectionHandlerUpgrErr<TUpgradeError>>, Result<UpgradeOutput, StreamUpgradeError<TUpgradeError>>,
); );
fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> { fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
@ -502,28 +502,34 @@ where
self.user_data self.user_data
.take() .take()
.expect("Future not to be polled again once ready."), .expect("Future not to be polled again once ready."),
Err(ConnectionHandlerUpgrErr::Timeout), Err(StreamUpgradeError::Timeout),
)) ))
} }
Poll::Pending => {} Poll::Pending => {}
} }
match self.upgrade.poll_unpin(cx) { let result = futures::ready!(self.upgrade.poll_unpin(cx));
Poll::Ready(Ok(upgrade)) => Poll::Ready(( let user_data = self
self.user_data .user_data
.take() .take()
.expect("Future not to be polled again once ready."), .expect("Future not to be polled again once ready.");
Ok(upgrade),
)), Poll::Ready((
Poll::Ready(Err(err)) => Poll::Ready(( user_data,
self.user_data result.map_err(|e| match e {
.take() upgrade::UpgradeError::Select(NegotiationError::Failed) => {
.expect("Future not to be polled again once ready."), StreamUpgradeError::NegotiationFailed
Err(ConnectionHandlerUpgrErr::Upgrade(err)), }
)), upgrade::UpgradeError::Select(NegotiationError::ProtocolError(
Poll::Pending => Poll::Pending, ProtocolError::IoError(e),
} )) => StreamUpgradeError::Io(e),
upgrade::UpgradeError::Select(NegotiationError::ProtocolError(other)) => {
StreamUpgradeError::Io(io::Error::new(io::ErrorKind::Other, other))
}
upgrade::UpgradeError::Apply(e) => StreamUpgradeError::Apply(e),
}),
))
} }
} }
@ -683,7 +689,7 @@ mod tests {
assert!(matches!( assert!(matches!(
connection.handler.error.unwrap(), connection.handler.error.unwrap(),
ConnectionHandlerUpgrErr::Timeout StreamUpgradeError::Timeout
)) ))
} }
@ -786,7 +792,7 @@ mod tests {
struct MockConnectionHandler { struct MockConnectionHandler {
outbound_requested: bool, outbound_requested: bool,
error: Option<ConnectionHandlerUpgrErr<Void>>, error: Option<StreamUpgradeError<Void>>,
upgrade_timeout: Duration, upgrade_timeout: Duration,
} }

View File

@ -4,12 +4,12 @@ use crate::handler::{
ConnectionEvent, DialUpgradeError, FullyNegotiatedInbound, FullyNegotiatedOutbound, ConnectionEvent, DialUpgradeError, FullyNegotiatedInbound, FullyNegotiatedOutbound,
}; };
use crate::{ use crate::{
ConnectionDenied, ConnectionHandlerEvent, ConnectionHandlerUpgrErr, KeepAlive, ConnectionDenied, ConnectionHandlerEvent, KeepAlive, StreamUpgradeError, SubstreamProtocol,
SubstreamProtocol, THandler, THandlerInEvent, THandlerOutEvent, THandler, THandlerInEvent, THandlerOutEvent,
}; };
use libp2p_core::upgrade::DeniedUpgrade; use libp2p_core::upgrade::DeniedUpgrade;
use libp2p_core::Endpoint; use libp2p_core::Endpoint;
use libp2p_core::{Multiaddr, UpgradeError}; use libp2p_core::Multiaddr;
use libp2p_identity::PeerId; use libp2p_identity::PeerId;
use std::task::{Context, Poll}; use std::task::{Context, Poll};
use void::Void; use void::Void;
@ -132,9 +132,9 @@ impl crate::handler::ConnectionHandler for ConnectionHandler {
protocol, .. protocol, ..
}) => void::unreachable(protocol), }) => void::unreachable(protocol),
ConnectionEvent::DialUpgradeError(DialUpgradeError { info: _, error }) => match error { ConnectionEvent::DialUpgradeError(DialUpgradeError { info: _, error }) => match error {
ConnectionHandlerUpgrErr::Timeout => unreachable!(), StreamUpgradeError::Timeout => unreachable!(),
ConnectionHandlerUpgrErr::Upgrade(UpgradeError::Apply(e)) => void::unreachable(e), StreamUpgradeError::Apply(e) => void::unreachable(e),
ConnectionHandlerUpgrErr::Upgrade(UpgradeError::Select(_)) => { StreamUpgradeError::NegotiationFailed | StreamUpgradeError::Io(_) => {
unreachable!("Denied upgrade does not support any protocols") unreachable!("Denied upgrade does not support any protocols")
} }
}, },

View File

@ -49,8 +49,8 @@ mod select;
pub use crate::upgrade::{InboundUpgradeSend, OutboundUpgradeSend, SendWrapper, UpgradeInfoSend}; pub use crate::upgrade::{InboundUpgradeSend, OutboundUpgradeSend, SendWrapper, UpgradeInfoSend};
use instant::Instant; use instant::Instant;
use libp2p_core::{upgrade::UpgradeError, Multiaddr}; use libp2p_core::Multiaddr;
use std::{cmp::Ordering, error, fmt, task::Context, task::Poll, time::Duration}; use std::{cmp::Ordering, error, fmt, io, task::Context, task::Poll, time::Duration};
pub use map_in::MapInEvent; pub use map_in::MapInEvent;
pub use map_out::MapOutEvent; pub use map_out::MapOutEvent;
@ -270,7 +270,7 @@ pub struct AddressChange<'a> {
/// that upgrading an outbound substream to the given protocol has failed. /// that upgrading an outbound substream to the given protocol has failed.
pub struct DialUpgradeError<OOI, OP: OutboundUpgradeSend> { pub struct DialUpgradeError<OOI, OP: OutboundUpgradeSend> {
pub info: OOI, pub info: OOI,
pub error: ConnectionHandlerUpgrErr<OP::Error>, pub error: StreamUpgradeError<OP::Error>,
} }
/// [`ConnectionEvent`] variant that informs the handler /// [`ConnectionEvent`] variant that informs the handler
@ -458,54 +458,67 @@ impl<TConnectionUpgrade, TOutboundOpenInfo, TCustom, TErr>
} }
} }
#[deprecated(note = "Renamed to `StreamUpgradeError`")]
pub type ConnectionHandlerUpgrErr<TUpgrErr> = StreamUpgradeError<TUpgrErr>;
/// Error that can happen on an outbound substream opening attempt. /// Error that can happen on an outbound substream opening attempt.
#[derive(Debug)] #[derive(Debug)]
pub enum ConnectionHandlerUpgrErr<TUpgrErr> { pub enum StreamUpgradeError<TUpgrErr> {
/// The opening attempt timed out before the negotiation was fully completed. /// The opening attempt timed out before the negotiation was fully completed.
Timeout, Timeout,
/// Error while upgrading the substream to the protocol we want. /// The upgrade produced an error.
Upgrade(UpgradeError<TUpgrErr>), Apply(TUpgrErr),
/// No protocol could be agreed upon.
NegotiationFailed,
/// An IO or otherwise unrecoverable error happened.
Io(io::Error),
} }
impl<TUpgrErr> ConnectionHandlerUpgrErr<TUpgrErr> { impl<TUpgrErr> StreamUpgradeError<TUpgrErr> {
/// Map the inner [`UpgradeError`] type. /// Map the inner [`StreamUpgradeError`] type.
pub fn map_upgrade_err<F, E>(self, f: F) -> ConnectionHandlerUpgrErr<E> pub fn map_upgrade_err<F, E>(self, f: F) -> StreamUpgradeError<E>
where where
F: FnOnce(UpgradeError<TUpgrErr>) -> UpgradeError<E>, F: FnOnce(TUpgrErr) -> E,
{ {
match self { match self {
ConnectionHandlerUpgrErr::Timeout => ConnectionHandlerUpgrErr::Timeout, StreamUpgradeError::Timeout => StreamUpgradeError::Timeout,
ConnectionHandlerUpgrErr::Upgrade(e) => ConnectionHandlerUpgrErr::Upgrade(f(e)), StreamUpgradeError::Apply(e) => StreamUpgradeError::Apply(f(e)),
StreamUpgradeError::NegotiationFailed => StreamUpgradeError::NegotiationFailed,
StreamUpgradeError::Io(e) => StreamUpgradeError::Io(e),
} }
} }
} }
impl<TUpgrErr> fmt::Display for ConnectionHandlerUpgrErr<TUpgrErr> impl<TUpgrErr> fmt::Display for StreamUpgradeError<TUpgrErr>
where where
TUpgrErr: error::Error + 'static, TUpgrErr: error::Error + 'static,
{ {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self { match self {
ConnectionHandlerUpgrErr::Timeout => { StreamUpgradeError::Timeout => {
write!(f, "Timeout error while opening a substream") write!(f, "Timeout error while opening a substream")
} }
ConnectionHandlerUpgrErr::Upgrade(err) => { StreamUpgradeError::Apply(err) => {
write!(f, "Upgrade: ")?; write!(f, "Apply: ")?;
crate::print_error_chain(f, err) crate::print_error_chain(f, err)
} }
StreamUpgradeError::NegotiationFailed => {
write!(f, "no protocols could be agreed upon")
}
StreamUpgradeError::Io(e) => {
write!(f, "IO error: ")?;
crate::print_error_chain(f, e)
}
} }
} }
} }
impl<TUpgrErr> error::Error for ConnectionHandlerUpgrErr<TUpgrErr> impl<TUpgrErr> error::Error for StreamUpgradeError<TUpgrErr>
where where
TUpgrErr: error::Error + 'static, TUpgrErr: error::Error + 'static,
{ {
fn source(&self) -> Option<&(dyn error::Error + 'static)> { fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match self { None
ConnectionHandlerUpgrErr::Timeout => None,
ConnectionHandlerUpgrErr::Upgrade(_) => None,
}
} }
} }

View File

@ -19,8 +19,8 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
use crate::handler::{ use crate::handler::{
ConnectionEvent, ConnectionHandler, ConnectionHandlerEvent, ConnectionHandlerUpgrErr, ConnectionEvent, ConnectionHandler, ConnectionHandlerEvent, DialUpgradeError,
DialUpgradeError, FullyNegotiatedInbound, FullyNegotiatedOutbound, KeepAlive, FullyNegotiatedInbound, FullyNegotiatedOutbound, KeepAlive, StreamUpgradeError,
SubstreamProtocol, SubstreamProtocol,
}; };
use crate::upgrade::{InboundUpgradeSend, OutboundUpgradeSend}; use crate::upgrade::{InboundUpgradeSend, OutboundUpgradeSend};
@ -37,7 +37,7 @@ where
/// The upgrade for inbound substreams. /// The upgrade for inbound substreams.
listen_protocol: SubstreamProtocol<TInbound, ()>, listen_protocol: SubstreamProtocol<TInbound, ()>,
/// If `Some`, something bad happened and we should shut down the handler with an error. /// If `Some`, something bad happened and we should shut down the handler with an error.
pending_error: Option<ConnectionHandlerUpgrErr<<TOutbound as OutboundUpgradeSend>::Error>>, pending_error: Option<StreamUpgradeError<<TOutbound as OutboundUpgradeSend>::Error>>,
/// Queue of events to produce in `poll()`. /// Queue of events to produce in `poll()`.
events_out: SmallVec<[TEvent; 4]>, events_out: SmallVec<[TEvent; 4]>,
/// Queue of outbound substreams to open. /// Queue of outbound substreams to open.
@ -123,7 +123,7 @@ where
{ {
type InEvent = TOutbound; type InEvent = TOutbound;
type OutEvent = TEvent; type OutEvent = TEvent;
type Error = ConnectionHandlerUpgrErr<<Self::OutboundProtocol as OutboundUpgradeSend>::Error>; type Error = StreamUpgradeError<<Self::OutboundProtocol as OutboundUpgradeSend>::Error>;
type InboundProtocol = TInbound; type InboundProtocol = TInbound;
type OutboundProtocol = TOutbound; type OutboundProtocol = TOutbound;
type OutboundOpenInfo = (); type OutboundOpenInfo = ();

View File

@ -19,14 +19,14 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
use crate::handler::{ use crate::handler::{
AddressChange, ConnectionEvent, ConnectionHandler, ConnectionHandlerEvent, AddressChange, ConnectionEvent, ConnectionHandler, ConnectionHandlerEvent, DialUpgradeError,
ConnectionHandlerUpgrErr, DialUpgradeError, FullyNegotiatedInbound, FullyNegotiatedOutbound, FullyNegotiatedInbound, FullyNegotiatedOutbound, InboundUpgradeSend, KeepAlive,
InboundUpgradeSend, KeepAlive, ListenUpgradeError, OutboundUpgradeSend, SubstreamProtocol, ListenUpgradeError, OutboundUpgradeSend, StreamUpgradeError, SubstreamProtocol,
}; };
use crate::upgrade::SendWrapper; use crate::upgrade::SendWrapper;
use either::Either; use either::Either;
use futures::future; use futures::future;
use libp2p_core::upgrade::{SelectUpgrade, UpgradeError}; use libp2p_core::upgrade::SelectUpgrade;
use std::{cmp, task::Context, task::Poll}; use std::{cmp, task::Context, task::Poll};
/// Implementation of [`ConnectionHandler`] that combines two protocols into one. /// Implementation of [`ConnectionHandler`] that combines two protocols into one.
@ -110,47 +110,32 @@ where
match self { match self {
DialUpgradeError { DialUpgradeError {
info: Either::Left(info), info: Either::Left(info),
error: ConnectionHandlerUpgrErr::Timeout, error: StreamUpgradeError::Apply(Either::Left(err)),
} => Either::Left(DialUpgradeError { } => Either::Left(DialUpgradeError {
info, info,
error: ConnectionHandlerUpgrErr::Timeout, error: StreamUpgradeError::Apply(err),
}),
DialUpgradeError {
info: Either::Right(info),
error: StreamUpgradeError::Apply(Either::Right(err)),
} => Either::Right(DialUpgradeError {
info,
error: StreamUpgradeError::Apply(err),
}), }),
DialUpgradeError { DialUpgradeError {
info: Either::Left(info), info: Either::Left(info),
error: ConnectionHandlerUpgrErr::Upgrade(UpgradeError::Select(err)), error: e,
} => Either::Left(DialUpgradeError { } => Either::Left(DialUpgradeError {
info, info,
error: ConnectionHandlerUpgrErr::Upgrade(UpgradeError::Select(err)), error: e.map_upgrade_err(|_| panic!("already handled above")),
}),
DialUpgradeError {
info: Either::Left(info),
error: ConnectionHandlerUpgrErr::Upgrade(UpgradeError::Apply(Either::Left(err))),
} => Either::Left(DialUpgradeError {
info,
error: ConnectionHandlerUpgrErr::Upgrade(UpgradeError::Apply(err)),
}), }),
DialUpgradeError { DialUpgradeError {
info: Either::Right(info), info: Either::Right(info),
error: ConnectionHandlerUpgrErr::Timeout, error: e,
} => Either::Right(DialUpgradeError { } => Either::Right(DialUpgradeError {
info, info,
error: ConnectionHandlerUpgrErr::Timeout, error: e.map_upgrade_err(|_| panic!("already handled above")),
}), }),
DialUpgradeError {
info: Either::Right(info),
error: ConnectionHandlerUpgrErr::Upgrade(UpgradeError::Select(err)),
} => Either::Right(DialUpgradeError {
info,
error: ConnectionHandlerUpgrErr::Upgrade(UpgradeError::Select(err)),
}),
DialUpgradeError {
info: Either::Right(info),
error: ConnectionHandlerUpgrErr::Upgrade(UpgradeError::Apply(Either::Right(err))),
} => Either::Right(DialUpgradeError {
info,
error: ConnectionHandlerUpgrErr::Upgrade(UpgradeError::Apply(err)),
}),
_ => panic!("Wrong API usage; the upgrade error doesn't match the outbound open info"),
} }
} }
} }

View File

@ -122,8 +122,8 @@ pub use connection::pool::{ConnectionCounters, ConnectionLimits};
pub use connection::{ConnectionError, ConnectionId}; pub use connection::{ConnectionError, ConnectionId};
pub use executor::Executor; pub use executor::Executor;
pub use handler::{ pub use handler::{
ConnectionHandler, ConnectionHandlerEvent, ConnectionHandlerSelect, ConnectionHandlerUpgrErr, ConnectionHandler, ConnectionHandlerEvent, ConnectionHandlerSelect, KeepAlive, OneShotHandler,
KeepAlive, OneShotHandler, OneShotHandlerConfig, SubstreamProtocol, OneShotHandlerConfig, StreamUpgradeError, SubstreamProtocol,
}; };
#[cfg(feature = "macros")] #[cfg(feature = "macros")]
pub use libp2p_swarm_derive::NetworkBehaviour; pub use libp2p_swarm_derive::NetworkBehaviour;