2018-12-07 10:23:38 +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.
|
|
|
|
|
2023-02-24 10:43:33 +11:00
|
|
|
use crate::handler::{self, Handler, InEvent};
|
2023-05-08 16:36:30 +02:00
|
|
|
use crate::protocol::{Info, UpgradeError};
|
2023-03-13 01:46:58 +11:00
|
|
|
use libp2p_core::{multiaddr, ConnectedPoint, Endpoint, Multiaddr};
|
|
|
|
use libp2p_identity::PeerId;
|
|
|
|
use libp2p_identity::PublicKey;
|
2023-02-24 10:43:33 +11:00
|
|
|
use libp2p_swarm::behaviour::{ConnectionClosed, ConnectionEstablished, DialFailure, FromSwarm};
|
2019-07-04 14:47:59 +02:00
|
|
|
use libp2p_swarm::{
|
2023-05-24 09:52:16 +02:00
|
|
|
ConnectionDenied, DialError, ExternalAddresses, ListenAddresses, NetworkBehaviour,
|
|
|
|
NotifyHandler, PollParameters, StreamUpgradeError, THandlerInEvent, ToSwarm,
|
2019-07-04 14:47:59 +02:00
|
|
|
};
|
2023-02-24 10:43:33 +11:00
|
|
|
use libp2p_swarm::{ConnectionId, THandler, THandlerOutEvent};
|
2021-10-14 06:46:34 +11:00
|
|
|
use lru::LruCache;
|
2022-09-27 11:39:10 +10:00
|
|
|
use std::num::NonZeroUsize;
|
2020-03-31 15:41:13 +02:00
|
|
|
use std::{
|
2021-03-18 12:47:01 +01:00
|
|
|
collections::{HashMap, HashSet, VecDeque},
|
2021-10-14 06:46:34 +11:00
|
|
|
iter::FromIterator,
|
2020-03-31 15:41:13 +02:00
|
|
|
task::Context,
|
2021-03-18 12:47:01 +01:00
|
|
|
task::Poll,
|
|
|
|
time::Duration,
|
2020-03-31 15:41:13 +02:00
|
|
|
};
|
2018-12-07 10:23:38 +01:00
|
|
|
|
|
|
|
/// Network behaviour that automatically identifies nodes periodically, returns information
|
|
|
|
/// about them, and answers identify queries from other nodes.
|
2020-11-18 15:52:33 +01:00
|
|
|
///
|
|
|
|
/// All external addresses of the local node supposedly observed by remotes
|
2023-05-24 09:52:16 +02:00
|
|
|
/// are reported via [`ToSwarm::NewExternalAddrCandidate`].
|
2022-10-04 01:17:31 +01:00
|
|
|
pub struct Behaviour {
|
|
|
|
config: Config,
|
2018-12-07 10:23:38 +01:00
|
|
|
/// For each peer we're connected to, the observed address to send back to it.
|
2021-03-18 12:47:01 +01:00
|
|
|
connected: HashMap<PeerId, HashMap<ConnectionId, Multiaddr>>,
|
2019-09-02 11:16:52 +02:00
|
|
|
/// Pending events to be emitted when polled.
|
2023-03-24 14:43:49 +01:00
|
|
|
events: VecDeque<ToSwarm<Event, InEvent>>,
|
2021-10-14 06:46:34 +11:00
|
|
|
/// The addresses of all peers that we have discovered.
|
2022-09-27 11:39:10 +10:00
|
|
|
discovered_peers: PeerCache,
|
2022-12-14 11:50:08 +11:00
|
|
|
|
|
|
|
listen_addresses: ListenAddresses,
|
|
|
|
external_addresses: ExternalAddresses,
|
2019-09-02 11:16:52 +02:00
|
|
|
}
|
|
|
|
|
2022-10-04 01:17:31 +01:00
|
|
|
/// Configuration for the [`identify::Behaviour`](Behaviour).
|
2021-03-18 12:47:01 +01:00
|
|
|
#[non_exhaustive]
|
2022-02-16 17:16:54 +02:00
|
|
|
#[derive(Debug, Clone)]
|
2022-10-04 01:17:31 +01:00
|
|
|
pub struct Config {
|
2021-03-18 12:47:01 +01:00
|
|
|
/// Application-specific version of the protocol family used by the peer,
|
|
|
|
/// e.g. `ipfs/1.0.0` or `polkadot/1.0.0`.
|
|
|
|
pub protocol_version: String,
|
|
|
|
/// The public key of the local node. To report on the wire.
|
|
|
|
pub local_public_key: PublicKey,
|
|
|
|
/// Name and version of the local peer implementation, similar to the
|
|
|
|
/// `User-Agent` header in the HTTP protocol.
|
|
|
|
///
|
|
|
|
/// Defaults to `rust-libp2p/<libp2p-identify-version>`.
|
|
|
|
pub agent_version: String,
|
|
|
|
/// The initial delay before the first identification request
|
|
|
|
/// is sent to a remote on a newly established connection.
|
|
|
|
///
|
2023-05-02 16:24:56 +02:00
|
|
|
/// Defaults to 0ms.
|
|
|
|
#[deprecated(note = "The `initial_delay` is no longer necessary and will be
|
|
|
|
completely removed since a remote should be able to instantly
|
|
|
|
answer to an identify request")]
|
2021-03-18 12:47:01 +01:00
|
|
|
pub initial_delay: Duration,
|
|
|
|
/// The interval at which identification requests are sent to
|
|
|
|
/// the remote on established connections after the first request,
|
|
|
|
/// i.e. the delay between identification requests.
|
|
|
|
///
|
|
|
|
/// Defaults to 5 minutes.
|
|
|
|
pub interval: Duration,
|
2021-03-22 10:53:30 +01:00
|
|
|
|
|
|
|
/// Whether new or expired listen addresses of the local node should
|
|
|
|
/// trigger an active push of an identify message to all connected peers.
|
|
|
|
///
|
|
|
|
/// Enabling this option can result in connected peers being informed
|
|
|
|
/// earlier about new or expired listen addresses of the local node,
|
|
|
|
/// i.e. before the next periodic identify request with each peer.
|
|
|
|
///
|
|
|
|
/// Disabled by default.
|
|
|
|
pub push_listen_addr_updates: bool,
|
2021-10-14 06:46:34 +11:00
|
|
|
|
|
|
|
/// How many entries of discovered peers to keep before we discard
|
|
|
|
/// the least-recently used one.
|
2021-10-27 18:25:37 +02:00
|
|
|
///
|
|
|
|
/// Disabled by default.
|
2021-10-14 06:46:34 +11:00
|
|
|
pub cache_size: usize,
|
2021-03-18 12:47:01 +01:00
|
|
|
}
|
|
|
|
|
2022-10-04 01:17:31 +01:00
|
|
|
impl Config {
|
|
|
|
/// Creates a new configuration for the identify [`Behaviour`] that
|
2021-03-18 12:47:01 +01:00
|
|
|
/// advertises the given protocol version and public key.
|
2023-05-02 16:24:56 +02:00
|
|
|
#[allow(deprecated)]
|
2021-03-18 12:47:01 +01:00
|
|
|
pub fn new(protocol_version: String, local_public_key: PublicKey) -> Self {
|
2022-10-04 01:17:31 +01:00
|
|
|
Self {
|
2021-03-18 12:47:01 +01:00
|
|
|
protocol_version,
|
|
|
|
agent_version: format!("rust-libp2p/{}", env!("CARGO_PKG_VERSION")),
|
|
|
|
local_public_key,
|
2023-05-02 16:24:56 +02:00
|
|
|
initial_delay: Duration::from_millis(0),
|
2021-03-18 12:47:01 +01:00
|
|
|
interval: Duration::from_secs(5 * 60),
|
2021-03-22 10:53:30 +01:00
|
|
|
push_listen_addr_updates: false,
|
2022-11-05 01:10:30 +05:30
|
|
|
cache_size: 100,
|
2021-03-18 12:47:01 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Configures the agent version sent to peers.
|
|
|
|
pub fn with_agent_version(mut self, v: String) -> Self {
|
|
|
|
self.agent_version = v;
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Configures the initial delay before the first identification
|
|
|
|
/// request is sent on a newly established connection to a peer.
|
2023-05-02 16:24:56 +02:00
|
|
|
#[deprecated(note = "The `initial_delay` is no longer necessary and will be
|
|
|
|
completely removed since a remote should be able to instantly
|
|
|
|
answer to an identify request thus also this setter will be removed")]
|
|
|
|
#[allow(deprecated)]
|
2021-03-18 12:47:01 +01:00
|
|
|
pub fn with_initial_delay(mut self, d: Duration) -> Self {
|
|
|
|
self.initial_delay = d;
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Configures the interval at which identification requests are
|
|
|
|
/// sent to peers after the initial request.
|
|
|
|
pub fn with_interval(mut self, d: Duration) -> Self {
|
|
|
|
self.interval = d;
|
|
|
|
self
|
|
|
|
}
|
2021-03-22 10:53:30 +01:00
|
|
|
|
|
|
|
/// Configures whether new or expired listen addresses of the local
|
|
|
|
/// node should trigger an active push of an identify message to all
|
|
|
|
/// connected peers.
|
|
|
|
pub fn with_push_listen_addr_updates(mut self, b: bool) -> Self {
|
|
|
|
self.push_listen_addr_updates = b;
|
|
|
|
self
|
|
|
|
}
|
2021-10-14 06:46:34 +11:00
|
|
|
|
|
|
|
/// Configures the size of the LRU cache, caching addresses of discovered peers.
|
|
|
|
pub fn with_cache_size(mut self, cache_size: usize) -> Self {
|
|
|
|
self.cache_size = cache_size;
|
|
|
|
self
|
|
|
|
}
|
2021-03-18 12:47:01 +01:00
|
|
|
}
|
|
|
|
|
2022-10-04 01:17:31 +01:00
|
|
|
impl Behaviour {
|
|
|
|
/// Creates a new identify [`Behaviour`].
|
|
|
|
pub fn new(config: Config) -> Self {
|
2022-09-27 11:39:10 +10:00
|
|
|
let discovered_peers = match NonZeroUsize::new(config.cache_size) {
|
|
|
|
None => PeerCache::disabled(),
|
|
|
|
Some(size) => PeerCache::enabled(size),
|
|
|
|
};
|
2021-10-14 06:46:34 +11:00
|
|
|
|
2022-10-04 01:17:31 +01:00
|
|
|
Self {
|
2021-03-18 12:47:01 +01:00
|
|
|
config,
|
|
|
|
connected: HashMap::new(),
|
2018-12-07 10:23:38 +01:00
|
|
|
events: VecDeque::new(),
|
2021-10-14 06:46:34 +11:00
|
|
|
discovered_peers,
|
2022-12-14 11:50:08 +11:00
|
|
|
listen_addresses: Default::default(),
|
|
|
|
external_addresses: Default::default(),
|
2021-03-18 12:47:01 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Initiates an active push of the local peer information to the given peers.
|
|
|
|
pub fn push<I>(&mut self, peers: I)
|
|
|
|
where
|
|
|
|
I: IntoIterator<Item = PeerId>,
|
|
|
|
{
|
|
|
|
for p in peers {
|
2023-04-28 16:06:33 +02:00
|
|
|
if !self.connected.contains_key(&p) {
|
|
|
|
log::debug!("Not pushing to {p} because we are not connected");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2023-05-08 16:36:30 +02:00
|
|
|
self.events.push_back(ToSwarm::NotifyHandler {
|
2022-12-13 20:24:31 +00:00
|
|
|
peer_id: p,
|
2023-05-08 16:36:30 +02:00
|
|
|
handler: NotifyHandler::Any,
|
|
|
|
event: InEvent::Push,
|
|
|
|
});
|
2018-12-07 10:23:38 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-17 09:28:40 +00:00
|
|
|
fn on_connection_established(
|
2020-03-31 15:41:13 +02:00
|
|
|
&mut self,
|
2022-11-17 09:28:40 +00:00
|
|
|
ConnectionEstablished {
|
|
|
|
peer_id,
|
|
|
|
connection_id: conn,
|
|
|
|
endpoint,
|
|
|
|
failed_addresses,
|
|
|
|
..
|
|
|
|
}: ConnectionEstablished,
|
2020-03-31 15:41:13 +02:00
|
|
|
) {
|
|
|
|
let addr = match endpoint {
|
2022-01-17 16:35:14 +01:00
|
|
|
ConnectedPoint::Dialer { address, .. } => address.clone(),
|
2020-03-31 15:41:13 +02:00
|
|
|
ConnectedPoint::Listener { send_back_addr, .. } => send_back_addr.clone(),
|
2018-12-07 10:23:38 +01:00
|
|
|
};
|
|
|
|
|
2021-03-22 10:53:30 +01:00
|
|
|
self.connected
|
2022-11-17 09:28:40 +00:00
|
|
|
.entry(peer_id)
|
2021-03-22 10:53:30 +01:00
|
|
|
.or_default()
|
2022-11-17 09:28:40 +00:00
|
|
|
.insert(conn, addr);
|
2021-10-14 18:05:07 +02:00
|
|
|
|
2022-11-17 09:28:40 +00:00
|
|
|
if let Some(entry) = self.discovered_peers.get_mut(&peer_id) {
|
|
|
|
for addr in failed_addresses {
|
2021-10-14 18:05:07 +02:00
|
|
|
entry.remove(addr);
|
|
|
|
}
|
|
|
|
}
|
2020-03-31 15:41:13 +02:00
|
|
|
}
|
2023-05-08 16:36:30 +02:00
|
|
|
|
|
|
|
fn all_addresses(&self) -> HashSet<Multiaddr> {
|
|
|
|
self.listen_addresses
|
|
|
|
.iter()
|
|
|
|
.chain(self.external_addresses.iter())
|
|
|
|
.cloned()
|
|
|
|
.collect()
|
|
|
|
}
|
2022-11-17 09:28:40 +00:00
|
|
|
}
|
2020-03-31 15:41:13 +02:00
|
|
|
|
2022-11-17 09:28:40 +00:00
|
|
|
impl NetworkBehaviour for Behaviour {
|
2023-02-24 10:43:33 +11:00
|
|
|
type ConnectionHandler = Handler;
|
2023-05-14 12:58:08 +02:00
|
|
|
type ToSwarm = Event;
|
2021-03-22 10:53:30 +01:00
|
|
|
|
2023-05-02 16:24:56 +02:00
|
|
|
#[allow(deprecated)]
|
2023-02-24 10:43:33 +11:00
|
|
|
fn handle_established_inbound_connection(
|
|
|
|
&mut self,
|
|
|
|
_: ConnectionId,
|
|
|
|
peer: PeerId,
|
|
|
|
_: &Multiaddr,
|
|
|
|
remote_addr: &Multiaddr,
|
|
|
|
) -> Result<THandler<Self>, ConnectionDenied> {
|
|
|
|
Ok(Handler::new(
|
|
|
|
self.config.initial_delay,
|
|
|
|
self.config.interval,
|
|
|
|
peer,
|
|
|
|
self.config.local_public_key.clone(),
|
|
|
|
self.config.protocol_version.clone(),
|
|
|
|
self.config.agent_version.clone(),
|
|
|
|
remote_addr.clone(),
|
2023-05-08 16:36:30 +02:00
|
|
|
self.all_addresses(),
|
2023-02-24 10:43:33 +11:00
|
|
|
))
|
|
|
|
}
|
|
|
|
|
2023-05-02 16:24:56 +02:00
|
|
|
#[allow(deprecated)]
|
2023-02-24 10:43:33 +11:00
|
|
|
fn handle_established_outbound_connection(
|
|
|
|
&mut self,
|
|
|
|
_: ConnectionId,
|
|
|
|
peer: PeerId,
|
|
|
|
addr: &Multiaddr,
|
|
|
|
_: Endpoint,
|
|
|
|
) -> Result<THandler<Self>, ConnectionDenied> {
|
|
|
|
Ok(Handler::new(
|
2022-12-13 20:24:31 +00:00
|
|
|
self.config.initial_delay,
|
|
|
|
self.config.interval,
|
2023-02-24 10:43:33 +11:00
|
|
|
peer,
|
2022-12-13 20:24:31 +00:00
|
|
|
self.config.local_public_key.clone(),
|
|
|
|
self.config.protocol_version.clone(),
|
|
|
|
self.config.agent_version.clone(),
|
2023-02-24 10:43:33 +11:00
|
|
|
addr.clone(), // TODO: This is weird? That is the public address we dialed, shouldn't need to tell the other party?
|
2023-05-08 16:36:30 +02:00
|
|
|
self.all_addresses(),
|
2023-02-24 10:43:33 +11:00
|
|
|
))
|
2021-03-22 10:53:30 +01:00
|
|
|
}
|
|
|
|
|
2022-11-17 09:28:40 +00:00
|
|
|
fn on_connection_handler_event(
|
2018-12-07 10:23:38 +01:00
|
|
|
&mut self,
|
|
|
|
peer_id: PeerId,
|
2023-05-08 16:36:30 +02:00
|
|
|
_: ConnectionId,
|
2023-01-26 22:55:02 +11:00
|
|
|
event: THandlerOutEvent<Self>,
|
2018-12-07 10:23:38 +01:00
|
|
|
) {
|
|
|
|
match event {
|
2022-10-04 01:17:31 +01:00
|
|
|
handler::Event::Identified(mut info) => {
|
2021-11-16 04:05:47 -08:00
|
|
|
// Remove invalid multiaddrs.
|
|
|
|
info.listen_addrs
|
|
|
|
.retain(|addr| multiaddr_matches_peer_id(addr, &peer_id));
|
|
|
|
|
2021-10-14 06:46:34 +11:00
|
|
|
// Replace existing addresses to prevent other peer from filling up our memory.
|
|
|
|
self.discovered_peers
|
2022-09-27 11:39:10 +10:00
|
|
|
.put(peer_id, info.listen_addrs.iter().cloned());
|
2021-10-14 06:46:34 +11:00
|
|
|
|
2021-03-18 12:47:01 +01:00
|
|
|
let observed = info.observed_addr.clone();
|
2022-10-04 01:17:31 +01:00
|
|
|
self.events
|
2023-03-24 14:43:49 +01:00
|
|
|
.push_back(ToSwarm::GenerateEvent(Event::Received { peer_id, info }));
|
2023-05-24 09:52:16 +02:00
|
|
|
self.events
|
|
|
|
.push_back(ToSwarm::NewExternalAddrCandidate(observed));
|
2018-12-07 10:23:38 +01:00
|
|
|
}
|
2023-05-10 03:51:47 +02:00
|
|
|
handler::Event::Identification => {
|
2022-12-13 20:24:31 +00:00
|
|
|
self.events
|
2023-05-10 03:51:47 +02:00
|
|
|
.push_back(ToSwarm::GenerateEvent(Event::Sent { peer_id }));
|
2022-12-13 20:24:31 +00:00
|
|
|
}
|
2022-10-04 01:17:31 +01:00
|
|
|
handler::Event::IdentificationPushed => {
|
|
|
|
self.events
|
2023-03-24 14:43:49 +01:00
|
|
|
.push_back(ToSwarm::GenerateEvent(Event::Pushed { peer_id }));
|
2021-04-10 19:46:57 +02:00
|
|
|
}
|
2022-10-04 01:17:31 +01:00
|
|
|
handler::Event::IdentificationError(error) => {
|
|
|
|
self.events
|
2023-03-24 14:43:49 +01:00
|
|
|
.push_back(ToSwarm::GenerateEvent(Event::Error { peer_id, error }));
|
2018-12-07 10:23:38 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn poll(
|
|
|
|
&mut self,
|
2022-12-13 20:24:31 +00:00
|
|
|
_cx: &mut Context<'_>,
|
2023-05-08 16:36:30 +02:00
|
|
|
_: &mut impl PollParameters,
|
2023-05-14 12:58:08 +02:00
|
|
|
) -> Poll<ToSwarm<Self::ToSwarm, THandlerInEvent<Self>>> {
|
2018-12-07 10:23:38 +01:00
|
|
|
if let Some(event) = self.events.pop_front() {
|
2019-09-16 11:08:44 +02:00
|
|
|
return Poll::Ready(event);
|
2018-12-07 10:23:38 +01:00
|
|
|
}
|
|
|
|
|
2023-05-08 16:36:30 +02:00
|
|
|
Poll::Pending
|
2018-12-07 10:23:38 +01:00
|
|
|
}
|
2021-10-14 06:46:34 +11:00
|
|
|
|
2023-02-24 10:43:33 +11:00
|
|
|
fn handle_pending_outbound_connection(
|
|
|
|
&mut self,
|
|
|
|
_connection_id: ConnectionId,
|
|
|
|
maybe_peer: Option<PeerId>,
|
|
|
|
_addresses: &[Multiaddr],
|
|
|
|
_effective_role: Endpoint,
|
|
|
|
) -> Result<Vec<Multiaddr>, ConnectionDenied> {
|
|
|
|
let peer = match maybe_peer {
|
|
|
|
None => return Ok(vec![]),
|
|
|
|
Some(peer) => peer,
|
|
|
|
};
|
|
|
|
|
|
|
|
Ok(self.discovered_peers.get(&peer))
|
2021-10-14 06:46:34 +11:00
|
|
|
}
|
2022-11-17 09:28:40 +00:00
|
|
|
|
|
|
|
fn on_swarm_event(&mut self, event: FromSwarm<Self::ConnectionHandler>) {
|
2023-05-08 16:36:30 +02:00
|
|
|
let listen_addr_changed = self.listen_addresses.on_swarm_event(&event);
|
|
|
|
let external_addr_changed = self.external_addresses.on_swarm_event(&event);
|
|
|
|
|
|
|
|
if listen_addr_changed || external_addr_changed {
|
|
|
|
// notify all connected handlers about our changed addresses
|
|
|
|
let change_events = self
|
|
|
|
.connected
|
|
|
|
.iter()
|
|
|
|
.flat_map(|(peer, map)| map.keys().map(|id| (*peer, id)))
|
|
|
|
.map(|(peer_id, connection_id)| ToSwarm::NotifyHandler {
|
|
|
|
peer_id,
|
|
|
|
handler: NotifyHandler::One(*connection_id),
|
|
|
|
event: InEvent::AddressesChanged(self.all_addresses()),
|
|
|
|
})
|
|
|
|
.collect::<Vec<_>>();
|
|
|
|
|
|
|
|
self.events.extend(change_events)
|
|
|
|
}
|
|
|
|
|
|
|
|
if listen_addr_changed && self.config.push_listen_addr_updates {
|
|
|
|
// trigger an identify push for all connected peers
|
|
|
|
let push_events = self.connected.keys().map(|peer| ToSwarm::NotifyHandler {
|
|
|
|
peer_id: *peer,
|
|
|
|
handler: NotifyHandler::Any,
|
|
|
|
event: InEvent::Push,
|
|
|
|
});
|
|
|
|
|
|
|
|
self.events.extend(push_events);
|
|
|
|
}
|
2022-12-14 11:50:08 +11:00
|
|
|
|
2022-11-17 09:28:40 +00:00
|
|
|
match event {
|
|
|
|
FromSwarm::ConnectionEstablished(connection_established) => {
|
|
|
|
self.on_connection_established(connection_established)
|
|
|
|
}
|
|
|
|
FromSwarm::ConnectionClosed(ConnectionClosed {
|
|
|
|
peer_id,
|
|
|
|
connection_id,
|
|
|
|
remaining_established,
|
|
|
|
..
|
|
|
|
}) => {
|
|
|
|
if remaining_established == 0 {
|
|
|
|
self.connected.remove(&peer_id);
|
|
|
|
} else if let Some(addrs) = self.connected.get_mut(&peer_id) {
|
|
|
|
addrs.remove(&connection_id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
FromSwarm::DialFailure(DialFailure { peer_id, error, .. }) => {
|
|
|
|
if let Some(entry) = peer_id.and_then(|id| self.discovered_peers.get_mut(&id)) {
|
|
|
|
if let DialError::Transport(errors) = error {
|
|
|
|
for (addr, _error) in errors {
|
|
|
|
entry.remove(addr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-05-08 16:36:30 +02:00
|
|
|
FromSwarm::NewListenAddr(_)
|
|
|
|
| FromSwarm::ExpiredListenAddr(_)
|
|
|
|
| FromSwarm::AddressChange(_)
|
2022-11-17 09:28:40 +00:00
|
|
|
| FromSwarm::ListenFailure(_)
|
|
|
|
| FromSwarm::NewListener(_)
|
|
|
|
| FromSwarm::ListenerError(_)
|
|
|
|
| FromSwarm::ListenerClosed(_)
|
2023-05-24 09:52:16 +02:00
|
|
|
| FromSwarm::NewExternalAddrCandidate(_)
|
|
|
|
| FromSwarm::ExternalAddrExpired(_) => {}
|
|
|
|
FromSwarm::ExternalAddrConfirmed(_) => {}
|
2022-11-17 09:28:40 +00:00
|
|
|
}
|
|
|
|
}
|
2018-12-07 10:23:38 +01:00
|
|
|
}
|
|
|
|
|
2019-09-02 11:16:52 +02:00
|
|
|
/// Event emitted by the `Identify` behaviour.
|
2021-12-07 02:13:42 +11:00
|
|
|
#[allow(clippy::large_enum_variant)]
|
2018-12-07 10:23:38 +01:00
|
|
|
#[derive(Debug)]
|
2022-10-04 01:17:31 +01:00
|
|
|
pub enum Event {
|
2021-04-10 19:46:57 +02:00
|
|
|
/// Identification information has been received from a peer.
|
2019-09-02 11:16:52 +02:00
|
|
|
Received {
|
|
|
|
/// The peer that has been identified.
|
2018-12-07 10:23:38 +01:00
|
|
|
peer_id: PeerId,
|
2019-09-02 11:16:52 +02:00
|
|
|
/// The information provided by the peer.
|
2022-10-04 01:17:31 +01:00
|
|
|
info: Info,
|
2018-12-07 10:23:38 +01:00
|
|
|
},
|
2021-04-10 19:46:57 +02:00
|
|
|
/// Identification information of the local node has been sent to a peer in
|
|
|
|
/// response to an identification request.
|
2019-09-02 11:16:52 +02:00
|
|
|
Sent {
|
|
|
|
/// The peer that the information has been sent to.
|
|
|
|
peer_id: PeerId,
|
|
|
|
},
|
2021-04-10 19:46:57 +02:00
|
|
|
/// Identification information of the local node has been actively pushed to
|
|
|
|
/// a peer.
|
|
|
|
Pushed {
|
|
|
|
/// The peer that the information has been sent to.
|
|
|
|
peer_id: PeerId,
|
|
|
|
},
|
2018-12-07 10:23:38 +01:00
|
|
|
/// Error while attempting to identify the remote.
|
|
|
|
Error {
|
2019-09-02 11:16:52 +02:00
|
|
|
/// The peer with whom the error originated.
|
2018-12-07 10:23:38 +01:00
|
|
|
peer_id: PeerId,
|
2019-09-02 11:16:52 +02:00
|
|
|
/// The error that occurred.
|
2023-05-08 10:55:17 +02:00
|
|
|
error: StreamUpgradeError<UpgradeError>,
|
2018-12-07 10:23:38 +01:00
|
|
|
},
|
|
|
|
}
|
2019-02-18 13:59:12 +01:00
|
|
|
|
2021-11-16 04:05:47 -08:00
|
|
|
/// If there is a given peer_id in the multiaddr, make sure it is the same as
|
|
|
|
/// the given peer_id. If there is no peer_id for the peer in the mutiaddr, this returns true.
|
|
|
|
fn multiaddr_matches_peer_id(addr: &Multiaddr, peer_id: &PeerId) -> bool {
|
|
|
|
let last_component = addr.iter().last();
|
2022-12-13 20:24:31 +00:00
|
|
|
if let Some(multiaddr::Protocol::P2p(multi_addr_peer_id)) = last_component {
|
2023-06-08 03:38:18 +02:00
|
|
|
return multi_addr_peer_id == *peer_id;
|
2021-11-16 04:05:47 -08:00
|
|
|
}
|
2022-05-03 13:11:48 +02:00
|
|
|
true
|
2021-11-16 04:05:47 -08:00
|
|
|
}
|
|
|
|
|
2022-09-27 11:39:10 +10:00
|
|
|
struct PeerCache(Option<LruCache<PeerId, HashSet<Multiaddr>>>);
|
|
|
|
|
|
|
|
impl PeerCache {
|
|
|
|
fn disabled() -> Self {
|
|
|
|
Self(None)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn enabled(size: NonZeroUsize) -> Self {
|
|
|
|
Self(Some(LruCache::new(size)))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_mut(&mut self, peer: &PeerId) -> Option<&mut HashSet<Multiaddr>> {
|
|
|
|
self.0.as_mut()?.get_mut(peer)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn put(&mut self, peer: PeerId, addresses: impl Iterator<Item = Multiaddr>) {
|
|
|
|
let cache = match self.0.as_mut() {
|
|
|
|
None => return,
|
|
|
|
Some(cache) => cache,
|
|
|
|
};
|
|
|
|
|
|
|
|
cache.put(peer, HashSet::from_iter(addresses));
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get(&mut self, peer: &PeerId) -> Vec<Multiaddr> {
|
|
|
|
let cache = match self.0.as_mut() {
|
|
|
|
None => return Vec::new(),
|
|
|
|
Some(cache) => cache,
|
|
|
|
};
|
|
|
|
|
|
|
|
cache
|
|
|
|
.get(peer)
|
|
|
|
.cloned()
|
|
|
|
.map(Vec::from_iter)
|
|
|
|
.unwrap_or_default()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-18 13:59:12 +01:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
2021-03-18 12:47:01 +01:00
|
|
|
use super::*;
|
2021-11-16 04:05:47 -08:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn check_multiaddr_matches_peer_id() {
|
|
|
|
let peer_id = PeerId::random();
|
|
|
|
let other_peer_id = PeerId::random();
|
|
|
|
let mut addr: Multiaddr = "/ip4/147.75.69.143/tcp/4001"
|
|
|
|
.parse()
|
|
|
|
.expect("failed to parse multiaddr");
|
|
|
|
|
|
|
|
let addr_without_peer_id: Multiaddr = addr.clone();
|
|
|
|
let mut addr_with_other_peer_id = addr.clone();
|
|
|
|
|
2023-06-08 03:38:18 +02:00
|
|
|
addr.push(multiaddr::Protocol::P2p(peer_id));
|
|
|
|
addr_with_other_peer_id.push(multiaddr::Protocol::P2p(other_peer_id));
|
2021-11-16 04:05:47 -08:00
|
|
|
|
|
|
|
assert!(multiaddr_matches_peer_id(&addr, &peer_id));
|
|
|
|
assert!(!multiaddr_matches_peer_id(
|
|
|
|
&addr_with_other_peer_id,
|
|
|
|
&peer_id
|
|
|
|
));
|
|
|
|
assert!(multiaddr_matches_peer_id(&addr_without_peer_id, &peer_id));
|
|
|
|
}
|
2019-02-18 13:59:12 +01:00
|
|
|
}
|