libp2p_peer_store/
behaviour.rs

1use libp2p_core::{Multiaddr, PeerId};
2use libp2p_swarm::{dummy, NetworkBehaviour};
3
4use crate::store::Store;
5
6/// Behaviour that maintains a peer address book.
7///
8/// Usage:
9/// ```
10/// use libp2p::swarm::NetworkBehaviour;
11/// use libp2p_peer_store::{memory_store::MemoryStore, Behaviour};
12///
13/// // `identify::Behaviour` broadcasts listen addresses of the peer,
14/// // `peer_store::Behaviour` will then capture the resulting
15/// // `FromSwarm::NewExternalAddrOfPeer` and add the addresses
16/// // to address book.
17/// #[derive(NetworkBehaviour)]
18/// struct ComposedBehaviour {
19///     peer_store: Behaviour<MemoryStore>,
20///     identify: libp2p::identify::Behaviour,
21/// }
22/// ```
23pub struct Behaviour<S: Store> {
24    /// The internal store.
25    store: S,
26}
27
28impl<'a, S> Behaviour<S>
29where
30    S: Store + 'static,
31{
32    /// Build a new [`Behaviour`] with the given store.
33    pub fn new(store: S) -> Self {
34        Self { store }
35    }
36
37    /// Try to get all observed address of the given peer.  
38    /// Returns `None` when the peer is not in the store.
39    pub fn address_of_peer<'b>(
40        &'a self,
41        peer: &'b PeerId,
42    ) -> Option<impl Iterator<Item = &'a Multiaddr> + use<'a, 'b, S>> {
43        self.store.addresses_of_peer(peer)
44    }
45
46    /// Get an immutable reference to the internal store.
47    pub fn store(&self) -> &S {
48        &self.store
49    }
50
51    /// Get a mutable reference to the internal store.
52    pub fn store_mut(&mut self) -> &mut S {
53        &mut self.store
54    }
55}
56
57impl<S> NetworkBehaviour for Behaviour<S>
58where
59    S: Store + 'static,
60    <S as Store>::Event: Send + Sync,
61{
62    type ConnectionHandler = dummy::ConnectionHandler;
63
64    type ToSwarm = S::Event;
65
66    fn handle_established_inbound_connection(
67        &mut self,
68        _connection_id: libp2p_swarm::ConnectionId,
69        _peer: libp2p_core::PeerId,
70        _local_addr: &libp2p_core::Multiaddr,
71        _remote_addr: &libp2p_core::Multiaddr,
72    ) -> Result<libp2p_swarm::THandler<Self>, libp2p_swarm::ConnectionDenied> {
73        Ok(dummy::ConnectionHandler)
74    }
75
76    fn handle_pending_outbound_connection(
77        &mut self,
78        _connection_id: libp2p_swarm::ConnectionId,
79        maybe_peer: Option<PeerId>,
80        _addresses: &[Multiaddr],
81        _effective_role: libp2p_core::Endpoint,
82    ) -> Result<Vec<Multiaddr>, libp2p_swarm::ConnectionDenied> {
83        if maybe_peer.is_none() {
84            return Ok(Vec::new());
85        }
86        let peer = maybe_peer.expect("already handled");
87        Ok(self
88            .store
89            .addresses_of_peer(&peer)
90            .map(|i| i.cloned().collect())
91            .unwrap_or_default())
92    }
93
94    fn handle_established_outbound_connection(
95        &mut self,
96        _connection_id: libp2p_swarm::ConnectionId,
97        _peer: libp2p_core::PeerId,
98        _addr: &libp2p_core::Multiaddr,
99        _role_override: libp2p_core::Endpoint,
100        _port_use: libp2p_core::transport::PortUse,
101    ) -> Result<libp2p_swarm::THandler<Self>, libp2p_swarm::ConnectionDenied> {
102        Ok(dummy::ConnectionHandler)
103    }
104
105    fn on_swarm_event(&mut self, event: libp2p_swarm::FromSwarm) {
106        self.store.on_swarm_event(&event);
107    }
108
109    fn on_connection_handler_event(
110        &mut self,
111        _peer_id: libp2p_core::PeerId,
112        _connection_id: libp2p_swarm::ConnectionId,
113        _event: libp2p_swarm::THandlerOutEvent<Self>,
114    ) {
115        unreachable!("No event will be produced by a dummy handler.")
116    }
117
118    fn poll(
119        &mut self,
120        cx: &mut std::task::Context<'_>,
121    ) -> std::task::Poll<libp2p_swarm::ToSwarm<Self::ToSwarm, libp2p_swarm::THandlerInEvent<Self>>>
122    {
123        self.store
124            .poll(cx)
125            .map(libp2p_swarm::ToSwarm::GenerateEvent)
126    }
127}