libp2p_swarm/behaviour/
listen_addresses.rs

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