use crate::client;
use crate::enums::SignatureScheme;
use crate::error::Error;
use crate::key;
use crate::limited_cache;
use crate::sign;
use std::sync::{Arc, Mutex};
pub struct NoClientSessionStorage {}
impl client::StoresClientSessions for NoClientSessionStorage {
fn put(&self, _key: Vec<u8>, _value: Vec<u8>) -> bool {
false
}
fn get(&self, _key: &[u8]) -> Option<Vec<u8>> {
None
}
}
pub struct ClientSessionMemoryCache {
cache: Mutex<limited_cache::LimitedCache<Vec<u8>, Vec<u8>>>,
}
impl ClientSessionMemoryCache {
pub fn new(size: usize) -> Arc<Self> {
debug_assert!(size > 0);
Arc::new(Self {
cache: Mutex::new(limited_cache::LimitedCache::new(size)),
})
}
}
impl client::StoresClientSessions for ClientSessionMemoryCache {
fn put(&self, key: Vec<u8>, value: Vec<u8>) -> bool {
self.cache
.lock()
.unwrap()
.insert(key, value);
true
}
fn get(&self, key: &[u8]) -> Option<Vec<u8>> {
self.cache
.lock()
.unwrap()
.get(key)
.cloned()
}
}
pub(super) struct FailResolveClientCert {}
impl client::ResolvesClientCert for FailResolveClientCert {
fn resolve(
&self,
_acceptable_issuers: &[&[u8]],
_sigschemes: &[SignatureScheme],
) -> Option<Arc<sign::CertifiedKey>> {
None
}
fn has_certs(&self) -> bool {
false
}
}
pub(super) struct AlwaysResolvesClientCert(Arc<sign::CertifiedKey>);
impl AlwaysResolvesClientCert {
pub(super) fn new(
chain: Vec<key::Certificate>,
priv_key: &key::PrivateKey,
) -> Result<Self, Error> {
let key = sign::any_supported_type(priv_key)
.map_err(|_| Error::General("invalid private key".into()))?;
Ok(Self(Arc::new(sign::CertifiedKey::new(chain, key))))
}
}
impl client::ResolvesClientCert for AlwaysResolvesClientCert {
fn resolve(
&self,
_acceptable_issuers: &[&[u8]],
_sigschemes: &[SignatureScheme],
) -> Option<Arc<sign::CertifiedKey>> {
Some(Arc::clone(&self.0))
}
fn has_certs(&self) -> bool {
true
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::client::StoresClientSessions;
#[test]
fn test_noclientsessionstorage_drops_put() {
let c = NoClientSessionStorage {};
assert!(!c.put(vec![0x01], vec![0x02]));
}
#[test]
fn test_noclientsessionstorage_denies_gets() {
let c = NoClientSessionStorage {};
c.put(vec![0x01], vec![0x02]);
assert_eq!(c.get(&[]), None);
assert_eq!(c.get(&[0x01]), None);
assert_eq!(c.get(&[0x02]), None);
}
#[test]
fn test_clientsessionmemorycache_accepts_put() {
let c = ClientSessionMemoryCache::new(4);
assert!(c.put(vec![0x01], vec![0x02]));
}
#[test]
fn test_clientsessionmemorycache_persists_put() {
let c = ClientSessionMemoryCache::new(4);
assert!(c.put(vec![0x01], vec![0x02]));
assert_eq!(c.get(&[0x01]), Some(vec![0x02]));
assert_eq!(c.get(&[0x01]), Some(vec![0x02]));
}
#[test]
fn test_clientsessionmemorycache_overwrites_put() {
let c = ClientSessionMemoryCache::new(4);
assert!(c.put(vec![0x01], vec![0x02]));
assert!(c.put(vec![0x01], vec![0x04]));
assert_eq!(c.get(&[0x01]), Some(vec![0x04]));
}
#[test]
fn test_clientsessionmemorycache_drops_to_maintain_size_invariant() {
let c = ClientSessionMemoryCache::new(2);
assert!(c.put(vec![0x01], vec![0x02]));
assert!(c.put(vec![0x03], vec![0x04]));
assert!(c.put(vec![0x05], vec![0x06]));
assert!(c.put(vec![0x07], vec![0x08]));
assert!(c.put(vec![0x09], vec![0x0a]));
let count = c.get(&[0x01]).iter().count()
+ c.get(&[0x03]).iter().count()
+ c.get(&[0x05]).iter().count()
+ c.get(&[0x07]).iter().count()
+ c.get(&[0x09]).iter().count();
assert!(count < 5);
}
}