@@ -205,9 +205,9 @@ fn prune_ip_paths(paths: &mut FxHashMap<transports::Addr, PathState>) {
205205 }
206206
207207 // paths that were opened at one point but have previously been closed
208- let mut can_prune = Vec :: new ( ) ;
208+ let mut inactive = Vec :: new ( ) ;
209209 // paths where we attempted hole punching but it not successful
210- let mut must_prune = Vec :: new ( ) ;
210+ let mut failed = Vec :: new ( ) ;
211211
212212 for ( addr, state) in ip_paths {
213213 match state. abandoned {
@@ -218,28 +218,32 @@ fn prune_ip_paths(paths: &mut FxHashMap<transports::Addr, PathState>) {
218218 Some ( abandoned) => {
219219 if state. usable {
220220 // These are paths where hole punching succeeded at one point, but the path was closed.
221- can_prune . push ( ( addr. clone ( ) , abandoned) ) ;
221+ inactive . push ( ( addr. clone ( ) , abandoned) ) ;
222222 } else {
223223 // These are paths where hole punching has been attempted and failed.
224- must_prune . push ( addr. clone ( ) ) ;
224+ failed . push ( addr. clone ( ) ) ;
225225 }
226226 }
227227 }
228228 }
229229
230- // sort the potentially prunable from most recently closed to least recently closed
231- can_prune. sort_by ( |a, b| b. 1 . cmp ( & a. 1 ) ) ;
230+ // All paths are bad, don't prune all of them.
231+ //
232+ // This implies that `inactive` is empty.
233+ if failed. len ( ) == paths. len ( ) {
234+ failed. truncate ( MAX_IP_PATHS ) ;
235+ }
232236
233- // Don't prune any potentially usable but inactive paths if we don't need to.
234- let prunable_slots = MAX_INACTIVE_IP_PATHS . saturating_sub ( must_prune . len ( ) ) ;
237+ // sort the potentially prunable from most recently closed to least recently closed
238+ inactive . sort_by ( |a , b| b . 1 . cmp ( & a . 1 ) ) ;
235239
236240 // Prune the "oldest" closed paths.
237- let prune = can_prune . split_off ( can_prune . len ( ) . saturating_sub ( prunable_slots ) ) ;
241+ let old_inactive = inactive . split_off ( inactive . len ( ) . saturating_sub ( MAX_INACTIVE_IP_PATHS ) ) ;
238242
239243 // collect all the paths that should be pruned
240- let must_prune: HashSet < _ > = must_prune
244+ let must_prune: HashSet < _ > = failed
241245 . into_iter ( )
242- . chain ( prune . into_iter ( ) . map ( |( addr, _) | addr) )
246+ . chain ( old_inactive . into_iter ( ) . map ( |( addr, _) | addr) )
243247 . collect ( ) ;
244248
245249 paths. retain ( |addr, _| !must_prune. contains ( addr) ) ;
@@ -285,7 +289,7 @@ mod tests {
285289 }
286290
287291 prune_ip_paths ( & mut paths) ;
288- assert_eq ! ( paths. len( ) , 20 , "should not prune when under MAX_IP_PATHS" ) ;
292+ assert_eq ! ( 20 , paths. len( ) , "should not prune when under MAX_IP_PATHS" ) ;
289293 }
290294
291295 #[ test]
@@ -297,7 +301,7 @@ mod tests {
297301 }
298302
299303 prune_ip_paths ( & mut paths) ;
300- assert_eq ! ( paths. len( ) , MAX_IP_PATHS , "should not prune active paths" ) ;
304+ assert_eq ! ( MAX_IP_PATHS , paths. len( ) , "should not prune active paths" ) ;
301305 }
302306
303307 #[ test]
@@ -318,7 +322,7 @@ mod tests {
318322 prune_ip_paths ( & mut paths) ;
319323
320324 // All failed holepunch paths should be pruned
321- assert_eq ! ( paths. len( ) , 20 ) ;
325+ assert_eq ! ( 20 , paths. len( ) ) ;
322326 for i in 0 ..20 {
323327 assert ! ( paths. contains_key( & ip_addr( i) ) ) ;
324328 }
@@ -347,11 +351,11 @@ mod tests {
347351 ) ;
348352 }
349353
350- assert_eq ! ( paths. len( ) , 35 ) ;
354+ assert_eq ! ( 35 , paths. len( ) ) ;
351355 prune_ip_paths ( & mut paths) ;
352356
353357 // Should keep 15 active + 10 most recently abandoned
354- assert_eq ! ( paths. len( ) , 25 ) ;
358+ assert_eq ! ( 25 , paths. len( ) ) ;
355359
356360 // Active paths should remain
357361 for i in 0 ..15 {
@@ -397,11 +401,12 @@ mod tests {
397401 ) ;
398402 }
399403
400- assert_eq ! ( paths. len( ) , 35 ) ;
404+ assert_eq ! ( 35 , paths. len( ) ) ;
401405 prune_ip_paths ( & mut paths) ;
402406
403- // Total: 15 active + 5 most recent can_prune = 20
404- assert_eq ! ( paths. len( ) , 20 ) ;
407+ // Remove all failed paths -> down to 30
408+ // Keep MAX_INACTIVE_IP_PATHS, eg remove 5 usable but abandoned paths -> down to 20
409+ assert_eq ! ( 20 , paths. len( ) ) ;
405410
406411 // Active paths should remain
407412 for i in 0 ..15 {
@@ -440,11 +445,11 @@ mod tests {
440445 paths. insert ( relay_addr, PathState :: default ( ) ) ;
441446 }
442447
443- assert_eq ! ( paths. len( ) , 35 ) ; // 25 IP + 10 relay
448+ assert_eq ! ( 35 , paths. len( ) ) ; // 25 IP + 10 relay
444449 prune_ip_paths ( & mut paths) ;
445450
446451 // Should not prune since IP paths < MAX_IP_PATHS
447- assert_eq ! ( paths. len( ) , 35 ) ;
452+ assert_eq ! ( 35 , paths. len( ) ) ;
448453 }
449454
450455 #[ test]
0 commit comments