From 35cff8dfcdd5d03b217b7d5d89bf0e30cbf9c38e Mon Sep 17 00:00:00 2001 From: Jedrzej Stuczynski Date: Thu, 12 Dec 2019 14:40:10 +0000 Subject: [PATCH] Moved store related functionalities to separate module --- src/provider/client_handling/mod.rs | 0 src/provider/mix_handling/mod.rs | 0 src/provider/mod.rs | 101 ++++-------------------- src/provider/storage/mod.rs | 116 ++++++++++++++++++++++++++++ 4 files changed, 133 insertions(+), 84 deletions(-) create mode 100644 src/provider/client_handling/mod.rs create mode 100644 src/provider/mix_handling/mod.rs create mode 100644 src/provider/storage/mod.rs diff --git a/src/provider/client_handling/mod.rs b/src/provider/client_handling/mod.rs new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/provider/mix_handling/mod.rs b/src/provider/mix_handling/mod.rs new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/provider/mod.rs b/src/provider/mod.rs index a1bae0c751..d815c32b4c 100644 --- a/src/provider/mod.rs +++ b/src/provider/mod.rs @@ -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, -} - - 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::() - } - - fn dummy_message() -> Vec { - // 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>, 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 for ClientProcessingError { - fn from(_: std::io::Error) -> Self { - use ClientProcessingError::*; - - FileIOFailure - } + StoreError, + InvalidRequest, } impl From for ClientProcessingError { @@ -189,6 +115,13 @@ impl From for ClientProcessingError { } } +impl From for ClientProcessingError { + fn from(_: StoreError) -> Self { + use ClientProcessingError::*; + + StoreError + } +} #[derive(Debug, Clone)] struct ClientProcessingData { diff --git a/src/provider/storage/mod.rs b/src/provider/storage/mod.rs new file mode 100644 index 0000000000..330c51d502 --- /dev/null +++ b/src/provider/storage/mod.rs @@ -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 for StoreError { + fn from(_: std::io::Error) -> Self { + use StoreError::*; + + FileIOFailure + } +} + +pub struct StoreData { + client_address: DestinationAddressBytes, + client_surb_id: SURBIdentifier, + message: Vec, +} + +impl StoreData { + pub(crate) fn new( + client_address: DestinationAddressBytes, + client_surb_id: SURBIdentifier, + message: Vec, + ) -> 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::() + } + + fn dummy_message() -> Vec { + // 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>, 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() {} +}