diff --git a/.gitignore b/.gitignore index d9087bcff..8bfa717b7 100644 --- a/.gitignore +++ b/.gitignore @@ -15,4 +15,5 @@ callgrind.out codecov.json lcov.info -perf.data* \ No newline at end of file +perf.data* +rustc-ice-*.txt diff --git a/cSpell.json b/cSpell.json index e067df932..dcdcc9cf6 100644 --- a/cSpell.json +++ b/cSpell.json @@ -136,6 +136,7 @@ "routable", "rstest", "rusqlite", + "rustc", "RUSTDOCFLAGS", "RUSTFLAGS", "rustfmt", diff --git a/packages/axum-http-tracker-server/src/server.rs b/packages/axum-http-tracker-server/src/server.rs index 4cf5afc13..ea8003a4f 100644 --- a/packages/axum-http-tracker-server/src/server.rs +++ b/packages/axum-http-tracker-server/src/server.rs @@ -239,6 +239,8 @@ mod tests { use std::sync::Arc; use bittorrent_http_tracker_core::container::HttpTrackerCoreContainer; + use bittorrent_http_tracker_core::services::announce::AnnounceService; + use bittorrent_http_tracker_core::services::scrape::ScrapeService; use bittorrent_tracker_core::announce_handler::AnnounceHandler; use bittorrent_tracker_core::authentication::key::repository::in_memory::InMemoryKeyRepository; use bittorrent_tracker_core::authentication::service; @@ -293,6 +295,21 @@ mod tests { let scrape_handler = Arc::new(ScrapeHandler::new(&whitelist_authorization, &in_memory_torrent_repository)); + let announce_service = Arc::new(AnnounceService::new( + core_config.clone(), + announce_handler.clone(), + authentication_service.clone(), + whitelist_authorization.clone(), + http_stats_event_sender.clone(), + )); + + let scrape_service = Arc::new(ScrapeService::new( + core_config.clone(), + scrape_handler.clone(), + authentication_service.clone(), + http_stats_event_sender.clone(), + )); + HttpTrackerCoreContainer { core_config, announce_handler, @@ -303,6 +320,8 @@ mod tests { http_tracker_config, http_stats_event_sender, http_stats_repository, + announce_service, + scrape_service, } } diff --git a/packages/axum-http-tracker-server/src/v1/handlers/announce.rs b/packages/axum-http-tracker-server/src/v1/handlers/announce.rs index 0221f8dad..6c2e4b713 100644 --- a/packages/axum-http-tracker-server/src/v1/handlers/announce.rs +++ b/packages/axum-http-tracker-server/src/v1/handlers/announce.rs @@ -6,16 +6,12 @@ use std::sync::Arc; use axum::extract::State; use axum::response::{IntoResponse, Response}; -use bittorrent_http_tracker_core::services::announce::HttpAnnounceError; +use bittorrent_http_tracker_core::services::announce::{AnnounceService, HttpAnnounceError}; use bittorrent_http_tracker_protocol::v1::requests::announce::{Announce, Compact}; use bittorrent_http_tracker_protocol::v1::responses::{self}; use bittorrent_http_tracker_protocol::v1::services::peer_ip_resolver::ClientIpSources; -use bittorrent_tracker_core::announce_handler::AnnounceHandler; -use bittorrent_tracker_core::authentication::service::AuthenticationService; use bittorrent_tracker_core::authentication::Key; -use bittorrent_tracker_core::whitelist; use hyper::StatusCode; -use torrust_tracker_configuration::Core; use torrust_tracker_primitives::core::AnnounceData; use crate::v1::extractors::announce_request::ExtractRequest; @@ -25,91 +21,41 @@ use crate::v1::extractors::client_ip_sources::Extract as ExtractClientIpSources; /// It handles the `announce` request when the HTTP tracker does not require /// authentication (no PATH `key` parameter required). #[allow(clippy::unused_async)] -#[allow(clippy::type_complexity)] pub async fn handle_without_key( - State(state): State<( - Arc, - Arc, - Arc, - Arc, - Arc>>, - )>, + State(state): State>, ExtractRequest(announce_request): ExtractRequest, ExtractClientIpSources(client_ip_sources): ExtractClientIpSources, ) -> Response { tracing::debug!("http announce request: {:#?}", announce_request); - handle( - &state.0, - &state.1, - &state.2, - &state.3, - &state.4, - &announce_request, - &client_ip_sources, - None, - ) - .await + handle(&state, &announce_request, &client_ip_sources, None).await } /// It handles the `announce` request when the HTTP tracker requires /// authentication (PATH `key` parameter required). #[allow(clippy::unused_async)] -#[allow(clippy::type_complexity)] pub async fn handle_with_key( - State(state): State<( - Arc, - Arc, - Arc, - Arc, - Arc>>, - )>, + State(state): State>, ExtractRequest(announce_request): ExtractRequest, ExtractClientIpSources(client_ip_sources): ExtractClientIpSources, ExtractKey(key): ExtractKey, ) -> Response { tracing::debug!("http announce request: {:#?}", announce_request); - handle( - &state.0, - &state.1, - &state.2, - &state.3, - &state.4, - &announce_request, - &client_ip_sources, - Some(key), - ) - .await + handle(&state, &announce_request, &client_ip_sources, Some(key)).await } /// It handles the `announce` request. /// /// Internal implementation that handles both the `authenticated` and /// `unauthenticated` modes. -#[allow(clippy::too_many_arguments)] async fn handle( - config: &Arc, - announce_handler: &Arc, - authentication_service: &Arc, - whitelist_authorization: &Arc, - opt_http_stats_event_sender: &Arc>>, + announce_service: &Arc, announce_request: &Announce, client_ip_sources: &ClientIpSources, maybe_key: Option, ) -> Response { - let announce_data = match handle_announce( - config, - announce_handler, - authentication_service, - whitelist_authorization, - opt_http_stats_event_sender, - announce_request, - client_ip_sources, - maybe_key, - ) - .await - { + let announce_data = match handle_announce(announce_service, announce_request, client_ip_sources, maybe_key).await { Ok(announce_data) => announce_data, Err(error) => { let error_response = responses::error::Error { @@ -121,28 +67,15 @@ async fn handle( build_response(announce_request, announce_data) } -#[allow(clippy::too_many_arguments)] async fn handle_announce( - core_config: &Arc, - announce_handler: &Arc, - authentication_service: &Arc, - whitelist_authorization: &Arc, - opt_http_stats_event_sender: &Arc>>, + announce_service: &Arc, announce_request: &Announce, client_ip_sources: &ClientIpSources, maybe_key: Option, ) -> Result { - bittorrent_http_tracker_core::services::announce::handle_announce( - &core_config.clone(), - &announce_handler.clone(), - &authentication_service.clone(), - &whitelist_authorization.clone(), - &opt_http_stats_event_sender.clone(), - announce_request, - client_ip_sources, - maybe_key, - ) - .await + announce_service + .handle_announce(announce_request, client_ip_sources, maybe_key) + .await } fn build_response(announce_request: &Announce, announce_data: AnnounceData) -> Response { @@ -163,6 +96,7 @@ mod tests { use std::sync::Arc; use aquatic_udp_protocol::PeerId; + use bittorrent_http_tracker_core::services::announce::AnnounceService; use bittorrent_http_tracker_protocol::v1::requests::announce::Announce; use bittorrent_http_tracker_protocol::v1::responses; use bittorrent_http_tracker_protocol::v1::services::peer_ip_resolver::ClientIpSources; @@ -174,39 +108,32 @@ mod tests { use bittorrent_tracker_core::torrent::repository::persisted::DatabasePersistentTorrentRepository; use bittorrent_tracker_core::whitelist::authorization::WhitelistAuthorization; use bittorrent_tracker_core::whitelist::repository::in_memory::InMemoryWhitelist; - use torrust_tracker_configuration::{Configuration, Core}; + use torrust_tracker_configuration::Configuration; use torrust_tracker_test_helpers::configuration; use crate::tests::helpers::sample_info_hash; - struct CoreTrackerServices { - pub core_config: Arc, - pub announce_handler: Arc, - pub whitelist_authorization: Arc, - pub authentication_service: Arc, - } - struct CoreHttpTrackerServices { - pub http_stats_event_sender: Arc>>, + pub announce_service: Arc, } - fn initialize_private_tracker() -> (CoreTrackerServices, CoreHttpTrackerServices) { + fn initialize_private_tracker() -> CoreHttpTrackerServices { initialize_core_tracker_services(&configuration::ephemeral_private()) } - fn initialize_listed_tracker() -> (CoreTrackerServices, CoreHttpTrackerServices) { + fn initialize_listed_tracker() -> CoreHttpTrackerServices { initialize_core_tracker_services(&configuration::ephemeral_listed()) } - fn initialize_tracker_on_reverse_proxy() -> (CoreTrackerServices, CoreHttpTrackerServices) { + fn initialize_tracker_on_reverse_proxy() -> CoreHttpTrackerServices { initialize_core_tracker_services(&configuration::ephemeral_with_reverse_proxy()) } - fn initialize_tracker_not_on_reverse_proxy() -> (CoreTrackerServices, CoreHttpTrackerServices) { + fn initialize_tracker_not_on_reverse_proxy() -> CoreHttpTrackerServices { initialize_core_tracker_services(&configuration::ephemeral_without_reverse_proxy()) } - fn initialize_core_tracker_services(config: &Configuration) -> (CoreTrackerServices, CoreHttpTrackerServices) { + fn initialize_core_tracker_services(config: &Configuration) -> CoreHttpTrackerServices { let core_config = Arc::new(config.core.clone()); let database = initialize_database(&config.core); let in_memory_whitelist = Arc::new(InMemoryWhitelist::default()); @@ -228,15 +155,15 @@ mod tests { let http_stats_event_sender = Arc::new(http_stats_event_sender); let _http_stats_repository = Arc::new(http_stats_repository); - ( - CoreTrackerServices { - core_config, - announce_handler, - whitelist_authorization, - authentication_service, - }, - CoreHttpTrackerServices { http_stats_event_sender }, - ) + let announce_service = Arc::new(AnnounceService::new( + core_config.clone(), + announce_handler.clone(), + authentication_service.clone(), + whitelist_authorization.clone(), + http_stats_event_sender.clone(), + )); + + CoreHttpTrackerServices { announce_service } } fn sample_announce_request() -> Announce { @@ -280,16 +207,12 @@ mod tests { #[tokio::test] async fn it_should_fail_when_the_authentication_key_is_missing() { - let (core_tracker_services, http_core_tracker_services) = initialize_private_tracker(); + let http_core_tracker_services = initialize_private_tracker(); let maybe_key = None; let response = handle_announce( - &core_tracker_services.core_config, - &core_tracker_services.announce_handler, - &core_tracker_services.authentication_service, - &core_tracker_services.whitelist_authorization, - &http_core_tracker_services.http_stats_event_sender, + &http_core_tracker_services.announce_service, &sample_announce_request(), &sample_client_ip_sources(), maybe_key, @@ -309,18 +232,14 @@ mod tests { #[tokio::test] async fn it_should_fail_when_the_authentication_key_is_invalid() { - let (core_tracker_services, http_core_tracker_services) = initialize_private_tracker(); + let http_core_tracker_services = initialize_private_tracker(); let unregistered_key = authentication::Key::from_str("YZSl4lMZupRuOpSRC3krIKR5BPB14nrJ").unwrap(); let maybe_key = Some(unregistered_key); let response = handle_announce( - &core_tracker_services.core_config, - &core_tracker_services.announce_handler, - &core_tracker_services.authentication_service, - &core_tracker_services.whitelist_authorization, - &http_core_tracker_services.http_stats_event_sender, + &http_core_tracker_services.announce_service, &sample_announce_request(), &sample_client_ip_sources(), maybe_key, @@ -349,16 +268,12 @@ mod tests { #[tokio::test] async fn it_should_fail_when_the_announced_torrent_is_not_whitelisted() { - let (core_tracker_services, http_core_tracker_services) = initialize_listed_tracker(); + let http_core_tracker_services = initialize_listed_tracker(); let announce_request = sample_announce_request(); let response = handle_announce( - &core_tracker_services.core_config, - &core_tracker_services.announce_handler, - &core_tracker_services.authentication_service, - &core_tracker_services.whitelist_authorization, - &http_core_tracker_services.http_stats_event_sender, + &http_core_tracker_services.announce_service, &announce_request, &sample_client_ip_sources(), None, @@ -391,7 +306,7 @@ mod tests { #[tokio::test] async fn it_should_fail_when_the_right_most_x_forwarded_for_header_ip_is_not_available() { - let (core_tracker_services, http_core_tracker_services) = initialize_tracker_on_reverse_proxy(); + let http_core_tracker_services = initialize_tracker_on_reverse_proxy(); let client_ip_sources = ClientIpSources { right_most_x_forwarded_for: None, @@ -399,11 +314,7 @@ mod tests { }; let response = handle_announce( - &core_tracker_services.core_config, - &core_tracker_services.announce_handler, - &core_tracker_services.authentication_service, - &core_tracker_services.whitelist_authorization, - &http_core_tracker_services.http_stats_event_sender, + &http_core_tracker_services.announce_service, &sample_announce_request(), &client_ip_sources, None, @@ -433,7 +344,7 @@ mod tests { #[tokio::test] async fn it_should_fail_when_the_client_ip_from_the_connection_info_is_not_available() { - let (core_tracker_services, http_core_tracker_services) = initialize_tracker_not_on_reverse_proxy(); + let http_core_tracker_services = initialize_tracker_not_on_reverse_proxy(); let client_ip_sources = ClientIpSources { right_most_x_forwarded_for: None, @@ -441,11 +352,7 @@ mod tests { }; let response = handle_announce( - &core_tracker_services.core_config, - &core_tracker_services.announce_handler, - &core_tracker_services.authentication_service, - &core_tracker_services.whitelist_authorization, - &http_core_tracker_services.http_stats_event_sender, + &http_core_tracker_services.announce_service, &sample_announce_request(), &client_ip_sources, None, diff --git a/packages/axum-http-tracker-server/src/v1/handlers/scrape.rs b/packages/axum-http-tracker-server/src/v1/handlers/scrape.rs index 00046a618..ae3a35bd3 100644 --- a/packages/axum-http-tracker-server/src/v1/handlers/scrape.rs +++ b/packages/axum-http-tracker-server/src/v1/handlers/scrape.rs @@ -6,15 +6,12 @@ use std::sync::Arc; use axum::extract::State; use axum::response::{IntoResponse, Response}; -use bittorrent_http_tracker_core::services::scrape::HttpScrapeError; +use bittorrent_http_tracker_core::services::scrape::ScrapeService; use bittorrent_http_tracker_protocol::v1::requests::scrape::Scrape; use bittorrent_http_tracker_protocol::v1::responses; use bittorrent_http_tracker_protocol::v1::services::peer_ip_resolver::ClientIpSources; -use bittorrent_tracker_core::authentication::service::AuthenticationService; use bittorrent_tracker_core::authentication::Key; -use bittorrent_tracker_core::scrape_handler::ScrapeHandler; use hyper::StatusCode; -use torrust_tracker_configuration::Core; use torrust_tracker_primitives::core::ScrapeData; use crate::v1::extractors::authentication_key::Extract as ExtractKey; @@ -24,29 +21,14 @@ use crate::v1::extractors::scrape_request::ExtractRequest; /// It handles the `scrape` request when the HTTP tracker is configured /// to run in `public` mode. #[allow(clippy::unused_async)] -#[allow(clippy::type_complexity)] pub async fn handle_without_key( - State(state): State<( - Arc, - Arc, - Arc, - Arc>>, - )>, + State(state): State>, ExtractRequest(scrape_request): ExtractRequest, ExtractClientIpSources(client_ip_sources): ExtractClientIpSources, ) -> Response { tracing::debug!("http scrape request: {:#?}", &scrape_request); - handle( - &state.0, - &state.1, - &state.2, - &state.3, - &scrape_request, - &client_ip_sources, - None, - ) - .await + handle(&state, &scrape_request, &client_ip_sources, None).await } /// It handles the `scrape` request when the HTTP tracker is configured @@ -54,52 +36,26 @@ pub async fn handle_without_key( /// /// In this case, the authentication `key` parameter is required. #[allow(clippy::unused_async)] -#[allow(clippy::type_complexity)] pub async fn handle_with_key( - State(state): State<( - Arc, - Arc, - Arc, - Arc>>, - )>, + State(state): State>, ExtractRequest(scrape_request): ExtractRequest, ExtractClientIpSources(client_ip_sources): ExtractClientIpSources, ExtractKey(key): ExtractKey, ) -> Response { tracing::debug!("http scrape request: {:#?}", &scrape_request); - handle( - &state.0, - &state.1, - &state.2, - &state.3, - &scrape_request, - &client_ip_sources, - Some(key), - ) - .await + handle(&state, &scrape_request, &client_ip_sources, Some(key)).await } -#[allow(clippy::too_many_arguments)] async fn handle( - core_config: &Arc, - scrape_handler: &Arc, - authentication_service: &Arc, - http_stats_event_sender: &Arc>>, + scrape_service: &Arc, scrape_request: &Scrape, client_ip_sources: &ClientIpSources, maybe_key: Option, ) -> Response { - let scrape_data = match handle_scrape( - core_config, - scrape_handler, - authentication_service, - http_stats_event_sender, - scrape_request, - client_ip_sources, - maybe_key, - ) - .await + let scrape_data = match scrape_service + .handle_scrape(scrape_request, client_ip_sources, maybe_key) + .await { Ok(scrape_data) => scrape_data, Err(error) => { @@ -113,28 +69,6 @@ async fn handle( build_response(scrape_data) } -#[allow(clippy::too_many_arguments)] -async fn handle_scrape( - core_config: &Arc, - scrape_handler: &Arc, - authentication_service: &Arc, - opt_http_stats_event_sender: &Arc>>, - scrape_request: &Scrape, - client_ip_sources: &ClientIpSources, - maybe_key: Option, -) -> Result { - bittorrent_http_tracker_core::services::scrape::handle_scrape( - core_config, - scrape_handler, - authentication_service, - opt_http_stats_event_sender, - scrape_request, - client_ip_sources, - maybe_key, - ) - .await -} - fn build_response(scrape_data: ScrapeData) -> Response { let response = responses::scrape::Bencoded::from(scrape_data); @@ -233,11 +167,11 @@ mod tests { mod with_tracker_in_private_mode { use std::str::FromStr; + use bittorrent_http_tracker_core::services::scrape::ScrapeService; use bittorrent_tracker_core::authentication; use torrust_tracker_primitives::core::ScrapeData; use super::{initialize_private_tracker, sample_client_ip_sources, sample_scrape_request}; - use crate::v1::handlers::scrape::handle_scrape; #[tokio::test] async fn it_should_return_zeroed_swarm_metadata_when_the_authentication_key_is_missing() { @@ -246,17 +180,17 @@ mod tests { let scrape_request = sample_scrape_request(); let maybe_key = None; - let scrape_data = handle_scrape( - &core_tracker_services.core_config, - &core_tracker_services.scrape_handler, - &core_tracker_services.authentication_service, - &core_http_tracker_services.http_stats_event_sender, - &scrape_request, - &sample_client_ip_sources(), - maybe_key, - ) - .await - .unwrap(); + let scrape_service = ScrapeService::new( + core_tracker_services.core_config.clone(), + core_tracker_services.scrape_handler.clone(), + core_tracker_services.authentication_service.clone(), + core_http_tracker_services.http_stats_event_sender.clone(), + ); + + let scrape_data = scrape_service + .handle_scrape(&scrape_request, &sample_client_ip_sources(), maybe_key) + .await + .unwrap(); let expected_scrape_data = ScrapeData::zeroed(&scrape_request.info_hashes); @@ -271,17 +205,17 @@ mod tests { let unregistered_key = authentication::Key::from_str("YZSl4lMZupRuOpSRC3krIKR5BPB14nrJ").unwrap(); let maybe_key = Some(unregistered_key); - let scrape_data = handle_scrape( - &core_tracker_services.core_config, - &core_tracker_services.scrape_handler, - &core_tracker_services.authentication_service, - &core_http_tracker_services.http_stats_event_sender, - &scrape_request, - &sample_client_ip_sources(), - maybe_key, - ) - .await - .unwrap(); + let scrape_service = ScrapeService::new( + core_tracker_services.core_config.clone(), + core_tracker_services.scrape_handler.clone(), + core_tracker_services.authentication_service.clone(), + core_http_tracker_services.http_stats_event_sender.clone(), + ); + + let scrape_data = scrape_service + .handle_scrape(&scrape_request, &sample_client_ip_sources(), maybe_key) + .await + .unwrap(); let expected_scrape_data = ScrapeData::zeroed(&scrape_request.info_hashes); @@ -291,10 +225,10 @@ mod tests { mod with_tracker_in_listed_mode { + use bittorrent_http_tracker_core::services::scrape::ScrapeService; use torrust_tracker_primitives::core::ScrapeData; use super::{initialize_listed_tracker, sample_client_ip_sources, sample_scrape_request}; - use crate::v1::handlers::scrape::handle_scrape; #[tokio::test] async fn it_should_return_zeroed_swarm_metadata_when_the_torrent_is_not_whitelisted() { @@ -302,17 +236,17 @@ mod tests { let scrape_request = sample_scrape_request(); - let scrape_data = handle_scrape( - &core_tracker_services.core_config, - &core_tracker_services.scrape_handler, - &core_tracker_services.authentication_service, - &core_http_tracker_services.http_stats_event_sender, - &scrape_request, - &sample_client_ip_sources(), - None, - ) - .await - .unwrap(); + let scrape_service = ScrapeService::new( + core_tracker_services.core_config.clone(), + core_tracker_services.scrape_handler.clone(), + core_tracker_services.authentication_service.clone(), + core_http_tracker_services.http_stats_event_sender.clone(), + ); + + let scrape_data = scrape_service + .handle_scrape(&scrape_request, &sample_client_ip_sources(), None) + .await + .unwrap(); let expected_scrape_data = ScrapeData::zeroed(&scrape_request.info_hashes); @@ -322,11 +256,11 @@ mod tests { mod with_tracker_on_reverse_proxy { + use bittorrent_http_tracker_core::services::scrape::ScrapeService; use bittorrent_http_tracker_protocol::v1::responses; use bittorrent_http_tracker_protocol::v1::services::peer_ip_resolver::ClientIpSources; use super::{initialize_tracker_on_reverse_proxy, sample_scrape_request}; - use crate::v1::handlers::scrape::handle_scrape; use crate::v1::handlers::scrape::tests::assert_error_response; #[tokio::test] @@ -338,17 +272,17 @@ mod tests { connection_info_ip: None, }; - let response = handle_scrape( - &core_tracker_services.core_config, - &core_tracker_services.scrape_handler, - &core_tracker_services.authentication_service, - &core_http_tracker_services.http_stats_event_sender, - &sample_scrape_request(), - &client_ip_sources, - None, - ) - .await - .unwrap_err(); + let scrape_service = ScrapeService::new( + core_tracker_services.core_config.clone(), + core_tracker_services.scrape_handler.clone(), + core_tracker_services.authentication_service.clone(), + core_http_tracker_services.http_stats_event_sender.clone(), + ); + + let response = scrape_service + .handle_scrape(&sample_scrape_request(), &client_ip_sources, None) + .await + .unwrap_err(); let error_response = responses::error::Error { failure_reason: response.to_string(), @@ -363,11 +297,11 @@ mod tests { mod with_tracker_not_on_reverse_proxy { + use bittorrent_http_tracker_core::services::scrape::ScrapeService; use bittorrent_http_tracker_protocol::v1::responses; use bittorrent_http_tracker_protocol::v1::services::peer_ip_resolver::ClientIpSources; use super::{initialize_tracker_not_on_reverse_proxy, sample_scrape_request}; - use crate::v1::handlers::scrape::handle_scrape; use crate::v1::handlers::scrape::tests::assert_error_response; #[tokio::test] @@ -379,17 +313,17 @@ mod tests { connection_info_ip: None, }; - let response = handle_scrape( - &core_tracker_services.core_config, - &core_tracker_services.scrape_handler, - &core_tracker_services.authentication_service, - &core_http_tracker_services.http_stats_event_sender, - &sample_scrape_request(), - &client_ip_sources, - None, - ) - .await - .unwrap_err(); + let scrape_service = ScrapeService::new( + core_tracker_services.core_config.clone(), + core_tracker_services.scrape_handler.clone(), + core_tracker_services.authentication_service.clone(), + core_http_tracker_services.http_stats_event_sender.clone(), + ); + + let response = scrape_service + .handle_scrape(&sample_scrape_request(), &client_ip_sources, None) + .await + .unwrap_err(); let error_response = responses::error::Error { failure_reason: response.to_string(), diff --git a/packages/axum-http-tracker-server/src/v1/routes.rs b/packages/axum-http-tracker-server/src/v1/routes.rs index 7a96f6014..5f666e9d4 100644 --- a/packages/axum-http-tracker-server/src/v1/routes.rs +++ b/packages/axum-http-tracker-server/src/v1/routes.rs @@ -38,42 +38,20 @@ pub fn router(http_tracker_container: Arc, server_sock // Announce request .route( "/announce", - get(announce::handle_without_key).with_state(( - http_tracker_container.core_config.clone(), - http_tracker_container.announce_handler.clone(), - http_tracker_container.authentication_service.clone(), - http_tracker_container.whitelist_authorization.clone(), - http_tracker_container.http_stats_event_sender.clone(), - )), + get(announce::handle_without_key).with_state(http_tracker_container.announce_service.clone()), ) .route( "/announce/{key}", - get(announce::handle_with_key).with_state(( - http_tracker_container.core_config.clone(), - http_tracker_container.announce_handler.clone(), - http_tracker_container.authentication_service.clone(), - http_tracker_container.whitelist_authorization.clone(), - http_tracker_container.http_stats_event_sender.clone(), - )), + get(announce::handle_with_key).with_state(http_tracker_container.announce_service.clone()), ) // Scrape request .route( "/scrape", - get(scrape::handle_without_key).with_state(( - http_tracker_container.core_config.clone(), - http_tracker_container.scrape_handler.clone(), - http_tracker_container.authentication_service.clone(), - http_tracker_container.http_stats_event_sender.clone(), - )), + get(scrape::handle_without_key).with_state(http_tracker_container.scrape_service.clone()), ) .route( "/scrape/{key}", - get(scrape::handle_with_key).with_state(( - http_tracker_container.core_config.clone(), - http_tracker_container.scrape_handler.clone(), - http_tracker_container.authentication_service.clone(), - http_tracker_container.http_stats_event_sender.clone(), - )), + get(scrape::handle_with_key).with_state(http_tracker_container.scrape_service.clone()), ) // Add extension to get the client IP from the connection info .layer(SecureClientIpSource::ConnectInfo.into_extension()) diff --git a/packages/http-tracker-core/src/container.rs b/packages/http-tracker-core/src/container.rs index 0fc313a38..448dce246 100644 --- a/packages/http-tracker-core/src/container.rs +++ b/packages/http-tracker-core/src/container.rs @@ -7,6 +7,8 @@ use bittorrent_tracker_core::scrape_handler::ScrapeHandler; use bittorrent_tracker_core::whitelist; use torrust_tracker_configuration::{Core, HttpTracker}; +use crate::services::announce::AnnounceService; +use crate::services::scrape::ScrapeService; use crate::statistics; pub struct HttpTrackerCoreContainer { @@ -20,6 +22,8 @@ pub struct HttpTrackerCoreContainer { pub http_tracker_config: Arc, pub http_stats_event_sender: Arc>>, pub http_stats_repository: Arc, + pub announce_service: Arc, + pub scrape_service: Arc, } impl HttpTrackerCoreContainer { @@ -39,6 +43,21 @@ impl HttpTrackerCoreContainer { let http_stats_event_sender = Arc::new(http_stats_event_sender); let http_stats_repository = Arc::new(http_stats_repository); + let announce_service = Arc::new(AnnounceService::new( + tracker_core_container.core_config.clone(), + tracker_core_container.announce_handler.clone(), + tracker_core_container.authentication_service.clone(), + tracker_core_container.whitelist_authorization.clone(), + http_stats_event_sender.clone(), + )); + + let scrape_service = Arc::new(ScrapeService::new( + tracker_core_container.core_config.clone(), + tracker_core_container.scrape_handler.clone(), + tracker_core_container.authentication_service.clone(), + http_stats_event_sender.clone(), + )); + Arc::new(Self { core_config: tracker_core_container.core_config.clone(), announce_handler: tracker_core_container.announce_handler.clone(), @@ -49,6 +68,8 @@ impl HttpTrackerCoreContainer { http_tracker_config: http_tracker_config.clone(), http_stats_event_sender: http_stats_event_sender.clone(), http_stats_repository: http_stats_repository.clone(), + announce_service: announce_service.clone(), + scrape_service: scrape_service.clone(), }) } } diff --git a/packages/http-tracker-core/src/services/announce.rs b/packages/http-tracker-core/src/services/announce.rs index 2f530c654..5890d35c1 100644 --- a/packages/http-tracker-core/src/services/announce.rs +++ b/packages/http-tracker-core/src/services/announce.rs @@ -83,81 +83,105 @@ impl From for HttpAnnounceError { /// > **NOTICE**: as the HTTP tracker does not requires a connection request /// > like the UDP tracker, the number of TCP connections is incremented for /// > each `announce` request. -/// -/// # Errors -/// -/// This function will return an error if: -/// -/// - The tracker is running in `listed` mode and the torrent is not whitelisted. -/// - There is an error when resolving the client IP address. -#[allow(clippy::too_many_arguments)] -pub async fn handle_announce( - core_config: &Arc, - announce_handler: &Arc, - authentication_service: &Arc, - whitelist_authorization: &Arc, - opt_http_stats_event_sender: &Arc>>, - announce_request: &Announce, - client_ip_sources: &ClientIpSources, - maybe_key: Option, -) -> Result { - // Authentication - if core_config.private { - match maybe_key { - Some(key) => match authentication_service.authenticate(&key).await { - Ok(()) => (), - Err(error) => return Err(error.into()), - }, - None => { - return Err(authentication::key::Error::MissingAuthKey { - location: Location::caller(), +pub struct AnnounceService { + core_config: Arc, + announce_handler: Arc, + authentication_service: Arc, + whitelist_authorization: Arc, + opt_http_stats_event_sender: Arc>>, +} + +impl AnnounceService { + #[must_use] + pub fn new( + core_config: Arc, + announce_handler: Arc, + authentication_service: Arc, + whitelist_authorization: Arc, + opt_http_stats_event_sender: Arc>>, + ) -> Self { + Self { + core_config, + announce_handler, + authentication_service, + whitelist_authorization, + opt_http_stats_event_sender, + } + } + + /// Handles an announce request. + /// + /// # Errors + /// + /// This function will return an error if: + /// + /// - The tracker is running in `listed` mode and the torrent is not whitelisted. + /// - There is an error when resolving the client IP address. + pub async fn handle_announce( + &self, + announce_request: &Announce, + client_ip_sources: &ClientIpSources, + maybe_key: Option, + ) -> Result { + // Authentication + if self.core_config.private { + match maybe_key { + Some(key) => match self.authentication_service.authenticate(&key).await { + Ok(()) => (), + Err(error) => return Err(error.into()), + }, + None => { + return Err(authentication::key::Error::MissingAuthKey { + location: Location::caller(), + } + .into()) } - .into()) } } - } - // Authorization - match whitelist_authorization.authorize(&announce_request.info_hash).await { - Ok(()) => (), - Err(error) => return Err(error.into()), - } + // Authorization + match self.whitelist_authorization.authorize(&announce_request.info_hash).await { + Ok(()) => (), + Err(error) => return Err(error.into()), + } - let peer_ip = match peer_ip_resolver::invoke(core_config.net.on_reverse_proxy, client_ip_sources) { - Ok(peer_ip) => peer_ip, - Err(error) => return Err(error.into()), - }; + let peer_ip = match peer_ip_resolver::invoke(self.core_config.net.on_reverse_proxy, client_ip_sources) { + Ok(peer_ip) => peer_ip, + Err(error) => return Err(error.into()), + }; - let mut peer = peer_from_request(announce_request, &peer_ip); + let mut peer = peer_from_request(announce_request, &peer_ip); - let peers_wanted = match announce_request.numwant { - Some(numwant) => PeersWanted::only(numwant), - None => PeersWanted::AsManyAsPossible, - }; + let peers_wanted = match announce_request.numwant { + Some(numwant) => PeersWanted::only(numwant), + None => PeersWanted::AsManyAsPossible, + }; - let original_peer_ip = peer.peer_addr.ip(); + let original_peer_ip = peer.peer_addr.ip(); - // The tracker could change the original peer ip - let announce_data = announce_handler - .announce(&announce_request.info_hash, &mut peer, &original_peer_ip, &peers_wanted) - .await?; + // The tracker could change the original peer ip + let announce_data = self + .announce_handler + .announce(&announce_request.info_hash, &mut peer, &original_peer_ip, &peers_wanted) + .await?; - if let Some(http_stats_event_sender) = opt_http_stats_event_sender.as_deref() { - match original_peer_ip { - IpAddr::V4(_) => { - http_stats_event_sender - .send_event(statistics::event::Event::Tcp4Announce) - .await; - } - IpAddr::V6(_) => { - http_stats_event_sender - .send_event(statistics::event::Event::Tcp6Announce) - .await; + if let Some(http_stats_event_sender) = self.opt_http_stats_event_sender.as_deref() { + match original_peer_ip { + IpAddr::V4(_) => { + http_stats_event_sender + .send_event(statistics::event::Event::Tcp4Announce) + .await; + } + IpAddr::V6(_) => { + http_stats_event_sender + .send_event(statistics::event::Event::Tcp6Announce) + .await; + } } } - } - Ok(announce_data) + Ok(announce_data) + } } #[cfg(test)] @@ -302,11 +326,11 @@ mod tests { use torrust_tracker_test_helpers::configuration; use super::{sample_peer_using_ipv4, sample_peer_using_ipv6}; - use crate::services::announce::handle_announce; use crate::services::announce::tests::{ initialize_core_tracker_services, initialize_core_tracker_services_with_config, sample_announce_request_for_peer, sample_peer, MockHttpStatsEventSender, }; + use crate::services::announce::AnnounceService; use crate::statistics; #[tokio::test] @@ -317,18 +341,18 @@ mod tests { let (announce_request, client_ip_sources) = sample_announce_request_for_peer(peer); - let announce_data = handle_announce( - &core_tracker_services.core_config, - &core_tracker_services.announce_handler, - &core_tracker_services.authentication_service, - &core_tracker_services.whitelist_authorization, - &core_http_tracker_services.http_stats_event_sender, - &announce_request, - &client_ip_sources, - None, - ) - .await - .unwrap(); + let announce_service = AnnounceService::new( + core_tracker_services.core_config.clone(), + core_tracker_services.announce_handler.clone(), + core_tracker_services.authentication_service.clone(), + core_tracker_services.whitelist_authorization.clone(), + core_http_tracker_services.http_stats_event_sender.clone(), + ); + + let announce_data = announce_service + .handle_announce(&announce_request, &client_ip_sources, None) + .await + .unwrap(); let expected_announce_data = AnnounceData { peers: vec![], @@ -361,18 +385,18 @@ mod tests { let (announce_request, client_ip_sources) = sample_announce_request_for_peer(peer); - let _announce_data = handle_announce( - &core_tracker_services.core_config, - &core_tracker_services.announce_handler, - &core_tracker_services.authentication_service, - &core_tracker_services.whitelist_authorization, - &core_http_tracker_services.http_stats_event_sender, - &announce_request, - &client_ip_sources, - None, - ) - .await - .unwrap(); + let announce_service = AnnounceService::new( + core_tracker_services.core_config.clone(), + core_tracker_services.announce_handler.clone(), + core_tracker_services.authentication_service.clone(), + core_tracker_services.whitelist_authorization.clone(), + core_http_tracker_services.http_stats_event_sender.clone(), + ); + + let _announce_data = announce_service + .handle_announce(&announce_request, &client_ip_sources, None) + .await + .unwrap(); } fn tracker_with_an_ipv6_external_ip() -> Configuration { @@ -413,18 +437,18 @@ mod tests { let (announce_request, client_ip_sources) = sample_announce_request_for_peer(peer); - let _announce_data = handle_announce( - &core_tracker_services.core_config, - &core_tracker_services.announce_handler, - &core_tracker_services.authentication_service, - &core_tracker_services.whitelist_authorization, - &core_http_tracker_services.http_stats_event_sender, - &announce_request, - &client_ip_sources, - None, - ) - .await - .unwrap(); + let announce_service = AnnounceService::new( + core_tracker_services.core_config.clone(), + core_tracker_services.announce_handler.clone(), + core_tracker_services.authentication_service.clone(), + core_tracker_services.whitelist_authorization.clone(), + core_http_tracker_services.http_stats_event_sender.clone(), + ); + + let _announce_data = announce_service + .handle_announce(&announce_request, &client_ip_sources, None) + .await + .unwrap(); } #[tokio::test] @@ -446,18 +470,18 @@ mod tests { let (announce_request, client_ip_sources) = sample_announce_request_for_peer(peer); - let _announce_data = handle_announce( - &core_tracker_services.core_config, - &core_tracker_services.announce_handler, - &core_tracker_services.authentication_service, - &core_tracker_services.whitelist_authorization, - &core_http_tracker_services.http_stats_event_sender, - &announce_request, - &client_ip_sources, - None, - ) - .await - .unwrap(); + let announce_service = AnnounceService::new( + core_tracker_services.core_config.clone(), + core_tracker_services.announce_handler.clone(), + core_tracker_services.authentication_service.clone(), + core_tracker_services.whitelist_authorization.clone(), + core_http_tracker_services.http_stats_event_sender.clone(), + ); + + let _announce_data = announce_service + .handle_announce(&announce_request, &client_ip_sources, None) + .await + .unwrap(); } } } diff --git a/packages/http-tracker-core/src/services/scrape.rs b/packages/http-tracker-core/src/services/scrape.rs index 394f285ee..48cee7c8c 100644 --- a/packages/http-tracker-core/src/services/scrape.rs +++ b/packages/http-tracker-core/src/services/scrape.rs @@ -71,7 +71,6 @@ impl From for HttpScrapeError { } } } - /// The HTTP tracker `scrape` service. /// /// The service sends an statistics event that increments: @@ -88,46 +87,71 @@ impl From for HttpScrapeError { /// This function will return an error if: /// /// - There is an error when resolving the client IP address. -#[allow(clippy::too_many_arguments)] -pub async fn handle_scrape( - core_config: &Arc, - scrape_handler: &Arc, - authentication_service: &Arc, - opt_http_stats_event_sender: &Arc>>, - scrape_request: &Scrape, - client_ip_sources: &ClientIpSources, - maybe_key: Option, -) -> Result { - // Authentication - let return_fake_scrape_data = if core_config.private { - match maybe_key { - Some(key) => match authentication_service.authenticate(&key).await { - Ok(()) => false, - Err(_error) => true, - }, - None => true, +pub struct ScrapeService { + core_config: Arc, + scrape_handler: Arc, + authentication_service: Arc, + opt_http_stats_event_sender: Arc>>, +} + +impl ScrapeService { + #[must_use] + pub fn new( + core_config: Arc, + scrape_handler: Arc, + authentication_service: Arc, + opt_http_stats_event_sender: Arc>>, + ) -> Self { + Self { + core_config, + scrape_handler, + authentication_service, + opt_http_stats_event_sender, } - } else { - false - }; + } - // Authorization for scrape requests is handled at the `bittorrent_tracker_core` - // level for each torrent. + /// # Errors + /// + /// This function will return an error if: + /// + /// - There is an error when resolving the client IP address. + pub async fn handle_scrape( + &self, + scrape_request: &Scrape, + client_ip_sources: &ClientIpSources, + maybe_key: Option, + ) -> Result { + // Authentication + let return_fake_scrape_data = if self.core_config.private { + match maybe_key { + Some(key) => match self.authentication_service.authenticate(&key).await { + Ok(()) => false, + Err(_error) => true, + }, + None => true, + } + } else { + false + }; - let peer_ip = match peer_ip_resolver::invoke(core_config.net.on_reverse_proxy, client_ip_sources) { - Ok(peer_ip) => peer_ip, - Err(error) => return Err(error.into()), - }; + // Authorization for scrape requests is handled at the `bittorrent_tracker_core` + // level for each torrent. - if return_fake_scrape_data { - return Ok(fake(opt_http_stats_event_sender, &scrape_request.info_hashes, &peer_ip).await); - } + let peer_ip = match peer_ip_resolver::invoke(self.core_config.net.on_reverse_proxy, client_ip_sources) { + Ok(peer_ip) => peer_ip, + Err(error) => return Err(error.into()), + }; + + if return_fake_scrape_data { + return Ok(fake(&self.opt_http_stats_event_sender, &scrape_request.info_hashes, &peer_ip).await); + } - let scrape_data = scrape_handler.scrape(&scrape_request.info_hashes).await?; + let scrape_data = self.scrape_handler.scrape(&scrape_request.info_hashes).await?; - send_scrape_event(&peer_ip, opt_http_stats_event_sender).await; + send_scrape_event(&peer_ip, &self.opt_http_stats_event_sender).await; - Ok(scrape_data) + Ok(scrape_data) + } } /// The HTTP tracker fake `scrape` service. It returns zeroed stats. @@ -261,10 +285,10 @@ mod tests { use torrust_tracker_primitives::swarm_metadata::SwarmMetadata; use torrust_tracker_test_helpers::configuration; - use crate::services::scrape::handle_scrape; use crate::services::scrape::tests::{ initialize_services_with_configuration, sample_info_hashes, sample_peer, MockHttpStatsEventSender, }; + use crate::services::scrape::ScrapeService; use crate::statistics; use crate::tests::sample_info_hash; @@ -299,17 +323,17 @@ mod tests { connection_info_ip: Some(original_peer_ip), }; - let scrape_data = handle_scrape( - &core_config, - &container.scrape_handler, - &container.authentication_service, - &http_stats_event_sender, - &scrape_request, - &client_ip_sources, - None, - ) - .await - .unwrap(); + let scrape_service = Arc::new(ScrapeService::new( + core_config.clone(), + container.scrape_handler.clone(), + container.authentication_service.clone(), + http_stats_event_sender.clone(), + )); + + let scrape_data = scrape_service + .handle_scrape(&scrape_request, &client_ip_sources, None) + .await + .unwrap(); let mut expected_scrape_data = ScrapeData::empty(); expected_scrape_data.add_file( @@ -350,17 +374,17 @@ mod tests { connection_info_ip: Some(peer_ip), }; - handle_scrape( - &Arc::new(config.core), - &container.scrape_handler, - &container.authentication_service, - &http_stats_event_sender, - &scrape_request, - &client_ip_sources, - None, - ) - .await - .unwrap(); + let scrape_service = Arc::new(ScrapeService::new( + Arc::new(config.core), + container.scrape_handler.clone(), + container.authentication_service.clone(), + http_stats_event_sender.clone(), + )); + + scrape_service + .handle_scrape(&scrape_request, &client_ip_sources, None) + .await + .unwrap(); } #[tokio::test] @@ -389,17 +413,17 @@ mod tests { connection_info_ip: Some(peer_ip), }; - handle_scrape( - &Arc::new(config.core), - &container.scrape_handler, - &container.authentication_service, - &http_stats_event_sender, - &scrape_request, - &client_ip_sources, - None, - ) - .await - .unwrap(); + let scrape_service = Arc::new(ScrapeService::new( + Arc::new(config.core), + container.scrape_handler.clone(), + container.authentication_service.clone(), + http_stats_event_sender.clone(), + )); + + scrape_service + .handle_scrape(&scrape_request, &client_ip_sources, None) + .await + .unwrap(); } } diff --git a/packages/udp-tracker-core/src/container.rs b/packages/udp-tracker-core/src/container.rs index 1467134c5..c4cce3dc1 100644 --- a/packages/udp-tracker-core/src/container.rs +++ b/packages/udp-tracker-core/src/container.rs @@ -7,7 +7,10 @@ use bittorrent_tracker_core::whitelist; use tokio::sync::RwLock; use torrust_tracker_configuration::{Core, UdpTracker}; +use crate::services::announce::AnnounceService; use crate::services::banning::BanService; +use crate::services::connect::ConnectService; +use crate::services::scrape::ScrapeService; use crate::{statistics, MAX_CONNECTION_ID_ERRORS_PER_IP}; pub struct UdpTrackerCoreContainer { @@ -21,6 +24,9 @@ pub struct UdpTrackerCoreContainer { pub udp_core_stats_event_sender: Arc>>, pub udp_core_stats_repository: Arc, pub ban_service: Arc>, + pub connect_service: Arc, + pub announce_service: Arc, + pub scrape_service: Arc, } impl UdpTrackerCoreContainer { @@ -39,8 +45,17 @@ impl UdpTrackerCoreContainer { statistics::setup::factory(tracker_core_container.core_config.tracker_usage_statistics); let udp_core_stats_event_sender = Arc::new(udp_core_stats_event_sender); let udp_core_stats_repository = Arc::new(udp_core_stats_repository); - let ban_service = Arc::new(RwLock::new(BanService::new(MAX_CONNECTION_ID_ERRORS_PER_IP))); + let connect_service = Arc::new(ConnectService::new(udp_core_stats_event_sender.clone())); + let announce_service = Arc::new(AnnounceService::new( + tracker_core_container.announce_handler.clone(), + tracker_core_container.whitelist_authorization.clone(), + udp_core_stats_event_sender.clone(), + )); + let scrape_service = Arc::new(ScrapeService::new( + tracker_core_container.scrape_handler.clone(), + udp_core_stats_event_sender.clone(), + )); Arc::new(UdpTrackerCoreContainer { core_config: tracker_core_container.core_config.clone(), @@ -52,6 +67,9 @@ impl UdpTrackerCoreContainer { udp_core_stats_event_sender: udp_core_stats_event_sender.clone(), udp_core_stats_repository: udp_core_stats_repository.clone(), ban_service: ban_service.clone(), + connect_service: connect_service.clone(), + announce_service: announce_service.clone(), + scrape_service: scrape_service.clone(), }) } } diff --git a/packages/udp-tracker-core/src/services/announce.rs b/packages/udp-tracker-core/src/services/announce.rs index b40162283..051944d7e 100644 --- a/packages/udp-tracker-core/src/services/announce.rs +++ b/packages/udp-tracker-core/src/services/announce.rs @@ -12,13 +12,11 @@ use std::ops::Range; use std::sync::Arc; use aquatic_udp_protocol::AnnounceRequest; -use bittorrent_primitives::info_hash::InfoHash; use bittorrent_tracker_core::announce_handler::{AnnounceHandler, PeersWanted}; use bittorrent_tracker_core::error::{AnnounceError, WhitelistError}; use bittorrent_tracker_core::whitelist; use bittorrent_udp_tracker_protocol::peer_builder; use torrust_tracker_primitives::core::AnnounceData; -use torrust_tracker_primitives::peer; use crate::connection_cookie::{check, gen_remote_fingerprint, ConnectionCookieError}; use crate::statistics; @@ -59,97 +57,81 @@ impl From for UdpAnnounceError { } } -/// It handles the `Announce` request. -/// -/// # Errors -/// -/// It will return an error if: -/// -/// - The tracker is running in listed mode and the torrent is not in the -/// whitelist. -#[allow(clippy::too_many_arguments)] -pub async fn handle_announce( - remote_addr: SocketAddr, - request: &AnnounceRequest, - announce_handler: &Arc, - whitelist_authorization: &Arc, - opt_udp_stats_event_sender: &Arc>>, - cookie_valid_range: Range, -) -> Result { - // todo: return a UDP response like the HTTP tracker instead of raw AnnounceData. - - // Authentication - check( - &request.connection_id, - gen_remote_fingerprint(&remote_addr), - cookie_valid_range, - )?; - - let info_hash = request.info_hash.into(); - let remote_client_ip = remote_addr.ip(); - - // Authorization - whitelist_authorization.authorize(&info_hash).await?; - - let mut peer = peer_builder::from_request(request, &remote_client_ip); - let peers_wanted: PeersWanted = i32::from(request.peers_wanted.0).into(); - - let original_peer_ip = peer.peer_addr.ip(); - - // The tracker could change the original peer ip - let announce_data = announce_handler - .announce(&info_hash, &mut peer, &original_peer_ip, &peers_wanted) - .await?; - - if let Some(udp_stats_event_sender) = opt_udp_stats_event_sender.as_deref() { - match original_peer_ip { - IpAddr::V4(_) => { - udp_stats_event_sender - .send_event(statistics::event::Event::Udp4Announce) - .await; - } - IpAddr::V6(_) => { - udp_stats_event_sender - .send_event(statistics::event::Event::Udp6Announce) - .await; - } +/// The `AnnounceService` is responsible for handling the `announce` requests. +pub struct AnnounceService { + pub announce_handler: Arc, + pub whitelist_authorization: Arc, + pub opt_udp_core_stats_event_sender: Arc>>, +} + +impl AnnounceService { + #[must_use] + pub fn new( + announce_handler: Arc, + whitelist_authorization: Arc, + opt_udp_core_stats_event_sender: Arc>>, + ) -> Self { + Self { + announce_handler, + whitelist_authorization, + opt_udp_core_stats_event_sender, } } - Ok(announce_data) -} - -/// # Errors -/// -/// It will return an error if the announce request fails. -pub async fn invoke( - announce_handler: Arc, - opt_udp_stats_event_sender: Arc>>, - info_hash: InfoHash, - peer: &mut peer::Peer, - peers_wanted: &PeersWanted, -) -> Result { - let original_peer_ip = peer.peer_addr.ip(); - - // The tracker could change the original peer ip - let announce_data = announce_handler - .announce(&info_hash, peer, &original_peer_ip, peers_wanted) - .await?; - - if let Some(udp_stats_event_sender) = opt_udp_stats_event_sender.as_deref() { - match original_peer_ip { - IpAddr::V4(_) => { - udp_stats_event_sender - .send_event(statistics::event::Event::Udp4Announce) - .await; - } - IpAddr::V6(_) => { - udp_stats_event_sender - .send_event(statistics::event::Event::Udp6Announce) - .await; + /// It handles the `Announce` request. + /// + /// # Errors + /// + /// It will return an error if: + /// + /// - The tracker is running in listed mode and the torrent is not in the + /// whitelist. + #[allow(clippy::too_many_arguments)] + pub async fn handle_announce( + &self, + remote_addr: SocketAddr, + request: &AnnounceRequest, + cookie_valid_range: Range, + ) -> Result { + // Authentication + check( + &request.connection_id, + gen_remote_fingerprint(&remote_addr), + cookie_valid_range, + )?; + + let info_hash = request.info_hash.into(); + let remote_client_ip = remote_addr.ip(); + + // Authorization + self.whitelist_authorization.authorize(&info_hash).await?; + + let mut peer = peer_builder::from_request(request, &remote_client_ip); + let peers_wanted: PeersWanted = i32::from(request.peers_wanted.0).into(); + + let original_peer_ip = peer.peer_addr.ip(); + + // The tracker could change the original peer ip + let announce_data = self + .announce_handler + .announce(&info_hash, &mut peer, &original_peer_ip, &peers_wanted) + .await?; + + if let Some(udp_stats_event_sender) = self.opt_udp_core_stats_event_sender.as_deref() { + match original_peer_ip { + IpAddr::V4(_) => { + udp_stats_event_sender + .send_event(statistics::event::Event::Udp4Announce) + .await; + } + IpAddr::V6(_) => { + udp_stats_event_sender + .send_event(statistics::event::Event::Udp6Announce) + .await; + } } } - } - Ok(announce_data) + Ok(announce_data) + } } diff --git a/packages/udp-tracker-core/src/services/connect.rs b/packages/udp-tracker-core/src/services/connect.rs index 3354595e5..14a3068e4 100644 --- a/packages/udp-tracker-core/src/services/connect.rs +++ b/packages/udp-tracker-core/src/services/connect.rs @@ -9,30 +9,43 @@ use aquatic_udp_protocol::ConnectionId; use crate::connection_cookie::{gen_remote_fingerprint, make}; use crate::statistics; -/// # Panics +/// The `ConnectService` is responsible for handling the `connect` requests. /// -/// IT will panic if there was an error making the connection cookie. -pub async fn handle_connect( - remote_addr: SocketAddr, - opt_udp_stats_event_sender: &Arc>>, - cookie_issue_time: f64, -) -> ConnectionId { - // todo: return a UDP response like the HTTP tracker instead of raw ConnectionId. - - let connection_id = make(gen_remote_fingerprint(&remote_addr), cookie_issue_time).expect("it should be a normal value"); - - if let Some(udp_stats_event_sender) = opt_udp_stats_event_sender.as_deref() { - match remote_addr { - SocketAddr::V4(_) => { - udp_stats_event_sender.send_event(statistics::event::Event::Udp4Connect).await; - } - SocketAddr::V6(_) => { - udp_stats_event_sender.send_event(statistics::event::Event::Udp6Connect).await; - } +/// It is responsible for generating the connection cookie and sending the +/// appropriate statistics events. +pub struct ConnectService { + pub opt_udp_core_stats_event_sender: Arc>>, +} + +impl ConnectService { + #[must_use] + pub fn new(opt_udp_core_stats_event_sender: Arc>>) -> Self { + Self { + opt_udp_core_stats_event_sender, } } - connection_id + /// Handles a `connect` request. + /// + /// # Panics + /// + /// It will panic if there was an error making the connection cookie. + pub async fn handle_connect(&self, remote_addr: SocketAddr, cookie_issue_time: f64) -> ConnectionId { + let connection_id = make(gen_remote_fingerprint(&remote_addr), cookie_issue_time).expect("it should be a normal value"); + + if let Some(udp_stats_event_sender) = self.opt_udp_core_stats_event_sender.as_deref() { + match remote_addr { + SocketAddr::V4(_) => { + udp_stats_event_sender.send_event(statistics::event::Event::Udp4Connect).await; + } + SocketAddr::V6(_) => { + udp_stats_event_sender.send_event(statistics::event::Event::Udp6Connect).await; + } + } + } + + connection_id + } } #[cfg(test)] @@ -46,10 +59,10 @@ mod tests { use mockall::predicate::eq; use crate::connection_cookie::make; - use crate::services::connect::handle_connect; + use crate::services::connect::ConnectService; use crate::services::tests::{ sample_ipv4_remote_addr, sample_ipv4_remote_addr_fingerprint, sample_ipv4_socket_address, sample_ipv6_remote_addr, - sample_ipv6_remote_addr_fingerprint, sample_issue_time, MockUdpStatsEventSender, + sample_ipv6_remote_addr_fingerprint, sample_issue_time, MockUdpCoreStatsEventSender, }; use crate::statistics; @@ -58,7 +71,11 @@ mod tests { let (udp_core_stats_event_sender, _udp_core_stats_repository) = statistics::setup::factory(false); let udp_core_stats_event_sender = Arc::new(udp_core_stats_event_sender); - let response = handle_connect(sample_ipv4_remote_addr(), &udp_core_stats_event_sender, sample_issue_time()).await; + let connect_service = Arc::new(ConnectService::new(udp_core_stats_event_sender)); + + let response = connect_service + .handle_connect(sample_ipv4_remote_addr(), sample_issue_time()) + .await; assert_eq!( response, @@ -71,7 +88,11 @@ mod tests { let (udp_core_stats_event_sender, _udp_core_stats_repository) = statistics::setup::factory(false); let udp_core_stats_event_sender = Arc::new(udp_core_stats_event_sender); - let response = handle_connect(sample_ipv4_remote_addr(), &udp_core_stats_event_sender, sample_issue_time()).await; + let connect_service = Arc::new(ConnectService::new(udp_core_stats_event_sender)); + + let response = connect_service + .handle_connect(sample_ipv4_remote_addr(), sample_issue_time()) + .await; assert_eq!( response, @@ -84,7 +105,11 @@ mod tests { let (udp_core_stats_event_sender, _udp_core_stats_repository) = statistics::setup::factory(false); let udp_core_stats_event_sender = Arc::new(udp_core_stats_event_sender); - let response = handle_connect(sample_ipv6_remote_addr(), &udp_core_stats_event_sender, sample_issue_time()).await; + let connect_service = Arc::new(ConnectService::new(udp_core_stats_event_sender)); + + let response = connect_service + .handle_connect(sample_ipv6_remote_addr(), sample_issue_time()) + .await; assert_eq!( response, @@ -94,32 +119,40 @@ mod tests { #[tokio::test] async fn it_should_send_the_upd4_connect_event_when_a_client_tries_to_connect_using_a_ip4_socket_address() { - let mut udp_stats_event_sender_mock = MockUdpStatsEventSender::new(); + let mut udp_stats_event_sender_mock = MockUdpCoreStatsEventSender::new(); udp_stats_event_sender_mock .expect_send_event() .with(eq(statistics::event::Event::Udp4Connect)) .times(1) .returning(|_| Box::pin(future::ready(Some(Ok(()))))); - let udp_stats_event_sender: Arc>> = + let opt_udp_stats_event_sender: Arc>> = Arc::new(Some(Box::new(udp_stats_event_sender_mock))); let client_socket_address = sample_ipv4_socket_address(); - handle_connect(client_socket_address, &udp_stats_event_sender, sample_issue_time()).await; + let connect_service = Arc::new(ConnectService::new(opt_udp_stats_event_sender)); + + connect_service + .handle_connect(client_socket_address, sample_issue_time()) + .await; } #[tokio::test] async fn it_should_send_the_upd6_connect_event_when_a_client_tries_to_connect_using_a_ip6_socket_address() { - let mut udp_stats_event_sender_mock = MockUdpStatsEventSender::new(); + let mut udp_stats_event_sender_mock = MockUdpCoreStatsEventSender::new(); udp_stats_event_sender_mock .expect_send_event() .with(eq(statistics::event::Event::Udp6Connect)) .times(1) .returning(|_| Box::pin(future::ready(Some(Ok(()))))); - let udp_stats_event_sender: Arc>> = + let opt_udp_stats_event_sender: Arc>> = Arc::new(Some(Box::new(udp_stats_event_sender_mock))); - handle_connect(sample_ipv6_remote_addr(), &udp_stats_event_sender, sample_issue_time()).await; + let connect_service = Arc::new(ConnectService::new(opt_udp_stats_event_sender)); + + connect_service + .handle_connect(sample_ipv6_remote_addr(), sample_issue_time()) + .await; } } } diff --git a/packages/udp-tracker-core/src/services/mod.rs b/packages/udp-tracker-core/src/services/mod.rs index 0fcb612e4..6aa254f41 100644 --- a/packages/udp-tracker-core/src/services/mod.rs +++ b/packages/udp-tracker-core/src/services/mod.rs @@ -44,8 +44,8 @@ pub(crate) mod tests { } mock! { - pub(crate) UdpStatsEventSender {} - impl statistics::event::sender::Sender for UdpStatsEventSender { + pub(crate) UdpCoreStatsEventSender {} + impl statistics::event::sender::Sender for UdpCoreStatsEventSender { fn send_event(&self, event: statistics::event::Event) -> BoxFuture<'static,Option > > > ; } } diff --git a/packages/udp-tracker-core/src/services/scrape.rs b/packages/udp-tracker-core/src/services/scrape.rs index bec55afe3..fddc2ec2d 100644 --- a/packages/udp-tracker-core/src/services/scrape.rs +++ b/packages/udp-tracker-core/src/services/scrape.rs @@ -56,41 +56,58 @@ impl From for UdpScrapeError { } } -/// It handles the `Scrape` request. -/// -/// # Errors -/// -/// It will return an error if the tracker core scrape handler returns an error. -pub async fn handle_scrape( - remote_addr: SocketAddr, - request: &ScrapeRequest, - scrape_handler: &Arc, - opt_udp_stats_event_sender: &Arc>>, - cookie_valid_range: Range, -) -> Result { - // todo: return a UDP response like the HTTP tracker instead of raw ScrapeData. +/// The `ScrapeService` is responsible for handling the `scrape` requests. +pub struct ScrapeService { + scrape_handler: Arc, + opt_udp_stats_event_sender: Arc>>, +} - check( - &request.connection_id, - gen_remote_fingerprint(&remote_addr), - cookie_valid_range, - )?; +impl ScrapeService { + /// Creates a new `ScrapeService`. + #[must_use] + pub fn new( + scrape_handler: Arc, + opt_udp_stats_event_sender: Arc>>, + ) -> Self { + Self { + scrape_handler, + opt_udp_stats_event_sender, + } + } - // Convert from aquatic infohashes - let info_hashes: Vec = request.info_hashes.iter().map(|&x| x.into()).collect(); + /// It handles the `Scrape` request. + /// + /// # Errors + /// + /// It will return an error if the tracker core scrape handler returns an error. + pub async fn handle_scrape( + &self, + remote_addr: SocketAddr, + request: &ScrapeRequest, + cookie_valid_range: Range, + ) -> Result { + check( + &request.connection_id, + gen_remote_fingerprint(&remote_addr), + cookie_valid_range, + )?; - let scrape_data = scrape_handler.scrape(&info_hashes).await?; + // Convert from aquatic infohashes + let info_hashes: Vec = request.info_hashes.iter().map(|&x| x.into()).collect(); - if let Some(udp_stats_event_sender) = opt_udp_stats_event_sender.as_deref() { - match remote_addr { - SocketAddr::V4(_) => { - udp_stats_event_sender.send_event(statistics::event::Event::Udp4Scrape).await; - } - SocketAddr::V6(_) => { - udp_stats_event_sender.send_event(statistics::event::Event::Udp6Scrape).await; + let scrape_data = self.scrape_handler.scrape(&info_hashes).await?; + + if let Some(udp_stats_event_sender) = self.opt_udp_stats_event_sender.as_deref() { + match remote_addr { + SocketAddr::V4(_) => { + udp_stats_event_sender.send_event(statistics::event::Event::Udp4Scrape).await; + } + SocketAddr::V6(_) => { + udp_stats_event_sender.send_event(statistics::event::Event::Udp6Scrape).await; + } } } - } - Ok(scrape_data) + Ok(scrape_data) + } } diff --git a/packages/udp-tracker-server/src/handlers/announce.rs b/packages/udp-tracker-server/src/handlers/announce.rs index 97ce6ba4a..9269dadfe 100644 --- a/packages/udp-tracker-server/src/handlers/announce.rs +++ b/packages/udp-tracker-server/src/handlers/announce.rs @@ -8,9 +8,7 @@ use aquatic_udp_protocol::{ Port, Response, ResponsePeer, TransactionId, }; use bittorrent_primitives::info_hash::InfoHash; -use bittorrent_tracker_core::announce_handler::AnnounceHandler; -use bittorrent_tracker_core::whitelist; -use bittorrent_udp_tracker_core::{services, statistics as core_statistics}; +use bittorrent_udp_tracker_core::services::announce::AnnounceService; use torrust_tracker_configuration::Core; use torrust_tracker_primitives::core::AnnounceData; use tracing::{instrument, Level}; @@ -25,15 +23,12 @@ use crate::statistics::event::UdpResponseKind; /// # Errors /// /// If a error happens in the `handle_announce` function, it will just return the `ServerError`. -#[allow(clippy::too_many_arguments)] -#[instrument(fields(transaction_id, connection_id, info_hash), skip(announce_handler, whitelist_authorization, opt_udp_core_stats_event_sender, opt_udp_server_stats_event_sender), ret(level = Level::TRACE))] +#[instrument(fields(transaction_id, connection_id, info_hash), skip(announce_service, opt_udp_server_stats_event_sender), ret(level = Level::TRACE))] pub async fn handle_announce( + announce_service: &Arc, remote_addr: SocketAddr, request: &AnnounceRequest, core_config: &Arc, - announce_handler: &Arc, - whitelist_authorization: &Arc, - opt_udp_core_stats_event_sender: &Arc>>, opt_udp_server_stats_event_sender: &Arc>>, cookie_valid_range: Range, ) -> Result { @@ -63,16 +58,10 @@ pub async fn handle_announce( } } - let announce_data = services::announce::handle_announce( - remote_addr, - request, - announce_handler, - whitelist_authorization, - opt_udp_core_stats_event_sender, - cookie_valid_range, - ) - .await - .map_err(|e| (e.into(), request.transaction_id))?; + let announce_data = announce_service + .handle_announce(remote_addr, request, cookie_valid_range) + .await + .map_err(|e| (e.into(), request.transaction_id))?; Ok(build_response(remote_addr, request, core_config, &announce_data)) } @@ -223,20 +212,17 @@ mod tests { AnnounceInterval, AnnounceResponse, AnnounceResponseFixedData, InfoHash as AquaticInfoHash, Ipv4AddrBytes, Ipv6AddrBytes, NumberOfPeers, PeerId as AquaticPeerId, Response, ResponsePeer, }; - use bittorrent_tracker_core::announce_handler::AnnounceHandler; use bittorrent_tracker_core::torrent::repository::in_memory::InMemoryTorrentRepository; - use bittorrent_tracker_core::whitelist; use bittorrent_udp_tracker_core::connection_cookie::{gen_remote_fingerprint, make}; - use bittorrent_udp_tracker_core::statistics as core_statistics; use mockall::predicate::eq; - use torrust_tracker_configuration::Core; use crate::handlers::announce::tests::announce_request::AnnounceRequestBuilder; use crate::handlers::handle_announce; use crate::handlers::tests::{ initialize_core_tracker_services_for_default_tracker_configuration, initialize_core_tracker_services_for_public_tracker, sample_cookie_valid_range, sample_ipv4_socket_address, - sample_issue_time, MockUdpCoreStatsEventSender, MockUdpServerStatsEventSender, TorrentPeerBuilder, + sample_issue_time, CoreTrackerServices, CoreUdpTrackerServices, MockUdpServerStatsEventSender, + TorrentPeerBuilder, }; use crate::statistics as server_statistics; use crate::statistics::event::UdpResponseKind; @@ -262,12 +248,10 @@ mod tests { .into(); handle_announce( + &core_udp_tracker_services.announce_service, remote_addr, &request, &core_tracker_services.core_config, - &core_tracker_services.announce_handler, - &core_tracker_services.whitelist_authorization, - &core_udp_tracker_services.udp_core_stats_event_sender, &server_udp_tracker_services.udp_server_stats_event_sender, sample_cookie_valid_range(), ) @@ -299,12 +283,10 @@ mod tests { .into(); let response = handle_announce( + &core_udp_tracker_services.announce_service, remote_addr, &request, &core_tracker_services.core_config, - &core_tracker_services.announce_handler, - &core_tracker_services.whitelist_authorization, - &core_udp_tracker_services.udp_core_stats_event_sender, &server_udp_tracker_services.udp_server_stats_event_sender, sample_cookie_valid_range(), ) @@ -354,12 +336,10 @@ mod tests { .into(); handle_announce( + &core_udp_tracker_services.announce_service, remote_addr, &request, &core_tracker_services.core_config, - &core_tracker_services.announce_handler, - &core_tracker_services.whitelist_authorization, - &core_udp_tracker_services.udp_core_stats_event_sender, &server_udp_tracker_services.udp_server_stats_event_sender, sample_cookie_valid_range(), ) @@ -390,13 +370,12 @@ mod tests { } async fn announce_a_new_peer_using_ipv4( - core_config: Arc, - announce_handler: Arc, - whitelist_authorization: Arc, + core_tracker_services: Arc, + core_udp_tracker_services: Arc, ) -> Response { let (udp_core_stats_event_sender, _udp_core_stats_repository) = bittorrent_udp_tracker_core::statistics::setup::factory(false); - let udp_core_stats_event_sender = Arc::new(udp_core_stats_event_sender); + let _udp_core_stats_event_sender = Arc::new(udp_core_stats_event_sender); let (udp_server_stats_event_sender, _udp_server_stats_repository) = crate::statistics::setup::factory(false); let udp_server_stats_event_sender = Arc::new(udp_server_stats_event_sender); @@ -407,12 +386,10 @@ mod tests { .into(); handle_announce( + &core_udp_tracker_services.announce_service, remote_addr, &request, - &core_config, - &announce_handler, - &whitelist_authorization, - &udp_core_stats_event_sender, + &core_tracker_services.core_config, &udp_server_stats_event_sender, sample_cookie_valid_range(), ) @@ -422,17 +399,13 @@ mod tests { #[tokio::test] async fn when_the_announce_request_comes_from_a_client_using_ipv4_the_response_should_not_include_peers_using_ipv6() { - let (core_tracker_services, _core_udp_tracker_services, _server_udp_tracker_services) = + let (core_tracker_services, core_udp_tracker_services, _server_udp_tracker_services) = initialize_core_tracker_services_for_public_tracker(); add_a_torrent_peer_using_ipv6(&core_tracker_services.in_memory_torrent_repository); - let response = announce_a_new_peer_using_ipv4( - core_tracker_services.core_config.clone(), - core_tracker_services.announce_handler.clone(), - core_tracker_services.whitelist_authorization, - ) - .await; + let response = + announce_a_new_peer_using_ipv4(Arc::new(core_tracker_services), Arc::new(core_udp_tracker_services)).await; // The response should not contain the peer using IPV6 let peers: Option>> = match response { @@ -445,15 +418,6 @@ mod tests { #[tokio::test] async fn should_send_the_upd4_announce_event() { - let mut udp_core_stats_event_sender_mock = MockUdpCoreStatsEventSender::new(); - udp_core_stats_event_sender_mock - .expect_send_event() - .with(eq(core_statistics::event::Event::Udp4Announce)) - .times(1) - .returning(|_| Box::pin(future::ready(Some(Ok(()))))); - let udp_core_stats_event_sender: Arc>> = - Arc::new(Some(Box::new(udp_core_stats_event_sender_mock))); - let mut udp_server_stats_event_sender_mock = MockUdpServerStatsEventSender::new(); udp_server_stats_event_sender_mock .expect_send_event() @@ -465,16 +429,14 @@ mod tests { let udp_server_stats_event_sender: Arc>> = Arc::new(Some(Box::new(udp_server_stats_event_sender_mock))); - let (core_tracker_services, _core_udp_tracker_services, _server_udp_tracker_services) = + let (core_tracker_services, core_udp_tracker_services, _server_udp_tracker_services) = initialize_core_tracker_services_for_default_tracker_configuration(); handle_announce( + &core_udp_tracker_services.announce_service, sample_ipv4_socket_address(), &AnnounceRequestBuilder::default().into(), &core_tracker_services.core_config, - &core_tracker_services.announce_handler, - &core_tracker_services.whitelist_authorization, - &udp_core_stats_event_sender, &udp_server_stats_event_sender, sample_cookie_valid_range(), ) @@ -517,12 +479,10 @@ mod tests { .into(); handle_announce( + &core_udp_tracker_services.announce_service, remote_addr, &request, &core_tracker_services.core_config, - &core_tracker_services.announce_handler, - &core_tracker_services.whitelist_authorization, - &core_udp_tracker_services.udp_core_stats_event_sender, &server_udp_tracker_services.udp_server_stats_event_sender, sample_cookie_valid_range(), ) @@ -560,7 +520,7 @@ mod tests { use bittorrent_tracker_core::torrent::repository::in_memory::InMemoryTorrentRepository; use bittorrent_tracker_core::whitelist; use bittorrent_udp_tracker_core::connection_cookie::{gen_remote_fingerprint, make}; - use bittorrent_udp_tracker_core::statistics as core_statistics; + use bittorrent_udp_tracker_core::services::announce::AnnounceService; use mockall::predicate::eq; use torrust_tracker_configuration::Core; @@ -569,7 +529,7 @@ mod tests { use crate::handlers::tests::{ initialize_core_tracker_services_for_default_tracker_configuration, initialize_core_tracker_services_for_public_tracker, sample_cookie_valid_range, sample_ipv6_remote_addr, - sample_issue_time, MockUdpCoreStatsEventSender, MockUdpServerStatsEventSender, TorrentPeerBuilder, + sample_issue_time, MockUdpServerStatsEventSender, TorrentPeerBuilder, }; use crate::statistics as server_statistics; use crate::statistics::event::UdpResponseKind; @@ -596,12 +556,10 @@ mod tests { .into(); handle_announce( + &core_udp_tracker_services.announce_service, remote_addr, &request, &core_tracker_services.core_config, - &core_tracker_services.announce_handler, - &core_tracker_services.whitelist_authorization, - &core_udp_tracker_services.udp_core_stats_event_sender, &server_udp_tracker_services.udp_server_stats_event_sender, sample_cookie_valid_range(), ) @@ -636,12 +594,10 @@ mod tests { .into(); let response = handle_announce( + &core_udp_tracker_services.announce_service, remote_addr, &request, &core_tracker_services.core_config, - &core_tracker_services.announce_handler, - &core_tracker_services.whitelist_authorization, - &core_udp_tracker_services.udp_core_stats_event_sender, &server_udp_tracker_services.udp_server_stats_event_sender, sample_cookie_valid_range(), ) @@ -691,12 +647,10 @@ mod tests { .into(); handle_announce( + &core_udp_tracker_services.announce_service, remote_addr, &request, &core_tracker_services.core_config, - &core_tracker_services.announce_handler, - &core_tracker_services.whitelist_authorization, - &core_udp_tracker_services.udp_core_stats_event_sender, &server_udp_tracker_service.udp_server_stats_event_sender, sample_cookie_valid_range(), ) @@ -746,13 +700,17 @@ mod tests { .with_connection_id(make(gen_remote_fingerprint(&remote_addr), sample_issue_time()).unwrap()) .into(); + let announce_service = Arc::new(AnnounceService::new( + announce_handler.clone(), + whitelist_authorization.clone(), + udp_core_stats_event_sender.clone(), + )); + handle_announce( + &announce_service, remote_addr, &request, &core_config, - &announce_handler, - &whitelist_authorization, - &udp_core_stats_event_sender, &udp_server_stats_event_sender, sample_cookie_valid_range(), ) @@ -785,15 +743,6 @@ mod tests { #[tokio::test] async fn should_send_the_upd6_announce_event() { - let mut udp_core_stats_event_sender_mock = MockUdpCoreStatsEventSender::new(); - udp_core_stats_event_sender_mock - .expect_send_event() - .with(eq(core_statistics::event::Event::Udp6Announce)) - .times(1) - .returning(|_| Box::pin(future::ready(Some(Ok(()))))); - let udp_core_stats_event_sender: Arc>> = - Arc::new(Some(Box::new(udp_core_stats_event_sender_mock))); - let mut udp_server_stats_event_sender_mock = MockUdpServerStatsEventSender::new(); udp_server_stats_event_sender_mock .expect_send_event() @@ -805,7 +754,7 @@ mod tests { let udp_server_stats_event_sender: Arc>> = Arc::new(Some(Box::new(udp_server_stats_event_sender_mock))); - let (core_tracker_services, _core_udp_tracker_services, _server_udp_tracker_services) = + let (core_tracker_services, core_udp_tracker_services, _server_udp_tracker_services) = initialize_core_tracker_services_for_default_tracker_configuration(); let remote_addr = sample_ipv6_remote_addr(); @@ -815,12 +764,10 @@ mod tests { .into(); handle_announce( + &core_udp_tracker_services.announce_service, remote_addr, &announce_request, &core_tracker_services.core_config, - &core_tracker_services.announce_handler, - &core_tracker_services.whitelist_authorization, - &udp_core_stats_event_sender, &udp_server_stats_event_sender, sample_cookie_valid_range(), ) @@ -841,6 +788,7 @@ mod tests { use bittorrent_tracker_core::whitelist::authorization::WhitelistAuthorization; use bittorrent_tracker_core::whitelist::repository::in_memory::InMemoryWhitelist; use bittorrent_udp_tracker_core::connection_cookie::{gen_remote_fingerprint, make}; + use bittorrent_udp_tracker_core::services::announce::AnnounceService; use bittorrent_udp_tracker_core::{self, statistics as core_statistics}; use mockall::predicate::eq; @@ -913,13 +861,17 @@ mod tests { let core_config = Arc::new(config.core.clone()); + let announce_service = Arc::new(AnnounceService::new( + announce_handler.clone(), + whitelist_authorization.clone(), + udp_core_stats_event_sender.clone(), + )); + handle_announce( + &announce_service, remote_addr, &request, &core_config, - &announce_handler, - &whitelist_authorization, - &udp_core_stats_event_sender, &udp_server_stats_event_sender, sample_cookie_valid_range(), ) diff --git a/packages/udp-tracker-server/src/handlers/connect.rs b/packages/udp-tracker-server/src/handlers/connect.rs index be6dc45d4..93d3bb6f1 100644 --- a/packages/udp-tracker-server/src/handlers/connect.rs +++ b/packages/udp-tracker-server/src/handlers/connect.rs @@ -3,18 +3,18 @@ use std::net::{IpAddr, SocketAddr}; use std::sync::Arc; use aquatic_udp_protocol::{ConnectRequest, ConnectResponse, ConnectionId, Response}; -use bittorrent_udp_tracker_core::{services, statistics as core_statistics}; +use bittorrent_udp_tracker_core::services::connect::ConnectService; use tracing::{instrument, Level}; use crate::statistics as server_statistics; use crate::statistics::event::UdpResponseKind; /// It handles the `Connect` request. -#[instrument(fields(transaction_id), skip(opt_udp_core_stats_event_sender, opt_udp_server_stats_event_sender), ret(level = Level::TRACE))] +#[instrument(fields(transaction_id), skip(connect_service, opt_udp_server_stats_event_sender), ret(level = Level::TRACE))] pub async fn handle_connect( remote_addr: SocketAddr, request: &ConnectRequest, - opt_udp_core_stats_event_sender: &Arc>>, + connect_service: &Arc, opt_udp_server_stats_event_sender: &Arc>>, cookie_issue_time: f64, ) -> Response { @@ -40,7 +40,7 @@ pub async fn handle_connect( } } - let connection_id = services::connect::handle_connect(remote_addr, opt_udp_core_stats_event_sender, cookie_issue_time).await; + let connection_id = connect_service.handle_connect(remote_addr, cookie_issue_time).await; build_response(*request, connection_id) } @@ -64,6 +64,7 @@ mod tests { use aquatic_udp_protocol::{ConnectRequest, ConnectResponse, Response, TransactionId}; use bittorrent_udp_tracker_core::connection_cookie::make; + use bittorrent_udp_tracker_core::services::connect::ConnectService; use bittorrent_udp_tracker_core::statistics as core_statistics; use mockall::predicate::eq; @@ -94,10 +95,12 @@ mod tests { transaction_id: TransactionId(0i32.into()), }; + let connect_service = Arc::new(ConnectService::new(udp_core_stats_event_sender)); + let response = handle_connect( sample_ipv4_remote_addr(), &request, - &udp_core_stats_event_sender, + &connect_service, &udp_server_stats_event_sender, sample_issue_time(), ) @@ -125,10 +128,12 @@ mod tests { transaction_id: TransactionId(0i32.into()), }; + let connect_service = Arc::new(ConnectService::new(udp_core_stats_event_sender)); + let response = handle_connect( sample_ipv4_remote_addr(), &request, - &udp_core_stats_event_sender, + &connect_service, &udp_server_stats_event_sender, sample_issue_time(), ) @@ -156,10 +161,12 @@ mod tests { transaction_id: TransactionId(0i32.into()), }; + let connect_service = Arc::new(ConnectService::new(udp_core_stats_event_sender)); + let response = handle_connect( sample_ipv6_remote_addr(), &request, - &udp_core_stats_event_sender, + &connect_service, &udp_server_stats_event_sender, sample_issue_time(), ) @@ -198,10 +205,12 @@ mod tests { let client_socket_address = sample_ipv4_socket_address(); + let connect_service = Arc::new(ConnectService::new(udp_core_stats_event_sender)); + handle_connect( client_socket_address, &sample_connect_request(), - &udp_core_stats_event_sender, + &connect_service, &udp_server_stats_event_sender, sample_issue_time(), ) @@ -230,10 +239,12 @@ mod tests { let udp_server_stats_event_sender: Arc>> = Arc::new(Some(Box::new(udp_server_stats_event_sender_mock))); + let connect_service = Arc::new(ConnectService::new(udp_core_stats_event_sender)); + handle_connect( sample_ipv6_remote_addr(), &sample_connect_request(), - &udp_core_stats_event_sender, + &connect_service, &udp_server_stats_event_sender, sample_issue_time(), ) diff --git a/packages/udp-tracker-server/src/handlers/mod.rs b/packages/udp-tracker-server/src/handlers/mod.rs index fd0536b8b..165b307e0 100644 --- a/packages/udp-tracker-server/src/handlers/mod.rs +++ b/packages/udp-tracker-server/src/handlers/mod.rs @@ -147,19 +147,17 @@ pub async fn handle_request( Request::Connect(connect_request) => Ok(handle_connect( remote_addr, &connect_request, - &udp_tracker_core_container.udp_core_stats_event_sender, + &udp_tracker_core_container.connect_service, &udp_tracker_server_container.udp_server_stats_event_sender, cookie_time_values.issue_time, ) .await), Request::Announce(announce_request) => { handle_announce( + &udp_tracker_core_container.announce_service, remote_addr, &announce_request, &udp_tracker_core_container.core_config, - &udp_tracker_core_container.announce_handler, - &udp_tracker_core_container.whitelist_authorization, - &udp_tracker_core_container.udp_core_stats_event_sender, &udp_tracker_server_container.udp_server_stats_event_sender, cookie_time_values.valid_range, ) @@ -167,10 +165,9 @@ pub async fn handle_request( } Request::Scrape(scrape_request) => { handle_scrape( + &udp_tracker_core_container.scrape_service, remote_addr, &scrape_request, - &udp_tracker_core_container.scrape_handler, - &udp_tracker_core_container.udp_core_stats_event_sender, &udp_tracker_server_container.udp_server_stats_event_sender, cookie_time_values.valid_range, ) @@ -196,6 +193,8 @@ pub(crate) mod tests { use bittorrent_tracker_core::whitelist::authorization::WhitelistAuthorization; use bittorrent_tracker_core::whitelist::repository::in_memory::InMemoryWhitelist; use bittorrent_udp_tracker_core::connection_cookie::gen_remote_fingerprint; + use bittorrent_udp_tracker_core::services::announce::AnnounceService; + use bittorrent_udp_tracker_core::services::scrape::ScrapeService; use bittorrent_udp_tracker_core::{self, statistics as core_statistics}; use futures::future::BoxFuture; use mockall::mock; @@ -210,14 +209,14 @@ pub(crate) mod tests { pub(crate) struct CoreTrackerServices { pub core_config: Arc, pub announce_handler: Arc, - pub scrape_handler: Arc, pub in_memory_torrent_repository: Arc, pub in_memory_whitelist: Arc, pub whitelist_authorization: Arc, } pub(crate) struct CoreUdpTrackerServices { - pub udp_core_stats_event_sender: Arc>>, + pub announce_service: Arc, + pub scrape_service: Arc, } pub(crate) struct ServerUdpTrackerServices { @@ -267,17 +266,28 @@ pub(crate) mod tests { let (udp_server_stats_event_sender, _udp_server_stats_repository) = crate::statistics::setup::factory(false); let udp_server_stats_event_sender = Arc::new(udp_server_stats_event_sender); + let announce_service = Arc::new(AnnounceService::new( + announce_handler.clone(), + whitelist_authorization.clone(), + udp_core_stats_event_sender.clone(), + )); + + let scrape_service = Arc::new(ScrapeService::new( + scrape_handler.clone(), + udp_core_stats_event_sender.clone(), + )); + ( CoreTrackerServices { core_config, announce_handler, - scrape_handler, in_memory_torrent_repository, in_memory_whitelist, whitelist_authorization, }, CoreUdpTrackerServices { - udp_core_stats_event_sender, + announce_service, + scrape_service, }, ServerUdpTrackerServices { udp_server_stats_event_sender, diff --git a/packages/udp-tracker-server/src/handlers/scrape.rs b/packages/udp-tracker-server/src/handlers/scrape.rs index 248f0ca12..3e6da4778 100644 --- a/packages/udp-tracker-server/src/handlers/scrape.rs +++ b/packages/udp-tracker-server/src/handlers/scrape.rs @@ -6,8 +6,8 @@ use std::sync::Arc; use aquatic_udp_protocol::{ NumberOfDownloads, NumberOfPeers, Response, ScrapeRequest, ScrapeResponse, TorrentScrapeStatistics, TransactionId, }; -use bittorrent_tracker_core::scrape_handler::ScrapeHandler; -use bittorrent_udp_tracker_core::{self, services, statistics as core_statistics}; +use bittorrent_udp_tracker_core::services::scrape::ScrapeService; +use bittorrent_udp_tracker_core::{self}; use torrust_tracker_primitives::core::ScrapeData; use tracing::{instrument, Level}; use zerocopy::network_endian::I32; @@ -21,12 +21,11 @@ use crate::statistics::event::UdpResponseKind; /// # Errors /// /// This function does not ever return an error. -#[instrument(fields(transaction_id, connection_id), skip(scrape_handler, opt_udp_core_stats_event_sender, opt_udp_server_stats_event_sender), ret(level = Level::TRACE))] +#[instrument(fields(transaction_id, connection_id), skip(scrape_service, opt_udp_server_stats_event_sender), ret(level = Level::TRACE))] pub async fn handle_scrape( + scrape_service: &Arc, remote_addr: SocketAddr, request: &ScrapeRequest, - scrape_handler: &Arc, - opt_udp_core_stats_event_sender: &Arc>>, opt_udp_server_stats_event_sender: &Arc>>, cookie_valid_range: Range, ) -> Result { @@ -55,15 +54,10 @@ pub async fn handle_scrape( } } - let scrape_data = services::scrape::handle_scrape( - remote_addr, - request, - scrape_handler, - opt_udp_core_stats_event_sender, - cookie_valid_range, - ) - .await - .map_err(|e| (e.into(), request.transaction_id))?; + let scrape_data = scrape_service + .handle_scrape(remote_addr, request, cookie_valid_range) + .await + .map_err(|e| (e.into(), request.transaction_id))?; Ok(build_response(request, &scrape_data)) } @@ -105,14 +99,13 @@ mod tests { InfoHash, NumberOfDownloads, NumberOfPeers, PeerId, Response, ScrapeRequest, ScrapeResponse, TorrentScrapeStatistics, TransactionId, }; - use bittorrent_tracker_core::scrape_handler::ScrapeHandler; use bittorrent_tracker_core::torrent::repository::in_memory::InMemoryTorrentRepository; use bittorrent_udp_tracker_core::connection_cookie::{gen_remote_fingerprint, make}; use crate::handlers::handle_scrape; use crate::handlers::tests::{ initialize_core_tracker_services_for_public_tracker, sample_cookie_valid_range, sample_ipv4_remote_addr, - sample_issue_time, TorrentPeerBuilder, + sample_issue_time, CoreTrackerServices, CoreUdpTrackerServices, TorrentPeerBuilder, }; fn zeroed_torrent_statistics() -> TorrentScrapeStatistics { @@ -125,7 +118,7 @@ mod tests { #[tokio::test] async fn should_return_no_stats_when_the_tracker_does_not_have_any_torrent() { - let (core_tracker_services, core_udp_tracker_services, server_udp_tracker_services) = + let (_core_tracker_services, core_udp_tracker_services, server_udp_tracker_services) = initialize_core_tracker_services_for_public_tracker(); let remote_addr = sample_ipv4_remote_addr(); @@ -140,10 +133,9 @@ mod tests { }; let response = handle_scrape( + &core_udp_tracker_services.scrape_service, remote_addr, &request, - &core_tracker_services.scrape_handler, - &core_udp_tracker_services.udp_core_stats_event_sender, &server_udp_tracker_services.udp_server_stats_event_sender, sample_cookie_valid_range(), ) @@ -188,28 +180,28 @@ mod tests { } async fn add_a_sample_seeder_and_scrape( - in_memory_torrent_repository: Arc, - scrape_handler: Arc, + core_tracker_services: Arc, + core_udp_tracker_services: Arc, ) -> Response { - let (udp_core_stats_event_sender, _udp_core_stats_repository) = - bittorrent_udp_tracker_core::statistics::setup::factory(false); - let udp_core_stats_event_sender = Arc::new(udp_core_stats_event_sender); - let (udp_server_stats_event_sender, _udp_server_stats_repository) = crate::statistics::setup::factory(false); let udp_server_stats_event_sender = Arc::new(udp_server_stats_event_sender); let remote_addr = sample_ipv4_remote_addr(); let info_hash = InfoHash([0u8; 20]); - add_a_seeder(in_memory_torrent_repository.clone(), &remote_addr, &info_hash).await; + add_a_seeder( + core_tracker_services.in_memory_torrent_repository.clone(), + &remote_addr, + &info_hash, + ) + .await; let request = build_scrape_request(&remote_addr, &info_hash); handle_scrape( + &core_udp_tracker_services.scrape_service, remote_addr, &request, - &scrape_handler, - &udp_core_stats_event_sender, &udp_server_stats_event_sender, sample_cookie_valid_range(), ) @@ -232,15 +224,11 @@ mod tests { #[tokio::test] async fn should_return_torrent_statistics_when_the_tracker_has_the_requested_torrent() { - let (core_tracker_services, _core_udp_tracker_services, _server_udp_tracker_services) = + let (core_tracker_services, core_udp_tracker_services, _server_udp_tracker_services) = initialize_core_tracker_services_for_public_tracker(); let torrent_stats = match_scrape_response( - add_a_sample_seeder_and_scrape( - core_tracker_services.in_memory_torrent_repository.clone(), - core_tracker_services.scrape_handler.clone(), - ) - .await, + add_a_sample_seeder_and_scrape(core_tracker_services.into(), core_udp_tracker_services.into()).await, ); let expected_torrent_stats = vec![TorrentScrapeStatistics { @@ -285,10 +273,9 @@ mod tests { let torrent_stats = match_scrape_response( handle_scrape( + &core_udp_tracker_services.scrape_service, remote_addr, &request, - &core_tracker_services.scrape_handler, - &core_udp_tracker_services.udp_core_stats_event_sender, &server_udp_tracker_services.udp_server_stats_event_sender, sample_cookie_valid_range(), ) @@ -325,10 +312,9 @@ mod tests { let torrent_stats = match_scrape_response( handle_scrape( + &core_udp_tracker_services.scrape_service, remote_addr, &request, - &core_tracker_services.scrape_handler, - &core_udp_tracker_services.udp_core_stats_event_sender, &server_udp_tracker_services.udp_server_stats_event_sender, sample_cookie_valid_range(), ) @@ -358,28 +344,18 @@ mod tests { use std::future; use std::sync::Arc; - use bittorrent_udp_tracker_core::statistics as core_statistics; use mockall::predicate::eq; use super::sample_scrape_request; use crate::handlers::handle_scrape; use crate::handlers::tests::{ initialize_core_tracker_services_for_default_tracker_configuration, sample_cookie_valid_range, - sample_ipv4_remote_addr, MockUdpCoreStatsEventSender, MockUdpServerStatsEventSender, + sample_ipv4_remote_addr, MockUdpServerStatsEventSender, }; use crate::statistics as server_statistics; #[tokio::test] async fn should_send_the_upd4_scrape_event() { - let mut udp_core_stats_event_sender_mock = MockUdpCoreStatsEventSender::new(); - udp_core_stats_event_sender_mock - .expect_send_event() - .with(eq(core_statistics::event::Event::Udp4Scrape)) - .times(1) - .returning(|_| Box::pin(future::ready(Some(Ok(()))))); - let udp_core_stats_event_sender: Arc>> = - Arc::new(Some(Box::new(udp_core_stats_event_sender_mock))); - let mut udp_server_stats_event_sender_mock = MockUdpServerStatsEventSender::new(); udp_server_stats_event_sender_mock .expect_send_event() @@ -393,14 +369,13 @@ mod tests { let remote_addr = sample_ipv4_remote_addr(); - let (core_tracker_services, _core_udp_tracker_services, _server_udp_tracker_services) = + let (_core_tracker_services, core_udp_tracker_services, _server_udp_tracker_services) = initialize_core_tracker_services_for_default_tracker_configuration(); handle_scrape( + &core_udp_tracker_services.scrape_service, remote_addr, &sample_scrape_request(&remote_addr), - &core_tracker_services.scrape_handler, - &udp_core_stats_event_sender, &udp_server_stats_event_sender, sample_cookie_valid_range(), ) @@ -413,28 +388,18 @@ mod tests { use std::future; use std::sync::Arc; - use bittorrent_udp_tracker_core::statistics as core_statistics; use mockall::predicate::eq; use super::sample_scrape_request; use crate::handlers::handle_scrape; use crate::handlers::tests::{ initialize_core_tracker_services_for_default_tracker_configuration, sample_cookie_valid_range, - sample_ipv6_remote_addr, MockUdpCoreStatsEventSender, MockUdpServerStatsEventSender, + sample_ipv6_remote_addr, MockUdpServerStatsEventSender, }; use crate::statistics as server_statistics; #[tokio::test] async fn should_send_the_upd6_scrape_event() { - let mut udp_core_stats_event_sender_mock = MockUdpCoreStatsEventSender::new(); - udp_core_stats_event_sender_mock - .expect_send_event() - .with(eq(core_statistics::event::Event::Udp6Scrape)) - .times(1) - .returning(|_| Box::pin(future::ready(Some(Ok(()))))); - let udp_core_stats_event_sender: Arc>> = - Arc::new(Some(Box::new(udp_core_stats_event_sender_mock))); - let mut udp_server_stats_event_sender_mock = MockUdpServerStatsEventSender::new(); udp_server_stats_event_sender_mock .expect_send_event() @@ -448,14 +413,13 @@ mod tests { let remote_addr = sample_ipv6_remote_addr(); - let (core_tracker_services, _core_udp_tracker_services, _server_udp_tracker_services) = + let (_core_tracker_services, core_udp_tracker_services, _server_udp_tracker_services) = initialize_core_tracker_services_for_default_tracker_configuration(); handle_scrape( + &core_udp_tracker_services.scrape_service, remote_addr, &sample_scrape_request(&remote_addr), - &core_tracker_services.scrape_handler, - &udp_core_stats_event_sender, &udp_server_stats_event_sender, sample_cookie_valid_range(), ) diff --git a/src/container.rs b/src/container.rs index 4bdae1b29..07c30d604 100644 --- a/src/container.rs +++ b/src/container.rs @@ -1,6 +1,8 @@ use std::sync::Arc; use bittorrent_http_tracker_core::container::HttpTrackerCoreContainer; +use bittorrent_http_tracker_core::services::announce::AnnounceService; +use bittorrent_http_tracker_core::services::scrape::ScrapeService; use bittorrent_tracker_core::announce_handler::AnnounceHandler; use bittorrent_tracker_core::authentication::handler::KeysHandler; use bittorrent_tracker_core::authentication::service::AuthenticationService; @@ -22,6 +24,18 @@ use torrust_tracker_configuration::{Configuration, Core, HttpApi, HttpTracker, U use torrust_udp_tracker_server::container::UdpTrackerServerContainer; use tracing::instrument; +/* todo: remove duplicate code. + + Use containers from packages as AppContainer fields: + + - bittorrent_tracker_core::container::TrackerCoreContainer + - bittorrent_udp_tracker_core::container::UdpTrackerCoreContainer + - bittorrent_http_tracker_core::container::HttpTrackerCoreContainer + - torrust_udp_tracker_server::container::UdpTrackerServerContainer + + Container initialization is duplicated. +*/ + pub struct AppContainer { // Tracker Core Services pub core_config: Arc, @@ -38,13 +52,18 @@ pub struct AppContainer { pub torrents_manager: Arc, // UDP Tracker Core Services - pub ban_service: Arc>, pub udp_core_stats_event_sender: Arc>>, pub udp_core_stats_repository: Arc, + pub udp_ban_service: Arc>, + pub udp_connect_service: Arc, + pub udp_announce_service: Arc, + pub udp_scrape_service: Arc, // HTTP Tracker Core Services pub http_stats_event_sender: Arc>>, pub http_stats_repository: Arc, + pub http_announce_service: Arc, + pub http_scrape_service: Arc, // UDP Tracker Server Services pub udp_server_stats_event_sender: Arc>>, @@ -58,27 +77,52 @@ impl AppContainer { let tracker_core_container = TrackerCoreContainer::initialize(&core_config); - // HTTP core stats + // HTTP Tracker Core Services let (http_stats_event_sender, http_stats_repository) = bittorrent_http_tracker_core::statistics::setup::factory(configuration.core.tracker_usage_statistics); let http_stats_event_sender = Arc::new(http_stats_event_sender); let http_stats_repository = Arc::new(http_stats_repository); - - // UDP core stats + let http_announce_service = Arc::new(AnnounceService::new( + tracker_core_container.core_config.clone(), + tracker_core_container.announce_handler.clone(), + tracker_core_container.authentication_service.clone(), + tracker_core_container.whitelist_authorization.clone(), + http_stats_event_sender.clone(), + )); + let http_scrape_service = Arc::new(ScrapeService::new( + tracker_core_container.core_config.clone(), + tracker_core_container.scrape_handler.clone(), + tracker_core_container.authentication_service.clone(), + http_stats_event_sender.clone(), + )); + + // UDP Tracker Core Services let (udp_core_stats_event_sender, udp_core_stats_repository) = bittorrent_udp_tracker_core::statistics::setup::factory(configuration.core.tracker_usage_statistics); let udp_core_stats_event_sender = Arc::new(udp_core_stats_event_sender); let udp_core_stats_repository = Arc::new(udp_core_stats_repository); - - let ban_service = Arc::new(RwLock::new(BanService::new(MAX_CONNECTION_ID_ERRORS_PER_IP))); - - // UDP server stats + let udp_ban_service = Arc::new(RwLock::new(BanService::new(MAX_CONNECTION_ID_ERRORS_PER_IP))); + let udp_connect_service = Arc::new(bittorrent_udp_tracker_core::services::connect::ConnectService::new( + udp_core_stats_event_sender.clone(), + )); + let udp_announce_service = Arc::new(bittorrent_udp_tracker_core::services::announce::AnnounceService::new( + tracker_core_container.announce_handler.clone(), + tracker_core_container.whitelist_authorization.clone(), + udp_core_stats_event_sender.clone(), + )); + let udp_scrape_service = Arc::new(bittorrent_udp_tracker_core::services::scrape::ScrapeService::new( + tracker_core_container.scrape_handler.clone(), + udp_core_stats_event_sender.clone(), + )); + + // UDP Tracker Server Services let (udp_server_stats_event_sender, udp_server_stats_repository) = torrust_udp_tracker_server::statistics::setup::factory(configuration.core.tracker_usage_statistics); let udp_server_stats_event_sender = Arc::new(udp_server_stats_event_sender); let udp_server_stats_repository = Arc::new(udp_server_stats_repository); AppContainer { + // Tracker Core Services core_config, database: tracker_core_container.database, announce_handler: tracker_core_container.announce_handler, @@ -91,11 +135,22 @@ impl AppContainer { in_memory_torrent_repository: tracker_core_container.in_memory_torrent_repository, db_torrent_repository: tracker_core_container.db_torrent_repository, torrents_manager: tracker_core_container.torrents_manager, - ban_service, - http_stats_event_sender, + + // UDP Tracker Core Services udp_core_stats_event_sender, - http_stats_repository, udp_core_stats_repository, + udp_ban_service, + udp_connect_service, + udp_announce_service, + udp_scrape_service, + + // HTTP Tracker Core Services + http_stats_event_sender, + http_stats_repository, + http_announce_service, + http_scrape_service, + + // UDP Tracker Server Services udp_server_stats_event_sender, udp_server_stats_repository, } @@ -113,6 +168,8 @@ impl AppContainer { http_tracker_config: http_tracker_config.clone(), http_stats_event_sender: self.http_stats_event_sender.clone(), http_stats_repository: self.http_stats_repository.clone(), + announce_service: self.http_announce_service.clone(), + scrape_service: self.http_scrape_service.clone(), } } @@ -127,7 +184,10 @@ impl AppContainer { udp_tracker_config: udp_tracker_config.clone(), udp_core_stats_event_sender: self.udp_core_stats_event_sender.clone(), udp_core_stats_repository: self.udp_core_stats_repository.clone(), - ban_service: self.ban_service.clone(), + ban_service: self.udp_ban_service.clone(), + connect_service: self.udp_connect_service.clone(), + announce_service: self.udp_announce_service.clone(), + scrape_service: self.udp_scrape_service.clone(), } } @@ -139,7 +199,7 @@ impl AppContainer { in_memory_torrent_repository: self.in_memory_torrent_repository.clone(), keys_handler: self.keys_handler.clone(), whitelist_manager: self.whitelist_manager.clone(), - ban_service: self.ban_service.clone(), + ban_service: self.udp_ban_service.clone(), http_stats_repository: self.http_stats_repository.clone(), udp_core_stats_repository: self.udp_core_stats_repository.clone(), udp_server_stats_repository: self.udp_server_stats_repository.clone(),