Skip to content

Commit 9aca0b3

Browse files
committed
Small refactor of entry exit picking algorithm
1 parent 801e5fc commit 9aca0b3

File tree

3 files changed

+31
-34
lines changed

3 files changed

+31
-34
lines changed

gui/build-e2e.sh

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/usr/bin/env bash
2+
3+
set -ex
4+
5+
COMMIT=$(git rev-parse --short=6 HEAD)
6+
npm run build-test-executable
7+
cp ../dist/mullvadvpn-app-e2e-tests "$HOME/.cache/mullvad-test/packages/app-e2e-tests-2024.1-beta2-dev-${COMMIT}_amd64-unknown-linux-gnu"
8+
cp ../dist/mullvadvpn-app-e2e-tests "$HOME/.cache/mullvad-test/packages/app-e2e-tests-2024.1-beta2-dev-${COMMIT}_x86_64-unknown-linux-gnu"

mullvad-relay-selector/src/relay_selector/helpers.rs

+6-19
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,11 @@ use mullvad_types::{
88
relay_constraints::Udp2TcpObfuscationSettings,
99
relay_list::{BridgeEndpointData, Relay, RelayEndpointData},
1010
};
11-
use rand::{
12-
seq::{IteratorRandom, SliceRandom},
13-
thread_rng, Rng,
14-
};
11+
use rand::{seq::SliceRandom, thread_rng, Rng};
1512
use talpid_types::net::{obfuscation::ObfuscatorConfig, proxy::CustomProxy};
1613

1714
use crate::SelectedObfuscator;
1815

19-
/// Pick a random element out of `from`, excluding the element `exclude` from the selection.
20-
pub fn random<'a, A: PartialEq>(
21-
from: impl IntoIterator<Item = &'a A>,
22-
exclude: &A,
23-
) -> Option<&'a A> {
24-
from.into_iter()
25-
.filter(|&a| a != exclude)
26-
.choose(&mut thread_rng())
27-
}
28-
2916
/// Picks a relay using [pick_random_relay_fn], using the `weight` member of each relay
3017
/// as the weight function.
3118
pub fn pick_random_relay(relays: &[Relay]) -> Option<&Relay> {
@@ -53,11 +40,11 @@ pub fn pick_random_relay_weighted<RelayType>(
5340
// |
5441
// v
5542
// _____________________________i___________________________________________________
56-
// 0|_____________|__________________________|___________|_____|___________|__________| total_weight
57-
// ^ ^ ^ ^ ^
58-
// | | | | |
59-
// ------------------------------------------ ------------
60-
// | | |
43+
// 0|_____________|__________________________|___________|_____|___________|__________|
44+
// total_weight ^ ^ ^
45+
// ^ ^ | | | |
46+
// | ------------------------------------------
47+
// ------------ | | |
6148
// weight(relay 0) weight(relay 1) .. .. .. weight(relay n)
6249
let mut i: u64 = rng.gen_range(1..=total_weight);
6350
Some(

mullvad-relay-selector/src/relay_selector/mod.rs

+17-15
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ pub mod query;
99
use chrono::{DateTime, Local};
1010
use itertools::Itertools;
1111
use once_cell::sync::Lazy;
12+
use rand::{seq::IteratorRandom, thread_rng};
1213
use std::{
1314
path::Path,
1415
sync::{Arc, Mutex},
@@ -694,31 +695,32 @@ impl RelaySelector {
694695
config.custom_lists,
695696
);
696697

697-
// This algorithm gracefully handles a particular edge case that arise when a constraint on
698-
// the exit relay is more specific than on the entry relay which forces the relay selector
699-
// to choose one specific relay. The relay selector could end up selecting that specific
700-
// relay as the entry relay, thus leaving no remaining exit relay candidates or vice versa.
698+
let pick_random_excluding = |list: &[Relay], exclude| {
699+
list.iter()
700+
.filter(|&a| a != exclude)
701+
.choose(&mut thread_rng())
702+
};
703+
// We avoid picking the same relay for entry and exit by choosing one and excluding it when
704+
// choosing the other.
701705
let (exit, entry) = match (exit_candidates.as_slice(), entry_candidates.as_slice()) {
702706
([exit], [entry]) if exit == entry => None,
707+
// In the case where there is only one exit to choose from, we have to pick it before
708+
// the entry
703709
(exits, [entry]) if exits.contains(entry) => {
704-
let exit = helpers::random(exits, entry).ok_or(Error::NoRelay)?;
705-
Some((exit, entry))
710+
pick_random_excluding(exits, entry).map(|exit| (exit, entry))
706711
}
712+
// Vice versa for the case of only one entry
707713
([exit], entries) if entries.contains(exit) => {
708-
let entry = helpers::random(entries, exit).ok_or(Error::NoRelay)?;
709-
Some((exit, entry))
710-
}
711-
(exits, entries) => {
712-
let exit = helpers::pick_random_relay(exits).ok_or(Error::NoRelay)?;
713-
let entry = helpers::random(entries, exit).ok_or(Error::NoRelay)?;
714-
Some((exit, entry))
714+
pick_random_excluding(entries, exit).map(|entry| (exit, entry))
715715
}
716+
(exits, entries) => helpers::pick_random_relay(exits)
717+
.and_then(|exit| pick_random_excluding(entries, exit).map(|entry| (exit, entry))),
716718
}
717719
.ok_or(Error::NoRelay)?;
718720

719721
Ok(WireguardConfig::Multihop {
720-
exit: exit.clone(),
721-
entry: entry.clone(),
722+
exit: exit.to_owned(),
723+
entry: entry.to_owned(),
722724
})
723725
}
724726

0 commit comments

Comments
 (0)