access lists: filter requests in socket workers instead

This commit is contained in:
Joakim Frostegård 2021-10-16 17:26:40 +02:00
parent 33966bed57
commit 7ccd5fcbf7
18 changed files with 221 additions and 163 deletions

View file

@ -118,15 +118,13 @@ pub type TorrentMap<I> = HashMap<InfoHash, TorrentData<I>>;
pub struct TorrentMaps {
pub ipv4: TorrentMap<Ipv4Addr>,
pub ipv6: TorrentMap<Ipv6Addr>,
pub access_list: AccessList,
}
impl TorrentMaps {
/// Remove disallowed and inactive torrents
pub fn clean(&mut self, config: &Config) {
pub fn clean(&mut self, config: &Config, access_list: &Arc<AccessList>) {
let now = Instant::now();
let access_list = &self.access_list;
let access_list_mode = config.access_list.mode;
self.ipv4.retain(|info_hash, torrent| {
@ -181,6 +179,7 @@ pub struct Statistics {
#[derive(Clone)]
pub struct State {
pub access_list: Arc<AccessList>,
pub connections: Arc<Mutex<ConnectionMap>>,
pub torrents: Arc<Mutex<TorrentMaps>>,
pub statistics: Arc<Statistics>,
@ -189,6 +188,7 @@ pub struct State {
impl Default for State {
fn default() -> Self {
Self {
access_list: Arc::new(AccessList::default()),
connections: Arc::new(Mutex::new(HashMap::new())),
torrents: Arc::new(Mutex::new(TorrentMaps::default())),
statistics: Arc::new(Statistics::default()),

View file

@ -19,44 +19,30 @@ pub fn handle_announce_requests(
responses: &mut Vec<(Response, SocketAddr)>,
) {
let peer_valid_until = ValidUntil::new(config.cleaning.max_peer_age);
let access_list_mode = config.access_list.mode;
responses.extend(requests.map(|(request, src)| {
let info_hash_allowed = torrents
.access_list
.allows(access_list_mode, &request.info_hash.0);
let peer_ip = convert_ipv4_mapped_ipv6(src.ip());
let response = if info_hash_allowed {
let peer_ip = convert_ipv4_mapped_ipv6(src.ip());
let response = match peer_ip {
IpAddr::V4(ip) => handle_announce_request(
config,
rng,
&mut torrents.ipv4,
request,
ip,
peer_valid_until,
),
IpAddr::V6(ip) => handle_announce_request(
config,
rng,
&mut torrents.ipv6,
request,
ip,
peer_valid_until,
),
};
Response::Announce(response)
} else {
Response::Error(ErrorResponse {
transaction_id: request.transaction_id,
message: "Info hash not allowed".into(),
})
let response = match peer_ip {
IpAddr::V4(ip) => handle_announce_request(
config,
rng,
&mut torrents.ipv4,
request,
ip,
peer_valid_until,
),
IpAddr::V6(ip) => handle_announce_request(
config,
rng,
&mut torrents.ipv6,
request,
ip,
peer_valid_until,
),
};
(response, src)
(Response::Announce(response), src)
}));
}

View file

@ -23,7 +23,7 @@ pub const APP_NAME: &str = "aquatic_udp: UDP BitTorrent tracker";
pub fn run(config: Config) -> ::anyhow::Result<()> {
let state = State::default();
tasks::update_access_list(&config, &mut state.torrents.lock());
tasks::update_access_list(&config, &state);
let num_bound_sockets = start_workers(config.clone(), state.clone())?;
@ -56,12 +56,9 @@ pub fn run(config: Config) -> ::anyhow::Result<()> {
::std::thread::sleep(Duration::from_secs(config.cleaning.interval));
tasks::clean_connections(&state);
tasks::update_access_list(&config, &state);
let mut torrent_maps = state.torrents.lock();
tasks::update_access_list(&config, &mut torrent_maps);
torrent_maps.clean(&config);
state.torrents.lock().clean(&config, &state.access_list);
}
}

View file

@ -131,6 +131,8 @@ fn read_requests(
let mut requests_received: usize = 0;
let mut bytes_received: usize = 0;
let access_list_mode = config.access_list.mode;
loop {
match socket.recv_from(&mut buffer[..]) {
Ok((amt, src)) => {
@ -145,7 +147,20 @@ fn read_requests(
match request {
Ok(request) => {
requests.push((request, src));
if let Request::Announce(AnnounceRequest { info_hash, transaction_id, ..}) = request {
if state.access_list.allows(access_list_mode, &info_hash.0) {
requests.push((request, src));
} else {
let response = Response::Error(ErrorResponse {
transaction_id,
message: "Info hash not allowed".into()
});
local_responses.push((response, src))
}
} else {
requests.push((request, src));
}
}
Err(err) => {
::log::debug!("request_from_bytes error: {:?}", err);

View file

@ -8,10 +8,10 @@ use aquatic_common::access_list::AccessListMode;
use crate::common::*;
use crate::config::Config;
pub fn update_access_list(config: &Config, torrent_maps: &mut TorrentMaps) {
pub fn update_access_list(config: &Config, state: &State) {
match config.access_list.mode {
AccessListMode::Require | AccessListMode::Forbid => {
if let Err(err) = torrent_maps
if let Err(err) = state
.access_list
.update_from_path(&config.access_list.path)
{