daemon
This commit is contained in:
parent
04bd3e62b6
commit
5a9f847097
9 changed files with 190 additions and 60 deletions
92
Cargo.lock
generated
92
Cargo.lock
generated
|
@ -43,6 +43,19 @@ version = "1.0.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
"time",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "3.0.0-beta.2"
|
||||
|
@ -301,6 +314,25 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.13.0"
|
||||
|
@ -324,15 +356,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "afb2e1c3ee07430c2cf76151675e583e0f19985fa6efae47d6848a3e2c824f85"
|
||||
|
||||
[[package]]
|
||||
name = "panorama-core"
|
||||
name = "panorama-daemon"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
"futures",
|
||||
"inotify",
|
||||
"log",
|
||||
"serde",
|
||||
"stderrlog",
|
||||
"tokio",
|
||||
"toml",
|
||||
"xdg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -482,6 +518,19 @@ version = "1.6.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e"
|
||||
|
||||
[[package]]
|
||||
name = "stderrlog"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "45a53e2eff3e94a019afa6265e8ee04cb05b9d33fe9f5078b14e4e391d155a38"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"chrono",
|
||||
"log",
|
||||
"termcolor",
|
||||
"thread_local",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.10.0"
|
||||
|
@ -517,6 +566,26 @@ dependencies = [
|
|||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.1.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"wasi",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.9.0"
|
||||
|
@ -548,6 +617,15 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.5.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
version = "1.8.0"
|
||||
|
@ -578,6 +656,12 @@ version = "0.9.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.10.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
|
@ -608,3 +692,9 @@ name = "winapi-x86_64-pc-windows-gnu"
|
|||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "xdg"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d089681aa106a86fade1b0128fb5daf07d5867a509ab036d99988dec80429a57"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
[workspace]
|
||||
members = [
|
||||
"core",
|
||||
"daemon",
|
||||
]
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
#[macro_use]
|
||||
extern crate serde;
|
||||
extern crate futures;
|
||||
|
||||
mod config;
|
||||
mod imap;
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
use clap::Clap;
|
||||
use anyhow::Result;
|
||||
|
||||
use crate::config::Config;
|
||||
|
||||
/// Panorama core
|
||||
#[derive(Debug, Clap)]
|
||||
struct Options {
|
||||
/// Config file path (defaults to XDG)
|
||||
#[clap(long = "config", short = 'c')]
|
||||
config_file: Option<PathBuf>,
|
||||
}
|
||||
|
||||
async fn run_with_config(config: Config) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<()> {
|
||||
let opts = Options::parse();
|
||||
println!("{:?}", opts);
|
||||
|
||||
let (tx, mut rx) = watch::channel(());
|
||||
|
||||
loop {
|
||||
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
[package]
|
||||
name = "panorama-core"
|
||||
name = "panorama-daemon"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
|
@ -10,3 +10,7 @@ tokio = { version = "1.9.0", features = ["full"] }
|
|||
clap = "3.0.0-beta.2"
|
||||
futures = "0.3.16"
|
||||
inotify = { version = "0.9.3", features = ["stream"] }
|
||||
xdg = "2.2.0"
|
||||
log = "0.4.14"
|
||||
toml = "0.5.8"
|
||||
stderrlog = "0.5.1"
|
|
@ -1,33 +1,37 @@
|
|||
mod watcher;
|
||||
|
||||
use std::path::{PathBuf, Path};
|
||||
use std::collections::HashMap;
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use anyhow::Result;
|
||||
|
||||
pub use self::watcher::spawn_config_watcher_system;
|
||||
|
||||
/// Configuration
|
||||
#[derive(Default, Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct Config {
|
||||
/// Version of the config to use
|
||||
/// (potentially for migration later?)
|
||||
pub version: String,
|
||||
|
||||
/// Directory to store panorama-related data in
|
||||
pub data_dir: PathBuf,
|
||||
|
||||
/// Mail accounts
|
||||
#[serde(rename = "mail")]
|
||||
pub mail_accounts: HashMap<String, MailAccountConfig>,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub async fn from_file(path: impl AsRef<Path>) -> Result<Self> {
|
||||
let mut file = File::open(path.as_ref())?;
|
||||
let mut contents = Vec::new();
|
||||
file.read_to_end(&mut contents)?;
|
||||
let config = toml::from_slice(&contents)?;
|
||||
Ok(config)
|
||||
}
|
||||
pub async fn from_file(path: impl AsRef<Path>) -> Result<Self> {
|
||||
let mut file = File::open(path.as_ref())?;
|
||||
let mut contents = Vec::new();
|
||||
file.read_to_end(&mut contents)?;
|
||||
let config = toml::from_slice(&contents)?;
|
||||
Ok(config)
|
||||
}
|
||||
}
|
||||
|
||||
/// Configuration for a single mail account
|
||||
|
@ -42,10 +46,13 @@ pub struct MailAccountConfig {
|
|||
pub struct ImapConfig {
|
||||
/// Host of the IMAP server (needs to be hostname for TLS)
|
||||
pub server: String,
|
||||
|
||||
/// Port of the IMAP server
|
||||
pub port: u16,
|
||||
|
||||
/// TLS
|
||||
pub tls: TlsMethod,
|
||||
|
||||
/// Auth
|
||||
#[serde(flatten)]
|
||||
pub auth: ImapAuth,
|
||||
|
@ -57,7 +64,6 @@ pub struct ImapConfig {
|
|||
pub enum ImapAuth {
|
||||
/// Use plain username/password authentication
|
||||
#[serde(rename = "plain")]
|
||||
#[allow(missing_docs)]
|
||||
Plain { username: String, password: String },
|
||||
}
|
||||
|
||||
|
@ -67,10 +73,12 @@ pub enum TlsMethod {
|
|||
/// Perform TLS handshake immediately upon connection
|
||||
#[serde(rename = "on")]
|
||||
On,
|
||||
|
||||
/// Perform TLS handshake after issuing the STARTTLS command
|
||||
#[serde(rename = "starttls")]
|
||||
Starttls,
|
||||
|
||||
/// Don't perform TLS handshake at all (unsecured)
|
||||
#[serde(rename = "off")]
|
||||
Off,
|
||||
}
|
||||
}
|
|
@ -1,9 +1,11 @@
|
|||
use std::fs;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use anyhow::{Result, Context};
|
||||
use anyhow::{Context, Result};
|
||||
use futures::{future::TryFutureExt, stream::StreamExt};
|
||||
use inotify::Inotify;
|
||||
use tokio::{task::JoinHandle, sync::watch};
|
||||
use inotify::{Inotify, WatchMask};
|
||||
use tokio::{sync::watch, task::JoinHandle};
|
||||
use xdg::BaseDirectories;
|
||||
|
||||
use super::Config;
|
||||
|
||||
|
@ -18,19 +20,15 @@ pub fn spawn_config_watcher_system() -> Result<(JoinHandle<()>, ConfigWatcher)>
|
|||
if !config_home.exists() {
|
||||
fs::create_dir_all(&config_home)?;
|
||||
}
|
||||
|
||||
inotify
|
||||
.add_watch(&config_home, WatchMask::CLOSE_WRITE)
|
||||
.context("adding watch for config home")?;
|
||||
// let config_file_path = config_home.join("panorama.toml");
|
||||
// if config_file_path.exists() {
|
||||
// inotify
|
||||
// .add_watch(config_file_path, WatchMask::ALL_EVENTS)
|
||||
// .context("adding watch for config file")?;
|
||||
// }
|
||||
|
||||
debug!("watching {:?}", config_home);
|
||||
let (config_tx, config_update) = watch::channel(Config::default());
|
||||
let handle = tokio::spawn(
|
||||
start_inotify_stream(inotify, config_home, config_tx).unwrap_or_else(report_err),
|
||||
start_inotify_stream(inotify, config_home, config_tx).unwrap_or_else(|_err| todo!()),
|
||||
);
|
||||
Ok((handle, config_update))
|
||||
}
|
1
daemon/src/imap.rs
Normal file
1
daemon/src/imap.rs
Normal file
|
@ -0,0 +1 @@
|
|||
pub struct ImapClient {}
|
66
daemon/src/main.rs
Normal file
66
daemon/src/main.rs
Normal file
|
@ -0,0 +1,66 @@
|
|||
#[macro_use]
|
||||
extern crate serde;
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
#[macro_use]
|
||||
extern crate futures;
|
||||
|
||||
mod config;
|
||||
mod imap;
|
||||
|
||||
use anyhow::Result;
|
||||
use clap::Clap;
|
||||
use futures::future::FutureExt;
|
||||
use tokio::sync::oneshot;
|
||||
|
||||
use crate::config::Config;
|
||||
|
||||
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();
|
||||
println!("{:?}", opt);
|
||||
|
||||
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<()> {
|
||||
println!("run with config: {:?}", config);
|
||||
|
||||
let mut exit = exit.fuse();
|
||||
loop {
|
||||
select! {
|
||||
_ = exit => break,
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
Loading…
Reference in a new issue