Fixes and improvements
This commit is contained in:
1 parent
1c9540c13c
commit
f24efd1401
33 files changed
+2618
-1093
No files matched your search
Generated
+180
-237
@@ -4,9 +4,9 @@ version = 4
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.22.1"
|
||||
version = "0.23.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
||||
checksum = "ac07cdecf99051d9a5238b80f35af32cdeba5b336e55d957b318b50137e18da5"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
@@ -16,34 +16,29 @@ checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da"
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.10.4"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
|
||||
checksum = "d2f6c7dbe95a6ed67ad9f18e57daf93a2f034c524b99fd2b76d18fdfeb6660aa"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"hybrid-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "1.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.4.0"
|
||||
version = "1.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5add81bb678e6cb321aff7fa0dc7689ad82b112dbc032cea19f91d6b8e3582b9"
|
||||
checksum = "5d262e149917187838d5b42777c8253bcb64500067342904e7d429499a6f277e"
|
||||
dependencies = [
|
||||
"find-msvc-tools",
|
||||
"shlex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nodeflare-agent"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2",
|
||||
"sysinfo",
|
||||
"ureq",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.4"
|
||||
@@ -51,47 +46,72 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation"
|
||||
version = "0.10.1"
|
||||
name = "const-oid"
|
||||
version = "0.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6"
|
||||
checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c"
|
||||
|
||||
[[package]]
|
||||
name = "cookie"
|
||||
version = "0.18.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a373e3602691c3cdea496d2f0ee5935151e6168fe87739483c463db1b2f2f87"
|
||||
dependencies = [
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
"percent-encoding",
|
||||
"time",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation-sys"
|
||||
version = "0.8.7"
|
||||
name = "cookie_store"
|
||||
version = "0.22.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
|
||||
checksum = "15b2c103cf610ec6cae3da84a766285b42fd16aad564758459e6ecf128c75206"
|
||||
dependencies = [
|
||||
"cookie",
|
||||
"document-features",
|
||||
"idna",
|
||||
"indexmap",
|
||||
"log",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"time",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.17"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
|
||||
checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-common"
|
||||
version = "0.1.7"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a"
|
||||
checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"typenum",
|
||||
"hybrid-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.10.7"
|
||||
name = "deranged"
|
||||
version = "0.5.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
||||
checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c"
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2"
|
||||
dependencies = [
|
||||
"block-buffer",
|
||||
"const-oid",
|
||||
"crypto-common",
|
||||
]
|
||||
|
||||
@@ -107,41 +127,25 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.14"
|
||||
name = "document-features"
|
||||
version = "0.2.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
||||
checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.61.2",
|
||||
"litrs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fastrand"
|
||||
version = "2.5.0"
|
||||
name = "equivalent"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223"
|
||||
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
||||
|
||||
[[package]]
|
||||
name = "find-msvc-tools"
|
||||
version = "0.1.9"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
|
||||
|
||||
[[package]]
|
||||
name = "foreign-types"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
|
||||
dependencies = [
|
||||
"foreign-types-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "foreign-types-shared"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
|
||||
checksum = "26b73573e6edcd2af0cdf47bd6cb58f0b3839491263c314eaad1ccf24430e1de"
|
||||
|
||||
[[package]]
|
||||
name = "form_urlencoded"
|
||||
@@ -152,16 +156,6 @@ dependencies = [
|
||||
"percent-encoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.17"
|
||||
@@ -174,14 +168,34 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.4.3"
|
||||
name = "hashbrown"
|
||||
version = "0.17.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099"
|
||||
checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
|
||||
|
||||
[[package]]
|
||||
name = "http"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "918d3568bebf352712bc2ef3d46a8bcf1a75b373be6539de198e9105cbbf9ce0"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"r-efi",
|
||||
"bytes",
|
||||
"itoa",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "httparse"
|
||||
version = "1.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"
|
||||
|
||||
[[package]]
|
||||
name = "hybrid-array"
|
||||
version = "0.4.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "707114b52a152fa7bdb290cd7cd5912d9467273b6d74e21b8d81aca1f8533f6b"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -287,6 +301,16 @@ dependencies = [
|
||||
"icu_properties",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.18"
|
||||
@@ -299,18 +323,18 @@ version = "0.2.189"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2"
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53"
|
||||
|
||||
[[package]]
|
||||
name = "litemap"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0"
|
||||
|
||||
[[package]]
|
||||
name = "litrs"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.33"
|
||||
@@ -324,20 +348,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
|
||||
|
||||
[[package]]
|
||||
name = "native-tls"
|
||||
version = "0.2.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "465500e14ea162429d264d44189adc38b199b62b1c21eea9f69e4b73cb03bbf2"
|
||||
name = "nodeflare-agent"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"openssl",
|
||||
"openssl-probe",
|
||||
"openssl-sys",
|
||||
"schannel",
|
||||
"security-framework",
|
||||
"security-framework-sys",
|
||||
"tempfile",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2",
|
||||
"sysinfo",
|
||||
"ureq",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -349,6 +368,12 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-conv"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441"
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-foundation"
|
||||
version = "0.3.2"
|
||||
@@ -374,61 +399,12 @@ version = "1.21.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
|
||||
|
||||
[[package]]
|
||||
name = "openssl"
|
||||
version = "0.10.81"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77823a27f0babb03091cb9ed9ef80af3b39dbc82f97e8fa530374b7dafd87a45"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
"foreign-types",
|
||||
"libc",
|
||||
"openssl-macros",
|
||||
"openssl-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "openssl-macros"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.119",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "openssl-probe"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe"
|
||||
|
||||
[[package]]
|
||||
name = "openssl-sys"
|
||||
version = "0.9.117"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b47e7e6bb2c38cd930d25a23b40fa52e068c10e85f3e03a7f5ba5aaca5713695"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
"pkg-config",
|
||||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "2.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e"
|
||||
|
||||
[[package]]
|
||||
name = "potential_utf"
|
||||
version = "0.1.5"
|
||||
@@ -438,6 +414,12 @@ dependencies = [
|
||||
"zerovec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "powerfmt"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.107"
|
||||
@@ -456,12 +438,6 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "r-efi"
|
||||
version = "6.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
|
||||
|
||||
[[package]]
|
||||
name = "ring"
|
||||
version = "0.17.14"
|
||||
@@ -470,23 +446,10 @@ checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"getrandom 0.2.17",
|
||||
"getrandom",
|
||||
"libc",
|
||||
"untrusted",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "1.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -524,38 +487,6 @@ dependencies = [
|
||||
"untrusted",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "schannel"
|
||||
version = "0.1.29"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939"
|
||||
dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "security-framework"
|
||||
version = "3.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"core-foundation",
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
"security-framework-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "security-framework-sys"
|
||||
version = "2.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3"
|
||||
dependencies = [
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.229"
|
||||
@@ -601,9 +532,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.10.9"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
|
||||
checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
@@ -682,16 +613,33 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.27.0"
|
||||
name = "time"
|
||||
version = "0.3.55"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd"
|
||||
checksum = "cdb87b95ec50ddfa440816d227a17b2ccbdda963a316a727fda0fc4334f7d134"
|
||||
dependencies = [
|
||||
"fastrand",
|
||||
"getrandom 0.4.3",
|
||||
"once_cell",
|
||||
"rustix",
|
||||
"windows-sys 0.61.2",
|
||||
"deranged",
|
||||
"num-conv",
|
||||
"powerfmt",
|
||||
"serde_core",
|
||||
"time-core",
|
||||
"time-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time-core"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109"
|
||||
|
||||
[[package]]
|
||||
name = "time-macros"
|
||||
version = "0.2.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7e689342a48d2ea927c87ea50cabf8594854bf940e9310208848d680d668ed85"
|
||||
dependencies = [
|
||||
"num-conv",
|
||||
"time-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -724,20 +672,33 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
|
||||
|
||||
[[package]]
|
||||
name = "ureq"
|
||||
version = "2.12.1"
|
||||
version = "3.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "02d1a66277ed75f640d608235660df48c8e3c19f3b4edb6a263315626cc3c01d"
|
||||
checksum = "972d7902c8735f2695410b8aed7df6ed12a47394aa1c8d7af49f0497b731a94d"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"cookie_store",
|
||||
"log",
|
||||
"native-tls",
|
||||
"once_cell",
|
||||
"percent-encoding",
|
||||
"rustls",
|
||||
"rustls-pki-types",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"url",
|
||||
"webpki-roots 0.26.11",
|
||||
"ureq-proto",
|
||||
"utf8-zero",
|
||||
"webpki-roots",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ureq-proto"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da5f78b09e6941e1a0f2e30e695e4b120377b54d5e0aec11b594bb57b3971613"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"http",
|
||||
"httparse",
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -752,18 +713,18 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "utf8-zero"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8c0a043c9540bae7c578c88f91dda8bd82e59ae27c21baca69c8b191aaf5a6e"
|
||||
|
||||
[[package]]
|
||||
name = "utf8_iter"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
|
||||
|
||||
[[package]]
|
||||
name = "vcpkg"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.5"
|
||||
@@ -776,15 +737,6 @@ version = "0.11.1+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
||||
|
||||
[[package]]
|
||||
name = "webpki-roots"
|
||||
version = "0.26.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9"
|
||||
dependencies = [
|
||||
"webpki-roots 1.0.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webpki-roots"
|
||||
version = "1.0.9"
|
||||
@@ -926,15 +878,6 @@ dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.61.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.6"
|
||||
|
||||
+3
-5
@@ -9,14 +9,12 @@ repository = "https://github.com/imengying/NodeFlare"
|
||||
[dependencies]
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
sha2 = "0.10"
|
||||
|
||||
[target.'cfg(target_os = "linux")'.dependencies]
|
||||
ureq = { version = "2.12", default-features = false, features = ["json", "tls"] }
|
||||
sha2 = "0.11"
|
||||
ureq = { version = "3.4", default-features = false, features = ["json", "rustls"] }
|
||||
url = "2.5"
|
||||
|
||||
[target.'cfg(any(target_os = "windows", target_os = "macos"))'.dependencies]
|
||||
sysinfo = { version = "0.39.6", default-features = false, features = ["disk", "network", "system"] }
|
||||
ureq = { version = "2.12", default-features = false, features = ["json", "native-tls"] }
|
||||
|
||||
[profile.release]
|
||||
codegen-units = 1
|
||||
|
||||
+5
-1
@@ -38,7 +38,11 @@ install_agent() {
|
||||
collect_interval=$(arg --collect-interval "$@" || printf '5')
|
||||
worker_url=${worker_url%/}
|
||||
safe_value "$server_id" && safe_value "$token" && safe_value "$worker_url" || { echo "Invalid install argument" >&2; exit 1; }
|
||||
case "$worker_url" in http://?*|https://?*) ;; *) echo "Worker URL must use HTTP or HTTPS" >&2; exit 1 ;; esac
|
||||
case "$worker_url" in
|
||||
https://?*|http://localhost|http://localhost/*|http://localhost:*|http://127.0.0.1|http://127.0.0.1/*|http://127.0.0.1:*) ;;
|
||||
*) echo "Worker URL must use HTTPS; HTTP is only allowed for loopback development" >&2; exit 1 ;;
|
||||
esac
|
||||
case "$worker_url" in *@*) echo "Worker URL must not contain user information" >&2; exit 1 ;; esac
|
||||
case "$interval" in ''|*[!0-9]*) echo "Invalid interval" >&2; exit 1 ;; esac
|
||||
[ "$interval" -ge 15 ] && [ "$interval" -le 3600 ] || { echo "Interval must be between 15 and 3600 seconds" >&2; exit 1; }
|
||||
case "$collect_interval" in ''|*[!0-9]*) echo "Invalid collect interval" >&2; exit 1 ;; esac
|
||||
|
||||
@@ -46,7 +46,11 @@ interval=$(arg --interval "$@" || printf '60')
|
||||
collect_interval=$(arg --collect-interval "$@" || printf '5')
|
||||
worker_url=${worker_url%/}
|
||||
safe_value "$server_id" && safe_value "$token" && safe_value "$worker_url" || { echo "Invalid argument" >&2; exit 1; }
|
||||
case "$worker_url" in http://?*|https://?*) ;; *) echo "Worker URL must use HTTP or HTTPS" >&2; exit 1 ;; esac
|
||||
case "$worker_url" in
|
||||
https://?*|http://localhost|http://localhost/*|http://localhost:*|http://127.0.0.1|http://127.0.0.1/*|http://127.0.0.1:*) ;;
|
||||
*) echo "Worker URL must use HTTPS; HTTP is only allowed for loopback development" >&2; exit 1 ;;
|
||||
esac
|
||||
case "$worker_url" in *@*) echo "Worker URL must not contain user information" >&2; exit 1 ;; esac
|
||||
case "$interval" in ''|*[!0-9]*) echo "Invalid interval" >&2; exit 1 ;; esac
|
||||
[ "$interval" -ge 15 ] && [ "$interval" -le 3600 ] || { echo "Interval must be between 15 and 3600 seconds" >&2; exit 1; }
|
||||
case "$collect_interval" in ''|*[!0-9]*) echo "Invalid collect interval" >&2; exit 1 ;; esac
|
||||
|
||||
+8
-3
@@ -21,17 +21,22 @@ function Assert-Safe([string]$Name, [string]$Value) {
|
||||
|
||||
function Assert-WorkerUrl([string]$Value) {
|
||||
$Parsed = $null
|
||||
$SecureScheme = $false
|
||||
if ([Uri]::TryCreate($Value, [UriKind]::Absolute, [ref]$Parsed)) {
|
||||
$SecureScheme = $Parsed.Scheme -eq "https" -or (
|
||||
$Parsed.Scheme -eq "http" -and $Parsed.Host -in @("localhost", "127.0.0.1", "::1")
|
||||
)
|
||||
}
|
||||
if (
|
||||
$Value.Length -gt 2048 -or
|
||||
$Value -match "\s" -or
|
||||
$Value.Contains("'") -or
|
||||
-not [Uri]::TryCreate($Value, [UriKind]::Absolute, [ref]$Parsed) -or
|
||||
$Parsed.Scheme -notin @("http", "https") -or
|
||||
-not $SecureScheme -or
|
||||
-not [string]::IsNullOrEmpty($Parsed.UserInfo) -or
|
||||
-not [string]::IsNullOrEmpty($Parsed.Query) -or
|
||||
-not [string]::IsNullOrEmpty($Parsed.Fragment)
|
||||
) {
|
||||
throw "Url must be an absolute HTTP or HTTPS URL"
|
||||
throw "Url must use HTTPS; HTTP is only allowed for loopback development"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+216
-106
@@ -2,9 +2,7 @@ use std::collections::{HashMap, HashSet};
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use std::io::{self, Read, Write};
|
||||
#[cfg(any(target_os = "windows", target_os = "macos"))]
|
||||
use std::net::UdpSocket;
|
||||
use std::net::{TcpStream, ToSocketAddrs};
|
||||
use std::net::{IpAddr, SocketAddr, TcpStream, ToSocketAddrs};
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
#[cfg(unix)]
|
||||
@@ -50,10 +48,12 @@ struct RuntimeConfig {
|
||||
report_interval: u64,
|
||||
collect_interval: u64,
|
||||
network_interface: String,
|
||||
auto_update: bool,
|
||||
latency_tasks: Vec<LatencyTask>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
struct LatencyTask {
|
||||
id: String,
|
||||
name: String,
|
||||
@@ -70,16 +70,13 @@ struct LatencyResult {
|
||||
packet_loss: f64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Deserialize)]
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
struct RemoteConfig {
|
||||
#[serde(default)]
|
||||
report_interval: u64,
|
||||
#[serde(default)]
|
||||
collect_interval: u64,
|
||||
#[serde(default)]
|
||||
network_interface: String,
|
||||
auto_update: i64,
|
||||
#[serde(default)]
|
||||
latency_tasks: Vec<LatencyTask>,
|
||||
}
|
||||
|
||||
@@ -96,8 +93,15 @@ struct GithubReleaseAsset {
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
struct ReportResponse {
|
||||
success: bool,
|
||||
config: RemoteConfig,
|
||||
}
|
||||
|
||||
struct SubmitResult {
|
||||
config: Option<RemoteConfig>,
|
||||
config_hash: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
@@ -120,7 +124,7 @@ struct DiskMetric {
|
||||
utilization: f64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Serialize)]
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
struct GpuMetric {
|
||||
model: String,
|
||||
usage: f64,
|
||||
@@ -155,8 +159,6 @@ struct Report {
|
||||
kernel: String,
|
||||
arch: String,
|
||||
virtualization: String,
|
||||
ipv4: String,
|
||||
ipv6: String,
|
||||
gpu_usage: f64,
|
||||
gpu_model: String,
|
||||
agent_version: String,
|
||||
@@ -392,17 +394,6 @@ fn cpu_model() -> String {
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn ip_address(family: &str) -> String {
|
||||
command("ip", &["-o", family, "addr", "show", "scope", "global"])
|
||||
.lines()
|
||||
.next()
|
||||
.and_then(|line| line.split_whitespace().find(|value| value.contains('/')))
|
||||
.and_then(|value| value.split('/').next())
|
||||
.unwrap_or("")
|
||||
.to_string()
|
||||
}
|
||||
|
||||
fn valid_probe_host(host: &str) -> bool {
|
||||
if host.is_empty() || host.len() > 50 || host.starts_with('.') || host.ends_with('.') {
|
||||
return false;
|
||||
@@ -413,24 +404,76 @@ fn valid_probe_host(host: &str) -> bool {
|
||||
.iter()
|
||||
.all(|label| !label.is_empty() && label.chars().all(|c| c.is_ascii_digit()));
|
||||
if ipv4_like {
|
||||
return labels.iter().all(|label| label.parse::<u8>().is_ok());
|
||||
return host
|
||||
.parse()
|
||||
.is_ok_and(|address| is_public_probe_ip(IpAddr::V4(address)));
|
||||
}
|
||||
let lower = host.to_ascii_lowercase();
|
||||
if labels.len() < 2
|
||||
|| ["local", "localhost", "internal", "lan", "localdomain"]
|
||||
.iter()
|
||||
.any(|suffix| lower == *suffix || lower.ends_with(&format!(".{suffix}")))
|
||||
|| lower == "home.arpa"
|
||||
|| lower.ends_with(".home.arpa")
|
||||
{
|
||||
return false;
|
||||
}
|
||||
labels.iter().all(|label| {
|
||||
!label.is_empty()
|
||||
&& label.chars().all(|character| {
|
||||
character.is_ascii_alphanumeric() || matches!(character, '_' | '-')
|
||||
})
|
||||
&& label
|
||||
.chars()
|
||||
.all(|character| character.is_ascii_alphanumeric() || character == '-')
|
||||
&& label
|
||||
.chars()
|
||||
.next()
|
||||
.is_some_and(|character| character.is_ascii_alphanumeric() || character == '_')
|
||||
.is_some_and(|character| character.is_ascii_alphanumeric())
|
||||
&& label
|
||||
.chars()
|
||||
.last()
|
||||
.is_some_and(|character| character.is_ascii_alphanumeric() || character == '_')
|
||||
.is_some_and(|character| character.is_ascii_alphanumeric())
|
||||
})
|
||||
}
|
||||
|
||||
fn is_public_probe_ip(address: IpAddr) -> bool {
|
||||
match address {
|
||||
IpAddr::V4(address) => {
|
||||
let [a, b, c, _] = address.octets();
|
||||
!(a == 0
|
||||
|| a == 10
|
||||
|| a == 127
|
||||
|| (a == 100 && (64..=127).contains(&b))
|
||||
|| (a == 169 && b == 254)
|
||||
|| (a == 172 && (16..=31).contains(&b))
|
||||
|| (a == 192 && b == 0 && c == 0)
|
||||
|| (a == 192 && b == 0 && c == 2)
|
||||
|| (a == 192 && b == 168)
|
||||
|| (a == 198 && (b == 18 || b == 19))
|
||||
|| (a == 198 && b == 51 && c == 100)
|
||||
|| (a == 203 && b == 0 && c == 113)
|
||||
|| a >= 224)
|
||||
}
|
||||
IpAddr::V6(address) => {
|
||||
if let Some(mapped) = address.to_ipv4_mapped() {
|
||||
return is_public_probe_ip(IpAddr::V4(mapped));
|
||||
}
|
||||
address.segments()[0] & 0xe000 == 0x2000
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_public_probe_address(host: &str, port: u16) -> Option<SocketAddr> {
|
||||
let addresses = (host, port)
|
||||
.to_socket_addrs()
|
||||
.ok()?
|
||||
.filter(|address| is_public_probe_ip(address.ip()))
|
||||
.collect::<Vec<_>>();
|
||||
addresses
|
||||
.iter()
|
||||
.find(|address| address.is_ipv4())
|
||||
.or_else(|| addresses.first())
|
||||
.copied()
|
||||
}
|
||||
|
||||
fn parse_probe_target(value: &str) -> Option<(String, u16)> {
|
||||
let raw = value.trim();
|
||||
if raw.is_empty()
|
||||
@@ -466,23 +509,17 @@ fn tcp_latency_probe(target: &str) -> (f64, f64) {
|
||||
let Some((host, port)) = parse_probe_target(target) else {
|
||||
return (-1.0, 100.0);
|
||||
};
|
||||
let Ok(addresses) = (host.as_str(), port).to_socket_addrs() else {
|
||||
return (-1.0, 100.0);
|
||||
};
|
||||
let addresses = addresses.collect::<Vec<_>>();
|
||||
let Some(address) = addresses
|
||||
.iter()
|
||||
.find(|address| address.is_ipv4())
|
||||
.or_else(|| addresses.first())
|
||||
.copied()
|
||||
else {
|
||||
let Some(address) = resolve_public_probe_address(&host, port) else {
|
||||
return (-1.0, 100.0);
|
||||
};
|
||||
tcp_latency_probe_address(&address)
|
||||
}
|
||||
|
||||
fn tcp_latency_probe_address(address: &SocketAddr) -> (f64, f64) {
|
||||
let mut latencies = Vec::with_capacity(PROBE_ATTEMPTS);
|
||||
for _ in 0..PROBE_ATTEMPTS {
|
||||
let started = Instant::now();
|
||||
if TcpStream::connect_timeout(&address, PROBE_TIMEOUT).is_ok() {
|
||||
if TcpStream::connect_timeout(address, PROBE_TIMEOUT).is_ok() {
|
||||
latencies.push(started.elapsed().as_secs_f64() * 1000.0);
|
||||
}
|
||||
}
|
||||
@@ -511,19 +548,26 @@ fn ping_latency(output: &str) -> Option<f64> {
|
||||
|
||||
fn icmp_latency_probe(target: &str) -> (f64, f64) {
|
||||
let host = target.trim();
|
||||
if host.contains(':') || !valid_probe_host(host) {
|
||||
if host.contains(':') {
|
||||
return (-1.0, 100.0);
|
||||
}
|
||||
let Some((host, _)) = parse_probe_target(host) else {
|
||||
return (-1.0, 100.0);
|
||||
};
|
||||
let Some(address) = resolve_public_probe_address(&host, 443) else {
|
||||
return (-1.0, 100.0);
|
||||
};
|
||||
let destination = address.ip().to_string();
|
||||
let mut latencies = Vec::with_capacity(PROBE_ATTEMPTS);
|
||||
for _ in 0..PROBE_ATTEMPTS {
|
||||
let started = Instant::now();
|
||||
let mut ping = Command::new("ping");
|
||||
#[cfg(target_os = "linux")]
|
||||
ping.args(["-n", "-c", "1", "-W", "1", host]);
|
||||
ping.args(["-n", "-c", "1", "-W", "1", destination.as_str()]);
|
||||
#[cfg(target_os = "macos")]
|
||||
ping.args(["-n", "-c", "1", "-W", "1000", host]);
|
||||
ping.args(["-n", "-c", "1", "-W", "1000", destination.as_str()]);
|
||||
#[cfg(target_os = "windows")]
|
||||
ping.args(["-n", "1", "-w", "1000", host]);
|
||||
ping.args(["-n", "1", "-w", "1000", destination.as_str()]);
|
||||
let output = ping.output();
|
||||
if let Ok(output) = output {
|
||||
if output.status.success() {
|
||||
@@ -611,17 +655,6 @@ fn gpu_info() -> Vec<GpuMetric> {
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "windows", target_os = "macos"))]
|
||||
fn local_ip(bind: &str, destination: &str) -> String {
|
||||
UdpSocket::bind(bind)
|
||||
.and_then(|socket| {
|
||||
socket.connect(destination)?;
|
||||
socket.local_addr()
|
||||
})
|
||||
.map(|address| address.ip().to_string())
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "windows", target_os = "macos"))]
|
||||
fn u64_to_i64(value: u64) -> i64 {
|
||||
value.min(i64::MAX as u64) as i64
|
||||
@@ -720,8 +753,6 @@ fn collect(config: &RuntimeConfig, latency_results: Vec<LatencyResult>) -> Repor
|
||||
kernel: command("uname", &["-r"]),
|
||||
arch: env::consts::ARCH.to_string(),
|
||||
virtualization: command("systemd-detect-virt", &[]),
|
||||
ipv4: ip_address("-4"),
|
||||
ipv6: ip_address("-6"),
|
||||
gpu_usage,
|
||||
gpu_model,
|
||||
agent_version: VERSION.to_string(),
|
||||
@@ -840,8 +871,6 @@ fn collect(config: &RuntimeConfig, latency_results: Vec<LatencyResult>) -> Repor
|
||||
kernel: System::kernel_version().unwrap_or_default(),
|
||||
arch: env::consts::ARCH.to_string(),
|
||||
virtualization: String::new(),
|
||||
ipv4: local_ip("0.0.0.0:0", "1.1.1.1:80"),
|
||||
ipv6: local_ip("[::]:0", "[2606:4700:4700::1111]:80"),
|
||||
gpu_usage,
|
||||
gpu_model,
|
||||
agent_version: VERSION.to_string(),
|
||||
@@ -886,7 +915,9 @@ fn runtime_config() -> Result<RuntimeConfig> {
|
||||
return Err("SERVER_ID or AGENT_TOKEN is invalid".into());
|
||||
}
|
||||
if !valid_worker_url(&worker_url) {
|
||||
return Err("WORKER_URL must be an http(s) URL without whitespace".into());
|
||||
return Err(
|
||||
"WORKER_URL must use HTTPS; HTTP is only allowed for loopback development".into(),
|
||||
);
|
||||
}
|
||||
Ok(RuntimeConfig {
|
||||
server_id,
|
||||
@@ -895,6 +926,7 @@ fn runtime_config() -> Result<RuntimeConfig> {
|
||||
report_interval: interval,
|
||||
collect_interval,
|
||||
network_interface: env::var("NETWORK_INTERFACE").unwrap_or_default(),
|
||||
auto_update: true,
|
||||
latency_tasks: Vec::new(),
|
||||
})
|
||||
}
|
||||
@@ -903,17 +935,38 @@ fn submit(
|
||||
agent: &ureq::Agent,
|
||||
config: &RuntimeConfig,
|
||||
reports: &[Report],
|
||||
) -> Result<Option<RemoteConfig>> {
|
||||
config_hash: &str,
|
||||
) -> Result<SubmitResult> {
|
||||
let batch = ReportBatch {
|
||||
server_id: &config.server_id,
|
||||
samples: reports,
|
||||
};
|
||||
let response = agent
|
||||
let mut response = agent
|
||||
.post(&format!("{}/api/agent/report", config.worker_url))
|
||||
.set("Authorization", &format!("Bearer {}", config.token))
|
||||
.set("User-Agent", &format!("nodeflare-agent/{VERSION}"))
|
||||
.header("Authorization", format!("Bearer {}", config.token))
|
||||
.header("User-Agent", format!("nodeflare-agent/{VERSION}"))
|
||||
.header("X-Agent-Config-Schema", "1")
|
||||
.header("X-Agent-Config-Sha256", config_hash)
|
||||
.send_json(batch)?;
|
||||
Ok(response.into_json::<ReportResponse>()?.config)
|
||||
let next_hash = response
|
||||
.headers()
|
||||
.get("X-Agent-Config-Sha256")
|
||||
.and_then(|value| value.to_str().ok())
|
||||
.unwrap_or(config_hash)
|
||||
.to_string();
|
||||
let remote = if response.status().as_u16() == 204 {
|
||||
None
|
||||
} else {
|
||||
let payload = response.body_mut().read_json::<ReportResponse>()?;
|
||||
if !payload.success {
|
||||
return Err("Worker rejected the report".into());
|
||||
}
|
||||
Some(payload.config)
|
||||
};
|
||||
Ok(SubmitResult {
|
||||
config: remote,
|
||||
config_hash: next_hash,
|
||||
})
|
||||
}
|
||||
|
||||
fn apply_remote(config: &mut RuntimeConfig, remote: &RemoteConfig) -> bool {
|
||||
@@ -926,6 +979,7 @@ fn apply_remote(config: &mut RuntimeConfig, remote: &RemoteConfig) -> bool {
|
||||
config
|
||||
.network_interface
|
||||
.clone_from(&remote.network_interface);
|
||||
config.auto_update = remote.auto_update == 1;
|
||||
let tasks = sanitize_latency_tasks(&remote.latency_tasks);
|
||||
let changed = config.latency_tasks != tasks;
|
||||
config.latency_tasks = tasks;
|
||||
@@ -954,15 +1008,32 @@ fn sanitize_latency_tasks(tasks: &[LatencyTask]) -> Vec<LatencyTask> {
|
||||
|
||||
fn valid_worker_url(value: &str) -> bool {
|
||||
let value = value.trim_end_matches('/');
|
||||
let authority = value
|
||||
.strip_prefix("https://")
|
||||
.or_else(|| value.strip_prefix("http://"))
|
||||
.and_then(|remainder| remainder.split('/').next());
|
||||
value.len() <= 2048
|
||||
&& authority.is_some_and(|authority| !authority.is_empty() && !authority.contains('@'))
|
||||
&& !value
|
||||
.chars()
|
||||
.any(|character| character.is_whitespace() || matches!(character, '?' | '#'))
|
||||
if value.is_empty() || value.len() > 2048 || value.chars().any(char::is_whitespace) {
|
||||
return false;
|
||||
}
|
||||
let Ok(parsed) = url::Url::parse(value) else {
|
||||
return false;
|
||||
};
|
||||
if parsed.host().is_none()
|
||||
|| !parsed.username().is_empty()
|
||||
|| parsed.password().is_some()
|
||||
|| parsed.query().is_some()
|
||||
|| parsed.fragment().is_some()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if parsed.scheme() == "https" {
|
||||
return true;
|
||||
}
|
||||
if parsed.scheme() != "http" {
|
||||
return false;
|
||||
}
|
||||
match parsed.host() {
|
||||
Some(url::Host::Domain(host)) => host.eq_ignore_ascii_case("localhost"),
|
||||
Some(url::Host::Ipv4(address)) => address == std::net::Ipv4Addr::LOCALHOST,
|
||||
Some(url::Host::Ipv6(address)) => address.is_loopback(),
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn report_retry_delay(failures: u32, report_interval: u64) -> Duration {
|
||||
@@ -1037,7 +1108,11 @@ fn sha256_file(path: &Path) -> Result<String> {
|
||||
}
|
||||
digest.update(&buffer[..read]);
|
||||
}
|
||||
Ok(format!("{:x}", digest.finalize()))
|
||||
Ok(digest
|
||||
.finalize()
|
||||
.iter()
|
||||
.map(|byte| format!("{byte:02x}"))
|
||||
.collect())
|
||||
}
|
||||
|
||||
fn parse_checksum(contents: &str, artifact: &str) -> Option<String> {
|
||||
@@ -1058,6 +1133,7 @@ fn release_checksum(agent: &ureq::Agent, url: &str, artifact: &str) -> Result<St
|
||||
agent
|
||||
.get(url)
|
||||
.call()?
|
||||
.into_body()
|
||||
.into_reader()
|
||||
.take(1024 * 1024)
|
||||
.read_to_string(&mut contents)?;
|
||||
@@ -1075,7 +1151,7 @@ fn download_agent(
|
||||
let Ok(response) = agent.get(url).call() else {
|
||||
return Ok(false);
|
||||
};
|
||||
let response = response.into_reader();
|
||||
let response = response.into_body().into_reader();
|
||||
let mut file = fs::File::create(destination)?;
|
||||
let copied = io::copy(&mut response.take(MAX_AGENT_BINARY_BYTES + 1), &mut file)?;
|
||||
file.flush()?;
|
||||
@@ -1105,12 +1181,12 @@ fn download_agent(
|
||||
}
|
||||
|
||||
fn update(agent: &ureq::Agent) -> Result<bool> {
|
||||
let release = agent
|
||||
let mut response = agent
|
||||
.get(LATEST_RELEASE_API)
|
||||
.set("Accept", "application/vnd.github+json")
|
||||
.set("User-Agent", &format!("nodeflare-agent/{VERSION}"))
|
||||
.call()?
|
||||
.into_json::<GithubRelease>()?;
|
||||
.header("Accept", "application/vnd.github+json")
|
||||
.header("User-Agent", format!("nodeflare-agent/{VERSION}"))
|
||||
.call()?;
|
||||
let release = response.body_mut().read_json::<GithubRelease>()?;
|
||||
let Some(remote_version) = version_triplet(&release.tag_name) else {
|
||||
return Ok(false);
|
||||
};
|
||||
@@ -1199,9 +1275,10 @@ fn update(agent: &ureq::Agent) -> Result<bool> {
|
||||
|
||||
fn run(once: bool, print_only: bool) -> Result<()> {
|
||||
let mut config = runtime_config()?;
|
||||
let agent = ureq::AgentBuilder::new()
|
||||
.timeout(Duration::from_secs(20))
|
||||
.build();
|
||||
let agent: ureq::Agent = ureq::Agent::config_builder()
|
||||
.timeout_global(Some(Duration::from_secs(20)))
|
||||
.build()
|
||||
.into();
|
||||
let mut next_report = Instant::now();
|
||||
let mut next_collect = Instant::now();
|
||||
let mut next_latency: HashMap<String, Instant> = HashMap::new();
|
||||
@@ -1209,6 +1286,7 @@ fn run(once: bool, print_only: bool) -> Result<()> {
|
||||
let mut pending_samples = Vec::new();
|
||||
let mut report_failures = 0_u32;
|
||||
let mut next_update_check = Instant::now();
|
||||
let mut config_hash = String::new();
|
||||
loop {
|
||||
let current = Instant::now();
|
||||
let due = config
|
||||
@@ -1252,27 +1330,28 @@ fn run(once: bool, print_only: bool) -> Result<()> {
|
||||
}
|
||||
|
||||
if Instant::now() >= next_report && !pending_samples.is_empty() {
|
||||
match submit(&agent, &config, &pending_samples) {
|
||||
Ok(remote) => {
|
||||
match submit(&agent, &config, &pending_samples, &config_hash) {
|
||||
Ok(result) => {
|
||||
pending_samples.clear();
|
||||
report_failures = 0;
|
||||
if let Some(remote) = remote {
|
||||
if !once && remote.auto_update == 1 && Instant::now() >= next_update_check {
|
||||
match update(&agent) {
|
||||
Ok(true) => return Ok(()),
|
||||
Ok(false) => {
|
||||
next_update_check = Instant::now() + UPDATE_CHECK_INTERVAL;
|
||||
}
|
||||
Err(error) => {
|
||||
eprintln!("agent update failed: {error}");
|
||||
next_update_check = Instant::now() + UPDATE_RETRY_INTERVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
config_hash = result.config_hash;
|
||||
if let Some(remote) = result.config {
|
||||
if apply_remote(&mut config, &remote) {
|
||||
next_latency.clear();
|
||||
}
|
||||
}
|
||||
if !once && config.auto_update && Instant::now() >= next_update_check {
|
||||
match update(&agent) {
|
||||
Ok(true) => return Ok(()),
|
||||
Ok(false) => {
|
||||
next_update_check = Instant::now() + UPDATE_CHECK_INTERVAL;
|
||||
}
|
||||
Err(error) => {
|
||||
eprintln!("agent update failed: {error}");
|
||||
next_update_check = Instant::now() + UPDATE_RETRY_INTERVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(error) => {
|
||||
eprintln!("report failed: {error}");
|
||||
@@ -1329,10 +1408,10 @@ mod tests {
|
||||
use std::time::Duration;
|
||||
|
||||
use super::{
|
||||
agent_artifact_name, executable_format_valid, median, normalized_version, parse_checksum,
|
||||
parse_probe_target, ping_latency, prune_report_samples, report_retry_delay,
|
||||
sanitize_latency_tasks, selected_interface, tcp_latency_probe, valid_worker_url,
|
||||
version_triplet, LatencyTask, Report, MAX_LATENCY_TASKS, PROBE_ATTEMPTS,
|
||||
agent_artifact_name, executable_format_valid, is_public_probe_ip, median,
|
||||
normalized_version, parse_checksum, parse_probe_target, ping_latency, prune_report_samples,
|
||||
report_retry_delay, sanitize_latency_tasks, selected_interface, tcp_latency_probe_address,
|
||||
valid_worker_url, version_triplet, LatencyTask, Report, MAX_LATENCY_TASKS, PROBE_ATTEMPTS,
|
||||
};
|
||||
|
||||
#[cfg(any(target_os = "windows", target_os = "macos"))]
|
||||
@@ -1380,6 +1459,10 @@ mod tests {
|
||||
fn validates_worker_urls() {
|
||||
assert!(valid_worker_url("https://monitor.example.com/"));
|
||||
assert!(valid_worker_url("http://127.0.0.1:8787"));
|
||||
assert!(valid_worker_url("http://localhost:8787"));
|
||||
assert!(valid_worker_url("http://[::1]:8787"));
|
||||
assert!(!valid_worker_url("http://monitor.example.com"));
|
||||
assert!(!valid_worker_url("http://127.0.0.2:8787"));
|
||||
assert!(!valid_worker_url("monitor.example.com"));
|
||||
assert!(!valid_worker_url("https://"));
|
||||
assert!(!valid_worker_url("https://user@example.com"));
|
||||
@@ -1475,8 +1558,8 @@ mod tests {
|
||||
Some(("example.com".to_string(), 443))
|
||||
);
|
||||
assert_eq!(
|
||||
parse_probe_target("127.0.0.1:8080"),
|
||||
Some(("127.0.0.1".to_string(), 8080))
|
||||
parse_probe_target("1.1.1.1:8080"),
|
||||
Some(("1.1.1.1".to_string(), 8080))
|
||||
);
|
||||
for target in [
|
||||
"",
|
||||
@@ -1484,6 +1567,11 @@ mod tests {
|
||||
"example.com:0",
|
||||
"example.com:65536",
|
||||
"999.1.1.1",
|
||||
"127.0.0.1:8080",
|
||||
"169.254.169.254",
|
||||
"192.168.1.1",
|
||||
"router.local",
|
||||
"localhost",
|
||||
"[::1]:443",
|
||||
"bad host",
|
||||
] {
|
||||
@@ -1491,6 +1579,29 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn accepts_only_public_probe_addresses() {
|
||||
for address in ["1.1.1.1", "8.8.8.8", "2606:4700:4700::1111"] {
|
||||
assert!(is_public_probe_ip(address.parse().expect("IP address")));
|
||||
}
|
||||
for address in [
|
||||
"0.0.0.0",
|
||||
"10.0.0.1",
|
||||
"100.64.0.1",
|
||||
"127.0.0.1",
|
||||
"169.254.169.254",
|
||||
"172.16.0.1",
|
||||
"192.168.1.1",
|
||||
"198.18.0.1",
|
||||
"224.0.0.1",
|
||||
"::1",
|
||||
"fe80::1",
|
||||
"fd00:ec2::254",
|
||||
] {
|
||||
assert!(!is_public_probe_ip(address.parse().expect("IP address")));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn calculates_median() {
|
||||
assert_eq!(median(&mut [4.0, 1.0, 3.0]), 3.0);
|
||||
@@ -1506,11 +1617,10 @@ mod tests {
|
||||
listener.accept().expect("accept probe connection");
|
||||
}
|
||||
});
|
||||
let (latency, loss) = tcp_latency_probe(&address.to_string());
|
||||
let (latency, loss) = tcp_latency_probe_address(&address);
|
||||
accepter.join().expect("join listener");
|
||||
assert!(latency >= 0.0);
|
||||
assert_eq!(loss, 0.0);
|
||||
assert_eq!(tcp_latency_probe(""), (-1.0, -1.0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in new issue
Block a user