diff --git a/opensmtpd-derive/src/lib.rs b/opensmtpd-derive/src/lib.rs index 09a81d1..d6dc370 100644 --- a/opensmtpd-derive/src/lib.rs +++ b/opensmtpd-derive/src/lib.rs @@ -13,8 +13,13 @@ pub fn event(attr: TokenStream, input: TokenStream) -> TokenStream { let fn_body = &item.block; let fn_output = &item.decl.output; let output = quote! { - fn #fn_name() -> opensmtpd::EventHandler { - opensmtpd::EventHandler::new(#attr, |#fn_params| #fn_output #fn_body) + // TODO: set the correct EventHandler type + fn #fn_name() -> opensmtpd::EventHandler { + // TODO: set the correct Callback type + opensmtpd::EventHandler::new( + #attr, + opensmtpd::Callback::CtxMut(|#fn_params| #fn_output #fn_body) + ) } }; output.into() diff --git a/opensmtpd/examples/dummy.rs b/opensmtpd/examples/dummy.rs index 593b455..076af59 100644 --- a/opensmtpd/examples/dummy.rs +++ b/opensmtpd/examples/dummy.rs @@ -1,15 +1,15 @@ use env_logger::{Builder, Env}; use log::{debug, info}; -use opensmtpd::{event, handlers, Entry, Response, SmtpIn}; +use opensmtpd::{event, handlers, Entry, NoContext, Response, SmtpIn}; #[event(Any)] -fn on_event(entry: &Entry) -> Response { +fn on_event(_context: &mut NoContext, entry: &Entry) -> Response { debug!("Event received: {:?}", entry); Response::None } #[event(LinkConnect)] -fn on_connect(entry: &Entry) -> Response { +fn on_connect(_context: &mut NoContext, entry: &Entry) -> Response { info!("New client on session {:x}.", entry.session_id); Response::None } diff --git a/opensmtpd/src/errors.rs b/opensmtpd/src/errors.rs index 95ad784..26f707b 100644 --- a/opensmtpd/src/errors.rs +++ b/opensmtpd/src/errors.rs @@ -43,8 +43,8 @@ impl From> for Error { } } -impl From> for Error { - fn from(error: std::sync::mpsc::SendError) -> Self { +impl From>> for Error { + fn from(error: std::sync::mpsc::SendError>) -> Self { Error::new(&format!("IO error: {}", error)) } } diff --git a/opensmtpd/src/event_handlers.rs b/opensmtpd/src/event_handlers.rs index c573eb7..3543d84 100644 --- a/opensmtpd/src/event_handlers.rs +++ b/opensmtpd/src/event_handlers.rs @@ -9,30 +9,37 @@ pub enum MatchEvent { } #[derive(Clone)] -pub struct EventHandler { - event: MatchEvent, - callback: (fn(&Entry) -> Response), +pub enum Callback { + NoCtx(fn(&Entry) -> Response), + Ctx(fn(&T, &Entry) -> Response), + CtxMut(fn(&mut T, &Entry) -> Response), } -impl EventHandler { - fn get_events_from_string(event_str: &str) -> MatchEvent { - let mut events = Vec::new(); - for name in event_str.split(" , ") { - match name { - "Any" | "All" => { - return MatchEvent::All; - } - _ => if let Ok(e) = Event::from_str(name) { - events.push(e); - }, - } - } - MatchEvent::Evt(events) - } +#[derive(Clone)] +pub struct EventHandler { + event: MatchEvent, + callback: Callback, +} - pub fn new(event_str: &str, callback: (fn(&Entry) -> Response)) -> Self { +fn get_events_from_string(event_str: &str) -> MatchEvent { + let mut events = Vec::new(); + for name in event_str.split(" , ") { + match name { + "Any" | "All" => { + return MatchEvent::All; + } + _ => if let Ok(e) = Event::from_str(name) { + events.push(e); + }, + } + } + MatchEvent::Evt(events) +} + +impl EventHandler { + pub fn new(event_str: &str, callback: Callback) -> Self { EventHandler { - event: EventHandler::get_events_from_string(event_str), + event: get_events_from_string(event_str), callback, } } @@ -44,9 +51,27 @@ impl EventHandler { } } - pub fn call(&self, entry: &Entry) { - match (self.callback)(entry) { - Response::None => {} + pub fn call(&self, entry: &Entry, context: &mut T) { + let ret = match self.callback { + Callback::NoCtx(f) => f(entry), + Callback::Ctx(f) => f(context, entry), + Callback::CtxMut(f) => f(context, entry), }; + match ret { + Response::None => {} + } + } +} + +#[cfg(test)] +mod test { + use crate::*; + + #[test] + fn test_eventhandler_build() { + EventHandler::new( + "Any", + |_context: &mut NoContext, _entry: &Entry| -> Response { Response::None }, + ); } } diff --git a/opensmtpd/src/lib.rs b/opensmtpd/src/lib.rs index 99600a8..c50f4f0 100644 --- a/opensmtpd/src/lib.rs +++ b/opensmtpd/src/lib.rs @@ -11,7 +11,7 @@ use std::thread; pub use crate::entry::{Entry, Event}; pub use crate::errors::Error; -pub use crate::event_handlers::{EventHandler, MatchEvent}; +pub use crate::event_handlers::{Callback, EventHandler, MatchEvent}; pub use opensmtpd_derive::event; #[macro_export] @@ -31,13 +31,16 @@ pub enum Response { None, } -struct SessionHandler { +#[derive(Clone, Default)] +pub struct NoContext; + +struct SessionHandler { entry_rx: mpsc::Receiver, - event_handlers: Vec, + event_handlers: Vec>, } -impl SessionHandler { - fn new(entry_rx: mpsc::Receiver, handlers_rx: &mpsc::Receiver) -> Self { +impl SessionHandler { + fn new(entry_rx: mpsc::Receiver, handlers_rx: &mpsc::Receiver>) -> Self { debug!( "New thread for session {}", thread::current().name().unwrap() @@ -54,10 +57,11 @@ impl SessionHandler { } fn read_entries(&self) { + let mut context: T = Default::default(); for e in self.entry_rx.iter() { for h in self.event_handlers.iter() { if h.is_callable(&e.event) { - h.call(&e); + h.call(&e, &mut context); } } } @@ -65,15 +69,15 @@ impl SessionHandler { } #[derive(Default)] -pub struct SmtpIn { +pub struct SmtpIn { sessions: HashMap, thread::JoinHandle<()>)>, - event_handlers: Vec, + event_handlers: Vec>, } -impl SmtpIn { +impl SmtpIn { /// Read a line from the standard input. /// Since EOF should not append, it is considered as an error. - fn read() -> Result { + fn read(&self) -> Result { let mut input = String::new(); let nb = io::stdin().read_line(&mut input)?; match nb { @@ -133,7 +137,7 @@ impl SmtpIn { } } - pub fn event_handlers(&mut self, handlers: Vec) -> &mut Self { + pub fn event_handlers(&mut self, handlers: Vec>) -> &mut Self { self.event_handlers = handlers.to_owned(); self } @@ -141,7 +145,7 @@ impl SmtpIn { /// Run the infinite loop that will read and process input from stdin. pub fn run(&mut self) { loop { - let line = match SmtpIn::read() { + let line = match self.read() { Ok(l) => l, Err(e) => { self.graceful_exit_children();