panorama/daemon/src/main.rs

116 lines
2.8 KiB
Rust
Raw Normal View History

2021-07-30 03:47:53 +00:00
#[macro_use]
extern crate serde;
#[macro_use]
2021-08-09 11:50:19 +00:00
extern crate anyhow;
#[macro_use]
2021-07-30 03:47:53 +00:00
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-08-09 11:50:19 +00:00
use panorama_imap::client::ConfigBuilder;
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<()>;
2021-08-09 11:50:19 +00:00
/// The panorama daemon runs in the background and communicates with other
/// panorama components over Unix sockets.
2021-07-30 03:47:53 +00:00
#[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);
2021-08-09 11:50:19 +00:00
// set up the connection
let mut builder = ConfigBuilder::default();
let imap_cookie = builder
.hostname(account.imap.server.clone())
.port(account.imap.port)
2021-08-09 11:50:32 +00:00
.tls(matches!(account.imap.tls, TlsMethod::On))
.open();
2021-08-06 02:26:39 +00:00
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);
2021-08-09 11:50:19 +00:00
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(())
}