Add IntoNodeHandler and IntoProtocolsHandler traits (#848)

* Add IntoNodeHandler

* Add IntoProtocolsHandler
This commit is contained in:
Pierre Krieger
2019-01-14 14:22:25 +01:00
committed by GitHub
parent 60db872c31
commit bf52e9bd19
8 changed files with 267 additions and 112 deletions

View File

@ -33,6 +33,7 @@
//! > connection with a remote. In order to handle a protocol that requires knowledge of
//! > the network as a whole, see the `NetworkBehaviour` trait.
use crate::PeerId;
use crate::upgrade::{
InboundUpgrade,
OutboundUpgrade,
@ -46,7 +47,7 @@ pub use self::dummy::DummyProtocolsHandler;
pub use self::map_in::MapInEvent;
pub use self::map_out::MapOutEvent;
pub use self::node_handler::{NodeHandlerWrapper, NodeHandlerWrapperBuilder};
pub use self::select::ProtocolsHandlerSelect;
pub use self::select::{IntoProtocolsHandlerSelect, ProtocolsHandlerSelect};
mod dummy;
mod map_in;
@ -207,17 +208,19 @@ pub trait ProtocolsHandler {
where
Self: Sized,
{
NodeHandlerWrapperBuilder::new(self, Duration::from_secs(10), Duration::from_secs(10), Duration::from_secs(5))
IntoProtocolsHandler::into_node_handler_builder(self)
}
/// Builds an implementation of `NodeHandler` that handles this protocol exclusively.
///
/// > **Note**: This is a shortcut for `self.into_node_handler_builder().build()`.
#[inline]
#[deprecated(note = "Use into_node_handler_builder instead")]
fn into_node_handler(self) -> NodeHandlerWrapper<Self>
where
Self: Sized,
{
#![allow(deprecated)]
self.into_node_handler_builder().build()
}
}
@ -353,3 +356,45 @@ where
}
}
}
/// Prototype for a `ProtocolsHandler`.
pub trait IntoProtocolsHandler {
/// The protocols handler.
type Handler: ProtocolsHandler;
/// Builds the protocols handler.
///
/// The `PeerId` is the id of the node the handler is going to handle.
fn into_handler(self, remote_peer_id: &PeerId) -> Self::Handler;
/// Builds an implementation of `IntoProtocolsHandler` that handles both this protocol and the
/// other one together.
#[inline]
fn select<TProto2>(self, other: TProto2) -> IntoProtocolsHandlerSelect<Self, TProto2>
where
Self: Sized,
{
IntoProtocolsHandlerSelect::new(self, other)
}
/// Creates a builder that will allow creating a `NodeHandler` that handles this protocol
/// exclusively.
#[inline]
fn into_node_handler_builder(self) -> NodeHandlerWrapperBuilder<Self>
where
Self: Sized,
{
NodeHandlerWrapperBuilder::new(self, Duration::from_secs(10), Duration::from_secs(10), Duration::from_secs(5))
}
}
impl<T> IntoProtocolsHandler for T
where T: ProtocolsHandler
{
type Handler = Self;
#[inline]
fn into_handler(self, _: &PeerId) -> Self {
self
}
}

View File

