aboutsummaryrefslogtreecommitdiff
path: root/aerogramme/src/server.rs
diff options
context:
space:
mode:
Diffstat (limited to 'aerogramme/src/server.rs')
-rw-r--r--aerogramme/src/server.rs160
1 files changed, 160 insertions, 0 deletions
diff --git a/aerogramme/src/server.rs b/aerogramme/src/server.rs
new file mode 100644
index 0000000..3b3f6eb
--- /dev/null
+++ b/aerogramme/src/server.rs
@@ -0,0 +1,160 @@
+use std::io::Write;
+use std::path::PathBuf;
+use std::sync::Arc;
+
+use anyhow::Result;
+use futures::try_join;
+use log::*;
+use tokio::sync::watch;
+
+use aero_proto::dav;
+use aero_proto::imap;
+use aero_proto::lmtp::*;
+use aero_proto::sasl as auth;
+use aero_user::config::*;
+use aero_user::login::ArcLoginProvider;
+use aero_user::login::{demo_provider::*, ldap_provider::*, static_provider::*};
+
+pub struct Server {
+ lmtp_server: Option<Arc<LmtpServer>>,
+ imap_unsecure_server: Option<imap::Server>,
+ imap_server: Option<imap::Server>,
+ auth_server: Option<auth::AuthServer>,
+ dav_unsecure_server: Option<dav::Server>,
+ dav_server: Option<dav::Server>,
+ pid_file: Option<PathBuf>,
+}
+
+impl Server {
+ pub async fn from_companion_config(config: CompanionConfig) -> Result<Self> {
+ tracing::info!("Init as companion");
+ let login = Arc::new(StaticLoginProvider::new(config.users).await?);
+
+ let lmtp_server = None;
+ let imap_unsecure_server = Some(imap::new_unsecure(config.imap, login.clone()));
+ Ok(Self {
+ lmtp_server,
+ imap_unsecure_server,
+ imap_server: None,
+ auth_server: None,
+ dav_unsecure_server: None,
+ dav_server: None,
+ pid_file: config.pid,
+ })
+ }
+
+ pub async fn from_provider_config(config: ProviderConfig) -> Result<Self> {
+ tracing::info!("Init as provider");
+ let login: ArcLoginProvider = match config.users {
+ UserManagement::Demo => Arc::new(DemoLoginProvider::new()),
+ UserManagement::Static(x) => Arc::new(StaticLoginProvider::new(x).await?),
+ UserManagement::Ldap(x) => Arc::new(LdapLoginProvider::new(x)?),
+ };
+
+ let lmtp_server = config.lmtp.map(|lmtp| LmtpServer::new(lmtp, login.clone()));
+ let imap_unsecure_server = config
+ .imap_unsecure
+ .map(|imap| imap::new_unsecure(imap, login.clone()));
+ let imap_server = config
+ .imap
+ .map(|imap| imap::new(imap, login.clone()))
+ .transpose()?;
+ let auth_server = config
+ .auth
+ .map(|auth| auth::AuthServer::new(auth, login.clone()));
+ let dav_unsecure_server = config
+ .dav_unsecure
+ .map(|dav_config| dav::new_unsecure(dav_config, login.clone()));
+ let dav_server = config
+ .dav
+ .map(|dav_config| dav::new(dav_config, login.clone()))
+ .transpose()?;
+
+ Ok(Self {
+ lmtp_server,
+ imap_unsecure_server,
+ imap_server,
+ dav_unsecure_server,
+ dav_server,
+ auth_server,
+ pid_file: config.pid,
+ })
+ }
+
+ pub async fn run(self) -> Result<()> {
+ let pid = std::process::id();
+ tracing::info!(pid = pid, "Starting main loops");
+
+ // write the pid file
+ if let Some(pid_file) = self.pid_file {
+ let mut file = std::fs::OpenOptions::new()
+ .write(true)
+ .create(true)
+ .truncate(true)
+ .open(pid_file)?;
+ file.write_all(pid.to_string().as_bytes())?;
+ drop(file);
+ }
+
+ let (exit_signal, provoke_exit) = watch_ctrl_c();
+ let _exit_on_err = move |err: anyhow::Error| {
+ error!("Error: {}", err);
+ let _ = provoke_exit.send(true);
+ };
+
+ try_join!(
+ async {
+ match self.lmtp_server.as_ref() {
+ None => Ok(()),
+ Some(s) => s.run(exit_signal.clone()).await,
+ }
+ },
+ async {
+ match self.imap_unsecure_server {
+ None => Ok(()),
+ Some(s) => s.run(exit_signal.clone()).await,
+ }
+ },
+ async {
+ match self.imap_server {
+ None => Ok(()),
+ Some(s) => s.run(exit_signal.clone()).await,
+ }
+ },
+ async {
+ match self.auth_server {
+ None => Ok(()),
+ Some(a) => a.run(exit_signal.clone()).await,
+ }
+ },
+ async {
+ match self.dav_unsecure_server {
+ None => Ok(()),
+ Some(s) => s.run(exit_signal.clone()).await,
+ }
+ },
+ async {
+ match self.dav_server {
+ None => Ok(()),
+ Some(s) => s.run(exit_signal.clone()).await,
+ }
+ }
+ )?;
+
+ 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)
+}