feat: detect file changes
This commit is contained in:
Generated
+185
-5
@@ -190,7 +190,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -199,6 +199,15 @@ version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb"
|
||||
|
||||
[[package]]
|
||||
name = "fsevent-sys"
|
||||
version = "4.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.7"
|
||||
@@ -244,6 +253,26 @@ dependencies = [
|
||||
"hashbrown 0.16.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inotify"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd854a95a4ac672fed8c054136039fd32c22cf039ff09ead7280afe920486483"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"inotify-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inotify-sys"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c033f80b2c113cdf91ab7a33faa9cbc014726dcad99880c8609af2a370edf37d"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.18"
|
||||
@@ -261,6 +290,26 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kqueue"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "273c0752728918e0ac4976f2b275b6fefb9ecd400585dec929419f3844cd87b5"
|
||||
dependencies = [
|
||||
"kqueue-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kqueue-sys"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07293a4e297ac234359b510362495713f75ea345d5307140414f20c69ffeb087"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.5.0"
|
||||
@@ -310,8 +359,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "02bd0af71c67b473010cbbc60715ee815645a4dc942899111f494b4b737d6fda"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"wasi",
|
||||
"windows-sys",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -321,19 +371,47 @@ dependencies = [
|
||||
"anyhow",
|
||||
"config",
|
||||
"dotenv",
|
||||
"notify",
|
||||
"serde",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "notify"
|
||||
version = "8.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4d3d07927151ff8575b7087f245456e549fea62edf0ec4e565a5ee50c8402bc3"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"fsevent-sys",
|
||||
"inotify",
|
||||
"kqueue",
|
||||
"libc",
|
||||
"log",
|
||||
"mio",
|
||||
"notify-types",
|
||||
"walkdir",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "notify-types"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42b8cfee0e339a0337359f3c88165702ac6e600dc01c0cc9579a92d62b08477a"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nu-ansi-term"
|
||||
version = "0.50.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
|
||||
dependencies = [
|
||||
"windows-sys",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -498,6 +576,15 @@ dependencies = [
|
||||
"ordered-multimap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "same-file"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.2.0"
|
||||
@@ -611,7 +698,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -657,7 +744,7 @@ dependencies = [
|
||||
"signal-hook-registry",
|
||||
"socket2",
|
||||
"tokio-macros",
|
||||
"windows-sys",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -805,18 +892,46 @@ version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
|
||||
dependencies = [
|
||||
"same-file",
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.1+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
||||
dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.60.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.61.2"
|
||||
@@ -826,6 +941,71 @@ dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.53.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_gnullvm",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnullvm"
|
||||
version = "0.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650"
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "1.0.3"
|
||||
|
||||
@@ -7,6 +7,7 @@ edition = "2024"
|
||||
anyhow = "1.0.103"
|
||||
config = "0.15.25"
|
||||
dotenv = "0.15.0"
|
||||
notify = "8.2.0"
|
||||
serde = { version = "1.0.228", features = ["derive"] }
|
||||
tokio = { version = "1.52.3", features = ["full"] }
|
||||
tracing = "0.1.44"
|
||||
|
||||
+54
-2
@@ -1,9 +1,13 @@
|
||||
use std::{path::Path, sync::Arc, time::Duration};
|
||||
|
||||
use anyhow::{Result, ensure};
|
||||
use notify::{EventKind, INotifyWatcher, Watcher};
|
||||
use serde::Deserialize;
|
||||
use tokio::sync::{RwLock, mpsc};
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[allow(clippy::upper_case_acronyms)]
|
||||
pub enum EntryType {
|
||||
pub enum RecordType {
|
||||
A,
|
||||
AAAA,
|
||||
MX,
|
||||
@@ -12,7 +16,7 @@ pub enum EntryType {
|
||||
#[derive(Deserialize)]
|
||||
pub struct Entry {
|
||||
#[serde(rename = "type")]
|
||||
pub entry_type: EntryType,
|
||||
pub rtype: RecordType,
|
||||
pub name: String,
|
||||
pub address: String,
|
||||
#[serde(skip)]
|
||||
@@ -77,3 +81,51 @@ pub fn load() -> Result<ConfigData> {
|
||||
entries: file_config.entries,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn watch(config: Arc<RwLock<ConfigData>>) -> Result<INotifyWatcher> {
|
||||
let (tx, mut rx) = mpsc::channel(100);
|
||||
let mut watcher = notify::recommended_watcher(move |event| {
|
||||
let _ = tx.blocking_send(event);
|
||||
})?;
|
||||
watcher.configure(notify::Config::default().with_poll_interval(Duration::from_secs(10)))?;
|
||||
watcher.watch(
|
||||
Path::new("nanodns.toml"),
|
||||
notify::RecursiveMode::NonRecursive,
|
||||
)?;
|
||||
|
||||
tokio::spawn(async move {
|
||||
loop {
|
||||
let Some(event) = rx.recv().await else {
|
||||
tracing::info!("watch channel closed");
|
||||
break;
|
||||
};
|
||||
|
||||
match event {
|
||||
Ok(event) => {
|
||||
if let EventKind::Modify(_) = event.kind {
|
||||
let new_config = match load() {
|
||||
Ok(new_config) => new_config,
|
||||
Err(err) => {
|
||||
tracing::error!("Failed to load new config: {err}");
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
tracing::info!("Detected config change");
|
||||
{
|
||||
let mut config = config.write().await;
|
||||
*config = new_config;
|
||||
}
|
||||
tracing::info!("Config change applied");
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
tracing::error!("error in watch channel: {err}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Ok(watcher)
|
||||
}
|
||||
|
||||
+19
-9
@@ -10,11 +10,11 @@ mod ext;
|
||||
mod logging;
|
||||
mod macros;
|
||||
|
||||
use std::{io::Cursor, net::SocketAddr};
|
||||
use std::{io::Cursor, net::SocketAddr, sync::Arc};
|
||||
|
||||
use anyhow::Result;
|
||||
use dotenv::dotenv;
|
||||
use tokio::net::UdpSocket;
|
||||
use tokio::{net::UdpSocket, sync::RwLock};
|
||||
use tracing::{Instrument, Level};
|
||||
|
||||
use crate::{
|
||||
@@ -27,15 +27,18 @@ async fn main() -> Result<()> {
|
||||
dotenv().ok();
|
||||
logging::setup();
|
||||
let config = config::load()?;
|
||||
let port = config.port;
|
||||
let config = Arc::new(RwLock::new(config));
|
||||
let _watcher = config::watch(config.clone())?;
|
||||
|
||||
tracing::info!("start server on port {}", config.port);
|
||||
let sock = UdpSocket::bind(("0.0.0.0", config.port)).await?;
|
||||
tracing::info!("start server on port {}", port);
|
||||
let sock = UdpSocket::bind(("0.0.0.0", port)).await?;
|
||||
let mut buffer = [0u8; 512];
|
||||
|
||||
loop {
|
||||
let (size, addr) = sock.recv_from(&mut buffer).await?;
|
||||
let mut cursor = Cursor::new(&buffer[..size]);
|
||||
let result = handle_datagram(&config, &sock, &addr, &mut cursor).await;
|
||||
let result = handle_datagram(config.clone(), &sock, &addr, &mut cursor).await;
|
||||
if let Err(err) = result {
|
||||
tracing::error!("failed to handle datagram: {err}");
|
||||
}
|
||||
@@ -43,7 +46,7 @@ async fn main() -> Result<()> {
|
||||
}
|
||||
|
||||
async fn handle_datagram(
|
||||
config: &config::ConfigData,
|
||||
config: Arc<RwLock<config::ConfigData>>,
|
||||
sock: &UdpSocket,
|
||||
addr: &SocketAddr,
|
||||
cursor: &mut Cursor<&[u8]>,
|
||||
@@ -80,7 +83,7 @@ async fn handle_datagram(
|
||||
|
||||
match question.qtype {
|
||||
RECORD_TYPE_A => {
|
||||
handle_type_a_question(config, &question, &mut response);
|
||||
handle_type_a_question(config.clone(), &question, &mut response).await;
|
||||
}
|
||||
qt => {
|
||||
tracing::error!("unsupported question type, requested: {qt}");
|
||||
@@ -100,8 +103,15 @@ async fn handle_datagram(
|
||||
result
|
||||
}
|
||||
|
||||
fn handle_type_a_question(config: &ConfigData, question: &Question, response: &mut Message) {
|
||||
let address = config.get_ipv4_address_by_domain(&question.domain);
|
||||
async fn handle_type_a_question(
|
||||
config: Arc<RwLock<ConfigData>>,
|
||||
question: &Question,
|
||||
response: &mut Message,
|
||||
) {
|
||||
let address = {
|
||||
let config = config.read().await;
|
||||
config.get_ipv4_address_by_domain(&question.domain)
|
||||
};
|
||||
match address {
|
||||
Some(address) => {
|
||||
let answer = Answer {
|
||||
|
||||
Reference in New Issue
Block a user