@@ -756,12 +756,42 @@ impl RelaySelector {
756
756
custom_lists : & CustomListsSettings ,
757
757
parsed_relays : & ParsedRelays ,
758
758
) -> Result < WireguardConfig , Error > {
759
- // Modify the query to enable multihop
760
- let mut query = query. clone ( ) ;
761
- query. wireguard_constraints . use_multihop = Constraint :: Only ( true ) ;
762
- query. wireguard_constraints . entry_location = Constraint :: Any ; // TODO: smarter location selection
759
+ let mut exit_relay_query = query. clone ( ) ;
760
+
761
+ // DAITA should only be enabled for the entry relay
762
+ exit_relay_query. wireguard_constraints . daita = Constraint :: Only ( false ) ;
763
+
764
+ let exit_candidates =
765
+ filter_matching_relay_list ( & exit_relay_query, parsed_relays. relays ( ) , custom_lists) ;
766
+ let exit = helpers:: pick_random_relay ( & exit_candidates) . ok_or ( Error :: NoRelay ) ?;
767
+
768
+ // generate a list of potential entry relays, disregarding any location constraint
769
+ let entry_query = RelayQuery {
770
+ location : Constraint :: Any ,
771
+ ..query. clone ( )
772
+ } ;
773
+ let mut entry_candidates =
774
+ filter_matching_relay_list ( & entry_query, parsed_relays. relays ( ) , custom_lists)
775
+ . into_iter ( )
776
+ . map ( |entry| RelayWithDistance :: new_with_distance_from ( entry, & exit. location ) )
777
+ . collect_vec ( ) ;
778
+
779
+ // sort entry relay candidates by distance, and pick one from those that are closest
780
+ entry_candidates. sort_unstable_by ( |a, b| a. distance . total_cmp ( & b. distance ) ) ;
781
+ let smallest_distance = entry_candidates. first ( ) . map ( |relay| relay. distance ) ;
782
+ let smallest_distance = smallest_distance. unwrap_or_default ( ) ;
783
+ let entry_candidates = entry_candidates
784
+ . into_iter ( )
785
+ // only consider the relay(s) with the smallest distance. note that the list is sorted.
786
+ // NOTE: we could relax this requirement, but since so few relays support DAITA
787
+ // (and this function is only used for daita) we might end up picking relays that are
788
+ // needlessly far away. Consider making this closure configurable if needed.
789
+ . take_while ( |relay| relay. distance <= smallest_distance)
790
+ . map ( |relay_with_distance| relay_with_distance. relay )
791
+ . collect_vec ( ) ;
792
+ let entry = pick_random_excluding ( & entry_candidates, & exit) . ok_or ( Error :: NoRelay ) ?;
763
793
764
- Self :: get_wireguard_multihop_config ( & query , custom_lists , parsed_relays )
794
+ Ok ( WireguardConfig :: multihop ( exit . clone ( ) , entry . clone ( ) ) )
765
795
}
766
796
767
797
/// This function selects a valid entry and exit relay to be used in a multihop configuration.
@@ -793,11 +823,6 @@ impl RelaySelector {
793
823
let entry_candidates =
794
824
filter_matching_relay_list ( & entry_relay_query, parsed_relays. relays ( ) , custom_lists) ;
795
825
796
- fn pick_random_excluding < ' a > ( list : & ' a [ Relay ] , exclude : & ' a Relay ) -> Option < & ' a Relay > {
797
- list. iter ( )
798
- . filter ( |& a| a != exclude)
799
- . choose ( & mut thread_rng ( ) )
800
- }
801
826
// We avoid picking the same relay for entry and exit by choosing one and excluding it when
802
827
// choosing the other.
803
828
let ( exit, entry) = match ( exit_candidates. as_slice ( ) , entry_candidates. as_slice ( ) ) {
@@ -1026,19 +1051,10 @@ impl RelaySelector {
1026
1051
const MIN_BRIDGE_COUNT : usize = 5 ;
1027
1052
let location = location. into ( ) ;
1028
1053
1029
- #[ derive( Clone ) ]
1030
- struct RelayWithDistance {
1031
- relay : Relay ,
1032
- distance : f64 ,
1033
- }
1034
-
1035
1054
// Filter out all candidate bridges.
1036
1055
let matching_bridges: Vec < RelayWithDistance > = relays
1037
1056
. into_iter ( )
1038
- . map ( |relay| RelayWithDistance {
1039
- distance : relay. location . distance_from ( & location) ,
1040
- relay,
1041
- } )
1057
+ . map ( |relay| RelayWithDistance :: new_with_distance_from ( relay, location) )
1042
1058
. sorted_unstable_by_key ( |relay| relay. distance as usize )
1043
1059
. take ( MIN_BRIDGE_COUNT )
1044
1060
. collect ( ) ;
@@ -1100,3 +1116,22 @@ impl RelaySelector {
1100
1116
helpers:: pick_random_relay ( & candidates) . cloned ( )
1101
1117
}
1102
1118
}
1119
+
1120
+ fn pick_random_excluding < ' a > ( list : & ' a [ Relay ] , exclude : & ' a Relay ) -> Option < & ' a Relay > {
1121
+ list. iter ( )
1122
+ . filter ( |& a| a != exclude)
1123
+ . choose ( & mut thread_rng ( ) )
1124
+ }
1125
+
1126
+ #[ derive( Clone ) ]
1127
+ struct RelayWithDistance {
1128
+ distance : f64 ,
1129
+ relay : Relay ,
1130
+ }
1131
+
1132
+ impl RelayWithDistance {
1133
+ fn new_with_distance_from ( relay : Relay , from : impl Into < Coordinates > ) -> Self {
1134
+ let distance = relay. location . distance_from ( from) ;
1135
+ RelayWithDistance { relay, distance }
1136
+ }
1137
+ }
0 commit comments