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.
|
|
|
|
|
2021-03-18 12:47:01 +01:00
|
|
|
use crate::protocol::{
|
2021-08-11 13:12:12 +02:00
|
|
|
IdentifyInfo, IdentifyProtocol, IdentifyPushProtocol, InboundPush, OutboundPush, ReplySubstream,
|
2021-03-18 12:47:01 +01:00
|
|
|
};
|
2018-11-02 10:06:59 +01:00
|
|
|
use futures::prelude::*;
|
2021-10-30 12:41:30 +02:00
|
|
|
use futures_timer::Delay;
|
2021-08-11 13:12:12 +02:00
|
|
|
use libp2p_core::either::{EitherError, EitherOutput};
|
2019-09-02 11:16:52 +02:00
|
|
|
use libp2p_core::upgrade::{
|
2021-08-11 13:12:12 +02:00
|
|
|
EitherUpgrade, InboundUpgrade, OutboundUpgrade, SelectUpgrade, UpgradeError,
|
2019-09-02 11:16:52 +02:00
|
|
|
};
|
2019-07-04 14:47:59 +02:00
|
|
|
use libp2p_swarm::{
|
2021-08-11 13:12:12 +02:00
|
|
|
KeepAlive, NegotiatedSubstream, ProtocolsHandler, ProtocolsHandlerEvent,
|
|
|
|
ProtocolsHandlerUpgrErr, SubstreamProtocol,
|
2018-11-15 17:41:11 +01:00
|
|
|
};
|
2019-09-02 11:16:52 +02:00
|
|
|
use smallvec::SmallVec;
|
2021-03-18 12:47:01 +01:00
|
|
|
use std::{io, pin::Pin, task::Context, task::Poll, time::Duration};
|
2018-11-02 10:06:59 +01:00
|
|
|
|
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.
|
2020-02-07 16:29:30 +01:00
|
|
|
pub struct IdentifyHandler {
|
2019-09-02 11:16:52 +02:00
|
|
|
/// Pending events to yield.
|
2021-08-11 13:12:12 +02:00
|
|
|
events: SmallVec<
|
|
|
|
[ProtocolsHandlerEvent<
|
2021-03-18 12:47:01 +01:00
|
|
|
EitherUpgrade<IdentifyProtocol, IdentifyPushProtocol<OutboundPush>>,
|
|
|
|
(),
|
|
|
|
IdentifyHandlerEvent,
|
|
|
|
io::Error,
|
2021-08-11 13:12:12 +02:00
|
|
|
>; 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,
|
2021-03-18 12:47:01 +01:00
|
|
|
|
|
|
|
/// The interval of `next_id`, i.e. the recurrent delay.
|
|
|
|
interval: Duration,
|
2018-11-02 10:06:59 +01:00
|
|
|
}
|
|
|
|
|
2019-09-02 11:16:52 +02:00
|
|
|
/// Event produced by the `IdentifyHandler`.
|
2018-11-02 10:06:59 +01:00
|
|
|
#[derive(Debug)]
|
2020-02-07 16:29:30 +01:00
|
|
|
pub enum IdentifyHandlerEvent {
|
2021-03-18 12:47:01 +01:00
|
|
|
/// We obtained identification information from the remote.
|
|
|
|
Identified(IdentifyInfo),
|
2021-04-10 19:46:57 +02:00
|
|
|
/// We actively pushed our identification information to the remote.
|
|
|
|
IdentificationPushed,
|
2019-09-02 11:16:52 +02:00
|
|
|
/// We received a request for identification.
|
2020-02-07 16:29:30 +01:00
|
|
|
Identify(ReplySubstream<NegotiatedSubstream>),
|
2018-11-02 10:06:59 +01:00
|
|
|
/// Failed to identify the remote.
|
2021-03-18 12:47:01 +01:00
|
|
|
IdentificationError(ProtocolsHandlerUpgrErr<io::Error>),
|
2018-11-02 10:06:59 +01:00
|
|
|
}
|
|
|
|
|
2021-03-18 12:47:01 +01:00
|
|
|
/// Identifying information of the local node that is pushed to a remote.
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct IdentifyPush(pub IdentifyInfo);
|
|
|
|
|
2020-02-07 16:29:30 +01:00
|
|
|
impl IdentifyHandler {
|
2019-09-02 11:16:52 +02:00
|
|
|
/// Creates a new `IdentifyHandler`.
|
2021-03-18 12:47:01 +01:00
|
|
|
pub fn new(initial_delay: Duration, interval: Duration) -> Self {
|
2019-09-02 11:16:52 +02:00
|
|
|
IdentifyHandler {
|
|
|
|
events: SmallVec::new(),
|
2021-03-18 12:47:01 +01:00
|
|
|
next_id: Delay::new(initial_delay),
|
2019-09-02 11:16:52 +02:00
|
|
|
keep_alive: KeepAlive::Yes,
|
2021-03-18 12:47:01 +01:00
|
|
|
interval,
|
2018-11-02 10:06:59 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-07 16:29:30 +01:00
|
|
|
impl ProtocolsHandler for IdentifyHandler {
|
2021-03-18 12:47:01 +01:00
|
|
|
type InEvent = IdentifyPush;
|
2020-02-07 16:29:30 +01:00
|
|
|
type OutEvent = IdentifyHandlerEvent;
|
2021-03-18 12:47:01 +01:00
|
|
|
type Error = io::Error;
|
|
|
|
type InboundProtocol = SelectUpgrade<IdentifyProtocol, IdentifyPushProtocol<InboundPush>>;
|
|
|
|
type OutboundProtocol = EitherUpgrade<IdentifyProtocol, IdentifyPushProtocol<OutboundPush>>;
|
2018-11-02 10:06:59 +01:00
|
|
|
type OutboundOpenInfo = ();
|
2020-08-23 16:57:20 +02:00
|
|
|
type InboundOpenInfo = ();
|
2018-11-02 10:06:59 +01:00
|
|
|
|
2020-08-23 16:57:20 +02:00
|
|
|
fn listen_protocol(&self) -> SubstreamProtocol<Self::InboundProtocol, Self::InboundOpenInfo> {
|
2021-03-18 12:47:01 +01:00
|
|
|
SubstreamProtocol::new(
|
2021-08-11 13:12:12 +02:00
|
|
|
SelectUpgrade::new(IdentifyProtocol, IdentifyPushProtocol::inbound()),
|
|
|
|
(),
|
|
|
|
)
|
2018-11-15 17:41:11 +01:00
|
|
|
}
|
|
|
|
|
2019-09-02 11:16:52 +02:00
|
|
|
fn inject_fully_negotiated_inbound(
|
|
|
|
&mut self,
|
2021-03-18 12:47:01 +01:00
|
|
|
output: <Self::InboundProtocol as InboundUpgrade<NegotiatedSubstream>>::Output,
|
2021-08-11 13:12:12 +02:00
|
|
|
_: Self::InboundOpenInfo,
|
2019-09-02 11:16:52 +02:00
|
|
|
) {
|
2021-03-18 12:47:01 +01:00
|
|
|
match output {
|
2021-08-11 13:12:12 +02:00
|
|
|
EitherOutput::First(substream) => self.events.push(ProtocolsHandlerEvent::Custom(
|
|
|
|
IdentifyHandlerEvent::Identify(substream),
|
|
|
|
)),
|
|
|
|
EitherOutput::Second(info) => self.events.push(ProtocolsHandlerEvent::Custom(
|
|
|
|
IdentifyHandlerEvent::Identified(info),
|
|
|
|
)),
|
2021-03-18 12:47:01 +01:00
|
|
|
}
|
2018-11-15 17:41:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
fn inject_fully_negotiated_outbound(
|
2018-11-02 10:06:59 +01:00
|
|
|
&mut self,
|
2021-03-18 12:47:01 +01:00
|
|
|
output: <Self::OutboundProtocol as OutboundUpgrade<NegotiatedSubstream>>::Output,
|
|
|
|
_: Self::OutboundOpenInfo,
|
2018-11-02 10:06:59 +01:00
|
|
|
) {
|
2021-03-18 12:47:01 +01:00
|
|
|
match output {
|
|
|
|
EitherOutput::First(remote_info) => {
|
2021-08-11 13:12:12 +02:00
|
|
|
self.events.push(ProtocolsHandlerEvent::Custom(
|
|
|
|
IdentifyHandlerEvent::Identified(remote_info),
|
|
|
|
));
|
2021-03-18 12:47:01 +01:00
|
|
|
self.keep_alive = KeepAlive::No;
|
|
|
|
}
|
2021-08-11 13:12:12 +02:00
|
|
|
EitherOutput::Second(()) => self.events.push(ProtocolsHandlerEvent::Custom(
|
|
|
|
IdentifyHandlerEvent::IdentificationPushed,
|
|
|
|
)),
|
2021-03-18 12:47:01 +01:00
|
|
|
}
|
2018-11-02 10:06:59 +01:00
|
|
|
}
|
|
|
|
|
2021-03-18 12:47:01 +01:00
|
|
|
fn inject_event(&mut self, IdentifyPush(push): Self::InEvent) {
|
2021-08-11 13:12:12 +02:00
|
|
|
self.events
|
|
|
|
.push(ProtocolsHandlerEvent::OutboundSubstreamRequest {
|
|
|
|
protocol: SubstreamProtocol::new(
|
|
|
|
EitherUpgrade::B(IdentifyPushProtocol::outbound(push)),
|
|
|
|
(),
|
|
|
|
),
|
|
|
|
});
|
2021-03-18 12:47:01 +01:00
|
|
|
}
|
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<
|
2021-08-11 13:12:12 +02:00
|
|
|
<Self::OutboundProtocol as OutboundUpgrade<NegotiatedSubstream>>::Error,
|
|
|
|
>,
|
2019-09-02 11:16:52 +02:00
|
|
|
) {
|
2021-03-18 12:47:01 +01:00
|
|
|
let err = err.map_upgrade_err(|e| match e {
|
|
|
|
UpgradeError::Select(e) => UpgradeError::Select(e),
|
|
|
|
UpgradeError::Apply(EitherError::A(ioe)) => UpgradeError::Apply(ioe),
|
|
|
|
UpgradeError::Apply(EitherError::B(ioe)) => UpgradeError::Apply(ioe),
|
|
|
|
});
|
2021-08-11 13:12:12 +02:00
|
|
|
self.events.push(ProtocolsHandlerEvent::Custom(
|
|
|
|
IdentifyHandlerEvent::IdentificationError(err),
|
|
|
|
));
|
2019-09-02 11:16:52 +02:00
|
|
|
self.keep_alive = KeepAlive::No;
|
2021-03-18 12:47:01 +01:00
|
|
|
self.next_id.reset(self.interval);
|
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
|
|
|
}
|
|
|
|
|
2021-08-11 13:12:12 +02:00
|
|
|
fn poll(
|
|
|
|
&mut self,
|
|
|
|
cx: &mut Context<'_>,
|
|
|
|
) -> Poll<
|
2019-01-02 14:22:23 +01:00
|
|
|
ProtocolsHandlerEvent<
|
|
|
|
Self::OutboundProtocol,
|
|
|
|
Self::OutboundOpenInfo,
|
2020-02-07 16:29:30 +01:00
|
|
|
IdentifyHandlerEvent,
|
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() {
|
2021-08-11 13:12:12 +02:00
|
|
|
return Poll::Ready(self.events.remove(0));
|
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,
|
2021-10-30 12:41:30 +02:00
|
|
|
Poll::Ready(()) => {
|
2021-03-18 12:47:01 +01:00
|
|
|
self.next_id.reset(self.interval);
|
2019-04-16 15:57:29 +02:00
|
|
|
let ev = ProtocolsHandlerEvent::OutboundSubstreamRequest {
|
2021-08-11 13:12:12 +02:00
|
|
|
protocol: SubstreamProtocol::new(EitherUpgrade::A(IdentifyProtocol), ()),
|
2019-04-16 15:57:29 +02:00
|
|
|
};
|
2019-09-16 11:08:44 +02:00
|
|
|
Poll::Ready(ev)
|
2018-11-02 10:06:59 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|