Requests for messages

This commit is contained in:
Jedrzej Stuczynski
2019-12-11 15:17:47 +00:00
parent 16d5ca40e2
commit 456494f05f
2 changed files with 186 additions and 22 deletions
+160
View File
@@ -0,0 +1,160 @@
use sphinx::route::Node as MixNode;
use sphinx::SphinxPacket;
use tokio::prelude::*;
const PULL_REQUEST_MESSAGE_PREFIX: [u8; 2] = [1, 0];
const REGISTER_MESSAGE_PREFIX: [u8; 2] = [0, 1];
// TODO: how to do it more nicely, considering all requests implement same trait that is exercised here?
pub enum ProviderRequests {
PullMessages(PullRequest),
Register(RegisterRequest),
}
impl ProviderRequests {
fn to_bytes(&self) -> Vec<u8> {
use ProviderRequests::*;
match self {
PullMessages(pr) => pr.to_bytes(),
Register(pr) => pr.to_bytes(),
}
}
fn from_bytes(bytes: &[u8]) -> Result<Self, ProviderRequestError> {
use ProviderRequests::*;
if bytes.len() < 2 {
return Err(ProviderRequestError::UnmarshalError);
}
let mut received_prefix = [0; 2];
received_prefix.copy_from_slice(&bytes[..2]);
match received_prefix {
PULL_REQUEST_MESSAGE_PREFIX => Ok(PullMessages(PullRequest::from_bytes(bytes)?)),
REGISTER_MESSAGE_PREFIX => Ok(Register(RegisterRequest::from_bytes(bytes)?)),
_ => Err(ProviderRequestError::UnmarshalErrorIncorrectPrefix),
}
}
}
#[derive(Debug)]
pub enum ProviderRequestError {
MarshalError,
UnmarshalError,
UnmarshalErrorIncorrectPrefix,
}
pub trait ProviderRequest where Self: Sized {
fn get_prefix() -> [u8; 2];
fn to_bytes(&self) -> Vec<u8>;
fn from_bytes(bytes: &[u8]) -> Result<Self, ProviderRequestError>;
}
pub struct PullRequest {
// TODO: public keys, signatures, tokens, etc. basically some kind of authentication bs
destination_address: sphinx::route::DestinationAddressBytes,
}
impl PullRequest {
pub(crate) fn new(destination_address: sphinx::route::DestinationAddressBytes) -> Self {
PullRequest {
destination_address
}
}
}
impl ProviderRequest for PullRequest {
fn get_prefix() -> [u8; 2] {
PULL_REQUEST_MESSAGE_PREFIX
}
fn to_bytes(&self) -> Vec<u8> {
Self::get_prefix().to_vec().into_iter().chain(self.destination_address.iter().cloned()).collect()
}
fn from_bytes(bytes: &[u8]) -> Result<Self, ProviderRequestError> {
if bytes.len() != 2 + 32 {
return Err(ProviderRequestError::UnmarshalError);
}
let mut received_prefix = [0u8; 2];
received_prefix.copy_from_slice(&bytes[..2]);
if received_prefix != Self::get_prefix() {
return Err(ProviderRequestError::UnmarshalErrorIncorrectPrefix);
}
let mut destination_address = [0u8; 32];
destination_address.copy_from_slice(&bytes[2..]);
Ok(PullRequest {
destination_address,
})
}
}
pub struct RegisterRequest {}
impl ProviderRequest for RegisterRequest {
fn get_prefix() -> [u8; 2] {
unimplemented!()
}
fn to_bytes(&self) -> Vec<u8> {
unimplemented!()
}
fn from_bytes(bytes: &[u8]) -> Result<Self, ProviderRequestError> {
unimplemented!()
}
}
pub struct ProviderClient {}
impl ProviderClient {
pub fn new() -> Self {
ProviderClient {}
}
pub async fn send(
&self,
// provider: &MixNode,
) -> Result<(), Box<dyn std::error::Error>> {
let address = [0; 32];
let pull_request = PullRequest::new(address);
let bytes = pull_request.to_bytes();
let mut stream = tokio::net::TcpStream::connect("127.0.0.1:9000").await?;
stream.write_all(&bytes[..]).await?;
Ok(())
}
}
#[cfg(test)]
mod creating_pull_request {
use super::*;
#[test]
fn it_is_possible_to_recover_it_from_bytes() {
let address = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2];
let pull_request = PullRequest::new(address);
let bytes = pull_request.to_bytes();
let recovered = PullRequest::from_bytes(&bytes).unwrap();
assert_eq!(address, recovered.destination_address);
}
#[test]
fn it_is_possible_to_recover_it_from_bytes_with_enum_wrapper() {
let address = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2];
let pull_request = PullRequest::new(address);
let bytes = pull_request.to_bytes();
let recovered = ProviderRequests::from_bytes(&bytes).unwrap();
match recovered {
ProviderRequests::PullMessages(req) => assert_eq!(address, req.destination_address),
_ => panic!("expected to recover pull request!"),
}
}
}
+26 -22
View File
@@ -8,6 +8,7 @@ use sphinx::route::Destination;
use std::time::Duration;
use tokio::runtime::Runtime;
use tokio::time::{interval_at, Instant};
use crate::clients::provider::ProviderClient;
pub fn execute(matches: &ArgMatches) {
let custom_cfg = matches.value_of("customCfg");
@@ -26,30 +27,33 @@ pub fn execute(matches: &ArgMatches) {
let mut i: usize = 0;
loop {
interval.tick().await;
let message = format!("Hello, Sphinx {}", i).as_bytes().to_vec();
// set up the route
let directory_config = directory::Config {
base_url: "https://directory.nymtech.net".to_string(),
};
let directory = directory::Client::new(directory_config);
let topology = directory
.presence_topology
.get()
.expect("Failed to retrieve network topology.");
let route = topology.mix_nodes;
let destination = get_destination();
let delays = sphinx::header::delays::generate(2);
// 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;
// let message = format!("Hello, Sphinx {}", i).as_bytes().to_vec();
//
// // set up the route
// let directory_config = directory::Config {
// base_url: "https://directory.nymtech.net".to_string(),
// };
// let directory = directory::Client::new(directory_config);
//
// let topology = directory
// .presence_topology
// .get()
// .expect("Failed to retrieve network topology.");
// let route = topology.mix_nodes;
// let destination = get_destination();
// let delays = sphinx::header::delays::generate(2);
//
// // 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;
let provider_client = ProviderClient::new();
provider_client.send().await.unwrap();
}
})
}