mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-06-28 01:01:34 +00:00
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:
@ -32,7 +32,7 @@ use crate::handler::{
|
||||
FullyNegotiatedOutbound, ListenUpgradeError,
|
||||
};
|
||||
use crate::upgrade::{InboundUpgradeSend, OutboundUpgradeSend, SendWrapper};
|
||||
use crate::{ConnectionHandlerEvent, ConnectionHandlerUpgrErr, KeepAlive, SubstreamProtocol};
|
||||
use crate::{ConnectionHandlerEvent, KeepAlive, StreamUpgradeError, SubstreamProtocol};
|
||||
use futures::stream::FuturesUnordered;
|
||||
use futures::FutureExt;
|
||||
use futures::StreamExt;
|
||||
@ -41,9 +41,11 @@ use instant::Instant;
|
||||
use libp2p_core::connection::ConnectedPoint;
|
||||
use libp2p_core::multiaddr::Multiaddr;
|
||||
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::{upgrade, UpgradeError};
|
||||
use libp2p_identity::PeerId;
|
||||
use std::future::Future;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
@ -220,7 +222,7 @@ where
|
||||
handler.on_connection_event(ConnectionEvent::DialUpgradeError(
|
||||
DialUpgradeError {
|
||||
info,
|
||||
error: ConnectionHandlerUpgrErr::Timeout,
|
||||
error: StreamUpgradeError::Timeout,
|
||||
},
|
||||
));
|
||||
continue;
|
||||
@ -273,23 +275,21 @@ where
|
||||
));
|
||||
continue;
|
||||
}
|
||||
Poll::Ready(Some((
|
||||
info,
|
||||
Err(ConnectionHandlerUpgrErr::Upgrade(UpgradeError::Apply(error))),
|
||||
))) => {
|
||||
Poll::Ready(Some((info, Err(StreamUpgradeError::Apply(error))))) => {
|
||||
handler.on_connection_event(ConnectionEvent::ListenUpgradeError(
|
||||
ListenUpgradeError { info, error },
|
||||
));
|
||||
continue;
|
||||
}
|
||||
Poll::Ready(Some((
|
||||
_,
|
||||
Err(ConnectionHandlerUpgrErr::Upgrade(UpgradeError::Select(e))),
|
||||
))) => {
|
||||
Poll::Ready(Some((_, Err(StreamUpgradeError::Io(e))))) => {
|
||||
log::debug!("failed to upgrade inbound stream: {e}");
|
||||
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");
|
||||
continue;
|
||||
}
|
||||
@ -488,11 +488,11 @@ impl<UserData, Upgrade> Unpin for SubstreamUpgrade<UserData, Upgrade> {}
|
||||
|
||||
impl<UserData, Upgrade, UpgradeOutput, TUpgradeError> Future for SubstreamUpgrade<UserData, Upgrade>
|
||||
where
|
||||
Upgrade: Future<Output = Result<UpgradeOutput, UpgradeError<TUpgradeError>>> + Unpin,
|
||||
Upgrade: Future<Output = Result<UpgradeOutput, upgrade::UpgradeError<TUpgradeError>>> + Unpin,
|
||||
{
|
||||
type Output = (
|
||||
UserData,
|
||||
Result<UpgradeOutput, ConnectionHandlerUpgrErr<TUpgradeError>>,
|
||||
Result<UpgradeOutput, StreamUpgradeError<TUpgradeError>>,
|
||||
);
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||
@ -502,28 +502,34 @@ where
|
||||
self.user_data
|
||||
.take()
|
||||
.expect("Future not to be polled again once ready."),
|
||||
Err(ConnectionHandlerUpgrErr::Timeout),
|
||||
Err(StreamUpgradeError::Timeout),
|
||||
))
|
||||
}
|
||||
|
||||
Poll::Pending => {}
|
||||
}
|
||||
|
||||
match self.upgrade.poll_unpin(cx) {
|
||||
Poll::Ready(Ok(upgrade)) => Poll::Ready((
|
||||
self.user_data
|
||||
.take()
|
||||
.expect("Future not to be polled again once ready."),
|
||||
Ok(upgrade),
|
||||
)),
|
||||
Poll::Ready(Err(err)) => Poll::Ready((
|
||||
self.user_data
|
||||
.take()
|
||||
.expect("Future not to be polled again once ready."),
|
||||
Err(ConnectionHandlerUpgrErr::Upgrade(err)),
|
||||
)),
|
||||
Poll::Pending => Poll::Pending,
|
||||
}
|
||||
let result = futures::ready!(self.upgrade.poll_unpin(cx));
|
||||
let user_data = self
|
||||
.user_data
|
||||
.take()
|
||||
.expect("Future not to be polled again once ready.");
|
||||
|
||||
Poll::Ready((
|
||||
user_data,
|
||||
result.map_err(|e| match e {
|
||||
upgrade::UpgradeError::Select(NegotiationError::Failed) => {
|
||||
StreamUpgradeError::NegotiationFailed
|
||||
}
|
||||
upgrade::UpgradeError::Select(NegotiationError::ProtocolError(
|
||||
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!(
|
||||
connection.handler.error.unwrap(),
|
||||
ConnectionHandlerUpgrErr::Timeout
|
||||
StreamUpgradeError::Timeout
|
||||
))
|
||||
}
|
||||
|
||||
@ -786,7 +792,7 @@ mod tests {
|
||||
|
||||
struct MockConnectionHandler {
|
||||
outbound_requested: bool,
|
||||
error: Option<ConnectionHandlerUpgrErr<Void>>,
|
||||
error: Option<StreamUpgradeError<Void>>,
|
||||
upgrade_timeout: Duration,
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user