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
39    use super::*;
40
41    #[test]
42    fn new_listen_addr_returns_correct_changed_value() {
43        let mut addresses = ListenAddresses::default();
44
45        let changed = addresses.on_swarm_event(&new_listen_addr());
46        assert!(changed);
47
48        let changed = addresses.on_swarm_event(&new_listen_addr());
49        assert!(!changed)
50    }
51
52    #[test]
53    fn expired_listen_addr_returns_correct_changed_value() {
54        let mut addresses = ListenAddresses::default();
55        addresses.on_swarm_event(&new_listen_addr());
56
57        let changed = addresses.on_swarm_event(&expired_listen_addr());
58        assert!(changed);
59
60        let changed = addresses.on_swarm_event(&expired_listen_addr());
61        assert!(!changed)
62    }
63
64    fn new_listen_addr() -> FromSwarm<'static> {
65        FromSwarm::NewListenAddr(NewListenAddr {
66            listener_id: ListenerId::next(),
67            addr: &MEMORY_ADDR,
68        })
69    }
70
71    fn expired_listen_addr() -> FromSwarm<'static> {
72        FromSwarm::ExpiredListenAddr(ExpiredListenAddr {
73            listener_id: ListenerId::next(),
74            addr: &MEMORY_ADDR,
75        })
76    }
77
78    static MEMORY_ADDR: std::sync::LazyLock<Multiaddr> =
79        std::sync::LazyLock::new(|| Multiaddr::empty().with(Protocol::Memory(1000)));
80}