74 lines
2.2 KiB
Rust
74 lines
2.2 KiB
Rust
use std::net::{IpAddr, SocketAddr};
|
|
use std::time::Duration;
|
|
|
|
use anyhow::Result;
|
|
use tokio::net::TcpStream;
|
|
use tokio::time::timeout;
|
|
|
|
/// TCP Connectivity module for checking TCP connections
|
|
pub struct TcpConnector {
|
|
timeout: Duration,
|
|
}
|
|
|
|
impl TcpConnector {
|
|
/// Create a new TCP connector with the default timeout (5 seconds)
|
|
pub fn new() -> Self {
|
|
Self {
|
|
timeout: Duration::from_secs(5),
|
|
}
|
|
}
|
|
|
|
/// Create a new TCP connector with a custom timeout
|
|
pub fn with_timeout(timeout: Duration) -> Self {
|
|
Self { timeout }
|
|
}
|
|
|
|
/// Check if a TCP port is open on a host
|
|
pub async fn check_port<A: Into<IpAddr>>(&self, host: A, port: u16) -> Result<bool> {
|
|
let addr = SocketAddr::new(host.into(), port);
|
|
let connect_future = TcpStream::connect(addr);
|
|
|
|
match timeout(self.timeout, connect_future).await {
|
|
Ok(Ok(_)) => Ok(true),
|
|
Ok(Err(_)) => Ok(false),
|
|
Err(_) => Ok(false), // Timeout occurred
|
|
}
|
|
}
|
|
|
|
/// Check if multiple TCP ports are open on a host
|
|
pub async fn check_ports<A: Into<IpAddr> + Clone>(&self, host: A, ports: &[u16]) -> Result<Vec<(u16, bool)>> {
|
|
let mut results = Vec::with_capacity(ports.len());
|
|
|
|
for &port in ports {
|
|
let is_open = self.check_port(host.clone(), port).await?;
|
|
results.push((port, is_open));
|
|
}
|
|
|
|
Ok(results)
|
|
}
|
|
|
|
/// Check if a host is reachable on the network using ICMP ping
|
|
pub async fn ping<S: AsRef<str>>(&self, host: S) -> Result<bool> {
|
|
// Convert to owned strings to avoid borrowing issues
|
|
let host_str = host.as_ref().to_string();
|
|
let timeout_secs = self.timeout.as_secs().to_string();
|
|
|
|
// Run the ping command with explicit arguments
|
|
let status = tokio::process::Command::new("ping")
|
|
.arg("-c")
|
|
.arg("1") // Just one ping
|
|
.arg("-W")
|
|
.arg(timeout_secs) // Timeout in seconds
|
|
.arg(host_str) // Host to ping
|
|
.output()
|
|
.await?;
|
|
|
|
Ok(status.status.success())
|
|
}
|
|
}
|
|
|
|
impl Default for TcpConnector {
|
|
fn default() -> Self {
|
|
Self::new()
|
|
}
|
|
} |