Compare commits
	
		
			1 Commits 
		
	
	
		
			master
			...
			4-update-c
		
	
	| Author | SHA1 | Date | 
|---|---|---|
| 
							
							
								 | 
						1124495540 | 4 years ago | 
				 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