diff options
author | Alex Auvolat <alex@adnab.me> | 2022-05-31 17:07:34 +0200 |
---|---|---|
committer | Alex Auvolat <alex@adnab.me> | 2022-05-31 17:07:34 +0200 |
commit | 553a15a82a700792986b23cb89e2a8ec070cc27d (patch) | |
tree | 8ea039322b39064fa8c66d9647f84b79f64f1921 /src/server.rs | |
parent | 01d82c14ca61e7c4de1e72c5f94456610464c064 (diff) | |
download | aerogramme-553a15a82a700792986b23cb89e2a8ec070cc27d.tar.gz aerogramme-553a15a82a700792986b23cb89e2a8ec070cc27d.zip |
Implementn basic LMTP server
Diffstat (limited to 'src/server.rs')
-rw-r--r-- | src/server.rs | 67 |
1 files changed, 56 insertions, 11 deletions
diff --git a/src/server.rs b/src/server.rs index e1ab599..1fd21b4 100644 --- a/src/server.rs +++ b/src/server.rs @@ -1,18 +1,23 @@ -use anyhow::{bail, Result}; use std::sync::Arc; +use anyhow::{bail, Result}; +use futures::{try_join, StreamExt}; +use log::*; use rusoto_signature::Region; +use tokio::sync::watch; use crate::config::*; +use crate::lmtp::*; use crate::login::{ldap_provider::*, static_provider::*, *}; use crate::mailbox::Mailbox; pub struct Server { - pub login_provider: Box<dyn LoginProvider>, + pub login_provider: Arc<dyn LoginProvider + Send + Sync>, + pub lmtp_server: Option<Arc<LmtpServer>>, } impl Server { - pub fn new(config: Config) -> Result<Arc<Self>> { + pub fn new(config: Config) -> Result<Self> { let s3_region = Region::Custom { name: config.aws_region.clone(), endpoint: config.s3_endpoint, @@ -21,17 +26,43 @@ impl Server { name: config.aws_region, endpoint: config.k2v_endpoint, }; - let login_provider: Box<dyn LoginProvider> = match (config.login_static, config.login_ldap) - { - (Some(st), None) => Box::new(StaticLoginProvider::new(st, k2v_region, s3_region)?), - (None, Some(ld)) => Box::new(LdapLoginProvider::new(ld, k2v_region, s3_region)?), - (Some(_), Some(_)) => bail!("A single login provider must be set up in config file"), - (None, None) => bail!("No login provider is set up in config file"), + let login_provider: Arc<dyn LoginProvider + Send + Sync> = + match (config.login_static, config.login_ldap) { + (Some(st), None) => Arc::new(StaticLoginProvider::new(st, k2v_region, s3_region)?), + (None, Some(ld)) => Arc::new(LdapLoginProvider::new(ld, k2v_region, s3_region)?), + (Some(_), Some(_)) => { + bail!("A single login provider must be set up in config file") + } + (None, None) => bail!("No login provider is set up in config file"), + }; + + let lmtp_server = config + .lmtp + .map(|cfg| LmtpServer::new(cfg, login_provider.clone())); + + Ok(Self { + login_provider, + lmtp_server, + }) + } + + pub async fn run(&self) -> Result<()> { + let (exit_signal, provoke_exit) = watch_ctrl_c(); + let exit_on_err = move |err: anyhow::Error| { + error!("Error: {}", err); + let _ = provoke_exit.send(true); }; - Ok(Arc::new(Self { login_provider })) + + try_join!(async { + match self.lmtp_server.as_ref() { + None => Ok(()), + Some(s) => s.run(exit_signal.clone()).await, + } + })?; + Ok(()) } - pub async fn run(self: &Arc<Self>) -> Result<()> { + pub async fn test(&self) -> Result<()> { let creds = self.login_provider.login("lx", "plop").await?; let mut mailbox = Mailbox::new(&creds, "TestMailbox".to_string()).await?; @@ -41,3 +72,17 @@ impl Server { Ok(()) } } + +pub fn watch_ctrl_c() -> (watch::Receiver<bool>, Arc<watch::Sender<bool>>) { + let (send_cancel, watch_cancel) = watch::channel(false); + let send_cancel = Arc::new(send_cancel); + let send_cancel_2 = send_cancel.clone(); + tokio::spawn(async move { + tokio::signal::ctrl_c() + .await + .expect("failed to install CTRL+C signal handler"); + info!("Received CTRL+C, shutting down."); + send_cancel.send(true).unwrap(); + }); + (watch_cancel, send_cancel_2) +} |