use crate::error::{Error, check};
use crate::ffi;
use crate::types::{Duration, NodeId, Tstamp};
pub const CACHE_DEFAULT_CAPACITY: usize = 10000;
pub const CACHE_DEFAULT_TTL: Duration = 3600 * crate::types::SECONDS;
#[derive(Clone, Debug)]
pub struct IdentityCacheSettings {
pub capacity: usize,
pub ttl_ns: Duration,
}
impl Default for IdentityCacheSettings {
fn default() -> Self {
let mut s = unsafe { std::mem::zeroed::<ffi::nwep_identity_cache_settings>() };
unsafe { ffi::nwep_identity_cache_settings_default(&mut s) };
IdentityCacheSettings {
capacity: s.capacity,
ttl_ns: s.ttl_ns,
}
}
}
#[derive(Clone, Debug)]
pub struct CachedIdentity {
pub node_id: NodeId,
pub pubkey: [u8; 32],
pub log_index: u64,
pub verified_at: Tstamp,
pub expires_at: Tstamp,
}
impl CachedIdentity {
fn from_ffi(c: &ffi::nwep_cached_identity) -> Self {
CachedIdentity {
node_id: NodeId(c.nodeid.data),
pubkey: c.pubkey,
log_index: c.log_index,
verified_at: c.verified_at,
expires_at: c.expires_at,
}
}
}
#[derive(Clone, Debug, Default)]
pub struct CacheStats {
pub hits: u64,
pub misses: u64,
pub evictions: u64,
pub stores: u64,
pub invalidations: u64,
}
pub struct IdentityCache {
ptr: *mut ffi::nwep_identity_cache,
}
unsafe impl Send for IdentityCache {}
impl IdentityCache {
pub fn new(settings: Option<&IdentityCacheSettings>) -> Result<Self, Error> {
let mut ptr: *mut ffi::nwep_identity_cache = std::ptr::null_mut();
let rc = match settings {
Some(s) => {
let ffi_s = ffi::nwep_identity_cache_settings {
capacity: s.capacity,
ttl_ns: s.ttl_ns,
};
unsafe { ffi::nwep_identity_cache_new(&mut ptr, &ffi_s) }
}
None => unsafe { ffi::nwep_identity_cache_new(&mut ptr, std::ptr::null()) },
};
check(rc)?;
Ok(IdentityCache { ptr })
}
pub fn lookup(&mut self, node_id: &NodeId, now: Tstamp) -> Result<CachedIdentity, Error> {
let ffi_nid = ffi::nwep_nodeid { data: node_id.0 };
let mut out = unsafe { std::mem::zeroed::<ffi::nwep_cached_identity>() };
check(unsafe { ffi::nwep_identity_cache_lookup(self.ptr, &ffi_nid, now, &mut out) })?;
Ok(CachedIdentity::from_ffi(&out))
}
pub fn store(
&mut self,
node_id: &NodeId,
pubkey: &[u8; 32],
log_index: u64,
now: Tstamp,
) -> Result<(), Error> {
let ffi_nid = ffi::nwep_nodeid { data: node_id.0 };
check(unsafe {
ffi::nwep_identity_cache_store(self.ptr, &ffi_nid, pubkey.as_ptr(), log_index, now)
})
}
pub fn invalidate(&mut self, node_id: &NodeId) -> Result<(), Error> {
let ffi_nid = ffi::nwep_nodeid { data: node_id.0 };
check(unsafe { ffi::nwep_identity_cache_invalidate(self.ptr, &ffi_nid) })
}
pub fn clear(&mut self) {
unsafe { ffi::nwep_identity_cache_clear(self.ptr) }
}
pub fn size(&self) -> usize {
unsafe { ffi::nwep_identity_cache_size(self.ptr) }
}
pub fn capacity(&self) -> usize {
unsafe { ffi::nwep_identity_cache_capacity(self.ptr) }
}
pub fn on_rotation(
&mut self,
node_id: &NodeId,
new_pubkey: &[u8; 32],
new_log_index: u64,
now: Tstamp,
) -> Result<(), Error> {
let ffi_nid = ffi::nwep_nodeid { data: node_id.0 };
check(unsafe {
ffi::nwep_identity_cache_on_rotation(
self.ptr,
&ffi_nid,
new_pubkey.as_ptr(),
new_log_index,
now,
)
})
}
pub fn on_revocation(&mut self, node_id: &NodeId) -> Result<(), Error> {
let ffi_nid = ffi::nwep_nodeid { data: node_id.0 };
check(unsafe { ffi::nwep_identity_cache_on_revocation(self.ptr, &ffi_nid) })
}
pub fn stats(&self) -> CacheStats {
let mut s = unsafe { std::mem::zeroed::<ffi::nwep_cache_stats>() };
unsafe { ffi::nwep_identity_cache_get_stats(self.ptr, &mut s) };
CacheStats {
hits: s.hits,
misses: s.misses,
evictions: s.evictions,
stores: s.stores,
invalidations: s.invalidations,
}
}
pub fn reset_stats(&mut self) {
unsafe { ffi::nwep_identity_cache_reset_stats(self.ptr) }
}
}
impl Drop for IdentityCache {
fn drop(&mut self) {
if !self.ptr.is_null() {
unsafe { ffi::nwep_identity_cache_free(self.ptr) }
}
}
}