use std::fmt::{Debug, Formatter};
use libc::{c_int, c_void, size_t};
use crate::error::rustls_result;
use crate::rslice::rustls_slice_bytes;
use crate::userdata::userdata_get;
pub type rustls_session_store_userdata = *mut c_void;
pub type rustls_session_store_get_callback = Option<
unsafe extern "C" fn(
userdata: rustls_session_store_userdata,
key: *const rustls_slice_bytes,
remove_after: c_int,
buf: *mut u8,
count: size_t,
out_n: *mut size_t,
) -> u32,
>;
pub(crate) type SessionStoreGetCallback = unsafe extern "C" fn(
userdata: rustls_session_store_userdata,
key: *const rustls_slice_bytes,
remove_after: c_int,
buf: *mut u8,
count: size_t,
out_n: *mut size_t,
) -> u32;
pub type rustls_session_store_put_callback = Option<
unsafe extern "C" fn(
userdata: rustls_session_store_userdata,
key: *const rustls_slice_bytes,
val: *const rustls_slice_bytes,
) -> u32,
>;
pub(crate) type SessionStorePutCallback = unsafe extern "C" fn(
userdata: rustls_session_store_userdata,
key: *const rustls_slice_bytes,
val: *const rustls_slice_bytes,
) -> u32;
pub(crate) struct SessionStoreBroker {
pub get_cb: SessionStoreGetCallback,
pub put_cb: SessionStorePutCallback,
}
impl SessionStoreBroker {
pub fn new(get_cb: SessionStoreGetCallback, put_cb: SessionStorePutCallback) -> Self {
SessionStoreBroker { get_cb, put_cb }
}
fn retrieve(&self, key: &[u8], remove: bool) -> Option<Vec<u8>> {
let key: rustls_slice_bytes = key.into();
let userdata = userdata_get().ok()?;
let mut data = vec![0; 65 * 1024];
let mut out_n = 0;
let cb = self.get_cb;
let result = unsafe {
cb(
userdata,
&key,
remove as c_int,
data.as_mut_ptr(),
data.len(),
&mut out_n,
)
};
match rustls_result::from(result) {
rustls_result::Ok => {
unsafe { data.set_len(out_n) };
Some(data)
}
_ => None,
}
}
fn store(&self, key: Vec<u8>, value: Vec<u8>) -> bool {
let key = key.as_slice().into();
let value = value.as_slice().into();
let cb = self.put_cb;
let userdata = match userdata_get() {
Ok(u) => u,
Err(_) => return false,
};
let result = unsafe { cb(userdata, &key, &value) };
result == rustls_result::Ok as u32
}
}
impl rustls::server::StoresServerSessions for SessionStoreBroker {
fn put(&self, key: Vec<u8>, value: Vec<u8>) -> bool {
self.store(key, value)
}
fn get(&self, key: &[u8]) -> Option<Vec<u8>> {
self.retrieve(key, false)
}
fn take(&self, key: &[u8]) -> Option<Vec<u8>> {
self.retrieve(key, true)
}
fn can_cache(&self) -> bool {
true
}
}
impl Debug for SessionStoreBroker {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SessionStoreBroker").finish()
}
}
unsafe impl Sync for SessionStoreBroker {}
unsafe impl Send for SessionStoreBroker {}