diff --git a/packages/configuration/src/v1/core.rs b/packages/configuration/src/v1/core.rs index 17ac36ee0..5d8ab0b33 100644 --- a/packages/configuration/src/v1/core.rs +++ b/packages/configuration/src/v1/core.rs @@ -1,8 +1,7 @@ -use std::net::{IpAddr, Ipv4Addr}; - use serde::{Deserialize, Serialize}; use torrust_tracker_primitives::TrackerMode; +use super::network::Network; use crate::v1::database::Database; use crate::AnnouncePolicy; @@ -13,10 +12,6 @@ pub struct Core { #[serde(default = "Core::default_mode")] pub mode: TrackerMode, - // Database configuration. - #[serde(default = "Core::default_database")] - pub database: Database, - /// See [`AnnouncePolicy::interval`] #[serde(default = "AnnouncePolicy::default_interval")] pub announce_interval: u32, @@ -25,20 +20,6 @@ pub struct Core { #[serde(default = "AnnouncePolicy::default_interval_min")] pub min_announce_interval: u32, - /// Weather the tracker is behind a reverse proxy or not. - /// If the tracker is behind a reverse proxy, the `X-Forwarded-For` header - /// sent from the proxy will be used to get the client's IP address. - #[serde(default = "Core::default_on_reverse_proxy")] - pub on_reverse_proxy: bool, - - /// The external IP address of the tracker. If the client is using a - /// loopback IP address, this IP address will be used instead. If the peer - /// is using a loopback IP address, the tracker assumes that the peer is - /// in the same network as the tracker and will use the tracker's IP - /// address instead. - #[serde(default = "Core::default_external_ip")] - pub external_ip: Option, - /// Weather the tracker should collect statistics about tracker usage. /// If enabled, the tracker will collect statistics like the number of /// connections handled, the number of announce requests handled, etc. @@ -71,6 +52,14 @@ pub struct Core { /// enabled. #[serde(default = "Core::default_remove_peerless_torrents")] pub remove_peerless_torrents: bool, + + // Database configuration. + #[serde(default = "Core::default_database")] + pub database: Database, + + // Network configuration. + #[serde(default = "Core::default_network")] + pub net: Network, } impl Default for Core { @@ -79,16 +68,15 @@ impl Default for Core { Self { mode: Self::default_mode(), - database: Self::default_database(), announce_interval: announce_policy.interval, min_announce_interval: announce_policy.interval_min, max_peer_timeout: Self::default_max_peer_timeout(), - on_reverse_proxy: Self::default_on_reverse_proxy(), - external_ip: Self::default_external_ip(), tracker_usage_statistics: Self::default_tracker_usage_statistics(), persistent_torrent_completed_stat: Self::default_persistent_torrent_completed_stat(), inactive_peer_cleanup_interval: Self::default_inactive_peer_cleanup_interval(), remove_peerless_torrents: Self::default_remove_peerless_torrents(), + database: Self::default_database(), + net: Self::default_network(), } } } @@ -98,19 +86,6 @@ impl Core { TrackerMode::Public } - fn default_database() -> Database { - Database::default() - } - - fn default_on_reverse_proxy() -> bool { - false - } - - #[allow(clippy::unnecessary_wraps)] - fn default_external_ip() -> Option { - Some(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0))) - } - fn default_tracker_usage_statistics() -> bool { true } @@ -130,4 +105,12 @@ impl Core { fn default_remove_peerless_torrents() -> bool { true } + + fn default_database() -> Database { + Database::default() + } + + fn default_network() -> Network { + Network::default() + } } diff --git a/packages/configuration/src/v1/mod.rs b/packages/configuration/src/v1/mod.rs index 5b3cad3ea..d96e1335c 100644 --- a/packages/configuration/src/v1/mod.rs +++ b/packages/configuration/src/v1/mod.rs @@ -200,17 +200,19 @@ //! mode = "public" //! announce_interval = 120 //! min_announce_interval = 120 -//! on_reverse_proxy = false -//! external_ip = "0.0.0.0" //! tracker_usage_statistics = true //! persistent_torrent_completed_stat = false //! max_peer_timeout = 900 //! inactive_peer_cleanup_interval = 600 //! remove_peerless_torrents = true //! -//! [core.database] -//! driver = "Sqlite3" -//! path = "./storage/tracker/lib/database/sqlite3.db" +//! [core.database] +//! driver = "Sqlite3" +//! path = "./storage/tracker/lib/database/sqlite3.db" +//! +//! [core.net] +//! external_ip = "0.0.0.0" +//! on_reverse_proxy = false //! //! [[udp_trackers]] //! enabled = false @@ -240,6 +242,7 @@ pub mod database; pub mod health_check_api; pub mod http_tracker; pub mod logging; +pub mod network; pub mod tracker_api; pub mod udp_tracker; @@ -307,7 +310,7 @@ impl Configuration { /// and `None` otherwise. #[must_use] pub fn get_ext_ip(&self) -> Option { - self.core.external_ip.as_ref().map(|external_ip| *external_ip) + self.core.net.external_ip.as_ref().map(|external_ip| *external_ip) } /// Saves the default configuration at the given path. @@ -387,18 +390,20 @@ mod tests { mode = "public" announce_interval = 120 min_announce_interval = 120 - on_reverse_proxy = false - external_ip = "0.0.0.0" tracker_usage_statistics = true persistent_torrent_completed_stat = false max_peer_timeout = 900 inactive_peer_cleanup_interval = 600 remove_peerless_torrents = true - [core.database] - driver = "Sqlite3" - path = "./storage/tracker/lib/database/sqlite3.db" - + [core.database] + driver = "Sqlite3" + path = "./storage/tracker/lib/database/sqlite3.db" + + [core.net] + external_ip = "0.0.0.0" + on_reverse_proxy = false + [[udp_trackers]] enabled = false bind_address = "0.0.0.0:6969" @@ -443,7 +448,10 @@ mod tests { fn configuration_should_contain_the_external_ip() { let configuration = Configuration::default(); - assert_eq!(configuration.core.external_ip, Some(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)))); + assert_eq!( + configuration.core.net.external_ip, + Some(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0))) + ); } #[test] diff --git a/packages/configuration/src/v1/network.rs b/packages/configuration/src/v1/network.rs new file mode 100644 index 000000000..8e53d419c --- /dev/null +++ b/packages/configuration/src/v1/network.rs @@ -0,0 +1,41 @@ +use std::net::{IpAddr, Ipv4Addr}; + +use serde::{Deserialize, Serialize}; + +#[allow(clippy::struct_excessive_bools)] +#[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Clone)] +pub struct Network { + /// The external IP address of the tracker. If the client is using a + /// loopback IP address, this IP address will be used instead. If the peer + /// is using a loopback IP address, the tracker assumes that the peer is + /// in the same network as the tracker and will use the tracker's IP + /// address instead. + #[serde(default = "Network::default_external_ip")] + pub external_ip: Option, + + /// Weather the tracker is behind a reverse proxy or not. + /// If the tracker is behind a reverse proxy, the `X-Forwarded-For` header + /// sent from the proxy will be used to get the client's IP address. + #[serde(default = "Network::default_on_reverse_proxy")] + pub on_reverse_proxy: bool, +} + +impl Default for Network { + fn default() -> Self { + Self { + external_ip: Self::default_external_ip(), + on_reverse_proxy: Self::default_on_reverse_proxy(), + } + } +} + +impl Network { + #[allow(clippy::unnecessary_wraps)] + fn default_external_ip() -> Option { + Some(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0))) + } + + fn default_on_reverse_proxy() -> bool { + false + } +} diff --git a/packages/test-helpers/src/configuration.rs b/packages/test-helpers/src/configuration.rs index fe05407d9..9c6c0fe11 100644 --- a/packages/test-helpers/src/configuration.rs +++ b/packages/test-helpers/src/configuration.rs @@ -64,7 +64,7 @@ pub fn ephemeral() -> Configuration { pub fn ephemeral_with_reverse_proxy() -> Configuration { let mut cfg = ephemeral(); - cfg.core.on_reverse_proxy = true; + cfg.core.net.on_reverse_proxy = true; cfg } @@ -74,7 +74,7 @@ pub fn ephemeral_with_reverse_proxy() -> Configuration { pub fn ephemeral_without_reverse_proxy() -> Configuration { let mut cfg = ephemeral(); - cfg.core.on_reverse_proxy = false; + cfg.core.net.on_reverse_proxy = false; cfg } @@ -124,7 +124,7 @@ pub fn ephemeral_mode_private_whitelisted() -> Configuration { pub fn ephemeral_with_external_ip(ip: IpAddr) -> Configuration { let mut cfg = ephemeral(); - cfg.core.external_ip = Some(ip); + cfg.core.net.external_ip = Some(ip); cfg } diff --git a/src/core/mod.rs b/src/core/mod.rs index c5171ab58..f4eb2c335 100644 --- a/src/core/mod.rs +++ b/src/core/mod.rs @@ -320,16 +320,18 @@ //! announce_interval = 120 //! min_announce_interval = 120 //! max_peer_timeout = 900 -//! on_reverse_proxy = false -//! external_ip = "2.137.87.41" //! tracker_usage_statistics = true //! persistent_torrent_completed_stat = true //! inactive_peer_cleanup_interval = 600 //! remove_peerless_torrents = false //! -//! [core.database] -//! driver = "Sqlite3" -//! path = "./storage/tracker/lib/database/sqlite3.db" +//! [core.database] +//! driver = "Sqlite3" +//! path = "./storage/tracker/lib/database/sqlite3.db" +//! +//! [core.net] +//! on_reverse_proxy = false +//! external_ip = "2.137.87.41" //! ``` //! //! Refer to the [`configuration` module documentation](https://docs.rs/torrust-tracker-configuration) to get more information about all options. @@ -564,13 +566,13 @@ impl Tracker { stats_event_sender, stats_repository, database, - external_ip: config.external_ip, + external_ip: config.net.external_ip, policy: TrackerPolicy::new( config.remove_peerless_torrents, config.max_peer_timeout, config.persistent_torrent_completed_stat, ), - on_reverse_proxy: config.on_reverse_proxy, + on_reverse_proxy: config.net.on_reverse_proxy, }) } diff --git a/src/lib.rs b/src/lib.rs index b94da4717..bf9257123 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -172,12 +172,10 @@ //! //! [core] //! announce_interval = 120 -//! external_ip = "0.0.0.0" //! inactive_peer_cleanup_interval = 600 //! max_peer_timeout = 900 //! min_announce_interval = 120 //! mode = "public" -//! on_reverse_proxy = false //! persistent_torrent_completed_stat = false //! remove_peerless_torrents = true //! tracker_usage_statistics = true @@ -186,6 +184,10 @@ //! driver = "Sqlite3" //! path = "./storage/tracker/lib/database/sqlite3.db" //! +//! [core.net] +//! external_ip = "0.0.0.0" +//! on_reverse_proxy = false +//! //! [[udp_trackers]] //! bind_address = "0.0.0.0:6969" //! enabled = false diff --git a/src/servers/http/v1/services/announce.rs b/src/servers/http/v1/services/announce.rs index 253140fbc..eee5e4688 100644 --- a/src/servers/http/v1/services/announce.rs +++ b/src/servers/http/v1/services/announce.rs @@ -151,7 +151,7 @@ mod tests { fn tracker_with_an_ipv6_external_ip(stats_event_sender: Box) -> Tracker { let mut configuration = configuration::ephemeral(); - configuration.core.external_ip = Some(IpAddr::V6(Ipv6Addr::new( + configuration.core.net.external_ip = Some(IpAddr::V6(Ipv6Addr::new( 0x6969, 0x6969, 0x6969, 0x6969, 0x6969, 0x6969, 0x6969, 0x6969, ))); diff --git a/src/servers/udp/handlers.rs b/src/servers/udp/handlers.rs index 858d6606c..36825f084 100644 --- a/src/servers/udp/handlers.rs +++ b/src/servers/udp/handlers.rs @@ -425,7 +425,7 @@ mod tests { } pub fn with_external_ip(mut self, external_ip: &str) -> Self { - self.configuration.core.external_ip = Some(external_ip.to_owned().parse().expect("valid IP address")); + self.configuration.core.net.external_ip = Some(external_ip.to_owned().parse().expect("valid IP address")); self }