libp2p_swarm/behaviour/
listen_addresses.rs

1use std::collections::HashSet;
2
3use libp2p_core::Multiaddr;
4
5use crate::behaviour::{ExpiredListenAddr, FromSwarm, NewListenAddr};
6
7/// Utility struct for tracking the addresses a [`Swarm`](crate::Swarm) is listening on.
8#[derive(Debug, Default, Clone)]
9pub struct ListenAddresses {
10    addresses: HashSet<Multiaddr>,
11}
12
13impl ListenAddresses {
14    /// Returns an [`Iterator`] over all listen addresses.
15    pub fn iter(&self) -> impl ExactSizeIterator<Item = &Multiaddr> {
16        self.addresses.iter()
17    }
18
19    /// Feed a [`FromSwarm`] event to this struct.
20    ///
21    /// Returns whether the event changed our set of listen addresses.
22    pub fn on_swarm_event(&mut self, event: &FromSwarm) -> bool {
23        match event {
24            FromSwarm::NewListenAddr(NewListenAddr { addr, .. }) => {
25                self.addresses.insert((*addr).clone())
26            }
27            FromSwarm::ExpiredListenAddr(ExpiredListenAddr { addr, .. }) => {
28                self.addresses.remove(addr)
29            }
30            _ => false,
31        }
32    }
33}
34
35#[cfg(test)]
36mod tests {
37    use libp2p_core::{multiaddr::Protocol, transport::ListenerId};
38    use once_cell::sync::Lazy;
39
40    use super::*;
41
42    #[test]
43    fn new_listen_addr_returns_correct_changed_value() {
44        let mut addresses = ListenAddresses::default();
45
46        let changed = addresses.on_swarm_event(&new_listen_addr());
47        assert!(changed);
48
49        let changed = addresses.on_swarm_event(&new_listen_addr());
50        assert!(!changed)
51    }
52
53    #[test]
54    fn expired_listen_addr_returns_correct_changed_value() {
55        let mut addresses = ListenAddresses::default();
56        addresses.on_swarm_event(&new_listen_addr());
57
58        let changed = addresses.on_swarm_event(&expired_listen_addr());
59        assert!(changed);
60
61        let changed = addresses.on_swarm_event(&expired_listen_addr());
62        assert!(!changed)
63    }
64
65    fn new_listen_addr() -> FromSwarm<'static> {
66        FromSwarm::NewListenAddr(NewListenAddr {
67            listener_id: ListenerId::next(),
68            addr: &MEMORY_ADDR,
69        })
70    }
71
72    fn expired_listen_addr() -> FromSwarm<'static> {
73        FromSwarm::ExpiredListenAddr(ExpiredListenAddr {
74            listener_id: ListenerId::next(),
75            addr: &MEMORY_ADDR,
76        })
77    }
78
79    static MEMORY_ADDR: Lazy<Multiaddr> =
80        Lazy::new(|| Multiaddr::empty().with(Protocol::Memory(1000)));
81}