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