@@ -11,6 +11,7 @@ use futures::stream::FuturesUnordered;
11
11
use std:: {
12
12
io:: ErrorKind ,
13
13
net:: { IpAddr , Shutdown , SocketAddr } ,
14
+ num:: NonZeroU8 ,
14
15
time:: Duration ,
15
16
} ;
16
17
@@ -26,6 +27,7 @@ pub struct Scanner {
26
27
ips : Vec < IpAddr > ,
27
28
batch_size : u16 ,
28
29
timeout : Duration ,
30
+ tries : NonZeroU8 ,
29
31
greppable : bool ,
30
32
port_strategy : PortStrategy ,
31
33
accessible : bool ,
@@ -36,13 +38,15 @@ impl Scanner {
36
38
ips : & [ IpAddr ] ,
37
39
batch_size : u16 ,
38
40
timeout : Duration ,
41
+ tries : u8 ,
39
42
greppable : bool ,
40
43
port_strategy : PortStrategy ,
41
44
accessible : bool ,
42
45
) -> Self {
43
46
Self {
44
47
batch_size,
45
48
timeout,
49
+ tries : NonZeroU8 :: new ( std:: cmp:: max ( tries, 1 ) ) . unwrap ( ) ,
46
50
greppable,
47
51
port_strategy,
48
52
ips : ips. iter ( ) . map ( |ip| ip. to_owned ( ) ) . collect ( ) ,
@@ -87,54 +91,66 @@ impl Scanner {
87
91
open_sockets
88
92
}
89
93
90
- /// Given a port , scan it.
94
+ /// Given a socket , scan it self.tries times .
91
95
/// Turns the address into a SocketAddr
92
96
/// Deals with the <result> type
93
97
/// If it experiences error ErrorKind::Other then too many files are open and it Panics!
94
- /// ese any other error, it returns the error in Result as a string
95
- /// If no errors occur, it returns the port number in Result to signify the port is open.
98
+ /// Else any other error, it returns the error in Result as a string
99
+ /// If no errors occur, it returns the port number in Result to signify the port is open.
96
100
/// This function mainly deals with the logic of Results handling.
97
101
/// # Example
98
102
///
99
- /// self.scan_port(10:u16 )
103
+ /// self.scan_socket(socket )
100
104
///
101
105
/// Note: `self` must contain `self.ip`.
102
106
async fn scan_socket ( & self , socket : SocketAddr ) -> io:: Result < SocketAddr > {
103
- match self . connect ( socket) . await {
104
- Ok ( x) => {
105
- debug ! (
106
- "Connection was successful, shutting down stream {}" ,
107
- & socket
108
- ) ;
109
- match x. shutdown ( Shutdown :: Both ) {
110
- Err ( e) => debug ! ( "Shutdown stream error {}" , & e) ,
111
- _ => { }
112
- }
113
- if !self . greppable {
114
- if self . accessible {
115
- println ! ( "Open {}" , socket. to_string( ) ) ;
116
- } else {
117
- println ! ( "Open {}" , socket. to_string( ) . purple( ) ) ;
107
+ let tries = self . tries . get ( ) ;
108
+
109
+ debug ! ( "self.tries: {}" , tries) ;
110
+
111
+ for nr_try in 1 ..=tries {
112
+ debug ! ( "Try number: {}" , nr_try) ;
113
+
114
+ match self . connect ( socket) . await {
115
+ Ok ( x) => {
116
+ debug ! (
117
+ "Connection was successful, shutting down stream {}" ,
118
+ & socket
119
+ ) ;
120
+ if let Err ( e) = x. shutdown ( Shutdown :: Both ) {
121
+ debug ! ( "Shutdown stream error {}" , & e) ;
122
+ }
123
+ if !self . greppable {
124
+ if self . accessible {
125
+ println ! ( "Open {}" , socket. to_string( ) ) ;
126
+ } else {
127
+ println ! ( "Open {}" , socket. to_string( ) . purple( ) ) ;
128
+ }
118
129
}
130
+
131
+ debug ! ( "Return Ok after {} tries" , nr_try) ;
132
+ return Ok ( socket) ;
119
133
}
134
+ Err ( e) => {
135
+ let error_string = e. to_string ( ) ;
120
136
121
- Ok ( socket )
122
- }
123
- Err ( e ) => match e . kind ( ) {
124
- ErrorKind :: Other => {
125
- if e . to_string ( ) . contains ( "No route to host " )
126
- || e . to_string ( ) . contains ( "Network is unreachable" )
127
- {
128
- debug ! ( "Socket connect error: {} {}" , & e . to_string ( ) , & socket ) ;
129
- Err ( io :: Error :: new ( io :: ErrorKind :: Other , e . to_string ( ) ) )
130
- } else {
131
- debug ! ( "Socket connect error: {} {}" , & e . to_string ( ) , & socket ) ;
132
- panic ! ( "Too many open files. Please reduce batch size. The default is 5000. Try -b 2500." ) ;
137
+ if e . kind ( ) == ErrorKind :: Other {
138
+ debug ! ( "Socket connect error: {} {}" , & error_string , & socket ) ;
139
+
140
+ if !error_string . contains ( "No route to host" )
141
+ && !error_string . contains ( "Network is unreachable " )
142
+ {
143
+ panic ! ( "Too many open files. Please reduce batch size. The default is 5000. Try -b 2500." ) ;
144
+ }
145
+ }
146
+
147
+ if nr_try == tries {
148
+ return Err ( io :: Error :: new ( io :: ErrorKind :: Other , error_string ) ) ;
133
149
}
134
150
}
135
- _ => Err ( io:: Error :: new ( io:: ErrorKind :: Other , e. to_string ( ) ) ) ,
136
- } ,
151
+ } ;
137
152
}
153
+ unreachable ! ( ) ;
138
154
}
139
155
140
156
/// Performs the connection to the socket with timeout
@@ -174,7 +190,15 @@ mod tests {
174
190
end : 1_000 ,
175
191
} ;
176
192
let strategy = PortStrategy :: pick ( Some ( range) , None , ScanOrder :: Random ) ;
177
- let scanner = Scanner :: new ( & addrs, 10 , Duration :: from_millis ( 100 ) , true , strategy, true ) ;
193
+ let scanner = Scanner :: new (
194
+ & addrs,
195
+ 10 ,
196
+ Duration :: from_millis ( 100 ) ,
197
+ 1 ,
198
+ true ,
199
+ strategy,
200
+ true ,
201
+ ) ;
178
202
block_on ( scanner. run ( ) ) ;
179
203
// if the scan fails, it wouldn't be able to assert_eq! as it panicked!
180
204
assert_eq ! ( 1 , 1 ) ;
@@ -188,7 +212,15 @@ mod tests {
188
212
end : 1_000 ,
189
213
} ;
190
214
let strategy = PortStrategy :: pick ( Some ( range) , None , ScanOrder :: Random ) ;
191
- let scanner = Scanner :: new ( & addrs, 10 , Duration :: from_millis ( 100 ) , true , strategy, true ) ;
215
+ let scanner = Scanner :: new (
216
+ & addrs,
217
+ 10 ,
218
+ Duration :: from_millis ( 100 ) ,
219
+ 1 ,
220
+ true ,
221
+ strategy,
222
+ true ,
223
+ ) ;
192
224
block_on ( scanner. run ( ) ) ;
193
225
// if the scan fails, it wouldn't be able to assert_eq! as it panicked!
194
226
assert_eq ! ( 1 , 1 ) ;
@@ -201,7 +233,15 @@ mod tests {
201
233
end : 1_000 ,
202
234
} ;
203
235
let strategy = PortStrategy :: pick ( Some ( range) , None , ScanOrder :: Random ) ;
204
- let scanner = Scanner :: new ( & addrs, 10 , Duration :: from_millis ( 100 ) , true , strategy, true ) ;
236
+ let scanner = Scanner :: new (
237
+ & addrs,
238
+ 10 ,
239
+ Duration :: from_millis ( 100 ) ,
240
+ 1 ,
241
+ true ,
242
+ strategy,
243
+ true ,
244
+ ) ;
205
245
block_on ( scanner. run ( ) ) ;
206
246
assert_eq ! ( 1 , 1 ) ;
207
247
}
@@ -213,7 +253,15 @@ mod tests {
213
253
end : 445 ,
214
254
} ;
215
255
let strategy = PortStrategy :: pick ( Some ( range) , None , ScanOrder :: Random ) ;
216
- let scanner = Scanner :: new ( & addrs, 10 , Duration :: from_millis ( 100 ) , true , strategy, true ) ;
256
+ let scanner = Scanner :: new (
257
+ & addrs,
258
+ 10 ,
259
+ Duration :: from_millis ( 100 ) ,
260
+ 1 ,
261
+ true ,
262
+ strategy,
263
+ true ,
264
+ ) ;
217
265
block_on ( scanner. run ( ) ) ;
218
266
assert_eq ! ( 1 , 1 ) ;
219
267
}
@@ -228,7 +276,15 @@ mod tests {
228
276
end : 600 ,
229
277
} ;
230
278
let strategy = PortStrategy :: pick ( Some ( range) , None , ScanOrder :: Random ) ;
231
- let scanner = Scanner :: new ( & addrs, 10 , Duration :: from_millis ( 100 ) , true , strategy, true ) ;
279
+ let scanner = Scanner :: new (
280
+ & addrs,
281
+ 10 ,
282
+ Duration :: from_millis ( 100 ) ,
283
+ 1 ,
284
+ true ,
285
+ strategy,
286
+ true ,
287
+ ) ;
232
288
block_on ( scanner. run ( ) ) ;
233
289
assert_eq ! ( 1 , 1 ) ;
234
290
}
0 commit comments