use std::{net::IpAddr, time::Duration};
#[derive(Debug, PartialEq)]
pub enum TargetMethod {
Ping,
GET { ok_codes: Vec<u16> },
}
pub struct Target {
pub id: u32,
pub addr: String,
/// Check interval in ms
pub interval: u32,
pub method: TargetMethod,
}
pub enum CheckResponse {
Ping { duration: Duration },
GET { status_code: u16 },
}
impl Target {
/// Check the target using the assigned method.
///
/// # Errors
///
/// Errors should be treated as "unknown".
///
/// Returns an error if:
/// - IpAddr parse fails
/// - reqwest fails to send the request
pub async fn check(&self) -> Result<(bool, Option<CheckResponse>), Box<dyn std::error::Error>> {
match &self.method {
TargetMethod::Ping => {
let ip: IpAddr = self.addr.parse()?;
match surge_ping::ping(ip, &[0u8; 8]).await {
Ok((_, duration)) => Ok((true, Some(CheckResponse::Ping { duration }))),
Err(_) => Ok((false, None)),
}
}
TargetMethod::GET { ok_codes } => {
let response = reqwest::get(self.addr.clone()).await?;
let status_code = response.status().as_u16();
if ok_codes.contains(&status_code) {
Ok((true, Some(CheckResponse::GET { status_code })))
} else {
Ok((false, None))
}
}
}
}
}