add check every so other

This commit is contained in:
Love 2024-07-25 20:32:52 +02:00
parent 8e5d472018
commit b6f447e39f
4 changed files with 76 additions and 41 deletions

View File

@ -1,5 +1,6 @@
// SPDX: BSD-2-Clause // SPDX: BSD-2-Clause
use crate::utils::duration_to_string;
use anyhow; use anyhow;
use dirs; use dirs;
use log::warn; use log::warn;
@ -81,40 +82,10 @@ mod duration_format {
where where
S: Serializer, S: Serializer,
{ {
let duration = if let Some(aux) = duration.as_ref() { match duration.as_ref() {
aux Some(duration) => serializer.serialize_str(duration_to_string(duration).trim()),
} else { None => serializer.serialize_none(),
return serializer.serialize_none();
};
let mut secs = duration.as_secs();
let nanos = duration.subsec_nanos();
let days = secs / 86400;
secs %= 86400;
let hours = secs / 3600;
secs %= 3600;
let minutes = secs / 60;
secs %= 60;
let mut formatted = String::new();
if days > 0 {
formatted.push_str(&format!("{}d ", days));
} }
if hours > 0 {
formatted.push_str(&format!("{}h ", hours));
}
if minutes > 0 {
formatted.push_str(&format!("{}m ", minutes));
}
if secs > 0 {
formatted.push_str(&format!("{}s ", secs));
}
if nanos > 0 {
formatted.push_str(&format!("{}ns", nanos));
}
serializer.serialize_str(formatted.trim())
} }
pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<Duration>, D::Error> pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<Duration>, D::Error>

View File

@ -1,5 +1,6 @@
// SPDX: BSD-2-Clause // SPDX: BSD-2-Clause
use futures::future::{self, Either};
use std::sync::{ use std::sync::{
atomic::{AtomicBool, Ordering}, atomic::{AtomicBool, Ordering},
Arc, Arc,
@ -10,9 +11,12 @@ use log::{error, info};
use netlink_sys::{AsyncSocket, SocketAddr}; use netlink_sys::{AsyncSocket, SocketAddr};
use rtnetlink::new_connection; use rtnetlink::new_connection;
use dynip_cloudflare::{utils, CloudflareClient, MessageHandler, MAX_ERORS_IN_ROW_DEFAULT}; use dynip_cloudflare::{
utils::{self, duration_to_string},
CloudflareClient, MessageHandler, MAX_ERORS_IN_ROW_DEFAULT,
};
use scopeguard::defer; use scopeguard::defer;
use tokio::{signal, sync::Notify}; use tokio::{signal, sync::Notify, time};
const RTNLGRP_LINK: u32 = 1; const RTNLGRP_LINK: u32 = 1;
const RTNLGRP_IPV4_IFADDR: u32 = 5; const RTNLGRP_IPV4_IFADDR: u32 = 5;
@ -81,11 +85,32 @@ async fn main() {
config.max_errors_in_row.unwrap_or(MAX_ERORS_IN_ROW_DEFAULT), config.max_errors_in_row.unwrap_or(MAX_ERORS_IN_ROW_DEFAULT),
); );
let mut interval = config.max_duration.map(|duration| {
let mut interval = time::interval(duration);
interval.set_missed_tick_behavior(time::MissedTickBehavior::Delay);
interval
});
while !should_exit.load(Ordering::SeqCst) { while !should_exit.load(Ordering::SeqCst) {
let tick_future = match interval.as_mut() {
Some(interval) => Either::Left(interval.tick()),
None => Either::Right(future::pending::<tokio::time::Instant>()),
};
tokio::select! { tokio::select! {
_ = notify.notified() => break, _ = notify.notified() => break,
_ = tick_future => {
if let Some(duration) = config.max_duration.as_ref() {
let duration_string = duration_to_string(duration);
let log_string = format!("{} has passed since last check, checking...", duration_string.trim());
message_handler.log_and_check(Some(&log_string), Option::<&&str>::None).await;
}
}
message = messages.next() => { message = messages.next() => {
if let Some((message, _)) = message { if let Some((message, _)) = message {
if let Some(interval) = interval.as_mut() {
interval.reset();
}
message_handler.handle_message(message).await; message_handler.handle_message(message).await;
} }
} }

View File

@ -1,7 +1,6 @@
// SPDX: BSD-2-Clause // SPDX: BSD-2-Clause
use std::fmt; use std::fmt;
use log::{debug, error, info}; use log::{debug, error, info};
use netlink_packet_core::{NetlinkMessage, NetlinkPayload}; use netlink_packet_core::{NetlinkMessage, NetlinkPayload};
use netlink_packet_route::RouteNetlinkMessage as RtnlMessage; use netlink_packet_route::RouteNetlinkMessage as RtnlMessage;
@ -34,13 +33,14 @@ where
pub async fn handle_message(&mut self, message: NetlinkMessage<RtnlMessage>) -> Option<()> { pub async fn handle_message(&mut self, message: NetlinkMessage<RtnlMessage>) -> Option<()> {
match message.payload { match message.payload {
NetlinkPayload::InnerMessage(RtnlMessage::NewAddress(msg)) => { NetlinkPayload::InnerMessage(RtnlMessage::NewAddress(msg)) => {
self.log_and_check("New IPv4 address", &msg).await self.log_and_check(Some("New IPv4 address"), Some(&msg))
.await
} }
NetlinkPayload::InnerMessage(RtnlMessage::DelAddress(msg)) => { NetlinkPayload::InnerMessage(RtnlMessage::DelAddress(msg)) => {
self.log_info("Deleted IPv4 address", &msg).await self.log_info("Deleted IPv4 address", &msg).await
} }
NetlinkPayload::InnerMessage(RtnlMessage::NewLink(link)) => { NetlinkPayload::InnerMessage(RtnlMessage::NewLink(link)) => {
self.log_and_check("New link (interface connected)", &link) self.log_and_check(Some("New link (interface connected)"), Some(&link))
.await .await
} }
NetlinkPayload::InnerMessage(RtnlMessage::DelLink(link)) => { NetlinkPayload::InnerMessage(RtnlMessage::DelLink(link)) => {
@ -54,13 +54,21 @@ where
} }
} }
async fn log_and_check<D, M>(&mut self, log_msg: &D, msg: &M) -> Option<()> pub async fn log_and_check<D, M>(&mut self, log_msg: Option<&D>, msg: Option<&M>) -> Option<()>
where where
D: fmt::Display + ?Sized, D: fmt::Display + ?Sized,
M: fmt::Debug, M: fmt::Debug,
{ {
info!("{}", log_msg); if let Some(s) = log_msg {
debug!("{}: {:?}", log_msg, msg); info!("{}", s);
}
if let Some(m) = msg {
if let Some(lm) = log_msg {
debug!("{}: {:?}", lm, m);
} else {
debug!("{:?}", m);
}
}
if let Err(e) = self.cloudflare.check().await { if let Err(e) = self.cloudflare.check().await {
self.errs_counter += 1; self.errs_counter += 1;
error!( error!(

View File

@ -1,5 +1,7 @@
// SPDX: BSD-2-Clause // SPDX: BSD-2-Clause
use std::time::Duration;
use crate::{get_config_path, read_config, Config}; use crate::{get_config_path, read_config, Config};
use log::error; use log::error;
@ -28,3 +30,32 @@ pub async fn get_config() -> Option<Config> {
} }
read_result.ok() read_result.ok()
} }
pub fn duration_to_string(duration: &Duration) -> String {
let mut secs = duration.as_secs();
let nanos = duration.subsec_nanos();
let days = secs / 86400;
secs %= 86400;
let hours = secs / 3600;
secs %= 3600;
let minutes = secs / 60;
secs %= 60;
let mut ret = String::new();
if days > 0 {
ret.push_str(&format!("{}d ", days));
}
if hours > 0 {
ret.push_str(&format!("{}h ", hours));
}
if minutes > 0 {
ret.push_str(&format!("{}m ", minutes));
}
if secs > 0 {
ret.push_str(&format!("{}s ", secs));
}
if nanos > 0 {
ret.push_str(&format!("{}ns", nanos));
}
ret
}