panorama/daemon/src/main.rs

110 lines
2.6 KiB
Rust
Raw Normal View History

2021-07-30 03:47:53 +00:00
#[macro_use]
extern crate serde;
#[macro_use]
extern crate log;
#[macro_use]
extern crate futures;
mod config;
2021-08-06 02:26:39 +00:00
mod mail;
2021-07-30 03:47:53 +00:00
use anyhow::Result;
use clap::Clap;
2021-08-06 02:26:39 +00:00
use futures::future::{
select,
Either::{Left, Right},
FutureExt,
};
2021-07-30 03:47:53 +00:00
use tokio::sync::oneshot;
2021-08-06 02:26:39 +00:00
use crate::config::{Config, MailAccountConfig, TlsMethod};
2021-07-30 03:47:53 +00:00
type ExitListener = oneshot::Receiver<()>;
/// The panorama daemon runs in the background and communicates with other panorama components over Unix sockets.
#[derive(Debug, Clap)]
struct Options {
// /// Config file path (defaults to XDG)
// #[clap(long = "config", short = 'c')]
// config_file: Option<PathBuf>,
/// Verbose mode (-v, -vv, -vvv, etc)
#[clap(short = 'v', long = "verbose", parse(from_occurrences))]
verbose: usize,
}
#[tokio::main]
async fn main() -> Result<()> {
let opt = Options::parse();
stderrlog::new()
.module(module_path!())
.verbosity(opt.verbose)
.init()
.unwrap();
let (_, mut config_watcher) = config::spawn_config_watcher_system()?;
loop {
let (exit_tx, exit_rx) = oneshot::channel();
let new_config = config_watcher.borrow().clone();
tokio::spawn(run_with_config(new_config, exit_rx));
// wait till the config has changed, then tell the current thread to stop
config_watcher.changed().await?;
let _ = exit_tx.send(());
}
}
async fn run_with_config(config: Config, exit: ExitListener) -> Result<()> {
2021-08-06 02:26:39 +00:00
debug!("new config");
2021-07-30 03:47:53 +00:00
2021-08-06 02:26:39 +00:00
let mut notify_mail_threads = Vec::new();
for (account_name, account) in config.mail_accounts {
let (exit_tx, exit_rx) = oneshot::channel();
tokio::spawn(run_single_mail_account(account_name, account, exit_rx));
notify_mail_threads.push(exit_tx);
}
exit.await?;
for exit_tx in notify_mail_threads {
let _ = exit_tx.send(());
}
Ok(())
}
async fn run_single_mail_account(
account_name: String,
account: MailAccountConfig,
exit: ExitListener,
) -> Result<()> {
debug!("connecting to account {}", account_name);
let imap_cookie = ImapClient::open(
&account.imap.server,
account.imap.port,
matches!(account.imap.tls, TlsMethod::On),
);
pin_mut!(imap_cookie);
pin_mut!(exit);
let (imap, exit) = match select(imap_cookie, exit).await {
Left(res) => res,
Right(_) => return Ok(()),
};
debug!("connected to {}", account.imap.server);
let imap = imap?;
2021-07-30 03:47:53 +00:00
let mut exit = exit.fuse();
2021-08-06 02:26:39 +00:00
2021-07-30 03:47:53 +00:00
loop {
select! {
_ = exit => break,
}
}
2021-08-06 02:26:39 +00:00
debug!("disconnecting from account {}", account_name);
2021-07-30 03:47:53 +00:00
Ok(())
}