diff --git a/Cargo.lock b/Cargo.lock index 45bd2e6..7ee3832 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -27,15 +27,28 @@ dependencies = [ ] [[package]] -name = "async-std" -version = "0.99.4" +name = "async-macros" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "async-std" +version = "0.99.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "async-macros 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "async-task 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-preview 0.3.0-alpha.18 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-timer 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-io-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-timer 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "kv-log-macro 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -133,6 +146,28 @@ dependencies = [ "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "crossbeam-deque" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "crossbeam-utils" version = "0.6.6" @@ -201,75 +236,32 @@ name = "fuchsia-zircon-sys" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "futures-channel-preview" -version = "0.3.0-alpha.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures-core-preview 0.3.0-alpha.18 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink-preview 0.3.0-alpha.18 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "futures-core-preview" -version = "0.3.0-alpha.18" +version = "0.3.0-alpha.19" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "futures-executor-preview" -version = "0.3.0-alpha.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures-core-preview 0.3.0-alpha.18 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util-preview 0.3.0-alpha.18 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "futures-io-preview" -version = "0.3.0-alpha.18" +version = "0.3.0-alpha.19" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "futures-preview" -version = "0.3.0-alpha.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures-channel-preview 0.3.0-alpha.18 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core-preview 0.3.0-alpha.18 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-executor-preview 0.3.0-alpha.18 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-io-preview 0.3.0-alpha.18 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink-preview 0.3.0-alpha.18 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util-preview 0.3.0-alpha.18 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "futures-sink-preview" -version = "0.3.0-alpha.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures-core-preview 0.3.0-alpha.18 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "futures-timer" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures-preview 0.3.0-alpha.18 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "futures-util-preview" -version = "0.3.0-alpha.18" +version = "0.3.0-alpha.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures-channel-preview 0.3.0-alpha.18 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core-preview 0.3.0-alpha.18 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-io-preview 0.3.0-alpha.18 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink-preview 0.3.0-alpha.18 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -292,6 +284,14 @@ dependencies = [ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "kv-log-macro" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -315,6 +315,14 @@ name = "memchr" version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "memoffset" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "mio" version = "0.6.19" @@ -478,6 +486,32 @@ name = "rustc-demangle" version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "scopeguard" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "slab" version = "0.4.2" @@ -529,13 +563,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "updns" -version = "0.0.4" +version = "0.0.5" dependencies = [ "ace 0.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "async-std 0.99.4 (registry+https://github.com/rust-lang/crates.io-index)", + "async-std 0.99.9 (registry+https://github.com/rust-lang/crates.io-index)", "dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -583,7 +616,8 @@ dependencies = [ "checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" "checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" "checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba" -"checksum async-std 0.99.4 (registry+https://github.com/rust-lang/crates.io-index)" = "95dbe66a9f8c59a70277214f98d39f25fe1f36f20f6e8412a8b33af0272a2c79" +"checksum async-macros 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e421d59b24c1feea2496e409b3e0a8de23e5fc130a2ddc0b012e551f3b272bba" +"checksum async-std 0.99.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e274b0689dffa49d9c128a7bd1a86707b6bc8ea319af0899caae654e221656f4" "checksum async-task 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de6bd58f7b9cc49032559422595c81cbfcf04db2f2133592f70af19e258a1ced" "checksum backtrace 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)" = "1371048253fa3bac6704bfd6bbfc922ee9bdcee8881330d40f308b81cc5adc55" "checksum backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "82a830b4ef2d1124a711c71d263c5abdc710ef8e907bd508c88be475cebc422b" @@ -596,6 +630,8 @@ dependencies = [ "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum constant_time_eq 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "995a44c877f9212528ccc74b21a232f66ad69001e40ede5bcee2ac9ef2657120" "checksum crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c8ec7fcd21571dc78f96cc96243cab8d8f035247c3efd16c687be154c3fa9efa" +"checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" +"checksum crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" "checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" "checksum dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3" "checksum dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b" @@ -604,20 +640,18 @@ dependencies = [ "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" -"checksum futures-channel-preview 0.3.0-alpha.18 (registry+https://github.com/rust-lang/crates.io-index)" = "f477fd0292c4a4ae77044454e7f2b413207942ad405f759bb0b4698b7ace5b12" -"checksum futures-core-preview 0.3.0-alpha.18 (registry+https://github.com/rust-lang/crates.io-index)" = "4a2f26f774b81b3847dcda0c81bd4b6313acfb4f69e5a0390c7cb12c058953e9" -"checksum futures-executor-preview 0.3.0-alpha.18 (registry+https://github.com/rust-lang/crates.io-index)" = "80705612926df8a1bc05f0057e77460e29318801f988bf7d803a734cf54e7528" -"checksum futures-io-preview 0.3.0-alpha.18 (registry+https://github.com/rust-lang/crates.io-index)" = "ee7de0c1c9ed23f9457b0437fec7663ce64d9cc3c906597e714e529377b5ddd1" -"checksum futures-preview 0.3.0-alpha.18 (registry+https://github.com/rust-lang/crates.io-index)" = "efa8f90c4fb2328e381f8adfd4255b4a2b696f77d1c63a3dee6700b564c4e4b5" -"checksum futures-sink-preview 0.3.0-alpha.18 (registry+https://github.com/rust-lang/crates.io-index)" = "e9b65a2481863d1b78e094a07e9c0eed458cc7dc6e72b22b7138b8a67d924859" -"checksum futures-timer 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8f9eb554aa23143abc64ec4d0016f038caf53bb7cbc3d91490835c54edc96550" -"checksum futures-util-preview 0.3.0-alpha.18 (registry+https://github.com/rust-lang/crates.io-index)" = "7df53daff1e98cc024bf2720f3ceb0414d96fbb0a94f3cad3a5c3bf3be1d261c" +"checksum futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "b35b6263fb1ef523c3056565fa67b1d16f0a8604ff12b11b08c25f28a734c60a" +"checksum futures-io-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "f4914ae450db1921a56c91bde97a27846287d062087d4a652efc09bb3a01ebda" +"checksum futures-timer 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "878f1d2fc31355fa02ed2372e741b0c17e58373341e6a122569b4623a14a7d33" +"checksum futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "5ce968633c17e5f97936bd2797b6e38fb56cf16a7422319f7ec2e30d3c470e8d" "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +"checksum kv-log-macro 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c54d9f465d530a752e6ebdc217e081a7a614b48cb200f6f0aee21ba6bc9aabb" "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" "checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba" "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" +"checksum memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce6075db033bbbb7ee5a0bbd3a3186bbae616f57fb001c485c7ff77955f8177f" "checksum mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)" = "83f51996a3ed004ef184e16818edc51fadffe8e7ca68be67f9dee67d84d0ff23" "checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" @@ -637,6 +671,10 @@ dependencies = [ "checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" "checksum rust-argon2 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ca4eaef519b494d1f2848fc602d18816fed808a981aedf4f1f00ceb7c9d32cf" "checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" +"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +"checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" +"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" "checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" "checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f" diff --git a/Cargo.toml b/Cargo.toml index 39de61f..536a3fa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "updns" -version = "0.0.4" +version = "0.0.5" edition = "2018" authors = ["wyhaya "] @@ -19,9 +19,8 @@ keywords = [ [dependencies] ace = "0.0.2" -async-std = "0.99.4" +async-std = "0.99.9" dirs = "2.0.2" lazy_static = "1.4.0" -log = {version = "0.4.8", features = ["release_max_level_info"]} regex = "1.3.1" time = "0.1.42" \ No newline at end of file diff --git a/README.md b/README.md index 00125d6..1948b69 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,7 @@ Command: Option: -c Specify a config file + -w Check the interval of the configuration file ``` ## Config @@ -73,10 +74,12 @@ You can update the config file at any time, updns will listen for file changes ```ini bind 0.0.0.0:53 # Binding address proxy 8.8.8.8:53 # Proxy address +timeout 2000 # Proxy timeout (ms) # Domain matching google.com 1.1.1.1 -^(\w+.)?go+gle.com$ 2.2.2.2 +^\w+.bing.com$ 2.2.2.2 +github.com :: # Import from other file import /other/hosts diff --git a/src/config.rs b/src/config.rs index 5a9b868..66aa8e5 100644 --- a/src/config.rs +++ b/src/config.rs @@ -11,6 +11,7 @@ lazy_static! { static ref REG_IGNORE: Regex = Regex::new(r#"^\s*(#.*)?$"#).unwrap(); static ref REG_BIND: Regex = Regex::new(r#"^\s*bind\s+(?P[^\s#]+)"#).unwrap(); static ref REG_PROXY: Regex = Regex::new(r#"^\s*proxy\s+(?P[^\s#]+)"#).unwrap(); + static ref REG_TIMEOUT: Regex = Regex::new(r#"^\s*timeout\s+(?P[^\s#]+)"#).unwrap(); // todo // The path will also contain '#' and ' ' static ref REG_IMPORT: Regex = Regex::new(r#"^\s*import\s+(?P(.*))$"#).unwrap(); @@ -67,18 +68,11 @@ fn cap_ip_addr(text: &str) -> Option> { return Some(Ok((reg, ip))); } -#[derive(Debug)] -pub struct Config { - path: PathBuf, - file: File, - content: String, -} - #[derive(Debug)] pub struct Invalid { pub line: usize, pub source: String, - pub err: InvalidType, + pub kind: InvalidType, } #[derive(Debug)] @@ -86,9 +80,37 @@ pub enum InvalidType { Regex, SocketAddr, IpAddr, + Timeout, Other, } +impl InvalidType { + pub fn as_str(&self) -> &str { + match self { + InvalidType::SocketAddr => "Cannot parse socket addr", + InvalidType::IpAddr => "Cannot parse ip addr", + InvalidType::Regex => "Cannot parse Regular expression", + InvalidType::Timeout => "Cannot parse timeout", + InvalidType::Other => "Invalid line", + } + } +} + +#[derive(Debug)] +pub struct ParseConfig { + pub bind: Vec, + pub proxy: Vec, + pub hosts: Hosts, + pub timeout: Option, + pub invalid: Vec, +} + +#[derive(Debug)] +pub struct Config { + path: PathBuf, + file: File, +} + impl Config { pub fn new>(path: P) -> io::Result { let path = path.as_ref(); @@ -96,37 +118,39 @@ impl Config { if let Some(dir) = path.parent() { fs::create_dir_all(dir)?; } - let mut file = fs::OpenOptions::new() - .read(true) - .append(true) - .create(true) - .open(path)?; - - let mut content = String::new(); - file.read_to_string(&mut content)?; Ok(Config { - file, - content, + file: fs::OpenOptions::new() + .read(true) + .append(true) + .create(true) + .open(path)?, path: path.to_path_buf(), }) } - pub fn add(&mut self, domain: &str, ip: &str) -> std::io::Result<()> { - if self.content.ends_with("\n") { + fn read_to_string(&mut self) -> io::Result { + let mut content = String::new(); + self.file.read_to_string(&mut content)?; + Ok(content) + } + + pub fn add(&mut self, domain: &str, ip: &str) -> io::Result<()> { + if self.read_to_string()?.ends_with("\n") { writeln!(self.file, "{} {}", domain, ip) } else { writeln!(self.file, "\n{} {}", domain, ip) } } - pub fn parse(&mut self) -> io::Result<(Vec, Vec, Hosts, Vec)> { + pub fn parse(&mut self) -> io::Result { let mut hosts = Hosts::new(); - let mut binds = Vec::new(); + let mut bind = Vec::new(); let mut proxy = Vec::new(); - let mut errors = Vec::new(); + let mut invalid = Vec::new(); + let mut timeout = None; - for (n, line) in self.content.lines().enumerate() { + for (n, line) in self.read_to_string()?.lines().enumerate() { // ignore if REG_IGNORE.is_match(&line) { continue; @@ -135,12 +159,12 @@ impl Config { // bind if let Some(addr) = cap_socket_addr(®_BIND, &line) { match addr { - Ok(addr) => binds.push(addr), - Err(err) => { - errors.push(Invalid { + Ok(addr) => bind.push(addr), + Err(kind) => { + invalid.push(Invalid { line: n + 1, source: line.to_string(), - err, + kind, }); } } @@ -151,17 +175,33 @@ impl Config { if let Some(addr) = cap_socket_addr(®_PROXY, &line) { match addr { Ok(addr) => proxy.push(addr), - Err(err) => { - errors.push(Invalid { + Err(kind) => { + invalid.push(Invalid { line: n + 1, source: line.to_string(), - err, + kind, }); } } continue; } + // timeout + if let Some(cap) = REG_TIMEOUT.captures(&line) { + if let Some(time) = cap.name("val") { + if let Ok(t) = time.as_str().parse::() { + timeout = Some(t); + continue; + } + } + invalid.push(Invalid { + line: n + 1, + source: line.to_string(), + kind: InvalidType::Timeout, + }); + continue; + } + // import if let Some(cap) = REG_IMPORT.captures(&line) { if let Some(m) = cap.name("val") { @@ -173,11 +213,11 @@ impl Config { } } - let (b, p, h, e) = Config::new(p)?.parse()?; - binds.extend(b); - proxy.extend(p); - hosts.extend(h); - errors.extend(e); + let config = Config::new(p)?.parse()?; + bind.extend(config.bind); + proxy.extend(config.proxy); + hosts.extend(config.hosts); + invalid.extend(config.invalid); } else { // todo } @@ -188,54 +228,60 @@ impl Config { if let Some(d) = cap_ip_addr(&line) { match d { Ok((domain, ip)) => hosts.push(domain, ip), - Err(err) => { - errors.push(Invalid { + Err(kind) => { + invalid.push(Invalid { line: n + 1, source: line.to_string(), - err, + kind, }); } } continue; } - errors.push(Invalid { + invalid.push(Invalid { line: n + 1, source: line.to_string(), - err: InvalidType::Other, + kind: InvalidType::Other, }); } - Ok((binds, proxy, hosts, errors)) + Ok(ParseConfig { + bind, + proxy, + hosts, + timeout, + invalid, + }) } } #[derive(Debug)] pub struct Hosts { - list: Vec<(Regex, IpAddr)>, + record: Vec<(Regex, IpAddr)>, } impl Hosts { pub fn new() -> Hosts { - Hosts { list: Vec::new() } + Hosts { record: Vec::new() } } fn push(&mut self, domain: Regex, ip: IpAddr) { - self.list.push((domain, ip)); + self.record.push((domain, ip)); } fn extend(&mut self, hosts: Hosts) { - for item in hosts.list { - self.list.push(item); + for item in hosts.record { + self.record.push(item); } } pub fn iter(&mut self) -> Iter<(Regex, IpAddr)> { - self.list.iter() + self.record.iter() } pub fn get(&self, domain: &str) -> Option<&IpAddr> { - for (reg, ip) in &self.list { + for (reg, ip) in &self.record { if reg.is_match(domain) { return Some(ip); } diff --git a/src/logger.rs b/src/logger.rs deleted file mode 100644 index 48e34e0..0000000 --- a/src/logger.rs +++ /dev/null @@ -1,28 +0,0 @@ -use log::{Level, LevelFilter, Metadata, Record, SetLoggerError}; - -static LOGGER: Logger = Logger; - -pub fn init() -> Result<(), SetLoggerError> { - log::set_logger(&LOGGER).map(|()| log::set_max_level(LevelFilter::Trace)) -} - -struct Logger; - -impl log::Log for Logger { - fn enabled(&self, meta: &Metadata) -> bool { - meta.level() != Level::Trace - } - - fn log(&self, record: &Record) { - if self.enabled(record.metadata()) { - println!( - "{} {}: {}", - time::now().strftime("[%Y-%m-%d][%H:%M:%S]").unwrap(), - record.level(), - record.args() - ); - } - } - - fn flush(&self) {} -} diff --git a/src/main.rs b/src/main.rs index a5ceaab..9f75aa7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,17 +3,15 @@ extern crate lazy_static; mod config; mod lib; -mod logger; mod watch; use ace::App; use async_std::io; use async_std::net::UdpSocket; use async_std::task; -use config::{Config, Hosts, Invalid, InvalidType}; +use config::{Config, Hosts, Invalid, ParseConfig}; use dirs; use lib::*; -use log::{error, info, warn}; use regex::Regex; use std::env; use std::net::{IpAddr, SocketAddr}; @@ -22,13 +20,18 @@ use std::process::Command; use std::time::Duration; use watch::Watch; -const CONFIG_FILE: [&str; 2] = [".updns", "config"]; -const DEFAULT_BIND: &str = "0.0.0.0:53"; -const DEFAULT_PROXY: [&str; 2] = ["8.8.8.8:53", "1.1.1.1:53"]; -const PROXY_TIMEOUT: u64 = 2000; -const WATCH_INTERVAL: u64 = 3000; +const CONFIG_FILE: [&'static str; 2] = [".updns", "config"]; +const CONFIG_COMMAND: &'static str = "vim"; + +const DEFAULT_BIND: &'static str = "0.0.0.0:53"; +const DEFAULT_PROXY: [&'static str; 2] = ["8.8.8.8:53", "1.1.1.1:53"]; +const DEFAULT_TIMEOUT: u64 = 2000; + static mut PROXY: Vec = Vec::new(); static mut HOSTS: Option = None; +static mut TIMEOUT: u64 = DEFAULT_TIMEOUT; + +const WATCH_INTERVAL: u64 = 5000; macro_rules! exit { ($($arg:tt)*) => { @@ -38,18 +41,37 @@ macro_rules! exit { } }; } +macro_rules! error { + ($($arg:tt)*) => { + eprint!("{} ERROR ", time::now().strftime("[%Y-%m-%d %H:%M:%S]").unwrap()); + eprintln!($($arg)*); + }; +} +macro_rules! info { + ($($arg:tt)*) => { + print!("{} INFO ", time::now().strftime("[%Y-%m-%d %H:%M:%S]").unwrap()); + println!($($arg)*); + }; +} +macro_rules! warn { + ($($arg:tt)*) => { + print!("{} WARN ", time::now().strftime("[%Y-%m-%d %H:%M:%S]").unwrap()); + println!($($arg)*); + }; +} fn main() { - let _ = logger::init(); + let cct = format!("Call '{}' to edit the configuration file", CONFIG_COMMAND); let app = App::new(env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION")) .cmd("add", "Add a DNS record") .cmd("rm", "Remove a DNS record") .cmd("ls", "Print all configured DNS records") - .cmd("config", "Call vim to edit the configuration file") + .cmd("config", cct.as_str()) .cmd("path", "Print related directories") .cmd("help", "Print help information") .cmd("version", "Print version information") - .opt("-c", "Specify a config file"); + .opt("-c", "Specify a config file") + .opt("-w", "Check the interval of the configuration file"); let config_path = match app.value("-c") { Some(values) => { @@ -64,6 +86,20 @@ fn main() { }, }; + // Check profile interval + let watch_interval = match app.value("-w") { + Some(values) => { + if values.is_empty() { + exit!("'-w' value: [ms]"); + } + match &values[0].parse::() { + Ok(t) => *t, + Err(_) => exit!("Cannot resolve '{}' to number", &values[0]), + } + } + None => WATCH_INTERVAL, + }; + if let Some(cmd) = app.command() { match cmd.as_str() { "add" => { @@ -103,28 +139,35 @@ fn main() { } } "ls" => { - let (_, _, _, mut hosts) = config_parse(&config_path); + let mut config = config_parse(&config_path); let mut n = 0; - for (reg, _) in hosts.iter() { + for (reg, _) in config.hosts.iter() { if reg.as_str().len() > n { n = reg.as_str().len(); } } - for (domain, ip) in hosts.iter() { + for (domain, ip) in config.hosts.iter() { println!("{:domain$} {}", domain.as_str(), ip, domain = n); } } "config" => { - let cmd = Command::new("vim").arg(&config_path).status(); + let cmd = Command::new(CONFIG_COMMAND).arg(&config_path).status(); match cmd { Ok(status) => { + warn!( + "'{}' exits with a non-zero status code: {:?}", + CONFIG_COMMAND, status + ); if status.success() { config_parse(&config_path); } else { - warn!("Non-zero state exit\n{:?}", status); + warn!( + "'{}' exits with a non-zero status code: {:?}", + CONFIG_COMMAND, status + ); } } - Err(err) => exit!("Call vim command failed\n{:?}", err), + Err(err) => exit!("Call '{}' command failed\n{:?}", CONFIG_COMMAND, err), } } "path" => { @@ -151,32 +194,32 @@ fn main() { return; } - let (_, mut binds, proxy, hosts) = config_parse(&config_path); - if binds.is_empty() { + let mut parse = config_parse(&config_path); + if parse.bind.is_empty() { warn!("Will bind the default address '{}'", DEFAULT_BIND); - binds.push(DEFAULT_BIND.parse().unwrap()); + parse.bind.push(DEFAULT_BIND.parse().unwrap()); } - if proxy.is_empty() { + if parse.proxy.is_empty() { warn!( "Will use the default proxy address '{}'", DEFAULT_PROXY.join(", ") ); } - update_config(proxy, hosts); + update_config(parse.proxy, parse.hosts, parse.timeout); // Run server - for addr in binds { + for addr in parse.bind { task::spawn(run_server(addr.clone())); } // watch config - task::block_on(watch_config(config_path)); + task::block_on(watch_config(config_path, watch_interval)); } -fn ask(tips: &str) -> io::Result { +fn ask(text: &str) -> io::Result { use std::io; use std::io::Write; - io::stdout().write(tips.as_bytes())?; + io::stdout().write(text.as_bytes())?; io::stdout().flush()?; let mut s = String::new(); @@ -185,11 +228,11 @@ fn ask(tips: &str) -> io::Result { match s.to_uppercase().as_str() { "Y\n" => Ok(true), "N\n" => Ok(false), - _ => Ok(ask(&tips)?), + _ => Ok(ask(&text)?), } } -fn update_config(mut proxy: Vec, hosts: Hosts) { +fn update_config(mut proxy: Vec, hosts: Hosts, timeout: Option) { if proxy.is_empty() { proxy = DEFAULT_PROXY .iter() @@ -199,48 +242,48 @@ fn update_config(mut proxy: Vec, hosts: Hosts) { unsafe { PROXY = proxy; HOSTS = Some(hosts); + TIMEOUT = match timeout { + Some(t) => t, + None => DEFAULT_TIMEOUT, + }; }; } -fn config_parse(file: &PathBuf) -> (Config, Vec, Vec, Hosts) { +fn config_parse(file: &PathBuf) -> ParseConfig { let mut config = match Config::new(file) { Ok(c) => c, Err(err) => exit!("Failed to read config file {:?}\n{:?}", file, err), }; - let (binds, proxy, hosts, errors) = match config.parse() { + let parse = match config.parse() { Ok(d) => d, Err(err) => exit!("Parsing config file failed\n{:?}", err), }; - output_invalid(errors); + output_invalid(&parse.invalid); - (config, binds, proxy, hosts) + parse } -fn output_invalid(errors: Vec) { - if !errors.is_empty() { - for invalid in errors { - let msg = match invalid.err { - InvalidType::SocketAddr => "Cannot parse socket addr", - InvalidType::IpAddr => "Cannot parse ip addr", - InvalidType::Regex => "Cannot parse Regular expression", - InvalidType::Other => "Invalid line", - }; - warn!("{}", msg); - info!("Line {}: {}", invalid.line, invalid.source); - } +fn output_invalid(errors: &Vec) { + for invalid in errors { + error!( + "[line:{}] {} `{}`", + invalid.line, + invalid.kind.as_str(), + invalid.source + ); } } -async fn watch_config(p: PathBuf) { - let mut watch = Watch::new(p, WATCH_INTERVAL); +async fn watch_config(p: PathBuf, t: u64) { + let mut watch = Watch::new(p, t); watch .for_each(|c| { info!("Reload the configuration file: {:?}", &c); if let Ok(mut config) = Config::new(c) { - if let Ok((_, proxy, hosts, errors)) = config.parse() { - update_config(proxy, hosts); - output_invalid(errors); + if let Ok(parse) = config.parse() { + update_config(parse.proxy, parse.hosts, parse.timeout); + output_invalid(&parse.invalid); } } }) @@ -261,19 +304,19 @@ async fn run_server(addr: SocketAddr) { let (len, src) = match socket.recv_from(&mut req.buf).await { Ok(r) => r, Err(err) => { - error!("Failed to receive message\n{:?}", err); + error!("Failed to receive message {:?}", err); continue; } }; let res = match handle(req, len).await { Ok(data) => data, Err(err) => { - error!("Processing request failed\n{:?}", err); + error!("Processing request failed {:?}", err); continue; } }; if let Err(err) = socket.send_to(&res, &src).await { - error!("Replying to '{}' failed\n{:?}", &src, err); + error!("Replying to '{}' failed {:?}", &src, err); } } } @@ -284,7 +327,7 @@ async fn proxy(buf: &[u8]) -> io::Result> { for addr in proxy.iter() { let socket = UdpSocket::bind(("0.0.0.0", 0)).await?; - let data = io::timeout(Duration::from_millis(PROXY_TIMEOUT), async { + let data = io::timeout(Duration::from_millis(unsafe { TIMEOUT }), async { socket.send_to(&buf, addr).await?; let mut res = [0; 512]; let len = socket.recv(&mut res).await?; @@ -297,7 +340,7 @@ async fn proxy(buf: &[u8]) -> io::Result> { return Ok(data); } Err(err) => { - error!("Agent request to {}\n{:?}", addr, err); + error!("Agent request to {} {:?}", addr, err); } } } diff --git a/src/watch.rs b/src/watch.rs index c1537d3..45148dc 100644 --- a/src/watch.rs +++ b/src/watch.rs @@ -1,7 +1,7 @@ use async_std::fs; use async_std::io; +use async_std::prelude::*; use async_std::stream; -use async_std::stream::Stream; use async_std::task; use std::path::PathBuf; use std::time::{Duration, SystemTime}; diff --git a/tests/lookup.rs b/tests/lookup.rs new file mode 100644 index 0000000..73d94f4 --- /dev/null +++ b/tests/lookup.rs @@ -0,0 +1,4 @@ +// todo + +#[test] +fn lookup() {}