You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
123 lines
2.7 KiB
Rust
123 lines
2.7 KiB
Rust
use crate::infohash::v1::U160;
|
|
use crate::LookupFilter;
|
|
use std::collections::{HashMap, HashSet};
|
|
use std::net::SocketAddr;
|
|
use std::ops::Add;
|
|
use std::sync::{Arc, RwLock};
|
|
use std::time::{Duration, Instant};
|
|
use url::Url;
|
|
|
|
#[derive(Debug, Default)]
|
|
pub struct PeerStorage {
|
|
torrents: HashMap<U160, PeerCollection>,
|
|
}
|
|
|
|
#[derive(Debug, Default)]
|
|
pub struct PeerCollection {
|
|
sets: Vec<PeerSet>,
|
|
peers: HashSet<SocketAddr>,
|
|
peers6: HashSet<SocketAddr>,
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct PeerSet {
|
|
source: PeerStorageSource,
|
|
expires: Instant,
|
|
peers: Vec<SocketAddr>,
|
|
}
|
|
|
|
impl PeerCollection {
|
|
fn add_peers(&mut self, peers: Vec<SocketAddr>, source: PeerStorageSource) {
|
|
let set = PeerSet {
|
|
source,
|
|
peers,
|
|
expires: Instant::now().add(Duration::from_secs(60 * 30)),
|
|
};
|
|
|
|
for peer in &set.peers {
|
|
if peer.is_ipv4() {
|
|
self.peers.insert(*peer);
|
|
} else {
|
|
self.peers6.insert(*peer);
|
|
}
|
|
}
|
|
|
|
self.sets.push(set);
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub enum PeerStorageSource {
|
|
DHT,
|
|
Tracker(Url),
|
|
}
|
|
|
|
impl PeerStorage {
|
|
pub fn new() -> PeerStorage {
|
|
PeerStorage {
|
|
torrents: Default::default(),
|
|
}
|
|
}
|
|
|
|
pub fn add_peers(
|
|
&mut self,
|
|
info_hash: U160,
|
|
peers: Vec<SocketAddr>,
|
|
source: PeerStorageSource,
|
|
) {
|
|
self.torrents
|
|
.entry(info_hash)
|
|
.or_default()
|
|
.add_peers(peers, source)
|
|
}
|
|
|
|
pub fn get_peers(&self, info_hash: U160, filter: LookupFilter) -> Vec<SocketAddr> {
|
|
let collection = if let Some(collection) = self.torrents.get(&info_hash) {
|
|
collection
|
|
} else {
|
|
return vec![];
|
|
};
|
|
|
|
let mut buffer = vec![];
|
|
|
|
if filter != LookupFilter::IPv6 {
|
|
buffer.extend(&collection.peers);
|
|
}
|
|
|
|
if filter != LookupFilter::IPv4 {
|
|
buffer.extend(&collection.peers6);
|
|
}
|
|
|
|
buffer
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct PeerStorageHolder {
|
|
inner: Arc<RwLock<PeerStorage>>,
|
|
}
|
|
|
|
impl PeerStorageHolder {
|
|
pub fn new(peer_storage: PeerStorage) -> PeerStorageHolder {
|
|
PeerStorageHolder {
|
|
inner: Arc::new(RwLock::new(peer_storage)),
|
|
}
|
|
}
|
|
|
|
pub fn get_peers(&self, info_hash: U160, filter: LookupFilter) -> Vec<SocketAddr> {
|
|
self.inner.read().unwrap().get_peers(info_hash, filter)
|
|
}
|
|
|
|
pub fn add_peers(
|
|
&mut self,
|
|
info_hash: U160,
|
|
peers: Vec<SocketAddr>,
|
|
source: PeerStorageSource,
|
|
) {
|
|
self.inner
|
|
.write()
|
|
.unwrap()
|
|
.add_peers(info_hash, peers, source)
|
|
}
|
|
}
|