Skip to content

Commit adf31c8

Browse files
committed
misc/multistream-select: Fail negotiation for all Poll::Ready(None)
1 parent b332e03 commit adf31c8

File tree

2 files changed

+22
-17
lines changed

2 files changed

+22
-17
lines changed

misc/multistream-select/src/dialer_select.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use crate::{Negotiated, NegotiationError};
2424
use crate::protocol::{Protocol, ProtocolError, MessageIO, Message, Version};
2525

2626
use futures::{future::Either, prelude::*};
27-
use std::{convert::TryFrom as _, io, iter, mem, pin::Pin, task::{Context, Poll}};
27+
use std::{convert::TryFrom as _, iter, mem, pin::Pin, task::{Context, Poll}};
2828

2929
/// Returns a `Future` that negotiates a protocol on the given I/O stream
3030
/// for a peer acting as the _dialer_ (or _initiator_).
@@ -235,9 +235,10 @@ where
235235
*this.state = SeqState::AwaitProtocol { io, protocol };
236236
return Poll::Pending
237237
}
238-
Poll::Ready(None) =>
239-
return Poll::Ready(Err(NegotiationError::from(
240-
io::Error::from(io::ErrorKind::UnexpectedEof)))),
238+
// Treat EOF error as [`NegotiationError::Failed`], not as
239+
// [`NegotiationError::ProtocolError`], allowing dropping or closing an I/O
240+
// stream as a permissible way to "gracefully" fail a negotiation.
241+
Poll::Ready(None) => return Poll::Ready(Err(NegotiationError::Failed)),
241242
};
242243

243244
match msg {
@@ -358,9 +359,10 @@ where
358359
*this.state = ParState::RecvProtocols { io };
359360
return Poll::Pending
360361
}
361-
Poll::Ready(None) =>
362-
return Poll::Ready(Err(NegotiationError::from(
363-
io::Error::from(io::ErrorKind::UnexpectedEof)))),
362+
// Treat EOF error as [`NegotiationError::Failed`], not as
363+
// [`NegotiationError::ProtocolError`], allowing dropping or closing an I/O
364+
// stream as a permissible way to "gracefully" fail a negotiation.
365+
Poll::Ready(None) => return Poll::Ready(Err(NegotiationError::Failed)),
364366
};
365367

366368
match &msg {

misc/multistream-select/src/listener_select.rs

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use crate::protocol::{Protocol, ProtocolError, MessageIO, Message, Version};
2626

2727
use futures::prelude::*;
2828
use smallvec::SmallVec;
29-
use std::{convert::TryFrom as _, io, iter::FromIterator, mem, pin::Pin, task::{Context, Poll}};
29+
use std::{convert::TryFrom as _, iter::FromIterator, mem, pin::Pin, task::{Context, Poll}};
3030

3131
/// Returns a `Future` that negotiates a protocol on the given I/O stream
3232
/// for a peer acting as the _listener_ (or _responder_).
@@ -118,10 +118,10 @@ where
118118
return Poll::Ready(Err(ProtocolError::InvalidMessage.into()))
119119
},
120120
Poll::Ready(Some(Err(err))) => return Poll::Ready(Err(From::from(err))),
121-
Poll::Ready(None) =>
122-
return Poll::Ready(Err(NegotiationError::from(
123-
ProtocolError::IoError(
124-
io::ErrorKind::UnexpectedEof.into())))),
121+
// Treat EOF error as [`NegotiationError::Failed`], not as
122+
// [`NegotiationError::ProtocolError`], allowing dropping or closing an I/O
123+
// stream as a permissible way to "gracefully" fail a negotiation.
124+
Poll::Ready(None) => return Poll::Ready(Err(NegotiationError::Failed)),
125125
Poll::Pending => {
126126
*this.state = State::RecvHeader { io };
127127
return Poll::Pending
@@ -153,11 +153,14 @@ where
153153
let msg = match Pin::new(&mut io).poll_next(cx) {
154154
Poll::Ready(Some(Ok(msg))) => msg,
155155
// Treat EOF error as [`NegotiationError::Failed`], not as
156-
// [`NegotiationError::ProtocolError`]. This is e.g. important when a
157-
// listener rejects a protocol with [`Message::NotAvailable`] and the dialer
158-
// does not have alternative protocols to propose. Then the dialer will stop
159-
// the negotiation and drop the corresponding stream. As a listener this EOF
160-
// should be interpreted as a failed negotiation.
156+
// [`NegotiationError::ProtocolError`], allowing dropping or closing an I/O
157+
// stream as a permissible way to "gracefully" fail a negotiation.
158+
//
159+
// This is e.g. important when a listener rejects a protocol with
160+
// [`Message::NotAvailable`] and the dialer does not have alternative
161+
// protocols to propose. Then the dialer will stop the negotiation and drop
162+
// the corresponding stream. As a listener this EOF should be interpreted as
163+
// a failed negotiation.
161164
Poll::Ready(None) => return Poll::Ready(Err(NegotiationError::Failed)),
162165
Poll::Pending => {
163166
*this.state = State::RecvMessage { io };

0 commit comments

Comments
 (0)