//! The debug firewall (`/debug/firewall`, with `--debug-api`): drops messages from and //! to peers, by node ID, to test partitions on a real swarm. It works at the bottom of //! the node, in the paths layer (`transport::paths::Gate`), so it drops everything a //! partition would: WHO and ME, PINGs and their PONGs, as well as the node's messages. use std::collections::HashSet; use std::sync::{RwLock, RwLockReadGuard}; use serde::{Deserialize, Serialize}; use crate::locks::RwLockExt; #[derive(Debug, Clone, Default, Serialize, Deserialize)] pub(crate) struct FirewallRules { /// Messages from these peers are dropped before the application sees them. #[serde(default)] pub(crate) inbound: HashSet, /// Messages to these peers are silently dropped, like a lossy network. #[serde(default)] pub(crate) outbound: HashSet, } /// Uses a std lock: checks are tiny and the guard is never held across an await. #[derive(Default)] pub(crate) struct Firewall { rules: RwLock, } impl Firewall { fn read(&self) -> RwLockReadGuard<'_, FirewallRules> { self.rules.read_or_recover() } pub(crate) fn rules(&self) -> FirewallRules { self.read().clone() } pub(crate) fn set_rules(&self, rules: FirewallRules) { *self.rules.write_or_recover() = rules; } pub(crate) fn blocks_inbound(&self, peer: &str) -> bool { self.read().inbound.contains(peer) } pub(crate) fn blocks_outbound(&self, peer: &str) -> bool { self.read().outbound.contains(peer) } }