diff options
-rw-r--r-- | Cargo.lock | 23 | ||||
-rw-r--r-- | Cargo.toml | 1 | ||||
-rw-r--r-- | src/main.rs | 54 |
3 files changed, 66 insertions, 12 deletions
@@ -552,6 +552,7 @@ dependencies = [ "ntp", "rsdsl_ip_config", "thiserror", + "tokio", "trust-dns-resolver", ] @@ -635,6 +636,15 @@ dependencies = [ ] [[package]] +name = "signal-hook-registry" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +dependencies = [ + "libc", +] + +[[package]] name = "slab" version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -744,11 +754,24 @@ dependencies = [ "mio", "num_cpus", "pin-project-lite", + "signal-hook-registry", "socket2 0.4.9", + "tokio-macros", "windows-sys", ] [[package]] +name = "tokio-macros" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] name = "tracing" version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -11,6 +11,7 @@ nix = { version = "0.26.2", features = ["time"] } ntp = "0.5.0" rsdsl_ip_config = { git = "https://github.com/rsdsl/ip_config.git", version = "0.2.4" } thiserror = "1.0" +tokio = { version = "1.0", features = ["rt", "macros", "time", "fs", "signal"] } trust-dns-resolver = "0.23.0" [build-dependencies] diff --git a/src/main.rs b/src/main.rs index dd0da4d..8619555 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,12 @@ -use std::fs; use std::io; use std::net::{self, IpAddr, SocketAddr}; +use std::num; use std::path::Path; use std::thread; -use std::time::Duration; +use std::time::{self, Duration, SystemTime}; + +use tokio::fs; +use tokio::signal::unix::{signal, SignalKind}; use chrono::DateTime; use nix::sys::time::TimeSpec; @@ -27,6 +30,10 @@ enum Error { Io(#[from] io::Error), #[error("can't parse network address: {0}")] ParseAddr(#[from] net::AddrParseError), + #[error("system time monotonicity error: {0}")] + SystemTime(#[from] time::SystemTimeError), + #[error("integer doesn't fit: {0}")] + TryFromInt(#[from] num::TryFromIntError), #[error("chrono parse: {0}")] ChronoParse(#[from] chrono::ParseError), @@ -40,31 +47,54 @@ enum Error { type Result<T> = std::result::Result<T, Error>; -fn main() -> Result<()> { +#[tokio::main] +async fn main() -> Result<()> { let ds_config = Path::new(rsdsl_ip_config::LOCATION); while !ds_config.exists() { println!("wait for pppoe"); thread::sleep(Duration::from_secs(8)); } + let mut resync = tokio::time::interval(INTERVAL); + let mut sigterm = signal(SignalKind::terminate())?; + loop { - match sync_time(NTP_SERVER) { - Ok(_) => {} - Err(e) => eprintln!("can't synchronize system time: {}", e), + tokio::select! { + _ = resync.tick() => match sync_time(NTP_SERVER).await { + Ok(_) => {} + Err(e) => eprintln!("can't synchronize system time: {}", e), + }, + _ = sigterm.recv() => { + sysnow_to_disk().await?; + + println!("save system time"); + return Ok(()); + } } - - thread::sleep(INTERVAL); } } -fn last_time_unix() -> Option<i64> { +async fn last_time_unix() -> Option<i64> { Some(i64::from_be_bytes( - fs::read("/data/ntp.last_unix").ok()?[..8].try_into().ok()?, + fs::read("/data/ntp.last_unix").await.ok()?[..8] + .try_into() + .ok()?, )) } -fn sync_time(server: &str) -> Result<()> { +async fn sysnow_to_disk() -> Result<()> { + let t: i64 = SystemTime::now() + .duration_since(SystemTime::UNIX_EPOCH)? + .as_secs() + .try_into()?; + fs::write("/data/ntp.last_unix", t.to_be_bytes()).await?; + + Ok(()) +} + +async fn sync_time(server: &str) -> Result<()> { let last = last_time_unix() + .await .unwrap_or(DateTime::parse_from_rfc3339(env!("SOURCE_TIMESTAMP"))?.timestamp()); let dns = DNS_SERVER.parse()?; @@ -80,7 +110,7 @@ fn sync_time(server: &str) -> Result<()> { let timespec = TimeSpec::new(t, 0); nix::time::clock_settime(ClockId::CLOCK_REALTIME, timespec)?; - fs::write("/data/ntp.last_unix", t.to_be_bytes())?; + fs::write("/data/ntp.last_unix", t.to_be_bytes()).await?; println!("set system time"); Ok(()) |