mirror of
https://github.com/YGGverse/aquatic.git
synced 2026-03-31 17:55:36 +00:00
Refactor AccessList; update it periodically in aquatic_udp glommio
This commit is contained in:
parent
cad3618fad
commit
38617c70f4
18 changed files with 141 additions and 77 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -163,6 +163,7 @@ dependencies = [
|
||||||
"futures-lite",
|
"futures-lite",
|
||||||
"glommio",
|
"glommio",
|
||||||
"hashbrown 0.11.2",
|
"hashbrown 0.11.2",
|
||||||
|
"hex",
|
||||||
"histogram",
|
"histogram",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"log",
|
"log",
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,12 @@ pub enum AccessListMode {
|
||||||
Off,
|
Off,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl AccessListMode {
|
||||||
|
pub fn is_on(&self) -> bool {
|
||||||
|
!matches!(self, Self::Off)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct AccessListConfig {
|
pub struct AccessListConfig {
|
||||||
pub mode: AccessListMode,
|
pub mode: AccessListMode,
|
||||||
|
|
@ -36,54 +42,71 @@ impl Default for AccessListConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct AccessList(ArcSwap<HashSet<[u8; 20]>>);
|
#[derive(Default)]
|
||||||
|
pub struct AccessList(HashSet<[u8; 20]>);
|
||||||
|
|
||||||
impl Default for AccessList {
|
impl AccessList {
|
||||||
fn default() -> Self {
|
pub fn insert_from_line(&mut self, line: &str) -> anyhow::Result<()> {
|
||||||
Self(ArcSwap::from(Arc::new(HashSet::default())))
|
self.0.insert(parse_info_hash(line)?);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
pub fn allows(&self, mode: AccessListMode, info_hash: &[u8; 20]) -> bool {
|
||||||
|
match mode {
|
||||||
|
AccessListMode::White => self.0.contains(info_hash),
|
||||||
|
AccessListMode::Black => !self.0.contains(info_hash),
|
||||||
|
AccessListMode::Off => true,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AccessList {
|
pub trait AccessListQuery {
|
||||||
fn parse_info_hash(line: String) -> anyhow::Result<[u8; 20]> {
|
fn update_from_path(&self, path: &PathBuf) -> anyhow::Result<()>;
|
||||||
let mut bytes = [0u8; 20];
|
fn allows(&self, list_mode: AccessListMode, info_hash_bytes: &[u8; 20]) -> bool;
|
||||||
|
}
|
||||||
|
|
||||||
hex::decode_to_slice(line, &mut bytes)?;
|
pub type AccessListArcSwap = ArcSwap<AccessList>;
|
||||||
|
|
||||||
Ok(bytes)
|
impl AccessListQuery for AccessListArcSwap {
|
||||||
}
|
fn update_from_path(&self, path: &PathBuf) -> anyhow::Result<()> {
|
||||||
|
|
||||||
pub fn update_from_path(&self, path: &PathBuf) -> anyhow::Result<()> {
|
|
||||||
let file = File::open(path)?;
|
let file = File::open(path)?;
|
||||||
let reader = BufReader::new(file);
|
let reader = BufReader::new(file);
|
||||||
|
|
||||||
let mut new_list = HashSet::new();
|
let mut new_list = HashSet::new();
|
||||||
|
|
||||||
for line in reader.lines() {
|
for line in reader.lines() {
|
||||||
new_list.insert(Self::parse_info_hash(line?)?);
|
new_list.insert(parse_info_hash(&line?)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.0.store(Arc::new(new_list));
|
self.store(Arc::new(AccessList(new_list)));
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn allows(&self, list_mode: AccessListMode, info_hash_bytes: &[u8; 20]) -> bool {
|
fn allows(&self, mode: AccessListMode, info_hash_bytes: &[u8; 20]) -> bool {
|
||||||
match list_mode {
|
match mode {
|
||||||
AccessListMode::White => self.0.load().contains(info_hash_bytes),
|
AccessListMode::White => self.load().0.contains(info_hash_bytes),
|
||||||
AccessListMode::Black => !self.0.load().contains(info_hash_bytes),
|
AccessListMode::Black => !self.load().0.contains(info_hash_bytes),
|
||||||
AccessListMode::Off => true,
|
AccessListMode::Off => true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_info_hash(line: &str) -> anyhow::Result<[u8; 20]> {
|
||||||
|
let mut bytes = [0u8; 20];
|
||||||
|
|
||||||
|
hex::decode_to_slice(line, &mut bytes)?;
|
||||||
|
|
||||||
|
Ok(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_info_hash() {
|
fn test_parse_info_hash() {
|
||||||
let f = AccessList::parse_info_hash;
|
let f = parse_info_hash;
|
||||||
|
|
||||||
assert!(f("aaaabbbbccccddddeeeeaaaabbbbccccddddeeee".into()).is_ok());
|
assert!(f("aaaabbbbccccddddeeeeaaaabbbbccccddddeeee".into()).is_ok());
|
||||||
assert!(f("aaaabbbbccccddddeeeeaaaabbbbccccddddeeeef".into()).is_err());
|
assert!(f("aaaabbbbccccddddeeeeaaaabbbbccccddddeeeef".into()).is_err());
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
use aquatic_common::access_list::AccessList;
|
use aquatic_common::access_list::{AccessList, AccessListArcSwap};
|
||||||
use crossbeam_channel::{Receiver, Sender};
|
use crossbeam_channel::{Receiver, Sender};
|
||||||
use either::Either;
|
use either::Either;
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
|
|
@ -165,7 +165,7 @@ impl TorrentMaps {
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct State {
|
pub struct State {
|
||||||
pub access_list: Arc<AccessList>,
|
pub access_list: Arc<AccessListArcSwap>,
|
||||||
pub torrent_maps: Arc<Mutex<TorrentMaps>>,
|
pub torrent_maps: Arc<Mutex<TorrentMaps>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,10 @@ pub fn run(config: Config) -> anyhow::Result<()> {
|
||||||
|
|
||||||
tasks::update_access_list(&config, &state);
|
tasks::update_access_list(&config, &state);
|
||||||
|
|
||||||
state.torrent_maps.lock().clean(&config, &state.access_list);
|
state
|
||||||
|
.torrent_maps
|
||||||
|
.lock()
|
||||||
|
.clean(&config, &state.access_list.load_full());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ use std::sync::Arc;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
use std::vec::Drain;
|
use std::vec::Drain;
|
||||||
|
|
||||||
|
use aquatic_common::access_list::AccessListQuery;
|
||||||
use aquatic_http_protocol::request::Request;
|
use aquatic_http_protocol::request::Request;
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use log::{debug, error, info};
|
use log::{debug, error, info};
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use histogram::Histogram;
|
use histogram::Histogram;
|
||||||
|
|
||||||
use aquatic_common::access_list::AccessListMode;
|
use aquatic_common::access_list::{AccessListMode, AccessListQuery};
|
||||||
|
|
||||||
use crate::{common::*, config::Config};
|
use crate::{common::*, config::Config};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ aquatic_common = "0.1.0"
|
||||||
aquatic_udp_protocol = "0.1.0"
|
aquatic_udp_protocol = "0.1.0"
|
||||||
crossbeam-channel = "0.5"
|
crossbeam-channel = "0.5"
|
||||||
hashbrown = "0.11.2"
|
hashbrown = "0.11.2"
|
||||||
|
hex = "0.4"
|
||||||
histogram = "0.6"
|
histogram = "0.6"
|
||||||
indexmap = "1"
|
indexmap = "1"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
|
use std::borrow::Borrow;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
|
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
|
||||||
use std::sync::{atomic::AtomicUsize, Arc};
|
use std::sync::{atomic::AtomicUsize, Arc};
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
|
use aquatic_common::access_list::AccessListArcSwap;
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
|
|
@ -127,19 +129,19 @@ pub struct TorrentMaps {
|
||||||
|
|
||||||
impl TorrentMaps {
|
impl TorrentMaps {
|
||||||
/// Remove disallowed and inactive torrents
|
/// Remove disallowed and inactive torrents
|
||||||
pub fn clean(&mut self, config: &Config, access_list: &Arc<AccessList>) {
|
pub fn clean<T: Borrow<AccessList>>(&mut self, config: &Config, access_list: T) {
|
||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
|
|
||||||
let access_list_mode = config.access_list.mode;
|
let access_list_mode = config.access_list.mode;
|
||||||
|
|
||||||
self.ipv4.retain(|info_hash, torrent| {
|
self.ipv4.retain(|info_hash, torrent| {
|
||||||
access_list.allows(access_list_mode, &info_hash.0)
|
access_list.borrow().allows(access_list_mode, &info_hash.0)
|
||||||
&& Self::clean_torrent_and_peers(now, torrent)
|
&& Self::clean_torrent_and_peers(now, torrent)
|
||||||
});
|
});
|
||||||
self.ipv4.shrink_to_fit();
|
self.ipv4.shrink_to_fit();
|
||||||
|
|
||||||
self.ipv6.retain(|info_hash, torrent| {
|
self.ipv6.retain(|info_hash, torrent| {
|
||||||
access_list.allows(access_list_mode, &info_hash.0)
|
access_list.borrow().allows(access_list_mode, &info_hash.0)
|
||||||
&& Self::clean_torrent_and_peers(now, torrent)
|
&& Self::clean_torrent_and_peers(now, torrent)
|
||||||
});
|
});
|
||||||
self.ipv6.shrink_to_fit();
|
self.ipv6.shrink_to_fit();
|
||||||
|
|
@ -183,7 +185,7 @@ pub struct Statistics {
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct State {
|
pub struct State {
|
||||||
pub access_list: Arc<AccessList>,
|
pub access_list: Arc<AccessListArcSwap>,
|
||||||
pub torrents: Arc<Mutex<TorrentMaps>>,
|
pub torrents: Arc<Mutex<TorrentMaps>>,
|
||||||
pub statistics: Arc<Statistics>,
|
pub statistics: Arc<Statistics>,
|
||||||
}
|
}
|
||||||
|
|
@ -191,38 +193,13 @@ pub struct State {
|
||||||
impl Default for State {
|
impl Default for State {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
access_list: Arc::new(AccessList::default()),
|
access_list: Arc::new(AccessListArcSwap::default()),
|
||||||
torrents: Arc::new(Mutex::new(TorrentMaps::default())),
|
torrents: Arc::new(Mutex::new(TorrentMaps::default())),
|
||||||
statistics: Arc::new(Statistics::default()),
|
statistics: Arc::new(Statistics::default()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct ConnectionMap(HashMap<(ConnectionId, SocketAddr), ValidUntil>);
|
|
||||||
|
|
||||||
impl ConnectionMap {
|
|
||||||
pub fn insert(
|
|
||||||
&mut self,
|
|
||||||
connection_id: ConnectionId,
|
|
||||||
socket_addr: SocketAddr,
|
|
||||||
valid_until: ValidUntil,
|
|
||||||
) {
|
|
||||||
self.0.insert((connection_id, socket_addr), valid_until);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn contains(&mut self, connection_id: ConnectionId, socket_addr: SocketAddr) -> bool {
|
|
||||||
self.0.contains_key(&(connection_id, socket_addr))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn clean(&mut self) {
|
|
||||||
let now = Instant::now();
|
|
||||||
|
|
||||||
self.0.retain(|_, v| v.0 > now);
|
|
||||||
self.0.shrink_to_fit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
|
|
@ -1 +1,30 @@
|
||||||
|
use std::{net::SocketAddr, time::Instant};
|
||||||
|
|
||||||
|
pub use aquatic_common::{access_list::AccessList, ValidUntil};
|
||||||
|
pub use aquatic_udp_protocol::*;
|
||||||
|
use hashbrown::HashMap;
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct ConnectionMap(HashMap<(ConnectionId, SocketAddr), ValidUntil>);
|
||||||
|
|
||||||
|
impl ConnectionMap {
|
||||||
|
pub fn insert(
|
||||||
|
&mut self,
|
||||||
|
connection_id: ConnectionId,
|
||||||
|
socket_addr: SocketAddr,
|
||||||
|
valid_until: ValidUntil,
|
||||||
|
) {
|
||||||
|
self.0.insert((connection_id, socket_addr), valid_until);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn contains(&mut self, connection_id: ConnectionId, socket_addr: SocketAddr) -> bool {
|
||||||
|
self.0.contains_key(&(connection_id, socket_addr))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clean(&mut self) {
|
||||||
|
let now = Instant::now();
|
||||||
|
|
||||||
|
self.0.retain(|_, v| v.0 > now);
|
||||||
|
self.0.shrink_to_fit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,11 @@ use std::net::{IpAddr, SocketAddr};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use futures_lite::{Stream, StreamExt};
|
use futures_lite::{AsyncBufReadExt, Stream, StreamExt};
|
||||||
use glommio::channels::channel_mesh::{MeshBuilder, Partial, Role, Senders};
|
use glommio::channels::channel_mesh::{MeshBuilder, Partial, Role, Senders};
|
||||||
use glommio::{enclose, prelude::*};
|
use glommio::io::{BufferedFile, StreamReaderBuilder};
|
||||||
use glommio::timer::TimerActionRepeat;
|
use glommio::timer::TimerActionRepeat;
|
||||||
|
use glommio::{enclose, prelude::*};
|
||||||
use rand::prelude::SmallRng;
|
use rand::prelude::SmallRng;
|
||||||
use rand::SeedableRng;
|
use rand::SeedableRng;
|
||||||
|
|
||||||
|
|
@ -24,19 +25,34 @@ pub async fn run_request_worker(
|
||||||
|
|
||||||
let response_senders = Rc::new(response_senders);
|
let response_senders = Rc::new(response_senders);
|
||||||
|
|
||||||
let torrents= Rc::new(RefCell::new(TorrentMaps::default()));
|
let torrents = Rc::new(RefCell::new(TorrentMaps::default()));
|
||||||
|
let access_list = Rc::new(RefCell::new(AccessList::default()));
|
||||||
|
|
||||||
async fn clean(
|
TimerActionRepeat::repeat(enclose!((config, torrents, access_list) move || {
|
||||||
config: Config,
|
enclose!((config, torrents, access_list) move || async move {
|
||||||
torrents: Rc<RefCell<TorrentMaps>>,
|
if config.access_list.mode.is_on(){
|
||||||
) -> Option<Duration> {
|
let access_list_file = BufferedFile::open(config.access_list.path).await.unwrap();
|
||||||
torrents.borrow_mut(); // .clean(config, access_list);
|
|
||||||
|
|
||||||
Some(Duration::from_secs(config.cleaning.interval))
|
let mut reader = StreamReaderBuilder::new(access_list_file).build();
|
||||||
}
|
|
||||||
|
|
||||||
TimerActionRepeat::repeat(enclose!((config, torrents) move || {
|
loop {
|
||||||
clean(config.clone(), torrents.clone())
|
let mut buf = String::with_capacity(42);
|
||||||
|
|
||||||
|
match reader.read_line(&mut buf).await {
|
||||||
|
Ok(_) => {
|
||||||
|
access_list.borrow_mut().insert_from_line(&buf).unwrap() // FIXME
|
||||||
|
},
|
||||||
|
Err(err) => {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
torrents.borrow_mut().clean(&config, &*access_list.borrow());
|
||||||
|
|
||||||
|
Some(Duration::from_secs(config.cleaning.interval))
|
||||||
|
})()
|
||||||
}));
|
}));
|
||||||
|
|
||||||
for (_, receiver) in request_receivers.streams() {
|
for (_, receiver) in request_receivers.streams() {
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ use rand::prelude::{Rng, SeedableRng, StdRng};
|
||||||
|
|
||||||
use aquatic_udp_protocol::{IpVersion, Request, Response};
|
use aquatic_udp_protocol::{IpVersion, Request, Response};
|
||||||
|
|
||||||
|
use crate::common::network::ConnectionMap;
|
||||||
use crate::common::*;
|
use crate::common::*;
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use aquatic_common::access_list::{AccessList, AccessListMode};
|
use aquatic_common::access_list::{AccessListArcSwap, AccessListMode, AccessListQuery};
|
||||||
|
|
||||||
pub mod common;
|
pub mod common;
|
||||||
pub mod config;
|
pub mod config;
|
||||||
|
|
@ -15,7 +15,7 @@ pub fn run(config: Config) -> ::anyhow::Result<()> {
|
||||||
mio::run(config)
|
mio::run(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_access_list(config: &Config, access_list: &Arc<AccessList>) {
|
pub fn update_access_list(config: &Config, access_list: &Arc<AccessListArcSwap>) {
|
||||||
match config.access_list.mode {
|
match config.access_list.mode {
|
||||||
AccessListMode::White | AccessListMode::Black => {
|
AccessListMode::White | AccessListMode::Black => {
|
||||||
if let Err(err) = access_list.update_from_path(&config.access_list.path) {
|
if let Err(err) = access_list.update_from_path(&config.access_list.path) {
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,12 @@
|
||||||
use std::sync::{
|
|
||||||
atomic::{AtomicUsize, Ordering},
|
|
||||||
Arc,
|
|
||||||
};
|
|
||||||
use std::thread::Builder;
|
use std::thread::Builder;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
use std::{
|
||||||
|
ops::Deref,
|
||||||
|
sync::{
|
||||||
|
atomic::{AtomicUsize, Ordering},
|
||||||
|
Arc,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use crossbeam_channel::unbounded;
|
use crossbeam_channel::unbounded;
|
||||||
|
|
@ -56,7 +59,10 @@ pub fn run(config: Config) -> ::anyhow::Result<()> {
|
||||||
|
|
||||||
update_access_list(&config, &state.access_list);
|
update_access_list(&config, &state.access_list);
|
||||||
|
|
||||||
state.torrents.lock().clean(&config, &state.access_list);
|
state
|
||||||
|
.torrents
|
||||||
|
.lock()
|
||||||
|
.clean(&config, state.access_list.load_full().deref());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ use std::sync::{
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use std::vec::Drain;
|
use std::vec::Drain;
|
||||||
|
|
||||||
|
use aquatic_common::access_list::AccessListQuery;
|
||||||
use crossbeam_channel::{Receiver, Sender};
|
use crossbeam_channel::{Receiver, Sender};
|
||||||
use mio::net::UdpSocket;
|
use mio::net::UdpSocket;
|
||||||
use mio::{Events, Interest, Poll, Token};
|
use mio::{Events, Interest, Poll, Token};
|
||||||
|
|
@ -15,6 +16,7 @@ use socket2::{Domain, Protocol, Socket, Type};
|
||||||
|
|
||||||
use aquatic_udp_protocol::{IpVersion, Request, Response};
|
use aquatic_udp_protocol::{IpVersion, Request, Response};
|
||||||
|
|
||||||
|
use crate::common::network::ConnectionMap;
|
||||||
use crate::common::*;
|
use crate::common::*;
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ use std::net::{IpAddr, SocketAddr};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
use aquatic_common::access_list::AccessList;
|
use aquatic_common::access_list::{AccessList, AccessListArcSwap};
|
||||||
use crossbeam_channel::{Receiver, Sender};
|
use crossbeam_channel::{Receiver, Sender};
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
|
|
@ -136,7 +136,7 @@ impl TorrentMaps {
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct State {
|
pub struct State {
|
||||||
pub access_list: Arc<AccessList>,
|
pub access_list: Arc<AccessListArcSwap>,
|
||||||
pub torrent_maps: Arc<Mutex<TorrentMaps>>,
|
pub torrent_maps: Arc<Mutex<TorrentMaps>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,10 @@ pub fn run(config: Config) -> anyhow::Result<()> {
|
||||||
|
|
||||||
tasks::update_access_list(&config, &state);
|
tasks::update_access_list(&config, &state);
|
||||||
|
|
||||||
state.torrent_maps.lock().clean(&config, &state.access_list);
|
state
|
||||||
|
.torrent_maps
|
||||||
|
.lock()
|
||||||
|
.clean(&config, &state.access_list.load_full());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ use std::io::ErrorKind;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use std::vec::Drain;
|
use std::vec::Drain;
|
||||||
|
|
||||||
|
use aquatic_common::access_list::AccessListQuery;
|
||||||
use crossbeam_channel::Receiver;
|
use crossbeam_channel::Receiver;
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use log::{debug, error, info};
|
use log::{debug, error, info};
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use aquatic_common::access_list::AccessListMode;
|
use aquatic_common::access_list::{AccessListMode, AccessListQuery};
|
||||||
use histogram::Histogram;
|
use histogram::Histogram;
|
||||||
|
|
||||||
use crate::common::*;
|
use crate::common::*;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue