use tokio::net::TcpStream;
use tokio::time::{timeout, Duration};
use futures::stream::FuturesUnordered;
use futures::StreamExt;
use std::ops::RangeInclusive;
pub async fn scan_port(ip: &str, port: u16, timeout_ms: u64) -> bool {
let addr = format!("{}:{}", ip, port);
match timeout(Duration::from_millis(timeout_ms), TcpStream::connect(&addr)).await {
Ok(Ok(_)) => true,
_ => false,
}
}
pub async fn scan_ports_list(ip: &str, ports: &[u16], timeout_ms: u64) -> Vec<u16> {
let mut open_ports = Vec::new();
let mut tasks = FuturesUnordered::new();
let ip_loc = ip.to_string();
for &port in ports {
let ip = ip_loc.clone();
tasks.push(async move {
if scan_port(&ip, port, timeout_ms).await {
Some(port)
} else {
None
}
});
}
while let Some(result) = tasks.next().await {
if let Some(port) = result {
open_ports.push(port);
}
}
open_ports
}
pub async fn scan_ports_range(ip: &str, range: RangeInclusive<u16>, timeout_ms: u64) -> Vec<u16> {
let mut open_ports = Vec::new();
let mut tasks = FuturesUnordered::new();
let ip_loc = ip.to_string();
for port in range {
let ip = ip_loc.clone();
tasks.push(async move {
if scan_port(&ip, port, timeout_ms).await {
Some(port)
} else {
None
}
});
}
while let Some(result) = tasks.next().await {
if let Some(port) = result {
open_ports.push(port);
}
}
open_ports
}