2018-11-02 10:06:59 +01:00
|
|
|
// Copyright 2018 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.
|
|
|
|
|
2019-09-02 11:16:52 +02:00
|
|
|
use crate::protocol::{RemoteInfo, IdentifyProtocolConfig, ReplySubstream};
|
2018-11-02 10:06:59 +01:00
|
|
|
use futures::prelude::*;
|
2019-09-02 11:16:52 +02:00
|
|
|
use libp2p_core::upgrade::{
|
|
|
|
InboundUpgrade,
|
|
|
|
OutboundUpgrade,
|
2019-09-16 11:08:44 +02:00
|
|
|
ReadOneError,
|
2019-09-02 11:16:52 +02:00
|
|
|
Negotiated
|
|
|
|
};
|
2019-07-04 14:47:59 +02:00
|
|
|
use libp2p_swarm::{
|
|
|
|
KeepAlive,
|
|
|
|
SubstreamProtocol,
|
|
|
|
ProtocolsHandler,
|
|
|
|
ProtocolsHandlerEvent,
|
|
|
|
ProtocolsHandlerUpgrErr
|
2018-11-15 17:41:11 +01:00
|
|
|
};
|
2019-09-02 11:16:52 +02:00
|
|
|
use smallvec::SmallVec;
|
2019-09-16 11:08:44 +02:00
|
|
|
use std::{marker::PhantomData, pin::Pin, task::Context, task::Poll, time::Duration};
|
|
|
|
use wasm_timer::Delay;
|
2018-11-02 10:06:59 +01:00
|
|
|
|
|
|
|
/// Delay between the moment we connect and the first time we identify.
|
2019-02-18 13:59:12 +01:00
|
|
|
const DELAY_TO_FIRST_ID: Duration = Duration::from_millis(500);
|
2018-11-02 10:06:59 +01:00
|
|
|
/// After an identification succeeded, wait this long before the next time.
|
|
|
|
const DELAY_TO_NEXT_ID: Duration = Duration::from_secs(5 * 60);
|
|
|
|
/// After we failed to identify the remote, try again after the given delay.
|
|
|
|
const TRY_AGAIN_ON_ERR: Duration = Duration::from_secs(60 * 60);
|
|
|
|
|
2019-09-02 11:16:52 +02:00
|
|
|
/// Protocol handler for sending and receiving identification requests.
|
|
|
|
///
|
|
|
|
/// Outbound requests are sent periodically. The handler performs expects
|
|
|
|
/// at least one identification request to be answered by the remote before
|
|
|
|
/// permitting the underlying connection to be closed.
|
|
|
|
pub struct IdentifyHandler<TSubstream> {
|
2018-11-02 10:06:59 +01:00
|
|
|
/// Configuration for the protocol.
|
2018-11-20 15:09:59 +01:00
|
|
|
config: IdentifyProtocolConfig,
|
2018-11-02 10:06:59 +01:00
|
|
|
|
2019-09-02 11:16:52 +02:00
|
|
|
/// Pending events to yield.
|
|
|
|
events: SmallVec<[IdentifyHandlerEvent<TSubstream>; 4]>,
|
2018-11-02 10:06:59 +01:00
|
|
|
|
2019-03-11 17:19:50 +01:00
|
|
|
/// Future that fires when we need to identify the node again.
|
|
|
|
next_id: Delay,
|
2018-11-02 10:06:59 +01:00
|
|
|
|
2019-09-02 11:16:52 +02:00
|
|
|
/// Whether the handler should keep the connection alive.
|
|
|
|
keep_alive: KeepAlive,
|
2019-01-04 12:02:39 +01:00
|
|
|
|
2018-11-02 10:06:59 +01:00
|
|
|
/// Marker for strong typing.
|
|
|
|
marker: PhantomData<TSubstream>,
|
|
|
|
}
|
|
|
|
|
2019-09-02 11:16:52 +02:00
|
|
|
/// Event produced by the `IdentifyHandler`.
|
2018-11-02 10:06:59 +01:00
|
|
|
#[derive(Debug)]
|
2019-09-02 11:16:52 +02:00
|
|
|
pub enum IdentifyHandlerEvent<TSubstream> {
|
2018-11-02 10:06:59 +01:00
|
|
|
/// We obtained identification information from the remote
|
2018-11-15 17:41:11 +01:00
|
|
|
Identified(RemoteInfo),
|
2019-09-02 11:16:52 +02:00
|
|
|
/// We received a request for identification.
|
|
|
|
Identify(ReplySubstream<Negotiated<TSubstream>>),
|
2018-11-02 10:06:59 +01:00
|
|
|
/// Failed to identify the remote.
|
2019-09-16 11:08:44 +02:00
|
|
|
IdentificationError(ProtocolsHandlerUpgrErr<ReadOneError>),
|
2018-11-02 10:06:59 +01:00
|
|
|
}
|
|
|
|
|
2019-09-02 11:16:52 +02:00
|
|
|
impl<TSubstream> IdentifyHandler<TSubstream> {
|
|
|
|
/// Creates a new `IdentifyHandler`.
|
2018-11-02 10:06:59 +01:00
|
|
|
pub fn new() -> Self {
|
2019-09-02 11:16:52 +02:00
|
|
|
IdentifyHandler {
|
2018-11-20 15:09:59 +01:00
|
|
|
config: IdentifyProtocolConfig,
|
2019-09-02 11:16:52 +02:00
|
|
|
events: SmallVec::new(),
|
2019-09-16 11:08:44 +02:00
|
|
|
next_id: Delay::new(DELAY_TO_FIRST_ID),
|
2019-09-02 11:16:52 +02:00
|
|
|
keep_alive: KeepAlive::Yes,
|
2018-11-02 10:06:59 +01:00
|
|
|
marker: PhantomData,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-02 11:16:52 +02:00
|
|
|
impl<TSubstream> ProtocolsHandler for IdentifyHandler<TSubstream>
|
2018-11-02 10:06:59 +01:00
|
|
|
where
|
2019-11-26 14:47:49 +01:00
|
|
|
TSubstream: AsyncRead + AsyncWrite + Unpin + Send + 'static,
|
2018-11-02 10:06:59 +01:00
|
|
|
{
|
2019-11-06 16:09:15 +01:00
|
|
|
type InEvent = ();
|
2019-09-02 11:16:52 +02:00
|
|
|
type OutEvent = IdentifyHandlerEvent<TSubstream>;
|
2019-09-16 11:08:44 +02:00
|
|
|
type Error = ReadOneError;
|
2018-11-02 10:06:59 +01:00
|
|
|
type Substream = TSubstream;
|
2019-09-02 11:16:52 +02:00
|
|
|
type InboundProtocol = IdentifyProtocolConfig;
|
2018-11-20 15:09:59 +01:00
|
|
|
type OutboundProtocol = IdentifyProtocolConfig;
|
2018-11-02 10:06:59 +01:00
|
|
|
type OutboundOpenInfo = ();
|
|
|
|
|
2019-04-16 15:57:29 +02:00
|
|
|
fn listen_protocol(&self) -> SubstreamProtocol<Self::InboundProtocol> {
|
2019-09-02 11:16:52 +02:00
|
|
|
SubstreamProtocol::new(self.config.clone())
|
2018-11-15 17:41:11 +01:00
|
|
|
}
|
|
|
|
|
2019-09-02 11:16:52 +02:00
|
|
|
fn inject_fully_negotiated_inbound(
|
|
|
|
&mut self,
|
|
|
|
protocol: <Self::InboundProtocol as InboundUpgrade<TSubstream>>::Output
|
|
|
|
) {
|
|
|
|
self.events.push(IdentifyHandlerEvent::Identify(protocol))
|
2018-11-15 17:41:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
fn inject_fully_negotiated_outbound(
|
2018-11-02 10:06:59 +01:00
|
|
|
&mut self,
|
2018-11-15 17:41:11 +01:00
|
|
|
protocol: <Self::OutboundProtocol as OutboundUpgrade<TSubstream>>::Output,
|
|
|
|
_info: Self::OutboundOpenInfo,
|
2018-11-02 10:06:59 +01:00
|
|
|
) {
|
2019-09-02 11:16:52 +02:00
|
|
|
self.events.push(IdentifyHandlerEvent::Identified(protocol));
|
|
|
|
self.keep_alive = KeepAlive::No;
|
2018-11-02 10:06:59 +01:00
|
|
|
}
|
|
|
|
|
2018-11-05 16:53:04 +01:00
|
|
|
fn inject_event(&mut self, _: Self::InEvent) {}
|
2018-11-02 10:06:59 +01:00
|
|
|
|
2019-09-02 11:16:52 +02:00
|
|
|
fn inject_dial_upgrade_error(
|
|
|
|
&mut self,
|
|
|
|
_info: Self::OutboundOpenInfo,
|
|
|
|
err: ProtocolsHandlerUpgrErr<
|
|
|
|
<Self::OutboundProtocol as OutboundUpgrade<Self::Substream>>::Error
|
|
|
|
>
|
|
|
|
) {
|
|
|
|
self.events.push(IdentifyHandlerEvent::IdentificationError(err));
|
|
|
|
self.keep_alive = KeepAlive::No;
|
2019-09-16 11:08:44 +02:00
|
|
|
self.next_id.reset(TRY_AGAIN_ON_ERR);
|
2018-11-02 10:06:59 +01:00
|
|
|
}
|
|
|
|
|
2019-01-30 16:37:34 +01:00
|
|
|
fn connection_keep_alive(&self) -> KeepAlive {
|
2019-09-02 11:16:52 +02:00
|
|
|
self.keep_alive
|
2019-01-04 12:02:39 +01:00
|
|
|
}
|
|
|
|
|
2019-09-16 11:08:44 +02:00
|
|
|
fn poll(&mut self, cx: &mut Context) -> Poll<
|
2019-01-02 14:22:23 +01:00
|
|
|
ProtocolsHandlerEvent<
|
|
|
|
Self::OutboundProtocol,
|
|
|
|
Self::OutboundOpenInfo,
|
2019-09-02 11:16:52 +02:00
|
|
|
IdentifyHandlerEvent<TSubstream>,
|
2019-09-16 11:08:44 +02:00
|
|
|
Self::Error,
|
2018-11-02 10:06:59 +01:00
|
|
|
>,
|
|
|
|
> {
|
2019-09-02 11:16:52 +02:00
|
|
|
if !self.events.is_empty() {
|
2019-09-16 11:08:44 +02:00
|
|
|
return Poll::Ready(ProtocolsHandlerEvent::Custom(
|
2019-09-02 11:16:52 +02:00
|
|
|
self.events.remove(0),
|
2019-09-16 11:08:44 +02:00
|
|
|
));
|
2018-11-02 10:06:59 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Poll the future that fires when we need to identify the node again.
|
2019-09-16 11:08:44 +02:00
|
|
|
match Future::poll(Pin::new(&mut self.next_id), cx) {
|
|
|
|
Poll::Pending => Poll::Pending,
|
|
|
|
Poll::Ready(Ok(())) => {
|
|
|
|
self.next_id.reset(DELAY_TO_NEXT_ID);
|
2019-04-16 15:57:29 +02:00
|
|
|
let ev = ProtocolsHandlerEvent::OutboundSubstreamRequest {
|
|
|
|
protocol: SubstreamProtocol::new(self.config.clone()),
|
|
|
|
info: (),
|
|
|
|
};
|
2019-09-16 11:08:44 +02:00
|
|
|
Poll::Ready(ev)
|
2018-11-02 10:06:59 +01:00
|
|
|
}
|
2019-09-16 11:08:44 +02:00
|
|
|
Poll::Ready(Err(err)) => Poll::Ready(ProtocolsHandlerEvent::Close(err.into()))
|
2018-11-02 10:06:59 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|