use crate::{
context::{Context, EomContext, NegotiateContext},
proto_util::{Actions, ProtoOpts, SocketInfo},
};
use bytes::Bytes;
use std::{ffi::CString, future::Future, pin::Pin};
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum Status {
Accept,
Continue,
Reject,
Tempfail,
Discard,
Noreply,
Skip,
AllOpts,
}
impl Default for Status {
fn default() -> Self {
Self::Continue
}
}
pub type CallbackFuture<'a> = Pin<Box<dyn Future<Output = Status> + Send + 'a>>;
#[derive(Default)]
pub struct Callbacks<T: Send> {
pub negotiate:
Option<Box<dyn for<'cx> Fn(&'cx mut NegotiateContext<T>, Actions, ProtoOpts) -> CallbackFuture<'cx> + Send + Sync>>,
pub connect:
Option<Box<dyn for<'cx> Fn(&'cx mut Context<T>, CString, SocketInfo) -> CallbackFuture<'cx> + Send + Sync>>,
pub helo:
Option<Box<dyn for<'cx> Fn(&'cx mut Context<T>, CString) -> CallbackFuture<'cx> + Send + Sync>>,
pub mail:
Option<Box<dyn for<'cx> Fn(&'cx mut Context<T>, Vec<CString>) -> CallbackFuture<'cx> + Send + Sync>>,
pub rcpt:
Option<Box<dyn for<'cx> Fn(&'cx mut Context<T>, Vec<CString>) -> CallbackFuture<'cx> + Send + Sync>>,
pub data:
Option<Box<dyn for<'cx> Fn(&'cx mut Context<T>) -> CallbackFuture<'cx> + Send + Sync>>,
pub header:
Option<Box<dyn for<'cx> Fn(&'cx mut Context<T>, CString, CString) -> CallbackFuture<'cx> + Send + Sync>>,
pub eoh:
Option<Box<dyn for<'cx> Fn(&'cx mut Context<T>) -> CallbackFuture<'cx> + Send + Sync>>,
pub body:
Option<Box<dyn for<'cx> Fn(&'cx mut Context<T>, Bytes) -> CallbackFuture<'cx> + Send + Sync>>,
pub eom:
Option<Box<dyn for<'cx> Fn(&'cx mut EomContext<T>) -> CallbackFuture<'cx> + Send + Sync>>,
pub abort:
Option<Box<dyn for<'cx> Fn(&'cx mut Context<T>) -> CallbackFuture<'cx> + Send + Sync>>,
pub close:
Option<Box<dyn for<'cx> Fn(&'cx mut Context<T>) -> CallbackFuture<'cx> + Send + Sync>>,
pub unknown:
Option<Box<dyn for<'cx> Fn(&'cx mut Context<T>, CString) -> CallbackFuture<'cx> + Send + Sync>>,
}
impl<T: Send> Callbacks<T> {
pub fn new() -> Self {
Self {
negotiate: None,
connect: None,
helo: None,
mail: None,
rcpt: None,
data: None,
header: None,
eoh: None,
body: None,
eom: None,
abort: None,
close: None,
unknown: None,
}
}
pub fn on_negotiate(
mut self,
callback: impl Fn(&mut NegotiateContext<T>, Actions, ProtoOpts) -> CallbackFuture<'_> + Send + Sync + 'static,
) -> Self {
self.negotiate = Some(Box::new(callback));
self
}
pub fn on_connect(
mut self,
callback: impl Fn(&mut Context<T>, CString, SocketInfo) -> CallbackFuture<'_> + Send + Sync + 'static,
) -> Self {
self.connect = Some(Box::new(callback));
self
}
pub fn on_helo(
mut self,
callback: impl Fn(&mut Context<T>, CString) -> CallbackFuture<'_> + Send + Sync + 'static,
) -> Self {
self.helo = Some(Box::new(callback));
self
}
pub fn on_mail(
mut self,
callback: impl Fn(&mut Context<T>, Vec<CString>) -> CallbackFuture<'_> + Send + Sync + 'static,
) -> Self {
self.mail = Some(Box::new(callback));
self
}
pub fn on_rcpt(
mut self,
callback: impl Fn(&mut Context<T>, Vec<CString>) -> CallbackFuture<'_> + Send + Sync + 'static,
) -> Self {
self.rcpt = Some(Box::new(callback));
self
}
pub fn on_data(
mut self,
callback: impl Fn(&mut Context<T>) -> CallbackFuture<'_> + Send + Sync + 'static,
) -> Self {
self.data = Some(Box::new(callback));
self
}
pub fn on_header(
mut self,
callback: impl Fn(&mut Context<T>, CString, CString) -> CallbackFuture<'_> + Send + Sync + 'static,
) -> Self {
self.header = Some(Box::new(callback));
self
}
pub fn on_eoh(
mut self,
callback: impl Fn(&mut Context<T>) -> CallbackFuture<'_> + Send + Sync + 'static,
) -> Self {
self.eoh = Some(Box::new(callback));
self
}
pub fn on_body(
mut self,
callback: impl Fn(&mut Context<T>, Bytes) -> CallbackFuture<'_> + Send + Sync + 'static,
) -> Self {
self.body = Some(Box::new(callback));
self
}
pub fn on_eom(
mut self,
callback: impl Fn(&mut EomContext<T>) -> CallbackFuture<'_> + Send + Sync + 'static,
) -> Self {
self.eom = Some(Box::new(callback));
self
}
pub fn on_abort(
mut self,
callback: impl Fn(&mut Context<T>) -> CallbackFuture<'_> + Send + Sync + 'static,
) -> Self {
self.abort = Some(Box::new(callback));
self
}
pub fn on_close(
mut self,
callback: impl Fn(&mut Context<T>) -> CallbackFuture<'_> + Send + Sync + 'static,
) -> Self {
self.close = Some(Box::new(callback));
self
}
pub fn on_unknown(
mut self,
callback: impl Fn(&mut Context<T>, CString) -> CallbackFuture<'_> + Send + Sync + 'static,
) -> Self {
self.unknown = Some(Box::new(callback));
self
}
}