feat(swarm): report outcome of handling SwarmEvent

Previously, a user wouldn't know whether passing a `SwarmEvent` to `ListenAddresses` or `ExternalAddresses` changed the state. We now return a boolean where `true` indicates that we handled the event **and** changed state as a result.

The API is inspired by `HashSet::insert` and the like.

Pull-Request: #3865.
This commit is contained in:
Thomas Eizinger 2023-05-05 09:46:31 +02:00 committed by GitHub
parent 1eb929b38a
commit eecfe2f094
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 110 additions and 8 deletions

1
Cargo.lock generated
View File

@ -2992,6 +2992,7 @@ dependencies = [
"libp2p-swarm-test", "libp2p-swarm-test",
"libp2p-yamux", "libp2p-yamux",
"log", "log",
"once_cell",
"quickcheck-ext", "quickcheck-ext",
"rand 0.8.5", "rand 0.8.5",
"smallvec", "smallvec",

View File

@ -7,8 +7,12 @@
This type enforces invariants on protocol names, such as leading forward slashes and correct UTF8 encoding. This type enforces invariants on protocol names, such as leading forward slashes and correct UTF8 encoding.
See [PR 3746]. See [PR 3746].
[PR 3746]: https://github.com/libp2p/rust-libp2p/pull/3746 - Return a bool from `ExternalAddresses::on_swarm_event` and `ListenAddresses::on_swarm_event` indicating whether any state was changed.
See [PR 3865].
[PR 3715]: https://github.com/libp2p/rust-libp2p/pull/3715 [PR 3715]: https://github.com/libp2p/rust-libp2p/pull/3715
[PR 3746]: https://github.com/libp2p/rust-libp2p/pull/3746
[PR 3865]: https://github.com/libp2p/rust-libp2p/pull/3865
## 0.42.2 ## 0.42.2

View File

@ -51,6 +51,7 @@ libp2p-swarm-test = { workspace = true }
libp2p-yamux = { workspace = true } libp2p-yamux = { workspace = true }
quickcheck = { workspace = true } quickcheck = { workspace = true }
void = "1" void = "1"
once_cell = "1.17.1"
[[test]] [[test]]
name = "swarm_derive" name = "swarm_derive"

View File

@ -32,21 +32,67 @@ impl ExternalAddresses {
} }
/// Feed a [`FromSwarm`] event to this struct. /// Feed a [`FromSwarm`] event to this struct.
///
/// Returns whether the event changed our set of external addresses.
#[allow(deprecated)] #[allow(deprecated)]
pub fn on_swarm_event<THandler>(&mut self, event: &FromSwarm<THandler>) pub fn on_swarm_event<THandler>(&mut self, event: &FromSwarm<THandler>) -> bool
where where
THandler: IntoConnectionHandler, THandler: IntoConnectionHandler,
{ {
match event { match event {
FromSwarm::NewExternalAddr(NewExternalAddr { addr, .. }) => { FromSwarm::NewExternalAddr(NewExternalAddr { addr, .. }) => {
if self.addresses.len() < self.limit { if self.addresses.len() < self.limit {
self.addresses.insert((*addr).clone()); return self.addresses.insert((*addr).clone());
} }
} }
FromSwarm::ExpiredExternalAddr(ExpiredExternalAddr { addr, .. }) => { FromSwarm::ExpiredExternalAddr(ExpiredExternalAddr { addr, .. }) => {
self.addresses.remove(addr); return self.addresses.remove(addr)
} }
_ => {} _ => {}
} }
false
} }
} }
#[cfg(test)]
mod tests {
use super::*;
use crate::dummy;
use libp2p_core::multiaddr::Protocol;
use once_cell::sync::Lazy;
#[test]
fn new_external_addr_returns_correct_changed_value() {
let mut addresses = ExternalAddresses::default();
let changed = addresses.on_swarm_event(&new_external_addr());
assert!(changed);
let changed = addresses.on_swarm_event(&new_external_addr());
assert!(!changed)
}
#[test]
fn expired_external_addr_returns_correct_changed_value() {
let mut addresses = ExternalAddresses::default();
addresses.on_swarm_event(&new_external_addr());
let changed = addresses.on_swarm_event(&expired_external_addr());
assert!(changed);
let changed = addresses.on_swarm_event(&expired_external_addr());
assert!(!changed)
}
fn new_external_addr() -> FromSwarm<'static, dummy::ConnectionHandler> {
FromSwarm::NewExternalAddr(NewExternalAddr { addr: &MEMORY_ADDR })
}
fn expired_external_addr() -> FromSwarm<'static, dummy::ConnectionHandler> {
FromSwarm::ExpiredExternalAddr(ExpiredExternalAddr { addr: &MEMORY_ADDR })
}
static MEMORY_ADDR: Lazy<Multiaddr> =
Lazy::new(|| Multiaddr::empty().with(Protocol::Memory(1000)));
}

View File

@ -17,19 +17,69 @@ impl ListenAddresses {
} }
/// Feed a [`FromSwarm`] event to this struct. /// Feed a [`FromSwarm`] event to this struct.
///
/// Returns whether the event changed our set of listen addresses.
#[allow(deprecated)] #[allow(deprecated)]
pub fn on_swarm_event<THandler>(&mut self, event: &FromSwarm<THandler>) pub fn on_swarm_event<THandler>(&mut self, event: &FromSwarm<THandler>) -> bool
where where
THandler: IntoConnectionHandler, THandler: IntoConnectionHandler,
{ {
match event { match event {
FromSwarm::NewListenAddr(NewListenAddr { addr, .. }) => { FromSwarm::NewListenAddr(NewListenAddr { addr, .. }) => {
self.addresses.insert((*addr).clone()); self.addresses.insert((*addr).clone())
} }
FromSwarm::ExpiredListenAddr(ExpiredListenAddr { addr, .. }) => { FromSwarm::ExpiredListenAddr(ExpiredListenAddr { addr, .. }) => {
self.addresses.remove(addr); self.addresses.remove(addr)
} }
_ => {} _ => false,
} }
} }
} }
#[cfg(test)]
mod tests {
use super::*;
use crate::dummy;
use libp2p_core::multiaddr::Protocol;
use once_cell::sync::Lazy;
#[test]
fn new_listen_addr_returns_correct_changed_value() {
let mut addresses = ListenAddresses::default();
let changed = addresses.on_swarm_event(&new_listen_addr());
assert!(changed);
let changed = addresses.on_swarm_event(&new_listen_addr());
assert!(!changed)
}
#[test]
fn expired_listen_addr_returns_correct_changed_value() {
let mut addresses = ListenAddresses::default();
addresses.on_swarm_event(&new_listen_addr());
let changed = addresses.on_swarm_event(&expired_listen_addr());
assert!(changed);
let changed = addresses.on_swarm_event(&expired_listen_addr());
assert!(!changed)
}
fn new_listen_addr() -> FromSwarm<'static, dummy::ConnectionHandler> {
FromSwarm::NewListenAddr(NewListenAddr {
listener_id: Default::default(),
addr: &MEMORY_ADDR,
})
}
fn expired_listen_addr() -> FromSwarm<'static, dummy::ConnectionHandler> {
FromSwarm::ExpiredListenAddr(ExpiredListenAddr {
listener_id: Default::default(),
addr: &MEMORY_ADDR,
})
}
static MEMORY_ADDR: Lazy<Multiaddr> =
Lazy::new(|| Multiaddr::empty().with(Protocol::Memory(1000)));
}