diff --git a/mullvad-relay-selector/src/relay_selector/helpers.rs b/mullvad-relay-selector/src/relay_selector/helpers.rs index 263034d83659..f5f374ea28c8 100644 --- a/mullvad-relay-selector/src/relay_selector/helpers.rs +++ b/mullvad-relay-selector/src/relay_selector/helpers.rs @@ -64,19 +64,20 @@ pub fn pick_random_bridge(data: &BridgeEndpointData, relay: &Relay) -> Option { let location = relay.location.as_ref().ok_or(Error::NoRelay)?; - Ok(Self::get_bridge_for( + Self::get_bridge_for( bridge_query, location, // FIXME: This is temporary while talpid-core only supports TCP proxies TransportProtocol::Tcp, parsed_relays, custom_lists, - )) + ) } } } } + // TODO(markus): Document return value fn get_bridge_for( query: &BridgeQuery, location: &Location, transport_protocol: TransportProtocol, parsed_relays: &ParsedRelays, custom_lists: &CustomListsSettings, - ) -> Option { + ) -> Result, Error> { match query { BridgeQuery::Normal(settings) => { let bridge_constraints = InternalBridgeConstraints { @@ -921,16 +924,16 @@ impl RelaySelector { transport_protocol: Constraint::Only(transport_protocol), }; - Self::get_proxy_settings( + let (settings, relay) = Self::get_proxy_settings( parsed_relays, &bridge_constraints, Some(location), custom_lists, - ) - .map(|(settings, relay)| SelectedBridge::Normal { settings, relay }) + )?; + Ok(Some(SelectedBridge::Normal { settings, relay })) } - BridgeQuery::Custom(settings) => settings.clone().map(SelectedBridge::Custom), - BridgeQuery::Off | BridgeQuery::Auto => None, + BridgeQuery::Custom(settings) => Ok(settings.clone().map(SelectedBridge::Custom)), + BridgeQuery::Off | BridgeQuery::Auto => Ok(None), } } @@ -942,22 +945,24 @@ impl RelaySelector { constraints: &InternalBridgeConstraints, location: Option, custom_lists: &CustomListsSettings, - ) -> Option<(CustomProxy, Relay)> { + ) -> Result<(CustomProxy, Relay), Error> { let bridges = filter_matching_bridges(constraints, parsed_relays.relays(), custom_lists); + let bridge_data = &parsed_relays.parsed_list().bridge; let bridge = match location { Some(location) => Self::get_proximate_bridge(bridges, location), - None => helpers::pick_random_relay(&bridges).cloned(), + None => helpers::pick_random_relay(&bridges) + .cloned() + .ok_or(Error::NoRelay), }?; - - let bridge_data = &parsed_relays.parsed_list().bridge; - helpers::pick_random_bridge(bridge_data, &bridge).map(|endpoint| (endpoint, bridge.clone())) + let endpoint = helpers::pick_random_bridge(bridge_data, &bridge).ok_or(Error::NoBridge)?; + Ok((endpoint, bridge)) } /// Try to get a bridge which is close to `location`. fn get_proximate_bridge>( relays: Vec, location: T, - ) -> Option { + ) -> Result { /// Number of bridges to keep for selection by distance. const MIN_BRIDGE_COUNT: usize = 5; let location = location.into(); @@ -983,13 +988,15 @@ impl RelaySelector { let greatest_distance: f64 = matching_bridges .iter() .map(|relay| relay.distance) - .reduce(f64::max)?; + .reduce(f64::max) + .ok_or(Error::NoBridge)?; // Define the weight function to prioritize bridges which are closer to `location`. let weight_fn = |relay: &RelayWithDistance| 1 + (greatest_distance - relay.distance) as u64; helpers::pick_random_relay_weighted(&matching_bridges, weight_fn) .cloned() .map(|relay_with_distance| relay_with_distance.relay) + .ok_or(Error::NoBridge) } /// Returns the average location of relays that match the given constraints.