Updated directory_client reqwest to 0.10 (#226)

* Updated directory_client reqwest to 0.10

* Using consistent syntax
This commit is contained in:
Jędrzej Stuczyński
2020-05-12 12:52:31 +01:00
committed by GitHub
parent f47b7cfb13
commit ff2e24afbc
25 changed files with 759 additions and 480 deletions
Generated
+179 -8
View File
@@ -582,11 +582,13 @@ dependencies = [
name = "directory-client"
version = "0.1.0"
dependencies = [
"futures 0.3.4",
"log 0.4.8",
"mockito",
"pretty_env_logger",
"reqwest",
"reqwest 0.10.4",
"serde",
"tokio 0.2.16",
"topology",
]
@@ -970,6 +972,25 @@ dependencies = [
"tokio-io",
]
[[package]]
name = "h2"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79b7246d7e4b979c03fa093da39cfb3617a96bbeee6310af63991668d7e843ff"
dependencies = [
"bytes 0.5.4",
"fnv",
"futures-core",
"futures-sink",
"futures-util",
"http 0.2.1",
"indexmap",
"log 0.4.8",
"slab",
"tokio 0.2.16",
"tokio-util",
]
[[package]]
name = "handlebars"
version = "3.0.1"
@@ -1067,6 +1088,16 @@ dependencies = [
"tokio-buf",
]
[[package]]
name = "http-body"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b"
dependencies = [
"bytes 0.5.4",
"http 0.2.1",
]
[[package]]
name = "httparse"
version = "1.3.4"
@@ -1110,9 +1141,9 @@ dependencies = [
"bytes 0.4.12",
"futures 0.1.29",
"futures-cpupool",
"h2",
"h2 0.1.26",
"http 0.1.21",
"http-body",
"http-body 0.1.0",
"httparse",
"iovec",
"itoa",
@@ -1128,7 +1159,31 @@ dependencies = [
"tokio-tcp",
"tokio-threadpool",
"tokio-timer",
"want",
"want 0.2.0",
]
[[package]]
name = "hyper"
version = "0.13.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96816e1d921eca64d208a85aab4f7798455a8e34229ee5a88c935bdee1b78b14"
dependencies = [
"bytes 0.5.4",
"futures-channel",
"futures-core",
"futures-util",
"h2 0.2.5",
"http 0.2.1",
"http-body 0.3.1",
"httparse",
"itoa",
"log 0.4.8",
"net2",
"pin-project",
"time",
"tokio 0.2.16",
"tower-service",
"want 0.3.0",
]
[[package]]
@@ -1144,6 +1199,19 @@ dependencies = [
"tokio-io",
]
[[package]]
name = "hyper-tls"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3adcd308402b9553630734e9c36b77a7e48b3821251ca2493e8cd596763aafaa"
dependencies = [
"bytes 0.5.4",
"hyper 0.13.5",
"native-tls",
"tokio 0.2.16",
"tokio-tls",
]
[[package]]
name = "idna"
version = "0.1.5"
@@ -1617,7 +1685,7 @@ dependencies = [
"pem",
"pemstore",
"pretty_env_logger",
"reqwest",
"reqwest 0.9.24",
"serde",
"serde_json",
"tempfile",
@@ -2357,14 +2425,14 @@ dependencies = [
"futures 0.1.29",
"http 0.1.21",
"hyper 0.12.35",
"hyper-tls",
"hyper-tls 0.3.2",
"log 0.4.8",
"mime 0.3.16",
"mime_guess 2.0.3",
"native-tls",
"serde",
"serde_json",
"serde_urlencoded",
"serde_urlencoded 0.5.5",
"time",
"tokio 0.1.22",
"tokio-executor",
@@ -2376,6 +2444,42 @@ dependencies = [
"winreg",
]
[[package]]
name = "reqwest"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02b81e49ddec5109a9dcfc5f2a317ff53377c915e9ae9d4f2fb50914b85614e2"
dependencies = [
"base64 0.11.0",
"bytes 0.5.4",
"encoding_rs",
"futures-core",
"futures-util",
"http 0.2.1",
"http-body 0.3.1",
"hyper 0.13.5",
"hyper-tls 0.4.1",
"js-sys",
"lazy_static",
"log 0.4.8",
"mime 0.3.16",
"mime_guess 2.0.3",
"native-tls",
"percent-encoding 2.1.0",
"pin-project-lite",
"serde",
"serde_json",
"serde_urlencoded 0.6.1",
"time",
"tokio 0.2.16",
"tokio-tls",
"url 2.1.1",
"wasm-bindgen",
"wasm-bindgen-futures 0.4.10",
"web-sys",
"winreg",
]
[[package]]
name = "route-recognizer"
version = "0.1.13"
@@ -2535,6 +2639,18 @@ dependencies = [
"url 1.7.2",
]
[[package]]
name = "serde_urlencoded"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ec5d77e2d4c73717816afac02670d5c4f534ea95ed430442cad02e7a6e32c97"
dependencies = [
"dtoa",
"itoa",
"serde",
"url 2.1.1",
]
[[package]]
name = "sha-1"
version = "0.8.2"
@@ -2954,6 +3070,16 @@ dependencies = [
"tokio-executor",
]
[[package]]
name = "tokio-tls"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a70f4fcd7b3b24fb194f837560168208f669ca8cb70d0c4b862944452396343"
dependencies = [
"native-tls",
"tokio 0.2.16",
]
[[package]]
name = "tokio-tungstenite"
version = "0.10.1"
@@ -2967,6 +3093,20 @@ dependencies = [
"tungstenite",
]
[[package]]
name = "tokio-util"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499"
dependencies = [
"bytes 0.5.4",
"futures-core",
"futures-sink",
"log 0.4.8",
"pin-project-lite",
"tokio 0.2.16",
]
[[package]]
name = "toml"
version = "0.5.6"
@@ -2981,6 +3121,7 @@ name = "topology"
version = "0.1.0"
dependencies = [
"bs58",
"futures 0.3.4",
"itertools",
"log 0.4.8",
"nymsphinx",
@@ -2990,6 +3131,12 @@ dependencies = [
"version-checker",
]
[[package]]
name = "tower-service"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e987b6bf443f4b5b3b6f38704195592cca41c5bb7aedd3c3693c7081f8289860"
[[package]]
name = "traitobject"
version = "0.1.0"
@@ -3207,6 +3354,16 @@ dependencies = [
"try-lock",
]
[[package]]
name = "want"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0"
dependencies = [
"log 0.4.8",
"try-lock",
]
[[package]]
name = "wasi"
version = "0.9.0+wasi-snapshot-preview1"
@@ -3220,6 +3377,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2cc57ce05287f8376e998cbddfb4c8cb43b84a7ec55cf4551d7c00eef317a47f"
dependencies = [
"cfg-if",
"serde",
"serde_json",
"wasm-bindgen-macro",
]
@@ -3251,6 +3410,18 @@ dependencies = [
"web-sys",
]
[[package]]
name = "wasm-bindgen-futures"
version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7add542ea1ac7fdaa9dc25e031a6af33b7d63376292bd24140c637d00d1c312a"
dependencies = [
"cfg-if",
"js-sys",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.60"
@@ -3291,7 +3462,7 @@ dependencies = [
"js-sys",
"scoped-tls",
"wasm-bindgen",
"wasm-bindgen-futures",
"wasm-bindgen-futures 0.3.27",
"wasm-bindgen-test-macro",
]
+1 -1
View File
@@ -29,7 +29,7 @@ use gateway_client::{GatewayClient, SphinxPacketReceiver, SphinxPacketSender};
use gateway_requests::auth_token::AuthToken;
use log::*;
use nymsphinx::chunking::split_and_prepare_payloads;
use nymsphinx::{Destination, DestinationAddressBytes};
use nymsphinx::DestinationAddressBytes;
use received_buffer::{ReceivedBufferMessage, ReconstructedMessagesReceiver};
use tokio::runtime::Runtime;
@@ -157,7 +157,8 @@ impl<T: 'static + NymTopology> TopologyRefresher<T> {
}
async fn get_current_compatible_topology(&self) -> T {
let full_topology = T::new(self.directory_server.clone());
// note: this call makes it neccessary that `T::new()`does *not* have 'static lifetime
let full_topology = T::new(self.directory_server.clone()).await;
// just filter by version and assume the validators will remove all bad behaving
// nodes with the staking
full_topology.filter_system_version(built_info::PKG_VERSION)
+1 -1
View File
@@ -89,7 +89,7 @@ async fn choose_gateway(
our_address: DestinationAddressBytes,
) -> (String, AuthToken) {
// TODO: once we change to graph topology this here will need to be updated!
let topology = Topology::new(directory_server.clone());
let topology = Topology::new(directory_server.clone()).await;
let version_filtered_topology = topology.filter_system_version(built_info::PKG_VERSION);
// don't care about health of the networks as mixes can go up and down any time,
// but DO care about gateways
@@ -8,8 +8,9 @@ edition = "2018"
[dependencies]
log = "0.4"
futures = "0.3"
pretty_env_logger = "0.3"
reqwest = "0.9.22"
reqwest = { version = "0.10", features = ["json"] }
serde = { version = "1.0.104", features = ["derive"] }
## internal
@@ -17,3 +18,4 @@ topology = {path = "../../topology"}
[dev-dependencies]
mockito = "0.23.0"
tokio = { version = "0.2", features = ["macros"] }
+103 -41
View File
@@ -12,24 +12,21 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use crate::requests::health_check_get::{HealthCheckRequester, Request as HealthCheckRequest};
use crate::requests::metrics_mixes_get::{MetricsMixRequester, Request as MetricsMixRequest};
use crate::requests::metrics_mixes_post::{MetricsMixPoster, Request as MetricsMixPost};
use crate::requests::presence_coconodes_post::{
PresenceCocoNodesPoster, Request as PresenceCocoNodesPost,
};
use crate::requests::presence_gateways_post::{
PresenceGatewayPoster, Request as PresenceGatewayPost,
};
use crate::requests::presence_mixnodes_post::{
PresenceMixNodesPoster, Request as PresenceMixNodesPost,
};
use crate::requests::presence_providers_post::{
PresenceMixProviderPoster, Request as PresenceProvidersPost,
};
use crate::requests::presence_topology_get::{
PresenceTopologyGetRequester, Request as PresenceTopologyRequest,
use crate::requests::health_check_get::Request as HealthCheckRequest;
use crate::requests::metrics_mixes_get::Request as MetricsMixRequest;
use crate::requests::metrics_mixes_post::Request as MetricsMixPost;
use crate::requests::presence_coconodes_post::Request as PresenceCocoNodesPost;
use crate::requests::presence_gateways_post::Request as PresenceGatewayPost;
use crate::requests::presence_mixnodes_post::Request as PresenceMixNodesPost;
use crate::requests::presence_providers_post::Request as PresenceProvidersPost;
use crate::requests::presence_topology_get::Request as PresenceTopologyRequest;
use metrics::{MixMetric, PersistedMixMetric};
use presence::{
coconodes::CocoPresence, gateways::GatewayPresence, mixnodes::MixNodePresence,
providers::MixProviderPresence, Topology,
};
use requests::{health_check_get::HealthCheckResponse, DirectoryGetRequest, DirectoryPostRequest};
pub mod metrics;
pub mod presence;
@@ -50,35 +47,100 @@ pub trait DirectoryClient {
}
pub struct Client {
pub health_check: HealthCheckRequest,
pub metrics_mixes: MetricsMixRequest,
pub metrics_post: MetricsMixPost,
pub presence_coconodes_post: PresenceCocoNodesPost,
pub presence_gateway_post: PresenceGatewayPost,
pub presence_mix_nodes_post: PresenceMixNodesPost,
pub presence_providers_post: PresenceProvidersPost,
pub presence_topology: PresenceTopologyRequest,
base_url: String,
reqwest_client: reqwest::Client,
}
impl DirectoryClient for Client {
fn new(config: Config) -> Client {
let health_check = HealthCheckRequest::new(config.base_url.clone());
let metrics_mixes = MetricsMixRequest::new(config.base_url.clone());
let metrics_post = MetricsMixPost::new(config.base_url.clone());
let presence_topology = PresenceTopologyRequest::new(config.base_url.clone());
let presence_coconodes_post = PresenceCocoNodesPost::new(config.base_url.clone());
let presence_gateway_post = PresenceGatewayPost::new(config.base_url.clone());
let presence_mix_nodes_post = PresenceMixNodesPost::new(config.base_url.clone());
let presence_providers_post = PresenceProvidersPost::new(config.base_url);
let reqwest_client = reqwest::Client::new();
Client {
health_check,
metrics_mixes,
metrics_post,
presence_coconodes_post,
presence_gateway_post,
presence_mix_nodes_post,
presence_providers_post,
presence_topology,
base_url: config.base_url,
reqwest_client,
}
}
}
impl Client {
async fn post<R: DirectoryPostRequest>(
&self,
request: R,
) -> reqwest::Result<reqwest::Response> {
self.reqwest_client
.post(&request.url())
.json(request.json_payload())
.send()
.await
}
async fn get<R: DirectoryGetRequest>(&self, request: R) -> reqwest::Result<R::JSONResponse> {
self.reqwest_client
.get(&request.url())
.send()
.await?
.json()
.await
}
pub async fn get_healthcheck(&self) -> reqwest::Result<HealthCheckResponse> {
let req = HealthCheckRequest::new(&self.base_url);
self.get(req).await
}
pub async fn post_mix_metrics(&self, metrics: MixMetric) -> reqwest::Result<reqwest::Response> {
let req = MetricsMixPost::new(&self.base_url, metrics);
self.post(req).await
}
pub async fn get_mix_metrics(&self) -> reqwest::Result<Vec<PersistedMixMetric>> {
let req = MetricsMixRequest::new(&self.base_url);
self.get(req).await
}
pub async fn post_coconode_presence(
&self,
presence: CocoPresence,
) -> reqwest::Result<reqwest::Response> {
let req = PresenceCocoNodesPost::new(&self.base_url, presence);
self.post(req).await
}
pub async fn post_gateway_presence(
&self,
presence: GatewayPresence,
) -> reqwest::Result<reqwest::Response> {
let req = PresenceGatewayPost::new(&self.base_url, presence);
self.post(req).await
}
pub async fn post_mixnode_presence(
&self,
presence: MixNodePresence,
) -> reqwest::Result<reqwest::Response> {
let req = PresenceMixNodesPost::new(&self.base_url, presence);
self.post(req).await
}
// this should be soft-deprecated as the whole concept of provider will
// be removed in the next topology rework
pub async fn post_provider_presence(
&self,
presence: MixProviderPresence,
) -> reqwest::Result<reqwest::Response> {
let req = PresenceProvidersPost::new(&self.base_url, presence);
self.post(req).await
}
pub async fn get_topology(&self) -> reqwest::Result<Topology> {
let req = PresenceTopologyRequest::new(&self.base_url);
self.get(req).await
}
}
#[cfg(test)]
pub(crate) fn client_test_fixture(base_url: &str) -> Client {
Client {
base_url: base_url.to_string(),
reqwest_client: reqwest::Client::new(),
}
}
@@ -12,122 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use crate::requests::presence_topology_get::PresenceTopologyGetRequester;
use crate::{Client, Config, DirectoryClient};
use log::*;
use serde::{Deserialize, Serialize};
use std::convert::TryInto;
use topology::{coco, gateway, mix, provider, NymTopology};
pub mod coconodes;
pub mod gateways;
pub mod mixnodes;
pub mod providers;
pub mod topology;
// Topology shows us the current state of the overall Nym network
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Topology {
pub coco_nodes: Vec<coconodes::CocoPresence>,
pub mix_nodes: Vec<mixnodes::MixNodePresence>,
pub mix_provider_nodes: Vec<providers::MixProviderPresence>,
pub gateway_nodes: Vec<gateways::GatewayPresence>,
}
impl NymTopology for Topology {
// TODO: this will need some changes to not imply having to make an HTTP request in constructor
fn new(directory_server: String) -> Self {
debug!("Using directory server: {:?}", directory_server);
let directory_config = Config {
base_url: directory_server,
};
let directory = Client::new(directory_config);
directory
.presence_topology
.get()
.expect("Failed to retrieve network topology.")
}
fn new_from_nodes(
mix_nodes: Vec<mix::Node>,
mix_provider_nodes: Vec<provider::Node>,
coco_nodes: Vec<coco::Node>,
gateway_nodes: Vec<gateway::Node>,
) -> Self {
Topology {
coco_nodes: coco_nodes.into_iter().map(|node| node.into()).collect(),
mix_nodes: mix_nodes.into_iter().map(|node| node.into()).collect(),
mix_provider_nodes: mix_provider_nodes
.into_iter()
.map(|node| node.into())
.collect(),
gateway_nodes: gateway_nodes.into_iter().map(|node| node.into()).collect(),
}
}
fn mix_nodes(&self) -> Vec<mix::Node> {
self.mix_nodes
.iter()
.filter_map(|x| x.clone().try_into().ok())
.collect()
}
fn providers(&self) -> Vec<provider::Node> {
self.mix_provider_nodes
.iter()
.map(|x| x.clone().into())
.collect()
}
fn gateways(&self) -> Vec<gateway::Node> {
self.gateway_nodes
.iter()
.map(|x| x.clone().into())
.collect()
}
fn coco_nodes(&self) -> Vec<topology::coco::Node> {
self.coco_nodes.iter().map(|x| x.clone().into()).collect()
}
}
#[cfg(test)]
mod converting_mixnode_presence_into_topology_mixnode {
use super::*;
#[test]
fn it_returns_error_on_unresolvable_hostname() {
let unresolvable_hostname = "foomp.foomp.foomp:1234";
let mix_presence = mixnodes::MixNodePresence {
location: "".to_string(),
host: unresolvable_hostname.to_string(),
pub_key: "".to_string(),
layer: 0,
last_seen: 0,
version: "".to_string(),
};
let _result: Result<mix::Node, std::io::Error> = mix_presence.try_into();
// assert!(result.is_err()) // This fails only for me. Why?
// ¯\_(ツ)_/¯ - works on my machine (and travis)
}
#[test]
fn it_returns_resolved_ip_on_resolvable_hostname() {
let resolvable_hostname = "nymtech.net:1234";
let mix_presence = mixnodes::MixNodePresence {
location: "".to_string(),
host: resolvable_hostname.to_string(),
pub_key: "".to_string(),
layer: 0,
last_seen: 0,
version: "".to_string(),
};
let result: Result<topology::mix::Node, std::io::Error> = mix_presence.try_into();
assert!(result.is_ok())
}
}
pub use self::topology::Topology;
@@ -0,0 +1,133 @@
// Copyright 2020 Nym Technologies SA
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use super::{coconodes, gateways, mixnodes, providers};
use crate::{Client, Config, DirectoryClient};
use futures::future::BoxFuture;
use log::*;
use serde::{Deserialize, Serialize};
use std::convert::TryInto;
use topology::{coco, gateway, mix, provider, NymTopology};
// Topology shows us the current state of the overall Nym network
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Topology {
pub coco_nodes: Vec<coconodes::CocoPresence>,
pub mix_nodes: Vec<mixnodes::MixNodePresence>,
pub mix_provider_nodes: Vec<providers::MixProviderPresence>,
pub gateway_nodes: Vec<gateways::GatewayPresence>,
}
impl NymTopology for Topology {
// TODO: this will need some changes to not imply having to make an HTTP request in constructor
// TODO2: and also be reworked/removed with the topology re-work
fn new<'a>(directory_server: String) -> BoxFuture<'a, Self> {
debug!("Using directory server: {:?}", directory_server);
let directory_config = Config {
base_url: directory_server,
};
let directory = Client::new(directory_config);
Box::pin({
async move {
directory
.get_topology()
.await
.expect("Failed to retrieve network topology.")
}
})
}
fn new_from_nodes(
mix_nodes: Vec<mix::Node>,
mix_provider_nodes: Vec<provider::Node>,
coco_nodes: Vec<coco::Node>,
gateway_nodes: Vec<gateway::Node>,
) -> Self {
Topology {
coco_nodes: coco_nodes.into_iter().map(|node| node.into()).collect(),
mix_nodes: mix_nodes.into_iter().map(|node| node.into()).collect(),
mix_provider_nodes: mix_provider_nodes
.into_iter()
.map(|node| node.into())
.collect(),
gateway_nodes: gateway_nodes.into_iter().map(|node| node.into()).collect(),
}
}
fn mix_nodes(&self) -> Vec<mix::Node> {
self.mix_nodes
.iter()
.filter_map(|x| x.clone().try_into().ok())
.collect()
}
fn providers(&self) -> Vec<provider::Node> {
self.mix_provider_nodes
.iter()
.map(|x| x.clone().into())
.collect()
}
fn gateways(&self) -> Vec<gateway::Node> {
self.gateway_nodes
.iter()
.map(|x| x.clone().into())
.collect()
}
fn coco_nodes(&self) -> Vec<topology::coco::Node> {
self.coco_nodes.iter().map(|x| x.clone().into()).collect()
}
}
#[cfg(test)]
mod converting_mixnode_presence_into_topology_mixnode {
use super::*;
#[test]
fn it_returns_error_on_unresolvable_hostname() {
let unresolvable_hostname = "foomp.foomp.foomp:1234";
let mix_presence = mixnodes::MixNodePresence {
location: "".to_string(),
host: unresolvable_hostname.to_string(),
pub_key: "".to_string(),
layer: 0,
last_seen: 0,
version: "".to_string(),
};
let result: Result<mix::Node, std::io::Error> = mix_presence.try_into();
assert!(result.is_err()) // This fails only for me. Why?
// ¯\_(ツ)_/¯ - works on my machine (and travis)
// Is it still broken?
}
#[test]
fn it_returns_resolved_ip_on_resolvable_hostname() {
let resolvable_hostname = "nymtech.net:1234";
let mix_presence = mixnodes::MixNodePresence {
location: "".to_string(),
host: resolvable_hostname.to_string(),
pub_key: "".to_string(),
layer: 0,
last_seen: 0,
version: "".to_string(),
};
let result: Result<topology::mix::Node, std::io::Error> = mix_presence.try_into();
assert!(result.is_ok())
}
}
@@ -12,49 +12,53 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use reqwest::Response;
use super::{DirectoryGetRequest, DirectoryRequest};
use serde::{Deserialize, Serialize};
const PATH: &str = "/api/healthcheck";
#[derive(Deserialize, Serialize)]
pub struct HealthCheckResponse {
pub ok: bool,
}
pub struct Request {
base_url: String,
path: String,
}
pub trait HealthCheckRequester {
fn new(base_url: String) -> Self;
fn get(&self) -> Result<Response, reqwest::Error>;
impl DirectoryRequest for Request {
fn url(&self) -> String {
format!("{}{}", self.base_url, self.path)
}
}
impl HealthCheckRequester for Request {
fn new(base_url: String) -> Self {
Request {
base_url,
path: "/api/healthcheck".to_string(),
}
}
impl DirectoryGetRequest for Request {
type JSONResponse = HealthCheckResponse;
fn get(&self) -> Result<Response, reqwest::Error> {
let url = format!("{}{}", self.base_url, self.path);
reqwest::get(&url)
fn new(base_url: &str) -> Self {
Request {
base_url: base_url.to_string(),
path: PATH.to_string(),
}
}
}
#[cfg(test)]
mod healthcheck_requests {
use super::*;
#[cfg(test)]
use crate::client_test_fixture;
use mockito::mock;
#[cfg(test)]
mod on_a_400_status {
use super::*;
#[test]
#[should_panic]
fn it_returns_an_error() {
#[tokio::test]
async fn it_returns_an_error() {
let _m = mock("GET", "/api/healthcheck").with_status(400).create();
let req = Request::new(mockito::server_url());
assert!(req.get().is_err());
let client = client_test_fixture(&mockito::server_url());
let res = client.get_healthcheck().await;
assert!(res.is_err());
_m.assert();
}
}
@@ -63,11 +67,18 @@ mod healthcheck_requests {
mod on_a_200 {
use super::*;
#[test]
fn it_returns_a_response_with_200_status() {
let _m = mock("GET", "/api/healthcheck").with_status(200).create();
let req = Request::new(mockito::server_url());
assert!(req.get().is_ok());
#[tokio::test]
async fn it_returns_a_response_with_200_status() {
let json = r#"{
"ok": true
}"#;
let _m = mock("GET", "/api/healthcheck")
.with_status(200)
.with_body(json)
.create();
let client = client_test_fixture(&mockito::server_url());
let res = client.get_healthcheck().await;
assert!(res.unwrap().ok);
_m.assert();
}
}
@@ -12,50 +12,49 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use super::{DirectoryGetRequest, DirectoryRequest};
use crate::metrics::PersistedMixMetric;
const PATH: &str = "/api/metrics/mixes";
pub struct Request {
base_url: String,
path: String,
}
pub trait MetricsMixRequester {
fn new(base_url: String) -> Self;
fn get(&self) -> Result<Vec<PersistedMixMetric>, reqwest::Error>;
impl DirectoryRequest for Request {
fn url(&self) -> String {
format!("{}{}", self.base_url, self.path)
}
}
impl MetricsMixRequester for Request {
fn new(base_url: String) -> Self {
Request {
base_url,
path: "/api/metrics/mixes".to_string(),
}
}
impl DirectoryGetRequest for Request {
type JSONResponse = Vec<PersistedMixMetric>;
fn get(&self) -> Result<Vec<PersistedMixMetric>, reqwest::Error> {
let url = format!("{}{}", self.base_url, self.path);
let mix_metric_vec = reqwest::get(&url)?.json()?;
Ok(mix_metric_vec)
fn new(base_url: &str) -> Self {
Request {
base_url: base_url.to_string(),
path: PATH.to_string(),
}
}
}
#[cfg(test)]
mod metrics_get_request {
use super::*;
#[cfg(test)]
use crate::client_test_fixture;
use mockito::mock;
#[cfg(test)]
mod on_a_400_status {
use super::*;
#[test]
#[should_panic]
fn it_returns_an_error() {
let _m = mock("GET", "/api/metrics/mixes").with_status(400).create();
let req = Request::new(mockito::server_url());
req.get().unwrap();
#[tokio::test]
async fn it_returns_an_error() {
let _m = mock("GET", PATH).with_status(400).create();
let client = client_test_fixture(&mockito::server_url());
let result = client.get_mix_metrics().await;
assert!(result.is_err());
_m.assert();
}
}
@@ -63,20 +62,15 @@ mod metrics_get_request {
#[cfg(test)]
mod on_a_200 {
use super::*;
#[test]
fn it_returns_a_response_with_200_status_and_a_correct_topology() {
#[tokio::test]
async fn it_returns_a_response_with_200_status_and_a_correct_metrics() {
let json = fixtures::mix_metrics_response_json();
let _m = mock("GET", "/api/metrics/mixes")
.with_status(200)
.with_body(json)
.create();
let req = Request::new(mockito::server_url());
let result = req.get();
assert_eq!(true, result.is_ok());
assert_eq!(
1576061080635800000,
result.unwrap().first().unwrap().timestamp
);
let _m = mock("GET", PATH).with_status(200).with_body(json).create();
let client = client_test_fixture(&mockito::server_url());
let result = client.get_mix_metrics().await;
let unwrapped = result.unwrap();
assert_eq!(10, unwrapped.first().unwrap().received);
_m.assert();
}
}
@@ -84,7 +78,7 @@ mod metrics_get_request {
#[cfg(test)]
mod fixtures {
#[cfg(test)]
pub fn mix_metrics_response_json() -> String {
pub fn mix_metrics_response_json() -> &'static str {
r#"[
{
"pubKey": "OwOqwWjh_IlnaWS2PxO6odnhNahOYpRCkju50beQCTA=",
@@ -247,7 +241,6 @@ mod metrics_get_request {
"timestamp": 1576061080501732900
}
]"#
.to_string()
}
}
}
@@ -12,52 +12,53 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use super::{DirectoryPostRequest, DirectoryRequest};
use crate::metrics::MixMetric;
use reqwest::Response;
const PATH: &str = "/api/metrics/mixes";
pub struct Request {
base_url: String,
path: String,
payload: MixMetric,
}
pub trait MetricsMixPoster {
fn new(base_url: String) -> Self;
fn post(&self, metric: &MixMetric) -> Result<Response, reqwest::Error>;
impl DirectoryRequest for Request {
fn url(&self) -> String {
format!("{}{}", self.base_url, self.path)
}
}
impl MetricsMixPoster for Request {
fn new(base_url: String) -> Self {
Request {
base_url,
path: "/api/metrics/mixes".to_string(),
}
impl DirectoryPostRequest for Request {
type Payload = MixMetric;
fn json_payload(&self) -> &MixMetric {
&self.payload
}
fn post(&self, metric: &MixMetric) -> Result<Response, reqwest::Error> {
let url = format!("{}{}", self.base_url, self.path);
let client = reqwest::Client::new();
let mix_metric_vec = client.post(&url).json(&metric).send()?;
Ok(mix_metric_vec)
fn new(base_url: &str, payload: Self::Payload) -> Self {
Request {
base_url: base_url.to_string(),
path: PATH.to_string(),
payload,
}
}
}
#[cfg(test)]
mod metrics_get_request {
mod metrics_post_request {
use super::*;
#[cfg(test)]
use crate::client_test_fixture;
use mockito::mock;
#[cfg(test)]
mod on_a_400_status {
use super::*;
#[test]
fn it_returns_an_error() {
let _m = mock("POST", "/api/metrics/mixes").with_status(400).create();
let req = Request::new(mockito::server_url());
let metric = fixtures::new_metric();
let result = req.post(&metric);
#[tokio::test]
async fn it_returns_an_error() {
let _m = mock("POST", PATH).with_status(400).create();
let client = client_test_fixture(&mockito::server_url());
let result = client.post_mix_metrics(fixtures::new_metric()).await;
assert_eq!(400, result.unwrap().status());
_m.assert();
}
@@ -66,17 +67,16 @@ mod metrics_get_request {
#[cfg(test)]
mod on_a_200 {
use super::*;
#[test]
fn it_returns_a_response_with_200() {
#[tokio::test]
async fn it_returns_a_response_with_200() {
let json = fixtures::mix_metrics_response_json();
let _m = mock("POST", "/api/metrics/mixes")
.with_status(201)
.with_body(json)
.create();
let req = Request::new(mockito::server_url());
let metric = fixtures::new_metric();
let result = req.post(&metric);
assert_eq!(true, result.is_ok());
let client = client_test_fixture(&mockito::server_url());
let result = client.post_mix_metrics(fixtures::new_metric()).await;
assert!(result.is_ok());
_m.assert();
}
}
@@ -20,3 +20,26 @@ pub mod presence_gateways_post;
pub mod presence_mixnodes_post;
pub mod presence_providers_post;
pub mod presence_topology_get;
use serde::{de::DeserializeOwned, Serialize};
pub(crate) trait DirectoryRequest {
fn url(&self) -> String;
}
pub(crate) trait DirectoryGetRequest: DirectoryRequest {
// perhaps the name of this is not the best because it's technically not a JSON,
// but something that can be deserialised from JSON.
// I'm open to all suggestions on how to rename it
type JSONResponse: DeserializeOwned;
fn new(base_url: &str) -> Self;
}
pub(crate) trait DirectoryPostRequest: DirectoryRequest {
// Similarly this, it's something that can be serialized into a JSON
type Payload: Serialize + ?Sized;
fn new(base_url: &str, payload: Self::Payload) -> Self;
fn json_payload(&self) -> &Self::Payload;
}
@@ -12,54 +12,54 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use super::{DirectoryPostRequest, DirectoryRequest};
use crate::presence::coconodes::CocoPresence;
use reqwest::Response;
const PATH: &str = "/api/presence/coconodes";
pub struct Request {
base_url: String,
path: String,
payload: CocoPresence,
}
pub trait PresenceCocoNodesPoster {
fn new(base_url: String) -> Self;
fn post(&self, presence: &CocoPresence) -> Result<Response, reqwest::Error>;
impl DirectoryRequest for Request {
fn url(&self) -> String {
format!("{}{}", self.base_url, self.path)
}
}
impl PresenceCocoNodesPoster for Request {
fn new(base_url: String) -> Self {
Request {
base_url,
path: "/api/presence/coconodes".to_string(),
}
impl DirectoryPostRequest for Request {
type Payload = CocoPresence;
fn json_payload(&self) -> &CocoPresence {
&self.payload
}
fn post(&self, presence: &CocoPresence) -> Result<Response, reqwest::Error> {
let url = format!("{}{}", self.base_url, self.path);
let client = reqwest::Client::new();
let p = client.post(&url).json(&presence).send()?;
Ok(p)
fn new(base_url: &str, payload: Self::Payload) -> Self {
Request {
base_url: base_url.to_string(),
path: PATH.to_string(),
payload,
}
}
}
#[cfg(test)]
mod metrics_get_request {
mod presence_coconodes_post_request {
use super::*;
#[cfg(test)]
use crate::client_test_fixture;
use mockito::mock;
#[cfg(test)]
mod on_a_400_status {
use super::*;
#[test]
fn it_returns_an_error() {
let _m = mock("POST", "/api/presence/coconodes")
.with_status(400)
.create();
let req = Request::new(mockito::server_url());
#[tokio::test]
async fn it_returns_an_error() {
let _m = mock("POST", PATH).with_status(400).create();
let client = client_test_fixture(&mockito::server_url());
let presence = fixtures::new_presence();
let result = req.post(&presence);
let result = client.post_coconode_presence(presence).await;
assert_eq!(400, result.unwrap().status());
_m.assert();
}
@@ -68,19 +68,16 @@ mod metrics_get_request {
#[cfg(test)]
mod on_a_200 {
use super::*;
#[test]
fn it_returns_a_response_with_201() {
#[tokio::test]
async fn it_returns_a_response_with_201() {
let json = r#"{
"ok": true
}"#;
let _m = mock("POST", "/api/presence/coconodes")
.with_status(201)
.with_body(json)
.create();
let req = Request::new(mockito::server_url());
let _m = mock("POST", PATH).with_status(201).with_body(json).create();
let client = client_test_fixture(&mockito::server_url());
let presence = fixtures::new_presence();
let result = req.post(&presence);
assert_eq!(true, result.is_ok());
let result = client.post_coconode_presence(presence).await;
assert!(result.is_ok());
_m.assert();
}
}
@@ -12,54 +12,54 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use super::{DirectoryPostRequest, DirectoryRequest};
use crate::presence::gateways::GatewayPresence;
use reqwest::Response;
const PATH: &str = "/api/presence/gateways";
pub struct Request {
base_url: String,
path: String,
payload: GatewayPresence,
}
pub trait PresenceGatewayPoster {
fn new(base_url: String) -> Self;
fn post(&self, presence: &GatewayPresence) -> Result<Response, reqwest::Error>;
impl DirectoryRequest for Request {
fn url(&self) -> String {
format!("{}{}", self.base_url, self.path)
}
}
impl PresenceGatewayPoster for Request {
fn new(base_url: String) -> Self {
Request {
base_url,
path: "/api/presence/gateways".to_string(),
}
impl DirectoryPostRequest for Request {
type Payload = GatewayPresence;
fn json_payload(&self) -> &GatewayPresence {
&self.payload
}
fn post(&self, presence: &GatewayPresence) -> Result<Response, reqwest::Error> {
let url = format!("{}{}", self.base_url, self.path);
let client = reqwest::Client::new();
let p = client.post(&url).json(&presence).send()?;
Ok(p)
fn new(base_url: &str, payload: Self::Payload) -> Self {
Request {
base_url: base_url.to_string(),
path: PATH.to_string(),
payload,
}
}
}
#[cfg(test)]
mod metrics_get_request {
mod presence_gateways_post_request {
use super::*;
#[cfg(test)]
use crate::client_test_fixture;
use mockito::mock;
#[cfg(test)]
mod on_a_400_status {
use super::*;
#[test]
fn it_returns_an_error() {
let _m = mock("POST", "/api/presence/gateways")
.with_status(400)
.create();
let req = Request::new(mockito::server_url());
#[tokio::test]
async fn it_returns_an_error() {
let _m = mock("POST", PATH).with_status(400).create();
let client = client_test_fixture(&mockito::server_url());
let presence = fixtures::new_presence();
let result = req.post(&presence);
let result = client.post_gateway_presence(presence).await;
assert_eq!(400, result.unwrap().status());
_m.assert();
}
@@ -68,19 +68,16 @@ mod metrics_get_request {
#[cfg(test)]
mod on_a_200 {
use super::*;
#[test]
fn it_returns_a_response_with_201() {
#[tokio::test]
async fn it_returns_a_response_with_201() {
let json = r#"{
"ok": true
}"#;
let _m = mock("POST", "/api/presence/gateways")
.with_status(201)
.with_body(json)
.create();
let req = Request::new(mockito::server_url());
let _m = mock("POST", PATH).with_status(201).with_body(json).create();
let client = client_test_fixture(&mockito::server_url());
let presence = fixtures::new_presence();
let result = req.post(&presence);
assert_eq!(true, result.is_ok());
let result = client.post_gateway_presence(presence).await;
assert!(result.is_ok());
_m.assert();
}
}
@@ -12,54 +12,54 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use super::{DirectoryPostRequest, DirectoryRequest};
use crate::presence::mixnodes::MixNodePresence;
use reqwest::Response;
const PATH: &str = "/api/presence/mixnodes";
pub struct Request {
base_url: String,
path: String,
payload: MixNodePresence,
}
pub trait PresenceMixNodesPoster {
fn new(base_url: String) -> Self;
fn post(&self, presence: &MixNodePresence) -> Result<Response, reqwest::Error>;
impl DirectoryRequest for Request {
fn url(&self) -> String {
format!("{}{}", self.base_url, self.path)
}
}
impl PresenceMixNodesPoster for Request {
fn new(base_url: String) -> Self {
Request {
base_url,
path: "/api/presence/mixnodes".to_string(),
}
impl DirectoryPostRequest for Request {
type Payload = MixNodePresence;
fn json_payload(&self) -> &MixNodePresence {
&self.payload
}
fn post(&self, presence: &MixNodePresence) -> Result<Response, reqwest::Error> {
let url = format!("{}{}", self.base_url, self.path);
let client = reqwest::Client::new();
let p = client.post(&url).json(&presence).send()?;
Ok(p)
fn new(base_url: &str, payload: Self::Payload) -> Self {
Request {
base_url: base_url.to_string(),
path: PATH.to_string(),
payload,
}
}
}
#[cfg(test)]
mod metrics_get_request {
mod presence_mixnodes_post_request {
use super::*;
#[cfg(test)]
use crate::client_test_fixture;
use mockito::mock;
#[cfg(test)]
mod on_a_400_status {
use super::*;
#[test]
fn it_returns_an_error() {
let _m = mock("POST", "/api/presence/mixnodes")
.with_status(400)
.create();
let req = Request::new(mockito::server_url());
#[tokio::test]
async fn it_returns_an_error() {
let _m = mock("POST", PATH).with_status(400).create();
let client = client_test_fixture(&mockito::server_url());
let presence = fixtures::new_presence();
let result = req.post(&presence);
let result = client.post_mixnode_presence(presence).await;
assert_eq!(400, result.unwrap().status());
_m.assert();
}
@@ -68,19 +68,16 @@ mod metrics_get_request {
#[cfg(test)]
mod on_a_200 {
use super::*;
#[test]
fn it_returns_a_response_with_201() {
#[tokio::test]
async fn it_returns_a_response_with_201() {
let json = r#"{
"ok": true
}"#;
let _m = mock("POST", "/api/presence/mixnodes")
.with_status(201)
.with_body(json)
.create();
let req = Request::new(mockito::server_url());
let _m = mock("POST", PATH).with_status(201).with_body(json).create();
let client = client_test_fixture(&mockito::server_url());
let presence = fixtures::new_presence();
let result = req.post(&presence);
assert_eq!(true, result.is_ok());
let result = client.post_mixnode_presence(presence).await;
assert!(result.is_ok());
_m.assert();
}
}
@@ -12,54 +12,54 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use super::{DirectoryPostRequest, DirectoryRequest};
use crate::presence::providers::MixProviderPresence;
use reqwest::Response;
const PATH: &str = "/api/presence/mixproviders";
pub struct Request {
base_url: String,
path: String,
payload: MixProviderPresence,
}
pub trait PresenceMixProviderPoster {
fn new(base_url: String) -> Self;
fn post(&self, presence: &MixProviderPresence) -> Result<Response, reqwest::Error>;
impl DirectoryRequest for Request {
fn url(&self) -> String {
format!("{}{}", self.base_url, self.path)
}
}
impl PresenceMixProviderPoster for Request {
fn new(base_url: String) -> Self {
Request {
base_url,
path: "/api/presence/mixproviders".to_string(),
}
impl DirectoryPostRequest for Request {
type Payload = MixProviderPresence;
fn json_payload(&self) -> &MixProviderPresence {
&self.payload
}
fn post(&self, presence: &MixProviderPresence) -> Result<Response, reqwest::Error> {
let url = format!("{}{}", self.base_url, self.path);
let client = reqwest::Client::new();
let p = client.post(&url).json(&presence).send()?;
Ok(p)
fn new(base_url: &str, payload: Self::Payload) -> Self {
Request {
base_url: base_url.to_string(),
path: PATH.to_string(),
payload,
}
}
}
#[cfg(test)]
mod metrics_get_request {
mod presence_providers_post_request {
use super::*;
#[cfg(test)]
use crate::client_test_fixture;
use mockito::mock;
#[cfg(test)]
mod on_a_400_status {
use super::*;
#[test]
fn it_returns_an_error() {
let _m = mock("POST", "/api/presence/mixproviders")
.with_status(400)
.create();
let req = Request::new(mockito::server_url());
#[tokio::test]
async fn it_returns_an_error() {
let _m = mock("POST", PATH).with_status(400).create();
let client = client_test_fixture(&mockito::server_url());
let presence = fixtures::new_presence();
let result = req.post(&presence);
let result = client.post_provider_presence(presence).await;
assert_eq!(400, result.unwrap().status());
_m.assert();
}
@@ -68,19 +68,16 @@ mod metrics_get_request {
#[cfg(test)]
mod on_a_200 {
use super::*;
#[test]
fn it_returns_a_response_with_201() {
#[tokio::test]
async fn it_returns_a_response_with_201() {
let json = r#"{
"ok": true
}"#;
let _m = mock("POST", "/api/presence/mixproviders")
.with_status(201)
.with_body(json)
.create();
let req = Request::new(mockito::server_url());
let _m = mock("POST", PATH).with_status(201).with_body(json).create();
let client = client_test_fixture(&mockito::server_url());
let presence = fixtures::new_presence();
let result = req.post(&presence);
assert_eq!(true, result.is_ok());
let result = client.post_provider_presence(presence).await;
assert!(result.is_ok());
_m.assert();
}
}
@@ -12,73 +12,71 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use super::{DirectoryGetRequest, DirectoryRequest};
use crate::presence::Topology;
const PATH: &str = "/api/presence/topology";
pub struct Request {
base_url: String,
path: String,
}
pub trait PresenceTopologyGetRequester {
fn new(base_url: String) -> Self;
fn get(&self) -> Result<Topology, reqwest::Error>;
impl DirectoryRequest for Request {
fn url(&self) -> String {
format!("{}{}", self.base_url, self.path)
}
}
impl PresenceTopologyGetRequester for Request {
fn new(base_url: String) -> Self {
Request {
base_url,
path: "/api/presence/topology".to_string(),
}
}
impl DirectoryGetRequest for Request {
type JSONResponse = Topology;
fn get(&self) -> Result<Topology, reqwest::Error> {
let url = format!("{}{}", self.base_url, self.path);
let topology: Topology = reqwest::get(&url)?.json()?;
Ok(topology)
fn new(base_url: &str) -> Self {
Request {
base_url: base_url.to_string(),
path: PATH.to_string(),
}
}
}
#[cfg(test)]
mod topology_requests {
use super::*;
#[cfg(test)]
use crate::client_test_fixture;
use mockito::mock;
#[cfg(test)]
mod on_a_400_status {
use super::*;
#[test]
#[should_panic]
fn it_panics() {
let _m = mock("GET", "/api/presence/topology")
#[tokio::test]
async fn it_returns_an_error() {
let _m = mock("GET", PATH)
.with_status(400)
.with_body("bad body")
.create();
let req = Request::new(mockito::server_url());
req.get().unwrap();
let client = client_test_fixture(&mockito::server_url());
let result = client.get_topology().await;
assert!(result.is_err());
_m.assert();
}
}
#[cfg(test)]
mod on_a_200 {
use super::*;
#[test]
fn it_returns_a_response_with_200_status_and_a_correct_topology() {
#[tokio::test]
async fn it_returns_a_response_with_200_status_and_a_correct_topology() {
let json = fixtures::topology_response_json();
let _m = mock("GET", "/api/presence/topology")
.with_status(200)
.with_body(json)
.create();
let req = Request::new(mockito::server_url());
let result = req.get();
assert!(result.is_ok());
let _m = mock("GET", PATH).with_status(200).with_body(json).create();
let client = client_test_fixture(&mockito::server_url());
let result = client.get_topology().await;
assert_eq!(
1575915097085539300,
1_575_915_097_085_539_300,
result.unwrap().coco_nodes.first().unwrap().last_seen
);
_m.assert();
}
}
#[cfg(test)]
pub mod fixtures {
#[cfg(test)]
+1
View File
@@ -9,6 +9,7 @@ edition = "2018"
[dependencies]
bs58 = "0.3.0"
itertools = "0.8.2"
futures = "0.3"
log = "0.4"
pretty_env_logger = "0.3"
rand = "0.7.2"
+5 -1
View File
@@ -13,6 +13,7 @@
// limitations under the License.
use crate::filter::VersionFilterable;
use futures::future::BoxFuture;
use itertools::Itertools;
use nymsphinx::Node as SphinxNode;
use rand::seq::IteratorRandom;
@@ -28,7 +29,10 @@ pub mod provider;
// TODO: Figure out why 'Clone' was required to have 'TopologyAccessor<T>' working
// even though it only contains an Arc
pub trait NymTopology: Sized + std::fmt::Debug + Send + Sync + Clone {
fn new(directory_server: String) -> Self;
// this is just a temporary work-around to make current code work without having to
// do major topology rewrites now.
// This will be removed once topology is re-worked
fn new<'a>(directory_server: String) -> BoxFuture<'a, Self>;
fn new_from_nodes(
mix_nodes: Vec<mix::Node>,
mix_provider_nodes: Vec<provider::Node>,
-35
View File
@@ -19,8 +19,6 @@ use crate::node::Gateway;
use clap::{App, Arg, ArgMatches};
use config::NymConfig;
use crypto::encryption;
use directory_client::requests::presence_topology_get::PresenceTopologyGetRequester;
use directory_client::DirectoryClient;
use pemstore::pemstore::PemStore;
pub fn command_args<'a, 'b>() -> clap::App<'a, 'b> {
@@ -140,27 +138,6 @@ fn load_sphinx_keys(config_file: &Config) -> encryption::KeyPair {
sphinx_keypair
}
fn check_if_same_ip_gateway_exists(
directory_server: String,
announced_mix_host: String,
announced_clients_host: String,
) -> Option<String> {
let directory_client_cfg = directory_client::Config::new(directory_server);
let topology = directory_client::Client::new(directory_client_cfg)
.presence_topology
.get()
.expect("Failed to retrieve network topology");
let existing_gateways = topology.gateway_nodes;
existing_gateways
.iter()
.find(|node| {
node.mixnet_listener == announced_mix_host
|| node.client_listener == announced_clients_host
})
.map(|node| node.pub_key.clone())
}
pub fn execute(matches: &ArgMatches) {
let id = matches.value_of("id").unwrap();
@@ -172,18 +149,6 @@ pub fn execute(matches: &ArgMatches) {
config = override_config(config, matches);
if let Some(duplicate_gateway_key) = check_if_same_ip_gateway_exists(
config.get_presence_directory_server(),
config.get_mix_announce_address(),
config.get_clients_announce_address(),
) {
println!(
"Our announce-host is identical to an existing node's announce-host! (its key is {:?}",
duplicate_gateway_key
);
return;
}
let sphinx_keypair = load_sphinx_keys(&config);
let mix_listening_ip_string = config.get_mix_listening_address().ip().to_string();
+32
View File
@@ -18,6 +18,7 @@ use crate::node::client_handling::websocket;
use crate::node::mixnet_handling::sender::{OutboundMixMessageSender, PacketForwarder};
use crate::node::storage::{inboxes, ClientLedger};
use crypto::encryption;
use directory_client::DirectoryClient;
use log::*;
use std::sync::Arc;
use tokio::runtime::Runtime;
@@ -137,6 +138,26 @@ impl Gateway {
);
}
async fn check_if_same_ip_gateway_exists(&self) -> Option<String> {
let announced_mix_host = self.config.get_mix_announce_address();
let announced_clients_host = self.config.get_clients_announce_address();
let directory_client_cfg =
directory_client::Config::new(self.config.get_presence_directory_server());
let topology = directory_client::Client::new(directory_client_cfg)
.get_topology()
.await
.expect("Failed to retrieve network topology");
let existing_gateways = topology.gateway_nodes;
existing_gateways
.iter()
.find(|node| {
node.mixnet_listener == announced_mix_host
|| node.client_listener == announced_clients_host
})
.map(|node| node.pub_key.clone())
}
// Rather than starting all futures with explicit `&Handle` argument, let's see how it works
// out if we make it implicit using `tokio::spawn` inside Runtime context.
// Basically more or less equivalent of using #[tokio::main] attribute.
@@ -145,6 +166,17 @@ impl Gateway {
let mut runtime = Runtime::new().unwrap();
runtime.block_on(async {
if let Some(duplicate_gateway_key) = self.check_if_same_ip_gateway_exists().await {
error!(
"Our announce-host is identical to an existing node's announce-host! (its key is {:?}",
duplicate_gateway_key
);
return;
}
let mix_forwarding_channel = self.start_packet_forwarder();
let clients_handler_sender = self.start_clients_handler();
+3 -4
View File
@@ -15,7 +15,6 @@
use crate::built_info;
use crate::node::storage::ClientLedger;
use directory_client::presence::gateways::{GatewayClient, GatewayPresence};
use directory_client::requests::presence_gateways_post::PresenceGatewayPoster;
use directory_client::DirectoryClient;
use log::{error, trace};
use std::time::Duration;
@@ -98,8 +97,8 @@ impl Notifier {
}
}
pub(crate) fn notify(&self, presence: GatewayPresence) {
match self.net_client.presence_gateway_post.post(&presence) {
async fn notify(&self, presence: GatewayPresence) {
match self.net_client.post_gateway_presence(presence).await {
Err(err) => error!("failed to send presence - {:?}", err),
Ok(_) => trace!("sent presence information"),
}
@@ -111,7 +110,7 @@ impl Notifier {
// set the deadline in the future
let sending_delay = tokio::time::delay_for(self.sending_delay);
let presence = self.make_presence().await;
self.notify(presence);
self.notify(presence).await;
// wait for however much is left
sending_delay.await;
}
+9 -6
View File
@@ -13,7 +13,6 @@
// limitations under the License.
use directory_client::metrics::MixMetric;
use directory_client::requests::metrics_mixes_post::MetricsMixPoster;
use directory_client::DirectoryClient;
use futures::channel::mpsc;
use futures::lock::Mutex;
@@ -141,11 +140,15 @@ impl MetricsSender {
self.metrics_informer.log_report_stats(received, &sent);
self.metrics_informer.try_log_running_stats();
match self.directory_client.metrics_post.post(&MixMetric {
pub_key: self.pub_key_str.clone(),
received,
sent,
}) {
match self
.directory_client
.post_mix_metrics(MixMetric {
pub_key: self.pub_key_str.clone(),
received,
sent,
})
.await
{
Err(err) => error!("failed to send metrics - {:?}", err),
Ok(_) => debug!("sent metrics information"),
}
+4 -2
View File
@@ -100,9 +100,11 @@ impl MixNode {
.start(self.runtime.handle())
}
fn check_if_same_ip_node_exists(&self) -> Option<String> {
fn check_if_same_ip_node_exists(&mut self) -> Option<String> {
// TODO: once we change to graph topology this here will need to be updated!
let topology = Topology::new(self.config.get_presence_directory_server());
let topology = self
.runtime
.block_on(Topology::new(self.config.get_presence_directory_server()));
let existing_mixes_presence = topology.mix_nodes;
existing_mixes_presence
.iter()
+7 -4
View File
@@ -14,7 +14,6 @@
use crate::built_info;
use directory_client::presence::mixnodes::MixNodePresence;
use directory_client::requests::presence_mixnodes_post::PresenceMixNodesPoster;
use directory_client::DirectoryClient;
use log::{error, trace};
use std::time::Duration;
@@ -77,8 +76,12 @@ impl Notifier {
}
}
fn notify(&self) {
match self.net_client.presence_mix_nodes_post.post(&self.presence) {
async fn notify(&self) {
match self
.net_client
.post_mixnode_presence(self.presence.clone())
.await
{
Err(err) => error!("failed to send presence - {:?}", err),
Ok(_) => trace!("sent presence information"),
}
@@ -89,7 +92,7 @@ impl Notifier {
loop {
// set the deadline in the future
let sending_delay = tokio::time::delay_for(self.sending_delay);
self.notify();
self.notify().await;
// wait for however much is left
sending_delay.await;
}