1use tokio::net::TcpStream;
2use tokio::time::{timeout, Duration};
3use futures::stream::FuturesUnordered;
4use futures::StreamExt;
5use std::ops::RangeInclusive;
6
7
8pub async fn scan_port(ip: &str, port: u16, timeout_ms: u64) -> bool {
10 let addr = format!("{}:{}", ip, port);
11 match timeout(Duration::from_millis(timeout_ms), TcpStream::connect(&addr)).await {
12 Ok(Ok(_)) => true,
13 _ => false,
14 }
15}
16
17
18pub async fn scan_ports_list(ip: &str, ports: &[u16], timeout_ms: u64) -> Vec<u16> {
20 let mut open_ports = Vec::new();
21 let mut tasks = FuturesUnordered::new();
22
23 let ip_loc = ip.to_string();
24
25 for &port in ports {
26 let ip = ip_loc.clone();
27 tasks.push(async move {
28 if scan_port(&ip, port, timeout_ms).await {
29 Some(port)
30 } else {
31 None
32 }
33 });
34 }
35
36 while let Some(result) = tasks.next().await {
37 if let Some(port) = result {
38 open_ports.push(port);
39 }
40 }
41 open_ports
42}
43
44
45pub async fn scan_ports_range(ip: &str, range: RangeInclusive<u16>, timeout_ms: u64) -> Vec<u16> {
47 let mut open_ports = Vec::new();
48 let mut tasks = FuturesUnordered::new();
49
50 let ip_loc = ip.to_string();
51
52 for port in range {
53 let ip = ip_loc.clone();
54 tasks.push(async move {
55 if scan_port(&ip, port, timeout_ms).await {
56 Some(port)
57 } else {
58 None
59 }
60 });
61 }
62
63 while let Some(result) = tasks.next().await {
64 if let Some(port) = result {
65 open_ports.push(port);
66 }
67 }
68 open_ports
69
70}