mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-08-01 01:11:58 +00:00
Add dumb peerstore for feedback
This commit is contained in:
@@ -5,6 +5,7 @@ members = [
|
|||||||
"datastore",
|
"datastore",
|
||||||
"libp2p-host",
|
"libp2p-host",
|
||||||
"libp2p-peer",
|
"libp2p-peer",
|
||||||
|
"libp2p-peerstore",
|
||||||
"libp2p-transport",
|
"libp2p-transport",
|
||||||
"libp2p-tcp-transport",
|
"libp2p-tcp-transport",
|
||||||
]
|
]
|
||||||
|
9
libp2p-peerstore/Cargo.toml
Normal file
9
libp2p-peerstore/Cargo.toml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
[package]
|
||||||
|
name = "libp2p-peerstore"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Parity Technologies <admin@parity.io>"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
error-chain = "0.11"
|
||||||
|
multiaddr = "0.2"
|
||||||
|
libp2p-peer = { path = "../libp2p-peer" }
|
6
libp2p-peerstore/src/lib.rs
Normal file
6
libp2p-peerstore/src/lib.rs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#[macro_use] extern crate error_chain;
|
||||||
|
extern crate multiaddr;
|
||||||
|
extern crate libp2p_peer as peer;
|
||||||
|
|
||||||
|
mod memory_peerstore;
|
||||||
|
mod peerstore;
|
126
libp2p-peerstore/src/memory_peerstore.rs
Normal file
126
libp2p-peerstore/src/memory_peerstore.rs
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
use std::collections::{HashMap, HashSet};
|
||||||
|
use std::collections::hash_map;
|
||||||
|
use multiaddr::Multiaddr;
|
||||||
|
use peer::PeerId;
|
||||||
|
use peerstore::*;
|
||||||
|
|
||||||
|
pub struct MemoryPeerstore<T> {
|
||||||
|
store: HashMap<PeerId, PeerInfo<T>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> MemoryPeerstore<T> {
|
||||||
|
pub fn new() -> MemoryPeerstore<T> {
|
||||||
|
MemoryPeerstore {
|
||||||
|
store: HashMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Peerstore<T> for MemoryPeerstore<T> {
|
||||||
|
/// Returns a list of peers in this Peerstore
|
||||||
|
fn peers(&self) -> Vec<&PeerId> {
|
||||||
|
// this is terrible but I honestly can't think of any other way than to hand off ownership
|
||||||
|
// through this type of allocation or handing off the entire hashmap and letting people do what they
|
||||||
|
// want with that
|
||||||
|
self.store.keys().collect()
|
||||||
|
}
|
||||||
|
/// Returns the PeerInfo for a specific peer in this peer store, or None if it doesn't exist.
|
||||||
|
fn peer_info(&self, peer_id: &PeerId) -> Option<&PeerInfo<T>> {
|
||||||
|
self.store.get(peer_id)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Try to get a property for a given peer
|
||||||
|
fn get_data(&self, peer_id: &PeerId, key: &str) -> Option<&T> {
|
||||||
|
match self.store.get(peer_id) {
|
||||||
|
None => None,
|
||||||
|
Some(peer_info) => peer_info.get_data(key),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// Try to set a property for a given peer
|
||||||
|
fn put_data(&mut self, peer_id: &PeerId, key: String, val: T) -> Result<()> {
|
||||||
|
match self.store.get_mut(peer_id) {
|
||||||
|
None => Err(Error::from_kind(ErrorKind::NoSuchPeer((*peer_id).clone()))),
|
||||||
|
Some(mut peer_info) => {
|
||||||
|
peer_info.set_data(key, val);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Adds an address to a peer
|
||||||
|
fn add_addr(&mut self, peer_id: &PeerId, addr: Multiaddr, ttl: TTL) {
|
||||||
|
match self.store.get_mut(peer_id) {
|
||||||
|
None => (),
|
||||||
|
Some(peer_info) => peer_info.add_addr(addr),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddAddrs gives AddrManager addresses to use, with a given ttl
|
||||||
|
// (time-to-live), after which the address is no longer valid.
|
||||||
|
// If the manager has a longer TTL, the operation is a no-op for that address
|
||||||
|
fn add_addrs(&mut self, peer_id: &PeerId, addrs: Vec<Multiaddr>, ttl: TTL) {
|
||||||
|
match self.store.get_mut(peer_id) {
|
||||||
|
None => (),
|
||||||
|
Some(peer_info) => {
|
||||||
|
for addr in addrs {
|
||||||
|
peer_info.add_addr(addr)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetAddr calls mgr.SetAddrs(p, addr, ttl)
|
||||||
|
fn set_addr(&mut self, peer_id: &PeerId, addr: Multiaddr, ttl: TTL) {
|
||||||
|
self.set_addrs(peer_id, vec![addr], ttl)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetAddrs sets the ttl on addresses. This clears any TTL there previously.
|
||||||
|
// This is used when we receive the best estimate of the validity of an address.
|
||||||
|
fn set_addrs(&mut self, peer_id: &PeerId, addrs: Vec<Multiaddr>, ttl: TTL) {
|
||||||
|
match self.store.get_mut(peer_id) {
|
||||||
|
None => (),
|
||||||
|
Some(peer_info) => peer_info.set_addrs(addrs),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns all known (and valid) addresses for a given peer
|
||||||
|
fn addrs(&self, peer_id: &PeerId) -> &[Multiaddr] {
|
||||||
|
match self.store.get(peer_id) {
|
||||||
|
None => &[],
|
||||||
|
Some(peer_info) => peer_info.get_addrs(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Removes all previously stored addresses
|
||||||
|
fn clear_addrs(&mut self, peer_id: &PeerId) {
|
||||||
|
match self.store.get_mut(peer_id) {
|
||||||
|
None => (),
|
||||||
|
Some(peer_info) => peer_info.set_addrs(vec![]),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get public key for a peer
|
||||||
|
fn get_pub_key(&self, peer_id: &PeerId) -> Option<&[u8]> {
|
||||||
|
self.store.get(peer_id).map(|peer_info| peer_info.get_public_key())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set public key for a peer
|
||||||
|
fn set_pub_key(&mut self, peer_id: &PeerId, key: Vec<u8>) {
|
||||||
|
self.store.get_mut(peer_id).map(|peer_info| peer_info.set_public_key(key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use peer::PeerId;
|
||||||
|
use super::{Peerstore, MemoryPeerstore};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn insert_get_and_list() {
|
||||||
|
let peer_id = PeerId::new(vec![1,2,3]);
|
||||||
|
let mut peer_store: MemoryPeerstore<u8> = MemoryPeerstore::new();
|
||||||
|
peer_store.put(&peer_id, "test", 123u8);
|
||||||
|
let got = peer_store.get(&peer_id, "test").expect("should be able to fetch");
|
||||||
|
assert_eq!(*got, 123u8);
|
||||||
|
}
|
||||||
|
}
|
87
libp2p-peerstore/src/peerstore.rs
Normal file
87
libp2p-peerstore/src/peerstore.rs
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
use std::time;
|
||||||
|
use std::collections::{HashMap, HashSet};
|
||||||
|
use multiaddr::Multiaddr;
|
||||||
|
use peer::PeerId;
|
||||||
|
|
||||||
|
error_chain! {
|
||||||
|
errors {
|
||||||
|
NoSuchPeer(p: PeerId) {
|
||||||
|
description("tried operating on Peerstore with unknown PeerID")
|
||||||
|
display("invalid PeerId: '{}'", p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type TTL = time::Duration;
|
||||||
|
|
||||||
|
pub struct PeerInfo<T> {
|
||||||
|
public_key: Vec<u8>,
|
||||||
|
addrs: Vec<Multiaddr>,
|
||||||
|
data: HashMap<String, T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> PeerInfo<T> {
|
||||||
|
pub fn get_public_key(&self) -> &[u8] {
|
||||||
|
&self.public_key
|
||||||
|
}
|
||||||
|
pub fn set_public_key(&mut self, key: Vec<u8>) {
|
||||||
|
self.public_key = key;
|
||||||
|
}
|
||||||
|
pub fn get_addrs(&self) -> &[Multiaddr] {
|
||||||
|
&self.addrs
|
||||||
|
}
|
||||||
|
pub fn set_addrs(&mut self, addrs: Vec<Multiaddr>) {
|
||||||
|
self.addrs = addrs;
|
||||||
|
}
|
||||||
|
pub fn add_addr(&mut self, addr: Multiaddr) {
|
||||||
|
self.addrs.push(addr); // TODO: This is stupid, a more advanced thing using TTLs need to be implemented
|
||||||
|
self.addrs.dedup();
|
||||||
|
}
|
||||||
|
pub fn get_data(&self, key: &str) -> Option<&T> {
|
||||||
|
self.data.get(key)
|
||||||
|
}
|
||||||
|
pub fn set_data(&mut self, key: String, val: T) -> Option<T> {
|
||||||
|
self.data.insert(key, val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Peerstore<T> {
|
||||||
|
/// Returns a list of peers in this Peerstore
|
||||||
|
fn peers(&self) -> Vec<&PeerId>;
|
||||||
|
|
||||||
|
/// Returns the PeerInfo for a specific peer in this peer store, or None if it doesn't exist.
|
||||||
|
fn peer_info(&self, peer_id: &PeerId) -> Option<&PeerInfo<T>>;
|
||||||
|
|
||||||
|
/// Try to get a property for a given peer
|
||||||
|
fn get_data(&self, peer_id: &PeerId, key: &str) -> Option<&T>;
|
||||||
|
|
||||||
|
/// Try to set a property for a given peer
|
||||||
|
fn put_data(&mut self, peer_id: &PeerId, key: String, val: T) -> Result<()>;
|
||||||
|
|
||||||
|
/// Adds an address to a peer
|
||||||
|
fn add_addr(&mut self, peer_id: &PeerId, addr: Multiaddr, ttl: TTL);
|
||||||
|
|
||||||
|
// AddAddrs gives AddrManager addresses to use, with a given ttl
|
||||||
|
// (time-to-live), after which the address is no longer valid.
|
||||||
|
// If the manager has a longer TTL, the operation is a no-op for that address
|
||||||
|
fn add_addrs(&mut self, peer_id: &PeerId, addrs: Vec<Multiaddr>, ttl: TTL);
|
||||||
|
|
||||||
|
// SetAddr calls mgr.SetAddrs(p, addr, ttl)
|
||||||
|
fn set_addr(&mut self, peer_id: &PeerId, addr: Multiaddr, ttl: TTL);
|
||||||
|
|
||||||
|
// SetAddrs sets the ttl on addresses. This clears any TTL there previously.
|
||||||
|
// This is used when we receive the best estimate of the validity of an address.
|
||||||
|
fn set_addrs(&mut self, peer_id: &PeerId, addrs: Vec<Multiaddr>, ttl: TTL);
|
||||||
|
|
||||||
|
/// Returns all known (and valid) addresses for a given peer
|
||||||
|
fn addrs(&self, peer_id: &PeerId) -> &[Multiaddr];
|
||||||
|
|
||||||
|
/// Removes all previously stored addresses
|
||||||
|
fn clear_addrs(&mut self, peer_id: &PeerId);
|
||||||
|
|
||||||
|
/// Get public key for a peer
|
||||||
|
fn get_pub_key(&self, peer_id: &PeerId) -> Option<&[u8]>;
|
||||||
|
|
||||||
|
/// Set public key for a peer
|
||||||
|
fn set_pub_key(&mut self, peer_id: &PeerId, key: Vec<u8>);
|
||||||
|
}
|
Reference in New Issue
Block a user