#![allow(unsafe_op_in_unsafe_fn)]
use crate::error::{Error, check};
use crate::ffi;
use crate::merkle::{MerkleEntry, MerkleLog};
use crate::types::NodeId;
pub struct LogServerSettings {
pub authorize: Option<Box<dyn Fn(&NodeId, &MerkleEntry) -> Result<(), Error> + Send>>,
}
impl Default for LogServerSettings {
fn default() -> Self {
LogServerSettings { authorize: None }
}
}
struct Callbacks {
authorize: Option<Box<dyn Fn(&NodeId, &MerkleEntry) -> Result<(), Error> + Send>>,
}
unsafe extern "C" fn authorize_cb(
user_data: *mut std::ffi::c_void,
nodeid: *const ffi::nwep_nodeid,
entry: *const ffi::nwep_merkle_entry,
) -> std::ffi::c_int {
let cb = &*(user_data as *const Callbacks);
if let Some(f) = &cb.authorize {
let nid = NodeId((*nodeid).data);
let e = MerkleEntry::from_ffi(&*entry);
match f(&nid, &e) {
Ok(()) => 0,
Err(e) => e.code,
}
} else {
crate::error::ERR_PROTO_UNAUTHORIZED
}
}
pub struct LogServer {
ptr: *mut ffi::nwep_log_server,
_callbacks: Box<Callbacks>,
}
unsafe impl Send for LogServer {}
impl LogServer {
pub fn new(log: &mut MerkleLog, settings: LogServerSettings) -> Result<Self, Error> {
let has_authorize = settings.authorize.is_some();
let mut cb = Box::new(Callbacks {
authorize: settings.authorize,
});
let cb_ptr = cb.as_mut() as *mut _ as *mut std::ffi::c_void;
let ffi_settings = ffi::nwep_log_server_settings {
authorize: if has_authorize {
Some(authorize_cb)
} else {
None
},
user_data: cb_ptr,
};
let mut ptr: *mut ffi::nwep_log_server = std::ptr::null_mut();
check(unsafe { ffi::nwep_log_server_new(&mut ptr, log.as_ptr(), &ffi_settings) })?;
Ok(LogServer {
ptr,
_callbacks: cb,
})
}
pub fn handle_request(
&mut self,
stream: *mut ffi::nwep_stream,
req: *const ffi::nwep_request,
) -> Result<(), Error> {
check(unsafe { ffi::nwep_log_server_handle_request(self.ptr, stream, req) })
}
pub fn as_ptr(&mut self) -> *mut ffi::nwep_log_server {
self.ptr
}
}
impl Drop for LogServer {
fn drop(&mut self) {
if !self.ptr.is_null() {
unsafe { ffi::nwep_log_server_free(self.ptr) }
}
}
}