@@ -9,6 +9,7 @@ use serde::{Deserialize, Serialize};
99use thiserror:: Error ;
1010use tokio:: sync:: RwLock ;
1111use torrust_index_located_error:: { Located , LocatedError } ;
12+ use url:: { ParseError , Url } ;
1213
1314/// Information required for loading config
1415#[ derive( Debug , Default , Clone ) ]
@@ -99,6 +100,17 @@ pub enum Error {
99100 Infallible ,
100101}
101102
103+ /// Errors that can occur validating the configuration.
104+ #[ derive( Error , Debug ) ]
105+ pub enum ValidationError {
106+ /// Unable to load the configuration from the configuration file.
107+ #[ error( "Invalid tracker URL: {source}" ) ]
108+ InvalidTrackerUrl { source : LocatedError < ' static , ParseError > } ,
109+
110+ #[ error( "UDP private trackers are not supported. URL schemes for private tracker URLs must be HTTP ot HTTPS" ) ]
111+ UdpTrackersInPrivateModeNotSupported ,
112+ }
113+
102114impl From < ConfigError > for Error {
103115 #[ track_caller]
104116 fn from ( err : ConfigError ) -> Self {
@@ -149,6 +161,11 @@ impl TrackerMode {
149161 pub fn is_open ( & self ) -> bool {
150162 matches ! ( self , TrackerMode :: Public | TrackerMode :: Whitelisted )
151163 }
164+
165+ #[ must_use]
166+ pub fn is_close ( & self ) -> bool {
167+ !self . is_open ( )
168+ }
152169}
153170
154171/// Configuration for the associated tracker.
@@ -550,6 +567,42 @@ impl Configuration {
550567
551568 settings_lock. net . base_url . clone ( )
552569 }
570+
571+ /// # Errors
572+ ///
573+ /// Will return an error if the configuration is invalid.
574+ pub async fn validate ( & self ) -> Result < ( ) , ValidationError > {
575+ self . validate_tracker_config ( ) . await
576+ }
577+
578+ /// # Errors
579+ ///
580+ /// Will return an error if the `tracker` configuration section is invalid.
581+ pub async fn validate_tracker_config ( & self ) -> Result < ( ) , ValidationError > {
582+ let settings_lock = self . settings . read ( ) . await ;
583+
584+ let tracker_mode = settings_lock. tracker . mode . clone ( ) ;
585+ let tracker_url = settings_lock. tracker . url . clone ( ) ;
586+
587+ let tracker_url = match parse_url ( & tracker_url) {
588+ Ok ( url) => url,
589+ Err ( err) => {
590+ return Err ( ValidationError :: InvalidTrackerUrl {
591+ source : Located ( err) . into ( ) ,
592+ } )
593+ }
594+ } ;
595+
596+ if tracker_mode. is_close ( ) && ( tracker_url. scheme ( ) != "http" && tracker_url. scheme ( ) != "https" ) {
597+ return Err ( ValidationError :: UdpTrackersInPrivateModeNotSupported ) ;
598+ }
599+
600+ Ok ( ( ) )
601+ }
602+ }
603+
604+ fn parse_url ( url_str : & str ) -> Result < Url , url:: ParseError > {
605+ Url :: parse ( url_str)
553606}
554607
555608/// The public index configuration.
0 commit comments