Skip to content

Commit e6ec803

Browse files
authored
Bugfix/send to correct gateway (#213)
* Initial multiple gateway support * Hello random cargo fmt
1 parent 57c43a1 commit e6ec803

File tree

6 files changed

+81
-33
lines changed

6 files changed

+81
-33
lines changed

clients/desktop/src/client/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ impl NymClient {
200200

201201
async fn get_gateway_address<T: NymTopology>(
202202
gateway_id: String,
203-
mut topology_accessor: TopologyAccessor<T>,
203+
topology_accessor: TopologyAccessor<T>,
204204
) -> url::Url {
205205
// we already have our gateway written in the config
206206
let gateway_address = topology_accessor

clients/desktop/src/client/real_traffic_stream.rs

+42-22
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use futures::channel::mpsc;
1919
use futures::task::{Context, Poll};
2020
use futures::{Future, Stream, StreamExt};
2121
use log::{error, info, trace, warn};
22-
use nymsphinx::Destination;
22+
use nymsphinx::{Destination, DestinationAddressBytes};
2323
use std::pin::Pin;
2424
use std::time::Duration;
2525
use tokio::runtime::Handle;
@@ -96,31 +96,48 @@ impl<T: 'static + NymTopology> OutQueueControl<T> {
9696
}
9797
}
9898

99+
async fn get_route(
100+
&self,
101+
client: Option<DestinationAddressBytes>,
102+
) -> Option<Vec<nymsphinx::Node>> {
103+
let route = match client {
104+
None => self.topology_access.random_route().await,
105+
Some(client) => self.topology_access.random_route_to_client(client).await,
106+
};
107+
108+
route
109+
}
110+
99111
async fn on_message(&mut self, next_message: StreamMessage) {
100112
trace!("created new message");
101-
let route = match self.topology_access.random_route().await {
102-
None => {
103-
warn!("No valid topology detected - won't send any real or loop message this time");
104-
// TODO: this creates a potential problem: we can lose real messages if we were
105-
// unable to get topology, perhaps we should store them in some buffer?
106-
return;
107-
}
108-
Some(route) => route,
109-
};
110113

111114
let next_packet = match next_message {
112-
StreamMessage::Cover => mix_client::packet::loop_cover_message_route(
113-
self.our_info.address.clone(),
114-
self.our_info.identifier,
115-
route,
116-
self.average_packet_delay,
117-
),
118-
StreamMessage::Real(real_message) => mix_client::packet::encapsulate_message_route(
119-
real_message.0,
120-
real_message.1,
121-
route,
122-
self.average_packet_delay,
123-
),
115+
StreamMessage::Cover => {
116+
let route = self.get_route(None).await;
117+
if route.is_none() {
118+
warn!("No valid topology detected - won't send any real or loop message this time");
119+
}
120+
let route = route.unwrap();
121+
mix_client::packet::loop_cover_message_route(
122+
self.our_info.address.clone(),
123+
self.our_info.identifier,
124+
route,
125+
self.average_packet_delay,
126+
)
127+
}
128+
StreamMessage::Real(real_message) => {
129+
let route = self.get_route(Some(real_message.0.address.clone())).await;
130+
if route.is_none() {
131+
warn!("No valid topology detected - won't send any real or loop message this time");
132+
}
133+
let route = route.unwrap();
134+
mix_client::packet::encapsulate_message_route(
135+
real_message.0,
136+
real_message.1,
137+
route,
138+
self.average_packet_delay,
139+
)
140+
}
124141
};
125142

126143
let next_packet = match next_packet {
@@ -143,6 +160,9 @@ impl<T: 'static + NymTopology> OutQueueControl<T> {
143160
.unwrap();
144161
// JS: Not entirely sure why or how it fixes stuff, but without the yield call,
145162
// the UnboundedReceiver [of mix_rx] will not get a chance to read anything
163+
// JS2: Basically it was the case that with high enough rate, the stream had already a next value
164+
// ready and hence was immediately re-scheduled causing other tasks to be starved;
165+
// yield makes it go back the scheduling queue regardless of its value availability
146166
tokio::task::yield_now().await;
147167
}
148168

clients/desktop/src/client/topology_control.rs

+24-6
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use crypto::identity::MixIdentityKeyPair;
1717
use futures::lock::Mutex;
1818
use healthcheck::HealthChecker;
1919
use log::*;
20+
use nymsphinx::DestinationAddressBytes;
2021
use std::sync::Arc;
2122
use std::time;
2223
use std::time::Duration;
@@ -57,7 +58,7 @@ impl<T: NymTopology> TopologyAccessor<T> {
5758
}
5859

5960
// not removed until healtchecker is not fully changed to use gateways instead of providers
60-
pub(crate) async fn get_provider_socket_addr(&mut self, id: &str) -> Option<SocketAddr> {
61+
pub(crate) async fn get_provider_socket_addr(&self, id: &str) -> Option<SocketAddr> {
6162
match &self.inner.lock().await.0 {
6263
None => None,
6364
Some(ref topology) => topology
@@ -68,7 +69,7 @@ impl<T: NymTopology> TopologyAccessor<T> {
6869
}
6970
}
7071

71-
pub(crate) async fn get_gateway_socket_url(&mut self, id: &str) -> Option<String> {
72+
pub(crate) async fn get_gateway_socket_url(&self, id: &str) -> Option<String> {
7273
match &self.inner.lock().await.0 {
7374
None => None,
7475
Some(ref topology) => topology
@@ -89,11 +90,11 @@ impl<T: NymTopology> TopologyAccessor<T> {
8990
}
9091

9192
// Unless you absolutely need the entire topology, use `random_route` instead
92-
pub(crate) async fn get_current_topology_clone(&mut self) -> Option<T> {
93+
pub(crate) async fn get_current_topology_clone(&self) -> Option<T> {
9394
self.inner.lock().await.0.clone()
9495
}
9596

96-
pub(crate) async fn get_all_clients(&mut self) -> Option<Vec<provider::Client>> {
97+
pub(crate) async fn get_all_clients(&self) -> Option<Vec<provider::Client>> {
9798
// TODO: this will need to be modified to instead return pairs (provider, client)
9899
match &self.inner.lock().await.0 {
99100
None => None,
@@ -108,9 +109,26 @@ impl<T: NymTopology> TopologyAccessor<T> {
108109
}
109110
}
110111

112+
pub(crate) async fn random_route_to_client(
113+
&self,
114+
client_address: DestinationAddressBytes,
115+
) -> Option<Vec<nymsphinx::Node>> {
116+
let b58_address = client_address.to_base58_string();
117+
let guard = self.inner.lock().await;
118+
let topology = guard.0.as_ref()?;
119+
120+
let gateway = topology
121+
.gateways()
122+
.iter()
123+
.cloned()
124+
.find(|gateway| gateway.has_client(b58_address.clone()))?;
125+
126+
topology.random_route_to(gateway.into()).ok()
127+
}
128+
111129
// this is a rather temporary solution as each client will have an associated provider
112130
// currently that is not implemented yet and there only exists one provider in the network
113-
pub(crate) async fn random_route(&mut self) -> Option<Vec<nymsphinx::Node>> {
131+
pub(crate) async fn random_route(&self) -> Option<Vec<nymsphinx::Node>> {
114132
match &self.inner.lock().await.0 {
115133
None => None,
116134
Some(ref topology) => {
@@ -120,7 +138,7 @@ impl<T: NymTopology> TopologyAccessor<T> {
120138
}
121139
// unwrap is fine here as we asserted there is at least single provider
122140
let provider = gateways.pop().unwrap().into();
123-
topology.route_to(provider).ok()
141+
topology.random_route_to(provider).ok()
124142
}
125143
}
126144
}

common/client-libs/mix-client/src/packet.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ pub fn encapsulate_message<T: NymTopology>(
9797
// unwrap is fine here as we asserted there is at least single provider
9898
let provider = providers.pop().unwrap().into();
9999

100-
let route = topology.route_to(provider)?;
100+
let route = topology.random_route_to(provider)?;
101101

102102
let delays = delays::generate_from_average_duration(route.len(), average_delay);
103103

common/topology/src/gateway.rs

+7
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,13 @@ impl Node {
4040
bs58::decode(&self.pub_key).into(&mut key_bytes).unwrap();
4141
key_bytes
4242
}
43+
44+
pub fn has_client(&self, client_pub_key: String) -> bool {
45+
self.registered_clients
46+
.iter()
47+
.find(|client| client.pub_key == client_pub_key)
48+
.is_some()
49+
}
4350
}
4451

4552
impl filter::Versioned for Node {

common/topology/src/lib.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ pub trait NymTopology: Sized + std::fmt::Debug + Send + Sync + Clone {
7272
}
7373

7474
// Tries to get a route through the mix network
75-
fn mix_route(&self) -> Result<Vec<SphinxNode>, NymTopologyError> {
75+
fn random_mix_route(&self) -> Result<Vec<SphinxNode>, NymTopologyError> {
7676
let mut layered_topology = self.make_layered_topology()?;
7777
let num_layers = layered_topology.len();
7878
let route = (1..=num_layers as u64)
@@ -87,9 +87,12 @@ pub trait NymTopology: Sized + std::fmt::Debug + Send + Sync + Clone {
8787
}
8888

8989
// Sets up a route to a specific provider
90-
fn route_to(&self, provider_node: SphinxNode) -> Result<Vec<SphinxNode>, NymTopologyError> {
90+
fn random_route_to(
91+
&self,
92+
provider_node: SphinxNode,
93+
) -> Result<Vec<SphinxNode>, NymTopologyError> {
9194
Ok(self
92-
.mix_route()?
95+
.random_mix_route()?
9396
.into_iter()
9497
.chain(std::iter::once(provider_node))
9598
.collect())

0 commit comments

Comments
 (0)