swarm/one_shot: Initialize handler with KeepAlive::Until (#1698)

* swarm/one_shot: Add test for not keeping alive idle connection

A `OneShotHandler` without any ongoing requests should not keep the
underlying connection alive indefinitely.

* swarm/one_shot: Initialize handler with KeepAlive::Until

The `OneShotHandler` `keep_alive` property is altered on incoming and
outgoing reqeusts. By default it is initialized in `KeepAlive::Yes`. In
case there are no incoming or outgoing requests happening, this state is
never changed and thus the handler keeps the underlying connection alive
indefinitely.

With this commit the handler is initialized with `KeepAlive::Until`. As
before the `keep_alive` timer is updated on incoming requests and set to
`KeepAlive::Yes` on outgoing requests.

* swarm/one_shot: Move KeepAlive logic to poll

A `ProtocolsHandler` can be created before the underlying connection is
established. Thus setting a keep alive timeout might be problematic.
Instead set `keep_alive` to `Yes` at construction and alter it within
`ProtocolsHandler::poll`.

* swarm/CHANGELOG: Add entry for OneShotHandler keep-alive
This commit is contained in:
Max Inden
2020-08-13 11:18:20 +02:00
committed by GitHub
parent 9eca739331
commit e32ff74809
2 changed files with 34 additions and 5 deletions

View File

@ -161,11 +161,6 @@ where
_: Self::OutboundOpenInfo,
) {
self.dial_negotiated -= 1;
if self.dial_negotiated == 0 && self.dial_queue.is_empty() {
self.keep_alive = KeepAlive::Until(Instant::now() + self.config.keep_alive_timeout);
}
self.events_out.push(out.into());
}
@ -221,6 +216,10 @@ where
}
} else {
self.dial_queue.shrink_to_fit();
if self.dial_negotiated == 0 && self.keep_alive.is_yes() {
self.keep_alive = KeepAlive::Until(Instant::now() + self.config.keep_alive_timeout);
}
}
Poll::Pending
@ -245,3 +244,30 @@ impl Default for OneShotHandlerConfig {
}
}
#[cfg(test)]
mod tests {
use super::*;
use futures::executor::block_on;
use futures::future::poll_fn;
use libp2p_core::upgrade::DeniedUpgrade;
use void::Void;
#[test]
fn do_not_keep_idle_connection_alive() {
let mut handler: OneShotHandler<_, DeniedUpgrade, Void> = OneShotHandler::new(
SubstreamProtocol::new(DeniedUpgrade{}),
Default::default(),
);
block_on(poll_fn(|cx| {
loop {
if let Poll::Pending = handler.poll(cx) {
return Poll::Ready(())
}
}
}));
assert!(matches!(handler.connection_keep_alive(), KeepAlive::Until(_)));
}
}