2022-05-19 12:33:49 +00:00
|
|
|
use std::sync::Arc;
|
|
|
|
|
2022-05-31 15:07:34 +00:00
|
|
|
use anyhow::{bail, Result};
|
|
|
|
use futures::{try_join, StreamExt};
|
|
|
|
use log::*;
|
|
|
|
use tokio::sync::watch;
|
2022-05-19 12:33:49 +00:00
|
|
|
|
2022-06-15 16:40:39 +00:00
|
|
|
use crate::config::*;
|
2022-06-17 16:39:36 +00:00
|
|
|
use crate::imap;
|
2022-06-22 15:26:52 +00:00
|
|
|
use crate::lmtp::*;
|
2022-06-20 16:09:20 +00:00
|
|
|
use crate::login::ArcLoginProvider;
|
2022-06-29 13:39:54 +00:00
|
|
|
use crate::login::{ldap_provider::*, static_provider::*, Region};
|
2022-05-19 12:33:49 +00:00
|
|
|
|
2022-06-03 09:38:01 +00:00
|
|
|
pub struct Server {
|
2022-06-15 16:40:39 +00:00
|
|
|
lmtp_server: Option<Arc<LmtpServer>>,
|
2022-06-17 16:39:36 +00:00
|
|
|
imap_server: Option<imap::Server>,
|
2022-06-03 09:38:01 +00:00
|
|
|
}
|
2022-05-19 12:33:49 +00:00
|
|
|
|
2022-06-03 09:38:01 +00:00
|
|
|
impl Server {
|
|
|
|
pub async fn new(config: Config) -> Result<Self> {
|
2022-06-17 16:39:36 +00:00
|
|
|
let (login, lmtp_conf, imap_conf) = build(config)?;
|
2022-06-15 16:40:39 +00:00
|
|
|
|
2022-06-17 16:39:36 +00:00
|
|
|
let lmtp_server = lmtp_conf.map(|cfg| LmtpServer::new(cfg, login.clone()));
|
2022-06-22 12:58:57 +00:00
|
|
|
let imap_server = match imap_conf {
|
|
|
|
Some(cfg) => Some(imap::new(cfg, login.clone()).await?),
|
|
|
|
None => None,
|
|
|
|
};
|
2022-06-15 16:40:39 +00:00
|
|
|
|
2022-06-22 15:26:52 +00:00
|
|
|
Ok(Self {
|
|
|
|
lmtp_server,
|
|
|
|
imap_server,
|
|
|
|
})
|
2022-06-03 09:38:01 +00:00
|
|
|
}
|
2022-06-01 16:00:56 +00:00
|
|
|
|
2022-06-15 16:40:39 +00:00
|
|
|
pub async fn run(self) -> Result<()> {
|
|
|
|
tracing::info!("Starting Aerogramme...");
|
|
|
|
|
2022-05-31 15:07:34 +00:00
|
|
|
let (exit_signal, provoke_exit) = watch_ctrl_c();
|
2022-06-29 10:52:58 +00:00
|
|
|
let _exit_on_err = move |err: anyhow::Error| {
|
2022-05-31 15:07:34 +00:00
|
|
|
error!("Error: {}", err);
|
|
|
|
let _ = provoke_exit.send(true);
|
2022-05-19 12:33:49 +00:00
|
|
|
};
|
2022-05-31 15:07:34 +00:00
|
|
|
|
2022-06-17 08:42:02 +00:00
|
|
|
try_join!(
|
|
|
|
async {
|
|
|
|
match self.lmtp_server.as_ref() {
|
|
|
|
None => Ok(()),
|
|
|
|
Some(s) => s.run(exit_signal.clone()).await,
|
|
|
|
}
|
|
|
|
},
|
|
|
|
async {
|
2022-06-22 12:58:57 +00:00
|
|
|
match self.imap_server {
|
2022-06-17 16:39:36 +00:00
|
|
|
None => Ok(()),
|
|
|
|
Some(s) => s.run(exit_signal.clone()).await,
|
2022-06-17 08:42:02 +00:00
|
|
|
}
|
2022-05-31 15:07:34 +00:00
|
|
|
}
|
2022-06-15 16:40:39 +00:00
|
|
|
)?;
|
2022-06-03 12:11:00 +00:00
|
|
|
|
2022-05-19 12:33:49 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
2022-05-31 15:07:34 +00:00
|
|
|
|
2022-06-20 16:09:20 +00:00
|
|
|
fn build(config: Config) -> Result<(ArcLoginProvider, Option<LmtpConfig>, Option<ImapConfig>)> {
|
2022-06-29 13:39:54 +00:00
|
|
|
let s3_region = Region {
|
2022-06-15 16:40:39 +00:00
|
|
|
name: config.aws_region.clone(),
|
|
|
|
endpoint: config.s3_endpoint,
|
|
|
|
};
|
2022-06-29 13:39:54 +00:00
|
|
|
let k2v_region = Region {
|
2022-06-15 16:40:39 +00:00
|
|
|
name: config.aws_region,
|
|
|
|
endpoint: config.k2v_endpoint,
|
|
|
|
};
|
|
|
|
|
2022-06-20 16:09:20 +00:00
|
|
|
let lp: ArcLoginProvider = match (config.login_static, config.login_ldap) {
|
2022-06-15 16:40:39 +00:00
|
|
|
(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"),
|
|
|
|
};
|
2022-06-17 16:39:36 +00:00
|
|
|
|
2022-06-22 12:58:57 +00:00
|
|
|
Ok((lp, config.lmtp, config.imap))
|
2022-06-15 16:40:39 +00:00
|
|
|
}
|
|
|
|
|
2022-05-31 15:07:34 +00:00
|
|
|
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)
|
|
|
|
}
|