Merge branch 'develop' into feature/new_websocket_implementation
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Deserialize, Serialize, Clone)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CocoPresence {
|
||||
pub host: String,
|
||||
@@ -8,7 +8,7 @@ pub struct CocoPresence {
|
||||
pub last_seen: i64,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Clone)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct MixNodePresence {
|
||||
pub host: String,
|
||||
@@ -17,7 +17,7 @@ pub struct MixNodePresence {
|
||||
pub last_seen: u64,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Clone)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct MixProviderPresence {
|
||||
pub host: String,
|
||||
@@ -25,14 +25,14 @@ pub struct MixProviderPresence {
|
||||
pub registered_clients: Vec<MixProviderClient>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Clone)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct MixProviderClient {
|
||||
pub pub_key: String,
|
||||
}
|
||||
|
||||
// Topology shows us the current state of the overall Nym network
|
||||
#[derive(Deserialize, Serialize, Clone)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Topology {
|
||||
pub coco_nodes: Vec<CocoPresence>,
|
||||
|
||||
+1
-2
@@ -1,6 +1,5 @@
|
||||
use sphinx::route::{Node as MixNode, NodeAddressBytes};
|
||||
use sphinx::route::NodeAddressBytes;
|
||||
use sphinx::SphinxPacket;
|
||||
use std::net::SocketAddr;
|
||||
use std::net::{Ipv4Addr, SocketAddrV4};
|
||||
use tokio::prelude::*;
|
||||
|
||||
|
||||
+36
-12
@@ -1,17 +1,19 @@
|
||||
use crate::clients::directory::presence::Topology;
|
||||
use crate::clients::mix::MixClient;
|
||||
use crate::clients::provider::ProviderClient;
|
||||
use crate::sockets::ws;
|
||||
use crate::utils;
|
||||
use crate::utils::topology::get_topology;
|
||||
use futures::channel::mpsc;
|
||||
use futures::future::join5;
|
||||
use futures::select;
|
||||
use futures::{SinkExt, StreamExt};
|
||||
use sphinx::route::{Destination, DestinationAddressBytes, NodeAddressBytes};
|
||||
use sphinx::SphinxPacket;
|
||||
use std::net::SocketAddr;
|
||||
use std::net::SocketAddrV4;
|
||||
use std::time::Duration;
|
||||
use tokio::runtime::Runtime;
|
||||
use futures::future::join5;
|
||||
use crate::sockets::ws;
|
||||
use std::net::SocketAddr;
|
||||
|
||||
pub mod directory;
|
||||
pub mod mix;
|
||||
@@ -93,7 +95,8 @@ impl NymClient {
|
||||
let cover_message =
|
||||
utils::sphinx::loop_cover_message(our_info.address, our_info.identifier, &topology);
|
||||
tx.send(MixMessage(cover_message.0, cover_message.1))
|
||||
.await.unwrap();
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,20 +122,24 @@ impl NymClient {
|
||||
let cover_message = utils::sphinx::loop_cover_message(our_info.address, our_info.identifier, &topology);
|
||||
mix_tx.send(MixMessage(cover_message.0, cover_message.1)).await.unwrap();
|
||||
}
|
||||
}
|
||||
;
|
||||
};
|
||||
|
||||
let delay_duration = Duration::from_secs_f64(MESSAGE_SENDING_AVERAGE_DELAY);
|
||||
tokio::time::delay_for(delay_duration).await;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: proper return type
|
||||
async fn start_provider_polling() {
|
||||
async fn start_provider_polling(provider_address: SocketAddrV4) {
|
||||
let provider_client = ProviderClient::new();
|
||||
|
||||
loop {
|
||||
println!("[FETCH MSG] - Polling provider...");
|
||||
let delay_duration = Duration::from_secs_f64(FETCH_MESSAGES_DELAY);
|
||||
tokio::time::delay_for(delay_duration).await;
|
||||
provider_client
|
||||
.retrieve_messages(provider_address)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,8 +148,14 @@ impl NymClient {
|
||||
|
||||
let (mix_tx, mix_rx) = mpsc::unbounded();
|
||||
let mut rt = Runtime::new()?;
|
||||
|
||||
let topology = get_topology(self.is_local);
|
||||
let provider_address: SocketAddrV4 = topology
|
||||
.mix_provider_nodes
|
||||
.first()
|
||||
.unwrap()
|
||||
.host
|
||||
.parse()
|
||||
.unwrap();
|
||||
|
||||
let mix_traffic_future = rt.spawn(MixTrafficController::run(mix_rx));
|
||||
let loop_cover_traffic_future = rt.spawn(NymClient::start_loop_cover_traffic_stream(
|
||||
@@ -158,13 +171,24 @@ impl NymClient {
|
||||
topology.clone(),
|
||||
));
|
||||
|
||||
let provider_polling_future = rt.spawn(NymClient::start_provider_polling());
|
||||
let provider_polling_future = rt.spawn(NymClient::start_provider_polling(provider_address));
|
||||
let websocket_future = rt.spawn(ws::start_websocket(socket_address, self.input_tx));
|
||||
|
||||
rt.block_on(async {
|
||||
let future_results = join5(mix_traffic_future, loop_cover_traffic_future, out_queue_control_future, provider_polling_future, websocket_future).await;
|
||||
let future_results = join5(
|
||||
mix_traffic_future,
|
||||
loop_cover_traffic_future,
|
||||
out_queue_control_future,
|
||||
provider_polling_future,
|
||||
websocket_future,
|
||||
)
|
||||
.await;
|
||||
assert!(
|
||||
future_results.0.is_ok() && future_results.1.is_ok() && future_results.2.is_ok() && future_results.3.is_ok() && future_results.4.is_ok()
|
||||
future_results.0.is_ok()
|
||||
&& future_results.1.is_ok()
|
||||
&& future_results.2.is_ok()
|
||||
&& future_results.3.is_ok()
|
||||
&& future_results.4.is_ok()
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use sfw_provider_requests::requests::{ProviderRequest, PullRequest};
|
||||
use sfw_provider_requests::responses::{ProviderResponse, PullResponse};
|
||||
use std::net::Shutdown;
|
||||
use std::net::SocketAddrV4;
|
||||
use tokio::prelude::*;
|
||||
use tokio::time::Duration;
|
||||
|
||||
@@ -13,13 +14,19 @@ impl ProviderClient {
|
||||
|
||||
pub async fn retrieve_messages(
|
||||
&self,
|
||||
// provider: &MixNode,
|
||||
provider: SocketAddrV4,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let address = [42; 32];
|
||||
let pull_request = PullRequest::new(address);
|
||||
let bytes = pull_request.to_bytes();
|
||||
|
||||
let mut socket = tokio::net::TcpStream::connect("127.0.0.1:9000").await?;
|
||||
// DH temporary: the provider's client port is not in the topology, but we can't change that
|
||||
// right now without messing up the existing Go mixnet. So I'm going to hardcode this
|
||||
// for the moment until the Go mixnet goes away.
|
||||
let provider_socket = SocketAddrV4::new(*provider.ip(), 9000);
|
||||
println!("Provider: {:?}", provider_socket);
|
||||
|
||||
let mut socket = tokio::net::TcpStream::connect(provider_socket).await?;
|
||||
println!("keep alive: {:?}", socket.keepalive());
|
||||
socket.set_keepalive(Some(Duration::from_secs(2))).unwrap();
|
||||
socket.write_all(&bytes[..]).await?;
|
||||
|
||||
+9
-116
@@ -1,123 +1,16 @@
|
||||
use crate::clients::directory;
|
||||
use crate::clients::directory::presence::Topology;
|
||||
use crate::clients::directory::requests::presence_topology_get::PresenceTopologyGetRequester;
|
||||
use crate::clients::directory::DirectoryClient;
|
||||
use crate::clients::mix::MixClient;
|
||||
use crate::clients::provider::ProviderClient;
|
||||
use crate::banner;
|
||||
use crate::clients::NymClient;
|
||||
use crate::utils::bytes;
|
||||
use base64;
|
||||
use crate::persistence::pemstore;
|
||||
use clap::ArgMatches;
|
||||
use curve25519_dalek::montgomery::MontgomeryPoint;
|
||||
use sphinx::route::Destination;
|
||||
use sphinx::route::Node as SphinxNode;
|
||||
use std::net::SocketAddrV4;
|
||||
use std::time::Duration;
|
||||
use tokio::runtime::Runtime;
|
||||
use tokio::time::{interval_at, Instant};
|
||||
|
||||
pub fn execute(matches: &ArgMatches) {
|
||||
unimplemented!() // currently the 'run' starts websocket!
|
||||
println!("{}", banner());
|
||||
|
||||
// let is_local = matches.is_present("local");
|
||||
// println!("Starting client, local: {:?}", is_local);
|
||||
//
|
||||
// // todo: to be taken from config or something
|
||||
// let my_address = [42u8; 32];
|
||||
// let is_local = true;
|
||||
// let client = NymClient::new(my_address, is_local);
|
||||
// client.start().unwrap();
|
||||
// Grab the network topology from the remote directory server
|
||||
// let topology = get_topology(is_local);
|
||||
let is_local = matches.is_present("local");
|
||||
let id = matches.value_of("id").unwrap().to_string();
|
||||
println!("Starting client...");
|
||||
|
||||
// // Grab the network topology from the remote directory server
|
||||
// let topology = get_topology();
|
||||
//
|
||||
// // Create the runtime, probably later move it to Client struct itself?
|
||||
// let mut rt = Runtime::new().unwrap();
|
||||
//
|
||||
// // Spawn the root task
|
||||
// rt.block_on(async {
|
||||
// let start = Instant::now() + Duration::from_nanos(1000);
|
||||
// let mut interval = interval_at(start, Duration::from_millis(1000));
|
||||
// let mut i: usize = 0;
|
||||
// loop {
|
||||
// interval.tick().await;
|
||||
//// let message = format!("Hello, Sphinx {}", i).as_bytes().to_vec();
|
||||
////
|
||||
//// let route_len = 2;
|
||||
////
|
||||
//// // data needed to generate a new Sphinx packet
|
||||
//// let route = route_from(&topology, route_len);
|
||||
//// let destination = get_destination();
|
||||
//// let delays = sphinx::header::delays::generate(route_len);
|
||||
////
|
||||
//// // build the packet
|
||||
//// let packet =
|
||||
//// sphinx::SphinxPacket::new(message, &route[..], &destination, &delays).unwrap();
|
||||
////
|
||||
//// // send to mixnet
|
||||
//// let mix_client = MixClient::new();
|
||||
//// let result = mix_client.send(packet, route.first().unwrap()).await;
|
||||
//// println!("packet sent: {:?}", i);
|
||||
// i += 1;
|
||||
//
|
||||
// // retrieve messages every now and then
|
||||
// if i % 3 == 0 {
|
||||
// interval.tick().await;
|
||||
// println!("going to retrieve messages!");
|
||||
// let provider_client = ProviderClient::new();
|
||||
// provider_client.retrieve_messages().await.unwrap();
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
// // Create the runtime, probably later move it to Client struct itself?
|
||||
// let mut rt = Runtime::new().unwrap();
|
||||
//
|
||||
// // Spawn the root task
|
||||
// rt.block_on(async {
|
||||
// let start = Instant::now() + Duration::from_nanos(1000);
|
||||
// let mut interval = interval_at(start, Duration::from_millis(1000));
|
||||
// let mut i: usize = 0;
|
||||
// loop {
|
||||
// interval.tick().await;
|
||||
// let message = format!("Hello, Sphinx {}", i).as_bytes().to_vec();
|
||||
//
|
||||
// let route_len = 2;
|
||||
//
|
||||
// // data needed to generate a new Sphinx packet
|
||||
// let route = route_from(&topology, route_len);
|
||||
// let destination = get_destination();
|
||||
// let delays = sphinx::header::delays::generate(route_len);
|
||||
//
|
||||
// // build the packet
|
||||
// let packet =
|
||||
// sphinx::SphinxPacket::new(message, &route[..], &destination, &delays).unwrap();
|
||||
//
|
||||
// // send to mixnet
|
||||
// let mix_client = MixClient::new();
|
||||
// mix_client
|
||||
// .send(packet, route.first().unwrap())
|
||||
// .await
|
||||
// .unwrap();
|
||||
// println!("packet sent: {:?}", i);
|
||||
// i += 1;
|
||||
//
|
||||
// // retrieve messages every now and then
|
||||
// if i % 3 == 0 {
|
||||
// interval.tick().await;
|
||||
// println!("going to retrieve messages!");
|
||||
// let provider_client = ProviderClient::new();
|
||||
// provider_client.retrieve_messages().await.unwrap();
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
}
|
||||
|
||||
// TODO: where do we retrieve this guy from?
|
||||
fn get_destination() -> Destination {
|
||||
Destination {
|
||||
address: [42u8; 32],
|
||||
identifier: [1u8; 16],
|
||||
}
|
||||
let keypair = pemstore::read_keypair_from_disk(id);
|
||||
let client = NymClient::new(keypair.public_bytes(), is_local);
|
||||
client.start().unwrap();
|
||||
}
|
||||
|
||||
@@ -1,10 +1,33 @@
|
||||
use crate::banner;
|
||||
use crate::clients::NymClient;
|
||||
use crate::persistence::pemstore;
|
||||
use crate::sockets::tcp;
|
||||
|
||||
use clap::ArgMatches;
|
||||
use std::net::ToSocketAddrs;
|
||||
|
||||
pub fn execute(matches: &ArgMatches) {
|
||||
let port = match matches.value_of("port").unwrap().parse::<u16>() {
|
||||
println!("{}", banner());
|
||||
|
||||
let is_local = matches.is_present("local");
|
||||
let id = matches.value_of("id").unwrap().to_string();
|
||||
let port = match matches.value_of("port").unwrap_or("9001").parse::<u16>() {
|
||||
Ok(n) => n,
|
||||
Err(err) => panic!("Invalid port value provided - {:?}", err),
|
||||
};
|
||||
|
||||
println!("On the following port: {:?}", port);
|
||||
println!("Starting TCP socket on port: {:?}", port);
|
||||
println!("Listening for messages...");
|
||||
|
||||
let socket_address = ("127.0.0.1", port)
|
||||
.to_socket_addrs()
|
||||
.expect("Failed to combine host and port")
|
||||
.next()
|
||||
.expect("Failed to extract the socket address from the iterator");
|
||||
|
||||
let keypair = pemstore::read_keypair_from_disk(id);
|
||||
let _client = NymClient::new(keypair.public_bytes(), is_local);
|
||||
// Question: should we be passing the client into the TCP socket somehow next?
|
||||
|
||||
tcp::start(socket_address);
|
||||
}
|
||||
|
||||
@@ -1,15 +1,21 @@
|
||||
use crate::banner;
|
||||
use crate::clients::NymClient;
|
||||
use crate::persistence::pemstore;
|
||||
use crate::sockets::ws;
|
||||
|
||||
use clap::ArgMatches;
|
||||
use std::net::ToSocketAddrs;
|
||||
|
||||
pub fn execute(matches: &ArgMatches) {
|
||||
let port = match matches.value_of("port").unwrap().parse::<u16>() {
|
||||
println!("{}", banner());
|
||||
|
||||
let is_local = matches.is_present("local");
|
||||
let id = matches.value_of("id").unwrap().to_string();
|
||||
let port = match matches.value_of("port").unwrap_or("9001").parse::<u16>() {
|
||||
Ok(n) => n,
|
||||
Err(err) => panic!("Invalid port value provided - {:?}", err),
|
||||
};
|
||||
|
||||
println!("{}", banner());
|
||||
println!("Starting websocket on port: {:?}", port);
|
||||
println!("Listening for messages...");
|
||||
|
||||
@@ -19,13 +25,12 @@ pub fn execute(matches: &ArgMatches) {
|
||||
.next()
|
||||
.expect("Failed to extract the socket address from the iterator");
|
||||
|
||||
|
||||
let is_local = matches.is_present("local");
|
||||
println!("Starting client, local: {:?}", is_local);
|
||||
|
||||
// todo: to be taken from config or something
|
||||
let my_address = [42u8; 32];
|
||||
let is_local = true;
|
||||
let client = NymClient::new(my_address, is_local);
|
||||
let keypair = pemstore::read_keypair_from_disk(id);
|
||||
let client = NymClient::new(keypair.public_bytes(), is_local);
|
||||
|
||||
client.start(socket_address).unwrap();
|
||||
}
|
||||
|
||||
|
||||
@@ -23,11 +23,11 @@ impl KeyPair {
|
||||
KeyPair { private, public }
|
||||
}
|
||||
|
||||
pub fn private_bytes(&self) -> Vec<u8> {
|
||||
self.private.to_bytes().to_vec()
|
||||
pub fn private_bytes(&self) -> [u8; 32] {
|
||||
self.private.to_bytes()
|
||||
}
|
||||
|
||||
pub fn public_bytes(&self) -> Vec<u8> {
|
||||
self.public.to_bytes().to_vec()
|
||||
pub fn public_bytes(&self) -> [u8; 32] {
|
||||
self.public.to_bytes()
|
||||
}
|
||||
}
|
||||
|
||||
+24
-2
@@ -31,6 +31,12 @@ fn main() {
|
||||
.subcommand(
|
||||
SubCommand::with_name("run")
|
||||
.about("Run a persistent Nym client process")
|
||||
.arg(Arg::with_name("id")
|
||||
.long("id")
|
||||
.help("Id of the nym-mixnet-client we want to run.")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
)
|
||||
.arg(Arg::with_name("local")
|
||||
.long("local")
|
||||
.help("Flag to indicate whether the client is expected to run on the local deployment.")
|
||||
@@ -44,9 +50,19 @@ fn main() {
|
||||
Arg::with_name("port")
|
||||
.short("p")
|
||||
.long("port")
|
||||
.help("Port to listen on")
|
||||
.help("Port for TCP socket to listen on")
|
||||
.takes_value(true)
|
||||
.required(true),
|
||||
).arg(Arg::with_name("local")
|
||||
.long("local")
|
||||
.help("Flag to indicate whether the client is expected to run on the local deployment.")
|
||||
.takes_value(false)
|
||||
)
|
||||
.arg(Arg::with_name("id")
|
||||
.long("id")
|
||||
.help("Id of the nym-mixnet-client we want to run.")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
)
|
||||
.arg(Arg::with_name("local")
|
||||
.long("local")
|
||||
@@ -61,7 +77,7 @@ fn main() {
|
||||
Arg::with_name("port")
|
||||
.short("p")
|
||||
.long("port")
|
||||
.help("Port to listen on")
|
||||
.help("Port for websocket to listen on")
|
||||
.takes_value(true)
|
||||
.required(true),
|
||||
)
|
||||
@@ -70,6 +86,12 @@ fn main() {
|
||||
.help("Flag to indicate whether the client is expected to run on the local deployment.")
|
||||
.takes_value(false)
|
||||
)
|
||||
.arg(Arg::with_name("id")
|
||||
.long("id")
|
||||
.help("Id of the nym-mixnet-client we want to run.")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
)
|
||||
)
|
||||
.get_matches();
|
||||
|
||||
|
||||
@@ -5,6 +5,13 @@ use std::fs::File;
|
||||
use std::io::prelude::*;
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub fn read_keypair_from_disk(id: String) -> KeyPair {
|
||||
let pathfinder = Pathfinder::new(id);
|
||||
let pem_store = PemStore::new(pathfinder);
|
||||
let keypair = pem_store.read();
|
||||
keypair
|
||||
}
|
||||
|
||||
pub struct PemStore {
|
||||
config_dir: PathBuf,
|
||||
private_mix_key: PathBuf,
|
||||
@@ -52,10 +59,10 @@ impl PemStore {
|
||||
);
|
||||
}
|
||||
|
||||
fn write_pem_file(&self, filepath: PathBuf, data: Vec<u8>, tag: String) {
|
||||
fn write_pem_file(&self, filepath: PathBuf, data: [u8; 32], tag: String) {
|
||||
let pem = Pem {
|
||||
tag,
|
||||
contents: data,
|
||||
contents: data.to_vec(),
|
||||
};
|
||||
let key = encode(&pem);
|
||||
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
pub mod tcp;
|
||||
pub mod ws;
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
use std::net::SocketAddr;
|
||||
|
||||
pub fn start(_socket_address: SocketAddr) {
|
||||
println!("TCP server time!!!");
|
||||
}
|
||||
|
||||
+8
-2
@@ -1,5 +1,6 @@
|
||||
use crate::clients::directory::presence::Topology;
|
||||
use crate::utils::{bytes, topology};
|
||||
use curve25519_dalek::montgomery::MontgomeryPoint;
|
||||
use sphinx::route::{Destination, DestinationAddressBytes, Node, NodeAddressBytes, SURBIdentifier};
|
||||
use sphinx::SphinxPacket;
|
||||
|
||||
@@ -21,10 +22,15 @@ pub fn encapsulate_message(
|
||||
topology: &Topology,
|
||||
) -> (NodeAddressBytes, SphinxPacket) {
|
||||
let mixes_route = topology::route_from(&topology, 1);
|
||||
let first_provider = topology.mix_provider_nodes.first().unwrap();
|
||||
let decoded_key_bytes =
|
||||
base64::decode_config(&first_provider.pub_key, base64::URL_SAFE).unwrap();
|
||||
let key_bytes = bytes::zero_pad_to_32(decoded_key_bytes);
|
||||
let key = MontgomeryPoint(key_bytes);
|
||||
|
||||
let provider = Node::new(
|
||||
topology::socket_bytes_from_string("127.0.0.1:8081".to_string()),
|
||||
Default::default(),
|
||||
topology::socket_bytes_from_string(first_provider.host.clone()),
|
||||
key,
|
||||
);
|
||||
|
||||
let route = [mixes_route, vec![provider]].concat();
|
||||
|
||||
@@ -2,8 +2,6 @@ use crate::clients::directory;
|
||||
use crate::clients::directory::presence::Topology;
|
||||
use crate::clients::directory::requests::presence_topology_get::PresenceTopologyGetRequester;
|
||||
use crate::clients::directory::DirectoryClient;
|
||||
use crate::clients::mix::MixClient;
|
||||
use crate::clients::provider::ProviderClient;
|
||||
use crate::utils::bytes;
|
||||
use curve25519_dalek::montgomery::MontgomeryPoint;
|
||||
use sphinx::route::Node as SphinxNode;
|
||||
|
||||
Reference in New Issue
Block a user