mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-06-29 09:41:34 +00:00
Cleaner shutdown process (#992)
* Cleaner shutdown process * Finish * Fix Yamux panic * Remove irrelevant tests * Update core/src/nodes/handled_node_tasks.rs Co-Authored-By: tomaka <pierre.krieger1708@gmail.com> * Fix yamux error handling * Update yamux
This commit is contained in:
@ -33,7 +33,6 @@ use void::Void;
|
||||
|
||||
/// Implementation of `ProtocolsHandler` that doesn't handle anything.
|
||||
pub struct DummyProtocolsHandler<TSubstream> {
|
||||
shutting_down: bool,
|
||||
marker: PhantomData<TSubstream>,
|
||||
}
|
||||
|
||||
@ -41,7 +40,6 @@ impl<TSubstream> Default for DummyProtocolsHandler<TSubstream> {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
DummyProtocolsHandler {
|
||||
shutting_down: false,
|
||||
marker: PhantomData,
|
||||
}
|
||||
}
|
||||
@ -85,17 +83,9 @@ where
|
||||
#[inline]
|
||||
fn inject_dial_upgrade_error(&mut self, _: Self::OutboundOpenInfo, _: ProtocolsHandlerUpgrErr<<Self::OutboundProtocol as OutboundUpgrade<Self::Substream>>::Error>) {}
|
||||
|
||||
#[inline]
|
||||
fn inject_inbound_closed(&mut self) {}
|
||||
|
||||
#[inline]
|
||||
fn connection_keep_alive(&self) -> KeepAlive { KeepAlive::Now }
|
||||
|
||||
#[inline]
|
||||
fn shutdown(&mut self) {
|
||||
self.shutting_down = true;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn poll(
|
||||
&mut self,
|
||||
@ -103,10 +93,6 @@ where
|
||||
ProtocolsHandlerEvent<Self::OutboundProtocol, Self::OutboundOpenInfo, Self::OutEvent>,
|
||||
Void,
|
||||
> {
|
||||
if self.shutting_down {
|
||||
Ok(Async::Ready(ProtocolsHandlerEvent::Shutdown))
|
||||
} else {
|
||||
Ok(Async::NotReady)
|
||||
}
|
||||
Ok(Async::NotReady)
|
||||
}
|
||||
}
|
||||
|
@ -1,205 +0,0 @@
|
||||
// Copyright 2019 Parity Technologies (UK) Ltd.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
use crate::{
|
||||
either::EitherOutput,
|
||||
protocols_handler::{KeepAlive, ProtocolsHandler, ProtocolsHandlerEvent, ProtocolsHandlerUpgrErr},
|
||||
upgrade::{
|
||||
DeniedUpgrade,
|
||||
EitherUpgrade,
|
||||
InboundUpgrade,
|
||||
OutboundUpgrade,
|
||||
}
|
||||
};
|
||||
use futures::prelude::*;
|
||||
use std::mem;
|
||||
|
||||
/// Wrapper around a protocol handler and ignores all further method calls once it has shut down.
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct Fuse<TProtoHandler> {
|
||||
inner: State<TProtoHandler>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
enum State<TProtoHandler> {
|
||||
Normal(TProtoHandler),
|
||||
ShuttingDown(TProtoHandler),
|
||||
Shutdown,
|
||||
}
|
||||
|
||||
impl<TProtoHandler> State<TProtoHandler> {
|
||||
fn as_ref(&self) -> Option<&TProtoHandler> {
|
||||
match self {
|
||||
State::Normal(h) => Some(h),
|
||||
State::ShuttingDown(h) => Some(h),
|
||||
State::Shutdown => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn as_mut(&mut self) -> Option<&mut TProtoHandler> {
|
||||
match self {
|
||||
State::Normal(h) => Some(h),
|
||||
State::ShuttingDown(h) => Some(h),
|
||||
State::Shutdown => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<TProtoHandler> Fuse<TProtoHandler> {
|
||||
/// Creates a `Fuse`.
|
||||
#[inline]
|
||||
pub(crate) fn new(inner: TProtoHandler) -> Self {
|
||||
Fuse {
|
||||
inner: State::Normal(inner),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if `shutdown()` has been called in the past, or if polling has returned
|
||||
/// `Shutdown` in the past.
|
||||
pub fn is_shutting_down_or_shutdown(&self) -> bool {
|
||||
match self.inner {
|
||||
State::Normal(_) => false,
|
||||
State::ShuttingDown(_) => true,
|
||||
State::Shutdown => true,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if polling has returned `Shutdown` in the past.
|
||||
#[inline]
|
||||
pub fn is_shutdown(&self) -> bool {
|
||||
if let State::Shutdown = self.inner {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<TProtoHandler> ProtocolsHandler for Fuse<TProtoHandler>
|
||||
where
|
||||
TProtoHandler: ProtocolsHandler,
|
||||
{
|
||||
type InEvent = TProtoHandler::InEvent;
|
||||
type OutEvent = TProtoHandler::OutEvent;
|
||||
type Error = TProtoHandler::Error;
|
||||
type Substream = TProtoHandler::Substream;
|
||||
type InboundProtocol = EitherUpgrade<TProtoHandler::InboundProtocol, DeniedUpgrade>;
|
||||
type OutboundProtocol = TProtoHandler::OutboundProtocol;
|
||||
type OutboundOpenInfo = TProtoHandler::OutboundOpenInfo;
|
||||
|
||||
#[inline]
|
||||
fn listen_protocol(&self) -> Self::InboundProtocol {
|
||||
if let Some(inner) = self.inner.as_ref() {
|
||||
EitherUpgrade::A(inner.listen_protocol())
|
||||
} else {
|
||||
EitherUpgrade::B(DeniedUpgrade)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inject_fully_negotiated_inbound(
|
||||
&mut self,
|
||||
protocol: <Self::InboundProtocol as InboundUpgrade<Self::Substream>>::Output
|
||||
) {
|
||||
match (protocol, self.inner.as_mut()) {
|
||||
(EitherOutput::First(proto), Some(inner)) => {
|
||||
inner.inject_fully_negotiated_inbound(proto)
|
||||
},
|
||||
(EitherOutput::Second(_), None) => {}
|
||||
(EitherOutput::First(_), None) => {} // Can happen if we shut down during an upgrade.
|
||||
(EitherOutput::Second(_), Some(_)) => {
|
||||
panic!("Wrong API usage; an upgrade was passed to a different object that the \
|
||||
one that asked for the upgrade")
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inject_fully_negotiated_outbound(
|
||||
&mut self,
|
||||
protocol: <Self::OutboundProtocol as OutboundUpgrade<Self::Substream>>::Output,
|
||||
info: Self::OutboundOpenInfo
|
||||
) {
|
||||
if let Some(inner) = self.inner.as_mut() {
|
||||
inner.inject_fully_negotiated_outbound(protocol, info)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inject_event(&mut self, event: Self::InEvent) {
|
||||
if let Some(inner) = self.inner.as_mut() {
|
||||
inner.inject_event(event)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inject_dial_upgrade_error(&mut self, info: Self::OutboundOpenInfo, error: ProtocolsHandlerUpgrErr<<Self::OutboundProtocol as OutboundUpgrade<Self::Substream>>::Error>) {
|
||||
if let Some(inner) = self.inner.as_mut() {
|
||||
inner.inject_dial_upgrade_error(info, error)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inject_inbound_closed(&mut self) {
|
||||
if let Some(inner) = self.inner.as_mut() {
|
||||
inner.inject_inbound_closed()
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn connection_keep_alive(&self) -> KeepAlive {
|
||||
if let Some(inner) = self.inner.as_ref() {
|
||||
inner.connection_keep_alive()
|
||||
} else {
|
||||
KeepAlive::Now
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn shutdown(&mut self) {
|
||||
self.inner = match mem::replace(&mut self.inner, State::Shutdown) {
|
||||
State::Normal(mut inner) => {
|
||||
inner.shutdown();
|
||||
State::ShuttingDown(inner)
|
||||
},
|
||||
s @ State::ShuttingDown(_) => s,
|
||||
s @ State::Shutdown => s,
|
||||
};
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn poll(
|
||||
&mut self,
|
||||
) -> Poll<
|
||||
ProtocolsHandlerEvent<Self::OutboundProtocol, Self::OutboundOpenInfo, Self::OutEvent>,
|
||||
Self::Error,
|
||||
> {
|
||||
let poll = match self.inner.as_mut() {
|
||||
Some(i) => i.poll(),
|
||||
None => return Ok(Async::Ready(ProtocolsHandlerEvent::Shutdown)),
|
||||
};
|
||||
|
||||
if let Ok(Async::Ready(ProtocolsHandlerEvent::Shutdown)) = poll {
|
||||
self.inner = State::Shutdown;
|
||||
}
|
||||
|
||||
poll
|
||||
}
|
||||
}
|
@ -94,21 +94,11 @@ where
|
||||
self.inner.inject_dial_upgrade_error(info, error)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inject_inbound_closed(&mut self) {
|
||||
self.inner.inject_inbound_closed()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn connection_keep_alive(&self) -> KeepAlive {
|
||||
self.inner.connection_keep_alive()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn shutdown(&mut self) {
|
||||
self.inner.shutdown()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn poll(
|
||||
&mut self,
|
||||
|
@ -89,21 +89,11 @@ where
|
||||
self.inner.inject_dial_upgrade_error(info, error)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inject_inbound_closed(&mut self) {
|
||||
self.inner.inject_inbound_closed()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn connection_keep_alive(&self) -> KeepAlive {
|
||||
self.inner.connection_keep_alive()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn shutdown(&mut self) {
|
||||
self.inner.shutdown()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn poll(
|
||||
&mut self,
|
||||
@ -114,7 +104,6 @@ where
|
||||
Ok(self.inner.poll()?.map(|ev| {
|
||||
match ev {
|
||||
ProtocolsHandlerEvent::Custom(ev) => ProtocolsHandlerEvent::Custom((self.map)(ev)),
|
||||
ProtocolsHandlerEvent::Shutdown => ProtocolsHandlerEvent::Shutdown,
|
||||
ProtocolsHandlerEvent::OutboundSubstreamRequest { upgrade, info } => {
|
||||
ProtocolsHandlerEvent::OutboundSubstreamRequest { upgrade, info }
|
||||
}
|
||||
|
@ -44,15 +44,13 @@ use std::{cmp::Ordering, error, fmt, time::Duration, time::Instant};
|
||||
use tokio_io::{AsyncRead, AsyncWrite};
|
||||
|
||||
pub use self::dummy::DummyProtocolsHandler;
|
||||
pub use self::fuse::Fuse;
|
||||
pub use self::map_in::MapInEvent;
|
||||
pub use self::map_out::MapOutEvent;
|
||||
pub use self::node_handler::{NodeHandlerWrapper, NodeHandlerWrapperBuilder};
|
||||
pub use self::node_handler::{NodeHandlerWrapper, NodeHandlerWrapperBuilder, NodeHandlerWrapperError};
|
||||
pub use self::one_shot::OneShotHandler;
|
||||
pub use self::select::{IntoProtocolsHandlerSelect, ProtocolsHandlerSelect};
|
||||
|
||||
mod dummy;
|
||||
mod fuse;
|
||||
mod map_in;
|
||||
mod map_out;
|
||||
mod node_handler;
|
||||
@ -138,10 +136,6 @@ pub trait ProtocolsHandler {
|
||||
/// Indicates to the handler that upgrading a substream to the given protocol has failed.
|
||||
fn inject_dial_upgrade_error(&mut self, info: Self::OutboundOpenInfo, error: ProtocolsHandlerUpgrErr<<Self::OutboundProtocol as OutboundUpgrade<Self::Substream>>::Error>);
|
||||
|
||||
/// Indicates to the handler that the inbound part of the muxer has been closed, and that
|
||||
/// therefore no more inbound substreams will be produced.
|
||||
fn inject_inbound_closed(&mut self);
|
||||
|
||||
/// Returns until when the connection should be kept alive.
|
||||
///
|
||||
/// If returns `Until`, that indicates that this connection may invoke `shutdown()` after the
|
||||
@ -160,20 +154,9 @@ pub trait ProtocolsHandler {
|
||||
/// After `shutdown()` is called, the result of this method doesn't matter anymore.
|
||||
fn connection_keep_alive(&self) -> KeepAlive;
|
||||
|
||||
/// Indicates to the node that it should shut down. After that, it is expected that `poll()`
|
||||
/// returns `Ready(ProtocolsHandlerEvent::Shutdown)` as soon as possible.
|
||||
/// Should behave like `Stream::poll()`.
|
||||
///
|
||||
/// This method allows an implementation to perform a graceful shutdown of the substreams, and
|
||||
/// send back various events.
|
||||
fn shutdown(&mut self);
|
||||
|
||||
/// Should behave like `Stream::poll()`. Should close if no more event can be produced and the
|
||||
/// node should be closed.
|
||||
///
|
||||
/// > **Note**: If this handler is combined with other handlers, as soon as `poll()` returns
|
||||
/// > `Ok(Async::Ready(ProtocolsHandlerEvent::Shutdown))`, all the other handlers
|
||||
/// > will receive a call to `shutdown()` and will eventually be closed and
|
||||
/// > destroyed.
|
||||
/// Returning an error will close the connection to the remote.
|
||||
fn poll(&mut self) -> Poll<ProtocolsHandlerEvent<Self::OutboundProtocol, Self::OutboundOpenInfo, Self::OutEvent>, Self::Error>;
|
||||
|
||||
/// Adds a closure that turns the input event into something else.
|
||||
@ -196,16 +179,6 @@ pub trait ProtocolsHandler {
|
||||
MapOutEvent::new(self, map)
|
||||
}
|
||||
|
||||
/// Wraps around `self`. When `poll()` returns `Shutdown`, any further call to any method will
|
||||
/// be ignored.
|
||||
#[inline]
|
||||
fn fuse(self) -> Fuse<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
Fuse::new(self)
|
||||
}
|
||||
|
||||
/// Builds an implementation of `ProtocolsHandler` that handles both this protocol and the
|
||||
/// other one together.
|
||||
#[inline]
|
||||
@ -251,11 +224,6 @@ pub enum ProtocolsHandlerEvent<TConnectionUpgrade, TOutboundOpenInfo, TCustom> {
|
||||
info: TOutboundOpenInfo,
|
||||
},
|
||||
|
||||
/// Perform a graceful shutdown of the connection to the remote.
|
||||
///
|
||||
/// Should be returned after `shutdown()` has been called.
|
||||
Shutdown,
|
||||
|
||||
/// Other event.
|
||||
Custom(TCustom),
|
||||
}
|
||||
@ -280,7 +248,6 @@ impl<TConnectionUpgrade, TOutboundOpenInfo, TCustom>
|
||||
info: map(info),
|
||||
}
|
||||
}
|
||||
ProtocolsHandlerEvent::Shutdown => ProtocolsHandlerEvent::Shutdown,
|
||||
ProtocolsHandlerEvent::Custom(val) => ProtocolsHandlerEvent::Custom(val),
|
||||
}
|
||||
}
|
||||
@ -301,7 +268,6 @@ impl<TConnectionUpgrade, TOutboundOpenInfo, TCustom>
|
||||
info,
|
||||
}
|
||||
}
|
||||
ProtocolsHandlerEvent::Shutdown => ProtocolsHandlerEvent::Shutdown,
|
||||
ProtocolsHandlerEvent::Custom(val) => ProtocolsHandlerEvent::Custom(val),
|
||||
}
|
||||
}
|
||||
@ -319,7 +285,6 @@ impl<TConnectionUpgrade, TOutboundOpenInfo, TCustom>
|
||||
ProtocolsHandlerEvent::OutboundSubstreamRequest { upgrade, info } => {
|
||||
ProtocolsHandlerEvent::OutboundSubstreamRequest { upgrade, info }
|
||||
}
|
||||
ProtocolsHandlerEvent::Shutdown => ProtocolsHandlerEvent::Shutdown,
|
||||
ProtocolsHandlerEvent::Custom(val) => ProtocolsHandlerEvent::Custom(map(val)),
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ use crate::{
|
||||
}
|
||||
};
|
||||
use futures::prelude::*;
|
||||
use std::time::{Duration, Instant};
|
||||
use std::{error, fmt, time::Duration, time::Instant};
|
||||
use tokio_timer::{Delay, Timeout};
|
||||
|
||||
/// Prototype for a `NodeHandlerWrapper`.
|
||||
@ -145,6 +145,46 @@ where
|
||||
connection_shutdown: Option<Delay>,
|
||||
}
|
||||
|
||||
/// Error generated by the `NodeHandlerWrapper`.
|
||||
#[derive(Debug)]
|
||||
pub enum NodeHandlerWrapperError<TErr> {
|
||||
/// Error generated by the handler.
|
||||
Handler(TErr),
|
||||
/// The connection has been deemed useless and has been closed.
|
||||
UselessTimeout,
|
||||
}
|
||||
|
||||
impl<TErr> From<TErr> for NodeHandlerWrapperError<TErr> {
|
||||
fn from(err: TErr) -> NodeHandlerWrapperError<TErr> {
|
||||
NodeHandlerWrapperError::Handler(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl<TErr> fmt::Display for NodeHandlerWrapperError<TErr>
|
||||
where
|
||||
TErr: fmt::Display
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
NodeHandlerWrapperError::Handler(err) => write!(f, "{}", err),
|
||||
NodeHandlerWrapperError::UselessTimeout =>
|
||||
write!(f, "Node has been closed due to inactivity"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<TErr> error::Error for NodeHandlerWrapperError<TErr>
|
||||
where
|
||||
TErr: error::Error + 'static
|
||||
{
|
||||
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
|
||||
match self {
|
||||
NodeHandlerWrapperError::Handler(err) => Some(err),
|
||||
NodeHandlerWrapperError::UselessTimeout => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<TProtoHandler> NodeHandler for NodeHandlerWrapper<TProtoHandler>
|
||||
where
|
||||
TProtoHandler: ProtocolsHandler,
|
||||
@ -153,7 +193,7 @@ where
|
||||
{
|
||||
type InEvent = TProtoHandler::InEvent;
|
||||
type OutEvent = TProtoHandler::OutEvent;
|
||||
type Error = TProtoHandler::Error;
|
||||
type Error = NodeHandlerWrapperError<TProtoHandler::Error>;
|
||||
type Substream = TProtoHandler::Substream;
|
||||
// The first element of the tuple is the unique upgrade identifier
|
||||
// (see `unique_dial_upgrade_id`).
|
||||
@ -192,42 +232,11 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inject_inbound_closed(&mut self) {
|
||||
self.handler.inject_inbound_closed();
|
||||
}
|
||||
|
||||
fn inject_outbound_closed(&mut self, user_data: Self::OutboundOpenInfo) {
|
||||
let pos = match self
|
||||
.queued_dial_upgrades
|
||||
.iter()
|
||||
.position(|(id, _)| id == &user_data.0)
|
||||
{
|
||||
Some(p) => p,
|
||||
None => {
|
||||
debug_assert!(
|
||||
false,
|
||||
"Received an outbound closed error with an invalid upgrade ID"
|
||||
);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
self.queued_dial_upgrades.remove(pos);
|
||||
self.handler
|
||||
.inject_dial_upgrade_error(user_data.1, ProtocolsHandlerUpgrErr::MuxerDeniedSubstream);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inject_event(&mut self, event: Self::InEvent) {
|
||||
self.handler.inject_event(event);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn shutdown(&mut self) {
|
||||
self.handler.shutdown();
|
||||
}
|
||||
|
||||
fn poll(&mut self) -> Poll<NodeHandlerEvent<Self::OutboundOpenInfo, Self::OutEvent>, Self::Error> {
|
||||
// Continue negotiation of newly-opened substreams on the listening side.
|
||||
// We remove each element from `negotiating_in` one by one and add them back if not ready.
|
||||
@ -273,55 +282,47 @@ where
|
||||
|
||||
// Poll the handler at the end so that we see the consequences of the method calls on
|
||||
// `self.handler`.
|
||||
loop {
|
||||
let poll_result = self.handler.poll()?;
|
||||
let poll_result = self.handler.poll()?;
|
||||
|
||||
self.connection_shutdown = match self.handler.connection_keep_alive() {
|
||||
KeepAlive::Until(expiration) => Some(Delay::new(expiration)),
|
||||
KeepAlive::Now => Some(Delay::new(Instant::now())),
|
||||
KeepAlive::Forever => None,
|
||||
};
|
||||
self.connection_shutdown = match self.handler.connection_keep_alive() {
|
||||
KeepAlive::Until(expiration) => Some(Delay::new(expiration)),
|
||||
KeepAlive::Now => Some(Delay::new(Instant::now())),
|
||||
KeepAlive::Forever => None,
|
||||
};
|
||||
|
||||
match poll_result {
|
||||
Async::Ready(ProtocolsHandlerEvent::Custom(event)) => {
|
||||
return Ok(Async::Ready(NodeHandlerEvent::Custom(event)));
|
||||
}
|
||||
Async::Ready(ProtocolsHandlerEvent::OutboundSubstreamRequest {
|
||||
upgrade,
|
||||
info,
|
||||
}) => {
|
||||
let id = self.unique_dial_upgrade_id;
|
||||
self.unique_dial_upgrade_id += 1;
|
||||
self.queued_dial_upgrades.push((id, upgrade));
|
||||
return Ok(Async::Ready(
|
||||
NodeHandlerEvent::OutboundSubstreamRequest((id, info)),
|
||||
));
|
||||
}
|
||||
Async::Ready(ProtocolsHandlerEvent::Shutdown) => {
|
||||
return Ok(Async::Ready(NodeHandlerEvent::Shutdown))
|
||||
},
|
||||
Async::NotReady => (),
|
||||
};
|
||||
|
||||
// Check the `connection_shutdown`.
|
||||
if let Some(mut connection_shutdown) = self.connection_shutdown.take() {
|
||||
// If we're negotiating substreams, let's delay the closing.
|
||||
if self.negotiating_in.is_empty() && self.negotiating_out.is_empty() {
|
||||
match connection_shutdown.poll() {
|
||||
Ok(Async::Ready(_)) | Err(_) => {
|
||||
self.shutdown();
|
||||
continue; // We need to poll the handler again.
|
||||
},
|
||||
Ok(Async::NotReady) => {
|
||||
self.connection_shutdown = Some(connection_shutdown);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.connection_shutdown = Some(connection_shutdown);
|
||||
}
|
||||
match poll_result {
|
||||
Async::Ready(ProtocolsHandlerEvent::Custom(event)) => {
|
||||
return Ok(Async::Ready(NodeHandlerEvent::Custom(event)));
|
||||
}
|
||||
Async::Ready(ProtocolsHandlerEvent::OutboundSubstreamRequest {
|
||||
upgrade,
|
||||
info,
|
||||
}) => {
|
||||
let id = self.unique_dial_upgrade_id;
|
||||
self.unique_dial_upgrade_id += 1;
|
||||
self.queued_dial_upgrades.push((id, upgrade));
|
||||
return Ok(Async::Ready(
|
||||
NodeHandlerEvent::OutboundSubstreamRequest((id, info)),
|
||||
));
|
||||
}
|
||||
Async::NotReady => (),
|
||||
};
|
||||
|
||||
break;
|
||||
// Check the `connection_shutdown`.
|
||||
if let Some(mut connection_shutdown) = self.connection_shutdown.take() {
|
||||
// If we're negotiating substreams, let's delay the closing.
|
||||
if self.negotiating_in.is_empty() && self.negotiating_out.is_empty() {
|
||||
match connection_shutdown.poll() {
|
||||
Ok(Async::Ready(_)) | Err(_) => {
|
||||
return Err(NodeHandlerWrapperError::UselessTimeout);
|
||||
},
|
||||
Ok(Async::NotReady) => {
|
||||
self.connection_shutdown = Some(connection_shutdown);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.connection_shutdown = Some(connection_shutdown);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Async::NotReady)
|
||||
|
@ -188,20 +188,12 @@ where
|
||||
self.pending_error = Some(error);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inject_inbound_closed(&mut self) {}
|
||||
|
||||
|
||||
#[inline]
|
||||
fn connection_keep_alive(&self) -> KeepAlive {
|
||||
self.keep_alive
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn shutdown(&mut self) {
|
||||
self.shutting_down = true;
|
||||
}
|
||||
|
||||
fn poll(&mut self) -> Poll<ProtocolsHandlerEvent<Self::OutboundProtocol, Self::OutboundOpenInfo, Self::OutEvent>, Self::Error> {
|
||||
if let Some(err) = self.pending_error.take() {
|
||||
return Err(err);
|
||||
@ -213,10 +205,6 @@ where
|
||||
self.events_out.shrink_to_fit();
|
||||
}
|
||||
|
||||
if self.shutting_down && self.dial_negotiated == 0 {
|
||||
return Ok(Async::Ready(ProtocolsHandlerEvent::Shutdown));
|
||||
}
|
||||
|
||||
if !self.dial_queue.is_empty() {
|
||||
if !self.shutting_down && self.dial_negotiated < self.max_dial_negotiated {
|
||||
self.dial_negotiated += 1;
|
||||
|
@ -24,7 +24,6 @@ use crate::{
|
||||
either::EitherOutput,
|
||||
protocols_handler::{
|
||||
KeepAlive,
|
||||
Fuse,
|
||||
IntoProtocolsHandler,
|
||||
ProtocolsHandler,
|
||||
ProtocolsHandlerEvent,
|
||||
@ -78,8 +77,8 @@ where
|
||||
|
||||
fn into_handler(self, remote_peer_id: &PeerId) -> Self::Handler {
|
||||
ProtocolsHandlerSelect {
|
||||
proto1: self.proto1.into_handler(remote_peer_id).fuse(),
|
||||
proto2: self.proto2.into_handler(remote_peer_id).fuse(),
|
||||
proto1: self.proto1.into_handler(remote_peer_id),
|
||||
proto2: self.proto2.into_handler(remote_peer_id),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -88,9 +87,9 @@ where
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ProtocolsHandlerSelect<TProto1, TProto2> {
|
||||
/// The first protocol.
|
||||
proto1: Fuse<TProto1>,
|
||||
proto1: TProto1,
|
||||
/// The second protocol.
|
||||
proto2: Fuse<TProto2>,
|
||||
proto2: TProto2,
|
||||
}
|
||||
|
||||
impl<TProto1, TProto2> ProtocolsHandlerSelect<TProto1, TProto2> {
|
||||
@ -98,8 +97,8 @@ impl<TProto1, TProto2> ProtocolsHandlerSelect<TProto1, TProto2> {
|
||||
#[inline]
|
||||
pub(crate) fn new(proto1: TProto1, proto2: TProto2) -> Self {
|
||||
ProtocolsHandlerSelect {
|
||||
proto1: Fuse::new(proto1),
|
||||
proto2: Fuse::new(proto2),
|
||||
proto1,
|
||||
proto2,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -119,7 +118,7 @@ where
|
||||
type OutEvent = EitherOutput<TProto1::OutEvent, TProto2::OutEvent>;
|
||||
type Error = EitherError<TProto1::Error, TProto2::Error>;
|
||||
type Substream = TSubstream;
|
||||
type InboundProtocol = SelectUpgrade<<Fuse<TProto1> as ProtocolsHandler>::InboundProtocol, <Fuse<TProto2> as ProtocolsHandler>::InboundProtocol>;
|
||||
type InboundProtocol = SelectUpgrade<<TProto1 as ProtocolsHandler>::InboundProtocol, <TProto2 as ProtocolsHandler>::InboundProtocol>;
|
||||
type OutboundProtocol = EitherUpgrade<TProto1::OutboundProtocol, TProto2::OutboundProtocol>;
|
||||
type OutboundOpenInfo = EitherOutput<TProto1::OutboundOpenInfo, TProto2::OutboundOpenInfo>;
|
||||
|
||||
@ -160,12 +159,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inject_inbound_closed(&mut self) {
|
||||
self.proto1.inject_inbound_closed();
|
||||
self.proto2.inject_inbound_closed();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inject_dial_upgrade_error(&mut self, info: Self::OutboundOpenInfo, error: ProtocolsHandlerUpgrErr<<Self::OutboundProtocol as OutboundUpgrade<Self::Substream>>::Error>) {
|
||||
match (info, error) {
|
||||
@ -213,12 +206,6 @@ where
|
||||
cmp::max(self.proto1.connection_keep_alive(), self.proto2.connection_keep_alive())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn shutdown(&mut self) {
|
||||
self.proto1.shutdown();
|
||||
self.proto2.shutdown();
|
||||
}
|
||||
|
||||
fn poll(&mut self) -> Poll<ProtocolsHandlerEvent<Self::OutboundProtocol, Self::OutboundOpenInfo, Self::OutEvent>, Self::Error> {
|
||||
loop {
|
||||
match self.proto1.poll().map_err(EitherError::A)? {
|
||||
@ -231,9 +218,6 @@ where
|
||||
info: EitherOutput::First(info),
|
||||
}));
|
||||
},
|
||||
Async::Ready(ProtocolsHandlerEvent::Shutdown) => {
|
||||
self.proto2.shutdown();
|
||||
},
|
||||
Async::NotReady => ()
|
||||
};
|
||||
|
||||
@ -247,22 +231,12 @@ where
|
||||
info: EitherOutput::Second(info),
|
||||
}));
|
||||
},
|
||||
Async::Ready(ProtocolsHandlerEvent::Shutdown) => {
|
||||
if !self.proto1.is_shutting_down_or_shutdown() {
|
||||
self.proto1.shutdown();
|
||||
continue;
|
||||
}
|
||||
},
|
||||
Async::NotReady => ()
|
||||
};
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if self.proto1.is_shutdown() && self.proto2.is_shutdown() {
|
||||
Ok(Async::Ready(ProtocolsHandlerEvent::Shutdown))
|
||||
} else {
|
||||
Ok(Async::NotReady)
|
||||
}
|
||||
Ok(Async::NotReady)
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user