Moved store related functionalities to separate module

This commit is contained in:
Jedrzej Stuczynski
2019-12-12 14:40:10 +00:00
parent 2850c71317
commit 35cff8dfcd
4 changed files with 133 additions and 84 deletions
View File
View File
+17 -84
View File
@@ -13,6 +13,12 @@ use sphinx::route::{DestinationAddressBytes, SURBIdentifier};
use tokio::prelude::*;
use tokio::runtime::Runtime;
use sfw_provider_requests::DUMMY_MESSAGE_CONTENT;
use crate::provider::storage::{StoreData, ClientStorage, StoreError};
mod client_handling;
mod mix_handling;
mod storage;
// TODO: if we ever create config file, this should go there
const STORED_MESSAGE_FILENAME_LENGTH: usize = 16;
@@ -66,13 +72,6 @@ impl MixProcessingData {
}
}
struct StoreData {
client_address: DestinationAddressBytes,
client_surb_id: SURBIdentifier,
message: Vec<u8>,
}
struct MixPacketProcessor(());
impl MixPacketProcessor {
@@ -91,94 +90,21 @@ impl MixPacketProcessor {
return Err(MixProcessingError::NonMatchingRecipient);
}
Ok(StoreData {
Ok(StoreData::new(
client_address,
client_surb_id,
message,
})
))
}
}
struct ClientStorage(());
impl ClientStorage {
fn generate_random_file_name() -> String {
rand::thread_rng().sample_iter(&rand::distributions::Alphanumeric).take(STORED_MESSAGE_FILENAME_LENGTH).collect::<String>()
}
fn dummy_message() -> Vec<u8> {
// TODO: should it be padded to constant length?
DUMMY_MESSAGE_CONTENT.to_vec()
}
fn store_processed_data(store_data: StoreData, store_dir: &Path) -> io::Result<()> {
let client_dir_name = hex::encode(store_data.client_address);
let full_store_dir = store_dir.join(client_dir_name);
let full_store_path = full_store_dir.join(ClientStorage::generate_random_file_name());
println!("going to store: {:?} in file: {:?}", store_data.message, full_store_path);
// TODO: what to do with surbIDs??
// TODO: this should be called when client sends 'register' request!
std::fs::create_dir_all(full_store_dir)?;
// we can use normal io here, no need for tokio as it's all happening in one thread per connection
let mut file = File::create(full_store_path)?;
file.write_all(store_data.message.as_ref())?;
Ok(())
}
fn retrieve_client_files(client_address: DestinationAddressBytes, store_dir: &Path) -> Result<Vec<Vec<u8>>, ClientProcessingError> {
let client_dir_name = hex::encode(client_address);
let full_store_dir = store_dir.join(client_dir_name);
println!("going to lookup: {:?}!", full_store_dir);
if !full_store_dir.exists() {
return Err(ClientProcessingError::ClientDoesntExistError)
}
let msgs: Vec<_> = std::fs::read_dir(full_store_dir)?
.map(|entry| entry.unwrap())
.filter(|entry| {
let is_file = entry.metadata().unwrap().is_file();
if !is_file {
eprintln!("potentially corrupted client inbox! - found a non-file - {:?}", entry.path());
}
is_file
})
.map(|entry| std::fs::read(entry.path()).unwrap()) // TODO: also delete; THIS MAP IS UNSAFE!!
.chain(std::iter::repeat(ClientStorage::dummy_message()))
.take(MESSAGE_RETRIEVAL_LIMIT)
.collect();
println!("retrieved the following data: {:?}", msgs);
Ok(msgs)
}
// TODO: THIS NEEDS A LOCKING MECHANISM!!! (or a db layer on top - basically 'ClientStorage' on steroids)
fn delete_file() {
}
}
#[derive(Debug)]
enum ClientProcessingError {
ClientDoesntExistError,
FileIOFailure,
InvalidRequest
}
impl From<std::io::Error> for ClientProcessingError {
fn from(_: std::io::Error) -> Self {
use ClientProcessingError::*;
FileIOFailure
}
StoreError,
InvalidRequest,
}
impl From<ProviderRequestError> for ClientProcessingError {
@@ -189,6 +115,13 @@ impl From<ProviderRequestError> for ClientProcessingError {
}
}
impl From<StoreError> for ClientProcessingError {
fn from(_: StoreError) -> Self {
use ClientProcessingError::*;
StoreError
}
}
#[derive(Debug, Clone)]
struct ClientProcessingData {
+116
View File
@@ -0,0 +1,116 @@
use crate::provider::{MESSAGE_RETRIEVAL_LIMIT, STORED_MESSAGE_FILENAME_LENGTH};
use rand::Rng;
use sfw_provider_requests::DUMMY_MESSAGE_CONTENT;
use sphinx::route::{DestinationAddressBytes, SURBIdentifier};
use std::fs::File;
use std::io;
use std::io::Write;
use std::path::Path;
pub enum StoreError {
ClientDoesntExistError,
FileIOFailure,
}
impl From<std::io::Error> for StoreError {
fn from(_: std::io::Error) -> Self {
use StoreError::*;
FileIOFailure
}
}
pub struct StoreData {
client_address: DestinationAddressBytes,
client_surb_id: SURBIdentifier,
message: Vec<u8>,
}
impl StoreData {
pub(crate) fn new(
client_address: DestinationAddressBytes,
client_surb_id: SURBIdentifier,
message: Vec<u8>,
) -> Self {
StoreData {
client_address,
client_surb_id,
message,
}
}
}
// TODO: replace with database
pub struct ClientStorage(());
impl ClientStorage {
fn generate_random_file_name() -> String {
rand::thread_rng()
.sample_iter(&rand::distributions::Alphanumeric)
.take(STORED_MESSAGE_FILENAME_LENGTH)
.collect::<String>()
}
fn dummy_message() -> Vec<u8> {
// TODO: should it be padded to constant length?
DUMMY_MESSAGE_CONTENT.to_vec()
}
pub fn store_processed_data(store_data: StoreData, store_dir: &Path) -> io::Result<()> {
let client_dir_name = hex::encode(store_data.client_address);
let full_store_dir = store_dir.join(client_dir_name);
let full_store_path = full_store_dir.join(ClientStorage::generate_random_file_name());
println!(
"going to store: {:?} in file: {:?}",
store_data.message, full_store_path
);
// TODO: what to do with surbIDs??
// TODO: this should be called when client sends 'register' request!
std::fs::create_dir_all(full_store_dir)?;
// we can use normal io here, no need for tokio as it's all happening in one thread per connection
let mut file = File::create(full_store_path)?;
file.write_all(store_data.message.as_ref())?;
Ok(())
}
pub fn retrieve_client_files(
client_address: DestinationAddressBytes,
store_dir: &Path,
) -> Result<Vec<Vec<u8>>, StoreError> {
let client_dir_name = hex::encode(client_address);
let full_store_dir = store_dir.join(client_dir_name);
println!("going to lookup: {:?}!", full_store_dir);
if !full_store_dir.exists() {
return Err(StoreError::ClientDoesntExistError);
}
let msgs: Vec<_> = std::fs::read_dir(full_store_dir)?
.map(|entry| entry.unwrap())
.filter(|entry| {
let is_file = entry.metadata().unwrap().is_file();
if !is_file {
eprintln!(
"potentially corrupted client inbox! - found a non-file - {:?}",
entry.path()
);
}
is_file
})
.map(|entry| std::fs::read(entry.path()).unwrap()) // TODO: also delete; THIS MAP IS UNSAFE!!
.chain(std::iter::repeat(ClientStorage::dummy_message()))
.take(MESSAGE_RETRIEVAL_LIMIT)
.collect();
println!("retrieved the following data: {:?}", msgs);
Ok(msgs)
}
// TODO: THIS NEEDS A LOCKING MECHANISM!!! (or a db layer on top - basically 'ClientStorage' on steroids)
fn delete_file() {}
}