use std::collections::HashMap;
use crate::{swarm::ConnectedPoint, Multiaddr, PeerId, PublicKey};
pub trait Topology {
fn addresses_of_peer(&mut self, peer: &PeerId) -> Vec<Multiaddr>;
fn local_peer_id(&self) -> &PeerId;
fn local_public_key(&self) -> &PublicKey;
fn add_local_external_addrs<TIter>(&mut self, addrs: TIter)
where TIter: Iterator<Item = Multiaddr>;
fn set_connected(&mut self, _peer_id: &PeerId, _addr: &ConnectedPoint) {}
fn set_disconnected(&mut self, _peer_id: &PeerId, _addr: &ConnectedPoint, _reason: DisconnectReason) {}
fn set_unreachable(&mut self, _addr: &Multiaddr) {}
}
#[derive(Debug, Copy, Clone)]
pub enum DisconnectReason {
Error,
Graceful,
Replaced,
}
pub struct MemoryTopology {
list: HashMap<PeerId, Vec<Multiaddr>>,
local_peer_id: PeerId,
local_public_key: PublicKey,
}
impl MemoryTopology {
#[inline]
pub fn empty(pubkey: PublicKey) -> MemoryTopology {
let local_peer_id = pubkey.clone().into_peer_id();
MemoryTopology {
list: Default::default(),
local_peer_id,
local_public_key: pubkey,
}
}
#[inline]
pub fn is_empty(&self) -> bool {
self.list.is_empty()
}
#[inline]
pub fn add_address(&mut self, peer: PeerId, addr: Multiaddr) {
let addrs = self.list.entry(peer).or_insert_with(|| Vec::new());
if addrs.iter().all(|a| a != &addr) {
addrs.push(addr);
}
}
#[inline]
pub fn peers(&self) -> impl Iterator<Item = &PeerId> {
self.list.keys()
}
#[inline]
pub fn iter(&self) -> impl Iterator<Item = (&PeerId, &Multiaddr)> {
self.list.iter().flat_map(|(p, l)| l.iter().map(move |ma| (p, ma)))
}
}
impl Topology for MemoryTopology {
fn addresses_of_peer(&mut self, peer: &PeerId) -> Vec<Multiaddr> {
self.list.get(peer).map(|v| v.clone()).unwrap_or(Vec::new())
}
fn add_local_external_addrs<TIter>(&mut self, addrs: TIter)
where TIter: Iterator<Item = Multiaddr>
{
for addr in addrs {
let id = self.local_peer_id.clone();
self.add_address(id, addr);
}
}
#[inline]
fn local_peer_id(&self) -> &PeerId {
&self.local_peer_id
}
#[inline]
fn local_public_key(&self) -> &PublicKey {
&self.local_public_key
}
}