added untested code for disk persistence

This commit is contained in:
ghe0 2024-08-22 20:53:30 +03:00
parent e13fb05dbb
commit 3c2137f224
Signed by: ghe0
GPG Key ID: 451028EE56A0FBB4
2 changed files with 109 additions and 0 deletions

@ -1,3 +1,4 @@
mod persistence;
mod datastore; mod datastore;
use crate::grpc::challenge::NodeUpdate; use crate::grpc::challenge::NodeUpdate;
use tokio::sync::broadcast::Sender; use tokio::sync::broadcast::Sender;

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))
}
}