diff --git a/console/tracker-client/src/console/clients/checker/checks/http.rs b/console/tracker-client/src/console/clients/checker/checks/http.rs index 0fd37ca48..1a69d9c22 100644 --- a/console/tracker-client/src/console/clients/checker/checks/http.rs +++ b/console/tracker-client/src/console/clients/checker/checks/http.rs @@ -61,7 +61,7 @@ pub async fn run(http_trackers: Vec, timeout: Duration) -> Vec Result { - let info_hash_str = "9c38422213e30bff212b30c360d26f9a02136422".to_string(); // # DevSkim: ignore DS173237 + let info_hash_str = "9c38422213e30bff212b30c360d26f9a02136422".to_string(); // DevSkim: ignore DS173237 let info_hash = InfoHash::from_str(&info_hash_str).expect("a valid info-hash is required"); let client = Client::new(url.clone(), timeout).map_err(|err| Error::HttpClientError { err })?; @@ -86,7 +86,7 @@ async fn check_http_announce(url: &Url, timeout: Duration) -> Result Result { - let info_hashes: Vec = vec!["9c38422213e30bff212b30c360d26f9a02136422".to_string()]; // # DevSkim: ignore DS173237 + let info_hashes: Vec = vec!["9c38422213e30bff212b30c360d26f9a02136422".to_string()]; // DevSkim: ignore DS173237 let query = requests::scrape::Query::try_from(info_hashes).expect("a valid array of info-hashes is required"); let client = Client::new(url.clone(), timeout).map_err(|err| Error::HttpClientError { err })?; diff --git a/console/tracker-client/src/console/clients/checker/checks/udp.rs b/console/tracker-client/src/console/clients/checker/checks/udp.rs index 21bdcd1b7..b4edb2e2c 100644 --- a/console/tracker-client/src/console/clients/checker/checks/udp.rs +++ b/console/tracker-client/src/console/clients/checker/checks/udp.rs @@ -29,7 +29,7 @@ pub async fn run(udp_trackers: Vec, timeout: Duration) -> Vec QueryBuilder { let default_announce_query = Query { - info_hash: InfoHash::from_str("9c38422213e30bff212b30c360d26f9a02136422").unwrap().0, // # DevSkim: ignore DS173237 + info_hash: InfoHash::from_str("9c38422213e30bff212b30c360d26f9a02136422").unwrap().0, // DevSkim: ignore DS173237 peer_addr: IpAddr::V4(Ipv4Addr::new(192, 168, 1, 88)), downloaded: 0, uploaded: 0, diff --git a/packages/tracker-client/src/http/client/requests/scrape.rs b/packages/tracker-client/src/http/client/requests/scrape.rs index 1b423390b..b25c3c4c7 100644 --- a/packages/tracker-client/src/http/client/requests/scrape.rs +++ b/packages/tracker-client/src/http/client/requests/scrape.rs @@ -90,7 +90,7 @@ pub struct QueryBuilder { impl Default for QueryBuilder { fn default() -> Self { let default_scrape_query = Query { - info_hash: [InfoHash::from_str("9c38422213e30bff212b30c360d26f9a02136422").unwrap().0].to_vec(), // # DevSkim: ignore DS173237 + info_hash: [InfoHash::from_str("9c38422213e30bff212b30c360d26f9a02136422").unwrap().0].to_vec(), // DevSkim: ignore DS173237 }; Self { scrape_query: default_scrape_query, diff --git a/src/app.rs b/src/app.rs index 75c2e13bc..13bdc904a 100644 --- a/src/app.rs +++ b/src/app.rs @@ -28,7 +28,7 @@ use torrust_tracker_configuration::Configuration; use tracing::instrument; use crate::bootstrap::jobs::{health_check_api, http_tracker, torrent_cleanup, tracker_apis, udp_tracker}; -use crate::container::AppContainer; +use crate::container::{AppContainer, HttpApiContainer, HttpTrackerContainer, UdpTrackerContainer}; use crate::servers; use crate::servers::registar::Registar; @@ -39,7 +39,7 @@ use crate::servers::registar::Registar; /// - Can't retrieve tracker keys from database. /// - Can't load whitelist from database. #[instrument(skip(config, app_container))] -pub async fn start(config: &Configuration, app_container: &AppContainer) -> Vec> { +pub async fn start(config: &Configuration, app_container: &Arc) -> Vec> { if config.http_api.is_none() && (config.udp_trackers.is_none() || config.udp_trackers.as_ref().map_or(true, std::vec::Vec::is_empty)) && (config.http_trackers.is_none() || config.http_trackers.as_ref().map_or(true, std::vec::Vec::is_empty)) @@ -78,19 +78,10 @@ pub async fn start(config: &Configuration, app_container: &AppContainer) -> Vec< udp_tracker_config.bind_address ); } else { - jobs.push( - udp_tracker::start_job( - Arc::new(config.core.clone()), - udp_tracker_config, - app_container.announce_handler.clone(), - app_container.scrape_handler.clone(), - app_container.whitelist_authorization.clone(), - app_container.stats_event_sender.clone(), - app_container.ban_service.clone(), - registar.give_form(), - ) - .await, - ); + let udp_tracker_config = Arc::new(udp_tracker_config.clone()); + let udp_tracker_container = Arc::new(UdpTrackerContainer::from_app_container(&udp_tracker_config, app_container)); + + jobs.push(udp_tracker::start_job(udp_tracker_container, registar.give_form()).await); } } } else { @@ -100,18 +91,11 @@ pub async fn start(config: &Configuration, app_container: &AppContainer) -> Vec< // Start the HTTP blocks if let Some(http_trackers) = &config.http_trackers { for http_tracker_config in http_trackers { - if let Some(job) = http_tracker::start_job( - http_tracker_config, - Arc::new(config.core.clone()), - app_container.announce_handler.clone(), - app_container.scrape_handler.clone(), - app_container.authentication_service.clone(), - app_container.whitelist_authorization.clone(), - app_container.stats_event_sender.clone(), - registar.give_form(), - servers::http::Version::V1, - ) - .await + let http_tracker_config = Arc::new(http_tracker_config.clone()); + let http_tracker_container = Arc::new(HttpTrackerContainer::from_app_container(&http_tracker_config, app_container)); + + if let Some(job) = + http_tracker::start_job(http_tracker_container, registar.give_form(), servers::http::Version::V1).await { jobs.push(job); }; @@ -122,19 +106,10 @@ pub async fn start(config: &Configuration, app_container: &AppContainer) -> Vec< // Start HTTP API if let Some(http_api_config) = &config.http_api { - if let Some(job) = tracker_apis::start_job( - http_api_config, - app_container.in_memory_torrent_repository.clone(), - app_container.keys_handler.clone(), - app_container.whitelist_manager.clone(), - app_container.ban_service.clone(), - app_container.stats_event_sender.clone(), - app_container.stats_repository.clone(), - registar.give_form(), - servers::apis::Version::V1, - ) - .await - { + let http_api_config = Arc::new(http_api_config.clone()); + let http_api_container = Arc::new(HttpApiContainer::from_app_container(&http_api_config, app_container)); + + if let Some(job) = tracker_apis::start_job(http_api_container, registar.give_form(), servers::apis::Version::V1).await { jobs.push(job); }; } else { diff --git a/src/bootstrap/app.rs b/src/bootstrap/app.rs index c69162322..71684a7e3 100644 --- a/src/bootstrap/app.rs +++ b/src/bootstrap/app.rs @@ -32,7 +32,7 @@ use crate::core::services::{initialize_database, initialize_whitelist_manager, s use crate::core::torrent::manager::TorrentsManager; use crate::core::torrent::repository::in_memory::InMemoryTorrentRepository; use crate::core::torrent::repository::persisted::DatabasePersistentTorrentRepository; -use crate::core::whitelist; +use crate::core::whitelist::authorization::WhitelistAuthorization; use crate::core::whitelist::repository::in_memory::InMemoryWhitelist; use crate::servers::udp::server::banning::BanService; use crate::servers::udp::server::launcher::MAX_CONNECTION_ID_ERRORS_PER_IP; @@ -87,16 +87,14 @@ pub fn initialize_global_services(configuration: &Configuration) { /// It initializes the IoC Container. #[instrument(skip())] pub fn initialize_app_container(configuration: &Configuration) -> AppContainer { + let core_config = Arc::new(configuration.core.clone()); let (stats_event_sender, stats_repository) = statistics::setup::factory(configuration.core.tracker_usage_statistics); let stats_event_sender = Arc::new(stats_event_sender); let stats_repository = Arc::new(stats_repository); let ban_service = Arc::new(RwLock::new(BanService::new(MAX_CONNECTION_ID_ERRORS_PER_IP))); let database = initialize_database(configuration); let in_memory_whitelist = Arc::new(InMemoryWhitelist::default()); - let whitelist_authorization = Arc::new(whitelist::authorization::WhitelistAuthorization::new( - &configuration.core, - &in_memory_whitelist.clone(), - )); + let whitelist_authorization = Arc::new(WhitelistAuthorization::new(&configuration.core, &in_memory_whitelist.clone())); let whitelist_manager = initialize_whitelist_manager(database.clone(), in_memory_whitelist.clone()); let db_key_repository = Arc::new(DatabaseKeyRepository::new(&database)); let in_memory_key_repository = Arc::new(InMemoryKeyRepository::default()); @@ -125,6 +123,7 @@ pub fn initialize_app_container(configuration: &Configuration) -> AppContainer { let scrape_handler = Arc::new(ScrapeHandler::new(&whitelist_authorization, &in_memory_torrent_repository)); AppContainer { + core_config, database, announce_handler, scrape_handler, diff --git a/src/bootstrap/jobs/http_tracker.rs b/src/bootstrap/jobs/http_tracker.rs index dc6ed6b60..83cc0ae02 100644 --- a/src/bootstrap/jobs/http_tracker.rs +++ b/src/bootstrap/jobs/http_tracker.rs @@ -15,15 +15,10 @@ use std::sync::Arc; use axum_server::tls_rustls::RustlsConfig; use tokio::task::JoinHandle; -use torrust_tracker_configuration::{Core, HttpTracker}; use tracing::instrument; use super::make_rust_tls; -use crate::core::announce_handler::AnnounceHandler; -use crate::core::authentication::service::AuthenticationService; -use crate::core::scrape_handler::ScrapeHandler; -use crate::core::statistics::event::sender::Sender; -use crate::core::{statistics, whitelist}; +use crate::container::HttpTrackerContainer; use crate::servers::http::server::{HttpServer, Launcher}; use crate::servers::http::Version; use crate::servers::registar::ServiceRegistrationForm; @@ -36,83 +31,33 @@ use crate::servers::registar::ServiceRegistrationForm; /// # Panics /// /// It would panic if the `config::HttpTracker` struct would contain inappropriate values. -#[allow(clippy::too_many_arguments)] -#[instrument(skip( - config, - announce_handler, - scrape_handler, - authentication_service, - whitelist_authorization, - stats_event_sender, - form -))] +#[instrument(skip(http_tracker_container, form))] pub async fn start_job( - config: &HttpTracker, - core_config: Arc, - announce_handler: Arc, - scrape_handler: Arc, - authentication_service: Arc, - whitelist_authorization: Arc, - stats_event_sender: Arc>>, + http_tracker_container: Arc, form: ServiceRegistrationForm, version: Version, ) -> Option> { - let socket = config.bind_address; + let socket = http_tracker_container.http_tracker_config.bind_address; - let tls = make_rust_tls(&config.tsl_config) + let tls = make_rust_tls(&http_tracker_container.http_tracker_config.tsl_config) .await .map(|tls| tls.expect("it should have a valid http tracker tls configuration")); match version { - Version::V1 => Some( - start_v1( - socket, - tls, - core_config.clone(), - announce_handler.clone(), - scrape_handler.clone(), - authentication_service.clone(), - whitelist_authorization.clone(), - stats_event_sender.clone(), - form, - ) - .await, - ), + Version::V1 => Some(start_v1(socket, tls, http_tracker_container, form).await), } } -#[allow(clippy::too_many_arguments)] #[allow(clippy::async_yields_async)] -#[instrument(skip( - socket, - tls, - announce_handler, - scrape_handler, - whitelist_authorization, - stats_event_sender, - form -))] +#[instrument(skip(socket, tls, http_tracker_container, form))] async fn start_v1( socket: SocketAddr, tls: Option, - config: Arc, - announce_handler: Arc, - scrape_handler: Arc, - authentication_service: Arc, - whitelist_authorization: Arc, - stats_event_sender: Arc>>, + http_tracker_container: Arc, form: ServiceRegistrationForm, ) -> JoinHandle<()> { let server = HttpServer::new(Launcher::new(socket, tls)) - .start( - config, - announce_handler, - scrape_handler, - authentication_service, - whitelist_authorization, - stats_event_sender, - form, - ) + .start(http_tracker_container, form) .await .expect("it should be able to start to the http tracker"); @@ -137,6 +82,7 @@ mod tests { use crate::bootstrap::app::{initialize_app_container, initialize_global_services}; use crate::bootstrap::jobs::http_tracker::start_job; + use crate::container::HttpTrackerContainer; use crate::servers::http::Version; use crate::servers::registar::Registar; @@ -144,26 +90,18 @@ mod tests { async fn it_should_start_http_tracker() { let cfg = Arc::new(ephemeral_public()); let http_tracker = cfg.http_trackers.clone().expect("missing HTTP tracker configuration"); - let config = &http_tracker[0]; + let http_tracker_config = Arc::new(http_tracker[0].clone()); initialize_global_services(&cfg); - let app_container = initialize_app_container(&cfg); + let app_container = Arc::new(initialize_app_container(&cfg)); + + let http_tracker_container = Arc::new(HttpTrackerContainer::from_app_container(&http_tracker_config, &app_container)); let version = Version::V1; - start_job( - config, - Arc::new(cfg.core.clone()), - app_container.announce_handler, - app_container.scrape_handler, - app_container.authentication_service, - app_container.whitelist_authorization, - app_container.stats_event_sender, - Registar::default().give_form(), - version, - ) - .await - .expect("it should be able to join to the http tracker start-job"); + start_job(http_tracker_container, Registar::default().give_form(), version) + .await + .expect("it should be able to join to the http tracker start-job"); } } diff --git a/src/bootstrap/jobs/tracker_apis.rs b/src/bootstrap/jobs/tracker_apis.rs index ce6f3912c..cee6cbae2 100644 --- a/src/bootstrap/jobs/tracker_apis.rs +++ b/src/bootstrap/jobs/tracker_apis.rs @@ -24,21 +24,15 @@ use std::net::SocketAddr; use std::sync::Arc; use axum_server::tls_rustls::RustlsConfig; -use tokio::sync::RwLock; use tokio::task::JoinHandle; -use torrust_tracker_configuration::{AccessTokens, HttpApi}; +use torrust_tracker_configuration::AccessTokens; use tracing::instrument; use super::make_rust_tls; -use crate::core::authentication::handler::KeysHandler; -use crate::core::statistics::event::sender::Sender; -use crate::core::statistics::repository::Repository; -use crate::core::torrent::repository::in_memory::InMemoryTorrentRepository; -use crate::core::whitelist::manager::WhitelistManager; +use crate::container::HttpApiContainer; use crate::servers::apis::server::{ApiServer, Launcher}; use crate::servers::apis::Version; use crate::servers::registar::ServiceRegistrationForm; -use crate::servers::udp::server::banning::BanService; /// This is the message that the "launcher" spawned task sends to the main /// application process to notify the API server was successfully started. @@ -60,90 +54,36 @@ pub struct ApiServerJobStarted(); /// It would panic if unable to send the `ApiServerJobStarted` notice. /// /// -#[allow(clippy::too_many_arguments)] -#[instrument(skip( - config, - keys_handler, - whitelist_manager, - ban_service, - stats_event_sender, - stats_repository, - form -))] +#[instrument(skip(http_api_container, form))] pub async fn start_job( - config: &HttpApi, - in_memory_torrent_repository: Arc, - keys_handler: Arc, - whitelist_manager: Arc, - ban_service: Arc>, - stats_event_sender: Arc>>, - stats_repository: Arc, + http_api_container: Arc, form: ServiceRegistrationForm, version: Version, ) -> Option> { - let bind_to = config.bind_address; + let bind_to = http_api_container.http_api_config.bind_address; - let tls = make_rust_tls(&config.tsl_config) + let tls = make_rust_tls(&http_api_container.http_api_config.tsl_config) .await .map(|tls| tls.expect("it should have a valid tracker api tls configuration")); - let access_tokens = Arc::new(config.access_tokens.clone()); + let access_tokens = Arc::new(http_api_container.http_api_config.access_tokens.clone()); match version { - Version::V1 => Some( - start_v1( - bind_to, - tls, - in_memory_torrent_repository.clone(), - keys_handler.clone(), - whitelist_manager.clone(), - ban_service.clone(), - stats_event_sender.clone(), - stats_repository.clone(), - form, - access_tokens, - ) - .await, - ), + Version::V1 => Some(start_v1(bind_to, tls, http_api_container, form, access_tokens).await), } } #[allow(clippy::async_yields_async)] -#[allow(clippy::too_many_arguments)] -#[instrument(skip( - socket, - tls, - keys_handler, - whitelist_manager, - ban_service, - stats_event_sender, - stats_repository, - form, - access_tokens -))] +#[instrument(skip(socket, tls, http_api_container, form, access_tokens))] async fn start_v1( socket: SocketAddr, tls: Option, - in_memory_torrent_repository: Arc, - keys_handler: Arc, - whitelist_manager: Arc, - ban_service: Arc>, - stats_event_sender: Arc>>, - stats_repository: Arc, + http_api_container: Arc, form: ServiceRegistrationForm, access_tokens: Arc, ) -> JoinHandle<()> { let server = ApiServer::new(Launcher::new(socket, tls)) - .start( - in_memory_torrent_repository, - keys_handler, - whitelist_manager, - stats_event_sender, - stats_repository, - ban_service, - form, - access_tokens, - ) + .start(http_api_container, form, access_tokens) .await .expect("it should be able to start to the tracker api"); @@ -161,32 +101,25 @@ mod tests { use crate::bootstrap::app::{initialize_app_container, initialize_global_services}; use crate::bootstrap::jobs::tracker_apis::start_job; + use crate::container::HttpApiContainer; use crate::servers::apis::Version; use crate::servers::registar::Registar; #[tokio::test] async fn it_should_start_http_tracker() { let cfg = Arc::new(ephemeral_public()); - let config = &cfg.http_api.clone().unwrap(); + let http_api_config = Arc::new(cfg.http_api.clone().unwrap()); initialize_global_services(&cfg); - let app_container = initialize_app_container(&cfg); + let app_container = Arc::new(initialize_app_container(&cfg)); + + let http_api_container = Arc::new(HttpApiContainer::from_app_container(&http_api_config, &app_container)); let version = Version::V1; - start_job( - config, - app_container.in_memory_torrent_repository, - app_container.keys_handler, - app_container.whitelist_manager, - app_container.ban_service, - app_container.stats_event_sender, - app_container.stats_repository, - Registar::default().give_form(), - version, - ) - .await - .expect("it should be able to join to the tracker api start-job"); + start_job(http_api_container, Registar::default().give_form(), version) + .await + .expect("it should be able to join to the tracker api start-job"); } } diff --git a/src/bootstrap/jobs/udp_tracker.rs b/src/bootstrap/jobs/udp_tracker.rs index 4f54ecb59..387fdd6ae 100644 --- a/src/bootstrap/jobs/udp_tracker.rs +++ b/src/bootstrap/jobs/udp_tracker.rs @@ -8,17 +8,11 @@ //! > for the configuration options. use std::sync::Arc; -use tokio::sync::RwLock; use tokio::task::JoinHandle; -use torrust_tracker_configuration::{Core, UdpTracker}; use tracing::instrument; -use crate::core::announce_handler::AnnounceHandler; -use crate::core::scrape_handler::ScrapeHandler; -use crate::core::statistics::event::sender::Sender; -use crate::core::whitelist; +use crate::container::UdpTrackerContainer; use crate::servers::registar::ServiceRegistrationForm; -use crate::servers::udp::server::banning::BanService; use crate::servers::udp::server::spawner::Spawner; use crate::servers::udp::server::Server; use crate::servers::udp::UDP_TRACKER_LOG_TARGET; @@ -33,41 +27,14 @@ use crate::servers::udp::UDP_TRACKER_LOG_TARGET; /// It will panic if it is unable to start the UDP service. /// It will panic if the task did not finish successfully. #[must_use] -#[allow(clippy::too_many_arguments)] #[allow(clippy::async_yields_async)] -#[instrument(skip( - config, - announce_handler, - scrape_handler, - whitelist_authorization, - stats_event_sender, - ban_service, - form -))] -pub async fn start_job( - core_config: Arc, - config: &UdpTracker, - announce_handler: Arc, - scrape_handler: Arc, - whitelist_authorization: Arc, - stats_event_sender: Arc>>, - ban_service: Arc>, - form: ServiceRegistrationForm, -) -> JoinHandle<()> { - let bind_to = config.bind_address; - let cookie_lifetime = config.cookie_lifetime; +#[instrument(skip(udp_tracker_container, form))] +pub async fn start_job(udp_tracker_container: Arc, form: ServiceRegistrationForm) -> JoinHandle<()> { + let bind_to = udp_tracker_container.udp_tracker_config.bind_address; + let cookie_lifetime = udp_tracker_container.udp_tracker_config.cookie_lifetime; let server = Server::new(Spawner::new(bind_to)) - .start( - core_config, - announce_handler, - scrape_handler, - whitelist_authorization, - stats_event_sender, - ban_service, - form, - cookie_lifetime, - ) + .start(udp_tracker_container, form, cookie_lifetime) .await .expect("it should be able to start the udp tracker"); diff --git a/src/console/profiling.rs b/src/console/profiling.rs index 318fce1e8..f3829c073 100644 --- a/src/console/profiling.rs +++ b/src/console/profiling.rs @@ -157,6 +157,7 @@ //! kcachegrind callgrind.out //! ``` use std::env; +use std::sync::Arc; use std::time::Duration; use tokio::time::sleep; @@ -181,6 +182,8 @@ pub async fn run() { let (config, app_container) = bootstrap::app::setup(); + let app_container = Arc::new(app_container); + let jobs = app::start(&config, &app_container).await; // Run the tracker for a fixed duration diff --git a/src/container.rs b/src/container.rs index 192fa62f1..1a2a029ee 100644 --- a/src/container.rs +++ b/src/container.rs @@ -1,6 +1,7 @@ use std::sync::Arc; use tokio::sync::RwLock; +use torrust_tracker_configuration::{Core, HttpApi, HttpTracker, UdpTracker}; use crate::core::announce_handler::AnnounceHandler; use crate::core::authentication::handler::KeysHandler; @@ -17,6 +18,7 @@ use crate::core::whitelist::manager::WhitelistManager; use crate::servers::udp::server::banning::BanService; pub struct AppContainer { + pub core_config: Arc, pub database: Arc>, pub announce_handler: Arc, pub scrape_handler: Arc, @@ -31,3 +33,80 @@ pub struct AppContainer { pub db_torrent_repository: Arc, pub torrents_manager: Arc, } + +pub struct UdpTrackerContainer { + pub core_config: Arc, + pub udp_tracker_config: Arc, + pub announce_handler: Arc, + pub scrape_handler: Arc, + pub whitelist_authorization: Arc, + pub stats_event_sender: Arc>>, + pub ban_service: Arc>, +} + +impl UdpTrackerContainer { + #[must_use] + pub fn from_app_container(udp_tracker_config: &Arc, app_container: &Arc) -> Self { + Self { + udp_tracker_config: udp_tracker_config.clone(), + core_config: app_container.core_config.clone(), + announce_handler: app_container.announce_handler.clone(), + scrape_handler: app_container.scrape_handler.clone(), + whitelist_authorization: app_container.whitelist_authorization.clone(), + stats_event_sender: app_container.stats_event_sender.clone(), + ban_service: app_container.ban_service.clone(), + } + } +} + +pub struct HttpTrackerContainer { + pub core_config: Arc, + pub http_tracker_config: Arc, + pub announce_handler: Arc, + pub scrape_handler: Arc, + pub whitelist_authorization: Arc, + pub stats_event_sender: Arc>>, + pub authentication_service: Arc, +} + +impl HttpTrackerContainer { + #[must_use] + pub fn from_app_container(http_tracker_config: &Arc, app_container: &Arc) -> Self { + Self { + http_tracker_config: http_tracker_config.clone(), + core_config: app_container.core_config.clone(), + announce_handler: app_container.announce_handler.clone(), + scrape_handler: app_container.scrape_handler.clone(), + whitelist_authorization: app_container.whitelist_authorization.clone(), + stats_event_sender: app_container.stats_event_sender.clone(), + authentication_service: app_container.authentication_service.clone(), + } + } +} + +pub struct HttpApiContainer { + pub core_config: Arc, + pub http_api_config: Arc, + pub in_memory_torrent_repository: Arc, + pub keys_handler: Arc, + pub whitelist_manager: Arc, + pub ban_service: Arc>, + pub stats_event_sender: Arc>>, + pub stats_repository: Arc, +} + +impl HttpApiContainer { + #[must_use] + pub fn from_app_container(http_api_config: &Arc, app_container: &Arc) -> Self { + Self { + http_api_config: http_api_config.clone(), + core_config: app_container.core_config.clone(), + in_memory_torrent_repository: app_container.in_memory_torrent_repository.clone(), + keys_handler: app_container.keys_handler.clone(), + whitelist_manager: app_container.whitelist_manager.clone(), + ban_service: app_container.ban_service.clone(), + stats_event_sender: app_container.stats_event_sender.clone(), + stats_repository: app_container.stats_repository.clone(), + } + } +} diff --git a/src/core/mod.rs b/src/core/mod.rs index 77d8e1450..7d5e7d4d6 100644 --- a/src/core/mod.rs +++ b/src/core/mod.rs @@ -498,7 +498,7 @@ mod tests { async fn it_should_return_the_swarm_metadata_for_the_requested_file_if_the_tracker_has_that_torrent() { let (announce_handler, scrape_handler) = initialize_handlers_for_public_tracker(); - let info_hash = "3b245504cf5f11bbdbe1201cea6a6bf45aee1bc0".parse::().unwrap(); // # DevSkim: ignore DS173237 + let info_hash = "3b245504cf5f11bbdbe1201cea6a6bf45aee1bc0".parse::().unwrap(); // DevSkim: ignore DS173237 // Announce a "complete" peer for the torrent let mut complete_peer = complete_peer(); @@ -553,7 +553,7 @@ mod tests { async fn it_should_return_the_zeroed_swarm_metadata_for_the_requested_file_if_it_is_not_whitelisted() { let (announce_handler, scrape_handler) = initialize_handlers_for_listed_tracker(); - let info_hash = "3b245504cf5f11bbdbe1201cea6a6bf45aee1bc0".parse::().unwrap(); // # DevSkim: ignore DS173237 + let info_hash = "3b245504cf5f11bbdbe1201cea6a6bf45aee1bc0".parse::().unwrap(); // DevSkim: ignore DS173237 let mut peer = incomplete_peer(); announce_handler.announce(&info_hash, &mut peer, &peer_ip(), &PeersWanted::All); diff --git a/src/core/scrape_handler.rs b/src/core/scrape_handler.rs index 7de82aa06..33bb6ca6a 100644 --- a/src/core/scrape_handler.rs +++ b/src/core/scrape_handler.rs @@ -75,7 +75,7 @@ mod tests { async fn it_should_return_a_zeroed_swarm_metadata_for_the_requested_file_if_the_tracker_does_not_have_that_torrent() { let scrape_handler = scrape_handler(); - let info_hashes = vec!["3b245504cf5f11bbdbe1201cea6a6bf45aee1bc0".parse::().unwrap()]; // # DevSkim: ignore DS173237 + let info_hashes = vec!["3b245504cf5f11bbdbe1201cea6a6bf45aee1bc0".parse::().unwrap()]; // DevSkim: ignore DS173237 let scrape_data = scrape_handler.scrape(&info_hashes).await; @@ -91,8 +91,8 @@ mod tests { let scrape_handler = scrape_handler(); let info_hashes = vec![ - "3b245504cf5f11bbdbe1201cea6a6bf45aee1bc0".parse::().unwrap(), // # DevSkim: ignore DS173237 - "99c82bb73505a3c0b453f9fa0e881d6e5a32a0c1".parse::().unwrap(), // # DevSkim: ignore DS173237 + "3b245504cf5f11bbdbe1201cea6a6bf45aee1bc0".parse::().unwrap(), // DevSkim: ignore DS173237 + "99c82bb73505a3c0b453f9fa0e881d6e5a32a0c1".parse::().unwrap(), // DevSkim: ignore DS173237 ]; let scrape_data = scrape_handler.scrape(&info_hashes).await; diff --git a/src/core/services/torrent.rs b/src/core/services/torrent.rs index d809fc266..dac93ce16 100644 --- a/src/core/services/torrent.rs +++ b/src/core/services/torrent.rs @@ -145,7 +145,7 @@ mod tests { let torrent_info = get_torrent_info( in_memory_torrent_repository.clone(), - &InfoHash::from_str("0b3aea4adc213ce32295be85d3883a63bca25446").unwrap(), + &InfoHash::from_str("0b3aea4adc213ce32295be85d3883a63bca25446").unwrap(), // DevSkim: ignore DS173237 ) .await; @@ -156,7 +156,7 @@ mod tests { async fn should_return_the_torrent_info_if_the_tracker_has_the_torrent() { let in_memory_torrent_repository = Arc::new(InMemoryTorrentRepository::default()); - let hash = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); + let hash = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); // DevSkim: ignore DS173237 let info_hash = InfoHash::from_str(&hash).unwrap(); let () = in_memory_torrent_repository.upsert_peer(&info_hash, &sample_peer()); @@ -201,7 +201,7 @@ mod tests { async fn should_return_a_summarized_info_for_all_torrents() { let in_memory_torrent_repository = Arc::new(InMemoryTorrentRepository::default()); - let hash = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); + let hash = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); // DevSkim: ignore DS173237 let info_hash = InfoHash::from_str(&hash).unwrap(); let () = in_memory_torrent_repository.upsert_peer(&info_hash, &sample_peer()); @@ -223,7 +223,7 @@ mod tests { async fn should_allow_limiting_the_number_of_torrents_in_the_result() { let in_memory_torrent_repository = Arc::new(InMemoryTorrentRepository::default()); - let hash1 = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); + let hash1 = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); // DevSkim: ignore DS173237 let info_hash1 = InfoHash::from_str(&hash1).unwrap(); let hash2 = "03840548643af2a7b63a9f5cbca348bc7150ca3a".to_owned(); @@ -244,7 +244,7 @@ mod tests { async fn should_allow_using_pagination_in_the_result() { let in_memory_torrent_repository = Arc::new(InMemoryTorrentRepository::default()); - let hash1 = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); + let hash1 = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); // DevSkim: ignore DS173237 let info_hash1 = InfoHash::from_str(&hash1).unwrap(); let hash2 = "03840548643af2a7b63a9f5cbca348bc7150ca3a".to_owned(); @@ -274,7 +274,7 @@ mod tests { async fn should_return_torrents_ordered_by_info_hash() { let in_memory_torrent_repository = Arc::new(InMemoryTorrentRepository::default()); - let hash1 = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); + let hash1 = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); // DevSkim: ignore DS173237 let info_hash1 = InfoHash::from_str(&hash1).unwrap(); let () = in_memory_torrent_repository.upsert_peer(&info_hash1, &sample_peer()); diff --git a/src/main.rs b/src/main.rs index f05de0327..77f6e32a3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,13 @@ +use std::sync::Arc; + use torrust_tracker_lib::{app, bootstrap}; #[tokio::main] async fn main() { let (config, app_container) = bootstrap::app::setup(); + let app_container = Arc::new(app_container); + let jobs = app::start(&config, &app_container).await; // handle the signals diff --git a/src/servers/apis/routes.rs b/src/servers/apis/routes.rs index 92ecb067d..137975259 100644 --- a/src/servers/apis/routes.rs +++ b/src/servers/apis/routes.rs @@ -15,7 +15,6 @@ use axum::response::Response; use axum::routing::get; use axum::{middleware, BoxError, Router}; use hyper::{Request, StatusCode}; -use tokio::sync::RwLock; use torrust_tracker_configuration::{AccessTokens, DEFAULT_TIMEOUT}; use tower::timeout::TimeoutLayer; use tower::ServiceBuilder; @@ -30,33 +29,14 @@ use tracing::{instrument, Level, Span}; use super::v1; use super::v1::context::health_check::handlers::health_check_handler; use super::v1::middlewares::auth::State; -use crate::core::authentication::handler::KeysHandler; -use crate::core::statistics::event::sender::Sender; -use crate::core::statistics::repository::Repository; -use crate::core::torrent::repository::in_memory::InMemoryTorrentRepository; -use crate::core::whitelist::manager::WhitelistManager; +use crate::container::HttpApiContainer; use crate::servers::apis::API_LOG_TARGET; use crate::servers::logging::Latency; -use crate::servers::udp::server::banning::BanService; /// Add all API routes to the router. -#[allow(clippy::too_many_arguments)] -#[allow(clippy::needless_pass_by_value)] -#[instrument(skip( - keys_handler, - whitelist_manager, - ban_service, - stats_event_sender, - stats_repository, - access_tokens -))] +#[instrument(skip(http_api_container, access_tokens))] pub fn router( - in_memory_torrent_repository: Arc, - keys_handler: Arc, - whitelist_manager: Arc, - ban_service: Arc>, - stats_event_sender: Arc>>, - stats_repository: Arc, + http_api_container: Arc, access_tokens: Arc, server_socket_addr: SocketAddr, ) -> Router { @@ -64,16 +44,7 @@ pub fn router( let api_url_prefix = "/api"; - let router = v1::routes::add( - api_url_prefix, - router, - &in_memory_torrent_repository.clone(), - &keys_handler.clone(), - &whitelist_manager.clone(), - ban_service.clone(), - stats_event_sender.clone(), - stats_repository.clone(), - ); + let router = v1::routes::add(api_url_prefix, router, &http_api_container); let state = State { access_tokens }; diff --git a/src/servers/apis/server.rs b/src/servers/apis/server.rs index b3621de0e..7388a1851 100644 --- a/src/servers/apis/server.rs +++ b/src/servers/apis/server.rs @@ -33,23 +33,17 @@ use derive_more::Constructor; use futures::future::BoxFuture; use thiserror::Error; use tokio::sync::oneshot::{Receiver, Sender}; -use tokio::sync::RwLock; use torrust_tracker_configuration::AccessTokens; use tracing::{instrument, Level}; use super::routes::router; use crate::bootstrap::jobs::Started; -use crate::core::authentication::handler::KeysHandler; -use crate::core::statistics; -use crate::core::statistics::repository::Repository; -use crate::core::torrent::repository::in_memory::InMemoryTorrentRepository; -use crate::core::whitelist::manager::WhitelistManager; +use crate::container::HttpApiContainer; use crate::servers::apis::API_LOG_TARGET; use crate::servers::custom_axum_server::{self, TimeoutAcceptor}; use crate::servers::logging::STARTED_ON; use crate::servers::registar::{ServiceHealthCheckJob, ServiceRegistration, ServiceRegistrationForm}; use crate::servers::signals::{graceful_shutdown, Halted}; -use crate::servers::udp::server::banning::BanService; /// Errors that can occur when starting or stopping the API server. #[derive(Debug, Error)] @@ -128,16 +122,10 @@ impl ApiServer { /// # Panics /// /// It would panic if the bound socket address cannot be sent back to this starter. - #[allow(clippy::too_many_arguments)] - #[instrument(skip(self, in_memory_torrent_repository, keys_handler, whitelist_manager, stats_event_sender, ban_service, stats_repository, form, access_tokens), err, ret(Display, level = Level::INFO))] + #[instrument(skip(self, http_api_container, form, access_tokens), err, ret(Display, level = Level::INFO))] pub async fn start( self, - in_memory_torrent_repository: Arc, - keys_handler: Arc, - whitelist_manager: Arc, - stats_event_sender: Arc>>, - stats_repository: Arc, - ban_service: Arc>, + http_api_container: Arc, form: ServiceRegistrationForm, access_tokens: Arc, ) -> Result, Error> { @@ -149,19 +137,7 @@ impl ApiServer { let task = tokio::spawn(async move { tracing::debug!(target: API_LOG_TARGET, "Starting with launcher in spawned task ..."); - let _task = launcher - .start( - in_memory_torrent_repository, - keys_handler, - whitelist_manager, - ban_service, - stats_event_sender, - stats_repository, - access_tokens, - tx_start, - rx_halt, - ) - .await; + let _task = launcher.start(http_api_container, access_tokens, tx_start, rx_halt).await; tracing::debug!(target: API_LOG_TARGET, "Started with launcher in spawned task"); @@ -259,26 +235,10 @@ impl Launcher { /// /// Will panic if unable to bind to the socket, or unable to get the address of the bound socket. /// Will also panic if unable to send message regarding the bound socket address. - #[allow(clippy::too_many_arguments)] - #[instrument(skip( - self, - keys_handler, - whitelist_manager, - ban_service, - stats_event_sender, - stats_repository, - access_tokens, - tx_start, - rx_halt - ))] + #[instrument(skip(self, http_api_container, access_tokens, tx_start, rx_halt))] pub fn start( &self, - in_memory_torrent_repository: Arc, - keys_handler: Arc, - whitelist_manager: Arc, - ban_service: Arc>, - stats_event_sender: Arc>>, - stats_repository: Arc, + http_api_container: Arc, access_tokens: Arc, tx_start: Sender, rx_halt: Receiver, @@ -286,16 +246,7 @@ impl Launcher { let socket = std::net::TcpListener::bind(self.bind_to).expect("Could not bind tcp_listener to address."); let address = socket.local_addr().expect("Could not get local_addr from tcp_listener."); - let router = router( - in_memory_torrent_repository, - keys_handler, - whitelist_manager, - ban_service, - stats_event_sender, - stats_repository, - access_tokens, - address, - ); + let router = router(http_api_container, access_tokens, address); let handle = Handle::new(); @@ -347,41 +298,35 @@ mod tests { use crate::bootstrap::app::{initialize_app_container, initialize_global_services}; use crate::bootstrap::jobs::make_rust_tls; + use crate::container::HttpApiContainer; use crate::servers::apis::server::{ApiServer, Launcher}; use crate::servers::registar::Registar; #[tokio::test] async fn it_should_be_able_to_start_and_stop() { let cfg = Arc::new(ephemeral_public()); - let config = &cfg.http_api.clone().unwrap(); + let http_api_config = Arc::new(cfg.http_api.clone().unwrap()); initialize_global_services(&cfg); - let app_container = initialize_app_container(&cfg); + let app_container = Arc::new(initialize_app_container(&cfg)); - let bind_to = config.bind_address; + let bind_to = http_api_config.bind_address; - let tls = make_rust_tls(&config.tsl_config) + let tls = make_rust_tls(&http_api_config.tsl_config) .await .map(|tls| tls.expect("tls config failed")); - let access_tokens = Arc::new(config.access_tokens.clone()); + let access_tokens = Arc::new(http_api_config.access_tokens.clone()); let stopped = ApiServer::new(Launcher::new(bind_to, tls)); let register = &Registar::default(); + let http_api_container = Arc::new(HttpApiContainer::from_app_container(&http_api_config, &app_container)); + let started = stopped - .start( - app_container.in_memory_torrent_repository, - app_container.keys_handler, - app_container.whitelist_manager, - app_container.stats_event_sender, - app_container.stats_repository, - app_container.ban_service, - register.give_form(), - access_tokens, - ) + .start(http_api_container, register.give_form(), access_tokens) .await .expect("it should start the server"); let stopped = started.stop().await.expect("it should stop the server"); diff --git a/src/servers/apis/v1/context/auth_key/routes.rs b/src/servers/apis/v1/context/auth_key/routes.rs index 45aeb02ec..ee9f3252c 100644 --- a/src/servers/apis/v1/context/auth_key/routes.rs +++ b/src/servers/apis/v1/context/auth_key/routes.rs @@ -15,7 +15,7 @@ use super::handlers::{add_auth_key_handler, delete_auth_key_handler, generate_au use crate::core::authentication::handler::KeysHandler; /// It adds the routes to the router for the [`auth_key`](crate::servers::apis::v1::context::auth_key) API context. -pub fn add(prefix: &str, router: Router, keys_handler: Arc) -> Router { +pub fn add(prefix: &str, router: Router, keys_handler: &Arc) -> Router { // Keys router .route( @@ -38,5 +38,8 @@ pub fn add(prefix: &str, router: Router, keys_handler: Arc) -> Rout &format!("{prefix}/keys/reload"), get(reload_keys_handler).with_state(keys_handler.clone()), ) - .route(&format!("{prefix}/keys"), post(add_auth_key_handler).with_state(keys_handler)) + .route( + &format!("{prefix}/keys"), + post(add_auth_key_handler).with_state(keys_handler.clone()), + ) } diff --git a/src/servers/apis/v1/context/stats/routes.rs b/src/servers/apis/v1/context/stats/routes.rs index 083c72b10..4c80f110d 100644 --- a/src/servers/apis/v1/context/stats/routes.rs +++ b/src/servers/apis/v1/context/stats/routes.rs @@ -7,25 +7,18 @@ use std::sync::Arc; use axum::routing::get; use axum::Router; -use tokio::sync::RwLock; use super::handlers::get_stats_handler; -use crate::core::statistics::event::sender::Sender; -use crate::core::statistics::repository::Repository; -use crate::core::torrent::repository::in_memory::InMemoryTorrentRepository; -use crate::servers::udp::server::banning::BanService; +use crate::container::HttpApiContainer; /// It adds the routes to the router for the [`stats`](crate::servers::apis::v1::context::stats) API context. -pub fn add( - prefix: &str, - router: Router, - in_memory_torrent_repository: Arc, - ban_service: Arc>, - _stats_event_sender: Arc>>, - stats_repository: Arc, -) -> Router { +pub fn add(prefix: &str, router: Router, http_api_container: &Arc) -> Router { router.route( &format!("{prefix}/stats"), - get(get_stats_handler).with_state((in_memory_torrent_repository, ban_service, stats_repository)), + get(get_stats_handler).with_state(( + http_api_container.in_memory_torrent_repository.clone(), + http_api_container.ban_service.clone(), + http_api_container.stats_repository.clone(), + )), ) } diff --git a/src/servers/apis/v1/context/torrent/resources/torrent.rs b/src/servers/apis/v1/context/torrent/resources/torrent.rs index 8fbb89418..237470d88 100644 --- a/src/servers/apis/v1/context/torrent/resources/torrent.rs +++ b/src/servers/apis/v1/context/torrent/resources/torrent.rs @@ -122,14 +122,14 @@ mod tests { fn torrent_resource_should_be_converted_from_torrent_info() { assert_eq!( Torrent::from(Info { - info_hash: InfoHash::from_str("9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d").unwrap(), + info_hash: InfoHash::from_str("9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d").unwrap(), // DevSkim: ignore DS173237 seeders: 1, completed: 2, leechers: 3, peers: Some(vec![sample_peer()]), }), Torrent { - info_hash: "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_string(), + info_hash: "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_string(), // DevSkim: ignore DS173237 seeders: 1, completed: 2, leechers: 3, @@ -142,13 +142,13 @@ mod tests { fn torrent_resource_list_item_should_be_converted_from_the_basic_torrent_info() { assert_eq!( ListItem::from(BasicInfo { - info_hash: InfoHash::from_str("9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d").unwrap(), + info_hash: InfoHash::from_str("9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d").unwrap(), // DevSkim: ignore DS173237 seeders: 1, completed: 2, leechers: 3, }), ListItem { - info_hash: "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_string(), + info_hash: "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_string(), // DevSkim: ignore DS173237 seeders: 1, completed: 2, leechers: 3, diff --git a/src/servers/apis/v1/context/torrent/routes.rs b/src/servers/apis/v1/context/torrent/routes.rs index dc66a1753..3ea8c639c 100644 --- a/src/servers/apis/v1/context/torrent/routes.rs +++ b/src/servers/apis/v1/context/torrent/routes.rs @@ -13,7 +13,7 @@ use super::handlers::{get_torrent_handler, get_torrents_handler}; use crate::core::torrent::repository::in_memory::InMemoryTorrentRepository; /// It adds the routes to the router for the [`torrent`](crate::servers::apis::v1::context::torrent) API context. -pub fn add(prefix: &str, router: Router, in_memory_torrent_repository: Arc) -> Router { +pub fn add(prefix: &str, router: Router, in_memory_torrent_repository: &Arc) -> Router { // Torrents router .route( @@ -22,6 +22,6 @@ pub fn add(prefix: &str, router: Router, in_memory_torrent_repository: Arc, - keys_handler: &Arc, - whitelist_manager: &Arc, - ban_service: Arc>, - stats_event_sender: Arc>>, - stats_repository: Arc, -) -> Router { +pub fn add(prefix: &str, router: Router, http_api_container: &Arc) -> Router { let v1_prefix = format!("{prefix}/v1"); - let router = auth_key::routes::add(&v1_prefix, router, keys_handler.clone()); - let router = stats::routes::add( - &v1_prefix, - router, - in_memory_torrent_repository.clone(), - ban_service, - stats_event_sender, - stats_repository, - ); - let router = whitelist::routes::add(&v1_prefix, router, whitelist_manager); + let router = auth_key::routes::add(&v1_prefix, router, &http_api_container.keys_handler.clone()); + let router = stats::routes::add(&v1_prefix, router, http_api_container); + let router = whitelist::routes::add(&v1_prefix, router, &http_api_container.whitelist_manager); - torrent::routes::add(&v1_prefix, router, in_memory_torrent_repository.clone()) + torrent::routes::add(&v1_prefix, router, &http_api_container.in_memory_torrent_repository.clone()) } diff --git a/src/servers/http/server.rs b/src/servers/http/server.rs index 2792697b3..2355bedf9 100644 --- a/src/servers/http/server.rs +++ b/src/servers/http/server.rs @@ -7,15 +7,11 @@ use axum_server::Handle; use derive_more::Constructor; use futures::future::BoxFuture; use tokio::sync::oneshot::{Receiver, Sender}; -use torrust_tracker_configuration::Core; use tracing::instrument; use super::v1::routes::router; use crate::bootstrap::jobs::Started; -use crate::core::announce_handler::AnnounceHandler; -use crate::core::authentication::service::AuthenticationService; -use crate::core::scrape_handler::ScrapeHandler; -use crate::core::{statistics, whitelist}; +use crate::container::HttpTrackerContainer; use crate::servers::custom_axum_server::{self, TimeoutAcceptor}; use crate::servers::http::HTTP_TRACKER_LOG_TARGET; use crate::servers::logging::STARTED_ON; @@ -46,25 +42,10 @@ pub struct Launcher { } impl Launcher { - #[allow(clippy::too_many_arguments)] - #[instrument(skip( - self, - announce_handler, - scrape_handler, - authentication_service, - whitelist_authorization, - stats_event_sender, - tx_start, - rx_halt - ))] + #[instrument(skip(self, http_tracker_container, tx_start, rx_halt))] fn start( &self, - config: Arc, - announce_handler: Arc, - scrape_handler: Arc, - authentication_service: Arc, - whitelist_authorization: Arc, - stats_event_sender: Arc>>, + http_tracker_container: Arc, tx_start: Sender, rx_halt: Receiver, ) -> BoxFuture<'static, ()> { @@ -84,15 +65,7 @@ impl Launcher { tracing::info!(target: HTTP_TRACKER_LOG_TARGET, "Starting on: {protocol}://{}", address); - let app = router( - config, - announce_handler, - scrape_handler, - authentication_service, - whitelist_authorization, - stats_event_sender, - address, - ); + let app = router(http_tracker_container, address); let running = Box::pin(async { match tls { @@ -185,15 +158,9 @@ impl HttpServer { /// /// It would panic spawned HTTP server launcher cannot send the bound `SocketAddr` /// back to the main thread. - #[allow(clippy::too_many_arguments)] pub async fn start( self, - core_config: Arc, - announce_handler: Arc, - scrape_handler: Arc, - authentication_service: Arc, - whitelist_authorization: Arc, - stats_event_sender: Arc>>, + http_tracker_container: Arc, form: ServiceRegistrationForm, ) -> Result, Error> { let (tx_start, rx_start) = tokio::sync::oneshot::channel::(); @@ -202,16 +169,7 @@ impl HttpServer { let launcher = self.state.launcher; let task = tokio::spawn(async move { - let server = launcher.start( - core_config, - announce_handler, - scrape_handler, - authentication_service, - whitelist_authorization, - stats_event_sender, - tx_start, - rx_halt, - ); + let server = launcher.start(http_tracker_container, tx_start, rx_halt); server.await; @@ -284,6 +242,7 @@ mod tests { use crate::bootstrap::app::{initialize_app_container, initialize_global_services}; use crate::bootstrap::jobs::make_rust_tls; + use crate::container::HttpTrackerContainer; use crate::servers::http::server::{HttpServer, Launcher}; use crate::servers::registar::Registar; @@ -293,30 +252,24 @@ mod tests { initialize_global_services(&cfg); - let app_container = initialize_app_container(&cfg); + let app_container = Arc::new(initialize_app_container(&cfg)); let http_trackers = cfg.http_trackers.clone().expect("missing HTTP trackers configuration"); - let config = &http_trackers[0]; - - let bind_to = config.bind_address; + let http_tracker_config = &http_trackers[0]; + let bind_to = http_tracker_config.bind_address; - let tls = make_rust_tls(&config.tsl_config) + let tls = make_rust_tls(&http_tracker_config.tsl_config) .await .map(|tls| tls.expect("tls config failed")); - let register = &Registar::default(); + let http_tracker_config = Arc::new(http_tracker_config.clone()); + let http_tracker_container = Arc::new(HttpTrackerContainer::from_app_container(&http_tracker_config, &app_container)); + let register = &Registar::default(); let stopped = HttpServer::new(Launcher::new(bind_to, tls)); + let started = stopped - .start( - Arc::new(cfg.core.clone()), - app_container.announce_handler, - app_container.scrape_handler, - app_container.authentication_service, - app_container.whitelist_authorization, - app_container.stats_event_sender, - register.give_form(), - ) + .start(http_tracker_container, register.give_form()) .await .expect("it should start the server"); let stopped = started.stop().await.expect("it should stop the server"); diff --git a/src/servers/http/v1/routes.rs b/src/servers/http/v1/routes.rs index f80760955..ed9aa05e6 100644 --- a/src/servers/http/v1/routes.rs +++ b/src/servers/http/v1/routes.rs @@ -10,7 +10,7 @@ use axum::routing::get; use axum::{BoxError, Router}; use axum_client_ip::SecureClientIpSource; use hyper::{Request, StatusCode}; -use torrust_tracker_configuration::{Core, DEFAULT_TIMEOUT}; +use torrust_tracker_configuration::DEFAULT_TIMEOUT; use tower::timeout::TimeoutLayer; use tower::ServiceBuilder; use tower_http::classify::ServerErrorsFailureClass; @@ -22,11 +22,7 @@ use tower_http::LatencyUnit; use tracing::{instrument, Level, Span}; use super::handlers::{announce, health_check, scrape}; -use crate::core::announce_handler::AnnounceHandler; -use crate::core::authentication::service::AuthenticationService; -use crate::core::scrape_handler::ScrapeHandler; -use crate::core::statistics::event::sender::Sender; -use crate::core::whitelist; +use crate::container::HttpTrackerContainer; use crate::servers::http::HTTP_TRACKER_LOG_TARGET; use crate::servers::logging::Latency; @@ -34,25 +30,8 @@ use crate::servers::logging::Latency; /// /// > **NOTICE**: it's added a layer to get the client IP from the connection /// > info. The tracker could use the connection info to get the client IP. -#[allow(clippy::too_many_arguments)] -#[allow(clippy::needless_pass_by_value)] -#[instrument(skip( - announce_handler, - scrape_handler, - authentication_service, - whitelist_authorization, - stats_event_sender, - server_socket_addr -))] -pub fn router( - core_config: Arc, - announce_handler: Arc, - scrape_handler: Arc, - authentication_service: Arc, - whitelist_authorization: Arc, - stats_event_sender: Arc>>, - server_socket_addr: SocketAddr, -) -> Router { +#[instrument(skip(http_tracker_container, server_socket_addr))] +pub fn router(http_tracker_container: Arc, server_socket_addr: SocketAddr) -> Router { Router::new() // Health check .route("/health_check", get(health_check::handler)) @@ -60,40 +39,40 @@ pub fn router( .route( "/announce", get(announce::handle_without_key).with_state(( - core_config.clone(), - announce_handler.clone(), - authentication_service.clone(), - whitelist_authorization.clone(), - stats_event_sender.clone(), + 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.stats_event_sender.clone(), )), ) .route( "/announce/{key}", get(announce::handle_with_key).with_state(( - core_config.clone(), - announce_handler.clone(), - authentication_service.clone(), - whitelist_authorization.clone(), - stats_event_sender.clone(), + 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.stats_event_sender.clone(), )), ) // Scrape request .route( "/scrape", get(scrape::handle_without_key).with_state(( - core_config.clone(), - scrape_handler.clone(), - authentication_service.clone(), - stats_event_sender.clone(), + http_tracker_container.core_config.clone(), + http_tracker_container.scrape_handler.clone(), + http_tracker_container.authentication_service.clone(), + http_tracker_container.stats_event_sender.clone(), )), ) .route( "/scrape/{key}", get(scrape::handle_with_key).with_state(( - core_config.clone(), - scrape_handler.clone(), - authentication_service.clone(), - stats_event_sender.clone(), + http_tracker_container.core_config.clone(), + http_tracker_container.scrape_handler.clone(), + http_tracker_container.authentication_service.clone(), + http_tracker_container.stats_event_sender.clone(), )), ) // Add extension to get the client IP from the connection info diff --git a/src/servers/udp/handlers.rs b/src/servers/udp/handlers.rs index 43dc69019..992f27a44 100644 --- a/src/servers/udp/handlers.rs +++ b/src/servers/udp/handlers.rs @@ -11,7 +11,6 @@ use aquatic_udp_protocol::{ ResponsePeer, ScrapeRequest, ScrapeResponse, TorrentScrapeStatistics, TransactionId, }; use bittorrent_primitives::info_hash::InfoHash; -use tokio::sync::RwLock; use torrust_tracker_clock::clock::Time as _; use torrust_tracker_configuration::Core; use tracing::{instrument, Level}; @@ -19,8 +18,8 @@ use uuid::Uuid; use zerocopy::network_endian::I32; use super::connection_cookie::{check, make}; -use super::server::banning::BanService; use super::RawRequest; +use crate::container::UdpTrackerContainer; use crate::core::announce_handler::{AnnounceHandler, PeersWanted}; use crate::core::scrape_handler::ScrapeHandler; use crate::core::statistics::event::sender::Sender; @@ -57,18 +56,12 @@ impl CookieTimeValues { /// - Delegating the request to the correct handler depending on the request type. /// /// It will return an `Error` response if the request is invalid. -#[allow(clippy::too_many_arguments)] -#[instrument(fields(request_id), skip(udp_request, announce_handler, scrape_handler, whitelist_authorization, opt_stats_event_sender, cookie_time_values, ban_service), ret(level = Level::TRACE))] +#[instrument(fields(request_id), skip(udp_request, udp_tracker_container, cookie_time_values), ret(level = Level::TRACE))] pub(crate) async fn handle_packet( udp_request: RawRequest, - core_config: &Arc, - announce_handler: &Arc, - scrape_handler: &Arc, - whitelist_authorization: &Arc, - opt_stats_event_sender: &Arc>>, + udp_tracker_container: Arc, local_addr: SocketAddr, cookie_time_values: CookieTimeValues, - ban_service: Arc>, ) -> Response { let request_id = Uuid::new_v4(); @@ -82,11 +75,7 @@ pub(crate) async fn handle_packet( Ok(request) => match handle_request( request, udp_request.from, - core_config, - announce_handler, - scrape_handler, - whitelist_authorization, - opt_stats_event_sender, + udp_tracker_container.clone(), cookie_time_values.clone(), ) .await @@ -98,7 +87,7 @@ pub(crate) async fn handle_packet( | Error::CookieValueExpired { .. } | Error::CookieValueFromFuture { .. } => { // code-review: should we include `RequestParseError` and `BadRequest`? - let mut ban_service = ban_service.write().await; + let mut ban_service = udp_tracker_container.ban_service.write().await; ban_service.increase_counter(&udp_request.from.ip()); } _ => {} @@ -108,7 +97,7 @@ pub(crate) async fn handle_packet( udp_request.from, local_addr, request_id, - opt_stats_event_sender, + &udp_tracker_container.stats_event_sender, cookie_time_values.valid_range.clone(), &e, Some(transaction_id), @@ -121,7 +110,7 @@ pub(crate) async fn handle_packet( udp_request.from, local_addr, request_id, - opt_stats_event_sender, + &udp_tracker_container.stats_event_sender, cookie_time_values.valid_range.clone(), &e, None, @@ -141,24 +130,11 @@ pub(crate) async fn handle_packet( /// # Errors /// /// If a error happens in the `handle_request` function, it will just return the `ServerError`. -#[allow(clippy::too_many_arguments)] -#[instrument(skip( - request, - remote_addr, - announce_handler, - scrape_handler, - whitelist_authorization, - opt_stats_event_sender, - cookie_time_values -))] +#[instrument(skip(request, remote_addr, udp_tracker_container, cookie_time_values))] pub async fn handle_request( request: Request, remote_addr: SocketAddr, - core_config: &Arc, - announce_handler: &Arc, - scrape_handler: &Arc, - whitelist_authorization: &Arc, - opt_stats_event_sender: &Arc>>, + udp_tracker_container: Arc, cookie_time_values: CookieTimeValues, ) -> Result { tracing::trace!("handle request"); @@ -167,7 +143,7 @@ pub async fn handle_request( Request::Connect(connect_request) => Ok(handle_connect( remote_addr, &connect_request, - opt_stats_event_sender, + &udp_tracker_container.stats_event_sender, cookie_time_values.issue_time, ) .await), @@ -175,10 +151,10 @@ pub async fn handle_request( handle_announce( remote_addr, &announce_request, - core_config, - announce_handler, - whitelist_authorization, - opt_stats_event_sender, + &udp_tracker_container.core_config, + &udp_tracker_container.announce_handler, + &udp_tracker_container.whitelist_authorization, + &udp_tracker_container.stats_event_sender, cookie_time_values.valid_range, ) .await @@ -187,8 +163,8 @@ pub async fn handle_request( handle_scrape( remote_addr, &scrape_request, - scrape_handler, - opt_stats_event_sender, + &udp_tracker_container.scrape_handler, + &udp_tracker_container.stats_event_sender, cookie_time_values.valid_range, ) .await diff --git a/src/servers/udp/server/launcher.rs b/src/servers/udp/server/launcher.rs index 4aaf87ae2..e4edadd8f 100644 --- a/src/servers/udp/server/launcher.rs +++ b/src/servers/udp/server/launcher.rs @@ -6,18 +6,14 @@ use bittorrent_tracker_client::udp::client::check; use derive_more::Constructor; use futures_util::StreamExt; use tokio::select; -use tokio::sync::{oneshot, RwLock}; +use tokio::sync::oneshot; use tokio::time::interval; -use torrust_tracker_configuration::Core; use tracing::instrument; -use super::banning::BanService; use super::request_buffer::ActiveRequests; use crate::bootstrap::jobs::Started; -use crate::core::announce_handler::AnnounceHandler; -use crate::core::scrape_handler::ScrapeHandler; -use crate::core::statistics::event::sender::Sender; -use crate::core::{statistics, whitelist}; +use crate::container::UdpTrackerContainer; +use crate::core::statistics; use crate::servers::logging::STARTED_ON; use crate::servers::registar::ServiceHealthCheckJob; use crate::servers::signals::{shutdown_signal_with_message, Halted}; @@ -43,24 +39,9 @@ impl Launcher { /// It panics if unable to bind to udp socket, and get the address from the udp socket. /// It panics if unable to send address of socket. /// It panics if the udp server is loaded when the tracker is private. - #[allow(clippy::too_many_arguments)] - #[instrument(skip( - announce_handler, - scrape_handler, - whitelist_authorization, - opt_stats_event_sender, - ban_service, - bind_to, - tx_start, - rx_halt - ))] + #[instrument(skip(udp_tracker_container, bind_to, tx_start, rx_halt))] pub async fn run_with_graceful_shutdown( - core_config: Arc, - announce_handler: Arc, - scrape_handler: Arc, - whitelist_authorization: Arc, - opt_stats_event_sender: Arc>>, - ban_service: Arc>, + udp_tracker_container: Arc, bind_to: SocketAddr, cookie_lifetime: Duration, tx_start: oneshot::Sender, @@ -68,7 +49,7 @@ impl Launcher { ) { tracing::info!(target: UDP_TRACKER_LOG_TARGET, "Starting on: {bind_to}"); - if core_config.private { + if udp_tracker_container.core_config.private { tracing::error!("udp services cannot be used for private trackers"); panic!("it should not use udp if using authentication"); } @@ -98,17 +79,7 @@ impl Launcher { let local_addr = local_udp_url.clone(); tokio::task::spawn(async move { tracing::debug!(target: UDP_TRACKER_LOG_TARGET, local_addr, "Udp::run_with_graceful_shutdown::task (listening...)"); - let () = Self::run_udp_server_main( - receiver, - core_config.clone(), - announce_handler.clone(), - scrape_handler.clone(), - whitelist_authorization.clone(), - opt_stats_event_sender.clone(), - ban_service.clone(), - cookie_lifetime, - ) - .await; + let () = Self::run_udp_server_main(receiver, udp_tracker_container, cookie_lifetime).await; }) }; @@ -145,23 +116,10 @@ impl Launcher { ServiceHealthCheckJob::new(binding, info, job) } - #[allow(clippy::too_many_arguments)] - #[instrument(skip( - receiver, - announce_handler, - scrape_handler, - whitelist_authorization, - opt_stats_event_sender, - ban_service - ))] + #[instrument(skip(receiver, udp_tracker_container))] async fn run_udp_server_main( mut receiver: Receiver, - core_config: Arc, - announce_handler: Arc, - scrape_handler: Arc, - whitelist_authorization: Arc, - opt_stats_event_sender: Arc>>, - ban_service: Arc>, + udp_tracker_container: Arc, cookie_lifetime: Duration, ) { let active_requests = &mut ActiveRequests::default(); @@ -172,7 +130,7 @@ impl Launcher { let cookie_lifetime = cookie_lifetime.as_secs_f64(); - let ban_cleaner = ban_service.clone(); + let ban_cleaner = udp_tracker_container.ban_service.clone(); tokio::spawn(async move { let mut cleaner_interval = interval(Duration::from_secs(IP_BANS_RESET_INTERVAL_IN_SECS)); @@ -204,7 +162,7 @@ impl Launcher { } }; - if let Some(stats_event_sender) = opt_stats_event_sender.as_deref() { + if let Some(stats_event_sender) = udp_tracker_container.stats_event_sender.as_deref() { match req.from.ip() { IpAddr::V4(_) => { stats_event_sender.send_event(statistics::event::Event::Udp4Request).await; @@ -215,10 +173,10 @@ impl Launcher { } } - if ban_service.read().await.is_banned(&req.from.ip()) { + if udp_tracker_container.ban_service.read().await.is_banned(&req.from.ip()) { tracing::debug!(target: UDP_TRACKER_LOG_TARGET, local_addr, "Udp::run_udp_server::loop continue: (banned ip)"); - if let Some(stats_event_sender) = opt_stats_event_sender.as_deref() { + if let Some(stats_event_sender) = udp_tracker_container.stats_event_sender.as_deref() { stats_event_sender .send_event(statistics::event::Event::UdpRequestBanned) .await; @@ -227,15 +185,7 @@ impl Launcher { continue; } - let processor = Processor::new( - receiver.socket.clone(), - core_config.clone(), - announce_handler.clone(), - scrape_handler.clone(), - whitelist_authorization.clone(), - opt_stats_event_sender.clone(), - cookie_lifetime, - ); + let processor = Processor::new(receiver.socket.clone(), udp_tracker_container.clone(), cookie_lifetime); /* We spawn the new task even if the active requests buffer is full. This could seem counterintuitive because we are accepting @@ -248,8 +198,7 @@ impl Launcher { only adding and removing tasks without given them the chance to finish. However, the buffer is yielding before aborting one tasks, giving it the chance to finish. */ - let abort_handle: tokio::task::AbortHandle = - tokio::task::spawn(processor.process_request(req, ban_service.clone())).abort_handle(); + let abort_handle: tokio::task::AbortHandle = tokio::task::spawn(processor.process_request(req)).abort_handle(); if abort_handle.is_finished() { continue; @@ -260,7 +209,7 @@ impl Launcher { if old_request_aborted { // Evicted task from active requests buffer was aborted. - if let Some(stats_event_sender) = opt_stats_event_sender.as_deref() { + if let Some(stats_event_sender) = udp_tracker_container.stats_event_sender.as_deref() { stats_event_sender .send_event(statistics::event::Event::UdpRequestAborted) .await; diff --git a/src/servers/udp/server/mod.rs b/src/servers/udp/server/mod.rs index c87728361..941f6b5cb 100644 --- a/src/servers/udp/server/mod.rs +++ b/src/servers/udp/server/mod.rs @@ -63,6 +63,7 @@ mod tests { use super::spawner::Spawner; use super::Server; use crate::bootstrap::app::{initialize_app_container, initialize_global_services}; + use crate::container::UdpTrackerContainer; use crate::servers::registar::Registar; #[tokio::test] @@ -71,7 +72,7 @@ mod tests { initialize_global_services(&cfg); - let app_container = initialize_app_container(&cfg); + let app_container = Arc::new(initialize_app_container(&cfg)); let udp_trackers = cfg.udp_trackers.clone().expect("missing UDP trackers configuration"); let config = &udp_trackers[0]; @@ -80,17 +81,11 @@ mod tests { let stopped = Server::new(Spawner::new(bind_to)); + let udp_tracker_config = Arc::new(config.clone()); + let udp_tracker_container = Arc::new(UdpTrackerContainer::from_app_container(&udp_tracker_config, &app_container)); + let started = stopped - .start( - Arc::new(cfg.core.clone()), - app_container.announce_handler, - app_container.scrape_handler, - app_container.whitelist_authorization, - app_container.stats_event_sender, - app_container.ban_service, - register.give_form(), - config.cookie_lifetime, - ) + .start(udp_tracker_container, register.give_form(), config.cookie_lifetime) .await .expect("it should start the server"); @@ -107,25 +102,19 @@ mod tests { initialize_global_services(&cfg); - let app_container = initialize_app_container(&cfg); + let app_container = Arc::new(initialize_app_container(&cfg)); - let config = &cfg.udp_trackers.as_ref().unwrap().first().unwrap(); + let config = cfg.udp_trackers.as_ref().unwrap().first().unwrap(); let bind_to = config.bind_address; let register = &Registar::default(); let stopped = Server::new(Spawner::new(bind_to)); + let udp_tracker_config = Arc::new(config.clone()); + let udp_tracker_container = Arc::new(UdpTrackerContainer::from_app_container(&udp_tracker_config, &app_container)); + let started = stopped - .start( - Arc::new(cfg.core.clone()), - app_container.announce_handler, - app_container.scrape_handler, - app_container.whitelist_authorization, - app_container.stats_event_sender, - app_container.ban_service, - register.give_form(), - config.cookie_lifetime, - ) + .start(udp_tracker_container, register.give_form(), config.cookie_lifetime) .await .expect("it should start the server"); diff --git a/src/servers/udp/server/processor.rs b/src/servers/udp/server/processor.rs index 24a34f98d..e2beb2377 100644 --- a/src/servers/udp/server/processor.rs +++ b/src/servers/udp/server/processor.rs @@ -4,69 +4,42 @@ use std::sync::Arc; use std::time::Duration; use aquatic_udp_protocol::Response; -use tokio::sync::RwLock; use tokio::time::Instant; -use torrust_tracker_configuration::Core; use tracing::{instrument, Level}; -use super::banning::BanService; use super::bound_socket::BoundSocket; -use crate::core::announce_handler::AnnounceHandler; -use crate::core::scrape_handler::ScrapeHandler; -use crate::core::statistics::event::sender::Sender; +use crate::container::UdpTrackerContainer; +use crate::core::statistics; use crate::core::statistics::event::UdpResponseKind; -use crate::core::{statistics, whitelist}; use crate::servers::udp::handlers::CookieTimeValues; use crate::servers::udp::{handlers, RawRequest}; pub struct Processor { socket: Arc, - core_config: Arc, - announce_handler: Arc, - scrape_handler: Arc, - whitelist_authorization: Arc, - opt_stats_event_sender: Arc>>, + udp_tracker_container: Arc, cookie_lifetime: f64, } impl Processor { - #[allow(clippy::too_many_arguments)] - pub fn new( - socket: Arc, - core_config: Arc, - announce_handler: Arc, - scrape_handler: Arc, - whitelist_authorization: Arc, - opt_stats_event_sender: Arc>>, - cookie_lifetime: f64, - ) -> Self { + pub fn new(socket: Arc, udp_tracker_container: Arc, cookie_lifetime: f64) -> Self { Self { socket, - core_config, - announce_handler, - scrape_handler, - whitelist_authorization, - opt_stats_event_sender, + udp_tracker_container, cookie_lifetime, } } - #[instrument(skip(self, request, ban_service))] - pub async fn process_request(self, request: RawRequest, ban_service: Arc>) { + #[instrument(skip(self, request))] + pub async fn process_request(self, request: RawRequest) { let from = request.from; let start_time = Instant::now(); let response = handlers::handle_packet( request, - &self.core_config, - &self.announce_handler, - &self.scrape_handler, - &self.whitelist_authorization, - &self.opt_stats_event_sender, + self.udp_tracker_container.clone(), self.socket.address(), CookieTimeValues::new(self.cookie_lifetime), - ban_service, ) .await; @@ -109,7 +82,7 @@ impl Processor { tracing::debug!(%bytes_count, %sent_bytes, "sent {response_type}"); } - if let Some(stats_event_sender) = self.opt_stats_event_sender.as_deref() { + if let Some(stats_event_sender) = self.udp_tracker_container.stats_event_sender.as_deref() { match target.ip() { IpAddr::V4(_) => { stats_event_sender diff --git a/src/servers/udp/server/spawner.rs b/src/servers/udp/server/spawner.rs index d5fd5d58e..88ce5a245 100644 --- a/src/servers/udp/server/spawner.rs +++ b/src/servers/udp/server/spawner.rs @@ -5,17 +5,12 @@ use std::time::Duration; use derive_more::derive::Display; use derive_more::Constructor; -use tokio::sync::{oneshot, RwLock}; +use tokio::sync::oneshot; use tokio::task::JoinHandle; -use torrust_tracker_configuration::Core; -use super::banning::BanService; use super::launcher::Launcher; use crate::bootstrap::jobs::Started; -use crate::core::announce_handler::AnnounceHandler; -use crate::core::scrape_handler::ScrapeHandler; -use crate::core::statistics::event::sender::Sender; -use crate::core::whitelist; +use crate::container::UdpTrackerContainer; use crate::servers::signals::Halted; #[derive(Constructor, Copy, Clone, Debug, Display)] @@ -30,15 +25,10 @@ impl Spawner { /// # Panics /// /// It would panic if unable to resolve the `local_addr` from the supplied ´socket´. - #[allow(clippy::too_many_arguments)] + #[must_use] pub fn spawn_launcher( &self, - core_config: Arc, - announce_handler: Arc, - scrape_handler: Arc, - whitelist_authorization: Arc, - opt_stats_event_sender: Arc>>, - ban_service: Arc>, + udp_tracker_container: Arc, cookie_lifetime: Duration, tx_start: oneshot::Sender, rx_halt: oneshot::Receiver, @@ -46,19 +36,8 @@ impl Spawner { let spawner = Self::new(self.bind_to); tokio::spawn(async move { - Launcher::run_with_graceful_shutdown( - core_config, - announce_handler, - scrape_handler, - whitelist_authorization, - opt_stats_event_sender, - ban_service, - spawner.bind_to, - cookie_lifetime, - tx_start, - rx_halt, - ) - .await; + Launcher::run_with_graceful_shutdown(udp_tracker_container, spawner.bind_to, cookie_lifetime, tx_start, rx_halt) + .await; spawner }) } diff --git a/src/servers/udp/server/states.rs b/src/servers/udp/server/states.rs index 9bcde9003..abce9720a 100644 --- a/src/servers/udp/server/states.rs +++ b/src/servers/udp/server/states.rs @@ -5,19 +5,13 @@ use std::time::Duration; use derive_more::derive::Display; use derive_more::Constructor; -use tokio::sync::RwLock; use tokio::task::JoinHandle; -use torrust_tracker_configuration::Core; use tracing::{instrument, Level}; -use super::banning::BanService; use super::spawner::Spawner; use super::{Server, UdpError}; use crate::bootstrap::jobs::Started; -use crate::core::announce_handler::AnnounceHandler; -use crate::core::scrape_handler::ScrapeHandler; -use crate::core::statistics::event::sender::Sender; -use crate::core::whitelist; +use crate::container::UdpTrackerContainer; use crate::servers::registar::{ServiceRegistration, ServiceRegistrationForm}; use crate::servers::signals::Halted; use crate::servers::udp::server::launcher::Launcher; @@ -67,16 +61,10 @@ impl Server { /// # Panics /// /// It panics if unable to receive the bound socket address from service. - #[allow(clippy::too_many_arguments)] - #[instrument(skip(self, announce_handler, scrape_handler, whitelist_authorization, opt_stats_event_sender, ban_service, form), err, ret(Display, level = Level::INFO))] + #[instrument(skip(self, udp_tracker_container, form), err, ret(Display, level = Level::INFO))] pub async fn start( self, - core_config: Arc, - announce_handler: Arc, - scrape_handler: Arc, - whitelist_authorization: Arc, - opt_stats_event_sender: Arc>>, - ban_service: Arc>, + udp_tracker_container: Arc, form: ServiceRegistrationForm, cookie_lifetime: Duration, ) -> Result, std::io::Error> { @@ -86,17 +74,10 @@ impl Server { assert!(!tx_halt.is_closed(), "Halt channel for UDP tracker should be open"); // May need to wrap in a task to about a tokio bug. - let task = self.state.spawner.spawn_launcher( - core_config, - announce_handler, - scrape_handler, - whitelist_authorization, - opt_stats_event_sender, - ban_service, - cookie_lifetime, - tx_start, - rx_halt, - ); + let task = self + .state + .spawner + .spawn_launcher(udp_tracker_container, cookie_lifetime, tx_start, rx_halt); let local_addr = rx_start.await.expect("it should be able to start the service").address; diff --git a/tests/servers/api/environment.rs b/tests/servers/api/environment.rs index 66018032e..297e169d4 100644 --- a/tests/servers/api/environment.rs +++ b/tests/servers/api/environment.rs @@ -3,36 +3,26 @@ use std::sync::Arc; use bittorrent_primitives::info_hash::InfoHash; use futures::executor::block_on; -use tokio::sync::RwLock; use torrust_tracker_api_client::connection_info::{ConnectionInfo, Origin}; -use torrust_tracker_configuration::{Configuration, HttpApi}; +use torrust_tracker_configuration::Configuration; use torrust_tracker_lib::bootstrap::app::{initialize_app_container, initialize_global_services}; use torrust_tracker_lib::bootstrap::jobs::make_rust_tls; -use torrust_tracker_lib::core::authentication::handler::KeysHandler; +use torrust_tracker_lib::container::HttpApiContainer; use torrust_tracker_lib::core::authentication::service::AuthenticationService; use torrust_tracker_lib::core::databases::Database; -use torrust_tracker_lib::core::statistics::event::sender::Sender; -use torrust_tracker_lib::core::statistics::repository::Repository; -use torrust_tracker_lib::core::torrent::repository::in_memory::InMemoryTorrentRepository; -use torrust_tracker_lib::core::whitelist::manager::WhitelistManager; use torrust_tracker_lib::servers::apis::server::{ApiServer, Launcher, Running, Stopped}; use torrust_tracker_lib::servers::registar::Registar; -use torrust_tracker_lib::servers::udp::server::banning::BanService; use torrust_tracker_primitives::peer; pub struct Environment where S: std::fmt::Debug + std::fmt::Display, { - pub config: Arc, + pub http_api_container: Arc, + pub database: Arc>, - pub in_memory_torrent_repository: Arc, - pub keys_handler: Arc, pub authentication_service: Arc, - pub stats_event_sender: Arc>>, - pub stats_repository: Arc, - pub whitelist_manager: Arc, - pub ban_service: Arc>, + pub registar: Registar, pub server: ApiServer, } @@ -43,7 +33,10 @@ where { /// Add a torrent to the tracker pub fn add_torrent_peer(&self, info_hash: &InfoHash, peer: &peer::Peer) { - let () = self.in_memory_torrent_repository.upsert_peer(info_hash, peer); + let () = self + .http_api_container + .in_memory_torrent_repository + .upsert_peer(info_hash, peer); } } @@ -53,55 +46,49 @@ impl Environment { let app_container = initialize_app_container(configuration); - let config = Arc::new(configuration.http_api.clone().expect("missing API configuration")); + let http_api_config = Arc::new(configuration.http_api.clone().expect("missing API configuration")); - let bind_to = config.bind_address; + let bind_to = http_api_config.bind_address; - let tls = block_on(make_rust_tls(&config.tsl_config)).map(|tls| tls.expect("tls config failed")); + let tls = block_on(make_rust_tls(&http_api_config.tsl_config)).map(|tls| tls.expect("tls config failed")); let server = ApiServer::new(Launcher::new(bind_to, tls)); - Self { - config, - database: app_container.database.clone(), + let http_api_container = Arc::new(HttpApiContainer { + http_api_config: http_api_config.clone(), + core_config: app_container.core_config.clone(), in_memory_torrent_repository: app_container.in_memory_torrent_repository.clone(), keys_handler: app_container.keys_handler.clone(), - authentication_service: app_container.authentication_service.clone(), - stats_event_sender: app_container.stats_event_sender.clone(), - stats_repository: app_container.stats_repository.clone(), whitelist_manager: app_container.whitelist_manager.clone(), ban_service: app_container.ban_service.clone(), + stats_event_sender: app_container.stats_event_sender.clone(), + stats_repository: app_container.stats_repository.clone(), + }); + + Self { + http_api_container, + + database: app_container.database.clone(), + authentication_service: app_container.authentication_service.clone(), + registar: Registar::default(), server, } } pub async fn start(self) -> Environment { - let access_tokens = Arc::new(self.config.access_tokens.clone()); + let access_tokens = Arc::new(self.http_api_container.http_api_config.access_tokens.clone()); Environment { - config: self.config, + http_api_container: self.http_api_container.clone(), + database: self.database.clone(), - in_memory_torrent_repository: self.in_memory_torrent_repository.clone(), - keys_handler: self.keys_handler.clone(), authentication_service: self.authentication_service.clone(), - stats_event_sender: self.stats_event_sender.clone(), - stats_repository: self.stats_repository.clone(), - whitelist_manager: self.whitelist_manager.clone(), - ban_service: self.ban_service.clone(), + registar: self.registar.clone(), server: self .server - .start( - self.in_memory_torrent_repository, - self.keys_handler, - self.whitelist_manager, - self.stats_event_sender, - self.stats_repository, - self.ban_service, - self.registar.give_form(), - access_tokens, - ) + .start(self.http_api_container, self.registar.give_form(), access_tokens) .await .unwrap(), } @@ -115,15 +102,11 @@ impl Environment { pub async fn stop(self) -> Environment { Environment { - config: self.config, + http_api_container: self.http_api_container, + database: self.database, - in_memory_torrent_repository: self.in_memory_torrent_repository, - keys_handler: self.keys_handler, authentication_service: self.authentication_service, - stats_event_sender: self.stats_event_sender, - stats_repository: self.stats_repository, - whitelist_manager: self.whitelist_manager, - ban_service: self.ban_service, + registar: Registar::default(), server: self.server.stop().await.unwrap(), } @@ -134,7 +117,7 @@ impl Environment { ConnectionInfo { origin, - api_token: self.config.access_tokens.get("admin").cloned(), + api_token: self.http_api_container.http_api_config.access_tokens.get("admin").cloned(), } } diff --git a/tests/servers/api/v1/contract/context/auth_key.rs b/tests/servers/api/v1/contract/context/auth_key.rs index 3b7d2d6ba..3242c3ccc 100644 --- a/tests/servers/api/v1/contract/context/auth_key.rs +++ b/tests/servers/api/v1/contract/context/auth_key.rs @@ -158,6 +158,7 @@ async fn should_allow_deleting_an_auth_key() { let seconds_valid = 60; let auth_key = env + .http_api_container .keys_handler .generate_auth_key(Some(Duration::from_secs(seconds_valid))) .await @@ -292,6 +293,7 @@ async fn should_fail_when_the_auth_key_cannot_be_deleted() { let seconds_valid = 60; let auth_key = env + .http_api_container .keys_handler .generate_auth_key(Some(Duration::from_secs(seconds_valid))) .await @@ -325,6 +327,7 @@ async fn should_not_allow_deleting_an_auth_key_for_unauthenticated_users() { // Generate new auth key let auth_key = env + .http_api_container .keys_handler .generate_auth_key(Some(Duration::from_secs(seconds_valid))) .await @@ -345,6 +348,7 @@ async fn should_not_allow_deleting_an_auth_key_for_unauthenticated_users() { // Generate new auth key let auth_key = env + .http_api_container .keys_handler .generate_auth_key(Some(Duration::from_secs(seconds_valid))) .await @@ -373,7 +377,8 @@ async fn should_allow_reloading_keys() { let env = Started::new(&configuration::ephemeral().into()).await; let seconds_valid = 60; - env.keys_handler + env.http_api_container + .keys_handler .generate_auth_key(Some(Duration::from_secs(seconds_valid))) .await .unwrap(); @@ -398,7 +403,8 @@ async fn should_fail_when_keys_cannot_be_reloaded() { let request_id = Uuid::new_v4(); let seconds_valid = 60; - env.keys_handler + env.http_api_container + .keys_handler .generate_auth_key(Some(Duration::from_secs(seconds_valid))) .await .unwrap(); @@ -426,7 +432,8 @@ async fn should_not_allow_reloading_keys_for_unauthenticated_users() { let env = Started::new(&configuration::ephemeral().into()).await; let seconds_valid = 60; - env.keys_handler + env.http_api_container + .keys_handler .generate_auth_key(Some(Duration::from_secs(seconds_valid))) .await .unwrap(); diff --git a/tests/servers/api/v1/contract/context/stats.rs b/tests/servers/api/v1/contract/context/stats.rs index 2eda0ed4a..55d3cd869 100644 --- a/tests/servers/api/v1/contract/context/stats.rs +++ b/tests/servers/api/v1/contract/context/stats.rs @@ -19,7 +19,7 @@ async fn should_allow_getting_tracker_statistics() { let env = Started::new(&configuration::ephemeral().into()).await; env.add_torrent_peer( - &InfoHash::from_str("9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d").unwrap(), + &InfoHash::from_str("9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d").unwrap(), // DevSkim: ignore DS173237 &PeerBuilder::default().into(), ); diff --git a/tests/servers/api/v1/contract/context/torrent.rs b/tests/servers/api/v1/contract/context/torrent.rs index 76646db14..8aa408173 100644 --- a/tests/servers/api/v1/contract/context/torrent.rs +++ b/tests/servers/api/v1/contract/context/torrent.rs @@ -26,7 +26,7 @@ async fn should_allow_getting_all_torrents() { let env = Started::new(&configuration::ephemeral().into()).await; - let info_hash = InfoHash::from_str("9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d").unwrap(); + let info_hash = InfoHash::from_str("9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d").unwrap(); // DevSkim: ignore DS173237 env.add_torrent_peer(&info_hash, &PeerBuilder::default().into()); @@ -39,7 +39,7 @@ async fn should_allow_getting_all_torrents() { assert_torrent_list( response, vec![torrent::ListItem { - info_hash: "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_string(), + info_hash: "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_string(), // DevSkim: ignore DS173237 seeders: 1, completed: 0, leechers: 0, @@ -57,8 +57,8 @@ async fn should_allow_limiting_the_torrents_in_the_result() { let env = Started::new(&configuration::ephemeral().into()).await; // torrents are ordered alphabetically by infohashes - let info_hash_1 = InfoHash::from_str("9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d").unwrap(); - let info_hash_2 = InfoHash::from_str("0b3aea4adc213ce32295be85d3883a63bca25446").unwrap(); + let info_hash_1 = InfoHash::from_str("9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d").unwrap(); // DevSkim: ignore DS173237 + let info_hash_2 = InfoHash::from_str("0b3aea4adc213ce32295be85d3883a63bca25446").unwrap(); // DevSkim: ignore DS173237 env.add_torrent_peer(&info_hash_1, &PeerBuilder::default().into()); env.add_torrent_peer(&info_hash_2, &PeerBuilder::default().into()); @@ -75,7 +75,7 @@ async fn should_allow_limiting_the_torrents_in_the_result() { assert_torrent_list( response, vec![torrent::ListItem { - info_hash: "0b3aea4adc213ce32295be85d3883a63bca25446".to_string(), + info_hash: "0b3aea4adc213ce32295be85d3883a63bca25446".to_string(), // DevSkim: ignore DS173237 seeders: 1, completed: 0, leechers: 0, @@ -93,8 +93,8 @@ async fn should_allow_the_torrents_result_pagination() { let env = Started::new(&configuration::ephemeral().into()).await; // torrents are ordered alphabetically by infohashes - let info_hash_1 = InfoHash::from_str("9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d").unwrap(); - let info_hash_2 = InfoHash::from_str("0b3aea4adc213ce32295be85d3883a63bca25446").unwrap(); + let info_hash_1 = InfoHash::from_str("9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d").unwrap(); // DevSkim: ignore DS173237 + let info_hash_2 = InfoHash::from_str("0b3aea4adc213ce32295be85d3883a63bca25446").unwrap(); // DevSkim: ignore DS173237 env.add_torrent_peer(&info_hash_1, &PeerBuilder::default().into()); env.add_torrent_peer(&info_hash_2, &PeerBuilder::default().into()); @@ -111,7 +111,7 @@ async fn should_allow_the_torrents_result_pagination() { assert_torrent_list( response, vec![torrent::ListItem { - info_hash: "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_string(), + info_hash: "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_string(), // DevSkim: ignore DS173237 seeders: 1, completed: 0, leechers: 0, @@ -296,7 +296,7 @@ async fn should_allow_getting_a_torrent_info() { let env = Started::new(&configuration::ephemeral().into()).await; - let info_hash = InfoHash::from_str("9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d").unwrap(); + let info_hash = InfoHash::from_str("9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d").unwrap(); // DevSkim: ignore DS173237 let peer = PeerBuilder::default().into(); @@ -311,7 +311,7 @@ async fn should_allow_getting_a_torrent_info() { assert_torrent_info( response, Torrent { - info_hash: "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_string(), + info_hash: "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_string(), // DevSkim: ignore DS173237 seeders: 1, completed: 0, leechers: 0, @@ -330,7 +330,7 @@ async fn should_fail_while_getting_a_torrent_info_when_the_torrent_does_not_exis let env = Started::new(&configuration::ephemeral().into()).await; let request_id = Uuid::new_v4(); - let info_hash = InfoHash::from_str("9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d").unwrap(); + let info_hash = InfoHash::from_str("9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d").unwrap(); // DevSkim: ignore DS173237 let response = Client::new(env.get_connection_info()) .get_torrent(&info_hash.to_string(), Some(headers_with_request_id(request_id))) @@ -376,7 +376,7 @@ async fn should_not_allow_getting_a_torrent_info_for_unauthenticated_users() { let env = Started::new(&configuration::ephemeral().into()).await; - let info_hash = InfoHash::from_str("9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d").unwrap(); + let info_hash = InfoHash::from_str("9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d").unwrap(); // DevSkim: ignore DS173237 env.add_torrent_peer(&info_hash, &PeerBuilder::default().into()); diff --git a/tests/servers/api/v1/contract/context/whitelist.rs b/tests/servers/api/v1/contract/context/whitelist.rs index 78850d3bf..945cb00b5 100644 --- a/tests/servers/api/v1/contract/context/whitelist.rs +++ b/tests/servers/api/v1/contract/context/whitelist.rs @@ -23,7 +23,7 @@ async fn should_allow_whitelisting_a_torrent() { let env = Started::new(&configuration::ephemeral().into()).await; let request_id = Uuid::new_v4(); - let info_hash = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); + let info_hash = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); // DevSkim: ignore DS173237 let response = Client::new(env.get_connection_info()) .whitelist_a_torrent(&info_hash, Some(headers_with_request_id(request_id))) @@ -31,7 +31,8 @@ async fn should_allow_whitelisting_a_torrent() { assert_ok(response).await; assert!( - env.whitelist_manager + env.http_api_container + .whitelist_manager .is_info_hash_whitelisted(&InfoHash::from_str(&info_hash).unwrap()) .await ); @@ -45,7 +46,7 @@ async fn should_allow_whitelisting_a_torrent_that_has_been_already_whitelisted() let env = Started::new(&configuration::ephemeral().into()).await; - let info_hash = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); + let info_hash = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); // DevSkim: ignore DS173237 let api_client = Client::new(env.get_connection_info()); @@ -72,7 +73,7 @@ async fn should_not_allow_whitelisting_a_torrent_for_unauthenticated_users() { let env = Started::new(&configuration::ephemeral().into()).await; - let info_hash = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); + let info_hash = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); // DevSkim: ignore DS173237 let request_id = Uuid::new_v4(); @@ -109,7 +110,7 @@ async fn should_fail_when_the_torrent_cannot_be_whitelisted() { let env = Started::new(&configuration::ephemeral().into()).await; - let info_hash = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); + let info_hash = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); // DevSkim: ignore DS173237 force_database_error(&env.database); @@ -164,10 +165,14 @@ async fn should_allow_removing_a_torrent_from_the_whitelist() { let env = Started::new(&configuration::ephemeral().into()).await; - let hash = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); + let hash = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); // DevSkim: ignore DS173237 let info_hash = InfoHash::from_str(&hash).unwrap(); - env.whitelist_manager.add_torrent_to_whitelist(&info_hash).await.unwrap(); + env.http_api_container + .whitelist_manager + .add_torrent_to_whitelist(&info_hash) + .await + .unwrap(); let request_id = Uuid::new_v4(); @@ -176,7 +181,12 @@ async fn should_allow_removing_a_torrent_from_the_whitelist() { .await; assert_ok(response).await; - assert!(!env.whitelist_manager.is_info_hash_whitelisted(&info_hash).await); + assert!( + !env.http_api_container + .whitelist_manager + .is_info_hash_whitelisted(&info_hash) + .await + ); env.stop().await; } @@ -187,7 +197,7 @@ async fn should_not_fail_trying_to_remove_a_non_whitelisted_torrent_from_the_whi let env = Started::new(&configuration::ephemeral().into()).await; - let non_whitelisted_torrent_hash = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); + let non_whitelisted_torrent_hash = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); // DevSkim: ignore DS173237 let request_id = Uuid::new_v4(); @@ -235,9 +245,13 @@ async fn should_fail_when_the_torrent_cannot_be_removed_from_the_whitelist() { let env = Started::new(&configuration::ephemeral().into()).await; - let hash = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); + let hash = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); // DevSkim: ignore DS173237 let info_hash = InfoHash::from_str(&hash).unwrap(); - env.whitelist_manager.add_torrent_to_whitelist(&info_hash).await.unwrap(); + env.http_api_container + .whitelist_manager + .add_torrent_to_whitelist(&info_hash) + .await + .unwrap(); force_database_error(&env.database); @@ -263,10 +277,14 @@ async fn should_not_allow_removing_a_torrent_from_the_whitelist_for_unauthentica let env = Started::new(&configuration::ephemeral().into()).await; - let hash = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); + let hash = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); // DevSkim: ignore DS173237 let info_hash = InfoHash::from_str(&hash).unwrap(); - env.whitelist_manager.add_torrent_to_whitelist(&info_hash).await.unwrap(); + env.http_api_container + .whitelist_manager + .add_torrent_to_whitelist(&info_hash) + .await + .unwrap(); let request_id = Uuid::new_v4(); @@ -281,7 +299,11 @@ async fn should_not_allow_removing_a_torrent_from_the_whitelist_for_unauthentica "Expected logs to contain: ERROR ... API ... request_id={request_id}" ); - env.whitelist_manager.add_torrent_to_whitelist(&info_hash).await.unwrap(); + env.http_api_container + .whitelist_manager + .add_torrent_to_whitelist(&info_hash) + .await + .unwrap(); let request_id = Uuid::new_v4(); @@ -305,9 +327,13 @@ async fn should_allow_reload_the_whitelist_from_the_database() { let env = Started::new(&configuration::ephemeral().into()).await; - let hash = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); + let hash = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); // DevSkim: ignore DS173237 let info_hash = InfoHash::from_str(&hash).unwrap(); - env.whitelist_manager.add_torrent_to_whitelist(&info_hash).await.unwrap(); + env.http_api_container + .whitelist_manager + .add_torrent_to_whitelist(&info_hash) + .await + .unwrap(); let request_id = Uuid::new_v4(); @@ -336,9 +362,13 @@ async fn should_fail_when_the_whitelist_cannot_be_reloaded_from_the_database() { let env = Started::new(&configuration::ephemeral().into()).await; - let hash = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); + let hash = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); // DevSkim: ignore DS173237 let info_hash = InfoHash::from_str(&hash).unwrap(); - env.whitelist_manager.add_torrent_to_whitelist(&info_hash).await.unwrap(); + env.http_api_container + .whitelist_manager + .add_torrent_to_whitelist(&info_hash) + .await + .unwrap(); force_database_error(&env.database); diff --git a/tests/servers/http/environment.rs b/tests/servers/http/environment.rs index 5bf1d1c65..07ff2bc8c 100644 --- a/tests/servers/http/environment.rs +++ b/tests/servers/http/environment.rs @@ -2,36 +2,28 @@ use std::sync::Arc; use bittorrent_primitives::info_hash::InfoHash; use futures::executor::block_on; -use torrust_tracker_configuration::{Configuration, Core, HttpTracker}; +use torrust_tracker_configuration::Configuration; use torrust_tracker_lib::bootstrap::app::{initialize_app_container, initialize_global_services}; use torrust_tracker_lib::bootstrap::jobs::make_rust_tls; -use torrust_tracker_lib::core::announce_handler::AnnounceHandler; +use torrust_tracker_lib::container::HttpTrackerContainer; use torrust_tracker_lib::core::authentication::handler::KeysHandler; -use torrust_tracker_lib::core::authentication::service::AuthenticationService; use torrust_tracker_lib::core::databases::Database; -use torrust_tracker_lib::core::scrape_handler::ScrapeHandler; -use torrust_tracker_lib::core::statistics::event::sender::Sender; use torrust_tracker_lib::core::statistics::repository::Repository; use torrust_tracker_lib::core::torrent::repository::in_memory::InMemoryTorrentRepository; -use torrust_tracker_lib::core::whitelist; use torrust_tracker_lib::core::whitelist::manager::WhitelistManager; use torrust_tracker_lib::servers::http::server::{HttpServer, Launcher, Running, Stopped}; use torrust_tracker_lib::servers::registar::Registar; use torrust_tracker_primitives::peer; pub struct Environment { - pub core_config: Arc, - pub http_tracker_config: Arc, + pub http_tracker_container: Arc, + pub database: Arc>, - pub announce_handler: Arc, - pub scrape_handler: Arc, pub in_memory_torrent_repository: Arc, pub keys_handler: Arc, - pub authentication_service: Arc, - pub stats_event_sender: Arc>>, pub stats_repository: Arc, - pub whitelist_authorization: Arc, pub whitelist_manager: Arc, + pub registar: Registar, pub server: HttpServer, } @@ -54,28 +46,33 @@ impl Environment { .http_trackers .clone() .expect("missing HTTP tracker configuration"); + let http_tracker_config = Arc::new(http_tracker[0].clone()); - let config = Arc::new(http_tracker[0].clone()); - - let bind_to = config.bind_address; + let bind_to = http_tracker_config.bind_address; - let tls = block_on(make_rust_tls(&config.tsl_config)).map(|tls| tls.expect("tls config failed")); + let tls = block_on(make_rust_tls(&http_tracker_config.tsl_config)).map(|tls| tls.expect("tls config failed")); let server = HttpServer::new(Launcher::new(bind_to, tls)); - Self { - http_tracker_config: config, - core_config: Arc::new(configuration.core.clone()), - database: app_container.database.clone(), + let http_tracker_container = Arc::new(HttpTrackerContainer { + core_config: app_container.core_config.clone(), + http_tracker_config: http_tracker_config.clone(), announce_handler: app_container.announce_handler.clone(), scrape_handler: app_container.scrape_handler.clone(), + whitelist_authorization: app_container.whitelist_authorization.clone(), + stats_event_sender: app_container.stats_event_sender.clone(), + authentication_service: app_container.authentication_service.clone(), + }); + + Self { + http_tracker_container, + + database: app_container.database.clone(), in_memory_torrent_repository: app_container.in_memory_torrent_repository.clone(), keys_handler: app_container.keys_handler.clone(), - authentication_service: app_container.authentication_service.clone(), - stats_event_sender: app_container.stats_event_sender.clone(), stats_repository: app_container.stats_repository.clone(), - whitelist_authorization: app_container.whitelist_authorization.clone(), whitelist_manager: app_container.whitelist_manager.clone(), + registar: Registar::default(), server, } @@ -84,30 +81,18 @@ impl Environment { #[allow(dead_code)] pub async fn start(self) -> Environment { Environment { - http_tracker_config: self.http_tracker_config, - core_config: self.core_config.clone(), + http_tracker_container: self.http_tracker_container.clone(), + database: self.database.clone(), - announce_handler: self.announce_handler.clone(), - scrape_handler: self.scrape_handler.clone(), in_memory_torrent_repository: self.in_memory_torrent_repository.clone(), keys_handler: self.keys_handler.clone(), - authentication_service: self.authentication_service.clone(), - whitelist_authorization: self.whitelist_authorization.clone(), - stats_event_sender: self.stats_event_sender.clone(), stats_repository: self.stats_repository.clone(), whitelist_manager: self.whitelist_manager.clone(), + registar: self.registar.clone(), server: self .server - .start( - self.core_config, - self.announce_handler, - self.scrape_handler, - self.authentication_service, - self.whitelist_authorization, - self.stats_event_sender, - self.registar.give_form(), - ) + .start(self.http_tracker_container, self.registar.give_form()) .await .unwrap(), } @@ -121,20 +106,15 @@ impl Environment { pub async fn stop(self) -> Environment { Environment { - http_tracker_config: self.http_tracker_config, - core_config: self.core_config, + http_tracker_container: self.http_tracker_container, + database: self.database, - announce_handler: self.announce_handler, - scrape_handler: self.scrape_handler, in_memory_torrent_repository: self.in_memory_torrent_repository, keys_handler: self.keys_handler, - authentication_service: self.authentication_service, - whitelist_authorization: self.whitelist_authorization, - stats_event_sender: self.stats_event_sender, stats_repository: self.stats_repository, whitelist_manager: self.whitelist_manager, - registar: Registar::default(), + registar: Registar::default(), server: self.server.stop().await.unwrap(), } } diff --git a/tests/servers/http/v1/contract.rs b/tests/servers/http/v1/contract.rs index 33faf8578..f434467fc 100644 --- a/tests/servers/http/v1/contract.rs +++ b/tests/servers/http/v1/contract.rs @@ -449,7 +449,7 @@ mod for_all_config_modes { ) .await; - let announce_policy = env.core_config.announce_policy; + let announce_policy = env.http_tracker_container.core_config.announce_policy; assert_announce_response( response, @@ -490,7 +490,7 @@ mod for_all_config_modes { ) .await; - let announce_policy = env.core_config.announce_policy; + let announce_policy = env.http_tracker_container.core_config.announce_policy; // It should only contain the previously announced peer assert_announce_response( @@ -543,7 +543,7 @@ mod for_all_config_modes { ) .await; - let announce_policy = env.core_config.announce_policy; + let announce_policy = env.http_tracker_container.core_config.announce_policy; // The newly announced peer is not included on the response peer list, // but all the previously announced peers should be included regardless the IP version they are using. @@ -872,7 +872,10 @@ mod for_all_config_modes { let peers = env.in_memory_torrent_repository.get_torrent_peers(&info_hash); let peer_addr = peers[0].peer_addr; - assert_eq!(peer_addr.ip(), env.core_config.net.external_ip.unwrap()); + assert_eq!( + peer_addr.ip(), + env.http_tracker_container.core_config.net.external_ip.unwrap() + ); assert_ne!(peer_addr.ip(), IpAddr::from_str("2.2.2.2").unwrap()); env.stop().await; @@ -914,7 +917,10 @@ mod for_all_config_modes { let peers = env.in_memory_torrent_repository.get_torrent_peers(&info_hash); let peer_addr = peers[0].peer_addr; - assert_eq!(peer_addr.ip(), env.core_config.net.external_ip.unwrap()); + assert_eq!( + peer_addr.ip(), + env.http_tracker_container.core_config.net.external_ip.unwrap() + ); assert_ne!(peer_addr.ip(), IpAddr::from_str("2.2.2.2").unwrap()); env.stop().await; diff --git a/tests/servers/udp/contract.rs b/tests/servers/udp/contract.rs index 0767d5f07..f6a1feb06 100644 --- a/tests/servers/udp/contract.rs +++ b/tests/servers/udp/contract.rs @@ -229,7 +229,7 @@ mod receiving_an_announce_request { logging::setup(); let env = Started::new(&configuration::ephemeral().into()).await; - let ban_service = env.ban_service.clone(); + let ban_service = env.udp_tracker_container.ban_service.clone(); let client = match UdpTrackerClient::new(env.bind_address(), DEFAULT_TIMEOUT).await { Ok(udp_tracker_client) => udp_tracker_client, diff --git a/tests/servers/udp/environment.rs b/tests/servers/udp/environment.rs index b3a2670e8..af0b04e5c 100644 --- a/tests/servers/udp/environment.rs +++ b/tests/servers/udp/environment.rs @@ -2,18 +2,13 @@ use std::net::SocketAddr; use std::sync::Arc; use bittorrent_primitives::info_hash::InfoHash; -use tokio::sync::RwLock; -use torrust_tracker_configuration::{Configuration, Core, UdpTracker, DEFAULT_TIMEOUT}; +use torrust_tracker_configuration::{Configuration, DEFAULT_TIMEOUT}; use torrust_tracker_lib::bootstrap::app::{initialize_app_container, initialize_global_services}; -use torrust_tracker_lib::core::announce_handler::AnnounceHandler; +use torrust_tracker_lib::container::UdpTrackerContainer; use torrust_tracker_lib::core::databases::Database; -use torrust_tracker_lib::core::scrape_handler::ScrapeHandler; -use torrust_tracker_lib::core::statistics::event::sender::Sender; use torrust_tracker_lib::core::statistics::repository::Repository; use torrust_tracker_lib::core::torrent::repository::in_memory::InMemoryTorrentRepository; -use torrust_tracker_lib::core::whitelist; use torrust_tracker_lib::servers::registar::Registar; -use torrust_tracker_lib::servers::udp::server::banning::BanService; use torrust_tracker_lib::servers::udp::server::spawner::Spawner; use torrust_tracker_lib::servers::udp::server::states::{Running, Stopped}; use torrust_tracker_lib::servers::udp::server::Server; @@ -23,16 +18,12 @@ pub struct Environment where S: std::fmt::Debug + std::fmt::Display, { - pub core_config: Arc, - pub config: Arc, + pub udp_tracker_container: Arc, + pub database: Arc>, pub in_memory_torrent_repository: Arc, - pub announce_handler: Arc, - pub scrape_handler: Arc, - pub whitelist_authorization: Arc, - pub stats_event_sender: Arc>>, pub stats_repository: Arc, - pub ban_service: Arc>, + pub registar: Registar, pub server: Server, } @@ -55,25 +46,31 @@ impl Environment { let app_container = initialize_app_container(configuration); - let udp_tracker = configuration.udp_trackers.clone().expect("missing UDP tracker configuration"); + let udp_tracker_configurations = configuration.udp_trackers.clone().expect("missing UDP tracker configuration"); - let config = Arc::new(udp_tracker[0].clone()); + let udp_tracker_config = Arc::new(udp_tracker_configurations[0].clone()); - let bind_to = config.bind_address; + let bind_to = udp_tracker_config.bind_address; let server = Server::new(Spawner::new(bind_to)); - Self { - core_config: Arc::new(configuration.core.clone()), - config, - database: app_container.database.clone(), - in_memory_torrent_repository: app_container.in_memory_torrent_repository.clone(), + let udp_tracker_container = Arc::new(UdpTrackerContainer { + udp_tracker_config: udp_tracker_config.clone(), + core_config: app_container.core_config.clone(), announce_handler: app_container.announce_handler.clone(), scrape_handler: app_container.scrape_handler.clone(), whitelist_authorization: app_container.whitelist_authorization.clone(), stats_event_sender: app_container.stats_event_sender.clone(), - stats_repository: app_container.stats_repository.clone(), ban_service: app_container.ban_service.clone(), + }); + + Self { + udp_tracker_container, + + database: app_container.database.clone(), + in_memory_torrent_repository: app_container.in_memory_torrent_repository.clone(), + stats_repository: app_container.stats_repository.clone(), + registar: Registar::default(), server, } @@ -81,31 +78,19 @@ impl Environment { #[allow(dead_code)] pub async fn start(self) -> Environment { - let cookie_lifetime = self.config.cookie_lifetime; + let cookie_lifetime = self.udp_tracker_container.udp_tracker_config.cookie_lifetime; + Environment { - core_config: self.core_config.clone(), - config: self.config, + udp_tracker_container: self.udp_tracker_container.clone(), + database: self.database.clone(), in_memory_torrent_repository: self.in_memory_torrent_repository.clone(), - announce_handler: self.announce_handler.clone(), - scrape_handler: self.scrape_handler.clone(), - whitelist_authorization: self.whitelist_authorization.clone(), - stats_event_sender: self.stats_event_sender.clone(), stats_repository: self.stats_repository.clone(), - ban_service: self.ban_service.clone(), + registar: self.registar.clone(), server: self .server - .start( - self.core_config, - self.announce_handler, - self.scrape_handler, - self.whitelist_authorization, - self.stats_event_sender, - self.ban_service, - self.registar.give_form(), - cookie_lifetime, - ) + .start(self.udp_tracker_container, self.registar.give_form(), cookie_lifetime) .await .unwrap(), } @@ -126,16 +111,12 @@ impl Environment { .expect("it should stop the environment within the timeout"); Environment { - core_config: self.core_config, - config: self.config, + udp_tracker_container: self.udp_tracker_container, + database: self.database, in_memory_torrent_repository: self.in_memory_torrent_repository, - announce_handler: self.announce_handler, - scrape_handler: self.scrape_handler, - whitelist_authorization: self.whitelist_authorization, - stats_event_sender: self.stats_event_sender, stats_repository: self.stats_repository, - ban_service: self.ban_service, + registar: Registar::default(), server: stopped.expect("it stop the udp tracker service"), }