diff --git a/aquatic_http/src/lib/common.rs b/aquatic_http/src/lib/common.rs index 0c0419a..5d22510 100644 --- a/aquatic_http/src/lib/common.rs +++ b/aquatic_http/src/lib/common.rs @@ -112,19 +112,18 @@ pub type TorrentMap = HashMap>; pub struct TorrentMaps { pub ipv4: TorrentMap, pub ipv6: TorrentMap, + pub access_list: AccessList, } #[derive(Clone)] pub struct State { pub torrent_maps: Arc>, - pub access_list: Arc>, } impl Default for State { fn default() -> Self { Self { torrent_maps: Arc::new(Mutex::new(TorrentMaps::default())), - access_list: Arc::new(Mutex::new(AccessList::default())), } } } diff --git a/aquatic_http/src/lib/handler.rs b/aquatic_http/src/lib/handler.rs index cd823d8..feef6b1 100644 --- a/aquatic_http/src/lib/handler.rs +++ b/aquatic_http/src/lib/handler.rs @@ -105,69 +105,77 @@ pub fn handle_announce_requests( let valid_until = ValidUntil::new(config.cleaning.max_peer_age); for (meta, request) in requests { - let peer_ip = convert_ipv4_mapped_ipv6(meta.peer_addr.ip()); + let info_hash_allowed = torrent_maps + .access_list + .allows(config.access_list.mode, &request.info_hash.0); - ::log::debug!("peer ip: {:?}", peer_ip); + let response = if info_hash_allowed { + let peer_ip = convert_ipv4_mapped_ipv6(meta.peer_addr.ip()); - let response = match peer_ip { - IpAddr::V4(peer_ip_address) => { - let torrent_data: &mut TorrentData = - torrent_maps.ipv4.entry(request.info_hash).or_default(); + ::log::debug!("peer ip: {:?}", peer_ip); - let peer_connection_meta = PeerConnectionMeta { - worker_index: meta.worker_index, - poll_token: meta.poll_token, - peer_ip_address, - }; + match peer_ip { + IpAddr::V4(peer_ip_address) => { + let torrent_data: &mut TorrentData = + torrent_maps.ipv4.entry(request.info_hash).or_default(); - let (seeders, leechers, response_peers) = upsert_peer_and_get_response_peers( - config, - rng, - peer_connection_meta, - torrent_data, - request, - valid_until, - ); + let peer_connection_meta = PeerConnectionMeta { + worker_index: meta.worker_index, + poll_token: meta.poll_token, + peer_ip_address, + }; - let response = AnnounceResponse { - complete: seeders, - incomplete: leechers, - announce_interval: config.protocol.peer_announce_interval, - peers: ResponsePeerListV4(response_peers), - peers6: ResponsePeerListV6(vec![]), - }; + let (seeders, leechers, response_peers) = upsert_peer_and_get_response_peers( + config, + rng, + peer_connection_meta, + torrent_data, + request, + valid_until, + ); - Response::Announce(response) - } - IpAddr::V6(peer_ip_address) => { - let torrent_data: &mut TorrentData = - torrent_maps.ipv6.entry(request.info_hash).or_default(); - - let peer_connection_meta = PeerConnectionMeta { - worker_index: meta.worker_index, - poll_token: meta.poll_token, - peer_ip_address, - }; - - let (seeders, leechers, response_peers) = upsert_peer_and_get_response_peers( - config, - rng, - peer_connection_meta, - torrent_data, - request, - valid_until, - ); - - let response = AnnounceResponse { - complete: seeders, - incomplete: leechers, - announce_interval: config.protocol.peer_announce_interval, - peers: ResponsePeerListV4(vec![]), - peers6: ResponsePeerListV6(response_peers), - }; - - Response::Announce(response) + let response = AnnounceResponse { + complete: seeders, + incomplete: leechers, + announce_interval: config.protocol.peer_announce_interval, + peers: ResponsePeerListV4(response_peers), + peers6: ResponsePeerListV6(vec![]), + }; + + Response::Announce(response) + } + IpAddr::V6(peer_ip_address) => { + let torrent_data: &mut TorrentData = + torrent_maps.ipv6.entry(request.info_hash).or_default(); + + let peer_connection_meta = PeerConnectionMeta { + worker_index: meta.worker_index, + poll_token: meta.poll_token, + peer_ip_address, + }; + + let (seeders, leechers, response_peers) = upsert_peer_and_get_response_peers( + config, + rng, + peer_connection_meta, + torrent_data, + request, + valid_until, + ); + + let response = AnnounceResponse { + complete: seeders, + incomplete: leechers, + announce_interval: config.protocol.peer_announce_interval, + peers: ResponsePeerListV4(vec![]), + peers6: ResponsePeerListV6(response_peers), + }; + + Response::Announce(response) + } } + } else { + Response::Failure(FailureResponse::new("Info hash not allowed")) }; response_channel_sender.send(meta, response); diff --git a/aquatic_http/src/lib/lib.rs b/aquatic_http/src/lib/lib.rs index da26916..1c74ae1 100644 --- a/aquatic_http/src/lib/lib.rs +++ b/aquatic_http/src/lib/lib.rs @@ -27,8 +27,9 @@ pub fn run(config: Config) -> anyhow::Result<()> { match config.access_list.mode { AccessListMode::Require | AccessListMode::Forbid => { state - .access_list + .torrent_maps .lock() + .access_list .update_from_path(&config.access_list.path)?; } AccessListMode::Ignore => {} diff --git a/aquatic_http_protocol/src/response.rs b/aquatic_http_protocol/src/response.rs index b8e7598..5382469 100644 --- a/aquatic_http_protocol/src/response.rs +++ b/aquatic_http_protocol/src/response.rs @@ -135,6 +135,12 @@ pub struct FailureResponse { } impl FailureResponse { + pub fn new(reason: &str) -> Self { + Self { + failure_reason: reason.into() + } + } + fn write(&self, output: &mut W) -> ::std::io::Result { let mut bytes_written = 0usize;