use std::{ fs::File, io, sync::Arc }; use tokio::sync::RwLock; use rustls::pki_types::{CertificateDer, PrivateKeyDer}; use trie::Trie; pub struct Certificate { pub certs:Vec>, pub key:PrivateKeyDer<'static>, } pub struct CertificateStore { certs:Trie>, } impl CertificateStore { pub fn new() -> Self { Self { certs:Trie::>::new(), } } pub fn add(&mut self, domain:&str, cert_file:&str, key_file:&str) -> Result<(),()> { // load certificate file let certs = match File::open(cert_file) { Ok(fcert) => { let mut reader = io::BufReader::new(fcert); let mut certificates = Vec::::new(); for result in rustls_pemfile::certs(&mut reader) { match result { Ok(certificate) => { certificates.push(certificate); } Err(_) => { } } } Ok(certificates) } Err(_) => Err(()) }; // load private key file let key = match File::open(key_file) { Ok(fkey) => { let mut reader = io::BufReader::new(fkey); match rustls_pemfile::private_key(&mut reader) { Ok(result) => match result { Some(key) => Ok(key), None => Err(()) } Err(_) => Err(()) } } Err(_) => Err(()) }; if certs.is_ok() && key.is_ok() { self.certs.set(domain, Arc::new(Certificate { certs:certs.unwrap(), key:key.unwrap(), })); Ok(()) } else { Err(()) } } pub fn remove(&mut self, domain:&str) -> Result<(),()> { if self.certs.unset(domain) { Ok(()) } else { Err(()) } } pub fn get(&self, domain:&str) -> Result, ()> { match self.certs.get(domain) { Some(certs) => Ok(certs), None => Err(()) } } pub fn to_share(self) -> Arc> { Arc::new(RwLock::new(self)) } }