added untested code for disk persistence
This commit is contained in:
		
							parent
							
								
									e13fb05dbb
								
							
						
					
					
						commit
						3c2137f224
					
				| @ -1,3 +1,4 @@ | ||||
| mod persistence; | ||||
| mod datastore; | ||||
| use crate::grpc::challenge::NodeUpdate; | ||||
| use tokio::sync::broadcast::Sender; | ||||
|  | ||||
							
								
								
									
										108
									
								
								src/persistence.rs
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										108
									
								
								src/persistence.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,108 @@ | ||||
| #![allow(dead_code)] | ||||
| use ed25519_dalek::SigningKey; | ||||
| use ed25519_dalek::KEYPAIR_LENGTH; | ||||
| use std::net::AddrParseError; | ||||
| use std::net::Ipv4Addr; | ||||
| use std::time::{Duration, SystemTime, UNIX_EPOCH}; | ||||
| use tokio::fs::File; | ||||
| use tokio::io::{AsyncReadExt, AsyncSeekExt, AsyncWriteExt, SeekFrom}; | ||||
| use tokio::sync::Mutex; | ||||
| 
 | ||||
| const DATA_SIZE: usize = 78; | ||||
| 
 | ||||
| enum Error { | ||||
|     CorruptedIP, | ||||
| } | ||||
| 
 | ||||
| impl From<AddrParseError> for Error { | ||||
|     fn from(_: AddrParseError) -> Self { | ||||
|         Error::CorruptedIP | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| struct Node { | ||||
|     ip: Ipv4Addr, | ||||
|     keypair: SigningKey, | ||||
|     joined_at: SystemTime, | ||||
| } | ||||
| 
 | ||||
| impl TryFrom<(&str, SigningKey, SystemTime)> for Node { | ||||
|     type Error = Error; | ||||
|     fn try_from(value: (&str, SigningKey, SystemTime)) -> Result<Self, Self::Error> { | ||||
|         Ok(Self { | ||||
|             ip: value.0.parse()?, | ||||
|             keypair: value.1, | ||||
|             joined_at: value.2, | ||||
|         }) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Node { | ||||
|     fn ip_as_string(&self) -> String { | ||||
|         self.ip.to_string() | ||||
|     } | ||||
| 
 | ||||
|     fn signing_key(&self) -> SigningKey { | ||||
|         self.keypair.clone() | ||||
|     } | ||||
| 
 | ||||
|     fn to_bytes(self) -> [u8; DATA_SIZE] { | ||||
|         let mut result = [0; DATA_SIZE]; | ||||
|         result[0..4].copy_from_slice(&self.ip.octets()); | ||||
|         result[4..68].copy_from_slice(&self.keypair.to_keypair_bytes()); | ||||
|         result[69..DATA_SIZE].copy_from_slice( | ||||
|             &self | ||||
|                 .joined_at | ||||
|                 .duration_since(UNIX_EPOCH) | ||||
|                 .unwrap() | ||||
|                 .as_secs() | ||||
|                 .to_le_bytes(), | ||||
|         ); | ||||
|         result | ||||
|     } | ||||
| 
 | ||||
|     fn from_bytes(bytes: [u8; DATA_SIZE]) -> Self { | ||||
|         let ip: [u8; 4] = bytes[0..4].try_into().unwrap(); | ||||
|         let ip: Ipv4Addr = ip.into(); | ||||
|         let keypair: [u8; KEYPAIR_LENGTH] = bytes[4..68].try_into().unwrap(); | ||||
|         let keypair: SigningKey = SigningKey::from_keypair_bytes(&keypair).unwrap(); | ||||
|         let joined_at: [u8; 8] = bytes[69..DATA_SIZE].try_into().unwrap(); | ||||
|         let joined_at: u64 = u64::from_le_bytes(joined_at); | ||||
|         let joined_at = SystemTime::UNIX_EPOCH + Duration::from_secs(joined_at); | ||||
|         Self { | ||||
|             ip, | ||||
|             keypair, | ||||
|             joined_at, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| struct FileManager { | ||||
|     file: Mutex<File>, | ||||
| } | ||||
| 
 | ||||
| impl FileManager { | ||||
|     async fn init(path: &str) -> std::io::Result<Self> { | ||||
|         let file = File::open(path).await?; | ||||
|         Ok(Self { | ||||
|             file: Mutex::new(file), | ||||
|         }) | ||||
|     } | ||||
| 
 | ||||
|     async fn append_node(&self, node: Node) -> std::io::Result<()> { | ||||
|         let mut file = self.file.lock().await; | ||||
|         file.seek(SeekFrom::End(0)).await?; | ||||
|         file.write_all(&node.to_bytes()).await?; | ||||
|         file.flush().await?; | ||||
|         Ok(()) | ||||
|     } | ||||
| 
 | ||||
|     async fn get_node_by_id(&self, id: u64) -> std::io::Result<Node> { | ||||
|         let mut file = self.file.lock().await; | ||||
|         file.seek(SeekFrom::Start(id.wrapping_mul(DATA_SIZE.try_into().unwrap_or(0)))) | ||||
|             .await?; | ||||
|         let mut node_bytes = [0; DATA_SIZE]; | ||||
|         file.read_exact(&mut node_bytes).await?; | ||||
|         Ok(Node::from_bytes(node_bytes)) | ||||
|     } | ||||
| } | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user