11use std:: net:: SocketAddr ;
22use std:: sync:: Arc ;
33
4+ use aquatic_udp_protocol:: { ConnectRequest , Response , TransactionId } ;
45use axum:: extract:: State ;
56use axum:: Json ;
67use torrust_tracker_configuration:: Configuration ;
78
89use super :: resources:: Report ;
910use super :: responses;
11+ use crate :: shared:: bit_torrent:: udp:: client:: new_udp_tracker_client_connected;
1012
1113/// If port 0 is specified in the configuration the OS will automatically
1214/// assign a free port. But we do now know in from the configuration.
@@ -23,6 +25,8 @@ pub(crate) async fn health_check_handler(State(config): State<Arc<Configuration>
2325 // running service, after starting it as we do for testing with ephemeral
2426 // configurations.
2527
28+ // Health check for API
29+
2630 if config. http_api . enabled {
2731 let addr: SocketAddr = config. http_api . bind_address . parse ( ) . expect ( "invalid socket address for API" ) ;
2832
@@ -35,6 +39,8 @@ pub(crate) async fn health_check_handler(State(config): State<Arc<Configuration>
3539 }
3640 }
3741
42+ // Health check for HTTP Trackers
43+
3844 for http_tracker_config in & config. http_trackers {
3945 if !http_tracker_config. enabled {
4046 continue ;
@@ -56,7 +62,22 @@ pub(crate) async fn health_check_handler(State(config): State<Arc<Configuration>
5662 }
5763 }
5864
59- // todo: for all UDP Trackers, if enabled, check if is healthy
65+ // Health check for UDP Trackers
66+
67+ for udp_tracker_config in & config. udp_trackers {
68+ if !udp_tracker_config. enabled {
69+ continue ;
70+ }
71+
72+ let addr: SocketAddr = udp_tracker_config
73+ . bind_address
74+ . parse ( )
75+ . expect ( "invalid socket address for UDP tracker" ) ;
76+
77+ if addr. port ( ) != UNKNOWN_PORT && !can_connect_to_udp_tracker ( & addr. to_string ( ) ) . await {
78+ return responses:: error ( format ! ( "UDP Tracker is not healthy. Can't connect to: {addr}" ) ) ;
79+ }
80+ }
6081
6182 responses:: ok ( )
6283}
@@ -67,3 +88,18 @@ async fn get_req_is_ok(url: &str) -> bool {
6788 Err ( _err) => false ,
6889 }
6990}
91+
92+ /// Tries to connect to an UDP tracker. It returns true if it succeeded.
93+ async fn can_connect_to_udp_tracker ( url : & str ) -> bool {
94+ let client = new_udp_tracker_client_connected ( url) . await ;
95+
96+ let connect_request = ConnectRequest {
97+ transaction_id : TransactionId ( 123 ) ,
98+ } ;
99+
100+ client. send ( connect_request. into ( ) ) . await ;
101+
102+ let response = client. receive ( ) . await ;
103+
104+ matches ! ( response, Response :: Connect ( _connect_response) )
105+ }
0 commit comments