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::{
|
2022-10-04 01:17:31 +01:00
|
|
|
InboundPush, Info, OutboundPush, Protocol, PushProtocol, ReplySubstream, UpgradeError,
|
2021-03-18 12:47:01 +01:00
|
|
|
};
|
2022-06-07 13:42:34 +02:00
|
|
|
use futures::future::BoxFuture;
|
2018-11-02 10:06:59 +01:00
|
|
|
use futures::prelude::*;
|
2021-10-30 12:41:30 +02:00
|
|
|
use futures_timer::Delay;
|
2021-03-18 12:47:01 +01:00
|
|
|
use libp2p_core::either::{EitherError, EitherOutput};
|
2022-05-05 18:28:47 +02:00
|
|
|
use libp2p_core::upgrade::{EitherUpgrade, InboundUpgrade, OutboundUpgrade, SelectUpgrade};
|
2022-06-26 10:37:29 +02:00
|
|
|
use libp2p_core::{ConnectedPoint, PeerId};
|
2019-07-04 14:47:59 +02:00
|
|
|
use libp2p_swarm::{
|
2022-06-26 10:37:29 +02:00
|
|
|
ConnectionHandler, ConnectionHandlerEvent, ConnectionHandlerUpgrErr, IntoConnectionHandler,
|
|
|
|
KeepAlive, NegotiatedSubstream, SubstreamProtocol,
|
2018-11-15 17:41:11 +01:00
|
|
|
};
|
2022-06-07 13:42:34 +02:00
|
|
|
use log::warn;
|
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
|
|
|
|
2022-10-04 01:17:31 +01:00
|
|
|
pub struct Proto {
|
2022-06-26 10:37:29 +02:00
|
|
|
initial_delay: Duration,
|
|
|
|
interval: Duration,
|
|
|
|
}
|
|
|
|
|
2022-10-04 01:17:31 +01:00
|
|
|
impl Proto {
|
2022-06-26 10:37:29 +02:00
|
|
|
pub fn new(initial_delay: Duration, interval: Duration) -> Self {
|
2022-10-04 01:17:31 +01:00
|
|
|
Proto {
|
2022-06-26 10:37:29 +02:00
|
|
|
initial_delay,
|
|
|
|
interval,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-04 01:17:31 +01:00
|
|
|
impl IntoConnectionHandler for Proto {
|
|
|
|
type Handler = Handler;
|
2022-06-26 10:37:29 +02:00
|
|
|
|
|
|
|
fn into_handler(self, remote_peer_id: &PeerId, _endpoint: &ConnectedPoint) -> Self::Handler {
|
2022-10-04 01:17:31 +01:00
|
|
|
Handler::new(self.initial_delay, self.interval, *remote_peer_id)
|
2022-06-26 10:37:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fn inbound_protocol(&self) -> <Self::Handler as ConnectionHandler>::InboundProtocol {
|
2022-10-04 01:17:31 +01:00
|
|
|
SelectUpgrade::new(Protocol, PushProtocol::inbound())
|
2022-06-26 10:37:29 +02: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.
|
2022-10-04 01:17:31 +01:00
|
|
|
pub struct Handler {
|
2022-06-26 10:37:29 +02:00
|
|
|
remote_peer_id: PeerId,
|
2022-10-04 01:17:31 +01:00
|
|
|
inbound_identify_push: Option<BoxFuture<'static, Result<Info, UpgradeError>>>,
|
2019-09-02 11:16:52 +02:00
|
|
|
/// Pending events to yield.
|
2021-03-18 12:47:01 +01:00
|
|
|
events: SmallVec<
|
2022-02-21 13:32:24 +01:00
|
|
|
[ConnectionHandlerEvent<
|
2022-10-04 01:17:31 +01:00
|
|
|
EitherUpgrade<Protocol, PushProtocol<OutboundPush>>,
|
2021-03-18 12:47:01 +01:00
|
|
|
(),
|
2022-10-04 01:17:31 +01:00
|
|
|
Event,
|
2021-03-18 12:47:01 +01:00
|
|
|
io::Error,
|
|
|
|
>; 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.
|
2022-05-11 03:18:20 +02:00
|
|
|
trigger_next_identify: 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
|
|
|
|
2022-05-11 03:18:20 +02:00
|
|
|
/// The interval of `trigger_next_identify`, i.e. the recurrent delay.
|
2021-03-18 12:47:01 +01:00
|
|
|
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)]
|
2022-10-04 01:17:31 +01:00
|
|
|
pub enum Event {
|
2021-03-18 12:47:01 +01:00
|
|
|
/// We obtained identification information from the remote.
|
2022-10-04 01:17:31 +01:00
|
|
|
Identified(Info),
|
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.
|
2022-05-05 18:28:47 +02:00
|
|
|
IdentificationError(ConnectionHandlerUpgrErr<UpgradeError>),
|
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)]
|
2022-10-04 01:17:31 +01:00
|
|
|
pub struct Push(pub Info);
|
2021-03-18 12:47:01 +01:00
|
|
|
|
2022-10-04 01:17:31 +01:00
|
|
|
impl Handler {
|
2019-09-02 11:16:52 +02:00
|
|
|
/// Creates a new `IdentifyHandler`.
|
2022-06-26 10:37:29 +02:00
|
|
|
pub fn new(initial_delay: Duration, interval: Duration, remote_peer_id: PeerId) -> Self {
|
2022-10-04 01:17:31 +01:00
|
|
|
Self {
|
2022-06-26 10:37:29 +02:00
|
|
|
remote_peer_id,
|
2022-06-07 13:42:34 +02:00
|
|
|
inbound_identify_push: Default::default(),
|
2019-09-02 11:16:52 +02:00
|
|
|
events: SmallVec::new(),
|
2022-05-11 03:18:20 +02:00
|
|
|
trigger_next_identify: 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
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-04 01:17:31 +01:00
|
|
|
impl ConnectionHandler for Handler {
|
|
|
|
type InEvent = Push;
|
|
|
|
type OutEvent = Event;
|
2021-03-18 12:47:01 +01:00
|
|
|
type Error = io::Error;
|
2022-10-04 01:17:31 +01:00
|
|
|
type InboundProtocol = SelectUpgrade<Protocol, PushProtocol<InboundPush>>;
|
|
|
|
type OutboundProtocol = EitherUpgrade<Protocol, PushProtocol<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> {
|
2022-10-04 01:17:31 +01:00
|
|
|
SubstreamProtocol::new(SelectUpgrade::new(Protocol, PushProtocol::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,
|
|
|
|
_: Self::InboundOpenInfo,
|
2019-09-02 11:16:52 +02:00
|
|
|
) {
|
2021-03-18 12:47:01 +01:00
|
|
|
match output {
|
2022-10-04 01:17:31 +01:00
|
|
|
EitherOutput::First(substream) => self
|
|
|
|
.events
|
|
|
|
.push(ConnectionHandlerEvent::Custom(Event::Identify(substream))),
|
2022-06-07 13:42:34 +02:00
|
|
|
EitherOutput::Second(fut) => {
|
|
|
|
if self.inbound_identify_push.replace(fut).is_some() {
|
|
|
|
warn!(
|
2022-06-26 10:37:29 +02:00
|
|
|
"New inbound identify push stream from {} while still \
|
|
|
|
upgrading previous one. Replacing previous with new.",
|
|
|
|
self.remote_peer_id,
|
2022-06-07 13:42:34 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
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) => {
|
2022-10-04 01:17:31 +01:00
|
|
|
self.events
|
|
|
|
.push(ConnectionHandlerEvent::Custom(Event::Identified(
|
|
|
|
remote_info,
|
|
|
|
)));
|
2021-03-18 12:47:01 +01:00
|
|
|
self.keep_alive = KeepAlive::No;
|
|
|
|
}
|
2022-10-04 01:17:31 +01:00
|
|
|
EitherOutput::Second(()) => self
|
|
|
|
.events
|
|
|
|
.push(ConnectionHandlerEvent::Custom(Event::IdentificationPushed)),
|
2021-03-18 12:47:01 +01:00
|
|
|
}
|
2018-11-02 10:06:59 +01:00
|
|
|
}
|
|
|
|
|
2022-10-04 01:17:31 +01:00
|
|
|
fn inject_event(&mut self, Push(push): Self::InEvent) {
|
2021-03-18 12:47:01 +01:00
|
|
|
self.events
|
2022-02-21 13:32:24 +01:00
|
|
|
.push(ConnectionHandlerEvent::OutboundSubstreamRequest {
|
2021-03-18 12:47:01 +01:00
|
|
|
protocol: SubstreamProtocol::new(
|
2022-10-04 01:17:31 +01:00
|
|
|
EitherUpgrade::B(PushProtocol::outbound(push)),
|
2021-03-18 12:47:01 +01:00
|
|
|
(),
|
2021-08-11 13:12:12 +02:00
|
|
|
),
|
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,
|
2022-02-21 13:32:24 +01:00
|
|
|
err: ConnectionHandlerUpgrErr<
|
2020-02-07 16:29:30 +01:00
|
|
|
<Self::OutboundProtocol as OutboundUpgrade<NegotiatedSubstream>>::Error,
|
2019-09-02 11:16:52 +02:00
|
|
|
>,
|
|
|
|
) {
|
2022-05-05 18:28:47 +02:00
|
|
|
use libp2p_core::upgrade::UpgradeError;
|
|
|
|
|
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),
|
|
|
|
});
|
2022-10-04 01:17:31 +01:00
|
|
|
self.events
|
|
|
|
.push(ConnectionHandlerEvent::Custom(Event::IdentificationError(
|
|
|
|
err,
|
|
|
|
)));
|
2019-09-02 11:16:52 +02:00
|
|
|
self.keep_alive = KeepAlive::No;
|
2022-05-11 03:18:20 +02:00
|
|
|
self.trigger_next_identify.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
|
|
|
}
|
|
|
|
|
2020-07-27 20:27:33 +00:00
|
|
|
fn poll(
|
|
|
|
&mut self,
|
|
|
|
cx: &mut Context<'_>,
|
|
|
|
) -> Poll<
|
2022-10-04 01:17:31 +01:00
|
|
|
ConnectionHandlerEvent<Self::OutboundProtocol, Self::OutboundOpenInfo, Event, Self::Error>,
|
2018-11-02 10:06:59 +01:00
|
|
|
> {
|
2019-09-02 11:16:52 +02:00
|
|
|
if !self.events.is_empty() {
|
|
|
|
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.
|
2022-05-11 03:18:20 +02:00
|
|
|
match Future::poll(Pin::new(&mut self.trigger_next_identify), cx) {
|
2022-06-07 13:42:34 +02:00
|
|
|
Poll::Pending => {}
|
2021-10-30 12:41:30 +02:00
|
|
|
Poll::Ready(()) => {
|
2022-05-11 03:18:20 +02:00
|
|
|
self.trigger_next_identify.reset(self.interval);
|
2022-02-21 13:32:24 +01:00
|
|
|
let ev = ConnectionHandlerEvent::OutboundSubstreamRequest {
|
2022-10-04 01:17:31 +01:00
|
|
|
protocol: SubstreamProtocol::new(EitherUpgrade::A(Protocol), ()),
|
2019-04-16 15:57:29 +02:00
|
|
|
};
|
2022-06-07 13:42:34 +02:00
|
|
|
return Poll::Ready(ev);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if let Some(Poll::Ready(res)) = self
|
|
|
|
.inbound_identify_push
|
|
|
|
.as_mut()
|
|
|
|
.map(|f| f.poll_unpin(cx))
|
|
|
|
{
|
|
|
|
self.inbound_identify_push.take();
|
|
|
|
|
|
|
|
if let Ok(info) = res {
|
2022-10-04 01:17:31 +01:00
|
|
|
return Poll::Ready(ConnectionHandlerEvent::Custom(Event::Identified(info)));
|
2018-11-02 10:06:59 +01:00
|
|
|
}
|
|
|
|
}
|
2022-06-07 13:42:34 +02:00
|
|
|
|
|
|
|
Poll::Pending
|
2018-11-02 10:06:59 +01:00
|
|
|
}
|
|
|
|
}
|