Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 1 addition & 11 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ axum-extra = { version = "0", features = ["query"] }
axum-server = { version = "0", features = ["tls-rustls"] }
chrono = { version = "0", default-features = false, features = ["clock"] }
clap = { version = "4", features = ["derive", "env"] }
colored = "2"
config = "0"
crossbeam-skiplist = "0.1"
dashmap = "5.5.3"
Expand All @@ -62,7 +61,7 @@ ringbuf = "0"
serde = { version = "1", features = ["derive"] }
serde_bencode = "0"
serde_bytes = "0"
serde_json = "1"
serde_json = { version = "1", features = ["preserve_order"] }
serde_repr = "0"
thiserror = "1"
tokio = { version = "1", features = ["macros", "net", "rt-multi-thread", "signal", "sync"] }
Expand Down
52 changes: 25 additions & 27 deletions src/console/clients/checker/checks/health.rs
Original file line number Diff line number Diff line change
@@ -1,51 +1,49 @@
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 super::structs::{CheckerOutput, Status};
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 ...");
#[allow(clippy::missing_panics_doc)]
pub async fn run(health_checks: &Vec<ServiceUrl>, check_results: &mut Vec<CheckResult>) -> Vec<CheckerOutput> {
let mut health_checkers: Vec<CheckerOutput> = Vec::new();

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)),
let mut health_checker = CheckerOutput {
url: health_check_url.to_string(),
status: Status {
code: String::new(),
message: String::new(),
},
};
match run_health_check(health_check_url.clone()).await {
Ok(()) => {
check_results.push(Ok(()));
health_checker.status.code = "ok".to_string();
}
Err(err) => {
check_results.push(Err(err));
health_checker.status.code = "error".to_string();
health_checker.status.message = "Health API is failing.".to_string();
}
}
health_checkers.push(health_checker);
}
health_checkers
}

async fn run_health_check(url: Url, console: &Console) -> Result<(), CheckError> {
async fn run_health_check(url: Url) -> 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 })
}
Err(_) => Err(CheckError::HealthCheckError { url }),
}
}
29 changes: 19 additions & 10 deletions src/console/clients/checker/checks/http.rs
Original file line number Diff line number Diff line change
@@ -1,47 +1,56 @@
use std::str::FromStr;

use colored::Colorize;
use log::debug;
use reqwest::Url as ServiceUrl;
use torrust_tracker_primitives::info_hash::InfoHash;
use url::Url;

use crate::console::clients::checker::console::Console;
use crate::console::clients::checker::printer::Printer;
use super::structs::{CheckerOutput, Status};
use crate::console::clients::checker::service::{CheckError, CheckResult};
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 ...");
#[allow(clippy::missing_panics_doc)]
pub async fn run(http_trackers: &Vec<ServiceUrl>, check_results: &mut Vec<CheckResult>) -> Vec<CheckerOutput> {
let mut http_checkers: Vec<CheckerOutput> = Vec::new();

for http_tracker in http_trackers {
let colored_tracker_url = http_tracker.to_string().yellow();
let mut http_checker = CheckerOutput {
url: http_tracker.to_string(),
status: Status {
code: String::new(),
message: String::new(),
},
};

match check_http_announce(http_tracker).await {
Ok(()) => {
check_results.push(Ok(()));
console.println(&format!("{} - Announce at {} is OK", "✓".green(), colored_tracker_url));
http_checker.status.code = "ok".to_string();
}
Err(err) => {
check_results.push(Err(err));
console.println(&format!("{} - Announce at {} is failing", "✗".red(), colored_tracker_url));
http_checker.status.code = "error".to_string();
http_checker.status.message = "Announce is failing.".to_string();
}
}

match check_http_scrape(http_tracker).await {
Ok(()) => {
check_results.push(Ok(()));
console.println(&format!("{} - Scrape at {} is OK", "✓".green(), colored_tracker_url));
http_checker.status.code = "ok".to_string();
}
Err(err) => {
check_results.push(Err(err));
console.println(&format!("{} - Scrape at {} is failing", "✗".red(), colored_tracker_url));
http_checker.status.code = "error".to_string();
http_checker.status.message = "Scrape is failing.".to_string();
}
}
http_checkers.push(http_checker);
}
http_checkers
}

async fn check_http_announce(tracker_url: &Url) -> Result<(), CheckError> {
Expand Down
1 change: 1 addition & 0 deletions src/console/clients/checker/checks/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod health;
pub mod http;
pub mod structs;
pub mod udp;
12 changes: 12 additions & 0 deletions src/console/clients/checker/checks/structs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize)]
pub struct Status {
pub code: String,
pub message: String,
}
#[derive(Serialize, Deserialize)]
pub struct CheckerOutput {
pub url: String,
pub status: Status,
}
41 changes: 24 additions & 17 deletions src/console/clients/checker/checks/udp.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,31 @@
use std::net::SocketAddr;

