Skip to content

Commit 69d8cd1

Browse files
Serock3Pururun
authored andcommitted
Refactor how runtime IP version is applied
1 parent 01d36d9 commit 69d8cd1

File tree

4 files changed

+40
-79
lines changed

4 files changed

+40
-79
lines changed

mullvad-relay-selector/src/error.rs

+3
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ pub enum Error {
3636

3737
#[error("Invalid bridge settings")]
3838
InvalidBridgeSettings(#[from] MissingCustomBridgeSettings),
39+
40+
#[error("The requested IP version is not available")]
41+
IpVersionUnavailable,
3942
}
4043

4144
/// Special type which only shows up in [`Error`]. This error variant signals that no valid

mullvad-relay-selector/src/lib.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ mod relay_selector;
1010
pub use error::Error;
1111
pub use relay_selector::{
1212
detailer, matcher, matcher::filter_matching_relay_list, query, relays::WireguardConfig,
13-
AdditionalRelayConstraints, AdditionalWireguardConstraints, GetRelay, IpAvailability,
14-
RelaySelector, RuntimeParameters, SelectedBridge, SelectedObfuscator, SelectorConfig,
15-
OPENVPN_RETRY_ORDER, WIREGUARD_RETRY_ORDER,
13+
AdditionalRelayConstraints, AdditionalWireguardConstraints, GetRelay, RelaySelector,
14+
RuntimeParameters, SelectedBridge, SelectedObfuscator, SelectorConfig, OPENVPN_RETRY_ORDER,
15+
WIREGUARD_RETRY_ORDER,
1616
};

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

+27-69
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ use talpid_types::{
4747
net::{
4848
obfuscation::ObfuscatorConfig,
4949
proxy::{CustomProxy, Shadowsocks},
50-
Endpoint, TransportProtocol, TunnelType,
50+
Endpoint, IpVersion, TransportProtocol, TunnelType,
5151
},
5252
ErrorExt,
5353
};
@@ -182,63 +182,30 @@ pub struct AdditionalWireguardConstraints {
182182
#[derive(Clone, Debug)]
183183
pub struct RuntimeParameters {
184184
/// Whether IPv4, IPv6 or both is available
185-
pub ip_availability: IpAvailability,
185+
pub ip_availability: Option<Constraint<IpVersion>>,
186186
}
187187

188188
impl RuntimeParameters {
189-
/// Return whether a given [query][`RelayQuery`] is valid given the current runtime parameters
190-
pub fn compatible(&self, query: &RelayQuery) -> bool {
191-
match query.wireguard_constraints().ip_version {
192-
Constraint::Any => true,
193-
Constraint::Only(talpid_types::net::IpVersion::V4) => self.ip_availability.has_ipv4(),
194-
Constraint::Only(talpid_types::net::IpVersion::V6) => self.ip_availability.has_ipv6(),
195-
}
196-
}
197-
198189
pub fn new(ipv4: bool, ipv6: bool) -> RuntimeParameters {
199-
if ipv4 && ipv6 {
200190
RuntimeParameters {
201-
ip_availability: IpAvailability::All,
202-
}
203-
} else if !ipv6 {
204-
RuntimeParameters {
205-
ip_availability: IpAvailability::Ipv4,
206-
}
207-
} else if !ipv4 {
208-
RuntimeParameters {
209-
ip_availability: IpAvailability::Ipv6,
210-
}
211-
} else {
212-
panic!("Device is offline!")
191+
ip_availability: match (ipv4, ipv6) {
192+
(true, true) => Some(Constraint::Any),
193+
(false, true) => Some(Constraint::Only(IpVersion::V6)),
194+
(true, false) => Some(Constraint::Only(IpVersion::V4)),
195+
(false, false) => None,
196+
},
213197
}
214198
}
215199
}
216200

217201
impl Default for RuntimeParameters {
218202
fn default() -> Self {
219203
RuntimeParameters {
220-
ip_availability: IpAvailability::Ipv4,
204+
ip_availability: Some(Constraint::Only(IpVersion::V4)),
221205
}
222206
}
223207
}
224208

225-
#[derive(Clone, Debug, PartialEq, Eq)]
226-
pub enum IpAvailability {
227-
Ipv4,
228-
Ipv6,
229-
All,
230-
}
231-
232-
impl IpAvailability {
233-
fn has_ipv4(&self) -> bool {
234-
self.clone() == IpAvailability::Ipv4 || self.clone() == IpAvailability::All
235-
}
236-
237-
fn has_ipv6(&self) -> bool {
238-
self.clone() == IpAvailability::Ipv6 || self.clone() == IpAvailability::All
239-
}
240-
}
241-
242209
/// This enum exists to separate the two types of [`SelectorConfig`] that exists.
243210
///
244211
/// The first one is a "regular" config, where [`SelectorConfig::relay_settings`] is
@@ -669,19 +636,12 @@ impl RelaySelector {
669636
user_config: &NormalSelectorConfig<'_>,
670637
parsed_relays: &RelayList,
671638
) -> Result<RelayQuery, Error> {
672-
let user_query = RelayQuery::try_from(user_config.clone())?;
639+
let mut user_query = RelayQuery::try_from(user_config.clone())?;
640+
apply_ip_availability(runtime_params, &mut user_query)?;
673641
log::trace!("Merging user preferences {user_query:?} with default retry strategy");
674642
retry_order
675643
.iter()
676-
// Remove candidate queries based on runtime parameters before trying to merge user
677-
// settings
678-
.filter(|query| runtime_params.compatible(query))
679-
// Check if the user query aligns with the runtime parameters so that if the user
680-
// has selected an ip version that is not available it will return an error
681-
.filter(|_query| runtime_params.compatible(&user_query))
682644
.filter_map(|query| query.clone().intersection(user_query.clone()))
683-
// Resolve query ip version set to Any based on runtime ip availability
684-
.map(|query| resolve_valid_ip_version(&query, &runtime_params))
685645
.filter(|query| Self::get_relay_inner(query, parsed_relays, user_config.custom_lists).is_ok())
686646
.cycle() // If the above filters remove all relays, cycle will also return an empty iterator
687647
.nth(retry_attempt)
@@ -1213,24 +1173,22 @@ impl RelaySelector {
12131173
}
12141174
}
12151175

1216-
/// If the selected ip version is Any we want to resolve that to an Only ip version if only
1217-
/// one ip version is available on the network. This is to avoid situations where in other parts
1218-
/// of the relay selector that Any is resolved to IPv4 and IPv4 is not available.
1219-
fn resolve_valid_ip_version(query: &RelayQuery, runtime_params: &RuntimeParameters) -> RelayQuery {
1220-
let mut wireguard_constraints = query.wireguard_constraints().clone();
1221-
if wireguard_constraints.ip_version.is_any() {
1222-
if runtime_params.ip_availability == IpAvailability::Ipv4 {
1223-
wireguard_constraints.ip_version = Constraint::Only(talpid_types::net::IpVersion::V4)
1224-
}
1225-
if runtime_params.ip_availability == IpAvailability::Ipv6 {
1226-
wireguard_constraints.ip_version = Constraint::Only(talpid_types::net::IpVersion::V6)
1227-
}
1228-
}
1229-
let mut ret = query.clone();
1230-
match ret.set_wireguard_constraints(wireguard_constraints) {
1231-
Ok(()) => ret,
1232-
_error => query.clone(),
1233-
}
1176+
fn apply_ip_availability(
1177+
runtime_params: RuntimeParameters,
1178+
user_query: &mut RelayQuery,
1179+
) -> Result<(), Error> {
1180+
let wireguard_constraints = user_query
1181+
.wireguard_constraints()
1182+
.to_owned()
1183+
.intersection(WireguardRelayQuery {
1184+
ip_version: runtime_params
1185+
.ip_availability
1186+
.ok_or(Error::IpVersionUnavailable)?,
1187+
..Default::default()
1188+
})
1189+
.ok_or(Error::IpVersionUnavailable)?;
1190+
user_query.set_wireguard_constraints(wireguard_constraints)?;
1191+
Ok(())
12341192
}
12351193

12361194
#[derive(Clone)]

mullvad-relay-selector/tests/relay_selector.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ use talpid_types::net::{
1515

1616
use mullvad_relay_selector::{
1717
query::{builder::RelayQueryBuilder, BridgeQuery, ObfuscationQuery, OpenVpnRelayQuery},
18-
Error, GetRelay, IpAvailability, RelaySelector, RuntimeParameters, SelectedObfuscator,
19-
SelectorConfig, WireguardConfig, OPENVPN_RETRY_ORDER, WIREGUARD_RETRY_ORDER,
18+
Error, GetRelay, RelaySelector, RuntimeParameters, SelectedObfuscator, SelectorConfig,
19+
WireguardConfig, OPENVPN_RETRY_ORDER, WIREGUARD_RETRY_ORDER,
2020
};
2121
use mullvad_types::{
2222
constraints::Constraint,
@@ -393,7 +393,7 @@ fn test_wireguard_retry_order() {
393393
.get_relay(
394394
retry_attempt,
395395
RuntimeParameters {
396-
ip_availability: IpAvailability::All,
396+
ip_availability: Some(Constraint::Any),
397397
},
398398
)
399399
.unwrap_or_else(|_| panic!("Retry attempt {retry_attempt} did not yield any relay"));
@@ -456,7 +456,7 @@ fn test_openvpn_retry_order() {
456456
.get_relay(
457457
retry_attempt,
458458
RuntimeParameters {
459-
ip_availability: IpAvailability::All,
459+
ip_availability: Some(Constraint::Any),
460460
},
461461
)
462462
.unwrap_or_else(|_| panic!("Retry attempt {retry_attempt} did not yield any relay"));
@@ -1643,7 +1643,7 @@ fn test_shadowsocks_runtime_ipv4_unavailable() {
16431643
};
16441644
let relay_selector = RelaySelector::from_list(config, RELAYS.clone());
16451645
let runtime_parameters = RuntimeParameters {
1646-
ip_availability: IpAvailability::Ipv6,
1646+
ip_availability: Some(Constraint::Only(IpVersion::V6)),
16471647
};
16481648
let user_result = relay_selector.get_relay(0, runtime_parameters).unwrap();
16491649
assert!(
@@ -1665,15 +1665,15 @@ fn test_shadowsocks_runtime_ipv4_unavailable() {
16651665
#[test]
16661666
fn test_runtime_ipv4_unavailable() {
16671667
// Make a valid user relay constraint
1668-
let (relay_constraints, _, _, _) = RelayQueryBuilder::wireguard().build().into_settings();
1668+
let (relay_constraints, ..) = RelayQueryBuilder::wireguard().build().into_settings();
16691669

16701670
let config = SelectorConfig {
16711671
relay_settings: relay_constraints.into(),
16721672
..SelectorConfig::default()
16731673
};
16741674
let relay_selector = RelaySelector::from_list(config, RELAYS.clone());
16751675
let runtime_parameters = RuntimeParameters {
1676-
ip_availability: IpAvailability::Ipv6,
1676+
ip_availability: Some(Constraint::Only(IpVersion::V6)),
16771677
};
16781678
let relay = relay_selector.get_relay(0, runtime_parameters).unwrap();
16791679
match relay {

0 commit comments

Comments
 (0)