1
1
use std:: net:: SocketAddr ;
2
+ use std:: str:: FromStr ;
2
3
use std:: sync:: Arc ;
3
4
use std:: time:: Duration ;
4
5
5
6
use colored:: Colorize ;
6
- use reqwest:: { Client , Url } ;
7
+ use reqwest:: { Client as HttpClient , Url } ;
7
8
8
9
use super :: config:: Configuration ;
9
10
use super :: console:: Console ;
10
11
use crate :: console:: clients:: checker:: printer:: Printer ;
12
+ use crate :: shared:: bit_torrent:: info_hash:: InfoHash ;
13
+ use crate :: shared:: bit_torrent:: tracker:: http:: client:: requests:: announce:: QueryBuilder ;
14
+ use crate :: shared:: bit_torrent:: tracker:: http:: client:: responses:: announce:: Announce ;
15
+ use crate :: shared:: bit_torrent:: tracker:: http:: client:: Client ;
11
16
12
17
pub struct Service {
13
18
pub ( crate ) config : Arc < Configuration > ,
@@ -19,7 +24,7 @@ pub type CheckResult = Result<(), CheckError>;
19
24
#[ derive( Debug ) ]
20
25
pub enum CheckError {
21
26
UdpError ,
22
- HttpError ,
27
+ HttpError { url : Url } ,
23
28
HealthCheckError { url : Url } ,
24
29
}
25
30
@@ -30,10 +35,15 @@ impl Service {
30
35
pub async fn run_checks ( & self ) -> Vec < CheckResult > {
31
36
self . console . println ( "Running checks for trackers ..." ) ;
32
37
38
+ let mut check_results = vec ! [ ] ;
39
+
33
40
self . check_udp_trackers ( ) ;
34
- self . check_http_trackers ( ) ;
35
41
36
- self . run_health_checks ( ) . await
42
+ self . check_http_trackers ( & mut check_results) . await ;
43
+
44
+ self . run_health_checks ( & mut check_results) . await ;
45
+
46
+ check_results
37
47
}
38
48
39
49
fn check_udp_trackers ( & self ) {
@@ -44,47 +54,67 @@ impl Service {
44
54
}
45
55
}
46
56
47
- fn check_http_trackers ( & self ) {
57
+ async fn check_http_trackers ( & self , check_results : & mut Vec < CheckResult > ) {
48
58
self . console . println ( "HTTP trackers ..." ) ;
49
59
50
60
for http_tracker in & self . config . http_trackers {
51
- self . check_http_tracker ( http_tracker) ;
61
+ match self . check_http_tracker ( http_tracker) . await {
62
+ Ok ( ( ) ) => check_results. push ( Ok ( ( ) ) ) ,
63
+ Err ( err) => check_results. push ( Err ( err) ) ,
64
+ }
52
65
}
53
66
}
54
67
55
- async fn run_health_checks ( & self ) -> Vec < CheckResult > {
68
+ async fn run_health_checks ( & self , check_results : & mut Vec < CheckResult > ) {
56
69
self . console . println ( "Health checks ..." ) ;
57
70
58
- let mut check_results = vec ! [ ] ;
59
-
60
71
for health_check_url in & self . config . health_checks {
61
72
match self . run_health_check ( health_check_url. clone ( ) ) . await {
62
73
Ok ( ( ) ) => check_results. push ( Ok ( ( ) ) ) ,
63
74
Err ( err) => check_results. push ( Err ( err) ) ,
64
75
}
65
76
}
66
-
67
- check_results
68
77
}
69
78
70
79
fn check_udp_tracker ( & self , address : & SocketAddr ) {
71
80
// todo:
72
81
// - Make announce request
73
82
// - Make scrape request
74
83
self . console
75
- . println ( & format ! ( "{} - UDP tracker at {:?} is OK (TODO)" , "✓" . green( ) , address) ) ;
84
+ . println ( & format ! ( "{} - UDP tracker at udp:// {:?} is OK (TODO)" , "✓" . green( ) , address) ) ;
76
85
}
77
86
78
- fn check_http_tracker ( & self , url : & Url ) {
79
- // todo:
80
- // - Make announce request
81
- // - Make scrape request
82
- self . console
83
- . println ( & format ! ( "{} - HTTP tracker at {} is OK (TODO)" , "✓" . green( ) , url) ) ;
87
+ async fn check_http_tracker ( & self , url : & Url ) -> Result < ( ) , CheckError > {
88
+ let info_hash_str = "9c38422213e30bff212b30c360d26f9a02136422" . to_string ( ) ; // # DevSkim: ignore DS173237
89
+ let info_hash = InfoHash :: from_str ( & info_hash_str) . expect ( "a valid info-hash is required" ) ;
90
+
91
+ // Announce request
92
+
93
+ let response = Client :: new ( url. clone ( ) )
94
+ . announce ( & QueryBuilder :: with_default_values ( ) . with_info_hash ( & info_hash) . query ( ) )
95
+ . await ;
96
+
97
+ if let Ok ( body) = response. bytes ( ) . await {
98
+ if let Ok ( _announce_response) = serde_bencode:: from_bytes :: < Announce > ( & body) {
99
+ self . console . println ( & format ! ( "{} - Announce at {} is OK" , "✓" . green( ) , url) ) ;
100
+
101
+ Ok ( ( ) )
102
+ } else {
103
+ self . console . println ( & format ! ( "{} - Announce at {} failing" , "✗" . red( ) , url) ) ;
104
+ Err ( CheckError :: HttpError { url : url. clone ( ) } )
105
+ }
106
+ } else {
107
+ self . console . println ( & format ! ( "{} - Announce at {} failing" , "✗" . red( ) , url) ) ;
108
+ Err ( CheckError :: HttpError { url : url. clone ( ) } )
109
+ }
110
+
111
+ // Scrape request
112
+
113
+ // todo
84
114
}
85
115
86
116
async fn run_health_check ( & self , url : Url ) -> Result < ( ) , CheckError > {
87
- let client = Client :: builder ( ) . timeout ( Duration :: from_secs ( 5 ) ) . build ( ) . unwrap ( ) ;
117
+ let client = HttpClient :: builder ( ) . timeout ( Duration :: from_secs ( 5 ) ) . build ( ) . unwrap ( ) ;
88
118
89
119
match client. get ( url. clone ( ) ) . send ( ) . await {
90
120
Ok ( response) => {
0 commit comments