use aquatic_udp_protocol::{Port, TransactionId};
use colored::Colorize;
use hex_literal::hex;
use log::debug;
use torrust_tracker_primitives::info_hash::InfoHash;

use crate::console::clients::checker::console::Console;
use crate::console::clients::checker::printer::Printer;
use crate::console::clients::checker::checks::structs::{CheckerOutput, Status};
use crate::console::clients::checker::service::{CheckError, CheckResult};
use crate::console::clients::udp::checker;

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 ...");
#[allow(clippy::missing_panics_doc)]
pub async fn run(udp_trackers: &Vec<SocketAddr>, check_results: &mut Vec<CheckResult>) -> Vec<CheckerOutput> {
let mut udp_checkers: Vec<CheckerOutput> = Vec::new();

for udp_tracker in udp_trackers {
debug!("UDP tracker: {:?}", udp_tracker);
let mut checker_output = CheckerOutput {
url: udp_tracker.to_string(),
status: Status {
code: String::new(),
message: String::new(),
},
};

let colored_tracker_url = udp_tracker.to_string().yellow();
debug!("UDP tracker: {:?}", udp_tracker);

let transaction_id = TransactionId(RANDOM_TRANSACTION_ID);

Expand All @@ -32,7 +37,8 @@ pub async fn run(udp_trackers: &Vec<SocketAddr>, console: &Console, check_result
check_results.push(Err(CheckError::UdpError {
socket_addr: *udp_tracker,
}));
console.println(&format!("{} - Can't connect to socket {}", "✗".red(), colored_tracker_url));
checker_output.status.code = "error".to_string();
checker_output.status.message = "Can't connect to socket.".to_string();
break;
};

Expand All @@ -42,11 +48,8 @@ pub async fn run(udp_trackers: &Vec<SocketAddr>, console: &Console, check_result
check_results.push(Err(CheckError::UdpError {
socket_addr: *udp_tracker,
}));
console.println(&format!(
"{} - Can't make tracker connection request to {}",
"✗".red(),
colored_tracker_url
));
checker_output.status.code = "error".to_string();
checker_output.status.message = "Can't make tracker connection request.".to_string();
break;
};

Expand All @@ -60,13 +63,14 @@ pub async fn run(udp_trackers: &Vec<SocketAddr>, console: &Console, check_result
.is_ok()
{
check_results.push(Ok(()));
console.println(&format!("{} - Announce at {} is OK", "✓".green(), colored_tracker_url));
checker_output.status.code = "ok".to_string();
} 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));
checker_output.status.code = "error".to_string();
checker_output.status.message = "Announce is failing.".to_string();
}

debug!("Send scrape request");
Expand All @@ -75,13 +79,16 @@ pub async fn run(udp_trackers: &Vec<SocketAddr>, console: &Console, check_result

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));
checker_output.status.code = "ok".to_string();
} 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));
checker_output.status.code = "error".to_string();
checker_output.status.message = "Scrape is failing.".to_string();
}
udp_checkers.push(checker_output);
}
udp_checkers
}
15 changes: 9 additions & 6 deletions src/console/clients/checker/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::sync::Arc;

use reqwest::Url;

use super::checks;
use super::checks::{self};
use super::config::Configuration;
use super::console::Console;
use crate::console::clients::checker::printer::Printer;
Expand All @@ -26,16 +26,19 @@ impl Service {
/// # Errors
///
/// Will return OK is all checks pass or an array with the check errors.
#[allow(clippy::missing_panics_doc)]
pub async fn run_checks(&self) -> Vec<CheckResult> {
self.console.println("Running checks for trackers ...");

let mut check_results = vec![];

checks::udp::run(&self.config.udp_trackers, &self.console, &mut check_results).await;
let udp_checkers = checks::udp::run(&self.config.udp_trackers, &mut check_results).await;

let http_checkers = checks::http::run(&self.config.http_trackers, &mut check_results).await;

checks::http::run(&self.config.http_trackers, &self.console, &mut check_results).await;
let health_checkers = checks::health::run(&self.config.health_checks, &mut check_results).await;

checks::health::run(&self.config.health_checks, &self.console, &mut check_results).await;
let json_output =
serde_json::json!({ "udp_trackers": udp_checkers, "http_trackers": http_checkers, "health_checks": health_checkers });
self.console.println(&serde_json::to_string_pretty(&json_output).unwrap());

check_results
}
Expand Down