mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-06-14 18:41:22 +00:00
feat: introduce libp2p-allow-block-list
connection management module
Currently, banning peers is a first-class feature of `Swarm`. With the new connection management capabilities of `NetworkBehaviour`, we can now implement allow and block lists as a separate module. We introduce a new crate `libp2p-allow-block-list` and deprecate `Swarm::ban_peer_id` in favor of that. Related #2824. Pull-Request: #3590.
This commit is contained in:
14
Cargo.lock
generated
14
Cargo.lock
generated
@ -2157,6 +2157,7 @@ dependencies = [
|
||||
"futures-timer",
|
||||
"getrandom 0.2.8",
|
||||
"instant",
|
||||
"libp2p-allow-block-list",
|
||||
"libp2p-autonat",
|
||||
"libp2p-connection-limits",
|
||||
"libp2p-core",
|
||||
@ -2193,6 +2194,19 @@ dependencies = [
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libp2p-allow-block-list"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"async-std",
|
||||
"libp2p-core",
|
||||
"libp2p-identity",
|
||||
"libp2p-swarm",
|
||||
"libp2p-swarm-derive",
|
||||
"libp2p-swarm-test",
|
||||
"void",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libp2p-autonat"
|
||||
version = "0.10.1"
|
||||
|
@ -12,6 +12,7 @@ members = [
|
||||
"examples/rendezvous",
|
||||
"identity",
|
||||
"interop-tests",
|
||||
"misc/allow-block-list",
|
||||
"misc/connection-limits",
|
||||
"misc/keygen",
|
||||
"misc/metrics",
|
||||
|
@ -8,8 +8,12 @@
|
||||
To properly communicate this to users, we want them to add the dependency directly which makes the `alpha` version visible.
|
||||
See [PR 3580].
|
||||
|
||||
- Introduce `libp2p::allow_block_list` module and deprecate `libp2p::Swarm::ban_peer_id`.
|
||||
See [PR 3590].
|
||||
|
||||
[PR 3386]: https://github.com/libp2p/rust-libp2p/pull/3386
|
||||
[PR 3580]: https://github.com/libp2p/rust-libp2p/pull/3580
|
||||
[PR 3590]: https://github.com/libp2p/rust-libp2p/pull/3590
|
||||
|
||||
# 0.51.1
|
||||
|
||||
|
@ -96,6 +96,7 @@ futures-timer = "3.0.2" # Explicit dependency to be used in `wasm-bindgen` featu
|
||||
getrandom = "0.2.3" # Explicit dependency to be used in `wasm-bindgen` feature
|
||||
instant = "0.1.11" # Explicit dependency to be used in `wasm-bindgen` feature
|
||||
|
||||
libp2p-allow-block-list = { version = "0.1.0", path = "../misc/allow-block-list" }
|
||||
libp2p-autonat = { version = "0.10.0", path = "../protocols/autonat", optional = true }
|
||||
libp2p-connection-limits = { version = "0.1.0", path = "../misc/connection-limits" }
|
||||
libp2p-core = { version = "0.39.0", path = "../core" }
|
||||
|
@ -40,6 +40,8 @@ pub use libp2p_core::multihash;
|
||||
#[doc(inline)]
|
||||
pub use multiaddr;
|
||||
|
||||
#[doc(inline)]
|
||||
pub use libp2p_allow_block_list as allow_block_list;
|
||||
#[cfg(feature = "autonat")]
|
||||
#[doc(inline)]
|
||||
pub use libp2p_autonat as autonat;
|
||||
|
3
misc/allow-block-list/CHANGELOG.md
Normal file
3
misc/allow-block-list/CHANGELOG.md
Normal file
@ -0,0 +1,3 @@
|
||||
# 0.1.0 - unreleased
|
||||
|
||||
- Initial release.
|
21
misc/allow-block-list/Cargo.toml
Normal file
21
misc/allow-block-list/Cargo.toml
Normal file
@ -0,0 +1,21 @@
|
||||
[package]
|
||||
name = "libp2p-allow-block-list"
|
||||
edition = "2021"
|
||||
rust-version = "1.62.0"
|
||||
description = "Allow/block list connection management for libp2p."
|
||||
version = "0.1.0"
|
||||
license = "MIT"
|
||||
repository = "https://github.com/libp2p/rust-libp2p"
|
||||
keywords = ["peer-to-peer", "libp2p", "networking"]
|
||||
categories = ["network-programming", "asynchronous"]
|
||||
|
||||
[dependencies]
|
||||
libp2p-core = { version = "0.39.0", path = "../../core" }
|
||||
libp2p-swarm = { version = "0.42.0", path = "../../swarm" }
|
||||
libp2p-identity = { version = "0.1.0", path = "../../identity", features = ["peerid"] }
|
||||
void = "1"
|
||||
|
||||
[dev-dependencies]
|
||||
async-std = { version = "1.12.0", features = ["attributes"] }
|
||||
libp2p-swarm-derive = { path = "../../swarm-derive" }
|
||||
libp2p-swarm-test = { path = "../../swarm-test" }
|
466
misc/allow-block-list/src/lib.rs
Normal file
466
misc/allow-block-list/src/lib.rs
Normal file
@ -0,0 +1,466 @@
|
||||
// Copyright 2023 Protocol Labs.
|
||||
//
|
||||
// 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.
|
||||
|
||||
//! A libp2p module for managing allow and blocks lists to peers.
|
||||
//!
|
||||
//! # Allow list example
|
||||
//!
|
||||
//! ```rust
|
||||
//! # use libp2p_swarm::Swarm;
|
||||
//! # use libp2p_swarm_derive::NetworkBehaviour;
|
||||
//! # use libp2p_allow_block_list as allow_block_list;
|
||||
//! # use libp2p_allow_block_list::AllowedPeers;
|
||||
//! #
|
||||
//! #[derive(NetworkBehaviour)]
|
||||
//! # #[behaviour(prelude = "libp2p_swarm::derive_prelude")]
|
||||
//! struct MyBehaviour {
|
||||
//! allowed_peers: allow_block_list::Behaviour<AllowedPeers>,
|
||||
//! }
|
||||
//!
|
||||
//! # fn main() {
|
||||
//! let behaviour = MyBehaviour {
|
||||
//! allowed_peers: allow_block_list::Behaviour::default()
|
||||
//! };
|
||||
//! # }
|
||||
//! ```
|
||||
//! # Block list example
|
||||
//!
|
||||
//! ```rust
|
||||
//! # use libp2p_swarm::Swarm;
|
||||
//! # use libp2p_swarm_derive::NetworkBehaviour;
|
||||
//! # use libp2p_allow_block_list as allow_block_list;
|
||||
//! # use libp2p_allow_block_list::BlockedPeers;
|
||||
//! #
|
||||
//! #[derive(NetworkBehaviour)]
|
||||
//! # #[behaviour(prelude = "libp2p_swarm::derive_prelude")]
|
||||
//! struct MyBehaviour {
|
||||
//! blocked_peers: allow_block_list::Behaviour<BlockedPeers>,
|
||||
//! }
|
||||
//!
|
||||
//! # fn main() {
|
||||
//! let behaviour = MyBehaviour {
|
||||
//! blocked_peers: allow_block_list::Behaviour::default()
|
||||
//! };
|
||||
//! # }
|
||||
//! ```
|
||||
|
||||
use libp2p_core::{Endpoint, Multiaddr};
|
||||
use libp2p_identity::PeerId;
|
||||
use libp2p_swarm::{
|
||||
dummy, CloseConnection, ConnectionDenied, ConnectionId, FromSwarm, NetworkBehaviour,
|
||||
NetworkBehaviourAction, PollParameters, THandler, THandlerInEvent, THandlerOutEvent,
|
||||
};
|
||||
use std::collections::{HashSet, VecDeque};
|
||||
use std::fmt;
|
||||
use std::task::{Context, Poll, Waker};
|
||||
use void::Void;
|
||||
|
||||
/// A [`NetworkBehaviour`] that can act as an allow or block list.
|
||||
#[derive(Default, Debug)]
|
||||
pub struct Behaviour<S> {
|
||||
state: S,
|
||||
close_connections: VecDeque<PeerId>,
|
||||
waker: Option<Waker>,
|
||||
}
|
||||
|
||||
/// The list of explicitly allowed peers.
|
||||
#[derive(Default)]
|
||||
pub struct AllowedPeers {
|
||||
peers: HashSet<PeerId>,
|
||||
}
|
||||
|
||||
/// The list of explicitly blocked peers.
|
||||
#[derive(Default)]
|
||||
pub struct BlockedPeers {
|
||||
peers: HashSet<PeerId>,
|
||||
}
|
||||
|
||||
impl Behaviour<AllowedPeers> {
|
||||
/// Allow connections to the given peer.
|
||||
pub fn allow_peer(&mut self, peer: PeerId) {
|
||||
self.state.peers.insert(peer);
|
||||
if let Some(waker) = self.waker.take() {
|
||||
waker.wake()
|
||||
}
|
||||
}
|
||||
|
||||
/// Disallow connections to the given peer.
|
||||
///
|
||||
/// All active connections to this peer will be closed immediately.
|
||||
pub fn disallow_peer(&mut self, peer: PeerId) {
|
||||
self.state.peers.insert(peer);
|
||||
self.close_connections.push_back(peer);
|
||||
if let Some(waker) = self.waker.take() {
|
||||
waker.wake()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Behaviour<BlockedPeers> {
|
||||
/// Block connections to a given peer.
|
||||
///
|
||||
/// All active connections to this peer will be closed immediately.
|
||||
pub fn block_peer(&mut self, peer: PeerId) {
|
||||
self.state.peers.insert(peer);
|
||||
self.close_connections.push_back(peer);
|
||||
if let Some(waker) = self.waker.take() {
|
||||
waker.wake()
|
||||
}
|
||||
}
|
||||
|
||||
/// Unblock connections to a given peer.
|
||||
pub fn unblock_peer(&mut self, peer: PeerId) {
|
||||
self.state.peers.insert(peer);
|
||||
if let Some(waker) = self.waker.take() {
|
||||
waker.wake()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A connection to this peer is not explicitly allowed and was thus [`denied`](ConnectionDenied).
|
||||
#[derive(Debug)]
|
||||
pub struct NotAllowed {
|
||||
peer: PeerId,
|
||||
}
|
||||
|
||||
impl fmt::Display for NotAllowed {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "peer {} is not in the allow list", self.peer)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for NotAllowed {}
|
||||
|
||||
/// A connection to this peer was explicitly blocked and was thus [`denied`](ConnectionDenied).
|
||||
#[derive(Debug)]
|
||||
pub struct Blocked {
|
||||
peer: PeerId,
|
||||
}
|
||||
|
||||
impl fmt::Display for Blocked {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "peer {} is in the block list", self.peer)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for Blocked {}
|
||||
|
||||
trait Enforce: 'static {
|
||||
fn enforce(&self, peer: &PeerId) -> Result<(), ConnectionDenied>;
|
||||
}
|
||||
|
||||
impl Enforce for AllowedPeers {
|
||||
fn enforce(&self, peer: &PeerId) -> Result<(), ConnectionDenied> {
|
||||
if !self.peers.contains(peer) {
|
||||
return Err(ConnectionDenied::new(NotAllowed { peer: *peer }));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Enforce for BlockedPeers {
|
||||
fn enforce(&self, peer: &PeerId) -> Result<(), ConnectionDenied> {
|
||||
if self.peers.contains(peer) {
|
||||
return Err(ConnectionDenied::new(Blocked { peer: *peer }));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> NetworkBehaviour for Behaviour<S>
|
||||
where
|
||||
S: Enforce,
|
||||
{
|
||||
type ConnectionHandler = dummy::ConnectionHandler;
|
||||
type OutEvent = Void;
|
||||
|
||||
fn handle_established_inbound_connection(
|
||||
&mut self,
|
||||
_: ConnectionId,
|
||||
peer: PeerId,
|
||||
_: &Multiaddr,
|
||||
_: &Multiaddr,
|
||||
) -> Result<THandler<Self>, ConnectionDenied> {
|
||||
self.state.enforce(&peer)?;
|
||||
|
||||
Ok(dummy::ConnectionHandler)
|
||||
}
|
||||
|
||||
fn handle_pending_outbound_connection(
|
||||
&mut self,
|
||||
_: ConnectionId,
|
||||
peer: Option<PeerId>,
|
||||
_: &[Multiaddr],
|
||||
_: Endpoint,
|
||||
) -> Result<Vec<Multiaddr>, ConnectionDenied> {
|
||||
if let Some(peer) = peer {
|
||||
self.state.enforce(&peer)?;
|
||||
}
|
||||
|
||||
Ok(vec![])
|
||||
}
|
||||
|
||||
fn handle_established_outbound_connection(
|
||||
&mut self,
|
||||
_: ConnectionId,
|
||||
peer: PeerId,
|
||||
_: &Multiaddr,
|
||||
_: Endpoint,
|
||||
) -> Result<THandler<Self>, ConnectionDenied> {
|
||||
self.state.enforce(&peer)?;
|
||||
|
||||
Ok(dummy::ConnectionHandler)
|
||||
}
|
||||
|
||||
fn on_swarm_event(&mut self, event: FromSwarm<Self::ConnectionHandler>) {
|
||||
match event {
|
||||
FromSwarm::ConnectionClosed(_) => {}
|
||||
FromSwarm::ConnectionEstablished(_) => {}
|
||||
FromSwarm::AddressChange(_) => {}
|
||||
FromSwarm::DialFailure(_) => {}
|
||||
FromSwarm::ListenFailure(_) => {}
|
||||
FromSwarm::NewListener(_) => {}
|
||||
FromSwarm::NewListenAddr(_) => {}
|
||||
FromSwarm::ExpiredListenAddr(_) => {}
|
||||
FromSwarm::ListenerError(_) => {}
|
||||
FromSwarm::ListenerClosed(_) => {}
|
||||
FromSwarm::NewExternalAddr(_) => {}
|
||||
FromSwarm::ExpiredExternalAddr(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn on_connection_handler_event(
|
||||
&mut self,
|
||||
_id: PeerId,
|
||||
_: ConnectionId,
|
||||
event: THandlerOutEvent<Self>,
|
||||
) {
|
||||
void::unreachable(event)
|
||||
}
|
||||
|
||||
fn poll(
|
||||
&mut self,
|
||||
cx: &mut Context<'_>,
|
||||
_: &mut impl PollParameters,
|
||||
) -> Poll<NetworkBehaviourAction<Self::OutEvent, THandlerInEvent<Self>>> {
|
||||
if let Some(peer) = self.close_connections.pop_front() {
|
||||
return Poll::Ready(NetworkBehaviourAction::CloseConnection {
|
||||
peer_id: peer,
|
||||
connection: CloseConnection::All,
|
||||
});
|
||||
}
|
||||
|
||||
self.waker = Some(cx.waker().clone());
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use libp2p_swarm::{dial_opts::DialOpts, DialError, ListenError, Swarm, SwarmEvent};
|
||||
use libp2p_swarm_test::SwarmExt;
|
||||
|
||||
#[async_std::test]
|
||||
async fn cannot_dial_blocked_peer() {
|
||||
let mut dialer = Swarm::new_ephemeral(|_| Behaviour::<BlockedPeers>::new());
|
||||
let mut listener = Swarm::new_ephemeral(|_| Behaviour::<BlockedPeers>::new());
|
||||
listener.listen().await;
|
||||
|
||||
dialer
|
||||
.behaviour_mut()
|
||||
.list
|
||||
.block_peer(*listener.local_peer_id());
|
||||
|
||||
let DialError::Denied { cause } = dial(&mut dialer, &listener).unwrap_err() else {
|
||||
panic!("unexpected dial error")
|
||||
};
|
||||
assert!(cause.downcast::<Blocked>().is_ok());
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn blocked_peer_cannot_dial_us() {
|
||||
let mut dialer = Swarm::new_ephemeral(|_| Behaviour::<BlockedPeers>::new());
|
||||
let mut listener = Swarm::new_ephemeral(|_| Behaviour::<BlockedPeers>::new());
|
||||
listener.listen().await;
|
||||
|
||||
listener
|
||||
.behaviour_mut()
|
||||
.list
|
||||
.block_peer(*dialer.local_peer_id());
|
||||
dial(&mut dialer, &listener).unwrap();
|
||||
async_std::task::spawn(dialer.loop_on_next());
|
||||
|
||||
let cause = listener
|
||||
.wait(|e| match e {
|
||||
SwarmEvent::IncomingConnectionError {
|
||||
error: ListenError::Denied { cause },
|
||||
..
|
||||
} => Some(cause),
|
||||
_ => None,
|
||||
})
|
||||
.await;
|
||||
assert!(cause.downcast::<Blocked>().is_ok());
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn connections_get_closed_upon_blocked() {
|
||||
let mut dialer = Swarm::new_ephemeral(|_| Behaviour::<BlockedPeers>::new());
|
||||
let mut listener = Swarm::new_ephemeral(|_| Behaviour::<BlockedPeers>::new());
|
||||
listener.listen().await;
|
||||
dialer.connect(&mut listener).await;
|
||||
|
||||
dialer
|
||||
.behaviour_mut()
|
||||
.list
|
||||
.block_peer(*listener.local_peer_id());
|
||||
|
||||
let (
|
||||
[SwarmEvent::ConnectionClosed { peer_id: closed_dialer_peer, .. }],
|
||||
[SwarmEvent::ConnectionClosed { peer_id: closed_listener_peer, .. }]
|
||||
) = libp2p_swarm_test::drive(&mut dialer, &mut listener).await else {
|
||||
panic!("unexpected events")
|
||||
};
|
||||
assert_eq!(closed_dialer_peer, *listener.local_peer_id());
|
||||
assert_eq!(closed_listener_peer, *dialer.local_peer_id());
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn cannot_dial_peer_unless_allowed() {
|
||||
let mut dialer = Swarm::new_ephemeral(|_| Behaviour::<AllowedPeers>::new());
|
||||
let mut listener = Swarm::new_ephemeral(|_| Behaviour::<AllowedPeers>::new());
|
||||
listener.listen().await;
|
||||
|
||||
let DialError::Denied { cause } = dial(&mut dialer, &listener).unwrap_err() else {
|
||||
panic!("unexpected dial error")
|
||||
};
|
||||
assert!(cause.downcast::<NotAllowed>().is_ok());
|
||||
|
||||
dialer
|
||||
.behaviour_mut()
|
||||
.list
|
||||
.allow_peer(*listener.local_peer_id());
|
||||
assert!(dial(&mut dialer, &listener).is_ok());
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn not_allowed_peer_cannot_dial_us() {
|
||||
let mut dialer = Swarm::new_ephemeral(|_| Behaviour::<AllowedPeers>::new());
|
||||
let mut listener = Swarm::new_ephemeral(|_| Behaviour::<AllowedPeers>::new());
|
||||
listener.listen().await;
|
||||
|
||||
dialer
|
||||
.dial(
|
||||
DialOpts::unknown_peer_id()
|
||||
.address(
|
||||
listener
|
||||
.external_addresses()
|
||||
.map(|a| a.addr.clone())
|
||||
.next()
|
||||
.unwrap(),
|
||||
)
|
||||
.build(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let (
|
||||
[SwarmEvent::OutgoingConnectionError { error: DialError::Denied { cause: outgoing_cause }, .. }],
|
||||
[_, _, _, SwarmEvent::IncomingConnectionError { error: ListenError::Denied { cause: incoming_cause }, .. }],
|
||||
) = libp2p_swarm_test::drive(&mut dialer, &mut listener).await else {
|
||||
panic!("unexpected events")
|
||||
};
|
||||
assert!(outgoing_cause.downcast::<NotAllowed>().is_ok());
|
||||
assert!(incoming_cause.downcast::<NotAllowed>().is_ok());
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn connections_get_closed_upon_disallow() {
|
||||
let mut dialer = Swarm::new_ephemeral(|_| Behaviour::<AllowedPeers>::new());
|
||||
let mut listener = Swarm::new_ephemeral(|_| Behaviour::<AllowedPeers>::new());
|
||||
listener.listen().await;
|
||||
dialer
|
||||
.behaviour_mut()
|
||||
.list
|
||||
.allow_peer(*listener.local_peer_id());
|
||||
listener
|
||||
.behaviour_mut()
|
||||
.list
|
||||
.allow_peer(*dialer.local_peer_id());
|
||||
|
||||
dialer.connect(&mut listener).await;
|
||||
|
||||
dialer
|
||||
.behaviour_mut()
|
||||
.list
|
||||
.disallow_peer(*listener.local_peer_id());
|
||||
let (
|
||||
[SwarmEvent::ConnectionClosed { peer_id: closed_dialer_peer, .. }],
|
||||
[SwarmEvent::ConnectionClosed { peer_id: closed_listener_peer, .. }]
|
||||
) = libp2p_swarm_test::drive(&mut dialer, &mut listener).await else {
|
||||
panic!("unexpected events")
|
||||
};
|
||||
assert_eq!(closed_dialer_peer, *listener.local_peer_id());
|
||||
assert_eq!(closed_listener_peer, *dialer.local_peer_id());
|
||||
}
|
||||
|
||||
fn dial<S>(
|
||||
dialer: &mut Swarm<Behaviour<S>>,
|
||||
listener: &Swarm<Behaviour<S>>,
|
||||
) -> Result<(), DialError>
|
||||
where
|
||||
S: Enforce,
|
||||
{
|
||||
dialer.dial(
|
||||
DialOpts::peer_id(*listener.local_peer_id())
|
||||
.addresses(
|
||||
listener
|
||||
.external_addresses()
|
||||
.map(|a| a.addr.clone())
|
||||
.collect(),
|
||||
)
|
||||
.build(),
|
||||
)
|
||||
}
|
||||
|
||||
#[derive(libp2p_swarm_derive::NetworkBehaviour)]
|
||||
#[behaviour(prelude = "libp2p_swarm::derive_prelude")]
|
||||
struct Behaviour<S> {
|
||||
list: super::Behaviour<S>,
|
||||
keep_alive: libp2p_swarm::keep_alive::Behaviour,
|
||||
}
|
||||
|
||||
impl<S> Behaviour<S>
|
||||
where
|
||||
S: Default,
|
||||
{
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
list: super::Behaviour {
|
||||
waker: None,
|
||||
close_connections: VecDeque::new(),
|
||||
state: S::default(),
|
||||
},
|
||||
keep_alive: libp2p_swarm::keep_alive::Behaviour,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -223,7 +223,7 @@ impl<TBvEv, THandleErr> super::Recorder<libp2p_swarm::SwarmEvent<TBvEv, THandleE
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
libp2p_swarm::DialError::Banned => record(OutgoingConnectionError::Banned),
|
||||
#[allow(deprecated)]
|
||||
libp2p_swarm::DialError::ConnectionLimit(_) => {
|
||||
@ -250,6 +250,7 @@ impl<TBvEv, THandleErr> super::Recorder<libp2p_swarm::SwarmEvent<TBvEv, THandleE
|
||||
}
|
||||
};
|
||||
}
|
||||
#[allow(deprecated)]
|
||||
libp2p_swarm::SwarmEvent::BannedPeer { endpoint, .. } => {
|
||||
self.connected_to_banned_peer
|
||||
.get_or_create(&AddressLabels {
|
||||
|
@ -1923,6 +1923,7 @@ where
|
||||
};
|
||||
|
||||
match error {
|
||||
#[allow(deprecated)]
|
||||
DialError::Banned
|
||||
| DialError::LocalPeerId { .. }
|
||||
| DialError::InvalidPeerId { .. }
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 0.42.1 [unreleased]
|
||||
# 0.42.1 - unreleased
|
||||
|
||||
- Deprecate `ConnectionLimits` in favor of `libp2p::connection_limits`.
|
||||
See [PR 3386].
|
||||
@ -6,8 +6,12 @@
|
||||
- Introduce `ConnectionId::new_unchecked` to allow for more sophisticated, manual tests of `NetworkBehaviour`.
|
||||
See [PR 3652].
|
||||
|
||||
- Deprecate `Swarm::ban_peer_id` in favor of the new `libp2p::allow_block_list` module.
|
||||
See [PR 3590].
|
||||
|
||||
[PR 3386]: https://github.com/libp2p/rust-libp2p/pull/3386
|
||||
[PR 3652]: https://github.com/libp2p/rust-libp2p/pull/3652
|
||||
[PR 3590]: https://github.com/libp2p/rust-libp2p/pull/3590
|
||||
|
||||
# 0.42.0
|
||||
|
||||
|
@ -251,6 +251,7 @@ pub enum SwarmEvent<TBehaviourOutEvent, THandlerErr> {
|
||||
error: DialError,
|
||||
},
|
||||
/// We connected to a peer, but we immediately closed the connection because that peer is banned.
|
||||
#[deprecated(note = "Use `libp2p::allow_block_list` instead.", since = "0.42.1")]
|
||||
BannedPeer {
|
||||
/// Identity of the banned peer.
|
||||
peer_id: PeerId,
|
||||
@ -556,6 +557,7 @@ where
|
||||
if let Some(peer_id) = peer_id {
|
||||
// Check if peer is banned.
|
||||
if self.banned_peers.contains(&peer_id) {
|
||||
#[allow(deprecated)]
|
||||
let error = DialError::Banned;
|
||||
self.behaviour
|
||||
.on_swarm_event(FromSwarm::DialFailure(DialFailure {
|
||||
@ -738,6 +740,7 @@ where
|
||||
///
|
||||
/// Any incoming connection and any dialing attempt will immediately be rejected.
|
||||
/// This function has no effect if the peer is already banned.
|
||||
#[deprecated(note = "Use `libp2p::allow_block_list` instead.", since = "0.42.1")]
|
||||
pub fn ban_peer_id(&mut self, peer_id: PeerId) {
|
||||
if self.banned_peers.insert(peer_id) {
|
||||
// Note that established connections to the now banned peer are closed but not
|
||||
@ -749,6 +752,7 @@ where
|
||||
}
|
||||
|
||||
/// Unbans a peer.
|
||||
#[deprecated(note = "Use `libp2p::allow_block_list` instead.", since = "0.42.1")]
|
||||
pub fn unban_peer_id(&mut self, peer_id: PeerId) {
|
||||
self.banned_peers.remove(&peer_id);
|
||||
}
|
||||
@ -809,6 +813,7 @@ where
|
||||
established_in,
|
||||
} => {
|
||||
if self.banned_peers.contains(&peer_id) {
|
||||
#[allow(deprecated)]
|
||||
return Some(SwarmEvent::BannedPeer { peer_id, endpoint });
|
||||
}
|
||||
|
||||
@ -1716,6 +1721,7 @@ where
|
||||
#[derive(Debug)]
|
||||
pub enum DialError {
|
||||
/// The peer is currently banned.
|
||||
#[deprecated(note = "Use `libp2p::allow_block_list` instead.", since = "0.42.1")]
|
||||
Banned,
|
||||
/// The configured limit for simultaneous outgoing connections
|
||||
/// has been reached.
|
||||
@ -1776,6 +1782,7 @@ impl fmt::Display for DialError {
|
||||
f,
|
||||
"Dial error: tried to dial local peer id at {endpoint:?}."
|
||||
),
|
||||
#[allow(deprecated)]
|
||||
DialError::Banned => write!(f, "Dial error: peer is banned."),
|
||||
DialError::DialPeerConditionFalse(c) => {
|
||||
write!(f, "Dial error: condition {c:?} for dialing peer was false.")
|
||||
@ -1827,6 +1834,7 @@ impl error::Error for DialError {
|
||||
DialError::ConnectionLimit(err) => Some(err),
|
||||
DialError::LocalPeerId { .. } => None,
|
||||
DialError::NoAddresses => None,
|
||||
#[allow(deprecated)]
|
||||
DialError::Banned => None,
|
||||
DialError::DialPeerConditionFalse(_) => None,
|
||||
DialError::Aborted => None,
|
||||
@ -1926,6 +1934,9 @@ impl error::Error for ListenError {
|
||||
}
|
||||
}
|
||||
|
||||
/// A connection was denied.
|
||||
///
|
||||
/// To figure out which [`NetworkBehaviour`] denied the connection, use [`ConnectionDenied::downcast`].
|
||||
#[derive(Debug)]
|
||||
pub struct ConnectionDenied {
|
||||
inner: Box<dyn error::Error + Send + Sync + 'static>,
|
||||
@ -2117,6 +2128,7 @@ mod tests {
|
||||
/// [`FromSwarm::ConnectionEstablished`], [`FromSwarm::ConnectionClosed`]
|
||||
/// calls should be registered.
|
||||
#[test]
|
||||
#[allow(deprecated)]
|
||||
fn test_connect_disconnect_ban() {
|
||||
let _ = env_logger::try_init();
|
||||
|
||||
|
Reference in New Issue
Block a user