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