Compare commits
8 Commits
5466090256
...
master
Author | SHA1 | Date | |
---|---|---|---|
64da1e7a2e | |||
60bdb83b6b | |||
1cd57845a1 | |||
787f74e3ec | |||
9b68b32354 | |||
e5c9cb6024 | |||
0cd2d364aa | |||
f34c4609a5 |
108
Cargo.lock
generated
108
Cargo.lock
generated
@ -109,9 +109,9 @@ checksum = "a12916984aab3fa6e39d655a33e09c0071eb36d6ab3aea5c2d78551f1df6d952"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.1.4"
|
version = "1.1.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9711f33475c22aab363b05564a17d7b789bf3dfec5ebabb586adee56f0e271b5"
|
checksum = "2aba8f4e9906c7ce3c73463f62a7f0c65183ada1a2d47e397cc8810827f9694f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
@ -337,7 +337,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.71",
|
"syn 2.0.72",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -705,13 +705,14 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mio"
|
name = "mio"
|
||||||
version = "0.8.11"
|
version = "1.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
|
checksum = "4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"hermit-abi",
|
||||||
"libc",
|
"libc",
|
||||||
"wasi",
|
"wasi",
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -816,21 +817,11 @@ dependencies = [
|
|||||||
"autocfg",
|
"autocfg",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "num_cpus"
|
|
||||||
version = "1.16.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
|
|
||||||
dependencies = [
|
|
||||||
"hermit-abi",
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "object"
|
name = "object"
|
||||||
version = "0.36.1"
|
version = "0.36.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "081b846d1d56ddfc18fdf1a922e4f6e07a11768ea1b92dec44e42b72712ccfce"
|
checksum = "3f203fa8daa7bb185f760ae12bd8e097f63d17041dcdcaf675ac54cdf863170e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
@ -843,9 +834,9 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "openssl"
|
name = "openssl"
|
||||||
version = "0.10.64"
|
version = "0.10.66"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f"
|
checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.6.0",
|
"bitflags 2.6.0",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
@ -864,7 +855,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.71",
|
"syn 2.0.72",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -875,9 +866,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "openssl-sys"
|
name = "openssl-sys"
|
||||||
version = "0.9.102"
|
version = "0.9.103"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2"
|
checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"libc",
|
"libc",
|
||||||
@ -952,7 +943,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.71",
|
"syn 2.0.72",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1029,9 +1020,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_syscall"
|
name = "redox_syscall"
|
||||||
version = "0.5.2"
|
version = "0.5.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd"
|
checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.6.0",
|
"bitflags 2.6.0",
|
||||||
]
|
]
|
||||||
@ -1144,9 +1135,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustls"
|
name = "rustls"
|
||||||
version = "0.23.11"
|
version = "0.23.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4828ea528154ae444e5a642dbb7d5623354030dc9822b83fd9bb79683c7399d0"
|
checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"rustls-pki-types",
|
"rustls-pki-types",
|
||||||
@ -1173,9 +1164,9 @@ checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustls-webpki"
|
name = "rustls-webpki"
|
||||||
version = "0.102.5"
|
version = "0.102.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f9a6fccd794a42c2c105b513a2f62bc3fd8f3ba57a4593677ceb0bd035164d78"
|
checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ring",
|
"ring",
|
||||||
"rustls-pki-types",
|
"rustls-pki-types",
|
||||||
@ -1253,7 +1244,7 @@ checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.71",
|
"syn 2.0.72",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1269,9 +1260,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_spanned"
|
name = "serde_spanned"
|
||||||
version = "0.6.6"
|
version = "0.6.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0"
|
checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
@ -1360,9 +1351,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.71"
|
version = "2.0.72"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b146dcf730474b4bcd16c311627b31ede9ab149045db4d6088b3becaea046462"
|
checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -1410,29 +1401,29 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "1.0.62"
|
version = "1.0.63"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f2675633b1499176c2dff06b0856a27976a8f9d436737b4cf4f312d4d91d8bbb"
|
checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"thiserror-impl",
|
"thiserror-impl",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror-impl"
|
name = "thiserror-impl"
|
||||||
version = "1.0.62"
|
version = "1.0.63"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d20468752b09f49e909e55a5d338caa8bedf615594e9d80bc4c565d30faf798c"
|
checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.71",
|
"syn 2.0.72",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thread-id"
|
name = "thread-id"
|
||||||
version = "4.2.1"
|
version = "4.2.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f0ec81c46e9eb50deaa257be2f148adf052d1fb7701cfd55ccfab2525280b70b"
|
checksum = "cfe8f25bbdd100db7e1d34acf7fd2dc59c4bf8f7483f505eaa7d4f12f76cc0ea"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"winapi",
|
"winapi",
|
||||||
@ -1455,32 +1446,31 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "tokio"
|
||||||
version = "1.38.0"
|
version = "1.39.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a"
|
checksum = "d040ac2b29ab03b09d4129c2f5bbd012a3ac2f79d38ff506a4bf8dd34b0eac8a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"backtrace",
|
"backtrace",
|
||||||
"bytes",
|
"bytes",
|
||||||
"libc",
|
"libc",
|
||||||
"mio",
|
"mio",
|
||||||
"num_cpus",
|
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"signal-hook-registry",
|
"signal-hook-registry",
|
||||||
"socket2",
|
"socket2",
|
||||||
"tokio-macros",
|
"tokio-macros",
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio-macros"
|
name = "tokio-macros"
|
||||||
version = "2.3.0"
|
version = "2.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a"
|
checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.71",
|
"syn 2.0.72",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1519,9 +1509,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml"
|
name = "toml"
|
||||||
version = "0.8.14"
|
version = "0.8.16"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6f49eb2ab21d2f26bd6db7bf383edc527a7ebaee412d17af4d40fdccd442f335"
|
checksum = "81967dd0dd2c1ab0bc3468bd7caecc32b8a4aa47d0c8c695d8c2b2108168d62c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
"serde_spanned",
|
"serde_spanned",
|
||||||
@ -1531,18 +1521,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml_datetime"
|
name = "toml_datetime"
|
||||||
version = "0.6.6"
|
version = "0.6.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf"
|
checksum = "f8fb9f64314842840f1d940ac544da178732128f1c78c21772e876579e0da1db"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml_edit"
|
name = "toml_edit"
|
||||||
version = "0.22.15"
|
version = "0.22.17"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d59a3a72298453f564e2b111fa896f8d07fabb36f51f06d7e875fc5e0b5a3ef1"
|
checksum = "8d9f8729f5aea9562aac1cc0441f5d6de3cff1ee0c5d67293eeca5eb36ee7c16"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"serde",
|
"serde",
|
||||||
@ -1707,7 +1697,7 @@ dependencies = [
|
|||||||
"once_cell",
|
"once_cell",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.71",
|
"syn 2.0.72",
|
||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -1741,7 +1731,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.71",
|
"syn 2.0.72",
|
||||||
"wasm-bindgen-backend",
|
"wasm-bindgen-backend",
|
||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
@ -1934,9 +1924,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winnow"
|
name = "winnow"
|
||||||
version = "0.6.13"
|
version = "0.6.16"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "59b5e5f6c299a3c7890b876a2a587f3115162487e704907d9b6cd29473052ba1"
|
checksum = "b480ae9340fc261e6be3e95a1ba86d54ae3f9171132a73ce8d4bbaf68339507c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
@ -77,4 +77,4 @@ The program handles errors gracefully, with retries and logging of error message
|
|||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
This project is licensed under the MIT License.
|
This project is licensed under the BSD 2-Clause License.
|
||||||
|
43
src/exit_listener.rs
Normal file
43
src/exit_listener.rs
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
use std::sync::{
|
||||||
|
atomic::{AtomicBool, Ordering},
|
||||||
|
Arc,
|
||||||
|
};
|
||||||
|
|
||||||
|
use tokio::{
|
||||||
|
self, signal,
|
||||||
|
sync::{futures::Notified, Notify},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct ExitListener {
|
||||||
|
should_exit: Arc<AtomicBool>,
|
||||||
|
notify: Arc<Notify>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ExitListener {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
let this = Self {
|
||||||
|
should_exit: Arc::new(AtomicBool::new(false)),
|
||||||
|
notify: Arc::new(Notify::new()),
|
||||||
|
};
|
||||||
|
|
||||||
|
let should_exit = this.should_exit.clone();
|
||||||
|
let notify = this.notify.clone();
|
||||||
|
|
||||||
|
tokio::spawn(async move {
|
||||||
|
signal::ctrl_c()
|
||||||
|
.await
|
||||||
|
.expect("Failed to install CTRL+C signal handler");
|
||||||
|
should_exit.store(true, Ordering::SeqCst);
|
||||||
|
notify.notify_one();
|
||||||
|
});
|
||||||
|
this
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn notified(&self) -> Notified<'_> {
|
||||||
|
self.notify.notified()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn should_exit(&self) -> bool {
|
||||||
|
self.should_exit.load(Ordering::SeqCst)
|
||||||
|
}
|
||||||
|
}
|
@ -3,40 +3,14 @@
|
|||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use log::{error, info};
|
use log::{error, info};
|
||||||
use reqwest::Client;
|
use reqwest::Client;
|
||||||
use serde::{self, Deserialize, Serialize};
|
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
|
||||||
fmt,
|
fmt,
|
||||||
net::{IpAddr, Ipv4Addr},
|
net::{IpAddr, Ipv4Addr},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use super::cloudflare_responses::{CloudflareResponse, DnsRecord};
|
||||||
use crate::get_current_public_ipv4;
|
use crate::get_current_public_ipv4;
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
|
||||||
struct DnsRecord {
|
|
||||||
id: String,
|
|
||||||
#[serde(rename = "type")]
|
|
||||||
record_type: Box<str>,
|
|
||||||
name: Box<str>,
|
|
||||||
content: Box<str>,
|
|
||||||
ttl: u32,
|
|
||||||
proxied: bool,
|
|
||||||
locked: bool,
|
|
||||||
zone_id: Box<str>,
|
|
||||||
zone_name: Box<str>,
|
|
||||||
modified_on: Box<str>,
|
|
||||||
created_on: Box<str>,
|
|
||||||
meta: HashMap<Box<str>, serde_json::Value>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
|
||||||
struct CloudflareResponse {
|
|
||||||
success: bool,
|
|
||||||
errors: Vec<HashMap<String, serde_json::Value>>,
|
|
||||||
messages: Vec<HashMap<String, serde_json::Value>>,
|
|
||||||
result: Option<Vec<DnsRecord>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct CloudflareClient<A, Z>
|
pub struct CloudflareClient<A, Z>
|
||||||
where
|
where
|
||||||
A: fmt::Display,
|
A: fmt::Display,
|
27
src/internet/cloudflare_responses.rs
Normal file
27
src/internet/cloudflare_responses.rs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use serde;
|
||||||
|
#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)]
|
||||||
|
pub struct DnsRecord {
|
||||||
|
pub id: Box<str>,
|
||||||
|
#[serde(rename = "type")]
|
||||||
|
pub record_type: Box<str>,
|
||||||
|
pub name: Box<str>,
|
||||||
|
pub content: Box<str>,
|
||||||
|
pub ttl: u32,
|
||||||
|
pub proxied: bool,
|
||||||
|
pub locked: bool,
|
||||||
|
pub zone_id: Box<str>,
|
||||||
|
pub zone_name: Box<str>,
|
||||||
|
pub modified_on: Box<str>,
|
||||||
|
pub created_on: Box<str>,
|
||||||
|
pub meta: HashMap<Box<str>, serde_json::Value>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(serde::Serialize, serde::Deserialize, Debug)]
|
||||||
|
pub struct CloudflareResponse {
|
||||||
|
pub success: bool,
|
||||||
|
pub errors: Box<[HashMap<Box<str>, serde_json::Value>]>,
|
||||||
|
pub messages: Box<[HashMap<Box<str>, serde_json::Value>]>,
|
||||||
|
pub result: Option<Vec<DnsRecord>>,
|
||||||
|
}
|
3
src/internet/mod.rs
Normal file
3
src/internet/mod.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
mod cloudflare;
|
||||||
|
pub mod cloudflare_responses;
|
||||||
|
pub use cloudflare::CloudflareClient;
|
@ -1,17 +1,20 @@
|
|||||||
// SPDX: BSD-2-Clause
|
// SPDX: BSD-2-Clause
|
||||||
|
|
||||||
mod cloudflare;
|
|
||||||
mod config;
|
mod config;
|
||||||
|
mod exit_listener;
|
||||||
|
mod internet;
|
||||||
mod logging;
|
mod logging;
|
||||||
mod message_handler;
|
mod message_handler;
|
||||||
|
mod network_change_listener;
|
||||||
mod public_ip;
|
mod public_ip;
|
||||||
mod tests;
|
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
|
|
||||||
pub use cloudflare::CloudflareClient;
|
|
||||||
pub use config::{get_config_path, read_config, Config};
|
pub use config::{get_config_path, read_config, Config};
|
||||||
|
pub use exit_listener::ExitListener;
|
||||||
|
pub use internet::CloudflareClient;
|
||||||
pub use logging::init_logger;
|
pub use logging::init_logger;
|
||||||
pub use message_handler::MessageHandler;
|
pub use message_handler::MessageHandler;
|
||||||
|
pub use network_change_listener::NetworkChangeListener;
|
||||||
pub use public_ip::get_current_public_ipv4;
|
pub use public_ip::get_current_public_ipv4;
|
||||||
|
|
||||||
pub const PROGRAM_NAME: &'static str = "dynip-cloudflare";
|
pub const PROGRAM_NAME: &'static str = "dynip-cloudflare";
|
||||||
|
81
src/main.rs
81
src/main.rs
@ -1,36 +1,14 @@
|
|||||||
// SPDX: BSD-2-Clause
|
// SPDX: BSD-2-Clause
|
||||||
|
|
||||||
use futures::future::{self, Either};
|
use futures::future::{self, Either};
|
||||||
use std::sync::{
|
|
||||||
atomic::{AtomicBool, Ordering},
|
|
||||||
Arc,
|
|
||||||
};
|
|
||||||
|
|
||||||
use futures::stream::StreamExt;
|
|
||||||
use log::{error, info};
|
use log::{error, info};
|
||||||
use netlink_sys::{AsyncSocket, SocketAddr};
|
use scopeguard::defer;
|
||||||
use rtnetlink::new_connection;
|
use tokio::time;
|
||||||
|
|
||||||
use dynip_cloudflare::{
|
use dynip_cloudflare::{
|
||||||
utils::{self, duration_to_string},
|
utils, CloudflareClient, ExitListener, MessageHandler, NetworkChangeListener,
|
||||||
CloudflareClient, MessageHandler, MAX_ERORS_IN_ROW_DEFAULT,
|
MAX_ERORS_IN_ROW_DEFAULT,
|
||||||
};
|
};
|
||||||
use scopeguard::defer;
|
|
||||||
use tokio::{signal, sync::Notify, time};
|
|
||||||
|
|
||||||
const RTNLGRP_LINK: u32 = 1;
|
|
||||||
const RTNLGRP_IPV4_IFADDR: u32 = 5;
|
|
||||||
|
|
||||||
const fn nl_mgrp(group: u32) -> u32 {
|
|
||||||
if group > 31 {
|
|
||||||
panic!("use netlink_sys::Socket::add_membership() for this group");
|
|
||||||
}
|
|
||||||
if group == 0 {
|
|
||||||
0
|
|
||||||
} else {
|
|
||||||
1 << (group - 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
@ -38,24 +16,11 @@ async fn main() {
|
|||||||
defer! {
|
defer! {
|
||||||
log::logger().flush();
|
log::logger().flush();
|
||||||
}
|
}
|
||||||
let should_exit = Arc::new(AtomicBool::new(false));
|
let exit_listener = ExitListener::new();
|
||||||
let notify = Arc::new(Notify::new());
|
|
||||||
|
|
||||||
let should_exit_clone = should_exit.clone();
|
let config = match utils::get_config().await {
|
||||||
let notify_clone = notify.clone();
|
Some(aux) => aux,
|
||||||
|
None => return,
|
||||||
tokio::spawn(async move {
|
|
||||||
signal::ctrl_c()
|
|
||||||
.await
|
|
||||||
.expect("Failed to install CTRL+C signal handler");
|
|
||||||
should_exit_clone.store(true, Ordering::SeqCst);
|
|
||||||
notify_clone.notify_one();
|
|
||||||
});
|
|
||||||
|
|
||||||
let config = if let Some(aux) = utils::get_config().await {
|
|
||||||
aux
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut cloudflare =
|
let mut cloudflare =
|
||||||
@ -67,18 +32,16 @@ async fn main() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let (mut conn, mut _handle, mut messages) = new_connection().unwrap();
|
let mut network_change_listener = match NetworkChangeListener::new() {
|
||||||
let groups = nl_mgrp(RTNLGRP_LINK) | nl_mgrp(RTNLGRP_IPV4_IFADDR);
|
Some(aux) => {
|
||||||
|
info!("Listening for IPv4 address changes and interface connect/disconnect events...");
|
||||||
let addr = SocketAddr::new(0, groups);
|
aux
|
||||||
|
}
|
||||||
if let Err(e) = conn.socket_mut().socket_mut().bind(&addr) {
|
None => {
|
||||||
error!("Failed to bind to socket: {:?}", &e);
|
error!("Failed to initialize networkchangelistener");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
};
|
||||||
tokio::spawn(conn);
|
|
||||||
info!("Listening for IPv4 address changes and interface connect/disconnect events...");
|
|
||||||
|
|
||||||
let mut message_handler = MessageHandler::new(
|
let mut message_handler = MessageHandler::new(
|
||||||
&mut cloudflare,
|
&mut cloudflare,
|
||||||
@ -91,22 +54,22 @@ async fn main() {
|
|||||||
interval
|
interval
|
||||||
});
|
});
|
||||||
|
|
||||||
while !should_exit.load(Ordering::SeqCst) {
|
while !exit_listener.should_exit() {
|
||||||
let tick_future = match interval.as_mut() {
|
let tick_future = match interval.as_mut() {
|
||||||
Some(interval) => Either::Left(interval.tick()),
|
Some(interval) => Either::Left(interval.tick()),
|
||||||
None => Either::Right(future::pending::<tokio::time::Instant>()),
|
None => Either::Right(future::pending::<tokio::time::Instant>()),
|
||||||
};
|
};
|
||||||
|
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
_ = notify.notified() => break,
|
_ = exit_listener.notified() => break,
|
||||||
_ = tick_future => {
|
_ = tick_future => {
|
||||||
if let Some(duration) = config.max_duration.as_ref() {
|
if let Some(duration) = config.max_duration.as_ref() {
|
||||||
let duration_string = duration_to_string(duration);
|
let duration_string = utils::duration_to_string(duration);
|
||||||
let log_string = format!("{} has passed since last check, checking...", duration_string.trim());
|
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_handler.log_and_check(Some(&log_string), Option::<&&str>::None).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
message = messages.next() => {
|
message = network_change_listener.next_message() => {
|
||||||
if let Some((message, _)) = message {
|
if let Some((message, _)) = message {
|
||||||
if let Some(interval) = interval.as_mut() {
|
if let Some(interval) = interval.as_mut() {
|
||||||
interval.reset();
|
interval.reset();
|
||||||
|
60
src/network_change_listener.rs
Normal file
60
src/network_change_listener.rs
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
use futures::{
|
||||||
|
channel::mpsc::UnboundedReceiver,
|
||||||
|
stream::{Next, StreamExt},
|
||||||
|
};
|
||||||
|
use log::error;
|
||||||
|
use netlink_packet_core::NetlinkMessage;
|
||||||
|
use netlink_packet_route::RouteNetlinkMessage;
|
||||||
|
use netlink_sys::{AsyncSocket, SocketAddr};
|
||||||
|
use rtnetlink::new_connection;
|
||||||
|
use tokio::task::JoinHandle;
|
||||||
|
|
||||||
|
const RTNLGRP_LINK: u32 = 1;
|
||||||
|
const RTNLGRP_IPV4_IFADDR: u32 = 5;
|
||||||
|
|
||||||
|
const fn nl_mgrp(group: u32) -> u32 {
|
||||||
|
if group > 31 {
|
||||||
|
panic!("use netlink_sys::Socket::add_membership() for this group");
|
||||||
|
}
|
||||||
|
if group == 0 {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
1 << (group - 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Messages = UnboundedReceiver<(NetlinkMessage<RouteNetlinkMessage>, SocketAddr)>;
|
||||||
|
pub struct NetworkChangeListener {
|
||||||
|
messages: Messages,
|
||||||
|
thread_handle: JoinHandle<()>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NetworkChangeListener {
|
||||||
|
pub fn new() -> Option<Self> {
|
||||||
|
let (mut conn, mut _handle, messages) = new_connection().ok()?;
|
||||||
|
let groups = nl_mgrp(RTNLGRP_LINK) | nl_mgrp(RTNLGRP_IPV4_IFADDR);
|
||||||
|
|
||||||
|
let addr = SocketAddr::new(0, groups);
|
||||||
|
|
||||||
|
if let Err(e) = conn.socket_mut().socket_mut().bind(&addr) {
|
||||||
|
error!("Failed to bind to socket: {:?}", &e);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let thread_handle = tokio::spawn(conn);
|
||||||
|
Some(Self {
|
||||||
|
messages,
|
||||||
|
thread_handle,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn next_message(&mut self) -> Next<'_, Messages> {
|
||||||
|
self.messages.next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for NetworkChangeListener {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
self.thread_handle.abort();
|
||||||
|
}
|
||||||
|
}
|
@ -1,2 +0,0 @@
|
|||||||
#[cfg(test)]
|
|
||||||
mod config_serialization;
|
|
@ -1,4 +1,4 @@
|
|||||||
use crate::Config;
|
use dynip_cloudflare::Config;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use toml;
|
use toml;
|
||||||
|
|
Reference in New Issue
Block a user