@@ -111,39 +111,50 @@ impl AnnounceHandler {
111111pub enum PeersWanted {
112112 /// The peer wants as many peers as possible in the announce response.
113113 #[ default]
114- All ,
114+ AsManyAsPossible ,
115115 /// The peer only wants a certain amount of peers in the announce response.
116116 Only { amount : usize } ,
117117}
118118
119119impl PeersWanted {
120120 #[ must_use]
121121 pub fn only ( limit : u32 ) -> Self {
122- let amount: usize = match limit. try_into ( ) {
123- Ok ( amount) => amount,
124- Err ( _) => TORRENT_PEERS_LIMIT ,
125- } ;
126-
127- Self :: Only { amount }
122+ limit. into ( )
128123 }
129124
130125 fn limit ( & self ) -> usize {
131126 match self {
132- PeersWanted :: All => TORRENT_PEERS_LIMIT ,
127+ PeersWanted :: AsManyAsPossible => TORRENT_PEERS_LIMIT ,
133128 PeersWanted :: Only { amount } => * amount,
134129 }
135130 }
136131}
137132
138133impl From < i32 > for PeersWanted {
139134 fn from ( value : i32 ) -> Self {
140- if value > 0 {
141- match value. try_into ( ) {
142- Ok ( peers_wanted) => Self :: Only { amount : peers_wanted } ,
143- Err ( _) => Self :: All ,
144- }
145- } else {
146- Self :: All
135+ if value <= 0 {
136+ return PeersWanted :: AsManyAsPossible ;
137+ }
138+
139+ // This conversion is safe because `value > 0`
140+ let amount = usize:: try_from ( value) . unwrap ( ) ;
141+
142+ PeersWanted :: Only {
143+ amount : amount. min ( TORRENT_PEERS_LIMIT ) ,
144+ }
145+ }
146+ }
147+
148+ impl From < u32 > for PeersWanted {
149+ fn from ( value : u32 ) -> Self {
150+ if value == 0 {
151+ return PeersWanted :: AsManyAsPossible ;
152+ }
153+
154+ let amount = value as usize ;
155+
156+ PeersWanted :: Only {
157+ amount : amount. min ( TORRENT_PEERS_LIMIT ) ,
147158 }
148159 }
149160}
@@ -210,14 +221,27 @@ mod tests {
210221 }
211222 }
212223
224+ /// Sample peer when for tests that need more than two peer
225+ fn sample_peer_3 ( ) -> Peer {
226+ Peer {
227+ peer_id : PeerId ( * b"-qB00000000000000003" ) ,
228+ peer_addr : SocketAddr :: new ( IpAddr :: V4 ( Ipv4Addr :: new ( 126 , 0 , 0 , 3 ) ) , 8082 ) ,
229+ updated : DurationSinceUnixEpoch :: new ( 1_669_397_478_934 , 0 ) ,
230+ uploaded : NumberOfBytes :: new ( 0 ) ,
231+ downloaded : NumberOfBytes :: new ( 0 ) ,
232+ left : NumberOfBytes :: new ( 0 ) ,
233+ event : AnnounceEvent :: Completed ,
234+ }
235+ }
236+
213237 mod for_all_tracker_config_modes {
214238
215239 mod handling_an_announce_request {
216240
217241 use std:: sync:: Arc ;
218242
219243 use crate :: announce_handler:: tests:: the_announce_handler:: {
220- peer_ip, public_tracker, sample_peer_1, sample_peer_2,
244+ peer_ip, public_tracker, sample_peer_1, sample_peer_2, sample_peer_3 ,
221245 } ;
222246 use crate :: announce_handler:: PeersWanted ;
223247 use crate :: core_tests:: { sample_info_hash, sample_peer} ;
@@ -326,7 +350,8 @@ mod tests {
326350
327351 let mut peer = sample_peer ( ) ;
328352
329- let announce_data = announce_handler. announce ( & sample_info_hash ( ) , & mut peer, & peer_ip ( ) , & PeersWanted :: All ) ;
353+ let announce_data =
354+ announce_handler. announce ( & sample_info_hash ( ) , & mut peer, & peer_ip ( ) , & PeersWanted :: AsManyAsPossible ) ;
330355
331356 assert_eq ! ( announce_data. peers, vec![ ] ) ;
332357 }
@@ -340,15 +365,48 @@ mod tests {
340365 & sample_info_hash ( ) ,
341366 & mut previously_announced_peer,
342367 & peer_ip ( ) ,
343- & PeersWanted :: All ,
368+ & PeersWanted :: AsManyAsPossible ,
344369 ) ;
345370
346371 let mut peer = sample_peer_2 ( ) ;
347- let announce_data = announce_handler. announce ( & sample_info_hash ( ) , & mut peer, & peer_ip ( ) , & PeersWanted :: All ) ;
372+ let announce_data =
373+ announce_handler. announce ( & sample_info_hash ( ) , & mut peer, & peer_ip ( ) , & PeersWanted :: AsManyAsPossible ) ;
348374
349375 assert_eq ! ( announce_data. peers, vec![ Arc :: new( previously_announced_peer) ] ) ;
350376 }
351377
378+ #[ tokio:: test]
379+ async fn it_should_allow_peers_to_get_only_a_subset_of_the_peers_in_the_swarm ( ) {
380+ let ( announce_handler, _scrape_handler) = public_tracker ( ) ;
381+
382+ let mut previously_announced_peer_1 = sample_peer_1 ( ) ;
383+ announce_handler. announce (
384+ & sample_info_hash ( ) ,
385+ & mut previously_announced_peer_1,
386+ & peer_ip ( ) ,
387+ & PeersWanted :: AsManyAsPossible ,
388+ ) ;
389+
390+ let mut previously_announced_peer_2 = sample_peer_2 ( ) ;
391+ announce_handler. announce (
392+ & sample_info_hash ( ) ,
393+ & mut previously_announced_peer_2,
394+ & peer_ip ( ) ,
395+ & PeersWanted :: AsManyAsPossible ,
396+ ) ;
397+
398+ let mut peer = sample_peer_3 ( ) ;
399+ let announce_data =
400+ announce_handler. announce ( & sample_info_hash ( ) , & mut peer, & peer_ip ( ) , & PeersWanted :: only ( 1 ) ) ;
401+
402+ // It should return only one peer. There is no guarantee on
403+ // which peer will be returned.
404+ assert ! (
405+ announce_data. peers == vec![ Arc :: new( previously_announced_peer_1) ]
406+ || announce_data. peers == vec![ Arc :: new( previously_announced_peer_2) ]
407+ ) ;
408+ }
409+
352410 mod it_should_update_the_swarm_stats_for_the_torrent {
353411
354412 use crate :: announce_handler:: tests:: the_announce_handler:: { peer_ip, public_tracker} ;
@@ -362,7 +420,7 @@ mod tests {
362420 let mut peer = seeder ( ) ;
363421
364422 let announce_data =
365- announce_handler. announce ( & sample_info_hash ( ) , & mut peer, & peer_ip ( ) , & PeersWanted :: All ) ;
423+ announce_handler. announce ( & sample_info_hash ( ) , & mut peer, & peer_ip ( ) , & PeersWanted :: AsManyAsPossible ) ;
366424
367425 assert_eq ! ( announce_data. stats. complete, 1 ) ;
368426 }
@@ -374,7 +432,7 @@ mod tests {
374432 let mut peer = leecher ( ) ;
375433
376434 let announce_data =
377- announce_handler. announce ( & sample_info_hash ( ) , & mut peer, & peer_ip ( ) , & PeersWanted :: All ) ;
435+ announce_handler. announce ( & sample_info_hash ( ) , & mut peer, & peer_ip ( ) , & PeersWanted :: AsManyAsPossible ) ;
378436
379437 assert_eq ! ( announce_data. stats. incomplete, 1 ) ;
380438 }
@@ -385,11 +443,20 @@ mod tests {
385443
386444 // We have to announce with "started" event because peer does not count if peer was not previously known
387445 let mut started_peer = started_peer ( ) ;
388- announce_handler. announce ( & sample_info_hash ( ) , & mut started_peer, & peer_ip ( ) , & PeersWanted :: All ) ;
446+ announce_handler. announce (
447+ & sample_info_hash ( ) ,
448+ & mut started_peer,
449+ & peer_ip ( ) ,
450+ & PeersWanted :: AsManyAsPossible ,
451+ ) ;
389452
390453 let mut completed_peer = completed_peer ( ) ;
391- let announce_data =
392- announce_handler. announce ( & sample_info_hash ( ) , & mut completed_peer, & peer_ip ( ) , & PeersWanted :: All ) ;
454+ let announce_data = announce_handler. announce (
455+ & sample_info_hash ( ) ,
456+ & mut completed_peer,
457+ & peer_ip ( ) ,
458+ & PeersWanted :: AsManyAsPossible ,
459+ ) ;
393460
394461 assert_eq ! ( announce_data. stats. downloaded, 1 ) ;
395462 }
@@ -438,11 +505,11 @@ mod tests {
438505 let mut peer = sample_peer ( ) ;
439506
440507 peer. event = AnnounceEvent :: Started ;
441- let announce_data = announce_handler. announce ( & info_hash, & mut peer, & peer_ip ( ) , & PeersWanted :: All ) ;
508+ let announce_data = announce_handler. announce ( & info_hash, & mut peer, & peer_ip ( ) , & PeersWanted :: AsManyAsPossible ) ;
442509 assert_eq ! ( announce_data. stats. downloaded, 0 ) ;
443510
444511 peer. event = AnnounceEvent :: Completed ;
445- let announce_data = announce_handler. announce ( & info_hash, & mut peer, & peer_ip ( ) , & PeersWanted :: All ) ;
512+ let announce_data = announce_handler. announce ( & info_hash, & mut peer, & peer_ip ( ) , & PeersWanted :: AsManyAsPossible ) ;
446513 assert_eq ! ( announce_data. stats. downloaded, 1 ) ;
447514
448515 // Remove the newly updated torrent from memory
@@ -461,5 +528,95 @@ mod tests {
461528 assert ! ( torrent_entry. peers_is_empty( ) ) ;
462529 }
463530 }
531+
532+ mod should_allow_the_client_peers_to_specified_the_number_of_peers_wanted {
533+
534+ use torrust_tracker_configuration:: TORRENT_PEERS_LIMIT ;
535+
536+ use crate :: announce_handler:: PeersWanted ;
537+
538+ #[ test]
539+ fn it_should_return_the_maximin_number_of_peers_by_default ( ) {
540+ let peers_wanted = PeersWanted :: default ( ) ;
541+
542+ assert_eq ! ( peers_wanted. limit( ) , TORRENT_PEERS_LIMIT ) ;
543+ }
544+
545+ #[ test]
546+ fn it_should_return_74_at_the_most_if_the_client_wants_them_all ( ) {
547+ let peers_wanted = PeersWanted :: AsManyAsPossible ;
548+
549+ assert_eq ! ( peers_wanted. limit( ) , TORRENT_PEERS_LIMIT ) ;
550+ }
551+
552+ #[ test]
553+ fn it_should_allow_limiting_the_peer_list ( ) {
554+ let peers_wanted = PeersWanted :: only ( 10 ) ;
555+
556+ assert_eq ! ( peers_wanted. limit( ) , 10 ) ;
557+ }
558+
559+ fn maximum_as_u32 ( ) -> u32 {
560+ u32:: try_from ( TORRENT_PEERS_LIMIT ) . unwrap ( )
561+ }
562+
563+ fn maximum_as_i32 ( ) -> i32 {
564+ i32:: try_from ( TORRENT_PEERS_LIMIT ) . unwrap ( )
565+ }
566+
567+ #[ test]
568+ fn it_should_return_the_maximum_when_wanting_more_than_the_maximum ( ) {
569+ let peers_wanted = PeersWanted :: only ( maximum_as_u32 ( ) + 1 ) ;
570+ assert_eq ! ( peers_wanted. limit( ) , TORRENT_PEERS_LIMIT ) ;
571+ }
572+
573+ #[ test]
574+ fn it_should_return_the_maximum_when_wanting_only_zero ( ) {
575+ let peers_wanted = PeersWanted :: only ( 0 ) ;
576+ assert_eq ! ( peers_wanted. limit( ) , TORRENT_PEERS_LIMIT ) ;
577+ }
578+
579+ #[ test]
580+ fn it_should_convert_the_peers_wanted_number_from_i32 ( ) {
581+ // Negative. It should return the maximum
582+ let peers_wanted: PeersWanted = ( -1i32 ) . into ( ) ;
583+ assert_eq ! ( peers_wanted. limit( ) , TORRENT_PEERS_LIMIT ) ;
584+
585+ // Zero. It should return the maximum
586+ let peers_wanted: PeersWanted = 0i32 . into ( ) ;
587+ assert_eq ! ( peers_wanted. limit( ) , TORRENT_PEERS_LIMIT ) ;
588+
589+ // Greater than the maximum. It should return the maximum
590+ let peers_wanted: PeersWanted = ( maximum_as_i32 ( ) + 1 ) . into ( ) ;
591+ assert_eq ! ( peers_wanted. limit( ) , TORRENT_PEERS_LIMIT ) ;
592+
593+ // The maximum
594+ let peers_wanted: PeersWanted = ( maximum_as_i32 ( ) ) . into ( ) ;
595+ assert_eq ! ( peers_wanted. limit( ) , TORRENT_PEERS_LIMIT ) ;
596+
597+ // Smaller than the maximum
598+ let peers_wanted: PeersWanted = ( maximum_as_i32 ( ) - 1 ) . into ( ) ;
599+ assert_eq ! ( i32 :: try_from( peers_wanted. limit( ) ) . unwrap( ) , maximum_as_i32( ) - 1 ) ;
600+ }
601+
602+ #[ test]
603+ fn it_should_convert_the_peers_wanted_number_from_u32 ( ) {
604+ // Zero. It should return the maximum
605+ let peers_wanted: PeersWanted = 0u32 . into ( ) ;
606+ assert_eq ! ( peers_wanted. limit( ) , TORRENT_PEERS_LIMIT ) ;
607+
608+ // Greater than the maximum. It should return the maximum
609+ let peers_wanted: PeersWanted = ( maximum_as_u32 ( ) + 1 ) . into ( ) ;
610+ assert_eq ! ( peers_wanted. limit( ) , TORRENT_PEERS_LIMIT ) ;
611+
612+ // The maximum
613+ let peers_wanted: PeersWanted = ( maximum_as_u32 ( ) ) . into ( ) ;
614+ assert_eq ! ( peers_wanted. limit( ) , TORRENT_PEERS_LIMIT ) ;
615+
616+ // Smaller than the maximum
617+ let peers_wanted: PeersWanted = ( maximum_as_u32 ( ) - 1 ) . into ( ) ;
618+ assert_eq ! ( i32 :: try_from( peers_wanted. limit( ) ) . unwrap( ) , maximum_as_i32( ) - 1 ) ;
619+ }
620+ }
464621 }
465622}
0 commit comments