mirror of https://github.com/dswd/vpncloud.git
Compare commits
3 Commits
805c4055a0
...
1f94d0deff
Author | SHA1 | Date |
---|---|---|
Dennis Schwerdel | 1f94d0deff | |
Dennis Schwerdel | ed0fdbc366 | |
Dennis Schwerdel | 02ccea326e |
|
@ -9,6 +9,7 @@ This project follows [semantic versioning](http://semver.org).
|
||||||
- [changed] Warning for missing router is now info
|
- [changed] Warning for missing router is now info
|
||||||
- [changed] New warning on claimed addresses in learning mode
|
- [changed] New warning on claimed addresses in learning mode
|
||||||
- [changed] Updated dependencies
|
- [changed] Updated dependencies
|
||||||
|
- [changed] Rewrote argument parsing
|
||||||
- [fixed] Fixed problem that could lead to 100% cpu consumption
|
- [fixed] Fixed problem that could lead to 100% cpu consumption
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
# This file is automatically @generated by Cargo.
|
# This file is automatically @generated by Cargo.
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aho-corasick"
|
name = "ansi_term"
|
||||||
version = "0.7.10"
|
version = "0.11.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -18,6 +18,16 @@ dependencies = [
|
||||||
"url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "atty"
|
||||||
|
version = "0.2.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"hermit-abi 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "base-x"
|
name = "base-x"
|
||||||
version = "0.2.6"
|
version = "0.2.6"
|
||||||
|
@ -53,6 +63,20 @@ name = "cfg-if"
|
||||||
version = "0.1.10"
|
version = "0.1.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap"
|
||||||
|
version = "2.33.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"vec_map 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "daemonize"
|
name = "daemonize"
|
||||||
version = "0.4.1"
|
version = "0.4.1"
|
||||||
|
@ -67,17 +91,6 @@ name = "discard"
|
||||||
version = "1.0.4"
|
version = "1.0.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "docopt"
|
|
||||||
version = "1.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"regex 1.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"serde 1.0.110 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"strsim 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dtoa"
|
name = "dtoa"
|
||||||
version = "0.4.5"
|
version = "0.4.5"
|
||||||
|
@ -98,6 +111,22 @@ dependencies = [
|
||||||
"wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "heck"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hermit-abi"
|
||||||
|
version = "0.1.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "http"
|
name = "http"
|
||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
|
@ -137,10 +166,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "js-sys"
|
name = "js-sys"
|
||||||
version = "0.3.39"
|
version = "0.3.40"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"wasm-bindgen 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
|
"wasm-bindgen 0.2.63 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -171,11 +200,6 @@ name = "matches"
|
||||||
version = "0.1.8"
|
version = "0.1.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "memchr"
|
|
||||||
version = "2.3.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nix"
|
name = "nix"
|
||||||
version = "0.14.1"
|
version = "0.14.1"
|
||||||
|
@ -229,6 +253,30 @@ dependencies = [
|
||||||
"nix 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"nix 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro-error"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro-error-attr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"proc-macro2 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"syn 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro-error-attr"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"syn 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"syn-mid 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro-hack"
|
name = "proc-macro-hack"
|
||||||
version = "0.5.16"
|
version = "0.5.16"
|
||||||
|
@ -292,22 +340,6 @@ name = "redox_syscall"
|
||||||
version = "0.1.56"
|
version = "0.1.56"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "regex"
|
|
||||||
version = "1.3.7"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"aho-corasick 0.7.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"regex-syntax 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "regex-syntax"
|
|
||||||
version = "0.6.17"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "remove_dir_all"
|
name = "remove_dir_all"
|
||||||
version = "0.5.2"
|
version = "0.5.2"
|
||||||
|
@ -326,7 +358,7 @@ dependencies = [
|
||||||
"once_cell 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"once_cell 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"untrusted 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"untrusted 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"web-sys 0.3.39 (registry+https://github.com/rust-lang/crates.io-index)",
|
"web-sys 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -360,9 +392,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.110"
|
version = "1.0.110"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
|
||||||
"serde_derive 1.0.110 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
|
@ -439,7 +468,7 @@ dependencies = [
|
||||||
"stdweb-derive 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"stdweb-derive 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"stdweb-internal-macros 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
"stdweb-internal-macros 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"stdweb-internal-runtime 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"stdweb-internal-runtime 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"wasm-bindgen 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
|
"wasm-bindgen 0.2.63 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -476,9 +505,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strsim"
|
name = "strsim"
|
||||||
version = "0.9.3"
|
version = "0.8.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "structopt"
|
||||||
|
version = "0.3.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"clap 2.33.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"structopt-derive 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "structopt-derive"
|
||||||
|
version = "0.4.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"proc-macro-error 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"proc-macro2 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"syn 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.27"
|
version = "1.0.27"
|
||||||
|
@ -489,6 +540,16 @@ dependencies = [
|
||||||
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn-mid"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"syn 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tempfile"
|
name = "tempfile"
|
||||||
version = "3.1.0"
|
version = "3.1.0"
|
||||||
|
@ -503,11 +564,11 @@ dependencies = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thread_local"
|
name = "textwrap"
|
||||||
version = "1.0.1"
|
version = "0.11.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -561,6 +622,16 @@ dependencies = [
|
||||||
"smallvec 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"smallvec 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-segmentation"
|
||||||
|
version = "1.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-width"
|
||||||
|
version = "0.1.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-xid"
|
name = "unicode-xid"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
|
@ -581,6 +652,11 @@ dependencies = [
|
||||||
"percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "vec_map"
|
||||||
|
version = "0.8.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "version_check"
|
name = "version_check"
|
||||||
version = "0.9.2"
|
version = "0.9.2"
|
||||||
|
@ -597,7 +673,6 @@ version = "1.3.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc 1.0.54 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cc 1.0.54 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"daemonize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"daemonize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"docopt 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"igd 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"igd 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -611,6 +686,7 @@ dependencies = [
|
||||||
"serde_yaml 0.8.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_yaml 0.8.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"signal 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"signal 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"siphasher 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"siphasher 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"structopt 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"time 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
"time 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -623,16 +699,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen"
|
name = "wasm-bindgen"
|
||||||
version = "0.2.62"
|
version = "0.2.63"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"wasm-bindgen-macro 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
|
"wasm-bindgen-macro 0.2.63 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-backend"
|
name = "wasm-bindgen-backend"
|
||||||
version = "0.2.62"
|
version = "0.2.63"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bumpalo 3.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bumpalo 3.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -641,42 +717,42 @@ dependencies = [
|
||||||
"proc-macro2 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
"proc-macro2 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"syn 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
"syn 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"wasm-bindgen-shared 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
|
"wasm-bindgen-shared 0.2.63 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-macro"
|
name = "wasm-bindgen-macro"
|
||||||
version = "0.2.62"
|
version = "0.2.63"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"wasm-bindgen-macro-support 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
|
"wasm-bindgen-macro-support 0.2.63 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-macro-support"
|
name = "wasm-bindgen-macro-support"
|
||||||
version = "0.2.62"
|
version = "0.2.63"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
"proc-macro2 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"syn 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
"syn 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"wasm-bindgen-backend 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
|
"wasm-bindgen-backend 0.2.63 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"wasm-bindgen-shared 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
|
"wasm-bindgen-shared 0.2.63 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-shared"
|
name = "wasm-bindgen-shared"
|
||||||
version = "0.2.62"
|
version = "0.2.63"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "web-sys"
|
name = "web-sys"
|
||||||
version = "0.3.39"
|
version = "0.3.40"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"js-sys 0.3.39 (registry+https://github.com/rust-lang/crates.io-index)",
|
"js-sys 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"wasm-bindgen 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
|
"wasm-bindgen 0.2.63 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -720,8 +796,9 @@ dependencies = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[metadata]
|
[metadata]
|
||||||
"checksum aho-corasick 0.7.10 (registry+https://github.com/rust-lang/crates.io-index)" = "8716408b8bc624ed7f65d223ddb9ac2d044c0547b6fa4b0d554f3a9540496ada"
|
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
|
||||||
"checksum attohttpc 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "baf13118df3e3dce4b5ac930641343b91b656e4e72c8f8325838b01a4b1c9d45"
|
"checksum attohttpc 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "baf13118df3e3dce4b5ac930641343b91b656e4e72c8f8325838b01a4b1c9d45"
|
||||||
|
"checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
||||||
"checksum base-x 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1b20b618342cf9891c292c4f5ac2cde7287cc5c87e87e9c769d617793607dec1"
|
"checksum base-x 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1b20b618342cf9891c292c4f5ac2cde7287cc5c87e87e9c769d617793607dec1"
|
||||||
"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||||
"checksum boxfnonce 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5988cb1d626264ac94100be357308f29ff7cbdd3b36bda27f450a4ee3f713426"
|
"checksum boxfnonce 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5988cb1d626264ac94100be357308f29ff7cbdd3b36bda27f450a4ee3f713426"
|
||||||
|
@ -729,23 +806,24 @@ dependencies = [
|
||||||
"checksum bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "130aac562c0dd69c56b3b1cc8ffd2e17be31d0b6c25b61c96b76231aa23e39e1"
|
"checksum bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "130aac562c0dd69c56b3b1cc8ffd2e17be31d0b6c25b61c96b76231aa23e39e1"
|
||||||
"checksum cc 1.0.54 (registry+https://github.com/rust-lang/crates.io-index)" = "7bbb73db36c1246e9034e307d0fba23f9a2e251faa47ade70c1bd252220c8311"
|
"checksum cc 1.0.54 (registry+https://github.com/rust-lang/crates.io-index)" = "7bbb73db36c1246e9034e307d0fba23f9a2e251faa47ade70c1bd252220c8311"
|
||||||
"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||||
|
"checksum clap 2.33.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bdfa80d47f954d53a35a64987ca1422f495b8d6483c0fe9f7117b36c2a792129"
|
||||||
"checksum daemonize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "70c24513e34f53b640819f0ac9f705b673fcf4006d7aab8778bee72ebfc89815"
|
"checksum daemonize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "70c24513e34f53b640819f0ac9f705b673fcf4006d7aab8778bee72ebfc89815"
|
||||||
"checksum discard 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0"
|
"checksum discard 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0"
|
||||||
"checksum docopt 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f525a586d310c87df72ebcd98009e57f1cc030c8c268305287a476beb653969"
|
|
||||||
"checksum dtoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4358a9e11b9a09cf52383b451b49a169e8d797b68aa02301ff586d70d9661ea3"
|
"checksum dtoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4358a9e11b9a09cf52383b451b49a169e8d797b68aa02301ff586d70d9661ea3"
|
||||||
"checksum fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
"checksum fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||||
"checksum getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb"
|
"checksum getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb"
|
||||||
|
"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
|
||||||
|
"checksum hermit-abi 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "91780f809e750b0a89f5544be56617ff6b1227ee485bcb06ebe10cdf89bd3b71"
|
||||||
"checksum http 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "28d569972648b2c512421b5f2a405ad6ac9666547189d0c5477a3f200f3e02f9"
|
"checksum http 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "28d569972648b2c512421b5f2a405ad6ac9666547189d0c5477a3f200f3e02f9"
|
||||||
"checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9"
|
"checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9"
|
||||||
"checksum igd 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9e8cad093dcfafa3770b737b9d570cf4d44177e90785385716d90322ef60ddc4"
|
"checksum igd 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9e8cad093dcfafa3770b737b9d570cf4d44177e90785385716d90322ef60ddc4"
|
||||||
"checksum itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e"
|
"checksum itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e"
|
||||||
"checksum js-sys 0.3.39 (registry+https://github.com/rust-lang/crates.io-index)" = "fa5a448de267e7358beaf4a5d849518fe9a0c13fce7afd44b06e68550e5562a7"
|
"checksum js-sys 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)" = "ce10c23ad2ea25ceca0093bd3192229da4c5b3c0f2de499c1ecac0d98d452177"
|
||||||
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
"checksum libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)" = "9457b06509d27052635f90d6466700c65095fdf75409b3fbdd903e988b886f49"
|
"checksum libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)" = "9457b06509d27052635f90d6466700c65095fdf75409b3fbdd903e988b886f49"
|
||||||
"checksum linked-hash-map 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8dd5a6d5999d9907cda8ed67bbd137d3af8085216c2ac62de5be860bd41f304a"
|
"checksum linked-hash-map 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8dd5a6d5999d9907cda8ed67bbd137d3af8085216c2ac62de5be860bd41f304a"
|
||||||
"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
|
"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
|
||||||
"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
|
"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
|
||||||
"checksum memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
|
|
||||||
"checksum nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6c722bee1037d430d0f8e687bbdbf222f27cc6e4e68d5caf630857bb2b6dbdce"
|
"checksum nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6c722bee1037d430d0f8e687bbdbf222f27cc6e4e68d5caf630857bb2b6dbdce"
|
||||||
"checksum nix 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dd0eaf8df8bab402257e0a5c17a254e4cc1f72a93588a1ddfb5d356c801aa7cb"
|
"checksum nix 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dd0eaf8df8bab402257e0a5c17a254e4cc1f72a93588a1ddfb5d356c801aa7cb"
|
||||||
"checksum once_cell 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0b631f7e854af39a1739f401cf34a8a013dfe09eac4fa4dba91e9768bd28168d"
|
"checksum once_cell 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0b631f7e854af39a1739f401cf34a8a013dfe09eac4fa4dba91e9768bd28168d"
|
||||||
|
@ -753,6 +831,8 @@ dependencies = [
|
||||||
"checksum pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677"
|
"checksum pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677"
|
||||||
"checksum ppv-lite86 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "237a5ed80e274dbc66f86bd59c1e25edc039660be53194b5fe0a482e0f2612ea"
|
"checksum ppv-lite86 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "237a5ed80e274dbc66f86bd59c1e25edc039660be53194b5fe0a482e0f2612ea"
|
||||||
"checksum privdrop 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "939fa7cbfef9c15c65cf2fb3ed57f3f2a14dca1757a556aa1ba4a7f998b2b479"
|
"checksum privdrop 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "939fa7cbfef9c15c65cf2fb3ed57f3f2a14dca1757a556aa1ba4a7f998b2b479"
|
||||||
|
"checksum proc-macro-error 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "98e9e4b82e0ef281812565ea4751049f1bdcdfccda7d3f459f2e138a40c08678"
|
||||||
|
"checksum proc-macro-error-attr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4f5444ead4e9935abd7f27dc51f7e852a0569ac888096d5ec2499470794e2e53"
|
||||||
"checksum proc-macro-hack 0.5.16 (registry+https://github.com/rust-lang/crates.io-index)" = "7e0456befd48169b9f13ef0f0ad46d492cf9d2dbb918bcf38e01eed4ce3ec5e4"
|
"checksum proc-macro-hack 0.5.16 (registry+https://github.com/rust-lang/crates.io-index)" = "7e0456befd48169b9f13ef0f0ad46d492cf9d2dbb918bcf38e01eed4ce3ec5e4"
|
||||||
"checksum proc-macro2 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "1502d12e458c49a4c9cbff560d0fe0060c252bc29799ed94ca2ed4bb665a0101"
|
"checksum proc-macro2 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "1502d12e458c49a4c9cbff560d0fe0060c252bc29799ed94ca2ed4bb665a0101"
|
||||||
"checksum quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "54a21852a652ad6f610c9510194f398ff6f8692e334fd1145fed931f7fbe44ea"
|
"checksum quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "54a21852a652ad6f610c9510194f398ff6f8692e334fd1145fed931f7fbe44ea"
|
||||||
|
@ -761,8 +841,6 @@ dependencies = [
|
||||||
"checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
|
"checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
|
||||||
"checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
|
"checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
|
||||||
"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
|
"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
|
||||||
"checksum regex 1.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a6020f034922e3194c711b82a627453881bc4682166cabb07134a10c26ba7692"
|
|
||||||
"checksum regex-syntax 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)" = "7fe5bd57d1d7414c6b5ed48563a2c855d995ff777729dcd91c369ec7fea395ae"
|
|
||||||
"checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e"
|
"checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e"
|
||||||
"checksum ring 0.16.13 (registry+https://github.com/rust-lang/crates.io-index)" = "703516ae74571f24b465b4a1431e81e2ad51336cb0ded733a55a1aa3eccac196"
|
"checksum ring 0.16.13 (registry+https://github.com/rust-lang/crates.io-index)" = "703516ae74571f24b465b4a1431e81e2ad51336cb0ded733a55a1aa3eccac196"
|
||||||
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
||||||
|
@ -783,27 +861,33 @@ dependencies = [
|
||||||
"checksum stdweb-derive 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef"
|
"checksum stdweb-derive 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef"
|
||||||
"checksum stdweb-internal-macros 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11"
|
"checksum stdweb-internal-macros 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11"
|
||||||
"checksum stdweb-internal-runtime 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0"
|
"checksum stdweb-internal-runtime 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0"
|
||||||
"checksum strsim 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c"
|
"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
||||||
|
"checksum structopt 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "863246aaf5ddd0d6928dfeb1a9ca65f505599e4e1b399935ef7e75107516b4ef"
|
||||||
|
"checksum structopt-derive 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "d239ca4b13aee7a2142e6795cbd69e457665ff8037aed33b3effdc430d2f927a"
|
||||||
"checksum syn 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "ef781e621ee763a2a40721a8861ec519cb76966aee03bb5d00adb6a31dc1c1de"
|
"checksum syn 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "ef781e621ee763a2a40721a8861ec519cb76966aee03bb5d00adb6a31dc1c1de"
|
||||||
|
"checksum syn-mid 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7be3539f6c128a931cf19dcee741c1af532c7fd387baa739c03dd2e96479338a"
|
||||||
"checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9"
|
"checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9"
|
||||||
"checksum thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
|
"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
|
||||||
"checksum time 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)" = "3a51cadc5b1eec673a685ff7c33192ff7b7603d0b75446fb354939ee615acb15"
|
"checksum time 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)" = "3a51cadc5b1eec673a685ff7c33192ff7b7603d0b75446fb354939ee615acb15"
|
||||||
"checksum time-macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9ae9b6e9f095bc105e183e3cd493d72579be3181ad4004fceb01adbe9eecab2d"
|
"checksum time-macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9ae9b6e9f095bc105e183e3cd493d72579be3181ad4004fceb01adbe9eecab2d"
|
||||||
"checksum time-macros-impl 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e5c3be1edfad6027c69f5491cf4cb310d1a71ecd6af742788c6ff8bced86b8fa"
|
"checksum time-macros-impl 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e5c3be1edfad6027c69f5491cf4cb310d1a71ecd6af742788c6ff8bced86b8fa"
|
||||||
"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
|
"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
|
||||||
"checksum unicode-normalization 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5479532badd04e128284890390c1e876ef7a993d0570b3597ae43dfa1d59afa4"
|
"checksum unicode-normalization 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5479532badd04e128284890390c1e876ef7a993d0570b3597ae43dfa1d59afa4"
|
||||||
|
"checksum unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0"
|
||||||
|
"checksum unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479"
|
||||||
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
|
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
|
||||||
"checksum untrusted 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
|
"checksum untrusted 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
|
||||||
"checksum url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb"
|
"checksum url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb"
|
||||||
|
"checksum vec_map 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
|
||||||
"checksum version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
|
"checksum version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
|
||||||
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
||||||
"checksum wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
|
"checksum wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
|
||||||
"checksum wasm-bindgen 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "e3c7d40d09cdbf0f4895ae58cf57d92e1e57a9dd8ed2e8390514b54a47cc5551"
|
"checksum wasm-bindgen 0.2.63 (registry+https://github.com/rust-lang/crates.io-index)" = "4c2dc4aa152834bc334f506c1a06b866416a8b6697d5c9f75b9a689c8486def0"
|
||||||
"checksum wasm-bindgen-backend 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "c3972e137ebf830900db522d6c8fd74d1900dcfc733462e9a12e942b00b4ac94"
|
"checksum wasm-bindgen-backend 0.2.63 (registry+https://github.com/rust-lang/crates.io-index)" = "ded84f06e0ed21499f6184df0e0cb3494727b0c5da89534e0fcc55c51d812101"
|
||||||
"checksum wasm-bindgen-macro 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "2cd85aa2c579e8892442954685f0d801f9129de24fa2136b2c6a539c76b65776"
|
"checksum wasm-bindgen-macro 0.2.63 (registry+https://github.com/rust-lang/crates.io-index)" = "838e423688dac18d73e31edce74ddfac468e37b1506ad163ffaf0a46f703ffe3"
|
||||||
"checksum wasm-bindgen-macro-support 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "8eb197bd3a47553334907ffd2f16507b4f4f01bbec3ac921a7719e0decdfe72a"
|
"checksum wasm-bindgen-macro-support 0.2.63 (registry+https://github.com/rust-lang/crates.io-index)" = "3156052d8ec77142051a533cdd686cba889537b213f948cd1d20869926e68e92"
|
||||||
"checksum wasm-bindgen-shared 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "a91c2916119c17a8e316507afaaa2dd94b47646048014bbdf6bef098c1bb58ad"
|
"checksum wasm-bindgen-shared 0.2.63 (registry+https://github.com/rust-lang/crates.io-index)" = "c9ba19973a58daf4db6f352eda73dc0e289493cd29fb2632eb172085b6521acd"
|
||||||
"checksum web-sys 0.3.39 (registry+https://github.com/rust-lang/crates.io-index)" = "8bc359e5dd3b46cb9687a051d50a2fdd228e4ba7cf6fcf861a5365c3d671a642"
|
"checksum web-sys 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)" = "7b72fe77fd39e4bd3eaa4412fd299a0be6b3dfe9d2597e2f1c20beb968f41d17"
|
||||||
"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
|
"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
|
||||||
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
|
|
@ -13,7 +13,7 @@ edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
time = "0.2"
|
time = "0.2"
|
||||||
docopt = "^1"
|
structopt = "0.3"
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
serde_derive = "1.0"
|
serde_derive = "1.0"
|
||||||
serde_yaml = "0.8"
|
serde_yaml = "0.8"
|
||||||
|
|
80
src/cloud.rs
80
src/cloud.rs
|
@ -28,7 +28,7 @@ use super::{
|
||||||
traffic::TrafficStats,
|
traffic::TrafficStats,
|
||||||
types::{Error, HeaderMagic, NodeId, Protocol, Range, Table},
|
types::{Error, HeaderMagic, NodeId, Protocol, Range, Table},
|
||||||
udpmessage::{decode, encode, Message},
|
udpmessage::{decode, encode, Message},
|
||||||
util::{resolve, CtrlC, Duration, Time, TimeSource}
|
util::{addr_nice, resolve, CtrlC, Duration, Time, TimeSource}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub type Hash = BuildHasherDefault<FnvHasher>;
|
pub type Hash = BuildHasherDefault<FnvHasher>;
|
||||||
|
@ -73,7 +73,7 @@ impl<TS: TimeSource> PeerList<TS> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for addr in &del {
|
for addr in &del {
|
||||||
info!("Forgot peer: {}", addr);
|
info!("Forgot peer: {}", addr_nice(*addr));
|
||||||
if let Some(data) = self.peers.remove(addr) {
|
if let Some(data) = self.peers.remove(addr) {
|
||||||
self.nodes.remove(&data.node_id);
|
self.nodes.remove(&data.node_id);
|
||||||
self.addresses.remove(addr);
|
self.addresses.remove(addr);
|
||||||
|
@ -113,7 +113,7 @@ impl<TS: TimeSource> PeerList<TS> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn add(&mut self, node_id: NodeId, addr: SocketAddr, peer_timeout: u16) {
|
fn add(&mut self, node_id: NodeId, addr: SocketAddr, peer_timeout: u16) {
|
||||||
if self.nodes.insert(node_id, addr).is_none() {
|
if self.nodes.insert(node_id, addr).is_none() {
|
||||||
info!("New peer: {}", addr);
|
info!("New peer: {}", addr_nice(addr));
|
||||||
let mut alt_addrs = vec![];
|
let mut alt_addrs = vec![];
|
||||||
if let SocketAddr::V6(v6_addr) = addr {
|
if let SocketAddr::V6(v6_addr) = addr {
|
||||||
if let Some(ipv4) = v6_addr.ip().to_ipv4() {
|
if let Some(ipv4) = v6_addr.ip().to_ipv4() {
|
||||||
|
@ -188,7 +188,7 @@ impl<TS: TimeSource> PeerList<TS> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn remove(&mut self, addr: &SocketAddr) {
|
fn remove(&mut self, addr: &SocketAddr) {
|
||||||
if let Some(data) = self.peers.remove(addr) {
|
if let Some(data) = self.peers.remove(addr) {
|
||||||
info!("Removed peer: {}", addr);
|
info!("Removed peer: {}", addr_nice(*addr));
|
||||||
self.nodes.remove(&data.node_id);
|
self.nodes.remove(&data.node_id);
|
||||||
self.addresses.remove(addr);
|
self.addresses.remove(addr);
|
||||||
for addr in data.alt_addrs {
|
for addr in data.alt_addrs {
|
||||||
|
@ -199,10 +199,10 @@ impl<TS: TimeSource> PeerList<TS> {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn write_out<W: Write>(&self, out: &mut W) -> Result<(), io::Error> {
|
fn write_out<W: Write>(&self, out: &mut W) -> Result<(), io::Error> {
|
||||||
writeln!(out, "Peers:")?;
|
writeln!(out, "peers:")?;
|
||||||
let now = TS::now();
|
let now = TS::now();
|
||||||
for (addr, data) in &self.peers {
|
for (addr, data) in &self.peers {
|
||||||
writeln!(out, " - {} (ttl: {} s)", addr, data.timeout - now)?;
|
writeln!(out, " - \"{}\": {{ ttl_secs: {} }}", addr_nice(*addr), data.timeout - now)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -238,6 +238,7 @@ pub struct GenericCloud<D: Device, P: Protocol, T: Table, S: Socket, TS: TimeSou
|
||||||
update_freq: u16,
|
update_freq: u16,
|
||||||
buffer_out: [u8; 64 * 1024],
|
buffer_out: [u8; 64 * 1024],
|
||||||
stats_file: Option<File>,
|
stats_file: Option<File>,
|
||||||
|
statsd_server: Option<String>,
|
||||||
next_housekeep: Time,
|
next_housekeep: Time,
|
||||||
next_stats_out: Time,
|
next_stats_out: Time,
|
||||||
next_beacon: Time,
|
next_beacon: Time,
|
||||||
|
@ -277,6 +278,7 @@ impl<D: Device, P: Protocol, T: Table, S: Socket, TS: TimeSource> GenericCloud<D
|
||||||
next_peerlist: now,
|
next_peerlist: now,
|
||||||
update_freq,
|
update_freq,
|
||||||
stats_file,
|
stats_file,
|
||||||
|
statsd_server: config.statsd_server.clone(),
|
||||||
buffer_out: [0; 64 * 1024],
|
buffer_out: [0; 64 * 1024],
|
||||||
next_housekeep: now,
|
next_housekeep: now,
|
||||||
next_stats_out: now + STATS_INTERVAL,
|
next_stats_out: now + STATS_INTERVAL,
|
||||||
|
@ -516,6 +518,7 @@ impl<D: Device, P: Protocol, T: Table, S: Socket, TS: TimeSource> GenericCloud<D
|
||||||
if self.next_stats_out < now {
|
if self.next_stats_out < now {
|
||||||
// Write out the statistics
|
// Write out the statistics
|
||||||
self.write_out_stats().map_err(|err| Error::File("Failed to write stats file", err))?;
|
self.write_out_stats().map_err(|err| Error::File("Failed to write stats file", err))?;
|
||||||
|
self.send_stats_to_statsd()?;
|
||||||
self.next_stats_out = now + STATS_INTERVAL;
|
self.next_stats_out = now + STATS_INTERVAL;
|
||||||
self.traffic.period(Some(5));
|
self.traffic.period(Some(5));
|
||||||
}
|
}
|
||||||
|
@ -575,7 +578,7 @@ impl<D: Device, P: Protocol, T: Table, S: Socket, TS: TimeSource> GenericCloud<D
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calculates, resets and writes out the statistics to a file
|
/// Writes out the statistics to a file
|
||||||
fn write_out_stats(&mut self) -> Result<(), io::Error> {
|
fn write_out_stats(&mut self) -> Result<(), io::Error> {
|
||||||
if let Some(ref mut f) = self.stats_file {
|
if let Some(ref mut f) = self.stats_file {
|
||||||
debug!("Writing out stats");
|
debug!("Writing out stats");
|
||||||
|
@ -591,6 +594,61 @@ impl<D: Device, P: Protocol, T: Table, S: Socket, TS: TimeSource> GenericCloud<D
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sends the statistics to a statsd endpoint
|
||||||
|
fn send_stats_to_statsd(&mut self) -> Result<(), Error> {
|
||||||
|
if let Some(ref endpoint) = self.statsd_server {
|
||||||
|
let peer_traffic = self.traffic.total_peer_traffic();
|
||||||
|
let payload_traffic = self.traffic.total_payload_traffic();
|
||||||
|
let dropped = &self.traffic.dropped;
|
||||||
|
let msg = format!(
|
||||||
|
"peer_count:{}|g\ntable_entries:{}|g\n\
|
||||||
|
traffic.protocol.inbound.bytes:{}\n\
|
||||||
|
traffic.protocol.inbound.packets:{}\n\
|
||||||
|
traffic.protocol.outbound.bytes:{}\n\
|
||||||
|
traffic.protocol.outbound.packets:{}\n\
|
||||||
|
traffic.payload.inbound.bytes:{}\n\
|
||||||
|
traffic.payload.inbound.packets:{}\n\
|
||||||
|
traffic.payload.outbound.bytes:{}\n\
|
||||||
|
traffic.payload.outbound.packets:{}\n\
|
||||||
|
invalid_protocol_traffic.bytes:{}\n\
|
||||||
|
invalid_protocol_traffic.packets:{}\n\
|
||||||
|
dropped_payload.bytes:{}\n\
|
||||||
|
dropped_payload.packets:{}",
|
||||||
|
self.peers.len(),
|
||||||
|
self.table.len(),
|
||||||
|
peer_traffic.in_bytes,
|
||||||
|
peer_traffic.in_packets,
|
||||||
|
peer_traffic.out_bytes,
|
||||||
|
peer_traffic.out_packets,
|
||||||
|
payload_traffic.in_bytes,
|
||||||
|
payload_traffic.in_packets,
|
||||||
|
payload_traffic.out_bytes,
|
||||||
|
payload_traffic.out_packets,
|
||||||
|
dropped.in_bytes,
|
||||||
|
dropped.in_packets,
|
||||||
|
dropped.out_bytes,
|
||||||
|
dropped.out_packets
|
||||||
|
);
|
||||||
|
let msg_data = msg.as_bytes();
|
||||||
|
let addrs = resolve(endpoint)?;
|
||||||
|
if let Some(addr) = addrs.first() {
|
||||||
|
match self.socket.send(msg_data, *addr) {
|
||||||
|
Ok(written) if written == msg_data.len() => Ok(()),
|
||||||
|
Ok(_) => {
|
||||||
|
Err(Error::Socket(
|
||||||
|
"Sent out truncated packet",
|
||||||
|
io::Error::new(io::ErrorKind::Other, "truncated")
|
||||||
|
))
|
||||||
|
}
|
||||||
|
Err(e) => Err(Error::Socket("IOError when sending", e))
|
||||||
|
}?
|
||||||
|
} else {
|
||||||
|
error!("Failed to resolve statsd server {}", endpoint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Handles payload data coming in from the local network device
|
/// Handles payload data coming in from the local network device
|
||||||
///
|
///
|
||||||
/// This method takes payload data received from the local device and parses it to obtain the
|
/// This method takes payload data received from the local device and parses it to obtain the
|
||||||
|
@ -619,7 +677,7 @@ impl<D: Device, P: Protocol, T: Table, S: Socket, TS: TimeSource> GenericCloud<D
|
||||||
if !self.peers.contains_addr(&addr) {
|
if !self.peers.contains_addr(&addr) {
|
||||||
// If the peer is not actually connected, remove the entry in the table and try
|
// If the peer is not actually connected, remove the entry in the table and try
|
||||||
// to reconnect.
|
// to reconnect.
|
||||||
warn!("Destination for {} not found in peers: {}", dst, addr);
|
warn!("Destination for {} not found in peers: {}", dst, addr_nice(addr));
|
||||||
self.table.remove(&dst);
|
self.table.remove(&dst);
|
||||||
self.connect_sock(addr)?;
|
self.connect_sock(addr)?;
|
||||||
}
|
}
|
||||||
|
@ -631,6 +689,7 @@ impl<D: Device, P: Protocol, T: Table, S: Socket, TS: TimeSource> GenericCloud<D
|
||||||
self.broadcast_msg(&mut msg)?;
|
self.broadcast_msg(&mut msg)?;
|
||||||
} else {
|
} else {
|
||||||
debug!("No destination for {} found, dropping", dst);
|
debug!("No destination for {} found, dropping", dst);
|
||||||
|
self.traffic.count_dropped_payload(end - start);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -714,7 +773,7 @@ impl<D: Device, P: Protocol, T: Table, S: Socket, TS: TimeSource> GenericCloud<D
|
||||||
} else {
|
} else {
|
||||||
self.peers.add(node_id, peer, peer_timeout);
|
self.peers.add(node_id, peer, peer_timeout);
|
||||||
if self.learning && !ranges.is_empty() {
|
if self.learning && !ranges.is_empty() {
|
||||||
warn!("Ignoring claimed addresses received from {} in learning mode.", peer);
|
warn!("Ignoring claimed addresses received from {} in learning mode.", addr_nice(peer));
|
||||||
} else {
|
} else {
|
||||||
for range in ranges {
|
for range in ranges {
|
||||||
self.table.learn(range.base, Some(range.prefix_len), peer);
|
self.table.learn(range.base, Some(range.prefix_len), peer);
|
||||||
|
@ -755,7 +814,8 @@ impl<D: Device, P: Protocol, T: Table, S: Socket, TS: TimeSource> GenericCloud<D
|
||||||
self.traffic.count_in_traffic(src, size);
|
self.traffic.count_in_traffic(src, size);
|
||||||
self.handle_net_message(src, msg)
|
self.handle_net_message(src, msg)
|
||||||
}) {
|
}) {
|
||||||
error!("Error: {}, from: {}", e, src);
|
error!("Error: {}, from: {}", e, addr_nice(src));
|
||||||
|
self.traffic.count_invalid_protocol(size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
117
src/config.rs
117
src/config.rs
|
@ -58,6 +58,7 @@ pub struct Config {
|
||||||
pub daemonize: bool,
|
pub daemonize: bool,
|
||||||
pub pid_file: Option<String>,
|
pub pid_file: Option<String>,
|
||||||
pub stats_file: Option<String>,
|
pub stats_file: Option<String>,
|
||||||
|
pub statsd_server: Option<String>,
|
||||||
pub user: Option<String>,
|
pub user: Option<String>,
|
||||||
pub group: Option<String>
|
pub group: Option<String>
|
||||||
}
|
}
|
||||||
|
@ -87,6 +88,7 @@ impl Default for Config {
|
||||||
daemonize: false,
|
daemonize: false,
|
||||||
pid_file: None,
|
pid_file: None,
|
||||||
stats_file: None,
|
stats_file: None,
|
||||||
|
statsd_server: None,
|
||||||
user: None,
|
user: None,
|
||||||
group: None
|
group: None
|
||||||
}
|
}
|
||||||
|
@ -163,6 +165,9 @@ impl Config {
|
||||||
if let Some(val) = file.stats_file {
|
if let Some(val) = file.stats_file {
|
||||||
self.stats_file = Some(val);
|
self.stats_file = Some(val);
|
||||||
}
|
}
|
||||||
|
if let Some(val) = file.statsd_server {
|
||||||
|
self.statsd_server = Some(val);
|
||||||
|
}
|
||||||
if let Some(val) = file.user {
|
if let Some(val) = file.user {
|
||||||
self.user = Some(val);
|
self.user = Some(val);
|
||||||
}
|
}
|
||||||
|
@ -172,76 +177,79 @@ impl Config {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn merge_args(&mut self, mut args: Args) {
|
pub fn merge_args(&mut self, mut args: Args) {
|
||||||
if let Some(val) = args.flag_type {
|
if let Some(val) = args.type_ {
|
||||||
self.device_type = val;
|
self.device_type = val;
|
||||||
}
|
}
|
||||||
if let Some(val) = args.flag_device {
|
if let Some(val) = args.device {
|
||||||
self.device_name = val;
|
self.device_name = val;
|
||||||
}
|
}
|
||||||
if let Some(val) = args.flag_device_path {
|
if let Some(val) = args.device_path {
|
||||||
self.device_path = Some(val);
|
self.device_path = Some(val);
|
||||||
}
|
}
|
||||||
if let Some(val) = args.flag_ifup {
|
if let Some(val) = args.ifup {
|
||||||
self.ifup = Some(val);
|
self.ifup = Some(val);
|
||||||
}
|
}
|
||||||
if let Some(val) = args.flag_ifdown {
|
if let Some(val) = args.ifdown {
|
||||||
self.ifdown = Some(val);
|
self.ifdown = Some(val);
|
||||||
}
|
}
|
||||||
if let Some(val) = args.flag_crypto {
|
if let Some(val) = args.crypto {
|
||||||
self.crypto = val;
|
self.crypto = val;
|
||||||
}
|
}
|
||||||
if let Some(val) = args.flag_shared_key {
|
if let Some(val) = args.key {
|
||||||
self.shared_key = Some(val);
|
self.shared_key = Some(val);
|
||||||
}
|
}
|
||||||
if let Some(val) = args.flag_network_id {
|
if let Some(val) = args.network_id {
|
||||||
warn!("The --network-id argument is deprecated, please use --magic instead.");
|
warn!("The --network-id argument is deprecated, please use --magic instead.");
|
||||||
self.magic = Some(val);
|
self.magic = Some(val);
|
||||||
}
|
}
|
||||||
if let Some(val) = args.flag_magic {
|
if let Some(val) = args.magic {
|
||||||
self.magic = Some(val);
|
self.magic = Some(val);
|
||||||
}
|
}
|
||||||
if let Some(val) = args.flag_listen {
|
if let Some(val) = args.listen {
|
||||||
self.listen = parse_listen(&val);
|
self.listen = parse_listen(&val);
|
||||||
}
|
}
|
||||||
self.peers.append(&mut args.flag_connect);
|
self.peers.append(&mut args.connect);
|
||||||
if let Some(val) = args.flag_peer_timeout {
|
if let Some(val) = args.peer_timeout {
|
||||||
self.peer_timeout = val;
|
self.peer_timeout = val;
|
||||||
}
|
}
|
||||||
if let Some(val) = args.flag_keepalive {
|
if let Some(val) = args.keepalive {
|
||||||
self.keepalive = Some(val);
|
self.keepalive = Some(val);
|
||||||
}
|
}
|
||||||
if let Some(val) = args.flag_beacon_store {
|
if let Some(val) = args.beacon_store {
|
||||||
self.beacon_store = Some(val);
|
self.beacon_store = Some(val);
|
||||||
}
|
}
|
||||||
if let Some(val) = args.flag_beacon_load {
|
if let Some(val) = args.beacon_load {
|
||||||
self.beacon_load = Some(val);
|
self.beacon_load = Some(val);
|
||||||
}
|
}
|
||||||
if let Some(val) = args.flag_beacon_interval {
|
if let Some(val) = args.beacon_interval {
|
||||||
self.beacon_interval = val;
|
self.beacon_interval = val;
|
||||||
}
|
}
|
||||||
if let Some(val) = args.flag_mode {
|
if let Some(val) = args.mode {
|
||||||
self.mode = val;
|
self.mode = val;
|
||||||
}
|
}
|
||||||
if let Some(val) = args.flag_dst_timeout {
|
if let Some(val) = args.dst_timeout {
|
||||||
self.dst_timeout = val;
|
self.dst_timeout = val;
|
||||||
}
|
}
|
||||||
self.subnets.append(&mut args.flag_subnet);
|
self.subnets.append(&mut args.subnets);
|
||||||
if args.flag_no_port_forwarding {
|
if args.no_port_forwarding {
|
||||||
self.port_forwarding = false;
|
self.port_forwarding = false;
|
||||||
}
|
}
|
||||||
if args.flag_daemon {
|
if args.daemon {
|
||||||
self.daemonize = true;
|
self.daemonize = true;
|
||||||
}
|
}
|
||||||
if let Some(val) = args.flag_pid_file {
|
if let Some(val) = args.pid_file {
|
||||||
self.pid_file = Some(val);
|
self.pid_file = Some(val);
|
||||||
}
|
}
|
||||||
if let Some(val) = args.flag_stats_file {
|
if let Some(val) = args.stats_file {
|
||||||
self.stats_file = Some(val);
|
self.stats_file = Some(val);
|
||||||
}
|
}
|
||||||
if let Some(val) = args.flag_user {
|
if let Some(val) = args.statsd_server {
|
||||||
|
self.statsd_server = Some(val);
|
||||||
|
}
|
||||||
|
if let Some(val) = args.user {
|
||||||
self.user = Some(val);
|
self.user = Some(val);
|
||||||
}
|
}
|
||||||
if let Some(val) = args.flag_group {
|
if let Some(val) = args.group {
|
||||||
self.group = Some(val);
|
self.group = Some(val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -298,6 +306,7 @@ pub struct ConfigFile {
|
||||||
pub port_forwarding: Option<bool>,
|
pub port_forwarding: Option<bool>,
|
||||||
pub pid_file: Option<String>,
|
pub pid_file: Option<String>,
|
||||||
pub stats_file: Option<String>,
|
pub stats_file: Option<String>,
|
||||||
|
pub statsd_server: Option<String>,
|
||||||
pub user: Option<String>,
|
pub user: Option<String>,
|
||||||
pub group: Option<String>
|
pub group: Option<String>
|
||||||
}
|
}
|
||||||
|
@ -332,6 +341,7 @@ user: nobody
|
||||||
group: nogroup
|
group: nogroup
|
||||||
pid_file: /run/vpncloud.run
|
pid_file: /run/vpncloud.run
|
||||||
stats_file: /var/log/vpncloud.stats
|
stats_file: /var/log/vpncloud.stats
|
||||||
|
statsd_server: example.com:1234
|
||||||
";
|
";
|
||||||
assert_eq!(serde_yaml::from_str::<ConfigFile>(config_file).unwrap(), ConfigFile {
|
assert_eq!(serde_yaml::from_str::<ConfigFile>(config_file).unwrap(), ConfigFile {
|
||||||
device_type: Some(Type::Tun),
|
device_type: Some(Type::Tun),
|
||||||
|
@ -357,7 +367,8 @@ stats_file: /var/log/vpncloud.stats
|
||||||
user: Some("nobody".to_string()),
|
user: Some("nobody".to_string()),
|
||||||
group: Some("nogroup".to_string()),
|
group: Some("nogroup".to_string()),
|
||||||
pid_file: Some("/run/vpncloud.run".to_string()),
|
pid_file: Some("/run/vpncloud.run".to_string()),
|
||||||
stats_file: Some("/var/log/vpncloud.stats".to_string())
|
stats_file: Some("/var/log/vpncloud.stats".to_string()),
|
||||||
|
statsd_server: Some("example.com:1234".to_string())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -388,7 +399,8 @@ fn config_merge() {
|
||||||
user: Some("nobody".to_string()),
|
user: Some("nobody".to_string()),
|
||||||
group: Some("nogroup".to_string()),
|
group: Some("nogroup".to_string()),
|
||||||
pid_file: Some("/run/vpncloud.run".to_string()),
|
pid_file: Some("/run/vpncloud.run".to_string()),
|
||||||
stats_file: Some("/var/log/vpncloud.stats".to_string())
|
stats_file: Some("/var/log/vpncloud.stats".to_string()),
|
||||||
|
statsd_server: Some("example.com:1234".to_string())
|
||||||
});
|
});
|
||||||
assert_eq!(config, Config {
|
assert_eq!(config, Config {
|
||||||
device_type: Type::Tun,
|
device_type: Type::Tun,
|
||||||
|
@ -414,33 +426,35 @@ fn config_merge() {
|
||||||
group: Some("nogroup".to_string()),
|
group: Some("nogroup".to_string()),
|
||||||
pid_file: Some("/run/vpncloud.run".to_string()),
|
pid_file: Some("/run/vpncloud.run".to_string()),
|
||||||
stats_file: Some("/var/log/vpncloud.stats".to_string()),
|
stats_file: Some("/var/log/vpncloud.stats".to_string()),
|
||||||
|
statsd_server: Some("example.com:1234".to_string()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
config.merge_args(Args {
|
config.merge_args(Args {
|
||||||
flag_type: Some(Type::Tap),
|
type_: Some(Type::Tap),
|
||||||
flag_device: Some("vpncloud0".to_string()),
|
device: Some("vpncloud0".to_string()),
|
||||||
flag_device_path: Some("/dev/null".to_string()),
|
device_path: Some("/dev/null".to_string()),
|
||||||
flag_ifup: Some("ifconfig $IFNAME 10.0.1.2/16 mtu 1400 up".to_string()),
|
ifup: Some("ifconfig $IFNAME 10.0.1.2/16 mtu 1400 up".to_string()),
|
||||||
flag_ifdown: Some("ifconfig $IFNAME down".to_string()),
|
ifdown: Some("ifconfig $IFNAME down".to_string()),
|
||||||
flag_crypto: Some(CryptoMethod::ChaCha20),
|
crypto: Some(CryptoMethod::ChaCha20),
|
||||||
flag_shared_key: Some("anothersecret".to_string()),
|
key: Some("anothersecret".to_string()),
|
||||||
flag_magic: Some("hash:mynet".to_string()),
|
magic: Some("hash:mynet".to_string()),
|
||||||
flag_listen: Some("3211".to_string()),
|
listen: Some("3211".to_string()),
|
||||||
flag_peer_timeout: Some(1801),
|
peer_timeout: Some(1801),
|
||||||
flag_keepalive: Some(850),
|
keepalive: Some(850),
|
||||||
flag_dst_timeout: Some(301),
|
dst_timeout: Some(301),
|
||||||
flag_beacon_store: Some("/run/vpncloud.beacon.out2".to_string()),
|
beacon_store: Some("/run/vpncloud.beacon.out2".to_string()),
|
||||||
flag_beacon_load: Some("/run/vpncloud.beacon.in2".to_string()),
|
beacon_load: Some("/run/vpncloud.beacon.in2".to_string()),
|
||||||
flag_beacon_interval: Some(3600),
|
beacon_interval: Some(3600),
|
||||||
flag_mode: Some(Mode::Switch),
|
mode: Some(Mode::Switch),
|
||||||
flag_subnet: vec![],
|
subnets: vec![],
|
||||||
flag_connect: vec!["another:3210".to_string()],
|
connect: vec!["another:3210".to_string()],
|
||||||
flag_no_port_forwarding: true,
|
no_port_forwarding: true,
|
||||||
flag_daemon: true,
|
daemon: true,
|
||||||
flag_pid_file: Some("/run/vpncloud-mynet.run".to_string()),
|
pid_file: Some("/run/vpncloud-mynet.run".to_string()),
|
||||||
flag_stats_file: Some("/var/log/vpncloud-mynet.stats".to_string()),
|
stats_file: Some("/var/log/vpncloud-mynet.stats".to_string()),
|
||||||
flag_user: Some("root".to_string()),
|
statsd_server: Some("example.com:2345".to_string()),
|
||||||
flag_group: Some("root".to_string()),
|
user: Some("root".to_string()),
|
||||||
|
group: Some("root".to_string()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
assert_eq!(config, Config {
|
assert_eq!(config, Config {
|
||||||
|
@ -471,6 +485,7 @@ fn config_merge() {
|
||||||
group: Some("root".to_string()),
|
group: Some("root".to_string()),
|
||||||
pid_file: Some("/run/vpncloud-mynet.run".to_string()),
|
pid_file: Some("/run/vpncloud-mynet.run".to_string()),
|
||||||
stats_file: Some("/var/log/vpncloud-mynet.stats".to_string()),
|
stats_file: Some("/var/log/vpncloud-mynet.stats".to_string()),
|
||||||
|
statsd_server: Some("example.com:2345".to_string()),
|
||||||
daemonize: true
|
daemonize: true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
// Copyright (C) 2015-2020 Dennis Schwerdel
|
// Copyright (C) 2015-2020 Dennis Schwerdel
|
||||||
// This software is licensed under GPL-3 or newer (see LICENSE.md)
|
// This software is licensed under GPL-3 or newer (see LICENSE.md)
|
||||||
|
|
||||||
use std::num::NonZeroU32;
|
use std::{num::NonZeroU32, str::FromStr};
|
||||||
|
|
||||||
use ring::{aead::*, pbkdf2, rand::*};
|
use ring::{aead::*, pbkdf2, rand::*};
|
||||||
|
|
||||||
|
@ -19,6 +19,17 @@ pub enum CryptoMethod {
|
||||||
#[serde(rename = "aes256")]
|
#[serde(rename = "aes256")]
|
||||||
AES256
|
AES256
|
||||||
}
|
}
|
||||||
|
impl FromStr for CryptoMethod {
|
||||||
|
type Err = &'static str;
|
||||||
|
|
||||||
|
fn from_str(text: &str) -> Result<Self, Self::Err> {
|
||||||
|
Ok(match &text.to_lowercase() as &str {
|
||||||
|
"chacha20" | "chacha" => Self::ChaCha20,
|
||||||
|
"aes256" | "aes" => Self::AES256,
|
||||||
|
_ => return Err("Unknown method")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct CryptoData {
|
pub struct CryptoData {
|
||||||
crypto_key: LessSafeKey,
|
crypto_key: LessSafeKey,
|
||||||
|
|
|
@ -6,7 +6,8 @@ use std::{
|
||||||
collections::VecDeque,
|
collections::VecDeque,
|
||||||
fmt, fs,
|
fmt, fs,
|
||||||
io::{self, Error as IoError, ErrorKind, Read, Write},
|
io::{self, Error as IoError, ErrorKind, Read, Write},
|
||||||
os::unix::io::{AsRawFd, RawFd}
|
os::unix::io::{AsRawFd, RawFd},
|
||||||
|
str::FromStr
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::types::Error;
|
use super::types::Error;
|
||||||
|
@ -23,7 +24,7 @@ pub enum Type {
|
||||||
/// Tun interface: This interface transports IP packets.
|
/// Tun interface: This interface transports IP packets.
|
||||||
#[serde(rename = "tun")]
|
#[serde(rename = "tun")]
|
||||||
Tun,
|
Tun,
|
||||||
/// Tap interface: This insterface transports Ethernet frames.
|
/// Tap interface: This interface transports Ethernet frames.
|
||||||
#[serde(rename = "tap")]
|
#[serde(rename = "tap")]
|
||||||
Tap,
|
Tap,
|
||||||
/// Dummy interface: This interface does nothing.
|
/// Dummy interface: This interface does nothing.
|
||||||
|
@ -41,6 +42,18 @@ impl fmt::Display for Type {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl FromStr for Type {
|
||||||
|
type Err = &'static str;
|
||||||
|
|
||||||
|
fn from_str(text: &str) -> Result<Self, Self::Err> {
|
||||||
|
Ok(match &text.to_lowercase() as &str {
|
||||||
|
"tun" => Self::Tun,
|
||||||
|
"tap" => Self::Tap,
|
||||||
|
"dummy" => Self::Dummy,
|
||||||
|
_ => return Err("Unknown device type")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait Device: AsRawFd {
|
pub trait Device: AsRawFd {
|
||||||
/// Returns the type of this device
|
/// Returns the type of this device
|
||||||
|
|
|
@ -14,7 +14,7 @@ use fnv::FnvHasher;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
types::{Address, Error, Protocol, Table},
|
types::{Address, Error, Protocol, Table},
|
||||||
util::{Duration, Time, TimeSource}
|
util::{addr_nice, Duration, Time, TimeSource}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// An ethernet frame dissector
|
/// An ethernet frame dissector
|
||||||
|
@ -110,9 +110,15 @@ impl<TS: TimeSource> Table for SwitchTable<TS> {
|
||||||
/// Write out the table
|
/// Write out the table
|
||||||
fn write_out<W: Write>(&self, out: &mut W) -> Result<(), io::Error> {
|
fn write_out<W: Write>(&self, out: &mut W) -> Result<(), io::Error> {
|
||||||
let now = TS::now();
|
let now = TS::now();
|
||||||
writeln!(out, "Switch table:")?;
|
writeln!(out, "switch_table:")?;
|
||||||
for (addr, val) in &self.table {
|
for (addr, val) in &self.table {
|
||||||
writeln!(out, " - {} => {} (ttl: {} s)", addr, val.address, val.timeout - now)?;
|
writeln!(
|
||||||
|
out,
|
||||||
|
" - \"{}\": {{ peer: \"{}\", ttl_secs: {} }}",
|
||||||
|
addr,
|
||||||
|
addr_nice(val.address),
|
||||||
|
val.timeout - now
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -124,7 +130,7 @@ impl<TS: TimeSource> Table for SwitchTable<TS> {
|
||||||
match self.table.entry(key) {
|
match self.table.entry(key) {
|
||||||
Entry::Vacant(entry) => {
|
Entry::Vacant(entry) => {
|
||||||
entry.insert(SwitchTableValue { address: addr, timeout: deadline });
|
entry.insert(SwitchTableValue { address: addr, timeout: deadline });
|
||||||
info!("Learned address {} => {}", key, addr);
|
info!("Learned address {} => {}", key, addr_nice(addr));
|
||||||
}
|
}
|
||||||
Entry::Occupied(mut entry) => {
|
Entry::Occupied(mut entry) => {
|
||||||
let mut entry = entry.get_mut();
|
let mut entry = entry.get_mut();
|
||||||
|
@ -165,6 +171,10 @@ impl<TS: TimeSource> Table for SwitchTable<TS> {
|
||||||
self.table.remove(&key);
|
self.table.remove(&key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn len(&self) -> usize {
|
||||||
|
self.table.len()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
21
src/ip.rs
21
src/ip.rs
|
@ -11,7 +11,10 @@ use std::{
|
||||||
|
|
||||||
use fnv::FnvHasher;
|
use fnv::FnvHasher;
|
||||||
|
|
||||||
use super::types::{Address, Error, Protocol, Table};
|
use super::{
|
||||||
|
types::{Address, Error, Protocol, Table},
|
||||||
|
util::addr_nice
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/// An IP packet dissector
|
/// An IP packet dissector
|
||||||
|
@ -85,7 +88,7 @@ impl Table for RoutingTable {
|
||||||
Some(val) => val,
|
Some(val) => val,
|
||||||
None => addr.len * 8
|
None => addr.len * 8
|
||||||
};
|
};
|
||||||
info!("New routing entry: {}/{} => {}", addr, prefix_len, address);
|
info!("New routing entry: {}/{} => {}", addr, prefix_len, addr_nice(address));
|
||||||
// Round the prefix length down to the next multiple of 8 and extraxt a prefix of that
|
// Round the prefix length down to the next multiple of 8 and extraxt a prefix of that
|
||||||
// length.
|
// length.
|
||||||
let group_len = prefix_len as usize / 8;
|
let group_len = prefix_len as usize / 8;
|
||||||
|
@ -153,10 +156,16 @@ impl Table for RoutingTable {
|
||||||
|
|
||||||
/// Write out the table
|
/// Write out the table
|
||||||
fn write_out<W: Write>(&self, out: &mut W) -> Result<(), io::Error> {
|
fn write_out<W: Write>(&self, out: &mut W) -> Result<(), io::Error> {
|
||||||
writeln!(out, "Routing table:")?;
|
writeln!(out, "routing_table:")?;
|
||||||
for entries in self.0.values() {
|
for entries in self.0.values() {
|
||||||
for entry in entries {
|
for entry in entries {
|
||||||
writeln!(out, " - {}/{} => {}", entry.bytes, entry.prefix_len, entry.address)?;
|
writeln!(
|
||||||
|
out,
|
||||||
|
" - \"{}/{}\": {{ peer: \"{}\" }}",
|
||||||
|
entry.bytes,
|
||||||
|
entry.prefix_len,
|
||||||
|
addr_nice(entry.address)
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -175,6 +184,10 @@ impl Table for RoutingTable {
|
||||||
entry.retain(|entr| &entr.address != addr);
|
entry.retain(|entr| &entr.address != addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn len(&self) -> usize {
|
||||||
|
self.0.len()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
172
src/main.rs
172
src/main.rs
|
@ -30,7 +30,7 @@ pub mod traffic;
|
||||||
pub mod types;
|
pub mod types;
|
||||||
pub mod udpmessage;
|
pub mod udpmessage;
|
||||||
|
|
||||||
use docopt::Docopt;
|
use structopt::StructOpt;
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
fs::{self, File, Permissions},
|
fs::{self, File, Permissions},
|
||||||
|
@ -59,41 +59,131 @@ use crate::{
|
||||||
const VERSION: u8 = 1;
|
const VERSION: u8 = 1;
|
||||||
const MAGIC: HeaderMagic = *b"vpn\x01";
|
const MAGIC: HeaderMagic = *b"vpn\x01";
|
||||||
|
|
||||||
static USAGE: &str = include_str!("usage.txt");
|
|
||||||
|
|
||||||
|
#[derive(StructOpt, Debug, Default)]
|
||||||
#[derive(Deserialize, Debug, Default)]
|
|
||||||
pub struct Args {
|
pub struct Args {
|
||||||
flag_config: Option<String>,
|
/// Read configuration options from the specified file.
|
||||||
flag_type: Option<Type>,
|
#[structopt(long)]
|
||||||
flag_device_path: Option<String>,
|
config: Option<String>,
|
||||||
flag_mode: Option<Mode>,
|
|
||||||
flag_shared_key: Option<String>,
|
/// Set the type of network ("tap" or "tun")
|
||||||
flag_crypto: Option<CryptoMethod>,
|
#[structopt(name = "type", short, long)]
|
||||||
flag_subnet: Vec<String>,
|
type_: Option<Type>,
|
||||||
flag_device: Option<String>,
|
|
||||||
flag_listen: Option<String>,
|
/// Set the path of the base device
|
||||||
flag_network_id: Option<String>,
|
#[structopt(long)]
|
||||||
flag_magic: Option<String>,
|
device_path: Option<String>,
|
||||||
flag_connect: Vec<String>,
|
|
||||||
flag_peer_timeout: Option<Duration>,
|
/// The mode of the VPN ("normal", "router", "switch", or "hub")
|
||||||
flag_keepalive: Option<Duration>,
|
#[structopt(short, long)]
|
||||||
flag_dst_timeout: Option<Duration>,
|
mode: Option<Mode>,
|
||||||
flag_beacon_store: Option<String>,
|
|
||||||
flag_beacon_load: Option<String>,
|
/// The shared key to encrypt all traffic
|
||||||
flag_beacon_interval: Option<Duration>,
|
#[structopt(short, long, aliases=&["shared-key", "secret-key", "secret"])]
|
||||||
flag_verbose: bool,
|
key: Option<String>,
|
||||||
flag_quiet: bool,
|
|
||||||
flag_ifup: Option<String>,
|
/// The encryption method to use ("aes256", or "chacha20")
|
||||||
flag_ifdown: Option<String>,
|
#[structopt(long)]
|
||||||
flag_version: bool,
|
crypto: Option<CryptoMethod>,
|
||||||
flag_no_port_forwarding: bool,
|
|
||||||
flag_daemon: bool,
|
/// The local subnets to use
|
||||||
flag_pid_file: Option<String>,
|
#[structopt(short, long)]
|
||||||
flag_stats_file: Option<String>,
|
subnets: Vec<String>,
|
||||||
flag_user: Option<String>,
|
|
||||||
flag_group: Option<String>,
|
/// Name of the virtual device
|
||||||
flag_log_file: Option<String>
|
#[structopt(short, long)]
|
||||||
|
device: Option<String>,
|
||||||
|
|
||||||
|
/// The port number (or ip:port) on which to listen for data
|
||||||
|
#[structopt(short, long)]
|
||||||
|
listen: Option<String>,
|
||||||
|
|
||||||
|
/// Optional token that identifies the network. (DEPRECATED)
|
||||||
|
#[structopt(long)]
|
||||||
|
network_id: Option<String>,
|
||||||
|
|
||||||
|
/// Override the 4-byte magic header of each packet
|
||||||
|
#[structopt(long)]
|
||||||
|
magic: Option<String>,
|
||||||
|
|
||||||
|
/// Address of a peer to connect to
|
||||||
|
#[structopt(short, long)]
|
||||||
|
connect: Vec<String>,
|
||||||
|
|
||||||
|
/// Peer timeout in seconds
|
||||||
|
#[structopt(long)]
|
||||||
|
peer_timeout: Option<Duration>,
|
||||||
|
/// Periodically send message to keep connections alive
|
||||||
|
#[structopt(long)]
|
||||||
|
keepalive: Option<Duration>,
|
||||||
|
|
||||||
|
/// Switch table entry timeout in seconds
|
||||||
|
#[structopt(long)]
|
||||||
|
dst_timeout: Option<Duration>,
|
||||||
|
|
||||||
|
/// The file path or |command to store the beacon
|
||||||
|
#[structopt(long)]
|
||||||
|
beacon_store: Option<String>,
|
||||||
|
|
||||||
|
/// The file path or |command to load the beacon
|
||||||
|
#[structopt(long)]
|
||||||
|
beacon_load: Option<String>,
|
||||||
|
|
||||||
|
/// Beacon store/load interval in seconds
|
||||||
|
#[structopt(long)]
|
||||||
|
beacon_interval: Option<Duration>,
|
||||||
|
|
||||||
|
/// Print debug information
|
||||||
|
#[structopt(short, long, conflicts_with = "quiet")]
|
||||||
|
verbose: bool,
|
||||||
|
|
||||||
|
/// Only print errors and warnings
|
||||||
|
#[structopt(short, long)]
|
||||||
|
quiet: bool,
|
||||||
|
|
||||||
|
/// A command to setup the network interface
|
||||||
|
#[structopt(long)]
|
||||||
|
ifup: Option<String>,
|
||||||
|
|
||||||
|
/// A command to bring down the network interface
|
||||||
|
#[structopt(long)]
|
||||||
|
ifdown: Option<String>,
|
||||||
|
|
||||||
|
/// Print the version and exit
|
||||||
|
#[structopt(long)]
|
||||||
|
version: bool,
|
||||||
|
|
||||||
|
/// Disable automatic port forwarding
|
||||||
|
#[structopt(long)]
|
||||||
|
no_port_forwarding: bool,
|
||||||
|
|
||||||
|
/// Run the process in the background
|
||||||
|
#[structopt(long)]
|
||||||
|
daemon: bool,
|
||||||
|
|
||||||
|
/// Store the process id in this file when daemonizing
|
||||||
|
#[structopt(long)]
|
||||||
|
pid_file: Option<String>,
|
||||||
|
|
||||||
|
/// Print statistics to this file
|
||||||
|
#[structopt(long)]
|
||||||
|
stats_file: Option<String>,
|
||||||
|
|
||||||
|
/// Send statistics to this statsd server
|
||||||
|
#[structopt(long)]
|
||||||
|
statsd_server: Option<String>,
|
||||||
|
|
||||||
|
/// Run as other user
|
||||||
|
#[structopt(long)]
|
||||||
|
user: Option<String>,
|
||||||
|
|
||||||
|
/// Run as other group
|
||||||
|
#[structopt(long)]
|
||||||
|
group: Option<String>,
|
||||||
|
|
||||||
|
/// Print logs also to this file
|
||||||
|
#[structopt(long)]
|
||||||
|
log_file: Option<String>
|
||||||
}
|
}
|
||||||
|
|
||||||
struct DualLogger {
|
struct DualLogger {
|
||||||
|
@ -326,23 +416,23 @@ fn run<P: Protocol>(config: Config) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let args: Args = Docopt::new(USAGE).and_then(|d| d.deserialize()).unwrap_or_else(|e| e.exit());
|
let args: Args = Args::from_args();
|
||||||
if args.flag_version {
|
if args.version {
|
||||||
println!("VpnCloud v{}, protocol version {}", env!("CARGO_PKG_VERSION"), VERSION);
|
println!("VpnCloud v{}, protocol version {}", env!("CARGO_PKG_VERSION"), VERSION);
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let logger = try_fail!(DualLogger::new(args.flag_log_file.as_ref()), "Failed to open logfile: {}");
|
let logger = try_fail!(DualLogger::new(args.log_file.as_ref()), "Failed to open logfile: {}");
|
||||||
log::set_boxed_logger(Box::new(logger)).unwrap();
|
log::set_boxed_logger(Box::new(logger)).unwrap();
|
||||||
assert!(!args.flag_verbose || !args.flag_quiet);
|
assert!(!args.verbose || !args.quiet);
|
||||||
log::set_max_level(if args.flag_verbose {
|
log::set_max_level(if args.verbose {
|
||||||
log::LevelFilter::Debug
|
log::LevelFilter::Debug
|
||||||
} else if args.flag_quiet {
|
} else if args.quiet {
|
||||||
log::LevelFilter::Error
|
log::LevelFilter::Error
|
||||||
} else {
|
} else {
|
||||||
log::LevelFilter::Info
|
log::LevelFilter::Info
|
||||||
});
|
});
|
||||||
let mut config = Config::default();
|
let mut config = Config::default();
|
||||||
if let Some(ref file) = args.flag_config {
|
if let Some(ref file) = args.config {
|
||||||
info!("Reading config file '{}'", file);
|
info!("Reading config file '{}'", file);
|
||||||
let f = try_fail!(File::open(file), "Failed to open config file: {:?}");
|
let f = try_fail!(File::open(file), "Failed to open config file: {:?}");
|
||||||
let config_file = try_fail!(serde_yaml::from_reader(f), "Failed to load config file: {:?}");
|
let config_file = try_fail!(serde_yaml::from_reader(f), "Failed to load config file: {:?}");
|
||||||
|
|
|
@ -5,10 +5,15 @@
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
io::{self, Write},
|
io::{self, Write},
|
||||||
net::SocketAddr
|
net::SocketAddr,
|
||||||
|
ops::AddAssign
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{cloud::Hash, types::Address, util::Bytes};
|
use super::{
|
||||||
|
cloud::Hash,
|
||||||
|
types::Address,
|
||||||
|
util::{addr_nice, Bytes}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
@ -24,6 +29,19 @@ pub struct TrafficEntry {
|
||||||
pub idle_periods: usize
|
pub idle_periods: usize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl AddAssign<&TrafficEntry> for TrafficEntry {
|
||||||
|
fn add_assign(&mut self, other: &TrafficEntry) {
|
||||||
|
self.out_bytes_total += other.out_bytes_total;
|
||||||
|
self.out_packets_total += other.out_packets_total;
|
||||||
|
self.out_bytes += other.out_bytes;
|
||||||
|
self.out_packets += other.out_packets;
|
||||||
|
self.in_bytes_total += other.in_bytes_total;
|
||||||
|
self.in_packets_total += other.in_packets_total;
|
||||||
|
self.in_bytes += other.in_bytes;
|
||||||
|
self.in_packets += other.in_packets;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl TrafficEntry {
|
impl TrafficEntry {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn count_out(&mut self, bytes: usize) {
|
fn count_out(&mut self, bytes: usize) {
|
||||||
|
@ -58,7 +76,8 @@ impl TrafficEntry {
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct TrafficStats {
|
pub struct TrafficStats {
|
||||||
peers: HashMap<SocketAddr, TrafficEntry, Hash>,
|
peers: HashMap<SocketAddr, TrafficEntry, Hash>,
|
||||||
payload: HashMap<(Address, Address), TrafficEntry, Hash>
|
payload: HashMap<(Address, Address), TrafficEntry, Hash>,
|
||||||
|
pub dropped: TrafficEntry
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TrafficStats {
|
impl TrafficStats {
|
||||||
|
@ -82,6 +101,14 @@ impl TrafficStats {
|
||||||
self.payload.entry((remote, local)).or_insert_with(TrafficEntry::default).count_in(bytes);
|
self.payload.entry((remote, local)).or_insert_with(TrafficEntry::default).count_in(bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn count_invalid_protocol(&mut self, bytes: usize) {
|
||||||
|
self.dropped.count_in(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn count_dropped_payload(&mut self, bytes: usize) {
|
||||||
|
self.dropped.count_out(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn period(&mut self, cleanup_idle: Option<usize>) {
|
pub fn period(&mut self, cleanup_idle: Option<usize>) {
|
||||||
for entry in self.peers.values_mut() {
|
for entry in self.peers.values_mut() {
|
||||||
entry.period();
|
entry.period();
|
||||||
|
@ -89,6 +116,7 @@ impl TrafficStats {
|
||||||
for entry in self.payload.values_mut() {
|
for entry in self.payload.values_mut() {
|
||||||
entry.period();
|
entry.period();
|
||||||
}
|
}
|
||||||
|
self.dropped.period();
|
||||||
if let Some(periods) = cleanup_idle {
|
if let Some(periods) = cleanup_idle {
|
||||||
self.peers.retain(|_, entry| entry.idle_periods < periods);
|
self.peers.retain(|_, entry| entry.idle_periods < periods);
|
||||||
self.payload.retain(|_, entry| entry.idle_periods < periods);
|
self.payload.retain(|_, entry| entry.idle_periods < periods);
|
||||||
|
@ -103,28 +131,73 @@ impl TrafficStats {
|
||||||
self.payload.iter()
|
self.payload.iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn total_peer_traffic(&self) -> TrafficEntry {
|
||||||
|
let mut total = TrafficEntry::default();
|
||||||
|
for e in self.peers.values() {
|
||||||
|
total += e
|
||||||
|
}
|
||||||
|
total
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn total_payload_traffic(&self) -> TrafficEntry {
|
||||||
|
let mut total = TrafficEntry::default();
|
||||||
|
for e in self.payload.values() {
|
||||||
|
total += e
|
||||||
|
}
|
||||||
|
total
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn write_out<W: Write>(&self, out: &mut W) -> Result<(), io::Error> {
|
pub fn write_out<W: Write>(&self, out: &mut W) -> Result<(), io::Error> {
|
||||||
writeln!(out, "Peer traffic:")?;
|
writeln!(out, "peer_traffic:")?;
|
||||||
let mut peers: Vec<_> = self.get_peer_traffic().collect();
|
let mut peers: Vec<_> = self.get_peer_traffic().collect();
|
||||||
peers.sort_unstable_by_key(|(_, data)| (data.out_bytes + data.in_bytes));
|
peers.sort_unstable_by_key(|(_, data)| (data.out_bytes + data.in_bytes));
|
||||||
for (addr, data) in peers.iter().rev() {
|
for (addr, data) in peers.iter().rev() {
|
||||||
writeln!(out, " - {}: in={}/s, out={}/s", addr, Bytes(data.in_bytes / 60), Bytes(data.out_bytes / 60))?;
|
writeln!(
|
||||||
|
out,
|
||||||
|
" - peer: \"{}\"\n in: {{ display: \"{}/s\", bytes: {}, packets: {} }}\n out: {{ display: \"{}/s\", bytes: {}, packets: {} }}",
|
||||||
|
addr_nice(**addr),
|
||||||
|
Bytes(data.in_bytes / 60),
|
||||||
|
data.in_bytes,
|
||||||
|
data.in_packets,
|
||||||
|
Bytes(data.out_bytes / 60),
|
||||||
|
data.out_bytes,
|
||||||
|
data.out_packets
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
writeln!(out)?;
|
writeln!(out)?;
|
||||||
writeln!(out, "Payload traffic:")?;
|
writeln!(out, "payload_traffic:")?;
|
||||||
let mut payload: Vec<_> = self.get_payload_traffic().collect();
|
let mut payload: Vec<_> = self.get_payload_traffic().collect();
|
||||||
payload.sort_unstable_by_key(|(_, data)| (data.out_bytes + data.in_bytes));
|
payload.sort_unstable_by_key(|(_, data)| (data.out_bytes + data.in_bytes));
|
||||||
for ((remote, local), data) in payload.iter().rev() {
|
for ((remote, local), data) in payload.iter().rev() {
|
||||||
writeln!(
|
writeln!(
|
||||||
out,
|
out,
|
||||||
" - {} <-> {}: in={}/s, out={}/s",
|
" - addrs: [\"{}\", \"{}\"]\n in: {{ display: \"{}/s\", bytes: {}, packets: {} }}\n out: {{ display: \"{}/s\", bytes: {}, packets: {} }}",
|
||||||
remote,
|
remote,
|
||||||
local,
|
local,
|
||||||
Bytes(data.in_bytes / 60),
|
Bytes(data.in_bytes / 60),
|
||||||
Bytes(data.out_bytes / 60)
|
data.in_bytes,
|
||||||
|
data.in_packets,
|
||||||
|
Bytes(data.out_bytes / 60),
|
||||||
|
data.out_bytes,
|
||||||
|
data.out_packets
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
writeln!(out)?;
|
||||||
|
writeln!(
|
||||||
|
out,
|
||||||
|
"invalid_protocol_traffic: {{ display: \"{}/s\", bytes: {}, packets: {} }}",
|
||||||
|
Bytes(self.dropped.in_bytes / 60),
|
||||||
|
self.dropped.in_bytes,
|
||||||
|
self.dropped.in_packets
|
||||||
|
)?;
|
||||||
|
writeln!(
|
||||||
|
out,
|
||||||
|
"dropped_payload_traffic: {{ display: \"{}/s\", bytes: {}, packets: {} }}",
|
||||||
|
Bytes(self.dropped.out_bytes / 60),
|
||||||
|
self.dropped.out_bytes,
|
||||||
|
self.dropped.out_packets
|
||||||
|
)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
14
src/types.rs
14
src/types.rs
|
@ -206,6 +206,19 @@ impl fmt::Display for Mode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl FromStr for Mode {
|
||||||
|
type Err = &'static str;
|
||||||
|
|
||||||
|
fn from_str(text: &str) -> Result<Self, Self::Err> {
|
||||||
|
Ok(match &text.to_lowercase() as &str {
|
||||||
|
"normal" => Self::Normal,
|
||||||
|
"hub" => Self::Hub,
|
||||||
|
"switch" => Self::Switch,
|
||||||
|
"router" => Self::Router,
|
||||||
|
_ => return Err("Unknown mode")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait Table {
|
pub trait Table {
|
||||||
fn learn(&mut self, _: Address, _: Option<u8>, _: SocketAddr);
|
fn learn(&mut self, _: Address, _: Option<u8>, _: SocketAddr);
|
||||||
|
@ -214,6 +227,7 @@ pub trait Table {
|
||||||
fn write_out<W: Write>(&self, out: &mut W) -> Result<(), io::Error>;
|
fn write_out<W: Write>(&self, out: &mut W) -> Result<(), io::Error>;
|
||||||
fn remove(&mut self, _: &Address) -> bool;
|
fn remove(&mut self, _: &Address) -> bool;
|
||||||
fn remove_all(&mut self, _: &SocketAddr);
|
fn remove_all(&mut self, _: &SocketAddr);
|
||||||
|
fn len(&self) -> usize;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Protocol: Sized {
|
pub trait Protocol: Sized {
|
||||||
|
|
|
@ -1,43 +0,0 @@
|
||||||
Usage:
|
|
||||||
vpncloud [options] [--config <file>] [-t <type>] [-d <name>] [-l <port>] [-c <addr>...] [-s <subnet>...]
|
|
||||||
|
|
||||||
Options:
|
|
||||||
--config <file> Read configuration options from the
|
|
||||||
specified file.
|
|
||||||
-t <type>, --type <type> Set the type of network ("tap" or "tun").
|
|
||||||
--device-path <path> Set the path of the base device.
|
|
||||||
-d <name>, --device <name> Name of the virtual device.
|
|
||||||
-m <mode>, --mode <mode> The mode of the VPN ("hub", "switch",
|
|
||||||
"router", or "normal").
|
|
||||||
-l <port>, --listen <port> The port number on which to listen for data.
|
|
||||||
-c <addr>, --connect <addr> Address of a peer to connect to.
|
|
||||||
-s <subnet>, --subnet <subnet> The local subnets to use.
|
|
||||||
--magic <hex> Override the 4-byte magic header of each
|
|
||||||
packet.
|
|
||||||
--network-id <id> Optional token that identifies the network.
|
|
||||||
(DEPRECATED)
|
|
||||||
--shared-key <key> The shared key to encrypt all traffic.
|
|
||||||
--crypto <method> The encryption method to use ("aes256", or
|
|
||||||
"chacha20").
|
|
||||||
--peer-timeout <secs> Peer timeout in seconds.
|
|
||||||
--keepalive <secs> Periodically send message to keep
|
|
||||||
connections alive.
|
|
||||||
--dst-timeout <secs> Switch table entry timeout in seconds.
|
|
||||||
--beacon-store <path|command> The file or command to store the beacon.
|
|
||||||
--beacon-load <path|command> The file or command to load the beacon.
|
|
||||||
--beacon-interval <secs> Beacon store/load interval in seconds.
|
|
||||||
--ifup <command> A command to setup the network interface.
|
|
||||||
--ifdown <command> A command to bring down the network
|
|
||||||
interface.
|
|
||||||
--pid-file <file> Store the process id in this file when
|
|
||||||
daemonizing.
|
|
||||||
--user <user> Run as other user.
|
|
||||||
--group <group> Run as other group.
|
|
||||||
--log-file <file> Print logs also to this file.
|
|
||||||
--stats-file <file> Print statistics to this file.
|
|
||||||
--no-port-forwarding Disable automatic port forward.
|
|
||||||
--daemon Run the process in the background.
|
|
||||||
-v, --verbose Print debug information.
|
|
||||||
-q, --quiet Only print errors and warnings.
|
|
||||||
-h, --help Display the help.
|
|
||||||
-V, --version Print the version and exit.
|
|
|
@ -31,6 +31,15 @@ pub fn bytes_to_hex(bytes: &[u8]) -> String {
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn addr_nice(addr: SocketAddr) -> SocketAddr {
|
||||||
|
if let SocketAddr::V6(v6addr) = addr {
|
||||||
|
if let Some(ip) = v6addr.ip().to_ipv4() {
|
||||||
|
return (ip, addr.port()).into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addr
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
pub struct Encoder;
|
pub struct Encoder;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue