Compare commits

...

1 Commits

Author SHA1 Message Date
Jon Häggblad ab280c99cf Initial work to expose latency based selection in sdk 2024-03-12 08:20:51 +01:00
8 changed files with 90 additions and 14 deletions
+1
View File
@@ -18,6 +18,7 @@ pub mod acquire;
pub mod error;
mod utils;
#[derive(Debug)]
pub struct BandwidthController<C, St> {
storage: St,
client: C,
+25
View File
@@ -178,6 +178,13 @@ impl<T> From<PersistedGatewayDetails<T>> for GatewayDetails<T> {
}
}
#[derive(Clone, Debug)]
pub enum GatewaySelectionSpecificationInput {
GatewayIdentity(String),
LatencyBased,
Uniform,
}
#[derive(Clone, Debug)]
pub enum GatewaySelectionSpecification<T = EmptyCustomDetails> {
/// Uniformly choose a random remote gateway.
@@ -226,8 +233,26 @@ impl<T> GatewaySelectionSpecification<T> {
GatewaySelectionSpecification::UniformRemote { must_use_tls }
}
}
pub fn new_from_input(input: GatewaySelectionSpecificationInput, must_use_tls: bool) -> Self {
match input {
GatewaySelectionSpecificationInput::GatewayIdentity(identity) => {
GatewaySelectionSpecification::Specified {
identity,
must_use_tls,
}
}
GatewaySelectionSpecificationInput::LatencyBased => {
GatewaySelectionSpecification::RemoteByLatency { must_use_tls }
}
GatewaySelectionSpecificationInput::Uniform => {
GatewaySelectionSpecification::UniformRemote { must_use_tls }
}
}
}
}
#[derive(Debug)]
pub enum GatewaySetup<T = EmptyCustomDetails> {
/// The gateway specification (details + keys) MUST BE loaded from the underlying storage.
MustLoad,
@@ -64,6 +64,7 @@ pub struct GatewayConfig {
}
// TODO: this should be refactored into a state machine that keeps track of its authentication state
#[derive(Debug)]
pub struct GatewayClient<C, St = EphemeralCredentialStorage> {
authenticated: bool,
disabled_credentials_mode: bool,
@@ -826,6 +827,7 @@ impl<C, St> GatewayClient<C, St> {
// type alias for an ease of use
pub type InitGatewayClient = GatewayClient<InitOnly>;
#[derive(Debug)]
pub struct InitOnly;
impl GatewayClient<InitOnly, EphemeralCredentialStorage> {
@@ -52,6 +52,7 @@ pub(crate) fn ws_fd(_conn: &WsConn) -> Option<RawFd> {
None
}
#[derive(Debug)]
pub(crate) struct PartiallyDelegated {
sink_half: SplitSink<WsConn, Message>,
delegated_stream: (SplitStreamReceiver, oneshot::Sender<()>),
@@ -224,6 +225,7 @@ impl PartiallyDelegated {
// we can either have the stream itself or an option to re-obtain it
// by notifying the future owning it to finish the execution and awaiting the result
// which should be almost immediate (or an invalid state which should never, ever happen)
#[derive(Debug)]
pub(crate) enum SocketState {
Available(Box<WsConn>),
PartiallyDelegated(PartiallyDelegated),
@@ -23,6 +23,12 @@ impl Default for EphemeralStorage {
}
}
impl std::fmt::Debug for EphemeralStorage {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "EphemeralStorage {{ .. }}")
}
}
#[async_trait]
impl Storage for EphemeralStorage {
type StorageError = StorageError;
+1 -1
View File
@@ -39,7 +39,7 @@ mod socks5_client;
mod traits;
pub use client::{DisconnectedMixnetClient, IncludedSurbs, MixnetClientBuilder};
pub use config::{Config, KeyMode};
pub use config::{Config, KeyMode, RequestGateway};
pub use native_client::MixnetClient;
pub use native_client::MixnetClientSender;
pub use nym_client_core::{
+41 -11
View File
@@ -1,7 +1,7 @@
// Copyright 2022-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use super::{connection_state::BuilderState, Config, StoragePaths};
use super::{connection_state::BuilderState, Config, RequestGateway, StoragePaths};
use crate::bandwidth::BandwidthAcquireClient;
use crate::mixnet::socks5_client::Socks5MixnetClient;
use crate::mixnet::{CredentialStorage, MixnetClient, Recipient};
@@ -21,7 +21,9 @@ use nym_client_core::client::base_client::BaseClient;
use nym_client_core::client::key_manager::persistence::KeyStore;
use nym_client_core::config::DebugConfig;
use nym_client_core::init::helpers::current_gateways;
use nym_client_core::init::types::{GatewaySelectionSpecification, GatewaySetup};
use nym_client_core::init::types::{
GatewaySelectionSpecification, GatewaySelectionSpecificationInput, GatewaySetup,
};
use nym_client_core::{
client::{base_client::BaseClientBuilder, replies::reply_storage::ReplyStorageBackend},
config::GatewayEndpointConfig,
@@ -155,11 +157,23 @@ where
/// Request a specific gateway instead of a random one.
#[must_use]
pub fn request_gateway(mut self, user_chosen_gateway: String) -> Self {
// pub fn request_gateway(mut self, user_chosen_gateway: String) -> Self {
pub fn request_gateway(mut self, user_chosen_gateway: RequestGateway) -> Self {
self.config.user_chosen_gateway = Some(user_chosen_gateway);
self
}
/*
/// When a random entry gateway is selected, we skew the probability of selection towards
/// gateways with lower latency.
/// If a specific requested gateway is selected, this will en up doing nothing.
#[must_use]
pub fn latency_based_selection(mut self, latency_based_selection: bool) -> Self {
self.config.latency_based_entry_gateway_selection = Some(latency_based_selection);
self
}
*/
/// Use a specific network instead of the default (mainnet) one.
#[must_use]
pub fn network_details(mut self, network_details: NymNetworkDetails) -> Self {
@@ -466,9 +480,9 @@ where
let gateway_setup = if self.has_valid_gateway_info().await {
GatewaySetup::MustLoad
} else {
let selection_spec = GatewaySelectionSpecification::new(
self.config.user_chosen_gateway.clone(),
None,
let gateway_selection = map_maybe_user_chosen_gateway_to_gateway_selection_specification_input(&self.config.user_chosen_gateway);
let selection_spec = GatewaySelectionSpecification::new_from_input(
gateway_selection,
self.force_tls,
);
@@ -529,11 +543,13 @@ where
let known_gateway = self.has_valid_gateway_info().await;
let mut base_builder: BaseClientBuilder<_, _> = if !known_gateway {
let selection_spec = GatewaySelectionSpecification::new(
self.config.user_chosen_gateway,
None,
self.force_tls,
);
let gateway_selection =
map_maybe_user_chosen_gateway_to_gateway_selection_specification_input(
&self.config.user_chosen_gateway,
);
let selection_spec =
GatewaySelectionSpecification::new_from_input(gateway_selection, self.force_tls);
log::error!("Gateway selection specification: {:?}", selection_spec);
let mut rng = OsRng;
let mut available_gateways = current_gateways(&mut rng, &nym_api_endpoints).await?;
@@ -747,3 +763,17 @@ impl IncludedSurbs {
Self::ExposeSelfAddress
}
}
fn map_maybe_user_chosen_gateway_to_gateway_selection_specification_input(
user_chosen_gateway: &Option<RequestGateway>,
) -> GatewaySelectionSpecificationInput {
match user_chosen_gateway {
Some(selection) => match selection {
RequestGateway::UserChosen(selection) => {
GatewaySelectionSpecificationInput::GatewayIdentity(selection.clone())
}
RequestGateway::LatencyBased => GatewaySelectionSpecificationInput::LatencyBased,
},
None => GatewaySelectionSpecificationInput::Uniform,
}
}
+12 -2
View File
@@ -1,4 +1,6 @@
use nym_client_core::config::{Client as ClientConfig, DebugConfig};
use nym_client_core::{
config::{Client as ClientConfig, DebugConfig},
};
use nym_network_defaults::NymNetworkDetails;
use nym_socks5_client_core::config::BaseClientConfig;
use url::Url;
@@ -20,12 +22,20 @@ impl KeyMode {
}
}
#[derive(Clone, Debug)]
pub enum RequestGateway {
UserChosen(String),
LatencyBased,
}
/// Config struct for [`crate::mixnet::MixnetClient`]
#[derive(Default)]
pub struct Config {
/// If the user has explicitly specified a gateway.
pub user_chosen_gateway: Option<String>,
// pub user_chosen_gateway: Option<String>,
pub user_chosen_gateway: Option<RequestGateway>,
// pub latency_based_entry_gateway_selection: Option<bool>,
/// Determines how to handle existing key files found.
pub key_mode: KeyMode,