@ -19,8 +19,10 @@
// DEALINGS IN THE SOFTWARE.
use crate::{
PeerId,
nodes::handled_node::{NodeHandler, NodeHandlerEndpoint, NodeHandlerEvent},
protocols_handler::{ProtocolsHandler, ProtocolsHandlerEvent, ProtocolsHandlerUpgrErr},
nodes::handled_node_tasks::IntoNodeHandler,
protocols_handler::{ProtocolsHandler, IntoProtocolsHandler, ProtocolsHandlerEvent, ProtocolsHandlerUpgrErr},
upgrade::{
self,
OutboundUpgrade,
@ -33,12 +35,9 @@ use std::time::{Duration, Instant};
use tokio_timer::{Delay, Timeout};
/// Prototype for a `NodeHandlerWrapper`.
pub struct NodeHandlerWrapperBuilder<TProtoHandler>
where
TProtoHandler: ProtocolsHandler,
{
pub struct NodeHandlerWrapperBuilder<TIntoProtoHandler> {
/// The underlying handler.
handler: TProtoHandler,
handler: TIntoProtoHandler,
/// Timeout for incoming substreams negotiation.
in_timeout: Duration,
/// Timeout for outgoing substreams negotiation.
@ -47,13 +46,13 @@ where
useless_timeout: Duration,
}
impl<TProtoHandler> NodeHandlerWrapperBuilder<TProtoHandler>
impl<TIntoProtoHandler> NodeHandlerWrapperBuilder<TIntoProtoHandler>
where
TProtoHandler: ProtocolsHandler
TIntoProtoHandler: IntoProtocolsHandler
{
/// Builds a `NodeHandlerWrapperBuilder`.
#[inline]
pub(crate) fn new(handler: TProtoHandler, in_timeout: Duration, out_timeout: Duration, useless_timeout: Duration) -> Self {
pub(crate) fn new(handler: TIntoProtoHandler, in_timeout: Duration, out_timeout: Duration, useless_timeout: Duration) -> Self {
NodeHandlerWrapperBuilder {
handler,
in_timeout,
@ -85,8 +84,11 @@ where
}
/// Builds the `NodeHandlerWrapper`.
#[deprecated(note = "Pass the NodeHandlerWrapperBuilder directly")]
#[inline]
pub fn build(self) -> NodeHandlerWrapper<TProtoHandler> {
pub fn build(self) -> NodeHandlerWrapper<TIntoProtoHandler>
where TIntoProtoHandler: ProtocolsHandler
{
NodeHandlerWrapper {
handler: self.handler,
negotiating_in: Vec::new(),
@ -101,6 +103,30 @@ where
}
}
impl<TIntoProtoHandler, TProtoHandler> IntoNodeHandler for NodeHandlerWrapperBuilder<TIntoProtoHandler>
where
TIntoProtoHandler: IntoProtocolsHandler<Handler = TProtoHandler>,
TProtoHandler: ProtocolsHandler,
// TODO: meh for Debug
<TProtoHandler::OutboundProtocol as OutboundUpgrade<<TProtoHandler as ProtocolsHandler>::Substream>>::Error: std::fmt::Debug
{
type Handler = NodeHandlerWrapper<TIntoProtoHandler::Handler>;
fn into_handler(self, remote_peer_id: &PeerId) -> Self::Handler {
NodeHandlerWrapper {
handler: self.handler.into_handler(remote_peer_id),
negotiating_in: Vec::new(),
negotiating_out: Vec::new(),
in_timeout: self.in_timeout,
out_timeout: self.out_timeout,
queued_dial_upgrades: Vec::new(),
unique_dial_upgrade_id: 0,
connection_shutdown: None,
useless_timeout: self.useless_timeout,
}
}
}
/// Wraps around an implementation of `ProtocolsHandler`, and implements `NodeHandler`.
// TODO: add a caching system for protocols that are supported or not
pub struct NodeHandlerWrapper<TProtoHandler>
@ -138,6 +164,7 @@ where
impl<TProtoHandler> NodeHandler for NodeHandlerWrapper<TProtoHandler>
where
TProtoHandler: ProtocolsHandler,
// TODO: meh for Debug
<TProtoHandler::OutboundProtocol as OutboundUpgrade<<TProtoHandler as ProtocolsHandler>::Substream>>::Error: std::fmt::Debug
{
type InEvent = TProtoHandler::InEvent;

View File

@ -19,9 +19,15 @@
// DEALINGS IN THE SOFTWARE.
use crate::{
PeerId,
either::EitherError,
either::EitherOutput,
protocols_handler::{ProtocolsHandler, ProtocolsHandlerEvent, ProtocolsHandlerUpgrErr},
protocols_handler::{
IntoProtocolsHandler,
ProtocolsHandler,
ProtocolsHandlerEvent,
ProtocolsHandlerUpgrErr,
},
upgrade::{
InboundUpgrade,
OutboundUpgrade,
@ -33,6 +39,46 @@ use crate::{
use futures::prelude::*;
use tokio_io::{AsyncRead, AsyncWrite};
/// Implementation of `IntoProtocolsHandler` that combines two protocols into one.
#[derive(Debug, Clone)]
pub struct IntoProtocolsHandlerSelect<TProto1, TProto2> {
proto1: TProto1,
proto2: TProto2,
}
impl<TProto1, TProto2> IntoProtocolsHandlerSelect<TProto1, TProto2> {
/// Builds a `IntoProtocolsHandlerSelect`.
#[inline]
pub(crate) fn new(proto1: TProto1, proto2: TProto2) -> Self {
IntoProtocolsHandlerSelect {
proto1,
proto2,
}
}
}
impl<TProto1, TProto2, TSubstream> IntoProtocolsHandler for IntoProtocolsHandlerSelect<TProto1, TProto2>
where
TProto1: IntoProtocolsHandler,
TProto2: IntoProtocolsHandler,
TProto1::Handler: ProtocolsHandler<Substream = TSubstream>,
TProto2::Handler: ProtocolsHandler<Substream = TSubstream>,
TSubstream: AsyncRead + AsyncWrite,
<TProto1::Handler as ProtocolsHandler>::InboundProtocol: InboundUpgrade<TSubstream>,
<TProto2::Handler as ProtocolsHandler>::InboundProtocol: InboundUpgrade<TSubstream>,
<TProto1::Handler as ProtocolsHandler>::OutboundProtocol: OutboundUpgrade<TSubstream>,
<TProto2::Handler as ProtocolsHandler>::OutboundProtocol: OutboundUpgrade<TSubstream>
{
type Handler = ProtocolsHandlerSelect<TProto1::Handler, TProto2::Handler>;
fn into_handler(self, remote_peer_id: &PeerId) -> Self::Handler {
ProtocolsHandlerSelect {
proto1: self.proto1.into_handler(remote_peer_id),
proto2: self.proto2.into_handler(remote_peer_id),
}
}
}
/// Implementation of `ProtocolsHandler` that combines two protocols into one.
#[derive(Debug, Clone)]
pub struct ProtocolsHandlerSelect<TProto1, TProto2> {