1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
use async_std::net::{IpAddr, TcpStream};
use futures::future::FutureExt;
use futures::stream::StreamExt;
const CONCURRENCY: usize = 100;
pub async fn is_port_open(ip: IpAddr, port: u16) -> bool {
TcpStream::connect((ip, port)).await.is_ok()
}
pub async fn get_open_ports(ip: IpAddr, ports: Vec<u16>, concurrency: Option<usize>) -> Vec<u16> {
let open_ports_futures = ports
.into_iter()
.map(|port| is_port_open(ip, port).map(move |is_open| (port, is_open)));
futures::stream::iter(open_ports_futures)
.buffer_unordered(concurrency.unwrap_or(CONCURRENCY))
.filter_map(|item| async move {
if item.1 {
Some(item.0)
} else {
None
}
})
.collect::<Vec<u16>>()
.await
}
pub async fn get_all_open_ports(ip: IpAddr, concurrency: Option<usize>) -> Vec<u16> {
let range = (0..u16::max_value()).collect::<Vec<u16>>();
get_open_ports(ip, range, concurrency).await
}
#[cfg(test)]
mod tests {
use async_std::net::{IpAddr, Ipv4Addr, TcpListener};
use pretty_assertions::assert_eq;
#[async_std::test]
async fn is_port_open() {
let _listener = TcpListener::bind("127.0.0.1:4040").await.unwrap();
let ip_v4_addr = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1));
let is_port_4040_open = super::is_port_open(ip_v4_addr, 4040).await;
let is_port_4041_open = super::is_port_open(ip_v4_addr, 4041).await;
assert_eq!(is_port_4040_open, true);
assert_eq!(is_port_4041_open, false);
}
#[async_std::test]
async fn get_open_ports() {
let _listener = TcpListener::bind("127.0.0.1:4045").await.unwrap();
let ip_v4_addr = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1));
let open_ports_from_0_to_10 =
super::get_open_ports(ip_v4_addr, (0..10).collect::<Vec<u16>>(), Some(100)).await;
let open_ports_from_4000_to_4100 =
super::get_open_ports(ip_v4_addr, (4000..4100).collect::<Vec<u16>>(), None).await;
assert_eq!(open_ports_from_0_to_10.len(), 0);
assert_eq!(open_ports_from_4000_to_4100.len(), 1);
assert_eq!(open_ports_from_4000_to_4100[0], 4045);
}
#[async_std::test]
#[ignore]
async fn get_all_open_ports() {
let _listener1 = TcpListener::bind("127.0.0.1:4050").await.unwrap();
let _listener2 = TcpListener::bind("127.0.0.1:4060").await.unwrap();
let ip_v4_addr = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1));
let open_ports = super::get_all_open_ports(ip_v4_addr, Some(100)).await;
assert!(open_ports.len() > 0);
assert!(open_ports.contains(&4050));
assert!(open_ports.contains(&4060));
}
}