misc/multistream-select: Interpretation of EOF as Failed negotiation (#1823)

Treat EOF error as [`NegotiationError::Failed`], not as
[`NegotiationError::ProtocolError`], allowing dropping or closing an I/O stream
as a permissible way to "gracefully" fail a negotiation.

This is e.g. important when a listener rejects a protocol with
[`Message::NotAvailable`] and the dialer does not have alternative protocols to
propose. Then the dialer will stop the negotiation and drop the corresponding
stream. As a listener this EOF should be interpreted as a failed negotiation.
This commit is contained in:
Max Inden
2020-11-09 16:04:00 +01:00
committed by GitHub
parent 3859116bca
commit 70bb2d7c11
6 changed files with 33 additions and 21 deletions

View File

@@ -24,7 +24,7 @@ use crate::{Negotiated, NegotiationError};
use crate::protocol::{Protocol, ProtocolError, MessageIO, Message, Version};
use futures::{future::Either, prelude::*};
use std::{convert::TryFrom as _, io, iter, mem, pin::Pin, task::{Context, Poll}};
use std::{convert::TryFrom as _, iter, mem, pin::Pin, task::{Context, Poll}};
/// Returns a `Future` that negotiates a protocol on the given I/O stream
/// for a peer acting as the _dialer_ (or _initiator_).
@@ -235,9 +235,10 @@ where
*this.state = SeqState::AwaitProtocol { io, protocol };
return Poll::Pending
}
Poll::Ready(None) =>
return Poll::Ready(Err(NegotiationError::from(
io::Error::from(io::ErrorKind::UnexpectedEof)))),
// Treat EOF error as [`NegotiationError::Failed`], not as
// [`NegotiationError::ProtocolError`], allowing dropping or closing an I/O
// stream as a permissible way to "gracefully" fail a negotiation.
Poll::Ready(None) => return Poll::Ready(Err(NegotiationError::Failed)),
};
match msg {
@@ -358,9 +359,10 @@ where
*this.state = ParState::RecvProtocols { io };
return Poll::Pending
}
Poll::Ready(None) =>
return Poll::Ready(Err(NegotiationError::from(
io::Error::from(io::ErrorKind::UnexpectedEof)))),
// Treat EOF error as [`NegotiationError::Failed`], not as
// [`NegotiationError::ProtocolError`], allowing dropping or closing an I/O
// stream as a permissible way to "gracefully" fail a negotiation.
Poll::Ready(None) => return Poll::Ready(Err(NegotiationError::Failed)),
};
match &msg {