From f23a3fc2a974f483a7a42f1d9270ea885f9a239f Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Mon, 27 Jan 2025 12:04:23 +0000 Subject: [PATCH 1/6] chore: [#1207] remove deprecated comment --- src/core/mod.rs | 6 ------ src/core/scrape_handler.rs | 2 -- 2 files changed, 8 deletions(-) diff --git a/src/core/mod.rs b/src/core/mod.rs index 064e8eb3..1d969068 100644 --- a/src/core/mod.rs +++ b/src/core/mod.rs @@ -583,8 +583,6 @@ impl Tracker { /// It handles an announce request. /// - /// # Context: Tracker - /// /// BEP 03: [The `BitTorrent` Protocol Specification](https://www.bittorrent.org/beps/bep_0003.html). pub fn announce( &self, @@ -628,8 +626,6 @@ impl Tracker { /// It updates the torrent entry in memory, it also stores in the database /// the torrent info data which is persistent, and finally return the data /// needed for a `announce` request response. - /// - /// # Context: Tracker #[must_use] pub fn upsert_peer_and_get_stats(&self, info_hash: &InfoHash, peer: &peer::Peer) -> SwarmMetadata { let swarm_metadata_before = match self.in_memory_torrent_repository.get_opt_swarm_metadata(info_hash) { @@ -652,8 +648,6 @@ impl Tracker { } /// It stores the torrents stats into the database (if persistency is enabled). - /// - /// # Context: Tracker fn persist_stats(&self, info_hash: &InfoHash, swarm_metadata: &SwarmMetadata) { if self.config.tracker_policy.persistent_torrent_completed_stat { let completed = swarm_metadata.downloaded; diff --git a/src/core/scrape_handler.rs b/src/core/scrape_handler.rs index 47049ed7..1d513a5a 100644 --- a/src/core/scrape_handler.rs +++ b/src/core/scrape_handler.rs @@ -29,8 +29,6 @@ impl ScrapeHandler { /// It handles a scrape request. /// - /// # Context: Tracker - /// /// BEP 48: [Tracker Protocol Extension: Scrape](https://www.bittorrent.org/beps/bep_0048.html). pub async fn scrape(&self, info_hashes: &Vec) -> ScrapeData { let mut scrape_data = ScrapeData::empty(); From f741d06db2281f44451e8097dcc0ce4e8b4972aa Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Mon, 27 Jan 2025 12:38:34 +0000 Subject: [PATCH 2/6] refactor: [#1207] use InMemoryTorrentRepository in tests to add torrents --- src/core/mod.rs | 42 +++++++++++------------ src/core/services/torrent.rs | 28 +++++++++------- src/servers/udp/handlers.rs | 56 ++++++++++++++++++------------- tests/servers/api/environment.rs | 2 +- tests/servers/http/environment.rs | 2 +- tests/servers/udp/environment.rs | 7 +++- 6 files changed, 77 insertions(+), 60 deletions(-) diff --git a/src/core/mod.rs b/src/core/mod.rs index 1d969068..5d501b00 100644 --- a/src/core/mod.rs +++ b/src/core/mod.rs @@ -693,7 +693,7 @@ mod tests { use crate::core::whitelist::manager::WhiteListManager; use crate::core::{whitelist, Tracker}; - fn public_tracker() -> (Arc, Arc) { + fn public_tracker() -> (Arc, Arc, Arc) { let config = configuration::ephemeral_public(); let ( @@ -714,7 +714,7 @@ mod tests { let scrape_handler = Arc::new(ScrapeHandler::new(&whitelist_authorization, &in_memory_torrent_repository)); - (tracker, scrape_handler) + (tracker, in_memory_torrent_repository, scrape_handler) } fn public_tracker_and_in_memory_torrents_repository() -> (Arc, Arc) { @@ -871,12 +871,12 @@ mod tests { #[tokio::test] async fn it_should_return_the_peers_for_a_given_torrent() { - let (tracker, in_memory_torrent_repository) = public_tracker_and_in_memory_torrents_repository(); + let (_tracker, in_memory_torrent_repository) = public_tracker_and_in_memory_torrents_repository(); let info_hash = sample_info_hash(); let peer = sample_peer(); - let _ = tracker.upsert_peer_and_get_stats(&info_hash, &peer); + let () = in_memory_torrent_repository.upsert_peer(&info_hash, &peer); let peers = in_memory_torrent_repository.get_torrent_peers(&info_hash); @@ -903,7 +903,7 @@ mod tests { #[tokio::test] async fn it_should_return_74_peers_at_the_most_for_a_given_torrent() { - let (tracker, in_memory_torrent_repository) = public_tracker_and_in_memory_torrents_repository(); + let (_tracker, in_memory_torrent_repository) = public_tracker_and_in_memory_torrents_repository(); let info_hash = sample_info_hash(); @@ -918,7 +918,7 @@ mod tests { event: AnnounceEvent::Completed, }; - let _ = tracker.upsert_peer_and_get_stats(&info_hash, &peer); + let () = in_memory_torrent_repository.upsert_peer(&info_hash, &peer); } let peers = in_memory_torrent_repository.get_torrent_peers(&info_hash); @@ -928,12 +928,12 @@ mod tests { #[tokio::test] async fn it_should_return_the_peers_for_a_given_torrent_excluding_a_given_peer() { - let (tracker, _scrape_handler) = public_tracker(); + let (tracker, in_memory_torrent_repository, _scrape_handler) = public_tracker(); let info_hash = sample_info_hash(); let peer = sample_peer(); - let _ = tracker.upsert_peer_and_get_stats(&info_hash, &peer); + let () = in_memory_torrent_repository.upsert_peer(&info_hash, &peer); let peers = tracker .in_memory_torrent_repository @@ -944,13 +944,13 @@ mod tests { #[tokio::test] async fn it_should_return_74_peers_at_the_most_for_a_given_torrent_when_it_filters_out_a_given_peer() { - let (tracker, _scrape_handler) = public_tracker(); + let (tracker, in_memory_torrent_repository, _scrape_handler) = public_tracker(); let info_hash = sample_info_hash(); let excluded_peer = sample_peer(); - let _ = tracker.upsert_peer_and_get_stats(&info_hash, &excluded_peer); + let () = in_memory_torrent_repository.upsert_peer(&info_hash, &excluded_peer); // Add 74 peers for idx in 2..=75 { @@ -964,7 +964,7 @@ mod tests { event: AnnounceEvent::Completed, }; - let _ = tracker.upsert_peer_and_get_stats(&info_hash, &peer); + let () = in_memory_torrent_repository.upsert_peer(&info_hash, &peer); } let peers = tracker @@ -976,9 +976,9 @@ mod tests { #[tokio::test] async fn it_should_return_the_torrent_metrics() { - let (tracker, in_memory_torrent_repository) = public_tracker_and_in_memory_torrents_repository(); + let (_tracker, in_memory_torrent_repository) = public_tracker_and_in_memory_torrents_repository(); - let _ = tracker.upsert_peer_and_get_stats(&sample_info_hash(), &leecher()); + let () = in_memory_torrent_repository.upsert_peer(&sample_info_hash(), &leecher()); let torrent_metrics = in_memory_torrent_repository.get_torrents_metrics(); @@ -995,11 +995,11 @@ mod tests { #[tokio::test] async fn it_should_get_many_the_torrent_metrics() { - let (tracker, in_memory_torrent_repository) = public_tracker_and_in_memory_torrents_repository(); + let (_tracker, in_memory_torrent_repository) = public_tracker_and_in_memory_torrents_repository(); let start_time = std::time::Instant::now(); for i in 0..1_000_000 { - let _ = tracker.upsert_peer_and_get_stats(&gen_seeded_infohash(&i), &leecher()); + let () = in_memory_torrent_repository.upsert_peer(&gen_seeded_infohash(&i), &leecher()); } let result_a = start_time.elapsed(); @@ -1130,7 +1130,7 @@ mod tests { #[tokio::test] async fn it_should_return_the_announce_data_with_an_empty_peer_list_when_it_is_the_first_announced_peer() { - let (tracker, _scrape_handler) = public_tracker(); + let (tracker, _in_memory_torrent_repository, _scrape_handler) = public_tracker(); let mut peer = sample_peer(); @@ -1141,7 +1141,7 @@ mod tests { #[tokio::test] async fn it_should_return_the_announce_data_with_the_previously_announced_peers() { - let (tracker, _scrape_handler) = public_tracker(); + let (tracker, _in_memory_torrent_repository, _scrape_handler) = public_tracker(); let mut previously_announced_peer = sample_peer_1(); tracker.announce( @@ -1166,7 +1166,7 @@ mod tests { #[tokio::test] async fn when_the_peer_is_a_seeder() { - let (tracker, _scrape_handler) = public_tracker(); + let (tracker, _in_memory_torrent_repository, _scrape_handler) = public_tracker(); let mut peer = seeder(); @@ -1177,7 +1177,7 @@ mod tests { #[tokio::test] async fn when_the_peer_is_a_leecher() { - let (tracker, _scrape_handler) = public_tracker(); + let (tracker, _in_memory_torrent_repository, _scrape_handler) = public_tracker(); let mut peer = leecher(); @@ -1188,7 +1188,7 @@ mod tests { #[tokio::test] async fn when_a_previously_announced_started_peer_has_completed_downloading() { - let (tracker, _scrape_handler) = public_tracker(); + let (tracker, _in_memory_torrent_repository, _scrape_handler) = public_tracker(); // We have to announce with "started" event because peer does not count if peer was not previously known let mut started_peer = started_peer(); @@ -1215,7 +1215,7 @@ mod tests { #[tokio::test] async fn it_should_return_the_swarm_metadata_for_the_requested_file_if_the_tracker_has_that_torrent() { - let (tracker, scrape_handler) = public_tracker(); + let (tracker, _in_memory_torrent_repository, scrape_handler) = public_tracker(); let info_hash = "3b245504cf5f11bbdbe1201cea6a6bf45aee1bc0".parse::().unwrap(); // # DevSkim: ignore DS173237 diff --git a/src/core/services/torrent.rs b/src/core/services/torrent.rs index 8677096c..5faaef1d 100644 --- a/src/core/services/torrent.rs +++ b/src/core/services/torrent.rs @@ -189,11 +189,11 @@ mod tests { async fn should_return_the_torrent_info_if_the_tracker_has_the_torrent() { let config = tracker_configuration(); - let (tracker, in_memory_torrent_repository) = initialize_tracker_and_deps(&config); + let (_tracker, in_memory_torrent_repository) = initialize_tracker_and_deps(&config); let hash = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); let info_hash = InfoHash::from_str(&hash).unwrap(); - let _ = tracker.upsert_peer_and_get_stats(&info_hash, &sample_peer()); + let () = in_memory_torrent_repository.upsert_peer(&info_hash, &sample_peer()); let torrent_info = get_torrent_info(in_memory_torrent_repository.clone(), &info_hash) .await @@ -242,12 +242,12 @@ mod tests { async fn should_return_a_summarized_info_for_all_torrents() { let config = tracker_configuration(); - let (tracker, in_memory_torrent_repository) = initialize_tracker_and_deps(&config); + let (_tracker, in_memory_torrent_repository) = initialize_tracker_and_deps(&config); let hash = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); let info_hash = InfoHash::from_str(&hash).unwrap(); - let _ = tracker.upsert_peer_and_get_stats(&info_hash, &sample_peer()); + let () = in_memory_torrent_repository.upsert_peer(&info_hash, &sample_peer()); let torrents = get_torrents_page(in_memory_torrent_repository.clone(), Some(&Pagination::default())).await; @@ -266,15 +266,16 @@ mod tests { async fn should_allow_limiting_the_number_of_torrents_in_the_result() { let config = tracker_configuration(); - let (tracker, in_memory_torrent_repository) = initialize_tracker_and_deps(&config); + let (_tracker, in_memory_torrent_repository) = initialize_tracker_and_deps(&config); let hash1 = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); let info_hash1 = InfoHash::from_str(&hash1).unwrap(); + let hash2 = "03840548643af2a7b63a9f5cbca348bc7150ca3a".to_owned(); let info_hash2 = InfoHash::from_str(&hash2).unwrap(); - let _ = tracker.upsert_peer_and_get_stats(&info_hash1, &sample_peer()); - let _ = tracker.upsert_peer_and_get_stats(&info_hash2, &sample_peer()); + let () = in_memory_torrent_repository.upsert_peer(&info_hash1, &sample_peer()); + let () = in_memory_torrent_repository.upsert_peer(&info_hash2, &sample_peer()); let offset = 0; let limit = 1; @@ -288,15 +289,16 @@ mod tests { async fn should_allow_using_pagination_in_the_result() { let config = tracker_configuration(); - let (tracker, in_memory_torrent_repository) = initialize_tracker_and_deps(&config); + let (_tracker, in_memory_torrent_repository) = initialize_tracker_and_deps(&config); let hash1 = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); let info_hash1 = InfoHash::from_str(&hash1).unwrap(); + let hash2 = "03840548643af2a7b63a9f5cbca348bc7150ca3a".to_owned(); let info_hash2 = InfoHash::from_str(&hash2).unwrap(); - let _ = tracker.upsert_peer_and_get_stats(&info_hash1, &sample_peer()); - let _ = tracker.upsert_peer_and_get_stats(&info_hash2, &sample_peer()); + let () = in_memory_torrent_repository.upsert_peer(&info_hash1, &sample_peer()); + let () = in_memory_torrent_repository.upsert_peer(&info_hash2, &sample_peer()); let offset = 1; let limit = 4000; @@ -319,15 +321,15 @@ mod tests { async fn should_return_torrents_ordered_by_info_hash() { let config = tracker_configuration(); - let (tracker, in_memory_torrent_repository) = initialize_tracker_and_deps(&config); + let (_tracker, in_memory_torrent_repository) = initialize_tracker_and_deps(&config); let hash1 = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); let info_hash1 = InfoHash::from_str(&hash1).unwrap(); - let _ = tracker.upsert_peer_and_get_stats(&info_hash1, &sample_peer()); + let () = in_memory_torrent_repository.upsert_peer(&info_hash1, &sample_peer()); let hash2 = "03840548643af2a7b63a9f5cbca348bc7150ca3a".to_owned(); let info_hash2 = InfoHash::from_str(&hash2).unwrap(); - let _ = tracker.upsert_peer_and_get_stats(&info_hash2, &sample_peer()); + let () = in_memory_torrent_repository.upsert_peer(&info_hash2, &sample_peer()); let torrents = get_torrents_page(in_memory_torrent_repository.clone(), Some(&Pagination::default())).await; diff --git a/src/servers/udp/handlers.rs b/src/servers/udp/handlers.rs index f8f57aea..d6073d2e 100644 --- a/src/servers/udp/handlers.rs +++ b/src/servers/udp/handlers.rs @@ -883,6 +883,7 @@ mod tests { }; use mockall::predicate::eq; + use crate::core::torrent::repository::in_memory::InMemoryTorrentRepository; use crate::core::{self, statistics, whitelist}; use crate::servers::udp::connection_cookie::make; use crate::servers::udp::handlers::tests::announce_request::AnnounceRequestBuilder; @@ -1034,7 +1035,7 @@ mod tests { assert_eq!(peers[0].peer_addr, SocketAddr::new(IpAddr::V4(remote_client_ip), client_port)); } - fn add_a_torrent_peer_using_ipv6(tracker: &Arc) { + fn add_a_torrent_peer_using_ipv6(in_memory_torrent_repository: &Arc) { let info_hash = AquaticInfoHash([0u8; 20]); let client_ip_v4 = Ipv4Addr::new(126, 0, 0, 1); @@ -1047,7 +1048,7 @@ mod tests { .with_peer_address(SocketAddr::new(IpAddr::V6(client_ip_v6), client_port)) .into(); - let _ = tracker.upsert_peer_and_get_stats(&info_hash.0.into(), &peer_using_ipv6); + let () = in_memory_torrent_repository.upsert_peer(&info_hash.0.into(), &peer_using_ipv6); } async fn announce_a_new_peer_using_ipv4( @@ -1079,14 +1080,14 @@ mod tests { let ( tracker, _scrape_handler, - _in_memory_torrent_repository, + in_memory_torrent_repository, _stats_event_sender, _in_memory_whitelist, _whitelist_manager, whitelist_authorization, ) = public_tracker(); - add_a_torrent_peer_using_ipv6(&tracker); + add_a_torrent_peer_using_ipv6(&in_memory_torrent_repository); let response = announce_a_new_peer_using_ipv4(tracker.clone(), whitelist_authorization).await; @@ -1201,6 +1202,7 @@ mod tests { }; use mockall::predicate::eq; + use crate::core::torrent::repository::in_memory::InMemoryTorrentRepository; use crate::core::{self, statistics, whitelist}; use crate::servers::udp::connection_cookie::make; use crate::servers::udp::handlers::tests::announce_request::AnnounceRequestBuilder; @@ -1357,7 +1359,7 @@ mod tests { assert_eq!(peers[0].peer_addr, SocketAddr::new(IpAddr::V6(remote_client_ip), client_port)); } - fn add_a_torrent_peer_using_ipv4(tracker: &Arc) { + fn add_a_torrent_peer_using_ipv4(in_memory_torrent_repository: &Arc) { let info_hash = AquaticInfoHash([0u8; 20]); let client_ip_v4 = Ipv4Addr::new(126, 0, 0, 1); @@ -1369,7 +1371,7 @@ mod tests { .with_peer_address(SocketAddr::new(IpAddr::V4(client_ip_v4), client_port)) .into(); - let _ = tracker.upsert_peer_and_get_stats(&info_hash.0.into(), &peer_using_ipv4); + let () = in_memory_torrent_repository.upsert_peer(&info_hash.0.into(), &peer_using_ipv4); } async fn announce_a_new_peer_using_ipv6( @@ -1404,14 +1406,14 @@ mod tests { let ( tracker, _scrape_handler, - _in_memory_torrent_repository, + in_memory_torrent_repository, _stats_event_sender, _in_memory_whitelist, _whitelist_manager, whitelist_authorization, ) = public_tracker(); - add_a_torrent_peer_using_ipv4(&tracker); + add_a_torrent_peer_using_ipv4(&in_memory_torrent_repository); let response = announce_a_new_peer_using_ipv6(tracker.clone(), whitelist_authorization).await; @@ -1559,7 +1561,7 @@ mod tests { use super::{gen_remote_fingerprint, TorrentPeerBuilder}; use crate::core::scrape_handler::ScrapeHandler; use crate::core::services::statistics; - use crate::core::{self}; + use crate::core::torrent::repository::in_memory::InMemoryTorrentRepository; use crate::servers::udp::connection_cookie::make; use crate::servers::udp::handlers::handle_scrape; use crate::servers::udp::handlers::tests::{ @@ -1618,7 +1620,11 @@ mod tests { ); } - async fn add_a_seeder(tracker: Arc, remote_addr: &SocketAddr, info_hash: &InfoHash) { + async fn add_a_seeder( + in_memory_torrent_repository: Arc, + remote_addr: &SocketAddr, + info_hash: &InfoHash, + ) { let peer_id = PeerId([255u8; 20]); let peer = TorrentPeerBuilder::new() @@ -1627,7 +1633,7 @@ mod tests { .with_number_of_bytes_left(0) .into(); - let _ = tracker.upsert_peer_and_get_stats(&info_hash.0.into(), &peer); + let () = in_memory_torrent_repository.upsert_peer(&info_hash.0.into(), &peer); } fn build_scrape_request(remote_addr: &SocketAddr, info_hash: &InfoHash) -> ScrapeRequest { @@ -1640,14 +1646,17 @@ mod tests { } } - async fn add_a_sample_seeder_and_scrape(tracker: Arc, scrape_handler: Arc) -> Response { + async fn add_a_sample_seeder_and_scrape( + in_memory_torrent_repository: Arc, + scrape_handler: Arc, + ) -> Response { let (stats_event_sender, _stats_repository) = statistics::setup::factory(false); let stats_event_sender = Arc::new(stats_event_sender); let remote_addr = sample_ipv4_remote_addr(); let info_hash = InfoHash([0u8; 20]); - add_a_seeder(tracker.clone(), &remote_addr, &info_hash).await; + add_a_seeder(in_memory_torrent_repository.clone(), &remote_addr, &info_hash).await; let request = build_scrape_request(&remote_addr, &info_hash); @@ -1678,17 +1687,18 @@ mod tests { #[tokio::test] async fn should_return_torrent_statistics_when_the_tracker_has_the_requested_torrent() { let ( - tracker, + _tracker, scrape_handler, - _in_memory_torrent_repository, + in_memory_torrent_repository, _stats_event_sender, _in_memory_whitelist, _whitelist_manager, _whitelist_authorization, ) = public_tracker(); - let torrent_stats = - match_scrape_response(add_a_sample_seeder_and_scrape(tracker.clone(), scrape_handler.clone()).await); + let torrent_stats = match_scrape_response( + add_a_sample_seeder_and_scrape(in_memory_torrent_repository.clone(), scrape_handler.clone()).await, + ); let expected_torrent_stats = vec![TorrentScrapeStatistics { seeders: NumberOfPeers(1.into()), @@ -1712,9 +1722,9 @@ mod tests { #[tokio::test] async fn should_return_the_torrent_statistics_when_the_requested_torrent_is_whitelisted() { let ( - tracker, + _tracker, scrape_handler, - _in_memory_torrent_repository, + in_memory_torrent_repository, stats_event_sender, in_memory_whitelist, _whitelist_manager, @@ -1724,7 +1734,7 @@ mod tests { let remote_addr = sample_ipv4_remote_addr(); let info_hash = InfoHash([0u8; 20]); - add_a_seeder(tracker.clone(), &remote_addr, &info_hash).await; + add_a_seeder(in_memory_torrent_repository.clone(), &remote_addr, &info_hash).await; in_memory_whitelist.add(&info_hash.0.into()).await; @@ -1755,9 +1765,9 @@ mod tests { #[tokio::test] async fn should_return_zeroed_statistics_when_the_requested_torrent_is_not_whitelisted() { let ( - tracker, + _tracker, scrape_handler, - _in_memory_torrent_repository, + in_memory_torrent_repository, stats_event_sender, _in_memory_whitelist, _whitelist_manager, @@ -1767,7 +1777,7 @@ mod tests { let remote_addr = sample_ipv4_remote_addr(); let info_hash = InfoHash([0u8; 20]); - add_a_seeder(tracker.clone(), &remote_addr, &info_hash).await; + add_a_seeder(in_memory_torrent_repository.clone(), &remote_addr, &info_hash).await; let request = build_scrape_request(&remote_addr, &info_hash); diff --git a/tests/servers/api/environment.rs b/tests/servers/api/environment.rs index 70f071bf..927f76ef 100644 --- a/tests/servers/api/environment.rs +++ b/tests/servers/api/environment.rs @@ -45,7 +45,7 @@ where { /// Add a torrent to the tracker pub fn add_torrent_peer(&self, info_hash: &InfoHash, peer: &peer::Peer) { - let _ = self.tracker.upsert_peer_and_get_stats(info_hash, peer); + let () = self.in_memory_torrent_repository.upsert_peer(info_hash, peer); } } diff --git a/tests/servers/http/environment.rs b/tests/servers/http/environment.rs index 63d37288..beaf2d38 100644 --- a/tests/servers/http/environment.rs +++ b/tests/servers/http/environment.rs @@ -37,7 +37,7 @@ pub struct Environment { impl Environment { /// Add a torrent to the tracker pub fn add_torrent_peer(&self, info_hash: &InfoHash, peer: &peer::Peer) { - let _ = self.tracker.upsert_peer_and_get_stats(info_hash, peer); + let () = self.in_memory_torrent_repository.upsert_peer(info_hash, peer); } } diff --git a/tests/servers/udp/environment.rs b/tests/servers/udp/environment.rs index 16719c31..09714146 100644 --- a/tests/servers/udp/environment.rs +++ b/tests/servers/udp/environment.rs @@ -9,6 +9,7 @@ use torrust_tracker_lib::core::databases::Database; use torrust_tracker_lib::core::scrape_handler::ScrapeHandler; use torrust_tracker_lib::core::statistics::event::sender::Sender; use torrust_tracker_lib::core::statistics::repository::Repository; +use torrust_tracker_lib::core::torrent::repository::in_memory::InMemoryTorrentRepository; use torrust_tracker_lib::core::{whitelist, Tracker}; use torrust_tracker_lib::servers::registar::Registar; use torrust_tracker_lib::servers::udp::server::banning::BanService; @@ -24,6 +25,7 @@ where pub config: Arc, pub database: Arc>, pub tracker: Arc, + pub in_memory_torrent_repository: Arc, pub scrape_handler: Arc, pub whitelist_authorization: Arc, pub stats_event_sender: Arc>>, @@ -40,7 +42,7 @@ where /// Add a torrent to the tracker #[allow(dead_code)] pub fn add_torrent(&self, info_hash: &InfoHash, peer: &peer::Peer) { - let _ = self.tracker.upsert_peer_and_get_stats(info_hash, peer); + let () = self.in_memory_torrent_repository.upsert_peer(info_hash, peer); } } @@ -63,6 +65,7 @@ impl Environment { config, database: app_container.database.clone(), tracker: app_container.tracker.clone(), + in_memory_torrent_repository: app_container.in_memory_torrent_repository.clone(), scrape_handler: app_container.scrape_handler.clone(), whitelist_authorization: app_container.whitelist_authorization.clone(), stats_event_sender: app_container.stats_event_sender.clone(), @@ -80,6 +83,7 @@ impl Environment { config: self.config, database: self.database.clone(), tracker: self.tracker.clone(), + in_memory_torrent_repository: self.in_memory_torrent_repository.clone(), scrape_handler: self.scrape_handler.clone(), whitelist_authorization: self.whitelist_authorization.clone(), stats_event_sender: self.stats_event_sender.clone(), @@ -120,6 +124,7 @@ impl Environment { config: self.config, database: self.database, tracker: self.tracker, + in_memory_torrent_repository: self.in_memory_torrent_repository, scrape_handler: self.scrape_handler, whitelist_authorization: self.whitelist_authorization, stats_event_sender: self.stats_event_sender, From 401c228b4e066a85af98af8a301e63ccaa366b3b Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Mon, 27 Jan 2025 12:45:53 +0000 Subject: [PATCH 3/6] refactor: [#1207] make method upsert_peer_and_get_stats private --- src/core/mod.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/core/mod.rs b/src/core/mod.rs index 5d501b00..5e5c2069 100644 --- a/src/core/mod.rs +++ b/src/core/mod.rs @@ -627,7 +627,7 @@ impl Tracker { /// the torrent info data which is persistent, and finally return the data /// needed for a `announce` request response. #[must_use] - pub fn upsert_peer_and_get_stats(&self, info_hash: &InfoHash, peer: &peer::Peer) -> SwarmMetadata { + fn upsert_peer_and_get_stats(&self, info_hash: &InfoHash, peer: &peer::Peer) -> SwarmMetadata { let swarm_metadata_before = match self.in_memory_torrent_repository.get_opt_swarm_metadata(info_hash) { Some(swarm_metadata) => swarm_metadata, None => SwarmMetadata::zeroed(), @@ -1393,7 +1393,10 @@ mod tests { use aquatic_udp_protocol::AnnounceEvent; use torrust_tracker_torrent_repository::entry::EntrySync; - use crate::core::tests::the_tracker::{sample_info_hash, sample_peer, tracker_persisting_torrents_in_database}; + use crate::core::tests::the_tracker::{ + peer_ip, sample_info_hash, sample_peer, tracker_persisting_torrents_in_database, + }; + use crate::core::PeersWanted; #[tokio::test] async fn it_should_persist_the_number_of_completed_peers_for_all_torrents_into_the_database() { @@ -1404,12 +1407,12 @@ mod tests { let mut peer = sample_peer(); peer.event = AnnounceEvent::Started; - let swarm_stats = tracker.upsert_peer_and_get_stats(&info_hash, &peer); - assert_eq!(swarm_stats.downloaded, 0); + let announce_data = tracker.announce(&info_hash, &mut peer, &peer_ip(), &PeersWanted::All); + assert_eq!(announce_data.stats.downloaded, 0); peer.event = AnnounceEvent::Completed; - let swarm_stats = tracker.upsert_peer_and_get_stats(&info_hash, &peer); - assert_eq!(swarm_stats.downloaded, 1); + let announce_data = tracker.announce(&info_hash, &mut peer, &peer_ip(), &PeersWanted::All); + assert_eq!(announce_data.stats.downloaded, 1); // Remove the newly updated torrent from memory let _unused = in_memory_torrent_repository.remove(&info_hash); From 026f957192072b4b62b53e4f291b3f38904390cd Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Mon, 27 Jan 2025 13:47:11 +0000 Subject: [PATCH 4/6] refactor: [#1207] extract AnnounceHandler --- src/app.rs | 2 + src/bootstrap/app.rs | 8 + src/bootstrap/jobs/http_tracker.rs | 18 +- src/bootstrap/jobs/udp_tracker.rs | 5 + src/container.rs | 2 + src/core/announce_handler.rs | 164 +++++++++++++ src/core/mod.rs | 298 +++++++++-------------- src/servers/http/server.rs | 8 + src/servers/http/v1/handlers/announce.rs | 49 +++- src/servers/http/v1/routes.rs | 5 + src/servers/http/v1/services/announce.rs | 79 ++++-- src/servers/http/v1/services/scrape.rs | 30 ++- src/servers/udp/handlers.rs | 90 ++++++- src/servers/udp/server/launcher.rs | 8 + src/servers/udp/server/mod.rs | 2 + src/servers/udp/server/processor.rs | 5 + src/servers/udp/server/spawner.rs | 3 + src/servers/udp/server/states.rs | 5 +- tests/servers/http/environment.rs | 6 + tests/servers/udp/environment.rs | 6 + 20 files changed, 554 insertions(+), 239 deletions(-) create mode 100644 src/core/announce_handler.rs diff --git a/src/app.rs b/src/app.rs index 3f0e8d39..00414bc1 100644 --- a/src/app.rs +++ b/src/app.rs @@ -80,6 +80,7 @@ pub async fn start(config: &Configuration, app_container: &AppContainer) -> Vec< udp_tracker::start_job( udp_tracker_config, app_container.tracker.clone(), + app_container.announce_handler.clone(), app_container.scrape_handler.clone(), app_container.whitelist_authorization.clone(), app_container.stats_event_sender.clone(), @@ -100,6 +101,7 @@ pub async fn start(config: &Configuration, app_container: &AppContainer) -> Vec< if let Some(job) = http_tracker::start_job( http_tracker_config, app_container.tracker.clone(), + app_container.announce_handler.clone(), app_container.scrape_handler.clone(), app_container.authentication_service.clone(), app_container.whitelist_authorization.clone(), diff --git a/src/bootstrap/app.rs b/src/bootstrap/app.rs index a0b6df3c..fa45998b 100644 --- a/src/bootstrap/app.rs +++ b/src/bootstrap/app.rs @@ -22,6 +22,7 @@ use tracing::instrument; use super::config::initialize_configuration; use crate::bootstrap; use crate::container::AppContainer; +use crate::core::announce_handler::AnnounceHandler; use crate::core::authentication::handler::KeysHandler; use crate::core::authentication::key::repository::in_memory::InMemoryKeyRepository; use crate::core::authentication::key::repository::persisted::DatabaseKeyRepository; @@ -121,11 +122,18 @@ pub fn initialize_app_container(configuration: &Configuration) -> AppContainer { &db_torrent_repository, )); + let announce_handler = Arc::new(AnnounceHandler::new( + &configuration.core, + &in_memory_torrent_repository, + &db_torrent_repository, + )); + let scrape_handler = Arc::new(ScrapeHandler::new(&whitelist_authorization, &in_memory_torrent_repository)); AppContainer { database, tracker, + announce_handler, scrape_handler, keys_handler, authentication_service, diff --git a/src/bootstrap/jobs/http_tracker.rs b/src/bootstrap/jobs/http_tracker.rs index 2e76e2f3..5da7da73 100644 --- a/src/bootstrap/jobs/http_tracker.rs +++ b/src/bootstrap/jobs/http_tracker.rs @@ -19,6 +19,7 @@ use torrust_tracker_configuration::HttpTracker; use tracing::instrument; use super::make_rust_tls; +use crate::core::announce_handler::AnnounceHandler; use crate::core::authentication::service::AuthenticationService; use crate::core::scrape_handler::ScrapeHandler; use crate::core::statistics::event::sender::Sender; @@ -39,6 +40,7 @@ use crate::servers::registar::ServiceRegistrationForm; #[instrument(skip( config, tracker, + announce_handler, scrape_handler, authentication_service, whitelist_authorization, @@ -48,6 +50,7 @@ use crate::servers::registar::ServiceRegistrationForm; pub async fn start_job( config: &HttpTracker, tracker: Arc, + announce_handler: Arc, scrape_handler: Arc, authentication_service: Arc, whitelist_authorization: Arc, @@ -67,6 +70,7 @@ pub async fn start_job( socket, tls, tracker.clone(), + announce_handler.clone(), scrape_handler.clone(), authentication_service.clone(), whitelist_authorization.clone(), @@ -80,11 +84,21 @@ pub async fn start_job( #[allow(clippy::too_many_arguments)] #[allow(clippy::async_yields_async)] -#[instrument(skip(socket, tls, tracker, scrape_handler, whitelist_authorization, stats_event_sender, form))] +#[instrument(skip( + socket, + tls, + tracker, + announce_handler, + scrape_handler, + whitelist_authorization, + stats_event_sender, + form +))] async fn start_v1( socket: SocketAddr, tls: Option, tracker: Arc, + announce_handler: Arc, scrape_handler: Arc, authentication_service: Arc, whitelist_authorization: Arc, @@ -94,6 +108,7 @@ async fn start_v1( let server = HttpServer::new(Launcher::new(socket, tls)) .start( tracker, + announce_handler, scrape_handler, authentication_service, whitelist_authorization, @@ -142,6 +157,7 @@ mod tests { start_job( config, app_container.tracker, + app_container.announce_handler, app_container.scrape_handler, app_container.authentication_service, app_container.whitelist_authorization, diff --git a/src/bootstrap/jobs/udp_tracker.rs b/src/bootstrap/jobs/udp_tracker.rs index dd55e4b8..d43c1c93 100644 --- a/src/bootstrap/jobs/udp_tracker.rs +++ b/src/bootstrap/jobs/udp_tracker.rs @@ -13,6 +13,7 @@ use tokio::task::JoinHandle; use torrust_tracker_configuration::UdpTracker; use tracing::instrument; +use crate::core::announce_handler::AnnounceHandler; use crate::core::scrape_handler::ScrapeHandler; use crate::core::statistics::event::sender::Sender; use crate::core::{self, whitelist}; @@ -32,10 +33,12 @@ use crate::servers::udp::UDP_TRACKER_LOG_TARGET; /// It will panic if it is unable to start the UDP service. /// It will panic if the task did not finish successfully. #[must_use] +#[allow(clippy::too_many_arguments)] #[allow(clippy::async_yields_async)] #[instrument(skip( config, tracker, + announce_handler, scrape_handler, whitelist_authorization, stats_event_sender, @@ -45,6 +48,7 @@ use crate::servers::udp::UDP_TRACKER_LOG_TARGET; pub async fn start_job( config: &UdpTracker, tracker: Arc, + announce_handler: Arc, scrape_handler: Arc, whitelist_authorization: Arc, stats_event_sender: Arc>>, @@ -57,6 +61,7 @@ pub async fn start_job( let server = Server::new(Spawner::new(bind_to)) .start( tracker, + announce_handler, scrape_handler, whitelist_authorization, stats_event_sender, diff --git a/src/container.rs b/src/container.rs index a7386200..4e958b6e 100644 --- a/src/container.rs +++ b/src/container.rs @@ -2,6 +2,7 @@ use std::sync::Arc; use tokio::sync::RwLock; +use crate::core::announce_handler::AnnounceHandler; use crate::core::authentication::handler::KeysHandler; use crate::core::authentication::service::AuthenticationService; use crate::core::databases::Database; @@ -18,6 +19,7 @@ use crate::servers::udp::server::banning::BanService; pub struct AppContainer { pub database: Arc>, pub tracker: Arc, + pub announce_handler: Arc, pub scrape_handler: Arc, pub keys_handler: Arc, pub authentication_service: Arc, diff --git a/src/core/announce_handler.rs b/src/core/announce_handler.rs new file mode 100644 index 00000000..a037d33d --- /dev/null +++ b/src/core/announce_handler.rs @@ -0,0 +1,164 @@ +use std::net::IpAddr; +use std::sync::Arc; + +use bittorrent_primitives::info_hash::InfoHash; +use torrust_tracker_configuration::{Core, TORRENT_PEERS_LIMIT}; +use torrust_tracker_primitives::core::AnnounceData; +use torrust_tracker_primitives::peer; +use torrust_tracker_primitives::swarm_metadata::SwarmMetadata; + +use super::torrent::repository::in_memory::InMemoryTorrentRepository; +use super::torrent::repository::persisted::DatabasePersistentTorrentRepository; + +pub struct AnnounceHandler { + /// The tracker configuration. + config: Core, + + /// The in-memory torrents repository. + in_memory_torrent_repository: Arc, + + /// The persistent torrents repository. + db_torrent_repository: Arc, +} + +impl AnnounceHandler { + #[must_use] + pub fn new( + config: &Core, + in_memory_torrent_repository: &Arc, + db_torrent_repository: &Arc, + ) -> Self { + Self { + config: config.clone(), + in_memory_torrent_repository: in_memory_torrent_repository.clone(), + db_torrent_repository: db_torrent_repository.clone(), + } + } + + /// It handles an announce request. + /// + /// BEP 03: [The `BitTorrent` Protocol Specification](https://www.bittorrent.org/beps/bep_0003.html). + pub fn announce( + &self, + info_hash: &InfoHash, + peer: &mut peer::Peer, + remote_client_ip: &IpAddr, + peers_wanted: &PeersWanted, + ) -> AnnounceData { + // code-review: maybe instead of mutating the peer we could just return + // a tuple with the new peer and the announce data: (Peer, AnnounceData). + // It could even be a different struct: `StoredPeer` or `PublicPeer`. + + // code-review: in the `scrape` function we perform an authorization check. + // We check if the torrent is whitelisted. Should we also check authorization here? + // I think so because the `Tracker` has the responsibility for checking authentication and authorization. + // The `Tracker` has delegated that responsibility to the handlers + // (because we want to return a friendly error response) but that does not mean we should + // double-check authorization at this domain level too. + // I would propose to return a `Result` here. + // Besides, regarding authentication the `Tracker` is also responsible for authentication but + // we are actually handling authentication at the handlers level. So I would extract that + // responsibility into another authentication service. + + tracing::debug!("Before: {peer:?}"); + peer.change_ip(&assign_ip_address_to_peer(remote_client_ip, self.config.net.external_ip)); + tracing::debug!("After: {peer:?}"); + + let stats = self.upsert_peer_and_get_stats(info_hash, peer); + + let peers = self + .in_memory_torrent_repository + .get_peers_for(info_hash, peer, peers_wanted.limit()); + + AnnounceData { + peers, + stats, + policy: self.config.announce_policy, + } + } + + /// It updates the torrent entry in memory, it also stores in the database + /// the torrent info data which is persistent, and finally return the data + /// needed for a `announce` request response. + #[must_use] + fn upsert_peer_and_get_stats(&self, info_hash: &InfoHash, peer: &peer::Peer) -> SwarmMetadata { + let swarm_metadata_before = match self.in_memory_torrent_repository.get_opt_swarm_metadata(info_hash) { + Some(swarm_metadata) => swarm_metadata, + None => SwarmMetadata::zeroed(), + }; + + self.in_memory_torrent_repository.upsert_peer(info_hash, peer); + + let swarm_metadata_after = match self.in_memory_torrent_repository.get_opt_swarm_metadata(info_hash) { + Some(swarm_metadata) => swarm_metadata, + None => SwarmMetadata::zeroed(), + }; + + if swarm_metadata_before != swarm_metadata_after { + self.persist_stats(info_hash, &swarm_metadata_after); + } + + swarm_metadata_after + } + + /// It stores the torrents stats into the database (if persistency is enabled). + fn persist_stats(&self, info_hash: &InfoHash, swarm_metadata: &SwarmMetadata) { + if self.config.tracker_policy.persistent_torrent_completed_stat { + let completed = swarm_metadata.downloaded; + let info_hash = *info_hash; + + drop(self.db_torrent_repository.save(&info_hash, completed)); + } + } +} + +/// How many peers the peer announcing wants in the announce response. +#[derive(Clone, Debug, PartialEq, Default)] +pub enum PeersWanted { + /// The peer wants as many peers as possible in the announce response. + #[default] + All, + /// The peer only wants a certain amount of peers in the announce response. + Only { amount: usize }, +} + +impl PeersWanted { + #[must_use] + pub fn only(limit: u32) -> Self { + let amount: usize = match limit.try_into() { + Ok(amount) => amount, + Err(_) => TORRENT_PEERS_LIMIT, + }; + + Self::Only { amount } + } + + fn limit(&self) -> usize { + match self { + PeersWanted::All => TORRENT_PEERS_LIMIT, + PeersWanted::Only { amount } => *amount, + } + } +} + +impl From for PeersWanted { + fn from(value: i32) -> Self { + if value > 0 { + match value.try_into() { + Ok(peers_wanted) => Self::Only { amount: peers_wanted }, + Err(_) => Self::All, + } + } else { + Self::All + } + } +} + +#[must_use] +pub fn assign_ip_address_to_peer(remote_client_ip: &IpAddr, tracker_external_ip: Option) -> IpAddr { + if let Some(host_ip) = tracker_external_ip.filter(|_| remote_client_ip.is_loopback()) { + host_ip + } else { + *remote_client_ip + } +} diff --git a/src/core/mod.rs b/src/core/mod.rs index 5e5c2069..2151ec1e 100644 --- a/src/core/mod.rs +++ b/src/core/mod.rs @@ -439,6 +439,7 @@ //! - Torrent metrics //! //! Refer to [`databases`] module for more information about persistence. +pub mod announce_handler; pub mod authentication; pub mod databases; pub mod error; @@ -453,13 +454,9 @@ pub mod peer_tests; use std::net::IpAddr; use std::sync::Arc; -use bittorrent_primitives::info_hash::InfoHash; use torrent::repository::in_memory::InMemoryTorrentRepository; use torrent::repository::persisted::DatabasePersistentTorrentRepository; -use torrust_tracker_configuration::{AnnouncePolicy, Core, TORRENT_PEERS_LIMIT}; -use torrust_tracker_primitives::core::AnnounceData; -use torrust_tracker_primitives::peer; -use torrust_tracker_primitives::swarm_metadata::SwarmMetadata; +use torrust_tracker_configuration::{AnnouncePolicy, Core}; /// The domain layer tracker service. /// @@ -475,52 +472,10 @@ pub struct Tracker { config: Core, /// The in-memory torrents repository. - in_memory_torrent_repository: Arc, + _in_memory_torrent_repository: Arc, /// The persistent torrents repository. - db_torrent_repository: Arc, -} - -/// How many peers the peer announcing wants in the announce response. -#[derive(Clone, Debug, PartialEq, Default)] -pub enum PeersWanted { - /// The peer wants as many peers as possible in the announce response. - #[default] - All, - /// The peer only wants a certain amount of peers in the announce response. - Only { amount: usize }, -} - -impl PeersWanted { - #[must_use] - pub fn only(limit: u32) -> Self { - let amount: usize = match limit.try_into() { - Ok(amount) => amount, - Err(_) => TORRENT_PEERS_LIMIT, - }; - - Self::Only { amount } - } - - fn limit(&self) -> usize { - match self { - PeersWanted::All => TORRENT_PEERS_LIMIT, - PeersWanted::Only { amount } => *amount, - } - } -} - -impl From for PeersWanted { - fn from(value: i32) -> Self { - if value > 0 { - match value.try_into() { - Ok(peers_wanted) => Self::Only { amount: peers_wanted }, - Err(_) => Self::All, - } - } else { - Self::All - } - } + _db_torrent_repository: Arc, } impl Tracker { @@ -536,8 +491,8 @@ impl Tracker { ) -> Result { Ok(Tracker { config: config.clone(), - in_memory_torrent_repository: in_memory_torrent_repository.clone(), - db_torrent_repository: db_torrent_repository.clone(), + _in_memory_torrent_repository: in_memory_torrent_repository.clone(), + _db_torrent_repository: db_torrent_repository.clone(), }) } @@ -580,91 +535,6 @@ impl Tracker { pub fn get_maybe_external_ip(&self) -> Option { self.config.net.external_ip } - - /// It handles an announce request. - /// - /// BEP 03: [The `BitTorrent` Protocol Specification](https://www.bittorrent.org/beps/bep_0003.html). - pub fn announce( - &self, - info_hash: &InfoHash, - peer: &mut peer::Peer, - remote_client_ip: &IpAddr, - peers_wanted: &PeersWanted, - ) -> AnnounceData { - // code-review: maybe instead of mutating the peer we could just return - // a tuple with the new peer and the announce data: (Peer, AnnounceData). - // It could even be a different struct: `StoredPeer` or `PublicPeer`. - - // code-review: in the `scrape` function we perform an authorization check. - // We check if the torrent is whitelisted. Should we also check authorization here? - // I think so because the `Tracker` has the responsibility for checking authentication and authorization. - // The `Tracker` has delegated that responsibility to the handlers - // (because we want to return a friendly error response) but that does not mean we should - // double-check authorization at this domain level too. - // I would propose to return a `Result` here. - // Besides, regarding authentication the `Tracker` is also responsible for authentication but - // we are actually handling authentication at the handlers level. So I would extract that - // responsibility into another authentication service. - - tracing::debug!("Before: {peer:?}"); - peer.change_ip(&assign_ip_address_to_peer(remote_client_ip, self.config.net.external_ip)); - tracing::debug!("After: {peer:?}"); - - let stats = self.upsert_peer_and_get_stats(info_hash, peer); - - let peers = self - .in_memory_torrent_repository - .get_peers_for(info_hash, peer, peers_wanted.limit()); - - AnnounceData { - peers, - stats, - policy: self.get_announce_policy(), - } - } - - /// It updates the torrent entry in memory, it also stores in the database - /// the torrent info data which is persistent, and finally return the data - /// needed for a `announce` request response. - #[must_use] - fn upsert_peer_and_get_stats(&self, info_hash: &InfoHash, peer: &peer::Peer) -> SwarmMetadata { - let swarm_metadata_before = match self.in_memory_torrent_repository.get_opt_swarm_metadata(info_hash) { - Some(swarm_metadata) => swarm_metadata, - None => SwarmMetadata::zeroed(), - }; - - self.in_memory_torrent_repository.upsert_peer(info_hash, peer); - - let swarm_metadata_after = match self.in_memory_torrent_repository.get_opt_swarm_metadata(info_hash) { - Some(swarm_metadata) => swarm_metadata, - None => SwarmMetadata::zeroed(), - }; - - if swarm_metadata_before != swarm_metadata_after { - self.persist_stats(info_hash, &swarm_metadata_after); - } - - swarm_metadata_after - } - - /// It stores the torrents stats into the database (if persistency is enabled). - fn persist_stats(&self, info_hash: &InfoHash, swarm_metadata: &SwarmMetadata) { - if self.config.tracker_policy.persistent_torrent_completed_stat { - let completed = swarm_metadata.downloaded; - let info_hash = *info_hash; - - drop(self.db_torrent_repository.save(&info_hash, completed)); - } - } -} - -#[must_use] -fn assign_ip_address_to_peer(remote_client_ip: &IpAddr, tracker_external_ip: Option) -> IpAddr { - if let Some(host_ip) = tracker_external_ip.filter(|_| remote_client_ip.is_loopback()) { - host_ip - } else { - *remote_client_ip - } } #[cfg(test)] @@ -680,12 +550,13 @@ mod tests { use bittorrent_primitives::info_hash::fixture::gen_seeded_infohash; use bittorrent_primitives::info_hash::InfoHash; use torrust_tracker_configuration::TORRENT_PEERS_LIMIT; + use torrust_tracker_primitives::peer::Peer; use torrust_tracker_primitives::torrent_metrics::TorrentsMetrics; use torrust_tracker_primitives::DurationSinceUnixEpoch; use torrust_tracker_test_helpers::configuration; use crate::app_test::initialize_tracker_dependencies; - use crate::core::peer::Peer; + use crate::core::announce_handler::AnnounceHandler; use crate::core::scrape_handler::ScrapeHandler; use crate::core::services::{initialize_tracker, initialize_whitelist_manager}; use crate::core::torrent::manager::TorrentsManager; @@ -693,7 +564,12 @@ mod tests { use crate::core::whitelist::manager::WhiteListManager; use crate::core::{whitelist, Tracker}; - fn public_tracker() -> (Arc, Arc, Arc) { + fn public_tracker() -> ( + Arc, + Arc, + Arc, + Arc, + ) { let config = configuration::ephemeral_public(); let ( @@ -712,9 +588,15 @@ mod tests { &db_torrent_repository, )); + let announce_handler = Arc::new(AnnounceHandler::new( + &config.core, + &in_memory_torrent_repository, + &db_torrent_repository, + )); + let scrape_handler = Arc::new(ScrapeHandler::new(&whitelist_authorization, &in_memory_torrent_repository)); - (tracker, in_memory_torrent_repository, scrape_handler) + (tracker, announce_handler, in_memory_torrent_repository, scrape_handler) } fn public_tracker_and_in_memory_torrents_repository() -> (Arc, Arc) { @@ -739,8 +621,10 @@ mod tests { (tracker, in_memory_torrent_repository) } + #[allow(clippy::type_complexity)] fn whitelisted_tracker() -> ( - Tracker, + Arc, + Arc, Arc, Arc, Arc, @@ -759,14 +643,35 @@ mod tests { let whitelist_manager = initialize_whitelist_manager(database.clone(), in_memory_whitelist.clone()); - let tracker = initialize_tracker(&config, &in_memory_torrent_repository, &db_torrent_repository); + let tracker = Arc::new(initialize_tracker( + &config, + &in_memory_torrent_repository, + &db_torrent_repository, + )); + + let announce_handler = Arc::new(AnnounceHandler::new( + &config.core, + &in_memory_torrent_repository, + &db_torrent_repository, + )); let scrape_handler = Arc::new(ScrapeHandler::new(&whitelist_authorization, &in_memory_torrent_repository)); - (tracker, whitelist_authorization, whitelist_manager, scrape_handler) + ( + tracker, + announce_handler, + whitelist_authorization, + whitelist_manager, + scrape_handler, + ) } - pub fn tracker_persisting_torrents_in_database() -> (Tracker, Arc, Arc) { + pub fn tracker_persisting_torrents_in_database() -> ( + Arc, + Arc, + Arc, + Arc, + ) { let mut config = configuration::ephemeral_listed(); config.core.tracker_policy.persistent_torrent_completed_stat = true; @@ -780,9 +685,19 @@ mod tests { torrents_manager, ) = initialize_tracker_dependencies(&config); - let tracker = initialize_tracker(&config, &in_memory_torrent_repository, &db_torrent_repository); + let tracker = Arc::new(initialize_tracker( + &config, + &in_memory_torrent_repository, + &db_torrent_repository, + )); - (tracker, torrents_manager, in_memory_torrent_repository) + let announce_handler = Arc::new(AnnounceHandler::new( + &config.core, + &in_memory_torrent_repository, + &db_torrent_repository, + )); + + (tracker, announce_handler, torrents_manager, in_memory_torrent_repository) } fn sample_info_hash() -> InfoHash { @@ -928,23 +843,21 @@ mod tests { #[tokio::test] async fn it_should_return_the_peers_for_a_given_torrent_excluding_a_given_peer() { - let (tracker, in_memory_torrent_repository, _scrape_handler) = public_tracker(); + let (_tracker, _announce_handler, in_memory_torrent_repository, _scrape_handler) = public_tracker(); let info_hash = sample_info_hash(); let peer = sample_peer(); let () = in_memory_torrent_repository.upsert_peer(&info_hash, &peer); - let peers = tracker - .in_memory_torrent_repository - .get_peers_for(&info_hash, &peer, TORRENT_PEERS_LIMIT); + let peers = in_memory_torrent_repository.get_peers_for(&info_hash, &peer, TORRENT_PEERS_LIMIT); assert_eq!(peers, vec![]); } #[tokio::test] async fn it_should_return_74_peers_at_the_most_for_a_given_torrent_when_it_filters_out_a_given_peer() { - let (tracker, in_memory_torrent_repository, _scrape_handler) = public_tracker(); + let (_tracker, _announce_handler, in_memory_torrent_repository, _scrape_handler) = public_tracker(); let info_hash = sample_info_hash(); @@ -967,9 +880,7 @@ mod tests { let () = in_memory_torrent_repository.upsert_peer(&info_hash, &peer); } - let peers = tracker - .in_memory_torrent_repository - .get_peers_for(&info_hash, &excluded_peer, TORRENT_PEERS_LIMIT); + let peers = in_memory_torrent_repository.get_peers_for(&info_hash, &excluded_peer, TORRENT_PEERS_LIMIT); assert_eq!(peers.len(), 74); } @@ -1025,16 +936,16 @@ mod tests { use std::sync::Arc; + use crate::core::announce_handler::PeersWanted; use crate::core::tests::the_tracker::{ peer_ip, public_tracker, sample_info_hash, sample_peer, sample_peer_1, sample_peer_2, }; - use crate::core::PeersWanted; mod should_assign_the_ip_to_the_peer { use std::net::{IpAddr, Ipv4Addr}; - use crate::core::assign_ip_address_to_peer; + use crate::core::announce_handler::assign_ip_address_to_peer; #[test] fn using_the_source_ip_instead_of_the_ip_in_the_announce_request() { @@ -1050,7 +961,7 @@ mod tests { use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; use std::str::FromStr; - use crate::core::assign_ip_address_to_peer; + use crate::core::announce_handler::assign_ip_address_to_peer; #[test] fn it_should_use_the_loopback_ip_if_the_tracker_does_not_have_the_external_ip_configuration() { @@ -1091,7 +1002,7 @@ mod tests { use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; use std::str::FromStr; - use crate::core::assign_ip_address_to_peer; + use crate::core::announce_handler::assign_ip_address_to_peer; #[test] fn it_should_use_the_loopback_ip_if_the_tracker_does_not_have_the_external_ip_configuration() { @@ -1130,21 +1041,21 @@ mod tests { #[tokio::test] async fn it_should_return_the_announce_data_with_an_empty_peer_list_when_it_is_the_first_announced_peer() { - let (tracker, _in_memory_torrent_repository, _scrape_handler) = public_tracker(); + let (_tracker, announce_handler, _in_memory_torrent_repository, _scrape_handler) = public_tracker(); let mut peer = sample_peer(); - let announce_data = tracker.announce(&sample_info_hash(), &mut peer, &peer_ip(), &PeersWanted::All); + let announce_data = announce_handler.announce(&sample_info_hash(), &mut peer, &peer_ip(), &PeersWanted::All); assert_eq!(announce_data.peers, vec![]); } #[tokio::test] async fn it_should_return_the_announce_data_with_the_previously_announced_peers() { - let (tracker, _in_memory_torrent_repository, _scrape_handler) = public_tracker(); + let (_tracker, announce_handler, _in_memory_torrent_repository, _scrape_handler) = public_tracker(); let mut previously_announced_peer = sample_peer_1(); - tracker.announce( + announce_handler.announce( &sample_info_hash(), &mut previously_announced_peer, &peer_ip(), @@ -1152,51 +1063,53 @@ mod tests { ); let mut peer = sample_peer_2(); - let announce_data = tracker.announce(&sample_info_hash(), &mut peer, &peer_ip(), &PeersWanted::All); + let announce_data = announce_handler.announce(&sample_info_hash(), &mut peer, &peer_ip(), &PeersWanted::All); assert_eq!(announce_data.peers, vec![Arc::new(previously_announced_peer)]); } mod it_should_update_the_swarm_stats_for_the_torrent { + use crate::core::announce_handler::PeersWanted; use crate::core::tests::the_tracker::{ completed_peer, leecher, peer_ip, public_tracker, sample_info_hash, seeder, started_peer, }; - use crate::core::PeersWanted; #[tokio::test] async fn when_the_peer_is_a_seeder() { - let (tracker, _in_memory_torrent_repository, _scrape_handler) = public_tracker(); + let (_tracker, announce_handler, _in_memory_torrent_repository, _scrape_handler) = public_tracker(); let mut peer = seeder(); - let announce_data = tracker.announce(&sample_info_hash(), &mut peer, &peer_ip(), &PeersWanted::All); + let announce_data = + announce_handler.announce(&sample_info_hash(), &mut peer, &peer_ip(), &PeersWanted::All); assert_eq!(announce_data.stats.complete, 1); } #[tokio::test] async fn when_the_peer_is_a_leecher() { - let (tracker, _in_memory_torrent_repository, _scrape_handler) = public_tracker(); + let (_tracker, announce_handler, _in_memory_torrent_repository, _scrape_handler) = public_tracker(); let mut peer = leecher(); - let announce_data = tracker.announce(&sample_info_hash(), &mut peer, &peer_ip(), &PeersWanted::All); + let announce_data = + announce_handler.announce(&sample_info_hash(), &mut peer, &peer_ip(), &PeersWanted::All); assert_eq!(announce_data.stats.incomplete, 1); } #[tokio::test] async fn when_a_previously_announced_started_peer_has_completed_downloading() { - let (tracker, _in_memory_torrent_repository, _scrape_handler) = public_tracker(); + let (_tracker, announce_handler, _in_memory_torrent_repository, _scrape_handler) = public_tracker(); // We have to announce with "started" event because peer does not count if peer was not previously known let mut started_peer = started_peer(); - tracker.announce(&sample_info_hash(), &mut started_peer, &peer_ip(), &PeersWanted::All); + announce_handler.announce(&sample_info_hash(), &mut started_peer, &peer_ip(), &PeersWanted::All); let mut completed_peer = completed_peer(); let announce_data = - tracker.announce(&sample_info_hash(), &mut completed_peer, &peer_ip(), &PeersWanted::All); + announce_handler.announce(&sample_info_hash(), &mut completed_peer, &peer_ip(), &PeersWanted::All); assert_eq!(announce_data.stats.downloaded, 1); } @@ -1209,19 +1122,20 @@ mod tests { use bittorrent_primitives::info_hash::InfoHash; use torrust_tracker_primitives::core::ScrapeData; + use torrust_tracker_primitives::swarm_metadata::SwarmMetadata; + use crate::core::announce_handler::PeersWanted; use crate::core::tests::the_tracker::{complete_peer, incomplete_peer, public_tracker}; - use crate::core::{PeersWanted, SwarmMetadata}; #[tokio::test] async fn it_should_return_the_swarm_metadata_for_the_requested_file_if_the_tracker_has_that_torrent() { - let (tracker, _in_memory_torrent_repository, scrape_handler) = public_tracker(); + let (_tracker, announce_handler, _in_memory_torrent_repository, scrape_handler) = public_tracker(); let info_hash = "3b245504cf5f11bbdbe1201cea6a6bf45aee1bc0".parse::().unwrap(); // # DevSkim: ignore DS173237 // Announce a "complete" peer for the torrent let mut complete_peer = complete_peer(); - tracker.announce( + announce_handler.announce( &info_hash, &mut complete_peer, &IpAddr::V4(Ipv4Addr::new(126, 0, 0, 10)), @@ -1230,7 +1144,7 @@ mod tests { // Announce an "incomplete" peer for the torrent let mut incomplete_peer = incomplete_peer(); - tracker.announce( + announce_handler.announce( &info_hash, &mut incomplete_peer, &IpAddr::V4(Ipv4Addr::new(126, 0, 0, 11)), @@ -1263,7 +1177,8 @@ mod tests { #[tokio::test] async fn it_should_authorize_the_announce_and_scrape_actions_on_whitelisted_torrents() { - let (_tracker, whitelist_authorization, whitelist_manager, _scrape_handler) = whitelisted_tracker(); + let (_tracker, _announce_handler, whitelist_authorization, whitelist_manager, _scrape_handler) = + whitelisted_tracker(); let info_hash = sample_info_hash(); @@ -1276,7 +1191,8 @@ mod tests { #[tokio::test] async fn it_should_not_authorize_the_announce_and_scrape_actions_on_not_whitelisted_torrents() { - let (_tracker, whitelist_authorization, _whitelist_manager, _scrape_handler) = whitelisted_tracker(); + let (_tracker, _announce_handler, whitelist_authorization, _whitelist_manager, _scrape_handler) = + whitelisted_tracker(); let info_hash = sample_info_hash(); @@ -1295,7 +1211,8 @@ mod tests { #[tokio::test] async fn it_should_add_a_torrent_to_the_whitelist() { - let (_tracker, _whitelist_authorization, whitelist_manager, _scrape_handler) = whitelisted_tracker(); + let (_tracker, _announce_handler, _whitelist_authorization, whitelist_manager, _scrape_handler) = + whitelisted_tracker(); let info_hash = sample_info_hash(); @@ -1306,7 +1223,8 @@ mod tests { #[tokio::test] async fn it_should_remove_a_torrent_from_the_whitelist() { - let (_tracker, _whitelist_authorization, whitelist_manager, _scrape_handler) = whitelisted_tracker(); + let (_tracker, _announce_handler, _whitelist_authorization, whitelist_manager, _scrape_handler) = + whitelisted_tracker(); let info_hash = sample_info_hash(); @@ -1322,7 +1240,8 @@ mod tests { #[tokio::test] async fn it_should_load_the_whitelist_from_the_database() { - let (_tracker, _whitelist_authorization, whitelist_manager, _scrape_handler) = whitelisted_tracker(); + let (_tracker, _announce_handler, _whitelist_authorization, whitelist_manager, _scrape_handler) = + whitelisted_tracker(); let info_hash = sample_info_hash(); @@ -1347,10 +1266,10 @@ mod tests { use torrust_tracker_primitives::core::ScrapeData; use torrust_tracker_primitives::swarm_metadata::SwarmMetadata; + use crate::core::announce_handler::PeersWanted; use crate::core::tests::the_tracker::{ complete_peer, incomplete_peer, peer_ip, sample_info_hash, whitelisted_tracker, }; - use crate::core::PeersWanted; #[test] fn it_should_be_able_to_build_a_zeroed_scrape_data_for_a_list_of_info_hashes() { @@ -1366,16 +1285,17 @@ mod tests { #[tokio::test] async fn it_should_return_the_zeroed_swarm_metadata_for_the_requested_file_if_it_is_not_whitelisted() { - let (tracker, _whitelist_authorization, _whitelist_manager, scrape_handler) = whitelisted_tracker(); + let (_tracker, announce_handler, _whitelist_authorization, _whitelist_manager, scrape_handler) = + whitelisted_tracker(); let info_hash = "3b245504cf5f11bbdbe1201cea6a6bf45aee1bc0".parse::().unwrap(); // # DevSkim: ignore DS173237 let mut peer = incomplete_peer(); - tracker.announce(&info_hash, &mut peer, &peer_ip(), &PeersWanted::All); + announce_handler.announce(&info_hash, &mut peer, &peer_ip(), &PeersWanted::All); // Announce twice to force non zeroed swarm metadata let mut peer = complete_peer(); - tracker.announce(&info_hash, &mut peer, &peer_ip(), &PeersWanted::All); + announce_handler.announce(&info_hash, &mut peer, &peer_ip(), &PeersWanted::All); let scrape_data = scrape_handler.scrape(&vec![info_hash]).await; @@ -1393,25 +1313,26 @@ mod tests { use aquatic_udp_protocol::AnnounceEvent; use torrust_tracker_torrent_repository::entry::EntrySync; + use crate::core::announce_handler::PeersWanted; use crate::core::tests::the_tracker::{ peer_ip, sample_info_hash, sample_peer, tracker_persisting_torrents_in_database, }; - use crate::core::PeersWanted; #[tokio::test] async fn it_should_persist_the_number_of_completed_peers_for_all_torrents_into_the_database() { - let (tracker, torrents_manager, in_memory_torrent_repository) = tracker_persisting_torrents_in_database(); + let (_tracker, announce_handler, torrents_manager, in_memory_torrent_repository) = + tracker_persisting_torrents_in_database(); let info_hash = sample_info_hash(); let mut peer = sample_peer(); peer.event = AnnounceEvent::Started; - let announce_data = tracker.announce(&info_hash, &mut peer, &peer_ip(), &PeersWanted::All); + let announce_data = announce_handler.announce(&info_hash, &mut peer, &peer_ip(), &PeersWanted::All); assert_eq!(announce_data.stats.downloaded, 0); peer.event = AnnounceEvent::Completed; - let announce_data = tracker.announce(&info_hash, &mut peer, &peer_ip(), &PeersWanted::All); + let announce_data = announce_handler.announce(&info_hash, &mut peer, &peer_ip(), &PeersWanted::All); assert_eq!(announce_data.stats.downloaded, 1); // Remove the newly updated torrent from memory @@ -1419,8 +1340,7 @@ mod tests { torrents_manager.load_torrents_from_database().unwrap(); - let torrent_entry = tracker - .in_memory_torrent_repository + let torrent_entry = in_memory_torrent_repository .get(&info_hash) .expect("it should be able to get entry"); diff --git a/src/servers/http/server.rs b/src/servers/http/server.rs index 573337ba..3bb49c1a 100644 --- a/src/servers/http/server.rs +++ b/src/servers/http/server.rs @@ -11,6 +11,7 @@ use tracing::instrument; use super::v1::routes::router; use crate::bootstrap::jobs::Started; +use crate::core::announce_handler::AnnounceHandler; use crate::core::authentication::service::AuthenticationService; use crate::core::scrape_handler::ScrapeHandler; use crate::core::{statistics, whitelist, Tracker}; @@ -48,6 +49,7 @@ impl Launcher { #[instrument(skip( self, tracker, + announce_handler, scrape_handler, authentication_service, whitelist_authorization, @@ -58,6 +60,7 @@ impl Launcher { fn start( &self, tracker: Arc, + announce_handler: Arc, scrape_handler: Arc, authentication_service: Arc, whitelist_authorization: Arc, @@ -83,6 +86,7 @@ impl Launcher { let app = router( tracker, + announce_handler, scrape_handler, authentication_service, whitelist_authorization, @@ -181,9 +185,11 @@ impl HttpServer { /// /// It would panic spawned HTTP server launcher cannot send the bound `SocketAddr` /// back to the main thread. + #[allow(clippy::too_many_arguments)] pub async fn start( self, tracker: Arc, + announce_handler: Arc, scrape_handler: Arc, authentication_service: Arc, whitelist_authorization: Arc, @@ -198,6 +204,7 @@ impl HttpServer { let task = tokio::spawn(async move { let server = launcher.start( tracker, + announce_handler, scrape_handler, authentication_service, whitelist_authorization, @@ -303,6 +310,7 @@ mod tests { let started = stopped .start( app_container.tracker, + app_container.announce_handler, app_container.scrape_handler, app_container.authentication_service, app_container.whitelist_authorization, diff --git a/src/servers/http/v1/handlers/announce.rs b/src/servers/http/v1/handlers/announce.rs index 8b57ce54..39ddd171 100644 --- a/src/servers/http/v1/handlers/announce.rs +++ b/src/servers/http/v1/handlers/announce.rs @@ -21,10 +21,11 @@ use torrust_tracker_clock::clock::Time; use torrust_tracker_primitives::core::AnnounceData; use torrust_tracker_primitives::peer; +use crate::core::announce_handler::{AnnounceHandler, PeersWanted}; use crate::core::authentication::service::AuthenticationService; use crate::core::authentication::Key; use crate::core::statistics::event::sender::Sender; -use crate::core::{whitelist, PeersWanted, Tracker}; +use crate::core::{whitelist, Tracker}; use crate::servers::http::v1::extractors::announce_request::ExtractRequest; use crate::servers::http::v1::extractors::authentication_key::Extract as ExtractKey; use crate::servers::http::v1::extractors::client_ip_sources::Extract as ExtractClientIpSources; @@ -39,6 +40,7 @@ use crate::CurrentClock; pub async fn handle_without_key( State(state): State<( Arc, + Arc, Arc, Arc, Arc>>, @@ -53,6 +55,7 @@ pub async fn handle_without_key( &state.1, &state.2, &state.3, + &state.4, &announce_request, &client_ip_sources, None, @@ -67,6 +70,7 @@ pub async fn handle_without_key( pub async fn handle_with_key( State(state): State<( Arc, + Arc, Arc, Arc, Arc>>, @@ -82,6 +86,7 @@ pub async fn handle_with_key( &state.1, &state.2, &state.3, + &state.4, &announce_request, &client_ip_sources, Some(key), @@ -93,8 +98,10 @@ pub async fn handle_with_key( /// /// Internal implementation that handles both the `authenticated` and /// `unauthenticated` modes. +#[allow(clippy::too_many_arguments)] async fn handle( tracker: &Arc, + announce_handler: &Arc, authentication_service: &Arc, whitelist_authorization: &Arc, opt_stats_event_sender: &Arc>>, @@ -104,6 +111,7 @@ async fn handle( ) -> Response { let announce_data = match handle_announce( tracker, + announce_handler, authentication_service, whitelist_authorization, opt_stats_event_sender, @@ -125,8 +133,10 @@ async fn handle( See https://github.com/torrust/torrust-tracker/discussions/240. */ +#[allow(clippy::too_many_arguments)] async fn handle_announce( tracker: &Arc, + announce_handler: &Arc, authentication_service: &Arc, whitelist_authorization: &Arc, opt_stats_event_sender: &Arc>>, @@ -168,6 +178,7 @@ async fn handle_announce( let announce_data = services::announce::invoke( tracker.clone(), + announce_handler.clone(), opt_stats_event_sender.clone(), announce_request.info_hash, &mut peer, @@ -244,6 +255,7 @@ mod tests { use torrust_tracker_test_helpers::configuration; use crate::app_test::initialize_tracker_dependencies; + use crate::core::announce_handler::AnnounceHandler; use crate::core::authentication::service::AuthenticationService; use crate::core::services::{initialize_tracker, statistics}; use crate::core::statistics::event::sender::Sender; @@ -251,6 +263,7 @@ mod tests { type TrackerAndDeps = ( Arc, + Arc, Arc>>, Arc, Arc, @@ -293,7 +306,19 @@ mod tests { &db_torrent_repository, )); - (tracker, stats_event_sender, whitelist_authorization, authentication_service) + let announce_handler = Arc::new(AnnounceHandler::new( + &config.core, + &in_memory_torrent_repository, + &db_torrent_repository, + )); + + ( + tracker, + announce_handler, + stats_event_sender, + whitelist_authorization, + authentication_service, + ) } fn sample_announce_request() -> Announce { @@ -336,7 +361,8 @@ mod tests { #[tokio::test] async fn it_should_fail_when_the_authentication_key_is_missing() { - let (tracker, stats_event_sender, whitelist_authorization, authentication_service) = private_tracker(); + let (tracker, announce_handler, stats_event_sender, whitelist_authorization, authentication_service) = + private_tracker(); let tracker = Arc::new(tracker); let stats_event_sender = Arc::new(stats_event_sender); @@ -345,6 +371,7 @@ mod tests { let response = handle_announce( &tracker, + &announce_handler, &authentication_service, &whitelist_authorization, &stats_event_sender, @@ -363,7 +390,8 @@ mod tests { #[tokio::test] async fn it_should_fail_when_the_authentication_key_is_invalid() { - let (tracker, stats_event_sender, whitelist_authorization, authentication_service) = private_tracker(); + let (tracker, announce_handler, stats_event_sender, whitelist_authorization, authentication_service) = + private_tracker(); let tracker = Arc::new(tracker); let stats_event_sender = Arc::new(stats_event_sender); @@ -374,6 +402,7 @@ mod tests { let response = handle_announce( &tracker, + &announce_handler, &authentication_service, &whitelist_authorization, &stats_event_sender, @@ -398,7 +427,8 @@ mod tests { #[tokio::test] async fn it_should_fail_when_the_announced_torrent_is_not_whitelisted() { - let (tracker, stats_event_sender, whitelist_authorization, authentication_service) = whitelisted_tracker(); + let (tracker, announce_handler, stats_event_sender, whitelist_authorization, authentication_service) = + whitelisted_tracker(); let tracker = Arc::new(tracker); let stats_event_sender = Arc::new(stats_event_sender); @@ -407,6 +437,7 @@ mod tests { let response = handle_announce( &tracker, + &announce_handler, &authentication_service, &whitelist_authorization, &stats_event_sender, @@ -439,7 +470,8 @@ mod tests { #[tokio::test] async fn it_should_fail_when_the_right_most_x_forwarded_for_header_ip_is_not_available() { - let (tracker, stats_event_sender, whitelist_authorization, authentication_service) = tracker_on_reverse_proxy(); + let (tracker, announce_handler, stats_event_sender, whitelist_authorization, authentication_service) = + tracker_on_reverse_proxy(); let tracker = Arc::new(tracker); let stats_event_sender = Arc::new(stats_event_sender); @@ -451,6 +483,7 @@ mod tests { let response = handle_announce( &tracker, + &announce_handler, &authentication_service, &whitelist_authorization, &stats_event_sender, @@ -480,7 +513,8 @@ mod tests { #[tokio::test] async fn it_should_fail_when_the_client_ip_from_the_connection_info_is_not_available() { - let (tracker, stats_event_sender, whitelist_authorization, authentication_service) = tracker_not_on_reverse_proxy(); + let (tracker, announce_handler, stats_event_sender, whitelist_authorization, authentication_service) = + tracker_not_on_reverse_proxy(); let tracker = Arc::new(tracker); let stats_event_sender = Arc::new(stats_event_sender); @@ -492,6 +526,7 @@ mod tests { let response = handle_announce( &tracker, + &announce_handler, &authentication_service, &whitelist_authorization, &stats_event_sender, diff --git a/src/servers/http/v1/routes.rs b/src/servers/http/v1/routes.rs index 0c0be5bd..50e1494b 100644 --- a/src/servers/http/v1/routes.rs +++ b/src/servers/http/v1/routes.rs @@ -22,6 +22,7 @@ use tower_http::LatencyUnit; use tracing::{instrument, Level, Span}; use super::handlers::{announce, health_check, scrape}; +use crate::core::announce_handler::AnnounceHandler; use crate::core::authentication::service::AuthenticationService; use crate::core::scrape_handler::ScrapeHandler; use crate::core::statistics::event::sender::Sender; @@ -36,6 +37,7 @@ use crate::servers::logging::Latency; #[allow(clippy::needless_pass_by_value)] #[instrument(skip( tracker, + announce_handler, scrape_handler, authentication_service, whitelist_authorization, @@ -44,6 +46,7 @@ use crate::servers::logging::Latency; ))] pub fn router( tracker: Arc, + announce_handler: Arc, scrape_handler: Arc, authentication_service: Arc, whitelist_authorization: Arc, @@ -58,6 +61,7 @@ pub fn router( "/announce", get(announce::handle_without_key).with_state(( tracker.clone(), + announce_handler.clone(), authentication_service.clone(), whitelist_authorization.clone(), stats_event_sender.clone(), @@ -67,6 +71,7 @@ pub fn router( "/announce/{key}", get(announce::handle_with_key).with_state(( tracker.clone(), + announce_handler.clone(), authentication_service.clone(), whitelist_authorization.clone(), stats_event_sender.clone(), diff --git a/src/servers/http/v1/services/announce.rs b/src/servers/http/v1/services/announce.rs index 9e381d8b..2c88ebc6 100644 --- a/src/servers/http/v1/services/announce.rs +++ b/src/servers/http/v1/services/announce.rs @@ -15,9 +15,10 @@ use bittorrent_primitives::info_hash::InfoHash; use torrust_tracker_primitives::core::AnnounceData; use torrust_tracker_primitives::peer; +use crate::core::announce_handler::{AnnounceHandler, PeersWanted}; use crate::core::statistics::event::sender::Sender; use crate::core::statistics::{self}; -use crate::core::{PeersWanted, Tracker}; +use crate::core::Tracker; /// The HTTP tracker `announce` service. /// @@ -30,7 +31,8 @@ use crate::core::{PeersWanted, Tracker}; /// > like the UDP tracker, the number of TCP connections is incremented for /// > each `announce` request. pub async fn invoke( - tracker: Arc, + _tracker: Arc, + announce_handler: Arc, opt_stats_event_sender: Arc>>, info_hash: InfoHash, peer: &mut peer::Peer, @@ -39,7 +41,7 @@ pub async fn invoke( let original_peer_ip = peer.peer_addr.ip(); // The tracker could change the original peer ip - let announce_data = tracker.announce(&info_hash, peer, &original_peer_ip, peers_wanted); + let announce_data = announce_handler.announce(&info_hash, peer, &original_peer_ip, peers_wanted); if let Some(stats_event_sender) = opt_stats_event_sender.as_deref() { match original_peer_ip { @@ -66,11 +68,13 @@ mod tests { use torrust_tracker_test_helpers::configuration; use crate::app_test::initialize_tracker_dependencies; + use crate::core::announce_handler::AnnounceHandler; use crate::core::services::{initialize_tracker, statistics}; use crate::core::statistics::event::sender::Sender; use crate::core::Tracker; - fn public_tracker() -> (Tracker, Arc>>) { + #[allow(clippy::type_complexity)] + fn public_tracker() -> (Arc, Arc, Arc>>) { let config = configuration::ephemeral_public(); let ( @@ -85,9 +89,19 @@ mod tests { let (stats_event_sender, _stats_repository) = statistics::setup::factory(config.core.tracker_usage_statistics); let stats_event_sender = Arc::new(stats_event_sender); - let tracker = initialize_tracker(&config, &in_memory_torrent_repository, &db_torrent_repository); + let tracker = Arc::new(initialize_tracker( + &config, + &in_memory_torrent_repository, + &db_torrent_repository, + )); - (tracker, stats_event_sender) + let announce_handler = Arc::new(AnnounceHandler::new( + &config.core, + &in_memory_torrent_repository, + &db_torrent_repository, + )); + + (tracker, announce_handler, stats_event_sender) } fn sample_info_hash() -> InfoHash { @@ -132,11 +146,12 @@ mod tests { use super::{sample_peer_using_ipv4, sample_peer_using_ipv6}; use crate::app_test::initialize_tracker_dependencies; - use crate::core::{statistics, PeersWanted, Tracker}; + use crate::core::announce_handler::{AnnounceHandler, PeersWanted}; + use crate::core::{statistics, Tracker}; use crate::servers::http::v1::services::announce::invoke; use crate::servers::http::v1::services::announce::tests::{public_tracker, sample_info_hash, sample_peer}; - fn test_tracker_factory() -> Tracker { + fn initialize_tracker_and_announce_handler() -> (Arc, Arc) { let config = configuration::ephemeral(); let ( @@ -149,19 +164,26 @@ mod tests { _torrents_manager, ) = initialize_tracker_dependencies(&config); - Tracker::new(&config.core, &in_memory_torrent_repository, &db_torrent_repository).unwrap() + let tracker = Arc::new(Tracker::new(&config.core, &in_memory_torrent_repository, &db_torrent_repository).unwrap()); + + let announce_handler = Arc::new(AnnounceHandler::new( + &config.core, + &in_memory_torrent_repository, + &db_torrent_repository, + )); + + (tracker, announce_handler) } #[tokio::test] async fn it_should_return_the_announce_data() { - let (tracker, stats_event_sender) = public_tracker(); - - let tracker = Arc::new(tracker); + let (tracker, announce_handler, stats_event_sender) = public_tracker(); let mut peer = sample_peer(); let announce_data = invoke( tracker.clone(), + announce_handler.clone(), stats_event_sender.clone(), sample_info_hash(), &mut peer, @@ -193,20 +215,28 @@ mod tests { let stats_event_sender: Arc>> = Arc::new(Some(Box::new(stats_event_sender_mock))); - let tracker = Arc::new(test_tracker_factory()); + let (tracker, announce_handler) = initialize_tracker_and_announce_handler(); let mut peer = sample_peer_using_ipv4(); - let _announce_data = invoke(tracker, stats_event_sender, sample_info_hash(), &mut peer, &PeersWanted::All).await; + let _announce_data = invoke( + tracker, + announce_handler, + stats_event_sender, + sample_info_hash(), + &mut peer, + &PeersWanted::All, + ) + .await; } - fn tracker_with_an_ipv6_external_ip() -> Tracker { + fn tracker_with_an_ipv6_external_ip() -> (Arc, Arc) { let mut configuration = configuration::ephemeral(); configuration.core.net.external_ip = Some(IpAddr::V6(Ipv6Addr::new( 0x6969, 0x6969, 0x6969, 0x6969, 0x6969, 0x6969, 0x6969, 0x6969, ))); - test_tracker_factory() + initialize_tracker_and_announce_handler() } fn peer_with_the_ipv4_loopback_ip() -> peer::Peer { @@ -233,8 +263,11 @@ mod tests { let mut peer = peer_with_the_ipv4_loopback_ip(); + let (tracker, announce_handler) = tracker_with_an_ipv6_external_ip(); + let _announce_data = invoke( - tracker_with_an_ipv6_external_ip().into(), + tracker, + announce_handler, stats_event_sender, sample_info_hash(), &mut peer, @@ -255,11 +288,19 @@ mod tests { let stats_event_sender: Arc>> = Arc::new(Some(Box::new(stats_event_sender_mock))); - let tracker = Arc::new(test_tracker_factory()); + let (tracker, announce_handler) = initialize_tracker_and_announce_handler(); let mut peer = sample_peer_using_ipv6(); - let _announce_data = invoke(tracker, stats_event_sender, sample_info_hash(), &mut peer, &PeersWanted::All).await; + let _announce_data = invoke( + tracker, + announce_handler, + stats_event_sender, + sample_info_hash(), + &mut peer, + &PeersWanted::All, + ) + .await; } } } diff --git a/src/servers/http/v1/services/scrape.rs b/src/servers/http/v1/services/scrape.rs index e3ee6560..6df267d3 100644 --- a/src/servers/http/v1/services/scrape.rs +++ b/src/servers/http/v1/services/scrape.rs @@ -81,11 +81,12 @@ mod tests { use torrust_tracker_test_helpers::configuration; use crate::app_test::initialize_tracker_dependencies; + use crate::core::announce_handler::AnnounceHandler; use crate::core::scrape_handler::ScrapeHandler; use crate::core::services::initialize_tracker; use crate::core::Tracker; - fn public_tracker_and_scrape_handler() -> (Arc, Arc) { + fn public_tracker_and_announce_and_scrape_handlers() -> (Arc, Arc, Arc) { let config = configuration::ephemeral_public(); let ( @@ -104,9 +105,15 @@ mod tests { &db_torrent_repository, )); + let announce_handler = Arc::new(AnnounceHandler::new( + &config.core, + &in_memory_torrent_repository, + &db_torrent_repository, + )); + let scrape_handler = Arc::new(ScrapeHandler::new(&whitelist_authorization, &in_memory_torrent_repository)); - (tracker, scrape_handler) + (tracker, announce_handler, scrape_handler) } fn sample_info_hashes() -> Vec { @@ -159,10 +166,12 @@ mod tests { use torrust_tracker_primitives::core::ScrapeData; use torrust_tracker_primitives::swarm_metadata::SwarmMetadata; - use crate::core::{statistics, PeersWanted}; + use crate::core::announce_handler::PeersWanted; + use crate::core::statistics; use crate::servers::http::v1::services::scrape::invoke; use crate::servers::http::v1::services::scrape::tests::{ - public_tracker_and_scrape_handler, sample_info_hash, sample_info_hashes, sample_peer, test_tracker_factory, + public_tracker_and_announce_and_scrape_handlers, sample_info_hash, sample_info_hashes, sample_peer, + test_tracker_factory, }; #[tokio::test] @@ -170,7 +179,7 @@ mod tests { let (stats_event_sender, _stats_repository) = crate::core::services::statistics::setup::factory(false); let stats_event_sender = Arc::new(stats_event_sender); - let (tracker, scrape_handler) = public_tracker_and_scrape_handler(); + let (_tracker, announce_handler, scrape_handler) = public_tracker_and_announce_and_scrape_handlers(); let info_hash = sample_info_hash(); let info_hashes = vec![info_hash]; @@ -178,7 +187,7 @@ mod tests { // Announce a new peer to force scrape data to contain not zeroed data let mut peer = sample_peer(); let original_peer_ip = peer.ip(); - tracker.announce(&info_hash, &mut peer, &original_peer_ip, &PeersWanted::All); + announce_handler.announce(&info_hash, &mut peer, &original_peer_ip, &PeersWanted::All); let scrape_data = invoke(&scrape_handler, &stats_event_sender, &info_hashes, &original_peer_ip).await; @@ -241,10 +250,11 @@ mod tests { use mockall::predicate::eq; use torrust_tracker_primitives::core::ScrapeData; - use crate::core::{statistics, PeersWanted}; + use crate::core::announce_handler::PeersWanted; + use crate::core::statistics; use crate::servers::http::v1::services::scrape::fake; use crate::servers::http::v1::services::scrape::tests::{ - public_tracker_and_scrape_handler, sample_info_hash, sample_info_hashes, sample_peer, + public_tracker_and_announce_and_scrape_handlers, sample_info_hash, sample_info_hashes, sample_peer, }; #[tokio::test] @@ -252,7 +262,7 @@ mod tests { let (stats_event_sender, _stats_repository) = crate::core::services::statistics::setup::factory(false); let stats_event_sender = Arc::new(stats_event_sender); - let (tracker, _scrape_handler) = public_tracker_and_scrape_handler(); + let (_tracker, announce_handler, _scrape_handler) = public_tracker_and_announce_and_scrape_handlers(); let info_hash = sample_info_hash(); let info_hashes = vec![info_hash]; @@ -260,7 +270,7 @@ mod tests { // Announce a new peer to force scrape data to contain not zeroed data let mut peer = sample_peer(); let original_peer_ip = peer.ip(); - tracker.announce(&info_hash, &mut peer, &original_peer_ip, &PeersWanted::All); + announce_handler.announce(&info_hash, &mut peer, &original_peer_ip, &PeersWanted::All); let scrape_data = fake(&stats_event_sender, &info_hashes, &original_peer_ip).await; diff --git a/src/servers/udp/handlers.rs b/src/servers/udp/handlers.rs index d6073d2e..03a0248d 100644 --- a/src/servers/udp/handlers.rs +++ b/src/servers/udp/handlers.rs @@ -20,9 +20,10 @@ use zerocopy::network_endian::I32; use super::connection_cookie::{check, make}; use super::server::banning::BanService; use super::RawRequest; +use crate::core::announce_handler::{AnnounceHandler, PeersWanted}; use crate::core::scrape_handler::ScrapeHandler; use crate::core::statistics::event::sender::Sender; -use crate::core::{statistics, whitelist, PeersWanted, Tracker}; +use crate::core::{statistics, whitelist, Tracker}; use crate::servers::udp::error::Error; use crate::servers::udp::{peer_builder, UDP_TRACKER_LOG_TARGET}; use crate::shared::bit_torrent::common::MAX_SCRAPE_TORRENTS; @@ -56,10 +57,11 @@ impl CookieTimeValues { /// /// It will return an `Error` response if the request is invalid. #[allow(clippy::too_many_arguments)] -#[instrument(fields(request_id), skip(udp_request, tracker, scrape_handler, whitelist_authorization, opt_stats_event_sender, cookie_time_values, ban_service), ret(level = Level::TRACE))] +#[instrument(fields(request_id), skip(udp_request, tracker, announce_handler, scrape_handler, whitelist_authorization, opt_stats_event_sender, cookie_time_values, ban_service), ret(level = Level::TRACE))] pub(crate) async fn handle_packet( udp_request: RawRequest, tracker: &Tracker, + announce_handler: &Arc, scrape_handler: &Arc, whitelist_authorization: &Arc, opt_stats_event_sender: &Arc>>, @@ -80,6 +82,7 @@ pub(crate) async fn handle_packet( request, udp_request.from, tracker, + announce_handler, scrape_handler, whitelist_authorization, opt_stats_event_sender, @@ -137,10 +140,12 @@ pub(crate) async fn handle_packet( /// # Errors /// /// If a error happens in the `handle_request` function, it will just return the `ServerError`. +#[allow(clippy::too_many_arguments)] #[instrument(skip( request, remote_addr, tracker, + announce_handler, scrape_handler, whitelist_authorization, opt_stats_event_sender, @@ -150,6 +155,7 @@ pub async fn handle_request( request: Request, remote_addr: SocketAddr, tracker: &Tracker, + announce_handler: &Arc, scrape_handler: &Arc, whitelist_authorization: &Arc, opt_stats_event_sender: &Arc>>, @@ -170,6 +176,7 @@ pub async fn handle_request( remote_addr, &announce_request, tracker, + announce_handler, whitelist_authorization, opt_stats_event_sender, cookie_time_values.valid_range, @@ -233,11 +240,12 @@ pub async fn handle_connect( /// # Errors /// /// If a error happens in the `handle_announce` function, it will just return the `ServerError`. -#[instrument(fields(transaction_id, connection_id, info_hash), skip(tracker, whitelist_authorization, opt_stats_event_sender), ret(level = Level::TRACE))] +#[instrument(fields(transaction_id, connection_id, info_hash), skip(tracker, announce_handler, whitelist_authorization, opt_stats_event_sender), ret(level = Level::TRACE))] pub async fn handle_announce( remote_addr: SocketAddr, request: &AnnounceRequest, tracker: &Tracker, + announce_handler: &Arc, whitelist_authorization: &Arc, opt_stats_event_sender: &Arc>>, cookie_valid_range: Range, @@ -271,7 +279,7 @@ pub async fn handle_announce( let mut peer = peer_builder::from_request(request, &remote_client_ip); let peers_wanted: PeersWanted = i32::from(request.peers_wanted.0).into(); - let response = tracker.announce(&info_hash, &mut peer, &remote_client_ip, &peers_wanted); + let response = announce_handler.announce(&info_hash, &mut peer, &remote_client_ip, &peers_wanted); if let Some(stats_event_sender) = opt_stats_event_sender.as_deref() { match remote_client_ip { @@ -490,6 +498,7 @@ mod tests { use super::gen_remote_fingerprint; use crate::app_test::initialize_tracker_dependencies; + use crate::core::announce_handler::AnnounceHandler; use crate::core::scrape_handler::ScrapeHandler; use crate::core::services::{initialize_tracker, initialize_whitelist_manager, statistics}; use crate::core::statistics::event::sender::Sender; @@ -501,6 +510,7 @@ mod tests { type TrackerAndDeps = ( Arc, + Arc, Arc, Arc, Arc>>, @@ -546,10 +556,17 @@ mod tests { &db_torrent_repository, )); + let announce_handler = Arc::new(AnnounceHandler::new( + &config.core, + &in_memory_torrent_repository, + &db_torrent_repository, + )); + let scrape_handler = Arc::new(ScrapeHandler::new(&whitelist_authorization, &in_memory_torrent_repository)); ( tracker, + announce_handler, scrape_handler, in_memory_torrent_repository, stats_event_sender, @@ -653,7 +670,12 @@ mod tests { } } - fn test_tracker_factory() -> (Arc, Arc, Arc) { + fn test_tracker_factory() -> ( + Arc, + Arc, + Arc, + Arc, + ) { let config = tracker_configuration(); let ( @@ -668,9 +690,15 @@ mod tests { let tracker = Arc::new(Tracker::new(&config.core, &in_memory_torrent_repository, &db_torrent_repository).unwrap()); + let announce_handler = Arc::new(AnnounceHandler::new( + &config.core, + &in_memory_torrent_repository, + &db_torrent_repository, + )); + let scrape_handler = Arc::new(ScrapeHandler::new(&whitelist_authorization, &in_memory_torrent_repository)); - (tracker, scrape_handler, whitelist_authorization) + (tracker, announce_handler, scrape_handler, whitelist_authorization) } mod connect_request { @@ -883,6 +911,7 @@ mod tests { }; use mockall::predicate::eq; + use crate::core::announce_handler::AnnounceHandler; use crate::core::torrent::repository::in_memory::InMemoryTorrentRepository; use crate::core::{self, statistics, whitelist}; use crate::servers::udp::connection_cookie::make; @@ -897,6 +926,7 @@ mod tests { async fn an_announced_peer_should_be_added_to_the_tracker() { let ( tracker, + announce_handler, _scrape_handler, in_memory_torrent_repository, stats_event_sender, @@ -924,6 +954,7 @@ mod tests { remote_addr, &request, &tracker, + &announce_handler, &whitelist_authorization, &stats_event_sender, sample_cookie_valid_range(), @@ -945,6 +976,7 @@ mod tests { async fn the_announced_peer_should_not_be_included_in_the_response() { let ( tracker, + announce_handler, _scrape_handler, _in_memory_torrent_repository, stats_event_sender, @@ -963,6 +995,7 @@ mod tests { remote_addr, &request, &tracker, + &announce_handler, &whitelist_authorization, &stats_event_sender, sample_cookie_valid_range(), @@ -993,6 +1026,7 @@ mod tests { let ( tracker, + announce_handler, _scrape_handler, in_memory_torrent_repository, stats_event_sender, @@ -1023,6 +1057,7 @@ mod tests { remote_addr, &request, &tracker, + &announce_handler, &whitelist_authorization, &stats_event_sender, sample_cookie_valid_range(), @@ -1053,6 +1088,7 @@ mod tests { async fn announce_a_new_peer_using_ipv4( tracker: Arc, + announce_handler: Arc, whitelist_authorization: Arc, ) -> Response { let (stats_event_sender, _stats_repository) = crate::core::services::statistics::setup::factory(false); @@ -1067,6 +1103,7 @@ mod tests { remote_addr, &request, &tracker, + &announce_handler, &whitelist_authorization, &stats_event_sender, sample_cookie_valid_range(), @@ -1079,6 +1116,7 @@ mod tests { async fn when_the_announce_request_comes_from_a_client_using_ipv4_the_response_should_not_include_peers_using_ipv6() { let ( tracker, + announce_handler, _scrape_handler, in_memory_torrent_repository, _stats_event_sender, @@ -1089,7 +1127,8 @@ mod tests { add_a_torrent_peer_using_ipv6(&in_memory_torrent_repository); - let response = announce_a_new_peer_using_ipv4(tracker.clone(), whitelist_authorization).await; + let response = + announce_a_new_peer_using_ipv4(tracker.clone(), announce_handler.clone(), whitelist_authorization).await; // The response should not contain the peer using IPV6 let peers: Option>> = match response { @@ -1111,12 +1150,13 @@ mod tests { let stats_event_sender: Arc>> = Arc::new(Some(Box::new(stats_event_sender_mock))); - let (tracker, _scrape_handler, whitelist_authorization) = test_tracker_factory(); + let (tracker, announce_handler, _scrape_handler, whitelist_authorization) = test_tracker_factory(); handle_announce( sample_ipv4_socket_address(), &AnnounceRequestBuilder::default().into(), &tracker, + &announce_handler, &whitelist_authorization, &stats_event_sender, sample_cookie_valid_range(), @@ -1142,6 +1182,7 @@ mod tests { async fn the_peer_ip_should_be_changed_to_the_external_ip_in_the_tracker_configuration_if_defined() { let ( tracker, + announce_handler, _scrape_handler, in_memory_torrent_repository, stats_event_sender, @@ -1169,6 +1210,7 @@ mod tests { remote_addr, &request, &tracker, + &announce_handler, &whitelist_authorization, &stats_event_sender, sample_cookie_valid_range(), @@ -1202,6 +1244,7 @@ mod tests { }; use mockall::predicate::eq; + use crate::core::announce_handler::AnnounceHandler; use crate::core::torrent::repository::in_memory::InMemoryTorrentRepository; use crate::core::{self, statistics, whitelist}; use crate::servers::udp::connection_cookie::make; @@ -1216,6 +1259,7 @@ mod tests { async fn an_announced_peer_should_be_added_to_the_tracker() { let ( tracker, + announce_handler, _scrape_handler, in_memory_torrent_repository, stats_event_sender, @@ -1244,6 +1288,7 @@ mod tests { remote_addr, &request, &tracker, + &announce_handler, &whitelist_authorization, &stats_event_sender, sample_cookie_valid_range(), @@ -1265,6 +1310,7 @@ mod tests { async fn the_announced_peer_should_not_be_included_in_the_response() { let ( tracker, + announce_handler, _scrape_handler, _in_memory_torrent_repository, stats_event_sender, @@ -1286,6 +1332,7 @@ mod tests { remote_addr, &request, &tracker, + &announce_handler, &whitelist_authorization, &stats_event_sender, sample_cookie_valid_range(), @@ -1316,6 +1363,7 @@ mod tests { let ( tracker, + announce_handler, _scrape_handler, in_memory_torrent_repository, stats_event_sender, @@ -1346,6 +1394,7 @@ mod tests { remote_addr, &request, &tracker, + &announce_handler, &whitelist_authorization, &stats_event_sender, sample_cookie_valid_range(), @@ -1376,6 +1425,7 @@ mod tests { async fn announce_a_new_peer_using_ipv6( tracker: Arc, + announce_handler: Arc, whitelist_authorization: Arc, ) -> Response { let (stats_event_sender, _stats_repository) = crate::core::services::statistics::setup::factory(false); @@ -1393,6 +1443,7 @@ mod tests { remote_addr, &request, &tracker, + &announce_handler, &whitelist_authorization, &stats_event_sender, sample_cookie_valid_range(), @@ -1405,6 +1456,7 @@ mod tests { async fn when_the_announce_request_comes_from_a_client_using_ipv6_the_response_should_not_include_peers_using_ipv4() { let ( tracker, + announce_handler, _scrape_handler, in_memory_torrent_repository, _stats_event_sender, @@ -1415,7 +1467,8 @@ mod tests { add_a_torrent_peer_using_ipv4(&in_memory_torrent_repository); - let response = announce_a_new_peer_using_ipv6(tracker.clone(), whitelist_authorization).await; + let response = + announce_a_new_peer_using_ipv6(tracker.clone(), announce_handler.clone(), whitelist_authorization).await; // The response should not contain the peer using IPV4 let peers: Option>> = match response { @@ -1437,7 +1490,7 @@ mod tests { let stats_event_sender: Arc>> = Arc::new(Some(Box::new(stats_event_sender_mock))); - let (tracker, _scrape_handler, whitelist_authorization) = test_tracker_factory(); + let (tracker, announce_handler, _scrape_handler, whitelist_authorization) = test_tracker_factory(); let remote_addr = sample_ipv6_remote_addr(); @@ -1449,6 +1502,7 @@ mod tests { remote_addr, &announce_request, &tracker, + &announce_handler, &whitelist_authorization, &stats_event_sender, sample_cookie_valid_range(), @@ -1466,6 +1520,7 @@ mod tests { use mockall::predicate::eq; use crate::app_test::initialize_tracker_dependencies; + use crate::core::announce_handler::AnnounceHandler; use crate::core::{self, statistics}; use crate::servers::udp::connection_cookie::make; use crate::servers::udp::handlers::handle_announce; @@ -1501,6 +1556,12 @@ mod tests { core::Tracker::new(&config.core, &in_memory_torrent_repository, &db_torrent_repository).unwrap(), ); + let announce_handler = Arc::new(AnnounceHandler::new( + &config.core, + &in_memory_torrent_repository, + &db_torrent_repository, + )); + let loopback_ipv4 = Ipv4Addr::new(127, 0, 0, 1); let loopback_ipv6 = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1); @@ -1525,6 +1586,7 @@ mod tests { remote_addr, &request, &tracker, + &announce_handler, &whitelist_authorization, &stats_event_sender, sample_cookie_valid_range(), @@ -1580,6 +1642,7 @@ mod tests { async fn should_return_no_stats_when_the_tracker_does_not_have_any_torrent() { let ( _tracker, + _announce_handler, scrape_handler, _in_memory_torrent_repository, stats_event_sender, @@ -1688,6 +1751,7 @@ mod tests { async fn should_return_torrent_statistics_when_the_tracker_has_the_requested_torrent() { let ( _tracker, + _announce_handler, scrape_handler, in_memory_torrent_repository, _stats_event_sender, @@ -1723,6 +1787,7 @@ mod tests { async fn should_return_the_torrent_statistics_when_the_requested_torrent_is_whitelisted() { let ( _tracker, + _announce_handler, scrape_handler, in_memory_torrent_repository, stats_event_sender, @@ -1766,6 +1831,7 @@ mod tests { async fn should_return_zeroed_statistics_when_the_requested_torrent_is_not_whitelisted() { let ( _tracker, + _announce_handler, scrape_handler, in_memory_torrent_repository, stats_event_sender, @@ -1837,7 +1903,7 @@ mod tests { let remote_addr = sample_ipv4_remote_addr(); - let (_tracker, scrape_handler, _whitelist_authorization) = test_tracker_factory(); + let (_tracker, _announce_handler, scrape_handler, _whitelist_authorization) = test_tracker_factory(); handle_scrape( remote_addr, @@ -1877,7 +1943,7 @@ mod tests { let remote_addr = sample_ipv6_remote_addr(); - let (_tracker, scrape_handler, _whitelist_authorization) = test_tracker_factory(); + let (_tracker, _announce_handler, scrape_handler, _whitelist_authorization) = test_tracker_factory(); handle_scrape( remote_addr, diff --git a/src/servers/udp/server/launcher.rs b/src/servers/udp/server/launcher.rs index d6bc230e..f1d0e485 100644 --- a/src/servers/udp/server/launcher.rs +++ b/src/servers/udp/server/launcher.rs @@ -13,6 +13,7 @@ use tracing::instrument; use super::banning::BanService; use super::request_buffer::ActiveRequests; use crate::bootstrap::jobs::Started; +use crate::core::announce_handler::AnnounceHandler; use crate::core::scrape_handler::ScrapeHandler; use crate::core::statistics::event::sender::Sender; use crate::core::{statistics, whitelist, Tracker}; @@ -44,6 +45,7 @@ impl Launcher { #[allow(clippy::too_many_arguments)] #[instrument(skip( tracker, + announce_handler, scrape_handler, whitelist_authorization, opt_stats_event_sender, @@ -54,6 +56,7 @@ impl Launcher { ))] pub async fn run_with_graceful_shutdown( tracker: Arc, + announce_handler: Arc, scrape_handler: Arc, whitelist_authorization: Arc, opt_stats_event_sender: Arc>>, @@ -98,6 +101,7 @@ impl Launcher { let () = Self::run_udp_server_main( receiver, tracker.clone(), + announce_handler.clone(), scrape_handler.clone(), whitelist_authorization.clone(), opt_stats_event_sender.clone(), @@ -141,9 +145,11 @@ impl Launcher { ServiceHealthCheckJob::new(binding, info, job) } + #[allow(clippy::too_many_arguments)] #[instrument(skip( receiver, tracker, + announce_handler, scrape_handler, whitelist_authorization, opt_stats_event_sender, @@ -152,6 +158,7 @@ impl Launcher { async fn run_udp_server_main( mut receiver: Receiver, tracker: Arc, + announce_handler: Arc, scrape_handler: Arc, whitelist_authorization: Arc, opt_stats_event_sender: Arc>>, @@ -224,6 +231,7 @@ impl Launcher { let processor = Processor::new( receiver.socket.clone(), tracker.clone(), + announce_handler.clone(), scrape_handler.clone(), whitelist_authorization.clone(), opt_stats_event_sender.clone(), diff --git a/src/servers/udp/server/mod.rs b/src/servers/udp/server/mod.rs index 66826575..53ba588d 100644 --- a/src/servers/udp/server/mod.rs +++ b/src/servers/udp/server/mod.rs @@ -83,6 +83,7 @@ mod tests { let started = stopped .start( app_container.tracker, + app_container.announce_handler, app_container.scrape_handler, app_container.whitelist_authorization, app_container.stats_event_sender, @@ -117,6 +118,7 @@ mod tests { let started = stopped .start( app_container.tracker, + app_container.announce_handler, app_container.scrape_handler, app_container.whitelist_authorization, app_container.stats_event_sender, diff --git a/src/servers/udp/server/processor.rs b/src/servers/udp/server/processor.rs index 889a2a91..4cecbc36 100644 --- a/src/servers/udp/server/processor.rs +++ b/src/servers/udp/server/processor.rs @@ -10,6 +10,7 @@ use tracing::{instrument, Level}; use super::banning::BanService; use super::bound_socket::BoundSocket; +use crate::core::announce_handler::AnnounceHandler; use crate::core::scrape_handler::ScrapeHandler; use crate::core::statistics::event::sender::Sender; use crate::core::statistics::event::UdpResponseKind; @@ -20,6 +21,7 @@ use crate::servers::udp::{handlers, RawRequest}; pub struct Processor { socket: Arc, tracker: Arc, + announce_handler: Arc, scrape_handler: Arc, whitelist_authorization: Arc, opt_stats_event_sender: Arc>>, @@ -30,6 +32,7 @@ impl Processor { pub fn new( socket: Arc, tracker: Arc, + announce_handler: Arc, scrape_handler: Arc, whitelist_authorization: Arc, opt_stats_event_sender: Arc>>, @@ -38,6 +41,7 @@ impl Processor { Self { socket, tracker, + announce_handler, scrape_handler, whitelist_authorization, opt_stats_event_sender, @@ -54,6 +58,7 @@ impl Processor { let response = handlers::handle_packet( request, &self.tracker, + &self.announce_handler, &self.scrape_handler, &self.whitelist_authorization, &self.opt_stats_event_sender, diff --git a/src/servers/udp/server/spawner.rs b/src/servers/udp/server/spawner.rs index 82fd808c..ea12b1c0 100644 --- a/src/servers/udp/server/spawner.rs +++ b/src/servers/udp/server/spawner.rs @@ -11,6 +11,7 @@ use tokio::task::JoinHandle; use super::banning::BanService; use super::launcher::Launcher; use crate::bootstrap::jobs::Started; +use crate::core::announce_handler::AnnounceHandler; use crate::core::scrape_handler::ScrapeHandler; use crate::core::statistics::event::sender::Sender; use crate::core::{whitelist, Tracker}; @@ -32,6 +33,7 @@ impl Spawner { pub fn spawn_launcher( &self, tracker: Arc, + announce_handler: Arc, scrape_handler: Arc, whitelist_authorization: Arc, opt_stats_event_sender: Arc>>, @@ -45,6 +47,7 @@ impl Spawner { tokio::spawn(async move { Launcher::run_with_graceful_shutdown( tracker, + announce_handler, scrape_handler, whitelist_authorization, opt_stats_event_sender, diff --git a/src/servers/udp/server/states.rs b/src/servers/udp/server/states.rs index d2c91b03..bab04fdc 100644 --- a/src/servers/udp/server/states.rs +++ b/src/servers/udp/server/states.rs @@ -13,6 +13,7 @@ use super::banning::BanService; use super::spawner::Spawner; use super::{Server, UdpError}; use crate::bootstrap::jobs::Started; +use crate::core::announce_handler::AnnounceHandler; use crate::core::scrape_handler::ScrapeHandler; use crate::core::statistics::event::sender::Sender; use crate::core::{whitelist, Tracker}; @@ -66,10 +67,11 @@ impl Server { /// /// It panics if unable to receive the bound socket address from service. #[allow(clippy::too_many_arguments)] - #[instrument(skip(self, tracker, scrape_handler, whitelist_authorization, opt_stats_event_sender, ban_service, form), err, ret(Display, level = Level::INFO))] + #[instrument(skip(self, tracker, announce_handler, scrape_handler, whitelist_authorization, opt_stats_event_sender, ban_service, form), err, ret(Display, level = Level::INFO))] pub async fn start( self, tracker: Arc, + announce_handler: Arc, scrape_handler: Arc, whitelist_authorization: Arc, opt_stats_event_sender: Arc>>, @@ -85,6 +87,7 @@ impl Server { // May need to wrap in a task to about a tokio bug. let task = self.state.spawner.spawn_launcher( tracker, + announce_handler, scrape_handler, whitelist_authorization, opt_stats_event_sender, diff --git a/tests/servers/http/environment.rs b/tests/servers/http/environment.rs index beaf2d38..78051cbb 100644 --- a/tests/servers/http/environment.rs +++ b/tests/servers/http/environment.rs @@ -5,6 +5,7 @@ use futures::executor::block_on; use torrust_tracker_configuration::{Configuration, HttpTracker}; use torrust_tracker_lib::bootstrap::app::{initialize_app_container, initialize_global_services}; use torrust_tracker_lib::bootstrap::jobs::make_rust_tls; +use torrust_tracker_lib::core::announce_handler::AnnounceHandler; use torrust_tracker_lib::core::authentication::handler::KeysHandler; use torrust_tracker_lib::core::authentication::service::AuthenticationService; use torrust_tracker_lib::core::databases::Database; @@ -22,6 +23,7 @@ pub struct Environment { pub config: Arc, pub database: Arc>, pub tracker: Arc, + pub announce_handler: Arc, pub scrape_handler: Arc, pub in_memory_torrent_repository: Arc, pub keys_handler: Arc, @@ -65,6 +67,7 @@ impl Environment { config, database: app_container.database.clone(), tracker: app_container.tracker.clone(), + announce_handler: app_container.announce_handler.clone(), scrape_handler: app_container.scrape_handler.clone(), in_memory_torrent_repository: app_container.in_memory_torrent_repository.clone(), keys_handler: app_container.keys_handler.clone(), @@ -84,6 +87,7 @@ impl Environment { config: self.config, database: self.database.clone(), tracker: self.tracker.clone(), + announce_handler: self.announce_handler.clone(), scrape_handler: self.scrape_handler.clone(), in_memory_torrent_repository: self.in_memory_torrent_repository.clone(), keys_handler: self.keys_handler.clone(), @@ -97,6 +101,7 @@ impl Environment { .server .start( self.tracker, + self.announce_handler, self.scrape_handler, self.authentication_service, self.whitelist_authorization, @@ -119,6 +124,7 @@ impl Environment { config: self.config, database: self.database, tracker: self.tracker, + announce_handler: self.announce_handler, scrape_handler: self.scrape_handler, in_memory_torrent_repository: self.in_memory_torrent_repository, keys_handler: self.keys_handler, diff --git a/tests/servers/udp/environment.rs b/tests/servers/udp/environment.rs index 09714146..fafb7ef7 100644 --- a/tests/servers/udp/environment.rs +++ b/tests/servers/udp/environment.rs @@ -5,6 +5,7 @@ use bittorrent_primitives::info_hash::InfoHash; use tokio::sync::RwLock; use torrust_tracker_configuration::{Configuration, UdpTracker, DEFAULT_TIMEOUT}; use torrust_tracker_lib::bootstrap::app::{initialize_app_container, initialize_global_services}; +use torrust_tracker_lib::core::announce_handler::AnnounceHandler; use torrust_tracker_lib::core::databases::Database; use torrust_tracker_lib::core::scrape_handler::ScrapeHandler; use torrust_tracker_lib::core::statistics::event::sender::Sender; @@ -26,6 +27,7 @@ where pub database: Arc>, pub tracker: Arc, pub in_memory_torrent_repository: Arc, + pub announce_handler: Arc, pub scrape_handler: Arc, pub whitelist_authorization: Arc, pub stats_event_sender: Arc>>, @@ -66,6 +68,7 @@ impl Environment { database: app_container.database.clone(), tracker: app_container.tracker.clone(), in_memory_torrent_repository: app_container.in_memory_torrent_repository.clone(), + announce_handler: app_container.announce_handler.clone(), scrape_handler: app_container.scrape_handler.clone(), whitelist_authorization: app_container.whitelist_authorization.clone(), stats_event_sender: app_container.stats_event_sender.clone(), @@ -84,6 +87,7 @@ impl Environment { database: self.database.clone(), tracker: self.tracker.clone(), in_memory_torrent_repository: self.in_memory_torrent_repository.clone(), + announce_handler: self.announce_handler.clone(), scrape_handler: self.scrape_handler.clone(), whitelist_authorization: self.whitelist_authorization.clone(), stats_event_sender: self.stats_event_sender.clone(), @@ -94,6 +98,7 @@ impl Environment { .server .start( self.tracker, + self.announce_handler, self.scrape_handler, self.whitelist_authorization, self.stats_event_sender, @@ -125,6 +130,7 @@ impl Environment { database: self.database, tracker: self.tracker, in_memory_torrent_repository: self.in_memory_torrent_repository, + announce_handler: self.announce_handler, scrape_handler: self.scrape_handler, whitelist_authorization: self.whitelist_authorization, stats_event_sender: self.stats_event_sender, From 209b52c0511a9b69e47a1a45f60310f5ae040723 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Mon, 27 Jan 2025 13:53:48 +0000 Subject: [PATCH 5/6] refactor: [#1207] inline methods --- src/app.rs | 6 +++--- src/core/mod.rs | 20 +------------------- 2 files changed, 4 insertions(+), 22 deletions(-) diff --git a/src/app.rs b/src/app.rs index 00414bc1..aafae5eb 100644 --- a/src/app.rs +++ b/src/app.rs @@ -50,7 +50,7 @@ pub async fn start(config: &Configuration, app_container: &AppContainer) -> Vec< let registar = Registar::default(); // Load peer keys - if app_container.tracker.is_private() { + if config.core.private { app_container .keys_handler .load_keys_from_database() @@ -59,7 +59,7 @@ pub async fn start(config: &Configuration, app_container: &AppContainer) -> Vec< } // Load whitelisted torrents - if app_container.tracker.is_listed() { + if config.core.listed { app_container .whitelist_manager .load_whitelist_from_database() @@ -70,7 +70,7 @@ pub async fn start(config: &Configuration, app_container: &AppContainer) -> Vec< // Start the UDP blocks if let Some(udp_trackers) = &config.udp_trackers { for udp_tracker_config in udp_trackers { - if app_container.tracker.is_private() { + if config.core.private { tracing::warn!( "Could not start UDP tracker on: {} while in private mode. UDP is not safe for private trackers!", udp_tracker_config.bind_address diff --git a/src/core/mod.rs b/src/core/mod.rs index 2151ec1e..ae728dc1 100644 --- a/src/core/mod.rs +++ b/src/core/mod.rs @@ -496,28 +496,10 @@ impl Tracker { }) } - /// Returns `true` is the tracker is in public mode. - #[must_use] - pub fn is_public(&self) -> bool { - !self.config.private - } - - /// Returns `true` is the tracker is in private mode. - #[must_use] - pub fn is_private(&self) -> bool { - self.config.private - } - - /// Returns `true` is the tracker is in whitelisted mode. - #[must_use] - pub fn is_listed(&self) -> bool { - self.config.listed - } - /// Returns `true` if the tracker requires authentication. #[must_use] pub fn requires_authentication(&self) -> bool { - self.is_private() + self.config.private } /// Returns `true` is the tracker is in whitelisted mode. From 2f74cafda7ee3cbc5c1030da448aca7664e8972c Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Mon, 27 Jan 2025 14:08:01 +0000 Subject: [PATCH 6/6] chore: fix linting errors --- packages/configuration/src/lib.rs | 2 +- packages/configuration/src/v2_0_0/mod.rs | 12 ++++++------ packages/http-protocol/src/v1/requests/announce.rs | 4 ++-- packages/http-protocol/src/v1/requests/mod.rs | 3 --- packages/http-protocol/src/v1/responses/announce.rs | 2 +- packages/http-protocol/src/v1/responses/error.rs | 4 ++-- packages/http-protocol/src/v1/responses/mod.rs | 3 --- packages/http-protocol/src/v1/responses/scrape.rs | 2 +- src/core/mod.rs | 6 +++--- src/servers/http/v1/services/announce.rs | 5 ++--- 10 files changed, 18 insertions(+), 25 deletions(-) diff --git a/packages/configuration/src/lib.rs b/packages/configuration/src/lib.rs index 1ab3479f..7e384297 100644 --- a/packages/configuration/src/lib.rs +++ b/packages/configuration/src/lib.rs @@ -3,7 +3,7 @@ //! This module contains the configuration data structures for the //! Torrust Tracker, which is a `BitTorrent` tracker server. //! -//! The current version for configuration is [`v2`]. +//! The current version for configuration is [`v2_0_0`]. pub mod v2_0_0; pub mod validator; diff --git a/packages/configuration/src/v2_0_0/mod.rs b/packages/configuration/src/v2_0_0/mod.rs index 5067210b..fd742d8d 100644 --- a/packages/configuration/src/v2_0_0/mod.rs +++ b/packages/configuration/src/v2_0_0/mod.rs @@ -39,11 +39,11 @@ //! Please refer to the documentation of each structure for more information //! about each section. //! -//! - [`Core configuration`](crate::v2::Configuration) -//! - [`HTTP API configuration`](crate::v2::tracker_api::HttpApi) -//! - [`HTTP Tracker configuration`](crate::v2::http_tracker::HttpTracker) -//! - [`UDP Tracker configuration`](crate::v2::udp_tracker::UdpTracker) -//! - [`Health Check API configuration`](crate::v2::health_check_api::HealthCheckApi) +//! - [`Core configuration`](crate::v2_0_0::Configuration) +//! - [`HTTP API configuration`](crate::v2_0_0::tracker_api::HttpApi) +//! - [`HTTP Tracker configuration`](crate::v2_0_0::http_tracker::HttpTracker) +//! - [`UDP Tracker configuration`](crate::v2_0_0::udp_tracker::UdpTracker) +//! - [`Health Check API configuration`](crate::v2_0_0::health_check_api::HealthCheckApi) //! //! ## Port binding //! @@ -78,7 +78,7 @@ //! //! Alternatively, you could setup a reverse proxy like Nginx or Apache to //! handle the SSL/TLS part and forward the requests to the tracker. If you do -//! that, you should set [`on_reverse_proxy`](crate::v2::network::Network::on_reverse_proxy) +//! that, you should set [`on_reverse_proxy`](crate::v2_0_0::network::Network::on_reverse_proxy) //! to `true` in the configuration file. It's out of scope for this //! documentation to explain in detail how to setup a reverse proxy, but the //! configuration file should be something like this: diff --git a/packages/http-protocol/src/v1/requests/announce.rs b/packages/http-protocol/src/v1/requests/announce.rs index ea76771d..9bde7ec1 100644 --- a/packages/http-protocol/src/v1/requests/announce.rs +++ b/packages/http-protocol/src/v1/requests/announce.rs @@ -185,8 +185,8 @@ impl fmt::Display for Event { /// Depending on the value of this param, the tracker will return a different /// response: /// -/// - [`Normal`](crate::servers::http::v1::responses::announce::Normal), i.e. a `non-compact` response. -/// - [`Compact`](crate::servers::http::v1::responses::announce::Compact) response. +/// - [`Normal`](crate::v1::responses::announce::Normal), i.e. a `non-compact` response. +/// - [`Compact`](crate::v1::responses::announce::Compact) response. /// /// Refer to [BEP 23. Tracker Returns Compact Peer Lists](https://www.bittorrent.org/beps/bep_0023.html) #[derive(PartialEq, Debug)] diff --git a/packages/http-protocol/src/v1/requests/mod.rs b/packages/http-protocol/src/v1/requests/mod.rs index ee34ca72..d19bd78d 100644 --- a/packages/http-protocol/src/v1/requests/mod.rs +++ b/packages/http-protocol/src/v1/requests/mod.rs @@ -1,6 +1,3 @@ //! HTTP requests for the HTTP tracker. -//! -//! Refer to the generic [HTTP server documentation](crate::servers::http) for -//! more information about the HTTP tracker. pub mod announce; pub mod scrape; diff --git a/packages/http-protocol/src/v1/responses/announce.rs b/packages/http-protocol/src/v1/responses/announce.rs index 3854c9f3..df187fdd 100644 --- a/packages/http-protocol/src/v1/responses/announce.rs +++ b/packages/http-protocol/src/v1/responses/announce.rs @@ -1,4 +1,4 @@ -//! `Announce` response for the HTTP tracker [`announce`](bittorrent_http_protocol::v1::requests::announce::Announce) request. +//! `Announce` response for the HTTP tracker [`announce`](crate::v1::requests::announce::Announce) request. //! //! Data structures and logic to build the `announce` response. use std::io::Write; diff --git a/packages/http-protocol/src/v1/responses/error.rs b/packages/http-protocol/src/v1/responses/error.rs index 7516cd39..f939ce29 100644 --- a/packages/http-protocol/src/v1/responses/error.rs +++ b/packages/http-protocol/src/v1/responses/error.rs @@ -1,4 +1,4 @@ -//! `Error` response for the [`HTTP tracker`](crate::servers::http). +//! `Error` response for the HTTP tracker. //! //! Data structures and logic to build the error responses. //! @@ -15,7 +15,7 @@ use serde::Serialize; use crate::v1::services::peer_ip_resolver::PeerIpResolutionError; -/// `Error` response for the [`HTTP tracker`](crate::servers::http). +/// `Error` response for the HTTP tracker. #[derive(Serialize, Debug, PartialEq)] pub struct Error { /// Human readable string which explains why the request failed. diff --git a/packages/http-protocol/src/v1/responses/mod.rs b/packages/http-protocol/src/v1/responses/mod.rs index 495b1eb8..e704d890 100644 --- a/packages/http-protocol/src/v1/responses/mod.rs +++ b/packages/http-protocol/src/v1/responses/mod.rs @@ -1,7 +1,4 @@ //! HTTP responses for the HTTP tracker. -//! -//! Refer to the generic [HTTP server documentation](crate::servers::http) for -//! more information about the HTTP tracker. pub mod announce; pub mod error; pub mod scrape; diff --git a/packages/http-protocol/src/v1/responses/scrape.rs b/packages/http-protocol/src/v1/responses/scrape.rs index ee4c4155..6b4dcc79 100644 --- a/packages/http-protocol/src/v1/responses/scrape.rs +++ b/packages/http-protocol/src/v1/responses/scrape.rs @@ -1,4 +1,4 @@ -//! `Scrape` response for the HTTP tracker [`scrape`](bittorrent_http_protocol::v1::requests::scrape::Scrape) request. +//! `Scrape` response for the HTTP tracker [`scrape`](crate::v1::requests::scrape::Scrape) request. //! //! Data structures and logic to build the `scrape` response. use std::borrow::Cow; diff --git a/src/core/mod.rs b/src/core/mod.rs index ae728dc1..d30c47c6 100644 --- a/src/core/mod.rs +++ b/src/core/mod.rs @@ -52,7 +52,7 @@ //! The tracker responds to the peer with the list of other peers in the swarm so that //! the peer can contact them to start downloading pieces of the file from them. //! -//! Once you have instantiated the `Tracker` you can `announce` a new [`peer::Peer`] with: +//! Once you have instantiated the `AnnounceHandler` you can `announce` a new [`peer::Peer`](torrust_tracker_primitives::peer::Peer) with: //! //! ```rust,no_run //! use std::net::SocketAddr; @@ -81,7 +81,7 @@ //! ``` //! //! ```text -//! let announce_data = tracker.announce(&info_hash, &mut peer, &peer_ip).await; +//! let announce_data = announce_handler.announce(&info_hash, &mut peer, &peer_ip).await; //! ``` //! //! The `Tracker` returns the list of peers for the torrent with the infohash `3b245504cf5f11bbdbe1201cea6a6bf45aee1bc0`, @@ -306,7 +306,7 @@ //! `c1277613db1d28709b034a017ab2cae4be07ae10` is the torrent infohash and `completed` contains the number of peers //! that have a full version of the torrent data, also known as seeders. //! -//! Refer to [`peer`] module for more information about peers. +//! Refer to [`peer`](torrust_tracker_primitives::peer) for more information about peers. //! //! # Configuration //! diff --git a/src/servers/http/v1/services/announce.rs b/src/servers/http/v1/services/announce.rs index 2c88ebc6..1923037b 100644 --- a/src/servers/http/v1/services/announce.rs +++ b/src/servers/http/v1/services/announce.rs @@ -2,9 +2,8 @@ //! //! The service is responsible for handling the `announce` requests. //! -//! It delegates the `announce` logic to the [`Tracker`](crate::core::Tracker::announce) -//! and it returns the [`AnnounceData`] returned -//! by the [`Tracker`]. +//! It delegates the `announce` logic to the [`AnnounceHandler`] and it returns +//! the [`AnnounceData`]. //! //! It also sends an [`statistics::event::Event`] //! because events are specific for the HTTP tracker.