parent
37ae67bd1c
commit
1124495540
8 changed files with 221 additions and 8 deletions
@ -0,0 +1,65 @@ |
|||||||
|
use crate::worker::Worker; |
||||||
|
use once_cell::sync::Lazy; |
||||||
|
use sha2::{Digest, Sha512}; |
||||||
|
use std::fs; |
||||||
|
use std::path::PathBuf; |
||||||
|
use u_lib::utils::{Hexlify, SharedStorage}; |
||||||
|
|
||||||
|
pub struct FileMeta { |
||||||
|
hashsum: String, |
||||||
|
path: PathBuf, |
||||||
|
name: String, |
||||||
|
} |
||||||
|
|
||||||
|
static FILES: Lazy<SharedStorage<String, FileMeta>> = SharedStorage::new(); |
||||||
|
|
||||||
|
pub struct FileIndex; |
||||||
|
|
||||||
|
impl FileIndex { |
||||||
|
pub fn search_by_name(pat: impl Into<String>) -> Option<String> { |
||||||
|
let name = pat.into(); |
||||||
|
let (key, _) = FILES.lock().iter().find(|(_, v)| v.name == name)?; |
||||||
|
Some(*key) |
||||||
|
} |
||||||
|
|
||||||
|
pub fn get(key: impl Into<String>) -> Option<FileMeta> { |
||||||
|
let name = key.into(); |
||||||
|
FILES.get(&name).and_then(|r| Some(*r)) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl Worker for FileIndex { |
||||||
|
fn process(&mut self) { |
||||||
|
let hexlify = |data: &[u8]| format!("{:x}", Hexlify(data)); |
||||||
|
let mut hasher = Sha512::new(); |
||||||
|
for file in fs::read_dir("./files/hosted/").unwrap() { |
||||||
|
let file = match file { |
||||||
|
Ok(f) => f.path(), |
||||||
|
Err(e) => { |
||||||
|
warn!("Error reading file: {}", e); |
||||||
|
continue; |
||||||
|
} |
||||||
|
}; |
||||||
|
if file.is_file() { |
||||||
|
let file_data = fs::read(file).unwrap(); |
||||||
|
hasher.update(file_data); |
||||||
|
let hashsum = hasher.finalize_reset(); |
||||||
|
let shrinked_sum = hashsum |
||||||
|
.iter() |
||||||
|
.cloned() |
||||||
|
.take(32) |
||||||
|
.map(|b| b ^ 0x5a) |
||||||
|
.collect::<Vec<u8>>(); |
||||||
|
let shrinked_sum = hexlify(&shrinked_sum); |
||||||
|
let hashsum = hexlify(&hashsum); |
||||||
|
let name = file.file_name().unwrap().to_string_lossy().into_owned(); |
||||||
|
let meta = FileMeta { |
||||||
|
hashsum, |
||||||
|
name, |
||||||
|
path: file, |
||||||
|
}; |
||||||
|
FILES.lock().insert(shrinked_sum, meta); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,78 @@ |
|||||||
|
use once_cell::sync::Lazy; |
||||||
|
use std::collections::HashSet; |
||||||
|
use std::io::Read; |
||||||
|
use std::iter::Iterator; |
||||||
|
use std::time::{Duration, SystemTime}; |
||||||
|
use u_lib::utils::SharedStorage; |
||||||
|
use uuid::Uuid; |
||||||
|
|
||||||
|
type Data = Box<dyn Read + Send + Sync>; |
||||||
|
|
||||||
|
/// This struct holds uids of various readable objects (files, streams, etc...)
|
||||||
|
/// with timeout and permissions for any uids to read data
|
||||||
|
struct MappedData { |
||||||
|
//ids that allowed to read the data
|
||||||
|
for_ids: HashSet<Uuid>, |
||||||
|
created: SystemTime, |
||||||
|
timeout: Duration, |
||||||
|
data: Data, |
||||||
|
} |
||||||
|
|
||||||
|
impl MappedData { |
||||||
|
pub fn new( |
||||||
|
ids: impl Iterator<Item = Uuid>, |
||||||
|
data: impl Read + Send + Sync + 'static, |
||||||
|
timeout: Duration, |
||||||
|
) -> Self { |
||||||
|
MappedData { |
||||||
|
for_ids: ids.collect(), |
||||||
|
created: SystemTime::now(), |
||||||
|
timeout, |
||||||
|
data: Box::new(data), |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
static MAPPER: Lazy<SharedStorage<Uuid, MappedData>> = SharedStorage::new(); |
||||||
|
|
||||||
|
pub struct Mapper; |
||||||
|
|
||||||
|
impl Mapper { |
||||||
|
fn remove_overdue() { |
||||||
|
MAPPER |
||||||
|
.lock() |
||||||
|
.retain(|_, v| v.created.elapsed().unwrap() < v.timeout); |
||||||
|
} |
||||||
|
|
||||||
|
pub fn get(item_uid: Uuid, getter_uid: Uuid) -> Option<Data> { |
||||||
|
Self::remove_overdue(); |
||||||
|
let allowed_ids = MAPPER.lock().get(&item_uid)?.for_ids; |
||||||
|
if allowed_ids.contains(&getter_uid) { |
||||||
|
MAPPER.lock().remove(&item_uid).map(|d| d.data) |
||||||
|
} else { |
||||||
|
None |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
pub fn set( |
||||||
|
for_ids: impl Iterator<Item = Uuid>, |
||||||
|
data: impl Read + Send + Sync + 'static, |
||||||
|
timeout: Option<Duration>, |
||||||
|
) -> Uuid { |
||||||
|
Self::remove_overdue(); |
||||||
|
let uid = Uuid::new_v4(); |
||||||
|
let timeout = timeout.unwrap_or(Duration::from_secs(60)); |
||||||
|
let mapped = MappedData::new(for_ids, data, timeout); |
||||||
|
MAPPER.lock().insert(uid, mapped); |
||||||
|
uid |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// init:
|
||||||
|
// fill index struct with files allowed to download (probably auto-refresh index on file adding)
|
||||||
|
// hashmap<stripped_hash_of_file_name, PathBuf>
|
||||||
|
// download:
|
||||||
|
// 1) agent sends download_request with hash of wanted file
|
||||||
|
// 2) handler checks if this agent is allowed to dl file
|
||||||
|
// 3) if all ok, create in entry in mapper and return its uid and hashsum to agent
|
||||||
|
// 4) agent downloads file by uid, uid destructed after that
|
@ -0,0 +1,5 @@ |
|||||||
|
pub mod files; |
||||||
|
pub mod mapper; |
||||||
|
|
||||||
|
pub use files::FileIndex; |
||||||
|
pub use mapper::Mapper; |
@ -0,0 +1,3 @@ |
|||||||
|
pub trait Worker { |
||||||
|
fn process(&mut self); |
||||||
|
} |
Loading…
Reference in new issue