forked from torrust/torrust-tracker
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge torrust#664: Tracker Checker: check UDP trackers
873f98d refactor: [torrust#639] Tracker Checker: extract mod for Health checks (Jose Celano) 70924ed refactor: [torrust#639] Tracker Checker: extract mod for HTTP checks (Jose Celano) 77c32a1 refactor: [torrust#639] Tracker Checker: extract mod for UDP checks (Jose Celano) 592c0dd fix: add timeouts to UdpClient operations (Jose Celano) 6b74c66 feat: [torrust#639] Tracker Checker. Setup logging (Jose Celano) bbfca2c feat: [torrust#639] Tracker Checker. Check UDP trackers (Jose Celano) 661b521 chore: [torrust#639] add cargo dependency: hex_literal (Jose Celano) 1b92b77 refactor: [torrust#639] UDP client. Extract aquatic reponses wrappers (Jose Celano) a2e123c refactor: [torrust#639] UDP client. Extract command handlers (Jose Celano) 011fdb7 refactor: [torrust#639] Tracker Checker: extract checker:Client to check UDP servers (Jose Celano) 3b735a7 refactor: [torrust#639] Tracker Checker: prepare outout for UDP checks (Jose Celano) Pull request description: Add checks for UDP trackers to the Tracker Checker. The output will look like the following: ```output Running checks for trackers ... UDP trackers ... ✓ - Announce at 127.0.0.1:6969 is OK ✓ - Scrape at 127.0.0.1:6969 is OK HTTP trackers ... ✓ - Announce at http://127.0.0.1:7070/ is OK ✓ - Scrape at http://127.0.0.1:7070/ is OK Health checks ... ✓ - Health API at http://127.0.0.1:1313/health_check is OK ``` See subtasks in torrust#639 ACKs for top commit: josecelano: ACK 873f98d Tree-SHA512: 04c5472c72d6c8b6659c07d18b9240e1320249c3cc7455c727e7030a8e18aebd7bee0962ab1f3153323fafbc722a9ec8efad2c67d36ff826e00d5b9ef3c234f4
- Loading branch information
Showing
14 changed files
with
675 additions
and
325 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
use std::time::Duration; | ||
|
||
use colored::Colorize; | ||
use reqwest::{Client as HttpClient, Url, Url as ServiceUrl}; | ||
|
||
use crate::console::clients::checker::console::Console; | ||
use crate::console::clients::checker::printer::Printer; | ||
use crate::console::clients::checker::service::{CheckError, CheckResult}; | ||
|
||
pub async fn run(health_checks: &Vec<ServiceUrl>, console: &Console, check_results: &mut Vec<CheckResult>) { | ||
console.println("Health checks ..."); | ||
|
||
for health_check_url in health_checks { | ||
match run_health_check(health_check_url.clone(), console).await { | ||
Ok(()) => check_results.push(Ok(())), | ||
Err(err) => check_results.push(Err(err)), | ||
} | ||
} | ||
} | ||
|
||
async fn run_health_check(url: Url, console: &Console) -> Result<(), CheckError> { | ||
let client = HttpClient::builder().timeout(Duration::from_secs(5)).build().unwrap(); | ||
|
||
let colored_url = url.to_string().yellow(); | ||
|
||
match client.get(url.clone()).send().await { | ||
Ok(response) => { | ||
if response.status().is_success() { | ||
console.println(&format!("{} - Health API at {} is OK", "✓".green(), colored_url)); | ||
Ok(()) | ||
} else { | ||
console.eprintln(&format!( | ||
"{} - Health API at {} is failing: {:?}", | ||
"✗".red(), | ||
colored_url, | ||
response | ||
)); | ||
Err(CheckError::HealthCheckError { url }) | ||
} | ||
} | ||
Err(err) => { | ||
console.eprintln(&format!( | ||
"{} - Health API at {} is failing: {:?}", | ||
"✗".red(), | ||
colored_url, | ||
err | ||
)); | ||
Err(CheckError::HealthCheckError { url }) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
use std::str::FromStr; | ||
|
||
use colored::Colorize; | ||
use log::debug; | ||
use reqwest::Url as ServiceUrl; | ||
use url::Url; | ||
|
||
use crate::console::clients::checker::console::Console; | ||
use crate::console::clients::checker::printer::Printer; | ||
use crate::console::clients::checker::service::{CheckError, CheckResult}; | ||
use crate::shared::bit_torrent::info_hash::InfoHash; | ||
use crate::shared::bit_torrent::tracker::http::client::requests::announce::QueryBuilder; | ||
use crate::shared::bit_torrent::tracker::http::client::responses::announce::Announce; | ||
use crate::shared::bit_torrent::tracker::http::client::responses::scrape; | ||
use crate::shared::bit_torrent::tracker::http::client::{requests, Client}; | ||
|
||
pub async fn run(http_trackers: &Vec<ServiceUrl>, console: &Console, check_results: &mut Vec<CheckResult>) { | ||
console.println("HTTP trackers ..."); | ||
|
||
for http_tracker in http_trackers { | ||
let colored_tracker_url = http_tracker.to_string().yellow(); | ||
|
||
match check_http_announce(http_tracker).await { | ||
Ok(()) => { | ||
check_results.push(Ok(())); | ||
console.println(&format!("{} - Announce at {} is OK", "✓".green(), colored_tracker_url)); | ||
} | ||
Err(err) => { | ||
check_results.push(Err(err)); | ||
console.println(&format!("{} - Announce at {} is failing", "✗".red(), colored_tracker_url)); | ||
} | ||
} | ||
|
||
match check_http_scrape(http_tracker).await { | ||
Ok(()) => { | ||
check_results.push(Ok(())); | ||
console.println(&format!("{} - Scrape at {} is OK", "✓".green(), colored_tracker_url)); | ||
} | ||
Err(err) => { | ||
check_results.push(Err(err)); | ||
console.println(&format!("{} - Scrape at {} is failing", "✗".red(), colored_tracker_url)); | ||
} | ||
} | ||
} | ||
} | ||
|
||
async fn check_http_announce(tracker_url: &Url) -> Result<(), CheckError> { | ||
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"); | ||
|
||
// todo: HTTP request could panic.For example, if the server is not accessible. | ||
// We should change the client to catch that error and return a `CheckError`. | ||
// Otherwise the checking process will stop. The idea is to process all checks | ||
// and return a final report. | ||
let response = Client::new(tracker_url.clone()) | ||
.announce(&QueryBuilder::with_default_values().with_info_hash(&info_hash).query()) | ||
.await; | ||
|
||
if let Ok(body) = response.bytes().await { | ||
if let Ok(_announce_response) = serde_bencode::from_bytes::<Announce>(&body) { | ||
Ok(()) | ||
} else { | ||
debug!("announce body {:#?}", body); | ||
Err(CheckError::HttpError { | ||
url: tracker_url.clone(), | ||
}) | ||
} | ||
} else { | ||
Err(CheckError::HttpError { | ||
url: tracker_url.clone(), | ||
}) | ||
} | ||
} | ||
|
||
async fn check_http_scrape(url: &Url) -> Result<(), CheckError> { | ||
let info_hashes: Vec<String> = 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"); | ||
|
||
// todo: HTTP request could panic.For example, if the server is not accessible. | ||
// We should change the client to catch that error and return a `CheckError`. | ||
// Otherwise the checking process will stop. The idea is to process all checks | ||
// and return a final report. | ||
let response = Client::new(url.clone()).scrape(&query).await; | ||
|
||
if let Ok(body) = response.bytes().await { | ||
if let Ok(_scrape_response) = scrape::Response::try_from_bencoded(&body) { | ||
Ok(()) | ||
} else { | ||
debug!("scrape body {:#?}", body); | ||
Err(CheckError::HttpError { url: url.clone() }) | ||
} | ||
} else { | ||
Err(CheckError::HttpError { url: url.clone() }) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
pub mod health; | ||
pub mod http; | ||
pub mod udp; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
use std::net::SocketAddr; | ||
|
||
use aquatic_udp_protocol::{Port, TransactionId}; | ||
use colored::Colorize; | ||
use hex_literal::hex; | ||
use log::debug; | ||
|
||
use crate::console::clients::checker::console::Console; | ||
use crate::console::clients::checker::printer::Printer; | ||
use crate::console::clients::checker::service::{CheckError, CheckResult}; | ||
use crate::console::clients::udp::checker; | ||
use crate::shared::bit_torrent::info_hash::InfoHash; | ||
|
||
const ASSIGNED_BY_OS: u16 = 0; | ||
const RANDOM_TRANSACTION_ID: i32 = -888_840_697; | ||
|
||
pub async fn run(udp_trackers: &Vec<SocketAddr>, console: &Console, check_results: &mut Vec<CheckResult>) { | ||
console.println("UDP trackers ..."); | ||
|
||
for udp_tracker in udp_trackers { | ||
debug!("UDP tracker: {:?}", udp_tracker); | ||
|
||
let colored_tracker_url = udp_tracker.to_string().yellow(); | ||
|
||
let transaction_id = TransactionId(RANDOM_TRANSACTION_ID); | ||
|
||
let mut client = checker::Client::default(); | ||
|
||
debug!("Bind and connect"); | ||
|
||
let Ok(bound_to) = client.bind_and_connect(ASSIGNED_BY_OS, udp_tracker).await else { | ||
check_results.push(Err(CheckError::UdpError { | ||
socket_addr: *udp_tracker, | ||
})); | ||
console.println(&format!("{} - Can't connect to socket {}", "✗".red(), colored_tracker_url)); | ||
break; | ||
}; | ||
|
||
debug!("Send connection request"); | ||
|
||
let Ok(connection_id) = client.send_connection_request(transaction_id).await else { | ||
check_results.push(Err(CheckError::UdpError { | ||
socket_addr: *udp_tracker, | ||
})); | ||
console.println(&format!( | ||
"{} - Can't make tracker connection request to {}", | ||
"✗".red(), | ||
colored_tracker_url | ||
)); | ||
break; | ||
}; | ||
|
||
let info_hash = InfoHash(hex!("9c38422213e30bff212b30c360d26f9a02136422")); // # DevSkim: ignore DS173237 | ||
|
||
debug!("Send announce request"); | ||
|
||
if (client | ||
.send_announce_request(connection_id, transaction_id, info_hash, Port(bound_to.port())) | ||
.await) | ||
.is_ok() | ||
{ | ||
check_results.push(Ok(())); | ||
console.println(&format!("{} - Announce at {} is OK", "✓".green(), colored_tracker_url)); | ||
} else { | ||
let err = CheckError::UdpError { | ||
socket_addr: *udp_tracker, | ||
}; | ||
check_results.push(Err(err)); | ||
console.println(&format!("{} - Announce at {} is failing", "✗".red(), colored_tracker_url)); | ||
} | ||
|
||
debug!("Send scrape request"); | ||
|
||
let info_hashes = vec![InfoHash(hex!("9c38422213e30bff212b30c360d26f9a02136422"))]; // # DevSkim: ignore DS173237 | ||
|
||
if (client.send_scrape_request(connection_id, transaction_id, info_hashes).await).is_ok() { | ||
check_results.push(Ok(())); | ||
console.println(&format!("{} - Announce at {} is OK", "✓".green(), colored_tracker_url)); | ||
} else { | ||
let err = CheckError::UdpError { | ||
socket_addr: *udp_tracker, | ||
}; | ||
check_results.push(Err(err)); | ||
console.println(&format!("{} - Announce at {} is failing", "✗".red(), colored_tracker_url)); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
pub mod app; | ||
pub mod checks; | ||
pub mod config; | ||
pub mod console; | ||
pub mod logger; | ||
|
Oops, something went wrong.