diff options
author | rustdesk <[email protected]> | 2022-05-12 20:00:33 +0800 |
---|---|---|
committer | rustdesk <[email protected]> | 2022-05-12 20:00:33 +0800 |
commit | b3f39598a7324dacec0cd84d5e09b95724805cc8 (patch) | |
tree | 9a80ecd503ec53089bfd03d65612d10e615b76af | |
parent | d36d6da4452f6250e4b9c9e821367e2dc6783f11 (diff) | |
download | rustdesk-server-b3f39598a7324dacec0cd84d5e09b95724805cc8.tar.gz rustdesk-server-b3f39598a7324dacec0cd84d5e09b95724805cc8.zip |
change sled to sqlite and remove lic
33 files changed, 4071 insertions, 2591 deletions
diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..176a458 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto @@ -1,6 +1,2 @@ -/target -**/*.rs.bk -version.rs -sled.db -hbbs.sh -hbbs.conf +target +id* @@ -1,10 +1,17 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "ahash" -version = "0.4.7" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "739f4a8db6605981345c5654f3a85b056ce52f37a39d34da03f25bf2151ea16e" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +dependencies = [ + "getrandom", + "once_cell", + "version_check", +] [[package]] name = "aho-corasick" @@ -17,18 +24,55 @@ dependencies = [ [[package]] name = "ansi_term" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" dependencies = [ - "winapi 0.3.9", + "winapi", ] [[package]] name = "anyhow" -version = "1.0.40" +version = "1.0.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f9b8508dccb7687a1d6c4ce66b2b0ecef467c94667de27d8d7fe1f8d2a9cdc" + +[[package]] +name = "arrayvec" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28b2cd92db5cbd74e8e5028f7e27dd7aa3090e89e4f2a197cc7c8dfb69c7063b" +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" + +[[package]] +name = "async-speed-limit" +version = "0.3.1" +source = "git+https://github.com/open-trade/async-speed-limit#f89f702ae01d4016429543d2f0dda1086157e420" +dependencies = [ + "futures-core", + "futures-io", + "futures-timer", + "pin-project-lite", +] + +[[package]] +name = "async-trait" +version = "0.1.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed6aa3524a2dfcf9fe180c51eae2b58738348d819517ceadf95789c51fff7600" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "atoi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "616896e05fc0e2649463a93a15183c6a16bf03413a7af88ef1285ddedfa9cda5" +dependencies = [ + "num-traits", +] [[package]] name = "atty" @@ -38,14 +82,60 @@ checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ "hermit-abi", "libc", - "winapi 0.3.9", + "winapi", ] [[package]] name = "autocfg" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "axum" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00f1e8a972137fad81e2a1a60b86ff17ce0338f8017264e45a9723d0083c39a1" +dependencies = [ + "async-trait", + "axum-core", + "bitflags", + "bytes", + "futures-util", + "headers", + "http", + "http-body", + "hyper", + "itoa", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tower", + "tower-http 0.3.3", + "tower-layer", + "tower-service", +] + +[[package]] +name = "axum-core" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da31c0ed7b4690e2c78fe4b880d21cd7db04a346ebc658b4270251b695437f17" +dependencies = [ + "async-trait", + "bytes", + "futures-util", + "http", + "http-body", + "mime", +] [[package]] name = "base64" @@ -54,59 +144,77 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" [[package]] -name = "bindgen" -version = "0.57.0" +name = "bcrypt" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd4865004a46a0aafb2a0a5eb19d3c9fc46ee5f063a6cfc605c69ac9ecf5263d" +checksum = "6fe4fef31efb0f76133ae8e3576a88e58edb7cfc5584c81c758c349ba46b43fc" dependencies = [ - "bitflags", - "cexpr", - "clang-sys", - "lazy_static", - "lazycell", - "peeking_take_while", - "proc-macro2", - "quote", - "regex", - "rustc-hash", - "shlex", + "base64", + "blowfish", + "getrandom", + "zeroize", ] [[package]] name = "bitflags" -version = "1.2.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] -name = "bytes" -version = "0.5.6" +name = "block-buffer" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] [[package]] -name = "cc" -version = "1.0.67" +name = "block-buffer" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd" +checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324" dependencies = [ - "jobserver", + "generic-array", ] [[package]] -name = "cexpr" -version = "0.4.0" +name = "blowfish" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4aedb84272dbe89af497cf81375129abda4fc0a9e7c5d317498c15cc30c0d27" +checksum = "e412e2cd0f2b2d93e02543ceae7917b3c70331573df19ee046bcbc35e45e87d7" dependencies = [ - "nom", + "byteorder", + "cipher", ] [[package]] -name = "cfg-if" -version = "0.1.10" +name = "bumpalo" +version = "3.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "bytes" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" + +[[package]] +name = "cc" +version = "1.0.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" +dependencies = [ + "jobserver", +] [[package]] name = "cfg-if" @@ -115,21 +223,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "clang-sys" -version = "1.2.0" +name = "chrono" +version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "853eda514c284c2287f4bf20ae614f8781f40a81d32ecda6e91449304dfe077c" +checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" dependencies = [ - "glob", "libc", - "libloading", + "num-integer", + "num-traits", + "time 0.1.43", + "winapi", +] + +[[package]] +name = "cipher" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1873270f8f7942c191139cb8a40fd228da6c3fd2fc376d7e92d47aa14aeb59e" +dependencies = [ + "crypto-common", + "inout", ] [[package]] name = "clap" -version = "2.33.3" +version = "2.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" dependencies = [ "ansi_term", "atty", @@ -141,29 +261,176 @@ dependencies = [ ] [[package]] +name = "config" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1b9d958c2b1368a663f05538fc1b5975adce1e19f435acceae987aceeeb369" +dependencies = [ + "lazy_static", + "nom 5.1.2", + "serde", +] + +[[package]] name = "confy" -version = "0.4.1" -source = "git+https://github.com/open-trade/confy#27fa12941291b44ccd856aef4a5452c1eb646047" +version = "0.4.0" +source = "git+https://github.com/open-trade/confy#630cc28a396cb7d01eefdd9f3824486fe4d8554b" dependencies = [ - "directories", + "directories-next", "serde", + "thiserror", "toml", ] [[package]] -name = "cryptoxide" -version = "0.3.3" +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + +[[package]] +name = "cpufeatures" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b" +dependencies = [ + "libc", +] + +[[package]] +name = "crc" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49fc9a695bca7f35f5f4c15cddc84415f66a74ea78eef08e90c5024f2b540e23" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccaeedb56da03b09f598226e25e80088cb4cd25f316e6e4df7d695f0feeb1403" + +[[package]] +name = "crossbeam" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae5588f6b3c3cb05239e90bd110f257254aecd01e4635400391aeae07497845" +dependencies = [ + "cfg-if", + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-epoch", + "crossbeam-queue", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8c4fdc86023bc33b265f256ce8205329125b86c38a8a96e243a6a705b7230ec" +checksum = "1145cf131a2c6ba0615079ab6a638f7e1973ac9c2634fcbeaaad6114246efe8c" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "lazy_static", + "memoffset", + "scopeguard", +] [[package]] -name = "directories" -version = "2.0.2" +name = "crossbeam-queue" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "551a778172a450d7fc12e629ca3b0428d00f6afa9a43da1b630d54604e97371c" +checksum = "1f25d8400f4a7a5778f0e4e52384a48cbd9b5c495d110786187fc750075277a2" dependencies = [ - "cfg-if 0.1.10", - "dirs-sys", + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" +dependencies = [ + "cfg-if", + "lazy_static", +] + +[[package]] +name = "crypto-common" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "deadpool" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef82259c587bceda08349f28ff00f69ae4c897898f254140af6021eb218e8232" +dependencies = [ + "async-trait", + "config", + "num_cpus", + "serde", + "tokio", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "digest" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" +dependencies = [ + "block-buffer 0.10.2", + "crypto-common", ] [[package]] @@ -172,7 +439,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "339ee130d97a610ea5a5872d2bbb130fdf68884ff09d3028b81bec8a1ac23bbc" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "dirs-sys-next", ] @@ -182,22 +449,11 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "dirs-sys-next", ] [[package]] -name = "dirs-sys" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780" -dependencies = [ - "libc", - "redox_users", - "winapi 0.3.9", -] - -[[package]] name = "dirs-sys-next" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -205,23 +461,41 @@ checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" dependencies = [ "libc", "redox_users", - "winapi 0.3.9", + "winapi", ] [[package]] name = "dlv-list" -version = "0.2.3" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0688c2a7f92e427f44895cd63841bff7b29f8d7a1648b9e7e07a4a365b2e1257" + +[[package]] +name = "dotenv" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68df3f2b690c1b86e65ef7830956aededf3cb0a16f898f79b9a6f421a7b6211b" +checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" + +[[package]] +name = "ed25519" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d916019f70ae3a1faa1195685e290287f39207d38e6dfee727197cffcc002214" dependencies = [ - "rand", + "signature", ] [[package]] +name = "either" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" + +[[package]] name = "env_logger" -version = "0.8.3" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17392a012ea30ef05a610aa97dfb49496e71c9f676b27879922ea5bdf60d9d3f" +checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3" dependencies = [ "atty", "humantime", @@ -231,44 +505,78 @@ dependencies = [ ] [[package]] +name = "fastrand" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" +dependencies = [ + "instant", +] + +[[package]] name = "filetime" -version = "0.2.14" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d34cfa13a63ae058bfa601fe9e313bbdb3746427c1459185464ce0fcf62e1e8" +checksum = "c0408e2626025178a6a7f7ffc05a25bc47103229f19c113755de7bf63816290c" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", "redox_syscall", - "winapi 0.3.9", + "winapi", ] [[package]] -name = "fnv" -version = "1.0.7" +name = "flexi_logger" +version = "0.22.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +checksum = "969940c39bc718475391e53a3a59b0157e64929c80cf83ad5dde5f770ecdc423" +dependencies = [ + "ansi_term", + "atty", + "chrono", + "crossbeam", + "glob", + "lazy_static", + "log", + "regex", + "rustversion", + "thiserror", + "time 0.3.9", +] [[package]] -name = "fuchsia-zircon" -version = "0.3.3" +name = "flume" +version = "0.10.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" +checksum = "843c03199d0c0ca54bc1ea90ac0d507274c28abcc4f691ae8b4eaa375087c76a" dependencies = [ - "bitflags", - "fuchsia-zircon-sys", + "futures-core", + "futures-sink", + "pin-project", + "spin 0.9.3", ] [[package]] -name = "fuchsia-zircon-sys" -version = "0.3.3" +name = "fnv" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "form_urlencoded" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" +dependencies = [ + "matches", + "percent-encoding", +] [[package]] name = "futures" -version = "0.3.15" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e7e43a803dae2fa37c1f6a8fe121e1f7bf9548b4dfc0522a42f34145dadfc27" +checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e" dependencies = [ "futures-channel", "futures-core", @@ -281,9 +589,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.15" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e682a68b29a882df0545c143dc3646daefe80ba479bcdede94d5a703de2871e2" +checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" dependencies = [ "futures-core", "futures-sink", @@ -291,15 +599,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.15" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0402f765d8a89a26043b889b26ce3c4679d268fa6bb22cd7c6aad98340e179d1" +checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" [[package]] name = "futures-executor" -version = "0.3.15" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "badaa6a909fac9e7236d0620a2f57f7664640c56575b71a7552fbd68deafab79" +checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6" dependencies = [ "futures-core", "futures-task", @@ -307,19 +615,28 @@ dependencies = [ ] [[package]] +name = "futures-intrusive" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62007592ac46aa7c2b6416f7deb9a8a8f63a01e0f1d6e1787d5630170db2b63e" +dependencies = [ + "futures-core", + "lock_api", + "parking_lot 0.11.2", +] + +[[package]] name = "futures-io" -version = "0.3.15" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acc499defb3b348f8d8f3f66415835a9131856ff7714bf10dadfc4ec4bdb29a1" +checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" [[package]] name = "futures-macro" -version = "0.3.15" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4c40298486cdf52cc00cd6d6987892ba502c7656a16a4192a9992b1ccedd121" +checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" dependencies = [ - "autocfg", - "proc-macro-hack", "proc-macro2", "quote", "syn", @@ -327,23 +644,28 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.15" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a57bead0ceff0d6dde8f465ecd96c9338121bb7717d3e7b108059531870c4282" +checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" [[package]] name = "futures-task" -version = "0.3.15" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a16bef9fc1a4dddb5bee51c989e3fbba26569cbb0e31f5b303c184e3dd33dae" +checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" + +[[package]] +name = "futures-timer" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" [[package]] name = "futures-util" -version = "0.3.15" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "feb5c238d27e2bf94ffdfd27b2c29e3df4a68c4193bb6427384259e2bf191967" +checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" dependencies = [ - "autocfg", "futures-channel", "futures-core", "futures-io", @@ -351,22 +673,39 @@ dependencies = [ "futures-sink", "futures-task", "memchr", - "pin-project-lite 0.2.6", + "pin-project-lite", "pin-utils", - "proc-macro-hack", - "proc-macro-nested", "slab", ] [[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + +[[package]] +name = "generic-array" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] name = "getrandom" -version = "0.2.2" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8" +checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", - "wasi", + "wasi 0.10.2+wasi-snapshot-preview1", ] [[package]] @@ -377,14 +716,32 @@ checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" [[package]] name = "hashbrown" -version = "0.9.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" dependencies = [ "ahash", ] [[package]] +name = "hashbrown" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db0d4cf898abf0081f964436dc980e96670a0f36863e4b83aaacdb65c9d7ccc3" +dependencies = [ + "ahash", +] + +[[package]] +name = "hashlink" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7249a3129cbc1ffccd74857f81464a323a152173cdb134e0fd81bc803b29facf" +dependencies = [ + "hashbrown 0.11.2", +] + +[[package]] name = "hbb_common" version = "0.1.0" dependencies = [ @@ -402,87 +759,260 @@ dependencies = [ "mac_address", "protobuf", "protobuf-codegen-pure", + "quinn", "rand", "regex", "serde", "serde_derive", "serde_json", - "socket2", + "socket2 0.3.19", "sodiumoxide", "tokio", - "tokio-util", + "tokio-socks", + "tokio-util 0.6.9", "toml", - "winapi 0.3.9", + "winapi", "zstd", ] [[package]] name = "hbbs" -version = "1.1.4" +version = "1.1.5" dependencies = [ + "async-speed-limit", + "async-trait", + "axum", "base64", + "bcrypt", + "chrono", "clap", - "cryptoxide", + "deadpool", + "flexi_logger", "hbb_common", + "headers", + "http", + "jsonwebtoken", "lazy_static", "mac_address", "machine-uid", "minreq", - "rocksdb", + "once_cell", + "regex", "rust-ini", "serde", "serde_derive", "serde_json", + "sodiumoxide", + "sqlx", + "tokio-tungstenite", + "tower-http 0.2.5", + "tungstenite", + "uuid", "whoami", ] [[package]] +name = "headers" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cff78e5788be1e0ab65b04d306b2ed5092c815ec97ec70f4ebd5aee158aa55d" +dependencies = [ + "base64", + "bitflags", + "bytes", + "headers-core", + "http", + "httpdate", + "mime", + "sha-1", +] + +[[package]] +name = "headers-core" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" +dependencies = [ + "http", +] + +[[package]] +name = "heck" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +dependencies = [ + "unicode-segmentation", +] + +[[package]] name = "hermit-abi" -version = "0.1.18" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" dependencies = [ "libc", ] [[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "http" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff8670570af52249509a86f5e3e18a08c60b177071826898fde8997cf5f6bfbb" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ff4f84919677303da5f147645dbea6b1881f368d03ac84e1dc09031ebd7b2c6" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "http-range-header" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfe8eed0a9285ef776bb792479ea3834e8b94e13d615c2f66d03dd50a435a29" + +[[package]] +name = "httparse" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "496ce29bb5a52785b44e0f7ca2847ae0bb839c9bd28f69acac9b99d461c0c04c" + +[[package]] +name = "httpdate" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" + +[[package]] name = "humantime" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] -name = "iovec" -version = "0.1.4" +name = "hyper" +version = "0.14.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" +checksum = "b26ae0a80afebe130861d90abf98e3814a4f28a4c6ffeb5ab8ebb2be311e0ef2" dependencies = [ - "libc", + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2 0.4.4", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "idna" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +dependencies = [ + "matches", + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "indexmap" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee" +dependencies = [ + "autocfg", + "hashbrown 0.11.2", +] + +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-array", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "itertools" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" +dependencies = [ + "either", ] [[package]] name = "itoa" -version = "0.4.7" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" +checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" [[package]] name = "jobserver" -version = "0.1.22" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "972f5ae5d1cb9c6ae417789196c803205313edde988685da5e3aae0827b9e7fd" +checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa" dependencies = [ "libc", ] [[package]] -name = "kernel32-sys" -version = "0.2.2" +name = "js-sys" +version = "0.3.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +checksum = "671a26f820db17c2a2750743f1dd03bafd15b98c9f30c7c2628c024c05d73397" dependencies = [ - "winapi 0.2.8", - "winapi-build", + "wasm-bindgen", +] + +[[package]] +name = "jsonwebtoken" +version = "8.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc9051c17f81bae79440afa041b3a278e1de71bfb96d32454b477fd4703ccb6f" +dependencies = [ + "base64", + "pem", + "ring", + "serde", + "serde_json", + "simple_asn1", ] [[package]] @@ -492,67 +1022,74 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] -name = "lazycell" -version = "1.3.0" +name = "lexical-core" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" +checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe" +dependencies = [ + "arrayvec", + "bitflags", + "cfg-if", + "ryu", + "static_assertions", +] [[package]] name = "libc" -version = "0.2.94" +version = "0.2.125" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18794a8ad5b29321f790b55d93dfba91e125cb1a9edbd4f8e3150acc771c1a5e" +checksum = "5916d2ae698f6de9bfb891ad7a8d65c09d232dc58cc4ac433c7da3b2fd84bc2b" [[package]] -name = "libloading" -version = "0.7.0" +name = "libsodium-sys" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f84d96438c15fcd6c3f244c8fce01d1e2b9c6b5623e9c711dc9286d8fc92d6a" +checksum = "6b779387cd56adfbc02ea4a668e704f729be8d6a6abd2c27ca5ee537849a92fd" dependencies = [ - "cfg-if 1.0.0", - "winapi 0.3.9", + "cc", + "libc", + "pkg-config", + "walkdir", ] [[package]] -name = "librocksdb-sys" -version = "6.17.3" +name = "libsqlite3-sys" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5da125e1c0f22c7cae785982115523a0738728498547f415c9054cb17c7e89f9" +checksum = "d2cafc7c74096c336d9d27145f7ebd4f4b6f95ba16aa5a282387267e6925cb58" dependencies = [ - "bindgen", "cc", - "glob", - "libc", + "pkg-config", + "vcpkg", ] [[package]] -name = "libsodium-sys" -version = "0.2.6" +name = "lock_api" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a685b64f837b339074115f2e7f7b431ac73681d08d75b389db7498b8892b8a58" +checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" dependencies = [ - "cc", - "libc", - "pkg-config", + "autocfg", + "scopeguard", ] [[package]] name = "log" -version = "0.4.14" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] [[package]] name = "mac_address" -version = "1.1.1" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d9bb26482176bddeea173ceaa2acec85146d20cdcc631eafaf9d605d3d4fc23" +checksum = "df1d1bc1084549d60725ccc53a2bfa07f67fe4689fda07b05a36531f2988104a" dependencies = [ "nix", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -565,72 +1102,87 @@ dependencies = [ ] [[package]] +name = "matches" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" + +[[package]] +name = "matchit" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73cbba799671b762df5a175adf59ce145165747bb891505c43d09aefbbf38beb" + +[[package]] name = "memchr" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] -name = "minreq" -version = "2.3.1" +name = "memoffset" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "781e56f7d29192378f0a04948b1e6aec67ce561273b2dd26ac510bbe88d7be70" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" dependencies = [ - "punycode", + "autocfg", ] [[package]] -name = "mio" -version = "0.6.23" +name = "mime" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4" +checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" + +[[package]] +name = "mime_guess" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" dependencies = [ - "cfg-if 0.1.10", - "fuchsia-zircon", - "fuchsia-zircon-sys", - "iovec", - "kernel32-sys", - "libc", - "log", - "miow 0.2.2", - "net2", - "slab", - "winapi 0.2.8", + "mime", + "unicase", ] [[package]] -name = "mio-named-pipes" -version = "0.1.7" +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "minreq" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0840c1c50fd55e521b247f949c241c9997709f23bd7f023b9762cd561e935656" +checksum = "4c785bc6027fd359756e538541c8624012ba3776d3d3fe123885643092ed4132" dependencies = [ "log", - "mio", - "miow 0.3.7", - "winapi 0.3.9", + "punycode", ] [[package]] -name = "mio-uds" -version = "0.6.8" +name = "mio" +version = "0.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afcb699eb26d4332647cc848492bbc15eafb26f08d0304550d5aa1f612e066f0" +checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc" dependencies = [ - "iovec", "libc", - "mio", + "log", + "miow", + "ntapi", + "winapi", ] [[package]] -name = "miow" -version = "0.2.2" +name = "mio" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d" +checksum = "713d550d9b44d89174e066b7a6217ae06234c10cb47819a88290d2b353c31799" dependencies = [ - "kernel32-sys", - "net2", - "winapi 0.2.8", - "ws2_32-sys", + "libc", + "log", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys", ] [[package]] @@ -639,30 +1191,20 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" dependencies = [ - "winapi 0.3.9", -] - -[[package]] -name = "net2" -version = "0.2.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "391630d12b68002ae1e25e8f974306474966550ad82dac6886fb8910c19568ae" -dependencies = [ - "cfg-if 0.1.10", - "libc", - "winapi 0.3.9", + "winapi", ] [[package]] name = "nix" -version = "0.19.1" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ccba0cfe4fdf15982d1674c69b1fd80bad427d293849982668dfe454bd61f2" +checksum = "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6" dependencies = [ "bitflags", "cc", - "cfg-if 1.0.0", + "cfg-if", "libc", + "memoffset", ] [[package]] @@ -671,107 +1213,283 @@ version = "5.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af" dependencies = [ + "lexical-core", "memchr", "version_check", ] [[package]] +name = "nom" +version = "7.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "ntapi" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f" +dependencies = [ + "winapi", +] + +[[package]] +name = "num-bigint" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + +[[package]] name = "num_cpus" -version = "1.13.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" dependencies = [ "hermit-abi", "libc", ] [[package]] +name = "num_threads" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" +dependencies = [ + "libc", +] + +[[package]] +name = "once_cell" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9" + +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] name = "ordered-multimap" -version = "0.3.1" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c672c7ad9ec066e428c00eb917124a06f08db19e2584de982cc34b1f4c12485" +checksum = "ccd746e37177e1711c20dd619a1620f34f5c8b569c53590a72dedd5344d8924a" dependencies = [ "dlv-list", - "hashbrown", + "hashbrown 0.12.1", ] [[package]] -name = "peeking_take_while" -version = "0.1.2" +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core 0.8.5", +] + +[[package]] +name = "parking_lot" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" +checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58" +dependencies = [ + "lock_api", + "parking_lot_core 0.9.3", +] [[package]] -name = "pin-project-lite" -version = "0.1.12" +name = "parking_lot_core" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "257b64915a082f7811703966789728173279bdebb956b143dbcd23f6f970a777" +checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall", + "smallvec", + "winapi", +] [[package]] -name = "pin-project-lite" -version = "0.2.6" +name = "parking_lot_core" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc0e1f259c92177c30a4c9d177246edd0a3568b25756a977d0632cf8fa37e905" +checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-sys", +] [[package]] -name = "pin-utils" -version = "0.1.0" +name = "paste" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "0c520e05135d6e763148b6426a837e239041653ba7becd2e538c076c738025fc" [[package]] -name = "pkg-config" -version = "0.3.19" +name = "pem" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" +checksum = "e9a3b09a20e374558580a4914d3b7d89bd61b954a5a5e1dcbea98753addb1947" +dependencies = [ + "base64", +] [[package]] -name = "ppv-lite86" -version = "0.2.10" +name = "percent-encoding" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" +checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" [[package]] -name = "proc-macro-hack" -version = "0.5.19" +name = "pin-project" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" +checksum = "58ad3879ad3baf4e44784bc6a718a8698867bb991f8ce24d1bcbe2cfb4c3a75e" +dependencies = [ + "pin-project-internal", +] [[package]] -name = "proc-macro-nested" -version = "0.1.7" +name = "pin-project-internal" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086" +checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" + +[[package]] +name = "ppv-lite86" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" [[package]] name = "proc-macro2" -version = "1.0.26" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec" +checksum = "9027b48e9d4c9175fa2218adf3557f91c1137021739951d4932f5f8268ac48aa" dependencies = [ "unicode-xid", ] [[package]] name = "protobuf" -version = "3.0.0-pre" -source = "git+https://github.com/stepancheg/rust-protobuf#bbe35a98e196c4dea67dd23ac93c0a66ca11b903" +version = "3.0.0-alpha.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d5ef59c35c7472ce5e1b6c5924b87585143d1fc2cf39eae0009bba6c4df62f1" [[package]] name = "protobuf-codegen" -version = "3.0.0-pre" -source = "git+https://github.com/stepancheg/rust-protobuf#bbe35a98e196c4dea67dd23ac93c0a66ca11b903" +version = "3.0.0-alpha.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89100ee819f69b77a4cab389fec9dd155a305af4c615e6413ec1ef9341f333ef" dependencies = [ + "anyhow", "protobuf", + "protobuf-parse", + "thiserror", ] [[package]] name = "protobuf-codegen-pure" -version = "3.0.0-pre" -source = "git+https://github.com/stepancheg/rust-protobuf#bbe35a98e196c4dea67dd23ac93c0a66ca11b903" +version = "3.0.0-alpha.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79453e74d08190551e821533ee42c447f9e21ca26f83520e120e6e8af27f6879" dependencies = [ + "anyhow", "protobuf", "protobuf-codegen", + "protobuf-parse", + "thiserror", +] + +[[package]] +name = "protobuf-parse" +version = "3.0.0-alpha.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c265ffc69976efc3056955b881641add3186ad0be893ef10622482d80d1d2b68" +dependencies = [ + "anyhow", + "protobuf", + "protoc", + "tempfile", + "thiserror", +] + +[[package]] +name = "protoc" +version = "3.0.0-alpha.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f1f8b318a54d18fbe542513331e058f4f8ce6502e542e057c50c7e5e803fdab" +dependencies = [ + "anyhow", + "log", + "thiserror", + "which", ] [[package]] @@ -781,31 +1499,93 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e9e1dcb320d6839f6edb64f7a4a59d39b30480d4d1765b56873f7c858538a5fe" [[package]] +name = "quickcheck" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "588f6378e4dd99458b60ec275b4477add41ce4fa9f64dcba6f15adccb19b50d6" +dependencies = [ + "rand", +] + +[[package]] +name = "quinn" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d147472bc9a09f13b06c044787b6683cdffa02e2865b7f0fb53d67c49ed2988e" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "fxhash", + "quinn-proto", + "quinn-udp", + "rustls 0.20.4", + "thiserror", + "tokio", + "tracing", + "webpki 0.22.0", +] + +[[package]] +name = "quinn-proto" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "359c5eb33845f3ee05c229e65f87cdbc503eea394964b8f1330833d460b4ff3e" +dependencies = [ + "bytes", + "fxhash", + "rand", + "ring", + "rustls 0.20.4", + "rustls-native-certs", + "rustls-pemfile 0.2.1", + "slab", + "thiserror", + "tinyvec", + "tracing", + "webpki 0.22.0", +] + +[[package]] +name = "quinn-udp" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df185e5e5f7611fa6e628ed8f9633df10114b03bbaecab186ec55822c44ac727" +dependencies = [ + "futures-util", + "libc", + "mio 0.7.14", + "quinn-proto", + "socket2 0.4.4", + "tokio", + "tracing", +] + +[[package]] name = "quote" -version = "1.0.9" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" +checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" dependencies = [ "proc-macro2", ] [[package]] name = "rand" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", "rand_core", - "rand_hc", ] [[package]] name = "rand_chacha" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", "rand_core", @@ -813,46 +1593,38 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" dependencies = [ "getrandom", ] [[package]] -name = "rand_hc" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" -dependencies = [ - "rand_core", -] - -[[package]] name = "redox_syscall" -version = "0.2.8" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "742739e41cd49414de871ea5e549afb7e2a3ac77b589bcbebe8c82fab37147fc" +checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" dependencies = [ "bitflags", ] [[package]] name = "redox_users" -version = "0.4.0" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ "getrandom", "redox_syscall", + "thiserror", ] [[package]] name = "regex" -version = "1.5.4" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" +checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286" dependencies = [ "aho-corasick", "memchr", @@ -866,48 +1638,187 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" [[package]] -name = "rocksdb" -version = "0.15.0" +name = "remove_dir_all" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23d83c02c429044d58474eaf5ae31e062d0de894e21125b47437ec0edc1397e6" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" dependencies = [ + "winapi", +] + +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", "libc", - "librocksdb-sys", + "once_cell", + "spin 0.5.2", + "untrusted", + "web-sys", + "winapi", ] [[package]] name = "rust-ini" -version = "0.16.1" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55b134767a87e0b086f73a4ce569ac9ce7d202f39c8eab6caa266e2617e73ac6" +checksum = "f6d5f2436026b4f6e79dc829837d467cc7e9a55ee40e750d716713540715a2df" dependencies = [ - "cfg-if 0.1.10", + "cfg-if", "ordered-multimap", ] [[package]] -name = "rustc-hash" -version = "1.1.0" +name = "rustls" +version = "0.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35edb675feee39aec9c99fa5ff985081995a06d594114ae14cbe797ad7b7a6d7" +dependencies = [ + "base64", + "log", + "ring", + "sct 0.6.1", + "webpki 0.21.4", +] + +[[package]] +name = "rustls" +version = "0.20.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fbfeb8d0ddb84706bc597a5574ab8912817c52a397f819e5b614e2265206921" +dependencies = [ + "ring", + "sct 0.7.0", + "webpki 0.22.0", +] + +[[package]] +name = "rustls-native-certs" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0167bac7a9f490495f3c33013e7722b53cb087ecbe082fb0c6387c96f634ea50" +dependencies = [ + "openssl-probe", + "rustls-pemfile 1.0.0", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-pemfile" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +checksum = "5eebeaeb360c87bfb72e84abdb3447159c0eaececf1bef2aecd65a8be949d1c9" +dependencies = [ + "base64", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7522c9de787ff061458fe9a829dc790a3f5b22dc571694fc5883f448b94d9a9" +dependencies = [ + "base64", +] + +[[package]] +name = "rustversion" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f" [[package]] name = "ryu" -version = "1.0.5" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" +checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "schannel" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" +dependencies = [ + "lazy_static", + "winapi", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "sct" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "sct" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "security-framework" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dc14f172faf8a0194a3aded622712b0de276821addc574fa54fc0a1167e10dc" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556" +dependencies = [ + "core-foundation-sys", + "libc", +] [[package]] name = "serde" -version = "1.0.126" +version = "1.0.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03" +checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" +dependencies = [ + "serde_derive", +] [[package]] name = "serde_derive" -version = "1.0.126" +version = "1.0.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "963a7dbc9895aeac7ac90e74f34a5d5261828f79df35cbed41e10189d3804d43" +checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" dependencies = [ "proc-macro2", "quote", @@ -916,9 +1827,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.64" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79" +checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c" dependencies = [ "itoa", "ryu", @@ -926,25 +1837,79 @@ dependencies = [ ] [[package]] -name = "shlex" -version = "0.1.1" +name = "serde_urlencoded" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha-1" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.3", +] + +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] [[package]] name = "signal-hook-registry" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16f1d0fef1604ba8f7a073c7e701f213e056707210e9020af4528e0101ce11a6" +checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" dependencies = [ "libc", ] [[package]] +name = "signature" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f054c6c1a6e95179d6f23ed974060dcefb2d9388bb7256900badad682c499de4" + +[[package]] +name = "simple_asn1" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a762b1c38b9b990c694b9c2f8abe3372ce6a9ceaae6bca39cfc46e054f45745" +dependencies = [ + "num-bigint", + "num-traits", + "thiserror", + "time 0.3.9", +] + +[[package]] name = "slab" -version = "0.4.3" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f173ac3d1a7e3b28003f40de0b5ce7fe2710f9b9dc3fc38664cebee46b3b6527" +checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32" + +[[package]] +name = "smallvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" [[package]] name = "socket2" @@ -952,23 +1917,160 @@ version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", + "libc", + "winapi", +] + +[[package]] +name = "socket2" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" +dependencies = [ "libc", - "winapi 0.3.9", + "winapi", ] [[package]] name = "sodiumoxide" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7038b67c941e23501573cb7242ffb08709abe9b11eb74bceff875bbda024a6a8" +checksum = "e26be3acb6c2d9a7aac28482586a7856436af4cfe7100031d219de2d2ecb0028" dependencies = [ + "ed25519", "libc", "libsodium-sys", "serde", ] [[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[package]] +name = "spin" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c530c2b0d0bf8b69304b39fe2001993e267461948b890cd037d8ad4293fa1a0d" +dependencies = [ + "lock_api", +] + +[[package]] +name = "sqlformat" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4b7922be017ee70900be125523f38bdd644f4f06a1b16e8fa5a8ee8c34bffd4" +dependencies = [ + "itertools", + "nom 7.1.1", + "unicode_categories", +] + +[[package]] +name = "sqlx" +version = "0.5.11" +source = "git+https://github.com/open-trade/sqlx#81392f03ba36fbd670447517dbc122fddb206de7" +dependencies = [ + "sqlx-core", + "sqlx-macros", +] + +[[package]] +name = "sqlx-core" +version = "0.5.11" +source = "git+https://github.com/open-trade/sqlx#81392f03ba36fbd670447517dbc122fddb206de7" +dependencies = [ + "ahash", + "atoi", + "bitflags", + "byteorder", + "bytes", + "chrono", + "crc", + "crossbeam-queue", + "either", + "flume", + "futures-channel", + "futures-core", + "futures-executor", + "futures-intrusive", + "futures-util", + "hashlink", + "hex", + "indexmap", + "itoa", + "libc", + "libsqlite3-sys", + "log", + "memchr", + "once_cell", + "paste", + "percent-encoding", + "rustls 0.19.1", + "serde", + "serde_json", + "sha2", + "smallvec", + "sqlformat", + "sqlx-rt", + "stringprep", + "thiserror", + "tokio-stream", + "url", + "webpki 0.21.4", + "webpki-roots", +] + +[[package]] +name = "sqlx-macros" +version = "0.5.11" +source = "git+https://github.com/open-trade/sqlx#81392f03ba36fbd670447517dbc122fddb206de7" +dependencies = [ + "dotenv", + "either", + "heck", + "once_cell", + "proc-macro2", + "quote", + "serde_json", + "sha2", + "sqlx-core", + "sqlx-rt", + "syn", + "url", +] + +[[package]] +name = "sqlx-rt" +version = "0.5.11" +source = "git+https://github.com/open-trade/sqlx#81392f03ba36fbd670447517dbc122fddb206de7" +dependencies = [ + "once_cell", + "tokio", + "tokio-rustls", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "stringprep" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ee348cb74b87454fff4b551cbf727025810a004f88aeacae7f85b87f4e9a1c1" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] name = "strsim" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -976,9 +2078,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" [[package]] name = "syn" -version = "1.0.72" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1e8cdbefb79a9a5a65e0db8b47b723ee907b7c7f8496c76a1770b5c310bab82" +checksum = "04066589568b72ec65f42d65a1a52436e954b168773148893c020269563decf2" dependencies = [ "proc-macro2", "quote", @@ -986,10 +2088,30 @@ dependencies = [ ] [[package]] +name = "sync_wrapper" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20518fe4a4c9acf048008599e464deb21beeae3d3578418951a189c235a7a9a8" + +[[package]] +name = "tempfile" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" +dependencies = [ + "cfg-if", + "fastrand", + "libc", + "redox_syscall", + "remove_dir_all", + "winapi", +] + +[[package]] name = "termcolor" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" dependencies = [ "winapi-util", ] @@ -1004,34 +2126,94 @@ dependencies = [ ] [[package]] +name = "thiserror" +version = "1.0.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "time" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "time" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2702e08a7a860f005826c6815dcac101b19b5eb330c27fe4a5928fec1d20ddd" +dependencies = [ + "itoa", + "libc", + "num_threads", + "quickcheck", + "time-macros", +] + +[[package]] +name = "time-macros" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792" + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" + +[[package]] name = "tokio" -version = "0.2.25" +version = "1.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6703a273949a90131b290be1fe7b039d0fc884aa1935860dfcbe056f28cd8092" +checksum = "4903bf0427cf68dddd5aa6a93220756f8be0c34fcfa9f5e6191e103e15a31395" dependencies = [ "bytes", - "fnv", - "futures-core", - "iovec", - "lazy_static", "libc", "memchr", - "mio", - "mio-named-pipes", - "mio-uds", + "mio 0.8.3", "num_cpus", - "pin-project-lite 0.1.12", + "once_cell", + "parking_lot 0.12.0", + "pin-project-lite", "signal-hook-registry", - "slab", + "socket2 0.4.4", "tokio-macros", - "winapi 0.3.9", + "winapi", ] [[package]] name = "tokio-macros" -version = "0.2.6" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e44da00bfc73a25f814cd8d7e57a68a5c31b74b3152a0a1d1f590c97ed06265a" +checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" dependencies = [ "proc-macro2", "quote", @@ -1039,40 +2221,316 @@ dependencies = [ ] [[package]] +name = "tokio-rustls" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc6844de72e57df1980054b38be3a9f4702aba4858be64dd700181a8a6d0e1b6" +dependencies = [ + "rustls 0.19.1", + "tokio", + "webpki 0.21.4", +] + +[[package]] +name = "tokio-socks" +version = "0.5.1" +source = "git+https://github.com/open-trade/tokio-socks#3de8300fbce37e2cdaef042e016aa95058d007cf" +dependencies = [ + "bytes", + "either", + "futures-core", + "futures-sink", + "futures-util", + "pin-project", + "thiserror", + "tokio", + "tokio-util 0.6.9", +] + +[[package]] +name = "tokio-stream" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50145484efff8818b5ccd256697f36863f587da82cf8b409c53adf1e840798e3" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-tungstenite" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06cda1232a49558c46f8a504d5b93101d42c0bf7f911f12a105ba48168f821ae" +dependencies = [ + "futures-util", + "log", + "tokio", + "tungstenite", +] + +[[package]] name = "tokio-util" -version = "0.3.1" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499" +checksum = "9e99e1983e5d376cd8eb4b66604d2e99e79f5bd988c3055891dcd8c9e2604cc0" dependencies = [ "bytes", "futures-core", "futures-io", "futures-sink", "log", - "pin-project-lite 0.1.12", + "pin-project-lite", + "slab", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0edfdeb067411dba2044da6d1cb2df793dd35add7888d73c16e3381ded401764" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", "tokio", ] [[package]] name = "toml" -version = "0.5.8" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" +checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" dependencies = [ "serde", ] [[package]] +name = "tower" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a89fd63ad6adf737582df5db40d286574513c69a11dac5214dc3b5603d6713e" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tokio", + "tokio-util 0.7.1", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-http" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aba3f3efabf7fb41fae8534fc20a817013dd1c12cb45441efb6c82e6556b4cd8" +dependencies = [ + "bitflags", + "bytes", + "futures-core", + "futures-util", + "http", + "http-body", + "http-range-header", + "httpdate", + "mime", + "mime_guess", + "percent-encoding", + "pin-project-lite", + "tokio", + "tokio-util 0.7.1", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-http" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d342c6d58709c0a6d48d48dabbb62d4ef955cf5f0f3bbfd845838e7ae88dbae" +dependencies = [ + "bitflags", + "bytes", + "futures-core", + "futures-util", + "http", + "http-body", + "http-range-header", + "pin-project-lite", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "343bc9466d3fe6b0f960ef45960509f84480bf4fd96f92901afe7ff3df9d3a62" + +[[package]] +name = "tower-service" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" + +[[package]] +name = "tracing" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0ecdcb44a79f0fe9844f0c4f33a342cbcbb5117de8001e6ba0dc2351327d09" +dependencies = [ + "cfg-if", + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc6b8ad3567499f98a1db7a752b07a7c8c7c7c34c332ec00effb2b0027974b7c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f54c8ca710e81886d498c2fd3331b56c93aa248d49de2222ad2742247c60072f" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "try-lock" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" + +[[package]] +name = "tungstenite" +version = "0.17.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d96a2dea40e7570482f28eb57afbe42d97551905da6a9400acc5c328d24004f5" +dependencies = [ + "base64", + "byteorder", + "bytes", + "http", + "httparse", + "log", + "rand", + "sha-1", + "thiserror", + "url", + "utf-8", +] + +[[package]] +name = "typenum" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" + +[[package]] +name = "unicase" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" +dependencies = [ + "version_check", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" + +[[package]] +name = "unicode-normalization" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-segmentation" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" + +[[package]] name = "unicode-width" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" +checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" [[package]] name = "unicode-xid" -version = "0.2.2" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04" + +[[package]] +name = "unicode_categories" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" +checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" + +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + +[[package]] +name = "url" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" +dependencies = [ + "form_urlencoded", + "idna", + "matches", + "percent-encoding", +] + +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + +[[package]] +name = "uuid" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" +dependencies = [ + "getrandom", +] + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "vec_map" @@ -1082,9 +2540,30 @@ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] name = "version_check" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "walkdir" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +dependencies = [ + "same-file", + "winapi", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +dependencies = [ + "log", + "try-lock", +] [[package]] name = "wasi" @@ -1093,16 +2572,124 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" [[package]] -name = "whoami" -version = "0.9.0" +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7884773ab69074615cb8f8425d0e53f11710786158704fca70f53e71b0e05504" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] -name = "winapi" -version = "0.2.8" +name = "wasm-bindgen" +version = "0.2.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27370197c907c55e3f1a9fbe26f44e937fe6451368324e009cba39e139dc08ad" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53e04185bfa3a779273da532f5025e33398409573f348985af9a1cbf3774d3f4" +dependencies = [ + "bumpalo", + "lazy_static", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17cae7ff784d7e83a2fe7611cfe766ecf034111b49deb850a3dc7699c08251f5" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" +checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d554b7f530dee5964d9a9468d95c1f8b8acae4f282807e7d27d4b03099a46744" + +[[package]] +name = "web-sys" +version = "0.3.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b17e741662c70c8bd24ac5c5b18de314a2c26c32bf8346ee1e6f53de919c283" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki" +version = "0.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "webpki" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "webpki-roots" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aabe153544e473b775453675851ecc86863d2a81d786d741f6b76778f2a48940" +dependencies = [ + "webpki 0.21.4", +] + +[[package]] +name = "which" +version = "4.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c4fb54e6113b6a8772ee41c3404fb0301ac79604489467e0a9ce1f3e97c24ae" +dependencies = [ + "either", + "lazy_static", + "libc", +] + +[[package]] +name = "whoami" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524b58fa5a20a2fb3014dd6358b70e6579692a56ef6fce928834e488f42f65e8" +dependencies = [ + "wasm-bindgen", + "web-sys", +] [[package]] name = "winapi" @@ -1115,12 +2702,6 @@ dependencies = [ ] [[package]] -name = "winapi-build" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" - -[[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1132,7 +2713,7 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" dependencies = [ - "winapi 0.3.9", + "winapi", ] [[package]] @@ -1142,38 +2723,77 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] +name = "windows-sys" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +dependencies = [ + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" + +[[package]] +name = "windows_i686_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" + +[[package]] +name = "windows_i686_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" + +[[package]] name = "winreg" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9" dependencies = [ - "winapi 0.3.9", + "winapi", ] [[package]] -name = "ws2_32-sys" -version = "0.2.1" +name = "zeroize" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" -dependencies = [ - "winapi 0.2.8", - "winapi-build", -] +checksum = "94693807d016b2f2d2e14420eb3bfcca689311ff775dcf113d74ea624b7cdf07" [[package]] name = "zstd" -version = "0.8.1+zstd.1.5.0" +version = "0.9.2+zstd.1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357d6bb1bd9c6f6a55a5a15c74d01260b272f724dc60cc829b86ebd2172ac5ef" +checksum = "2390ea1bf6c038c39674f22d95f0564725fc06034a47129179810b2fc58caa54" dependencies = [ "zstd-safe", ] [[package]] name = "zstd-safe" -version = "4.1.0+zstd.1.5.0" +version = "4.1.3+zstd.1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d30375f78e185ca4c91930f42ea2c0162f9aa29737032501f93b79266d985ae7" +checksum = "e99d81b99fb3c2c2c794e3fe56c305c63d5173a16a46b5850b07c935ffc7db79" dependencies = [ "libc", "zstd-sys", @@ -1181,9 +2801,9 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "1.6.0+zstd.1.5.0" +version = "1.6.2+zstd.1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2141bed8922b427761470e6bbfeff255da94fa20b0bbeab0d9297fcaf71e3aa7" +checksum = "2daf2f248d9ea44454bfcb2516534e8b8ad2fc91bf818a1885495fc42bc8ac9f" dependencies = [ "cc", "libc", @@ -1,9 +1,10 @@ [package] name = "hbbs" -version = "1.1.4" -authors = ["open-trade <[email protected]>"] -edition = "2018" -build= "build.rs" +version = "1.1.5" +authors = ["open-trade <[email protected]>"] +edition = "2021" +build = "build.rs" +default-run = "hbbs" [[bin]] name = "hbbr" @@ -17,22 +18,28 @@ serde_derive = "1.0" serde = "1.0" serde_json = "1.0" lazy_static = "1.4" -clap = "2.33" -rust-ini = "0.16" -minreq = { version = "2.3.1", features = ["punycode"] } +clap = "2" +rust-ini = "0.18" +minreq = { version = "2.4", features = ["punycode"] } machine-uid = "0.2" mac_address = "1.1" -whoami = "0.9" +whoami = "1.2" base64 = "0.13" -cryptoxide = "0.3" - -[build-dependencies] -hbb_common = { path = "libs/hbb_common" } - -[workspace] -members = ["libs/hbb_common"] - -[dependencies.rocksdb] -default-features = false -features = ["lz4"] -version = "0.15" +axum = { version = "0.5", features = ["headers"] } +sqlx = { git = "https://github.com/open-trade/sqlx", features = [ "runtime-tokio-rustls", "sqlite", "macros", "chrono", "json" ] } +deadpool = "0.8" +async-trait = "0.1" +async-speed-limit = { git = "https://github.com/open-trade/async-speed-limit" } +uuid = { version = "0.8", features = ["v4"] } +bcrypt = "0.12" +chrono = "0.4" +jsonwebtoken = "8" +headers = "0.3" +once_cell = "1.8" +sodiumoxide = "0.2" +tokio-tungstenite = "0.17" +tungstenite = "0.17" +regex = "1.4" +tower-http = { version = "0.2", features = ["fs", "trace", "cors"] } +http = "0.2" +flexi_logger = { version = "0.22", features = ["async", "use_chrono_for_offset"] } diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index d0b7560..0000000 --- a/Dockerfile +++ /dev/null @@ -1,4 +0,0 @@ -FROM ubuntu:20.04 -COPY target/release/hbbs /usr/bin/hbbs -COPY target/release/hbbr /usr/bin/hbbr -WORKDIR /root diff --git a/README.md b/README.md new file mode 100644 index 0000000..109a903 --- /dev/null +++ b/README.md @@ -0,0 +1,23 @@ +# RustDesk Server Program + +<<<<<<< HEAD +Self-host your own RustDesk server, it is free and open source. + +``` +cargo build --release +``` + +Two executables will be generated in target/release. + - hbbs - RustDesk ID/Rendezvous server + - hbbr - RustDesk relay server + +[**Manual**](https://rustdesk.com/docs/en/self-host/) +======= +**Could you please also help finish below "RustDesk Self-Hosting Sever Survey"? So that we can make it better.** https://forms.gle/9sDqAC5JBuB4b52S6 + +If you are looking for an open source implementation, please go to [rustdesk-server-demo](https://github.com/rustdesk/rustdesk-server-demo). + +[Download](https://github.com/rustdesk/rustdesk-server/releases) + +[Doc](https://rustdesk.com/docs/en/self-host) +>>>>>>> 5043b7ce7f5a2230661381cb9c63f84c60414035 diff --git a/db_v2.sqlite3 b/db_v2.sqlite3 Binary files differnew file mode 100644 index 0000000..1985922 --- /dev/null +++ b/db_v2.sqlite3 diff --git a/libs/hbb_common b/libs/hbb_common deleted file mode 160000 -Subproject ec453e5e65bdb3d082cca30416880e4ee0f3665 diff --git a/spk/INFO b/spk/INFO deleted file mode 100755 index a446791..0000000 --- a/spk/INFO +++ /dev/null @@ -1,18 +0,0 @@ -package="RustDesk Server" -version="1.1.3" -description="RustDesk is a remote desktop software allowing your own rendezvous/relay server. It attempts to make direct connect via TCP hole punch first, and then forward via relay server if direct connection fails. 4 ports are used. NAT test port: 21115(tcp), ID/rendezvous port: 21116(tcp/udp), relay port: 21117(tcp), Email: (), Key: ()" -displayname="RustDesk Rendezvous/Relay Server" -maintainer="CarrieZ Studio" -maintainer_url="https://rustdesk.com/zh/" -distributor="RustDesk & 裙下孤魂" -support_url="https://rustdesk.com/contact/" -arch="apollolake avoton braswell broadwell broadwellnk bromolow cedarview denverton dockerx64 geminilake grantley kvmx64 purley v1000 x86 x86_64" -os_min_ver="6.1" -reloadui="yes" -startable="yes" -thirdparty="yes" -install_reboot="no" -install_dep_packages="" -install_conflict_packages="" -extractsize="" -checkport="no" diff --git a/spk/PACKAGE_ICON.PNG b/spk/PACKAGE_ICON.PNG Binary files differdeleted file mode 100755 index c6c0367..0000000 --- a/spk/PACKAGE_ICON.PNG +++ /dev/null diff --git a/spk/PACKAGE_ICON_256.PNG b/spk/PACKAGE_ICON_256.PNG Binary files differdeleted file mode 100755 index a80abd5..0000000 --- a/spk/PACKAGE_ICON_256.PNG +++ /dev/null diff --git a/spk/WIZARD_UIFILES/install_uifile b/spk/WIZARD_UIFILES/install_uifile deleted file mode 100755 index 1da2baa..0000000 --- a/spk/WIZARD_UIFILES/install_uifile +++ /dev/null @@ -1,54 +0,0 @@ -[{ - "step_title": "Install Settings", - "items": [{ - "type": "textfield", - "desc": "Listening Ports", - "subitems": [{ - "key": "hbbs_port", - "desc": "RustDesk ID Server Port", - "defaultValue": "21116", - "validator": { - "allowBlank": false, - "regex": { - "expr": "/^([0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$/", - "errorText": "Digit number only" - } - } - }, { - "key": "hbbr_port", - "desc": "RustDesk Relay Server Port", - "defaultValue": "21117", - "validator": { - "allowBlank": false, - "regex": { - "expr": "/^([0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$/", - "errorText": "Digit number only" - } - } - }] - },{ - "type": "textfield", - "desc": "Registered email, check http://rustdesk.com/server for more information", - "subitems": [{ - "key": "email", - "desc": "Email", - "validator": { - "allowBlank": false, - "regex": { - "expr": "/^\\w+([-+.']\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$/", - "errorText": "Invalid email format" - } - } - }] - },{ - "type": "textfield", - "desc": "Only allow the client with the same key", - "subitems": [{ - "key": "key", - "desc": "Key", - "validator": { - "allowBlank": true - } - }] - }] - }] diff --git a/spk/scripts/RustDesk_Server.sc b/spk/scripts/RustDesk_Server.sc deleted file mode 100755 index 37eb1f4..0000000 --- a/spk/scripts/RustDesk_Server.sc +++ /dev/null @@ -1,23 +0,0 @@ -[RustDesk_Server_HBBR] -title="RustDesk Server (HBBR_TCP)" -desc="RustDesk Server" -port_forward="yes" -dst.ports="21117/tcp" - -[RustDesk_Server_HBBS_TCP] -title="RustDesk Server (HBBS_TCP)" -desc="RustDesk Server" -port_forward="yes" -dst.ports="21116/tcp" - -[RustDesk_Server_HBBS_UDP] -title="RustDesk Server (HBBS_UDP)" -desc="RustDesk Server" -port_forward="yes" -dst.ports="21116/udp" - -[RustDesk_Server_NAT_TCP] -title="RustDesk Server (NAT_TCP)" -desc="RustDesk Server" -port_forward="yes" -dst.ports="21115/tcp" diff --git a/spk/scripts/installer b/spk/scripts/installer deleted file mode 100755 index 9d6bb71..0000000 --- a/spk/scripts/installer +++ /dev/null @@ -1,167 +0,0 @@ -#!/bin/sh - -PACKAGE_NAME="$SYNOPKG_PKGNAME" -PACKAGE_BASE="/var/packages/${PACKAGE_NAME}/target" -PACKAGE_SSS="/var/packages/${PACKAGE_NAME}/scripts/start-stop-status" - -SERVICETOOL="/usr/syno/bin/servicetool" -GETKEYVALUE="/usr/syno/bin/synogetkeyvalue" -SETKEYVALUE="/usr/syno/bin/synosetkeyvalue" -FWFILENAME="RustDesk_Server.sc" - -[ "${hbbr_port}" == "" ] && hbbr_port="21117" -[ "${hbbs_port}" == "" ] && hbbs_port="21116" -[ "${key}" == "" ] && key="" -[ "${email}" == "" ] && email="" -nat_port=`expr ${hbbs_port} - 1` - -preinst() { - exit 0 -} - -postinst() { - if [ "${SYNOPKG_PKG_STATUS}" == "INSTALL" ]; then - # 导入另一个RustDesk服务器数据 - import_db="false" - import_all="false" - if [ "${rds_old_import_all}" == "true" ]; then - rds_old_import_db="true" - import_all="true" - elif [ "${rds_import_all}" == "true" ]; then - rds_import_db="true" - import_all="true" - fi - if [ "${rds_old_import_db}" == "true" ]; then - import_db="true" - PACKAGE_IMPORT_DIR="/var/packages/RustDesk_Server" - elif [ "${rds_import_db}" == "true" ]; then - import_db="true" - PACKAGE_IMPORT_DIR="/var/packages/RustDesk Server" - fi - if [ "${import_db}" == "true" ]; then - [ -x "${PACKAGE_IMPORT_DIR}/scripts/start-stop-status" ] \ - && SYNOPKG_PKGNAME="RustDesk Server" "${PACKAGE_IMPORT_DIR}/scripts/start-stop-status" stop 2>&1 - [ -f "${PACKAGE_IMPORT_DIR}/enabled" ] && rm -f "${PACKAGE_IMPORT_DIR}/enabled" - [ -d "${PACKAGE_IMPORT_DIR}/target/hbbs.db" ] && cp -prf "${PACKAGE_IMPORT_DIR}/target/hbbs.db" "${PACKAGE_BASE}" - fi - if [ "${import_all}" == "true" ]; then - [ -d "${PACKAGE_IMPORT_DIR}/target/logs" ] && cp -prf "${PACKAGE_IMPORT_DIR}/target/logs" "${PACKAGE_BASE}" - fi - - # 添加应用配置 - sed -i "s/relay port: 21117/relay port: ${hbbr_port}/" "/var/packages/${PACKAGE_NAME}/INFO" - sed -i "s/ID\/rendezvous port: 21116/ID\/rendezvous port: ${hbbs_port}/" "/var/packages/${PACKAGE_NAME}/INFO" - sed -i "s/NAT test port: 21115/NAT test port: ${nat_port}/" "/var/packages/${PACKAGE_NAME}/INFO" - sed -i "s/Key: ()/Key: (${key})/" "/var/packages/${PACKAGE_NAME}/INFO" - sed -i "s/Email: ()/Email: (${email})/" "/var/packages/${PACKAGE_NAME}/INFO" - sed -i "s/21117/${hbbr_port}/" "/var/packages/${PACKAGE_NAME}/scripts/${FWFILENAME}" - sed -i "s/21116/${hbbs_port}/" "/var/packages/${PACKAGE_NAME}/scripts/${FWFILENAME}" - sed -i "s/21115/${nat_port}/" "/var/packages/${PACKAGE_NAME}/scripts/${FWFILENAME}" - sed -i "s/port=[^ ]*/port=${hbbr_port}/g" "${PACKAGE_BASE}/config/hbbr.conf" - sed -i "s/port=[^ ]*/port=${hbbs_port}/g" "${PACKAGE_BASE}/config/hbbs.conf" - sed -i "s/key=[^ ]*/key=${key}/g" "${PACKAGE_BASE}/config/hbbs.conf" - sed -i "s/email=[^ ]*/email=${email}/g" "${PACKAGE_BASE}/config/hbbs.conf" - - # 添加防火墙配置 - cat "/var/packages/${PACKAGE_NAME}/scripts/${FWFILENAME}" >"/tmp/${FWFILENAME}" - ${SERVICETOOL} --install-configure-file --package "/tmp/${FWFILENAME}" >/dev/null - rm -f "/tmp/${FWFILENAME}" - - # 设置文件权限 - chmod -R 755 "${PACKAGE_BASE}"/* - chmod -R 755 "/var/packages/${PACKAGE_NAME}/scripts"/* - chmod -R 755 "/var/packages/${PACKAGE_NAME}/WIZARD_UIFILES"/* - chmod 644 "/var/packages/${PACKAGE_NAME}/INFO" - fi - - exit 0 -} - -preuninst() { - # 停用套件 - "${PACKAGE_SSS}" stop - - # 删除防火墙配置 - if [ "${SYNOPKG_PKG_STATUS}" == "UNINSTALL" ]; then - ${SERVICETOOL} --remove-configure-file --package "${FWFILENAME}" >/dev/null - fi - - exit 0 -} - -postuninst() { - # 删除不必要的目录... - if [ -d "/usr/syno/etc/packages/${PACKAGE_NAME}" ]; then - rm -rf "/usr/syno/etc/packages/${PACKAGE_NAME}" - fi - - exit 0 -} - -preupgrade() { - # 停用套件 - "${PACKAGE_SSS}" stop - -# Not working yet... -# # 检索旧设置... -# hbbr_port=`${GETKEYVALUE} "${PACKAGE_BASE}/config/hbbr.conf" port` -# hbbs_port=`${GETKEYVALUE} "${PACKAGE_BASE}/config/hbbs.conf" port` -# sed -i "s/21117/${hbbr_port}/" "/var/packages/${PACKAGE_NAME}/WIZARD_UIFILES/upgrade_uifile" -# sed -i "s/21116/${hbbs_port}/" "/var/packages/${PACKAGE_NAME}/WIZARD_UIFILES/upgrade_uifile" -## Not working yet... - - # 备份数据文件... - if [ -d "${SYNOPKG_PKGDEST}" ]; then - DIRS4BACKUP="data logs hbbs.db config" - for DIR in $DIRS4BACKUP; do - if [ -d "${SYNOPKG_PKGDEST}/${DIR}" ]; then - mkdir -p "${SYNOPKG_PKGDEST}/../${PACKAGE_NAME}_upgrade/${DIR}" - mv "${SYNOPKG_PKGDEST}/${DIR}"/* "${SYNOPKG_PKGDEST}/../${PACKAGE_NAME}_upgrade/${DIR}" - rmdir "${SYNOPKG_PKGDEST}/${DIR}" - elif [ -f "${SYNOPKG_PKGDEST}/${DIR}" ]; then - mv "${SYNOPKG_PKGDEST}/${DIR}" "${SYNOPKG_PKGDEST}/../${PACKAGE_NAME}_upgrade" - fi - done - fi - - exit 0 -} - -postupgrade() { - # 恢复数据文件... - if [ -d "${SYNOPKG_PKGDEST}/../${PACKAGE_NAME}_upgrade" ]; then - for DIR in `ls "${SYNOPKG_PKGDEST}/../${PACKAGE_NAME}_upgrade"` - do - if [ -d "${SYNOPKG_PKGDEST}/../${PACKAGE_NAME}_upgrade/${DIR}" ]; then - [ ! -d "${SYNOPKG_PKGDEST}/${DIR}" ] && mkdir "${SYNOPKG_PKGDEST}/${DIR}" - mv "${SYNOPKG_PKGDEST}/../${PACKAGE_NAME}_upgrade/${DIR}"/* "${SYNOPKG_PKGDEST}/${DIR}" - rmdir "${SYNOPKG_PKGDEST}/../${PACKAGE_NAME}_upgrade/${DIR}" - elif [ -f "${SYNOPKG_PKGDEST}/../${PACKAGE_NAME}_upgrade/${DIR}" ]; then - mv "${SYNOPKG_PKGDEST}/../${PACKAGE_NAME}_upgrade/${DIR}" "${SYNOPKG_PKGDEST}" - fi - done - rmdir "${SYNOPKG_PKGDEST}/../${PACKAGE_NAME}_upgrade" - fi - - # 恢复设置... - hbbr_port=`${GETKEYVALUE} "${PACKAGE_BASE}/config/hbbr.conf" port` >>/tmp/wakko.txt - hbbs_port=`${GETKEYVALUE} "${PACKAGE_BASE}/config/hbbs.conf" port` >>/tmp/wakko.txt - nat_port=`expr ${hbbs_port} - 1` - key=`${GETKEYVALUE} "${PACKAGE_BASE}/config/hbbs.conf" key` >>/tmp/wakko.txt - email=`${GETKEYVALUE} "${PACKAGE_BASE}/config/hbbs.conf" email` >>/tmp/wakko.txt - sed -i "s/relay port: 21117/relay port: ${hbbr_port}/" "/var/packages/${PACKAGE_NAME}/INFO" >>/tmp/wakko.txt - sed -i "s/ID\/rendezvous port: 21116/ID\/rendezvous port: ${hbbs_port}/" "/var/packages/${PACKAGE_NAME}/INFO" >>/tmp/wakko.txt - sed -i "s/NAT test port: 21115/NAT test port: ${nat_port}/" "/var/packages/${PACKAGE_NAME}/INFO" >>/tmp/wakko.txt - sed -i "s/Key: ()/Key: (${key})/" "/var/packages/${PACKAGE_NAME}/INFO" - sed -i "s/Email: ()/Email: (${email})/" "/var/packages/${PACKAGE_NAME}/INFO" - sed -i "s/21117/${hbbr_port}/" "/var/packages/${PACKAGE_NAME}/scripts/${FWFILENAME}" >>/tmp/wakko.txt - sed -i "s/21116/${hbbs_port}/" "/var/packages/${PACKAGE_NAME}/scripts/${FWFILENAME}" >>/tmp/wakko.txt - sed -i "s/21115/${nat_port}/" "/var/packages/${PACKAGE_NAME}/scripts/${FWFILENAME}" >>/tmp/wakko.txt - - # 设置文件权限 - chmod -R 755 "/var/packages/${PACKAGE_NAME}/scripts"/* - chmod -R 755 "/var/packages/${PACKAGE_NAME}/WIZARD_UIFILES"/* - chmod 644 "/var/packages/${PACKAGE_NAME}/INFO" - - exit 0 -} diff --git a/spk/scripts/postinst b/spk/scripts/postinst deleted file mode 100755 index f6c4bd9..0000000 --- a/spk/scripts/postinst +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -. "`dirname \"$0\"`/installer" -`basename "$0"` >$SYNOPKG_TEMP_LOGFILE diff --git a/spk/scripts/postuninst b/spk/scripts/postuninst deleted file mode 100755 index f6c4bd9..0000000 --- a/spk/scripts/postuninst +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -. "`dirname \"$0\"`/installer" -`basename "$0"` >$SYNOPKG_TEMP_LOGFILE diff --git a/spk/scripts/postupgrade b/spk/scripts/postupgrade deleted file mode 100755 index f6c4bd9..0000000 --- a/spk/scripts/postupgrade +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -. "`dirname \"$0\"`/installer" -`basename "$0"` >$SYNOPKG_TEMP_LOGFILE diff --git a/spk/scripts/preinst b/spk/scripts/preinst deleted file mode 100755 index f6c4bd9..0000000 --- a/spk/scripts/preinst +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -. "`dirname \"$0\"`/installer" -`basename "$0"` >$SYNOPKG_TEMP_LOGFILE diff --git a/spk/scripts/preuninst b/spk/scripts/preuninst deleted file mode 100755 index f6c4bd9..0000000 --- a/spk/scripts/preuninst +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -. "`dirname \"$0\"`/installer" -`basename "$0"` >$SYNOPKG_TEMP_LOGFILE diff --git a/spk/scripts/preupgrade b/spk/scripts/preupgrade deleted file mode 100755 index f6c4bd9..0000000 --- a/spk/scripts/preupgrade +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -. "`dirname \"$0\"`/installer" -`basename "$0"` >$SYNOPKG_TEMP_LOGFILE diff --git a/spk/scripts/start-stop-status b/spk/scripts/start-stop-status deleted file mode 100755 index 4af2f36..0000000 --- a/spk/scripts/start-stop-status +++ /dev/null @@ -1,158 +0,0 @@ -#!/bin/sh - - -sError="ERROR: " -[ ! -z "$SYNOPKG_PKGNAME" ] && sError="<br />${sError}" -TIMEOUT=120 -PACKAGE_NAME="RustDesk Server" -PACKAGE_BASE="/var/packages/${PACKAGE_NAME}/target" -HBBR_BIN="${PACKAGE_BASE}/bin/hbbr" -HBBR_PORT=`synogetkeyvalue "${PACKAGE_BASE}/config/hbbr.conf" port` -HBBR_LOG="/var/log/hbbr.log" -HBBS_BIN="${PACKAGE_BASE}/bin/hbbs" -HBBS_PORT=`synogetkeyvalue "${PACKAGE_BASE}/config/hbbs.conf" port` -KEY=`synogetkeyvalue "${PACKAGE_BASE}/config/hbbs.conf" key` -EMAIL=`synogetkeyvalue "${PACKAGE_BASE}/config/hbbs.conf" email` -HBBS_LOG="/var/log/hbbs.log" -PACKAGE_ENABLED="/var/packages/${PACKAGE_NAME}/enabled" -PS_CMD="/bin/ps -w" -DSM_MAJORVERSION=`synogetkeyvalue /etc.defaults/VERSION majorversion` -if [[ $DSM_MAJORVERSION -gt 5 ]]; then - PS_CMD="$PS_CMD -x" -fi - -CheckIfDaemonAlive() { - local PID="$1" - PROCESS_ALIVE="0" - [ -z "$PID" ] && return 1 - - kill -0 "$PID" - [ "0" == "$?" ] && PROCESS_ALIVE="1" -} - -running_hbbr() { - local PID=$(${PS_CMD} | sed -e 's/^[ \t]*//' | grep -v grep | grep hbbr | grep "${PACKAGE_NAME}" | head -n1 | cut -f1 -d' ') - CheckIfDaemonAlive $PID - [ "0" == "$PROCESS_ALIVE" ] && return 1 - return 0 -} - -running_hbbs() { - local PID=$(${PS_CMD} | sed -e 's/^[ \t]*//' | grep -v grep | grep hbbs | grep "${PACKAGE_NAME}" | head -n1 | cut -f1 -d' ') - CheckIfDaemonAlive $PID - [ "0" == "$PROCESS_ALIVE" ] && return 1 - return 0 -} - -start() { - [ "$SYNOPKG_TEMP_LOGFILE" == "" ] && SYNOPKG_TEMP_LOGFILE="/var/log/rustdeskserver.start.log" - LANG=C cd "$PACKAGE_BASE" && (nohup "$HBBR_BIN" -p $HBBR_PORT -k "$KEY" -m "$EMAIL" > "$HBBR_LOG" 2>&1 &) && (nohup "$HBBS_BIN" -p $HBBS_PORT -k "$KEY" -m "$EMAIL" > "$HBBS_LOG" 2>&1 &) - - - i=0 - while true; do - if ! running_hbbr || ! running_hbbs ; then -# echo "WAIT: ${i}s of ${TIMEOUT}s" - sleep 5s - i=$((i+5)) - else - break - fi - [ $i -ge $TIMEOUT ] && break - done - - # 检查hbbr进程状态 - if ! running_hbbr ; then - echo -e "${sError}hbbr process not running" | tee -a $SYNOPKG_TEMP_LOGFILE - stop - return 1 - fi - - # 检查hbbs进程状态 - if ! running_hbbs ; then - echo -e "${sError}hbbs process not running" | tee -a $SYNOPKG_TEMP_LOGFILE - stop - return 1 - fi - - return 0 -} - -stop() { - [ "$SYNOPKG_TEMP_LOGFILE" == "" ] && SYNOPKG_TEMP_LOGFILE="/var/log/rustdeskserver.stop.log" - # 检查hbbr进程状态 - if running_hbbr ; then - local PID=$(${PS_CMD} | sed -e 's/^[ \t]*//' | grep -v grep | grep hbbr | grep "${PACKAGE_NAME}" | head -n1 | cut -f1 -d' ') - [ -z "$PID" ] && return 0 - kill -15 $PID - sleep 5s - - # 检查hbbr进程状态 - if running_hbbr ; then - kill -9 $PID - sleep 5s - if running_hbbr ; then - echo "${sError}Failed to kill hbbr process(pid=$PID)!" | tee -a $SYNOPKG_TEMP_LOGFILE - return 1 - fi - fi - fi - - # 检查hbbs进程状态 - if running_hbbs ; then - local PID=$(${PS_CMD} | sed -e 's/^[ \t]*//' | grep -v grep | grep hbbs | grep "${PACKAGE_NAME}" | head -n1 | cut -f1 -d' ') - [ -z "$PID" ] && return 0 - kill -15 $PID - sleep 5s - - # 检查hbbs进程状态 - if running_hbbs ; then - kill -9 $PID - sleep 5s - if running_hbbs ; then - echo "${sError}无法关闭hbbs进程 (pid=$PID)!" | tee -a $SYNOPKG_TEMP_LOGFILE - return 1 - fi - fi - fi - - return 0 -} - -case $1 in - start) - # 启动服务器 - start - exit $? - ;; - stop) - # 关闭服务器 - stop - exit $? - ;; - status) - # 检查套件开关 - if [ ! -f "${PACKAGE_ENABLED}" ]; then - echo "${sError}package not started" | tee -a $SYNOPKG_TEMP_LOGFILE - exit 0 - fi - - # 检查hbbr进程状态 - if ! running_hbbr ; then - echo "${sError}hbbr process killed" | tee -a $SYNOPKG_TEMP_LOGFILE - exit 1 - fi - - # 检查hbbs进程状态 - if ! running_hbbs ; then - echo "${sError}hbbs process killed" | tee -a $SYNOPKG_TEMP_LOGFILE - exit 1 - fi - - exit 0 - ;; - log) - echo "$PACKAGE_BASE/logs/server.log" - exit 0 - ;; -esac diff --git a/src/common.rs b/src/common.rs new file mode 100644 index 0000000..473d730 --- /dev/null +++ b/src/common.rs @@ -0,0 +1,128 @@ +use clap::App; +use hbb_common::{anyhow::Context, log, ResultType}; +use ini::Ini; +use sodiumoxide::crypto::sign; +use std::{ + collections::HashMap, + io::prelude::*, + io::Read, + net::{IpAddr, SocketAddr}, + time::{Instant, SystemTime}, +}; + +pub(crate) fn get_expired_time() -> Instant { + let now = Instant::now(); + now.checked_sub(std::time::Duration::from_secs(3600)) + .unwrap_or(now) +} + +pub(crate) fn test_if_valid_server(host: &str, name: &str) -> ResultType<SocketAddr> { + use std::net::ToSocketAddrs; + let res = if host.contains(":") { + host.to_socket_addrs()?.next().context("") + } else { + format!("{}:{}", host, 0) + .to_socket_addrs()? + .next() + .context("") + }; + if res.is_err() { + log::error!("Invalid {} {}: {:?}", name, host, res); + } + res +} + +pub(crate) fn get_servers(s: &str, tag: &str) -> Vec<String> { + let servers: Vec<String> = s + .split(",") + .filter(|x| !x.is_empty() && test_if_valid_server(x, tag).is_ok()) + .map(|x| x.to_owned()) + .collect(); + log::info!("{}={:?}", tag, servers); + servers +} + +#[inline] +fn arg_name(name: &str) -> String { + name.to_uppercase().replace("_", "-") +} + +pub fn init_args(args: &str, name: &str, about: &str) { + let matches = App::new(name) + .version(crate::version::VERSION) + .author("Purslane Ltd. <[email protected]>") + .about(about) + .args_from_usage(&args) + .get_matches(); + if let Ok(v) = Ini::load_from_file(".env") { + if let Some(section) = v.section(None::<String>) { + section + .iter() + .for_each(|(k, v)| std::env::set_var(arg_name(k), v)); + } + } + if let Some(config) = matches.value_of("config") { + if let Ok(v) = Ini::load_from_file(config) { + if let Some(section) = v.section(None::<String>) { + section + .iter() + .for_each(|(k, v)| std::env::set_var(arg_name(k), v)); + } + } + } + for (k, v) in matches.args { + if let Some(v) = v.vals.get(0) { + std::env::set_var(arg_name(k), v.to_string_lossy().to_string()); + } + } +} + +#[inline] +pub fn get_arg(name: &str) -> String { + get_arg_or(name, "".to_owned()) +} + +#[inline] +pub fn get_arg_or(name: &str, default: String) -> String { + std::env::var(arg_name(name)).unwrap_or(default) +} + +#[inline] +pub fn now() -> u64 { + SystemTime::now() + .duration_since(SystemTime::UNIX_EPOCH) + .map(|x| x.as_secs()) + .unwrap_or_default() +} + +pub fn gen_sk() -> (String, Option<sign::SecretKey>) { + let sk_file = "id_ed25519"; + if let Ok(mut file) = std::fs::File::open(sk_file) { + let mut contents = String::new(); + if file.read_to_string(&mut contents).is_ok() { + let sk = base64::decode(&contents).unwrap_or_default(); + if sk.len() == sign::SECRETKEYBYTES { + let mut tmp = [0u8; sign::SECRETKEYBYTES]; + tmp[..].copy_from_slice(&sk); + let pk = base64::encode(&tmp[sign::SECRETKEYBYTES / 2..]); + log::info!("Private key comes from {}", sk_file); + return (pk, Some(sign::SecretKey(tmp))); + } + } + } else { + let (pk, sk) = sign::gen_keypair(); + let pub_file = format!("{}.pub", sk_file); + if let Ok(mut f) = std::fs::File::create(&pub_file) { + f.write_all(base64::encode(pk).as_bytes()).ok(); + if let Ok(mut f) = std::fs::File::create(sk_file) { + let s = base64::encode(&sk); + if f.write_all(s.as_bytes()).is_ok() { + log::info!("Private/public key written to {}/{}", sk_file, pub_file); + log::debug!("Public key: {:?}", pk); + return (base64::encode(pk), Some(sk)); + } + } + } + } + ("".to_owned(), None) +} diff --git a/src/database.rs b/src/database.rs new file mode 100644 index 0000000..5a199e6 --- /dev/null +++ b/src/database.rs @@ -0,0 +1,231 @@ +use async_trait::async_trait; +use hbb_common::{log, ResultType}; +use serde_json::value::Value; +use sqlx::{ + sqlite::SqliteConnectOptions, ConnectOptions, Connection, Error as SqlxError, SqliteConnection, +}; +use std::{ops::DerefMut, str::FromStr}; +//use sqlx::postgres::PgPoolOptions; +//use sqlx::mysql::MySqlPoolOptions; + +pub(crate) type DB = sqlx::Sqlite; +pub(crate) type MapValue = serde_json::map::Map<String, Value>; +pub(crate) type MapStr = std::collections::HashMap<String, String>; +type Pool = deadpool::managed::Pool<DbPool>; + +pub struct DbPool { + url: String, +} + +#[async_trait] +impl deadpool::managed::Manager for DbPool { + type Type = SqliteConnection; + type Error = SqlxError; + async fn create(&self) -> Result<SqliteConnection, SqlxError> { + let mut opt = SqliteConnectOptions::from_str(&self.url).unwrap(); + opt.log_statements(log::LevelFilter::Debug); + SqliteConnection::connect_with(&opt).await + } + async fn recycle( + &self, + obj: &mut SqliteConnection, + ) -> deadpool::managed::RecycleResult<SqlxError> { + Ok(obj.ping().await?) + } +} + +#[derive(Clone)] +pub struct Database { + pool: Pool, +} + +#[derive(Default)] +pub struct Peer { + pub guid: Vec<u8>, + pub id: String, + pub uuid: Vec<u8>, + pub pk: Vec<u8>, + pub user: Option<Vec<u8>>, + pub info: String, + pub status: Option<i64>, +} + +impl Database { + pub async fn new(url: &str) -> ResultType<Database> { + if !std::path::Path::new(url).exists() { + std::fs::File::create(url).ok(); + } + let n: usize = std::env::var("MAX_CONNECTIONS") + .unwrap_or("1".to_owned()) + .parse() + .unwrap_or(1); + log::info!("MAX_CONNECTIONS={}", n); + let pool = Pool::new( + DbPool { + url: url.to_owned(), + }, + n, + ); + let _ = pool.get().await?; // test + let db = Database { pool }; + db.create_tables().await?; + Ok(db) + } + + async fn create_tables(&self) -> ResultType<()> { + sqlx::query!( + " + create table if not exists peer ( + guid blob primary key not null, + id varchar(100) not null, + uuid blob not null, + pk blob not null, + created_at datetime not null default(current_timestamp), + user blob, + status tinyint, + note varchar(300), + info text not null + ) without rowid; + create unique index if not exists index_peer_id on peer (id); + create index if not exists index_peer_user on peer (user); + create index if not exists index_peer_created_at on peer (created_at); + create index if not exists index_peer_status on peer (status); + " + ) + .execute(self.pool.get().await?.deref_mut()) + .await?; + Ok(()) + } + + pub async fn get_peer(&self, id: &str) -> ResultType<Option<Peer>> { + Ok(sqlx::query_as!( + Peer, + "select guid, id, uuid, pk, user, status, info from peer where id = ?", + id + ) + .fetch_optional(self.pool.get().await?.deref_mut()) + .await?) + } + + pub async fn get_peer_id(&self, guid: &[u8]) -> ResultType<Option<String>> { + Ok(sqlx::query!("select id from peer where guid = ?", guid) + .fetch_optional(self.pool.get().await?.deref_mut()) + .await? + .map(|x| x.id)) + } + + #[inline] + pub async fn get_conn(&self) -> ResultType<deadpool::managed::Object<DbPool>> { + Ok(self.pool.get().await?) + } + + pub async fn update_peer(&self, payload: MapValue, guid: &[u8]) -> ResultType<()> { + let mut conn = self.get_conn().await?; + let mut tx = conn.begin().await?; + if let Some(v) = payload.get("note") { + let v = get_str(v); + sqlx::query!("update peer set note = ? where guid = ?", v, guid) + .execute(&mut tx) + .await?; + } + tx.commit().await?; + Ok(()) + } + + pub async fn insert_peer( + &self, + id: &str, + uuid: &Vec<u8>, + pk: &Vec<u8>, + info: &str, + ) -> ResultType<Vec<u8>> { + let guid = uuid::Uuid::new_v4().as_bytes().to_vec(); + sqlx::query!( + "insert into peer(guid, id, uuid, pk, info) values(?, ?, ?, ?, ?)", + guid, + id, + uuid, + pk, + info + ) + .execute(self.pool.get().await?.deref_mut()) + .await?; + Ok(guid) + } + + pub async fn update_pk( + &self, + guid: &Vec<u8>, + id: &str, + pk: &Vec<u8>, + info: &str, + ) -> ResultType<()> { + sqlx::query!( + "update peer set id=?, pk=?, info=? where guid=?", + id, + pk, + info, + guid + ) + .execute(self.pool.get().await?.deref_mut()) + .await?; + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use hbb_common::tokio; + #[test] + fn test_insert() { + insert(); + } + + #[tokio::main(flavor = "multi_thread")] + async fn insert() { + let db = super::Database::new("test.sqlite3").await.unwrap(); + let mut jobs = vec![]; + for i in 0..10000 { + let cloned = db.clone(); + let id = i.to_string(); + let a = tokio::spawn(async move { + let empty_vec = Vec::new(); + cloned + .insert_peer(&id, &empty_vec, &empty_vec, "") + .await + .unwrap(); + }); + jobs.push(a); + } + for i in 0..10000 { + let cloned = db.clone(); + let id = i.to_string(); + let a = tokio::spawn(async move { + cloned.get_peer(&id).await.unwrap(); + }); + jobs.push(a); + } + hbb_common::futures::future::join_all(jobs).await; + } +} + +#[inline] +pub fn guid2str(guid: &Vec<u8>) -> String { + let mut bytes = [0u8; 16]; + bytes[..].copy_from_slice(&guid); + uuid::Uuid::from_bytes(bytes).to_string() +} + +pub(crate) fn get_str(v: &Value) -> Option<&str> { + match v { + Value::String(v) => { + let v = v.trim(); + if v.is_empty() { + None + } else { + Some(v) + } + } + _ => None, + } +} diff --git a/src/hbbr.rs b/src/hbbr.rs index 7b795f5..f3cfa7c 100644 --- a/src/hbbr.rs +++ b/src/hbbr.rs @@ -1,34 +1,41 @@ use clap::App; +mod common; mod relay_server; -use hbb_common::{env_logger::*, ResultType}; +use flexi_logger::*; +use hbb_common::{config::RELAY_PORT, ResultType}; use relay_server::*; -use std::sync::{Arc, Mutex}; -mod lic; +mod version; fn main() -> ResultType<()> { - init_from_env(Env::default().filter_or(DEFAULT_FILTER_ENV, "info")); + let _logger = Logger::try_with_env_or_str("info")? + .log_to_stdout() + .format(opt_format) + .write_mode(WriteMode::Async) + .start()?; let args = format!( "-p, --port=[NUMBER(default={})] 'Sets the listening port' -k, --key=[KEY] 'Only allow the client with the same key' - {} ", - DEFAULT_PORT, - lic::EMAIL_ARG + RELAY_PORT, ); let matches = App::new("hbbr") - .version(hbbs::VERSION) - .author("CarrieZ Studio<[email protected]>") + .version(version::VERSION) + .author("Purslane Ltd. <[email protected]>") .about("RustDesk Relay Server") .args_from_usage(&args) .get_matches(); - if !lic::check_lic(matches.value_of("email").unwrap_or(""), hbbs::VERSION) { + if let Ok(v) = ini::Ini::load_from_file(".env") { + if let Some(section) = v.section(None::<String>) { + section.iter().for_each(|(k, v)| std::env::set_var(k, v)); + } + } + #[cfg(not(debug_assertions))] + if !lic::check_lic(matches.value_of("email").unwrap_or(""), version::VERSION) { return Ok(()); } - let stop: Arc<Mutex<bool>> = Default::default(); start( - matches.value_of("port").unwrap_or(DEFAULT_PORT), + matches.value_of("port").unwrap_or(&RELAY_PORT.to_string()), matches.value_of("key").unwrap_or(""), - stop, )?; Ok(()) } @@ -1,6 +1,6 @@ mod rendezvous_server; -mod sled_async; pub use rendezvous_server::*; -use sled_async::*; +pub mod common; +mod database; +mod peer; mod version; -pub use version::*; diff --git a/src/lic.rs b/src/lic.rs deleted file mode 100644 index 171c6b1..0000000 --- a/src/lic.rs +++ /dev/null @@ -1,170 +0,0 @@ -use hbb_common::{bail, log, ResultType, rand::{self, Rng}}; -use serde_derive::{Deserialize, Serialize}; -use std::io::prelude::*; -use std::path::Path; - -#[derive(Debug, PartialEq, Default, Serialize, Deserialize, Clone)] -pub struct Machine { - #[serde(default)] - hostname: String, - #[serde(default)] - uid: String, - #[serde(default)] - mac: String, -} - -#[derive(Debug, PartialEq, Default, Serialize, Deserialize, Clone)] -pub struct Post { - #[serde(default)] - machine: String, - #[serde(default)] - email: String, - #[serde(default)] - status: String, - #[serde(default)] - version: String, - #[serde(default)] - next_check_time: u64, - #[serde(default)] - nonce: String, - #[serde(default)] - tip: String, -} - -const LICENSE_FILE: &'static str = ".license.txt"; - -pub fn check_lic(email: &str, version: &str) -> bool { - if email.is_empty() { - log::error!("Registered email required (-m option). Please pay and register on https://rustdesk.com/server."); - return false; - } - - let is_docker = std::path::Path::new("/.dockerenv").exists(); - let machine = if is_docker { "".to_owned() } else { get_lic() }; - if !is_docker { - let path = Path::new(LICENSE_FILE); - if Path::is_file(&path) { - let contents = std::fs::read_to_string(&path).unwrap_or("".to_owned()); - if verify(&contents, &machine) { - async_check_email(&machine, email, version, 0); - return true; - } - } - } - - match check_email(machine.clone(), email.to_owned(), version.to_owned()) { - Ok(v) => { - async_check_email(&machine, email, version, v); - return true; - } - Err(err) => { - log::error!("{}", err); - return false; - } - } -} - -fn async_check_email(machine: &str, email: &str, version: &str, wait: u64) { - let machine = machine.to_owned(); - let email = email.to_owned(); - let version = version.to_owned(); - std::thread::spawn(move || { - let mut wait = wait; - loop { - let machine = machine.clone(); - let email = email.clone(); - let version = version.clone(); - std::thread::sleep(std::time::Duration::from_secs(wait)); - match check_email(machine, email, version) { - Ok(v) => { - wait = v; - } - Err(err) => { - log::error!("{}", err); - std::process::exit(-1); - } - } - } - }); -} - -fn write_lic(lic: &str) { - if let Ok(mut f) = std::fs::File::create(LICENSE_FILE) { - f.write_all(lic.as_bytes()).ok(); - f.sync_all().ok(); - } -} - -fn check_email(machine: String, email: String, version: String) -> ResultType<u64> { - log::info!("Checking email with the license server ..."); - let mut rng = rand::thread_rng(); - let nonce: usize = rng.gen(); - let nonce = nonce.to_string(); - let resp = minreq::post("http://rustdesk.com/api/check-email") - .with_body( - serde_json::to_string(&Post { - machine: machine.clone(), - version, - email, - nonce: nonce.clone(), - ..Default::default() - }) - .unwrap(), - ) - .send()?; - if resp.reason_phrase == "OK" { - let p: Post = serde_json::from_str(&resp.as_str()?)?; - if !p.status.is_empty() { - std::fs::remove_file(LICENSE_FILE).ok(); - bail!("{}", p.status); - } - if p.nonce.is_empty() { - bail!("Verification failure: nonce required"); - } - if !verify(&p.nonce, &nonce) { - bail!("Verification failure: nonce mismatch"); - } - if !machine.is_empty() { - if !verify(&p.machine, &machine) { - bail!("Verification failure"); - } - write_lic(&p.machine); - } - log::info!("License OK"); - if !p.tip.is_empty() { - log::info!("{}", p.tip); - } - let mut wait = p.next_check_time; - if wait == 0 { - wait = 3600 * 24 * 30; - } - - Ok(wait) - } else { - bail!("Server error: {}", resp.reason_phrase); - } -} - -fn get_lic() -> String { - let hostname = whoami::hostname(); - let uid = machine_uid::get().unwrap_or("".to_owned()); - let mac = if let Ok(Some(ma)) = mac_address::get_mac_address() { - base64::encode(ma.bytes()) - } else { - "".to_owned() - }; - serde_json::to_string(&Machine { hostname, uid, mac }).unwrap() -} - -fn verify(enc_str: &str, msg: &str) -> bool { - if let Ok(data) = base64::decode(enc_str) { - let key = - b"\xf1T\xc0\x1c\xffee\x86,S*\xd9.\x91\xcd\x85\x12:\xec\xa9 \x99:\x8a\xa2S\x1f Yy\x93R"; - cryptoxide::ed25519::verify(msg.as_bytes(), &key[..], &data) - } else { - false - } -} - -pub const EMAIL_ARG: &'static str = - "-m, --email=[EMAIL] 'Sets your email address registered with RustDesk'"; diff --git a/src/main.rs b/src/main.rs index 8e488f1..db2bbab 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,15 +1,18 @@ // https://tools.ietf.org/rfc/rfc5128.txt // https://blog.csdn.net/bytxl/article/details/44344855 -use clap::App; -use hbb_common::{env_logger::*, log, ResultType}; -use hbbs::*; -mod lic; -use ini::Ini; -use std::sync::{Arc, Mutex}; +use flexi_logger::*; +use hbb_common::{bail, config::RENDEZVOUS_PORT, ResultType}; +use hbbs::{common::*, *}; + +const RMEM: usize = 0; fn main() -> ResultType<()> { - init_from_env(Env::default().filter_or(DEFAULT_FILTER_ENV, "info")); + let _logger = Logger::try_with_env_or_str("info")? + .log_to_stdout() + .format(opt_format) + .write_mode(WriteMode::Async) + .start()?; let args = format!( "-c --config=[FILE] +takes_value 'Sets a custom config file' -p, --port=[NUMBER(default={})] 'Sets the listening port' @@ -18,66 +21,19 @@ fn main() -> ResultType<()> { -u, --software-url=[URL] 'Sets download url of RustDesk software of newest version' -r, --relay-servers=[HOST] 'Sets the default relay servers, seperated by colon' -C, --change-id=[BOOL(default=Y)] 'Sets if support to change id' - {} + -M, --rmem=[NUMBER(default={})] 'Sets UDP recv buffer size, set system rmem_max first, e.g., sudo sysctl -w net.core.rmem_max=52428800. vi /etc/sysctl.conf, net.core.rmem_max=52428800, sudo sysctl –p' -k, --key=[KEY] 'Only allow the client with the same key'", - DEFAULT_PORT, - lic::EMAIL_ARG + RENDEZVOUS_PORT, + RMEM, ); - let matches = App::new("hbbs") - .version(crate::VERSION) - .author("CarrieZ Studio<[email protected]>") - .about("RustDesk ID/Rendezvous Server") - .args_from_usage(&args) - .get_matches(); - let mut section = None; - let conf; // for holding section - if let Some(config) = matches.value_of("config") { - if let Ok(v) = Ini::load_from_file(config) { - conf = v; - section = conf.section(None::<String>); - } - } - let get_arg = |name: &str, default: &str| -> String { - if let Some(v) = matches.value_of(name) { - return v.to_owned(); - } else if let Some(section) = section { - if let Some(v) = section.get(name) { - return v.to_owned(); - } - } - return default.to_owned(); - }; - if !lic::check_lic(&get_arg("email", ""), crate::VERSION) { - return Ok(()); + init_args(&args, "hbbs", "RustDesk ID/Rendezvous Server"); + let port = get_arg_or("port", RENDEZVOUS_PORT.to_string()).parse::<i32>()?; + if port < 3 { + bail!("Invalid port"); } - let port = get_arg("port", DEFAULT_PORT); - let relay_servers: Vec<String> = get_arg("relay-servers", "") - .split(",") - .filter(|x| !x.is_empty() && test_if_valid_server(x, "relay-server").is_ok()) - .map(|x| x.to_owned()) - .collect(); - let serial: i32 = get_arg("serial", "").parse().unwrap_or(0); - let id_change_support: bool = get_arg("change-id", "Y").to_uppercase() == "Y"; - let rendezvous_servers: Vec<String> = get_arg("rendezvous-servers", "") - .split(",") - .filter(|x| !x.is_empty() && test_if_valid_server(x, "rendezvous-server").is_ok()) - .map(|x| x.to_owned()) - .collect(); - let addr = format!("0.0.0.0:{}", port); - let addr2 = format!("0.0.0.0:{}", port.parse::<i32>().unwrap_or(0) - 1); - log::info!("serial={}", serial); - log::info!("rendezvous-servers={:?}", rendezvous_servers); - let stop: Arc<Mutex<bool>> = Default::default(); - RendezvousServer::start( - &addr, - &addr2, - relay_servers, - serial, - rendezvous_servers, - get_arg("software-url", ""), - &get_arg("key", ""), - stop, - id_change_support, - )?; + let rmem = get_arg("rmem").parse::<usize>().unwrap_or(RMEM); + let serial: i32 = get_arg("serial").parse().unwrap_or(0); + let id_change_support: bool = get_arg_or("change-id", "Y".to_owned()).to_uppercase() == "Y"; + RendezvousServer::start(port, serial, &get_arg("key"), id_change_support, rmem)?; Ok(()) } diff --git a/src/peer.rs b/src/peer.rs new file mode 100644 index 0000000..72999b7 --- /dev/null +++ b/src/peer.rs @@ -0,0 +1,185 @@ +use crate::common::*; +use crate::database; +use hbb_common::{ + log, + rendezvous_proto::*, + tokio::sync::{Mutex, RwLock}, + ResultType, +}; +use serde_derive::{Deserialize, Serialize}; +use std::{collections::HashMap, collections::HashSet, net::SocketAddr, sync::Arc, time::Instant}; + +lazy_static::lazy_static! { + pub(crate) static ref IP_BLOCKER: Mutex<HashMap<String, ((u32, Instant), (HashSet<String>, Instant))>> = Default::default(); + pub(crate) static ref USER_STATUS: RwLock<HashMap<Vec<u8>, Arc<(Option<Vec<u8>>, bool)>>> = Default::default(); + pub(crate) static ref IP_CHANGES: Mutex<HashMap<String, (Instant, HashMap<String, i32>)>> = Default::default(); +} +pub static IP_CHANGE_DUR: u64 = 180; +pub static IP_CHANGE_DUR_X2: u64 = IP_CHANGE_DUR * 2; +pub static DAY_SECONDS: u64 = 3600 * 24; +pub static IP_BLOCK_DUR: u64 = 60; + +#[derive(Debug, Default, Serialize, Deserialize, Clone)] +pub(crate) struct PeerInfo { + #[serde(default)] + pub(crate) ip: String, +} + +#[derive(Clone, Debug)] +pub(crate) struct Peer { + pub(crate) socket_addr: SocketAddr, + pub(crate) last_reg_time: Instant, + pub(crate) guid: Vec<u8>, + pub(crate) uuid: Vec<u8>, + pub(crate) pk: Vec<u8>, + pub(crate) user: Option<Vec<u8>>, + pub(crate) info: PeerInfo, + pub(crate) disabled: bool, + pub(crate) reg_pk: (u32, Instant), // how often register_pk +} + +impl Default for Peer { + fn default() -> Self { + Self { + socket_addr: "0.0.0.0:0".parse().unwrap(), + last_reg_time: get_expired_time(), + guid: Vec::new(), + uuid: Vec::new(), + pk: Vec::new(), + info: Default::default(), + user: None, + disabled: false, + reg_pk: (0, get_expired_time()), + } + } +} + +pub(crate) type LockPeer = Arc<RwLock<Peer>>; + +#[derive(Clone)] +pub(crate) struct PeerMap { + map: Arc<RwLock<HashMap<String, LockPeer>>>, + pub(crate) db: database::Database, +} + +impl PeerMap { + pub(crate) async fn new() -> ResultType<Self> { + let db = std::env::var("DB_URL").unwrap_or({ + #[allow(unused_mut)] + let mut db = "db_v2.sqlite3".to_owned(); + #[cfg(all(windows, not(debug_assertions)))] + { + if let Some(path) = hbb_common::config::Config::icon_path().parent() { + db = format!("{}\\{}", path.to_str().unwrap_or("."), db); + } + } + #[cfg(not(windows))] + { + db = format!("./{}", db); + } + db + }); + log::info!("DB_URL={}", db); + let pm = Self { + map: Default::default(), + db: database::Database::new(&db).await?, + }; + Ok(pm) + } + + #[inline] + pub(crate) async fn update_pk( + &mut self, + id: String, + peer: LockPeer, + addr: SocketAddr, + uuid: Vec<u8>, + pk: Vec<u8>, + ip: String, + ) -> register_pk_response::Result { + log::info!("update_pk {} {:?} {:?} {:?}", id, addr, uuid, pk); + let (info_str, guid) = { + let mut w = peer.write().await; + w.socket_addr = addr; + w.uuid = uuid.clone(); + w.pk = pk.clone(); + w.last_reg_time = Instant::now(); + w.info.ip = ip; + ( + serde_json::to_string(&w.info).unwrap_or_default(), + w.guid.clone(), + ) + }; + if guid.is_empty() { + match self.db.insert_peer(&id, &uuid, &pk, &info_str).await { + Err(err) => { + log::error!("db.insert_peer failed: {}", err); + return register_pk_response::Result::SERVER_ERROR; + } + Ok(guid) => { + peer.write().await.guid = guid; + } + } + } else { + if let Err(err) = self.db.update_pk(&guid, &id, &pk, &info_str).await { + log::error!("db.update_pk failed: {}", err); + return register_pk_response::Result::SERVER_ERROR; + } + log::info!("pk updated instead of insert"); + } + register_pk_response::Result::OK + } + + #[inline] + pub(crate) async fn get(&self, id: &str) -> Option<LockPeer> { + let p = self.map.read().await.get(id).map(|x| x.clone()); + if p.is_some() { + return p; + } else { + if let Ok(Some(v)) = self.db.get_peer(id).await { + let peer = Peer { + guid: v.guid, + uuid: v.uuid, + pk: v.pk, + user: v.user, + info: serde_json::from_str::<PeerInfo>(&v.info).unwrap_or_default(), + disabled: v.status == Some(0), + ..Default::default() + }; + let peer = Arc::new(RwLock::new(peer)); + self.map.write().await.insert(id.to_owned(), peer.clone()); + return Some(peer); + } + } + None + } + + #[inline] + pub(crate) async fn get_or(&self, id: &str) -> LockPeer { + if let Some(p) = self.get(id).await { + return p; + } + let mut w = self.map.write().await; + if let Some(p) = w.get(id) { + return p.clone(); + } + let tmp = LockPeer::default(); + w.insert(id.to_owned(), tmp.clone()); + tmp + } + + #[inline] + pub(crate) async fn get_in_memory(&self, id: &str) -> Option<LockPeer> { + self.map.read().await.get(id).map(|x| x.clone()) + } + + #[inline] + pub(crate) async fn is_in_memory(&self, id: &str) -> bool { + self.map.read().await.contains_key(id) + } + + #[inline] + pub(crate) async fn remove(&self, id: &str) { + self.map.write().await.remove(id); + } +} diff --git a/src/protos/message.rs b/src/protos/message.rs deleted file mode 100644 index 58e186b..0000000 --- a/src/protos/message.rs +++ /dev/null @@ -1,930 +0,0 @@ -// This file is generated by rust-protobuf 2.10.2. Do not edit -// @generated - -// https://github.com/rust-lang/rust-clippy/issues/702 -#![allow(unknown_lints)] -#![allow(clippy::all)] - -#![cfg_attr(rustfmt, rustfmt_skip)] - -#![allow(box_pointers)] -#![allow(dead_code)] -#![allow(missing_docs)] -#![allow(non_camel_case_types)] -#![allow(non_snake_case)] -#![allow(non_upper_case_globals)] -#![allow(trivial_casts)] -#![allow(unsafe_code)] -#![allow(unused_imports)] -#![allow(unused_results)] -//! Generated file from `message.proto` - -use protobuf::Message as Message_imported_for_functions; -use protobuf::ProtobufEnum as ProtobufEnum_imported_for_functions; - -/// Generated files are compatible only with the same version -/// of protobuf runtime. -// const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_2_10_2; - -#[derive(PartialEq,Clone,Default)] -pub struct RegisterPeer { - // message fields - pub hbb_addr: ::std::string::String, - // special fields - pub unknown_fields: ::protobuf::UnknownFields, - pub cached_size: ::protobuf::CachedSize, -} - -impl<'a> ::std::default::Default for &'a RegisterPeer { - fn default() -> &'a RegisterPeer { - <RegisterPeer as ::protobuf::Message>::default_instance() - } -} - -impl RegisterPeer { - pub fn new() -> RegisterPeer { - ::std::default::Default::default() - } - - // string hbb_addr = 1; - - - pub fn get_hbb_addr(&self) -> &str { - &self.hbb_addr - } - pub fn clear_hbb_addr(&mut self) { - self.hbb_addr.clear(); - } - - // Param is passed by value, moved - pub fn set_hbb_addr(&mut self, v: ::std::string::String) { - self.hbb_addr = v; - } - - // Mutable pointer to the field. - // If field is not initialized, it is initialized with default value first. - pub fn mut_hbb_addr(&mut self) -> &mut ::std::string::String { - &mut self.hbb_addr - } - - // Take field - pub fn take_hbb_addr(&mut self) -> ::std::string::String { - ::std::mem::replace(&mut self.hbb_addr, ::std::string::String::new()) - } -} - -impl ::protobuf::Message for RegisterPeer { - fn is_initialized(&self) -> bool { - true - } - - fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> { - while !is.eof()? { - let (field_number, wire_type) = is.read_tag_unpack()?; - match field_number { - 1 => { - ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.hbb_addr)?; - }, - _ => { - ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; - }, - }; - } - ::std::result::Result::Ok(()) - } - - // Compute sizes of nested messages - #[allow(unused_variables)] - fn compute_size(&self) -> u32 { - let mut my_size = 0; - if !self.hbb_addr.is_empty() { - my_size += ::protobuf::rt::string_size(1, &self.hbb_addr); - } - my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); - self.cached_size.set(my_size); - my_size - } - - fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> { - if !self.hbb_addr.is_empty() { - os.write_string(1, &self.hbb_addr)?; - } - os.write_unknown_fields(self.get_unknown_fields())?; - ::std::result::Result::Ok(()) - } - - fn get_cached_size(&self) -> u32 { - self.cached_size.get() - } - - fn get_unknown_fields(&self) -> &::protobuf::UnknownFields { - &self.unknown_fields - } - - fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields { - &mut self.unknown_fields - } - - fn as_any(&self) -> &dyn (::std::any::Any) { - self as &dyn (::std::any::Any) - } - fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) { - self as &mut dyn (::std::any::Any) - } - fn into_any(self: Box<Self>) -> ::std::boxed::Box<dyn (::std::any::Any)> { - self - } - - fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor { - Self::descriptor_static() - } - - fn new() -> RegisterPeer { - RegisterPeer::new() - } - - fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { - static mut descriptor: ::protobuf::lazy::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::lazy::Lazy { - lock: ::protobuf::lazy::ONCE_INIT, - ptr: 0 as *const ::protobuf::reflect::MessageDescriptor, - }; - unsafe { - descriptor.get(|| { - let mut fields = ::std::vec::Vec::new(); - fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( - "hbb_addr", - |m: &RegisterPeer| { &m.hbb_addr }, - |m: &mut RegisterPeer| { &mut m.hbb_addr }, - )); - ::protobuf::reflect::MessageDescriptor::new::<RegisterPeer>( - "RegisterPeer", - fields, - file_descriptor_proto() - ) - }) - } - } - - fn default_instance() -> &'static RegisterPeer { - static mut instance: ::protobuf::lazy::Lazy<RegisterPeer> = ::protobuf::lazy::Lazy { - lock: ::protobuf::lazy::ONCE_INIT, - ptr: 0 as *const RegisterPeer, - }; - unsafe { - instance.get(RegisterPeer::new) - } - } -} - -impl ::protobuf::Clear for RegisterPeer { - fn clear(&mut self) { - self.hbb_addr.clear(); - self.unknown_fields.clear(); - } -} - -impl ::std::fmt::Debug for RegisterPeer { - fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - ::protobuf::text_format::fmt(self, f) - } -} - -impl ::protobuf::reflect::ProtobufValue for RegisterPeer { - fn as_ref(&self) -> ::protobuf::reflect::ProtobufValueRef { - ::protobuf::reflect::ProtobufValueRef::Message(self) - } -} - -#[derive(PartialEq,Clone,Default)] -pub struct PeekPeer { - // message fields - pub hbb_addr: ::std::string::String, - // special fields - pub unknown_fields: ::protobuf::UnknownFields, - pub cached_size: ::protobuf::CachedSize, -} - -impl<'a> ::std::default::Default for &'a PeekPeer { - fn default() -> &'a PeekPeer { - <PeekPeer as ::protobuf::Message>::default_instance() - } -} - -impl PeekPeer { - pub fn new() -> PeekPeer { - ::std::default::Default::default() - } - - // string hbb_addr = 1; - - - pub fn get_hbb_addr(&self) -> &str { - &self.hbb_addr - } - pub fn clear_hbb_addr(&mut self) { - self.hbb_addr.clear(); - } - - // Param is passed by value, moved - pub fn set_hbb_addr(&mut self, v: ::std::string::String) { - self.hbb_addr = v; - } - - // Mutable pointer to the field. - // If field is not initialized, it is initialized with default value first. - pub fn mut_hbb_addr(&mut self) -> &mut ::std::string::String { - &mut self.hbb_addr - } - - // Take field - pub fn take_hbb_addr(&mut self) -> ::std::string::String { - ::std::mem::replace(&mut self.hbb_addr, ::std::string::String::new()) - } -} - -impl ::protobuf::Message for PeekPeer { - fn is_initialized(&self) -> bool { - true - } - - fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> { - while !is.eof()? { - let (field_number, wire_type) = is.read_tag_unpack()?; - match field_number { - 1 => { - ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.hbb_addr)?; - }, - _ => { - ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; - }, - }; - } - ::std::result::Result::Ok(()) - } - - // Compute sizes of nested messages - #[allow(unused_variables)] - fn compute_size(&self) -> u32 { - let mut my_size = 0; - if !self.hbb_addr.is_empty() { - my_size += ::protobuf::rt::string_size(1, &self.hbb_addr); - } - my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); - self.cached_size.set(my_size); - my_size - } - - fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> { - if !self.hbb_addr.is_empty() { - os.write_string(1, &self.hbb_addr)?; - } - os.write_unknown_fields(self.get_unknown_fields())?; - ::std::result::Result::Ok(()) - } - - fn get_cached_size(&self) -> u32 { - self.cached_size.get() - } - - fn get_unknown_fields(&self) -> &::protobuf::UnknownFields { - &self.unknown_fields - } - - fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields { - &mut self.unknown_fields - } - - fn as_any(&self) -> &dyn (::std::any::Any) { - self as &dyn (::std::any::Any) - } - fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) { - self as &mut dyn (::std::any::Any) - } - fn into_any(self: Box<Self>) -> ::std::boxed::Box<dyn (::std::any::Any)> { - self - } - - fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor { - Self::descriptor_static() - } - - fn new() -> PeekPeer { - PeekPeer::new() - } - - fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { - static mut descriptor: ::protobuf::lazy::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::lazy::Lazy { - lock: ::protobuf::lazy::ONCE_INIT, - ptr: 0 as *const ::protobuf::reflect::MessageDescriptor, - }; - unsafe { - descriptor.get(|| { - let mut fields = ::std::vec::Vec::new(); - fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( - "hbb_addr", - |m: &PeekPeer| { &m.hbb_addr }, - |m: &mut PeekPeer| { &mut m.hbb_addr }, - )); - ::protobuf::reflect::MessageDescriptor::new::<PeekPeer>( - "PeekPeer", - fields, - file_descriptor_proto() - ) - }) - } - } - - fn default_instance() -> &'static PeekPeer { - static mut instance: ::protobuf::lazy::Lazy<PeekPeer> = ::protobuf::lazy::Lazy { - lock: ::protobuf::lazy::ONCE_INIT, - ptr: 0 as *const PeekPeer, - }; - unsafe { - instance.get(PeekPeer::new) - } - } -} - -impl ::protobuf::Clear for PeekPeer { - fn clear(&mut self) { - self.hbb_addr.clear(); - self.unknown_fields.clear(); - } -} - -impl ::std::fmt::Debug for PeekPeer { - fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - ::protobuf::text_format::fmt(self, f) - } -} - -impl ::protobuf::reflect::ProtobufValue for PeekPeer { - fn as_ref(&self) -> ::protobuf::reflect::ProtobufValueRef { - ::protobuf::reflect::ProtobufValueRef::Message(self) - } -} - -#[derive(PartialEq,Clone,Default)] -pub struct PeekPeerResponse { - // message fields - pub socket_addr: ::std::vec::Vec<u8>, - // special fields - pub unknown_fields: ::protobuf::UnknownFields, - pub cached_size: ::protobuf::CachedSize, -} - -impl<'a> ::std::default::Default for &'a PeekPeerResponse { - fn default() -> &'a PeekPeerResponse { - <PeekPeerResponse as ::protobuf::Message>::default_instance() - } -} - -impl PeekPeerResponse { - pub fn new() -> PeekPeerResponse { - ::std::default::Default::default() - } - - // bytes socket_addr = 1; - - - pub fn get_socket_addr(&self) -> &[u8] { - &self.socket_addr - } - pub fn clear_socket_addr(&mut self) { - self.socket_addr.clear(); - } - - // Param is passed by value, moved - pub fn set_socket_addr(&mut self, v: ::std::vec::Vec<u8>) { - self.socket_addr = v; - } - - // Mutable pointer to the field. - // If field is not initialized, it is initialized with default value first. - pub fn mut_socket_addr(&mut self) -> &mut ::std::vec::Vec<u8> { - &mut self.socket_addr - } - - // Take field - pub fn take_socket_addr(&mut self) -> ::std::vec::Vec<u8> { - ::std::mem::replace(&mut self.socket_addr, ::std::vec::Vec::new()) - } -} - -impl ::protobuf::Message for PeekPeerResponse { - fn is_initialized(&self) -> bool { - true - } - - fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> { - while !is.eof()? { - let (field_number, wire_type) = is.read_tag_unpack()?; - match field_number { - 1 => { - ::protobuf::rt::read_singular_proto3_bytes_into(wire_type, is, &mut self.socket_addr)?; - }, - _ => { - ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; - }, - }; - } - ::std::result::Result::Ok(()) - } - - // Compute sizes of nested messages - #[allow(unused_variables)] - fn compute_size(&self) -> u32 { - let mut my_size = 0; - if !self.socket_addr.is_empty() { - my_size += ::protobuf::rt::bytes_size(1, &self.socket_addr); - } - my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); - self.cached_size.set(my_size); - my_size - } - - fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> { - if !self.socket_addr.is_empty() { - os.write_bytes(1, &self.socket_addr)?; - } - os.write_unknown_fields(self.get_unknown_fields())?; - ::std::result::Result::Ok(()) - } - - fn get_cached_size(&self) -> u32 { - self.cached_size.get() - } - - fn get_unknown_fields(&self) -> &::protobuf::UnknownFields { - &self.unknown_fields - } - - fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields { - &mut self.unknown_fields - } - - fn as_any(&self) -> &dyn (::std::any::Any) { - self as &dyn (::std::any::Any) - } - fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) { - self as &mut dyn (::std::any::Any) - } - fn into_any(self: Box<Self>) -> ::std::boxed::Box<dyn (::std::any::Any)> { - self - } - - fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor { - Self::descriptor_static() - } - - fn new() -> PeekPeerResponse { - PeekPeerResponse::new() - } - - fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { - static mut descriptor: ::protobuf::lazy::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::lazy::Lazy { - lock: ::protobuf::lazy::ONCE_INIT, - ptr: 0 as *const ::protobuf::reflect::MessageDescriptor, - }; - unsafe { - descriptor.get(|| { - let mut fields = ::std::vec::Vec::new(); - fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>( - "socket_addr", - |m: &PeekPeerResponse| { &m.socket_addr }, - |m: &mut PeekPeerResponse| { &mut m.socket_addr }, - )); - ::protobuf::reflect::MessageDescriptor::new::<PeekPeerResponse>( - "PeekPeerResponse", - fields, - file_descriptor_proto() - ) - }) - } - } - - fn default_instance() -> &'static PeekPeerResponse { - static mut instance: ::protobuf::lazy::Lazy<PeekPeerResponse> = ::protobuf::lazy::Lazy { - lock: ::protobuf::lazy::ONCE_INIT, - ptr: 0 as *const PeekPeerResponse, - }; - unsafe { - instance.get(PeekPeerResponse::new) - } - } -} - -impl ::protobuf::Clear for PeekPeerResponse { - fn clear(&mut self) { - self.socket_addr.clear(); - self.unknown_fields.clear(); - } -} - -impl ::std::fmt::Debug for PeekPeerResponse { - fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - ::protobuf::text_format::fmt(self, f) - } -} - -impl ::protobuf::reflect::ProtobufValue for PeekPeerResponse { - fn as_ref(&self) -> ::protobuf::reflect::ProtobufValueRef { - ::protobuf::reflect::ProtobufValueRef::Message(self) - } -} - -#[derive(PartialEq,Clone,Default)] -pub struct Message { - // message oneof groups - pub union: ::std::option::Option<Message_oneof_union>, - // special fields - pub unknown_fields: ::protobuf::UnknownFields, - pub cached_size: ::protobuf::CachedSize, -} - -impl<'a> ::std::default::Default for &'a Message { - fn default() -> &'a Message { - <Message as ::protobuf::Message>::default_instance() - } -} - -#[derive(Clone,PartialEq,Debug)] -pub enum Message_oneof_union { - register_peer(RegisterPeer), - peek_peer(PeekPeer), - peek_peer_response(PeekPeerResponse), -} - -impl Message { - pub fn new() -> Message { - ::std::default::Default::default() - } - - // .hbb.RegisterPeer register_peer = 6; - - - pub fn get_register_peer(&self) -> &RegisterPeer { - match self.union { - ::std::option::Option::Some(Message_oneof_union::register_peer(ref v)) => v, - _ => RegisterPeer::default_instance(), - } - } - pub fn clear_register_peer(&mut self) { - self.union = ::std::option::Option::None; - } - - pub fn has_register_peer(&self) -> bool { - match self.union { - ::std::option::Option::Some(Message_oneof_union::register_peer(..)) => true, - _ => false, - } - } - - // Param is passed by value, moved - pub fn set_register_peer(&mut self, v: RegisterPeer) { - self.union = ::std::option::Option::Some(Message_oneof_union::register_peer(v)) - } - - // Mutable pointer to the field. - pub fn mut_register_peer(&mut self) -> &mut RegisterPeer { - if let ::std::option::Option::Some(Message_oneof_union::register_peer(_)) = self.union { - } else { - self.union = ::std::option::Option::Some(Message_oneof_union::register_peer(RegisterPeer::new())); - } - match self.union { - ::std::option::Option::Some(Message_oneof_union::register_peer(ref mut v)) => v, - _ => panic!(), - } - } - - // Take field - pub fn take_register_peer(&mut self) -> RegisterPeer { - if self.has_register_peer() { - match self.union.take() { - ::std::option::Option::Some(Message_oneof_union::register_peer(v)) => v, - _ => panic!(), - } - } else { - RegisterPeer::new() - } - } - - // .hbb.PeekPeer peek_peer = 7; - - - pub fn get_peek_peer(&self) -> &PeekPeer { - match self.union { - ::std::option::Option::Some(Message_oneof_union::peek_peer(ref v)) => v, - _ => PeekPeer::default_instance(), - } - } - pub fn clear_peek_peer(&mut self) { - self.union = ::std::option::Option::None; - } - - pub fn has_peek_peer(&self) -> bool { - match self.union { - ::std::option::Option::Some(Message_oneof_union::peek_peer(..)) => true, - _ => false, - } - } - - // Param is passed by value, moved - pub fn set_peek_peer(&mut self, v: PeekPeer) { - self.union = ::std::option::Option::Some(Message_oneof_union::peek_peer(v)) - } - - // Mutable pointer to the field. - pub fn mut_peek_peer(&mut self) -> &mut PeekPeer { - if let ::std::option::Option::Some(Message_oneof_union::peek_peer(_)) = self.union { - } else { - self.union = ::std::option::Option::Some(Message_oneof_union::peek_peer(PeekPeer::new())); - } - match self.union { - ::std::option::Option::Some(Message_oneof_union::peek_peer(ref mut v)) => v, - _ => panic!(), - } - } - - // Take field - pub fn take_peek_peer(&mut self) -> PeekPeer { - if self.has_peek_peer() { - match self.union.take() { - ::std::option::Option::Some(Message_oneof_union::peek_peer(v)) => v, - _ => panic!(), - } - } else { - PeekPeer::new() - } - } - - // .hbb.PeekPeerResponse peek_peer_response = 8; - - - pub fn get_peek_peer_response(&self) -> &PeekPeerResponse { - match self.union { - ::std::option::Option::Some(Message_oneof_union::peek_peer_response(ref v)) => v, - _ => PeekPeerResponse::default_instance(), - } - } - pub fn clear_peek_peer_response(&mut self) { - self.union = ::std::option::Option::None; - } - - pub fn has_peek_peer_response(&self) -> bool { - match self.union { - ::std::option::Option::Some(Message_oneof_union::peek_peer_response(..)) => true, - _ => false, - } - } - - // Param is passed by value, moved - pub fn set_peek_peer_response(&mut self, v: PeekPeerResponse) { - self.union = ::std::option::Option::Some(Message_oneof_union::peek_peer_response(v)) - } - - // Mutable pointer to the field. - pub fn mut_peek_peer_response(&mut self) -> &mut PeekPeerResponse { - if let ::std::option::Option::Some(Message_oneof_union::peek_peer_response(_)) = self.union { - } else { - self.union = ::std::option::Option::Some(Message_oneof_union::peek_peer_response(PeekPeerResponse::new())); - } - match self.union { - ::std::option::Option::Some(Message_oneof_union::peek_peer_response(ref mut v)) => v, - _ => panic!(), - } - } - - // Take field - pub fn take_peek_peer_response(&mut self) -> PeekPeerResponse { - if self.has_peek_peer_response() { - match self.union.take() { - ::std::option::Option::Some(Message_oneof_union::peek_peer_response(v)) => v, - _ => panic!(), - } - } else { - PeekPeerResponse::new() - } - } -} - -impl ::protobuf::Message for Message { - fn is_initialized(&self) -> bool { - if let Some(Message_oneof_union::register_peer(ref v)) = self.union { - if !v.is_initialized() { - return false; - } - } - if let Some(Message_oneof_union::peek_peer(ref v)) = self.union { - if !v.is_initialized() { - return false; - } - } - if let Some(Message_oneof_union::peek_peer_response(ref v)) = self.union { - if !v.is_initialized() { - return false; - } - } - true - } - - fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> { - while !is.eof()? { - let (field_number, wire_type) = is.read_tag_unpack()?; - match field_number { - 6 => { - if wire_type != ::protobuf::wire_format::WireTypeLengthDelimited { - return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); - } - self.union = ::std::option::Option::Some(Message_oneof_union::register_peer(is.read_message()?)); - }, - 7 => { - if wire_type != ::protobuf::wire_format::WireTypeLengthDelimited { - return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); - } - self.union = ::std::option::Option::Some(Message_oneof_union::peek_peer(is.read_message()?)); - }, - 8 => { - if wire_type != ::protobuf::wire_format::WireTypeLengthDelimited { - return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); - } - self.union = ::std::option::Option::Some(Message_oneof_union::peek_peer_response(is.read_message()?)); - }, - _ => { - ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; - }, - }; - } - ::std::result::Result::Ok(()) - } - - // Compute sizes of nested messages - #[allow(unused_variables)] - fn compute_size(&self) -> u32 { - let mut my_size = 0; - if let ::std::option::Option::Some(ref v) = self.union { - match v { - &Message_oneof_union::register_peer(ref v) => { - let len = v.compute_size(); - my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len; - }, - &Message_oneof_union::peek_peer(ref v) => { - let len = v.compute_size(); - my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len; - }, - &Message_oneof_union::peek_peer_response(ref v) => { - let len = v.compute_size(); - my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len; - }, - }; - } - my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); - self.cached_size.set(my_size); - my_size - } - - fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> { - if let ::std::option::Option::Some(ref v) = self.union { - match v { - &Message_oneof_union::register_peer(ref v) => { - os.write_tag(6, ::protobuf::wire_format::WireTypeLengthDelimited)?; - os.write_raw_varint32(v.get_cached_size())?; - v.write_to_with_cached_sizes(os)?; - }, - &Message_oneof_union::peek_peer(ref v) => { - os.write_tag(7, ::protobuf::wire_format::WireTypeLengthDelimited)?; - os.write_raw_varint32(v.get_cached_size())?; - v.write_to_with_cached_sizes(os)?; - }, - &Message_oneof_union::peek_peer_response(ref v) => { - os.write_tag(8, ::protobuf::wire_format::WireTypeLengthDelimited)?; - os.write_raw_varint32(v.get_cached_size())?; - v.write_to_with_cached_sizes(os)?; - }, - }; - } - os.write_unknown_fields(self.get_unknown_fields())?; - ::std::result::Result::Ok(()) - } - - fn get_cached_size(&self) -> u32 { - self.cached_size.get() - } - - fn get_unknown_fields(&self) -> &::protobuf::UnknownFields { - &self.unknown_fields - } - - fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields { - &mut self.unknown_fields - } - - fn as_any(&self) -> &dyn (::std::any::Any) { - self as &dyn (::std::any::Any) - } - fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) { - self as &mut dyn (::std::any::Any) - } - fn into_any(self: Box<Self>) -> ::std::boxed::Box<dyn (::std::any::Any)> { - self - } - - fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor { - Self::descriptor_static() - } - - fn new() -> Message { - Message::new() - } - - fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { - static mut descriptor: ::protobuf::lazy::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::lazy::Lazy { - lock: ::protobuf::lazy::ONCE_INIT, - ptr: 0 as *const ::protobuf::reflect::MessageDescriptor, - }; - unsafe { - descriptor.get(|| { - let mut fields = ::std::vec::Vec::new(); - fields.push(::protobuf::reflect::accessor::make_singular_message_accessor::<_, RegisterPeer>( - "register_peer", - Message::has_register_peer, - Message::get_register_peer, - )); - fields.push(::protobuf::reflect::accessor::make_singular_message_accessor::<_, PeekPeer>( - "peek_peer", - Message::has_peek_peer, - Message::get_peek_peer, - )); - fields.push(::protobuf::reflect::accessor::make_singular_message_accessor::<_, PeekPeerResponse>( - "peek_peer_response", - Message::has_peek_peer_response, - Message::get_peek_peer_response, - )); - ::protobuf::reflect::MessageDescriptor::new::<Message>( - "Message", - fields, - file_descriptor_proto() - ) - }) - } - } - - fn default_instance() -> &'static Message { - static mut instance: ::protobuf::lazy::Lazy<Message> = ::protobuf::lazy::Lazy { - lock: ::protobuf::lazy::ONCE_INIT, - ptr: 0 as *const Message, - }; - unsafe { - instance.get(Message::new) - } - } -} - -impl ::protobuf::Clear for Message { - fn clear(&mut self) { - self.union = ::std::option::Option::None; - self.union = ::std::option::Option::None; - self.union = ::std::option::Option::None; - self.unknown_fields.clear(); - } -} - -impl ::std::fmt::Debug for Message { - fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - ::protobuf::text_format::fmt(self, f) - } -} - -impl ::protobuf::reflect::ProtobufValue for Message { - fn as_ref(&self) -> ::protobuf::reflect::ProtobufValueRef { - ::protobuf::reflect::ProtobufValueRef::Message(self) - } -} - -static file_descriptor_proto_data: &'static [u8] = b"\ - \n\rmessage.proto\x12\x03hbb\"$\n\x0cRegisterPeer\x12\x12\n\x08hbb_addr\ - \x18\x01\x20\x01(\tB\0:\0\"\x20\n\x08PeekPeer\x12\x12\n\x08hbb_addr\x18\ - \x01\x20\x01(\tB\0:\0\"+\n\x10PeekPeerResponse\x12\x15\n\x0bsocket_addr\ - \x18\x01\x20\x01(\x0cB\0:\0\"\x9f\x01\n\x07Message\x12,\n\rregister_peer\ - \x18\x06\x20\x01(\x0b2\x11.hbb.RegisterPeerH\0B\0\x12$\n\tpeek_peer\x18\ - \x07\x20\x01(\x0b2\r.hbb.PeekPeerH\0B\0\x125\n\x12peek_peer_response\x18\ - \x08\x20\x01(\x0b2\x15.hbb.PeekPeerResponseH\0B\0B\x07\n\x05union:\0B\0b\ - \x06proto3\ -"; - -static mut file_descriptor_proto_lazy: ::protobuf::lazy::Lazy<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::lazy::Lazy { - lock: ::protobuf::lazy::ONCE_INIT, - ptr: 0 as *const ::protobuf::descriptor::FileDescriptorProto, -}; - -fn parse_descriptor_proto() -> ::protobuf::descriptor::FileDescriptorProto { - ::protobuf::parse_from_bytes(file_descriptor_proto_data).unwrap() -} - -pub fn file_descriptor_proto() -> &'static ::protobuf::descriptor::FileDescriptorProto { - unsafe { - file_descriptor_proto_lazy.get(|| { - parse_descriptor_proto() - }) - } -} diff --git a/src/relay_server.rs b/src/relay_server.rs index 785e875..9eccfe1 100644 --- a/src/relay_server.rs +++ b/src/relay_server.rs @@ -1,114 +1,638 @@ +use async_speed_limit::Limiter; +use async_trait::async_trait; use hbb_common::{ + allow_err, bail, + bytes::{Bytes, BytesMut}, + futures_util::{sink::SinkExt, stream::StreamExt}, log, protobuf::Message as _, rendezvous_proto::*, sleep, tcp::{new_listener, FramedStream}, + timeout, tokio::{ self, - net::TcpListener, + io::{AsyncReadExt, AsyncWriteExt}, + net::{TcpListener, TcpStream}, + sync::{Mutex, RwLock}, time::{interval, Duration}, }, ResultType, }; +use sodiumoxide::crypto::sign; use std::{ - collections::HashMap, + collections::{HashMap, HashSet}, + io::prelude::*, + io::Error, net::SocketAddr, - sync::{Arc, Mutex}, }; +type Usage = (usize, usize, usize, usize); + lazy_static::lazy_static! { - static ref PEERS: Arc<Mutex<HashMap<String, FramedStream>>> = Arc::new(Mutex::new(HashMap::new())); + static ref PEERS: Mutex<HashMap<String, Box<dyn StreamTrait>>> = Default::default(); + static ref USAGE: RwLock<HashMap<String, Usage>> = Default::default(); + static ref BLACKLIST: RwLock<HashSet<String>> = Default::default(); + static ref BLOCKLIST: RwLock<HashSet<String>> = Default::default(); } -pub const DEFAULT_PORT: &'static str = "21117"; +static mut DOWNGRADE_THRESHOLD: f64 = 0.66; +static mut DOWNGRADE_START_CHECK: usize = 1800_000; // in ms +static mut LIMIT_SPEED: usize = 4 * 1024 * 1024; // in bit/s +static mut TOTAL_BANDWIDTH: usize = 1024 * 1024 * 1024; // in bit/s +static mut SINGLE_BANDWIDTH: usize = 16 * 1024 * 1024; // in bit/s +const BLACKLIST_FILE: &'static str = "blacklist.txt"; +const BLOCKLIST_FILE: &'static str = "blocklist.txt"; -#[tokio::main(basic_scheduler)] -pub async fn start(port: &str, key: &str, stop: Arc<Mutex<bool>>) -> ResultType<()> { - if !key.is_empty() { - log::info!("Key: {}", key); +#[tokio::main(flavor = "multi_thread")] +pub async fn start(port: &str, key: &str) -> ResultType<()> { + let key = get_server_sk(key); + if let Ok(mut file) = std::fs::File::open(BLACKLIST_FILE) { + let mut contents = String::new(); + if file.read_to_string(&mut contents).is_ok() { + for x in contents.split("\n") { + if let Some(ip) = x.trim().split(' ').nth(0) { + BLACKLIST.write().await.insert(ip.to_owned()); + } + } + } + } + log::info!( + "#blacklist({}): {}", + BLACKLIST_FILE, + BLACKLIST.read().await.len() + ); + if let Ok(mut file) = std::fs::File::open(BLOCKLIST_FILE) { + let mut contents = String::new(); + if file.read_to_string(&mut contents).is_ok() { + for x in contents.split("\n") { + if let Some(ip) = x.trim().split(' ').nth(0) { + BLOCKLIST.write().await.insert(ip.to_owned()); + } + } + } } + log::info!( + "#blocklist({}): {}", + BLOCKLIST_FILE, + BLOCKLIST.read().await.len() + ); let addr = format!("0.0.0.0:{}", port); log::info!("Listening on tcp {}", addr); - let mut listener = new_listener(addr, false).await?; + let addr2 = format!("0.0.0.0:{}", port.parse::<u16>().unwrap() + 2); + log::info!("Listening on websocket {}", addr2); loop { - if *stop.lock().unwrap() { - sleep(0.1).await; - continue; - } log::info!("Start"); - io_loop(&mut listener, key, stop.clone()).await; + io_loop( + new_listener(&addr, false).await?, + new_listener(&addr2, false).await?, + &key, + ) + .await; } } -async fn io_loop(listener: &mut TcpListener, key: &str, stop: Arc<Mutex<bool>>) { - let mut timer = interval(Duration::from_millis(100)); +fn check_params() { + let tmp = std::env::var("DOWNGRADE_THRESHOLD") + .map(|x| x.parse::<f64>().unwrap_or(0.)) + .unwrap_or(0.); + if tmp > 0. { + unsafe { + DOWNGRADE_THRESHOLD = tmp; + } + } + unsafe { log::info!("DOWNGRADE_THRESHOLD: {}", DOWNGRADE_THRESHOLD) }; + let tmp = std::env::var("DOWNGRADE_START_CHECK") + .map(|x| x.parse::<usize>().unwrap_or(0)) + .unwrap_or(0); + if tmp > 0 { + unsafe { + DOWNGRADE_START_CHECK = tmp * 1000; + } + } + unsafe { log::info!("DOWNGRADE_START_CHECK: {}s", DOWNGRADE_START_CHECK / 1000) }; + let tmp = std::env::var("LIMIT_SPEED") + .map(|x| x.parse::<f64>().unwrap_or(0.)) + .unwrap_or(0.); + if tmp > 0. { + unsafe { + LIMIT_SPEED = (tmp * 1024. * 1024.) as usize; + } + } + unsafe { log::info!("LIMIT_SPEED: {}Mb/s", LIMIT_SPEED as f64 / 1024. / 1024.) }; + let tmp = std::env::var("TOTAL_BANDWIDTH") + .map(|x| x.parse::<f64>().unwrap_or(0.)) + .unwrap_or(0.); + if tmp > 0. { + unsafe { + TOTAL_BANDWIDTH = (tmp * 1024. * 1024.) as usize; + } + } + unsafe { + log::info!( + "TOTAL_BANDWIDTH: {}Mb/s", + TOTAL_BANDWIDTH as f64 / 1024. / 1024. + ) + }; + let tmp = std::env::var("SINGLE_BANDWIDTH") + .map(|x| x.parse::<f64>().unwrap_or(0.)) + .unwrap_or(0.); + if tmp > 0. { + unsafe { + SINGLE_BANDWIDTH = (tmp * 1024. * 1024.) as usize; + } + } + unsafe { + log::info!( + "SINGLE_BANDWIDTH: {}Mb/s", + SINGLE_BANDWIDTH as f64 / 1024. / 1024. + ) + }; +} + +async fn check_cmd(cmd: &str, limiter: Limiter) -> String { + let mut res = "".to_owned(); + let mut fds = cmd.trim().split(" "); + match fds.next() { + Some("h") => { + res = format!( + "{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n", + "blacklist-add(ba) <ip>", + "blacklist-remove(br) <ip>", + "blacklist(b) <ip>", + "blocklist-add(Ba) <ip>", + "blocklist-remove(Br) <ip>", + "blocklist(B) <ip>", + "downgrade-threshold(dt) [value]", + "downgrade-start-check(t) [value(second)]", + "limit-speed(ls) [value(Mb/s)]", + "total-bandwidth(tb) [value(Mb/s)]", + "single-bandwidth(sb) [value(Mb/s)]", + "usage(u)" + ) + } + Some("blacklist-add" | "ba") => { + if let Some(ip) = fds.next() { + for ip in ip.split("|") { + BLACKLIST.write().await.insert(ip.to_owned()); + } + } + } + Some("blacklist-remove" | "br") => { + if let Some(ip) = fds.next() { + if ip == "all" { + BLACKLIST.write().await.clear(); + } else { + for ip in ip.split("|") { + BLACKLIST.write().await.remove(ip); + } + } + } + } + Some("blacklist" | "b") => { + if let Some(ip) = fds.next() { + res = format!("{}\n", BLACKLIST.read().await.get(ip).is_some()); + } else { + for ip in BLACKLIST.read().await.clone().into_iter() { + res += &format!("{}\n", ip); + } + } + } + Some("blocklist-add" | "Ba") => { + if let Some(ip) = fds.next() { + for ip in ip.split("|") { + BLOCKLIST.write().await.insert(ip.to_owned()); + } + } + } + Some("blocklist-remove" | "Br") => { + if let Some(ip) = fds.next() { + if ip == "all" { + BLOCKLIST.write().await.clear(); + } else { + for ip in ip.split("|") { + BLOCKLIST.write().await.remove(ip); + } + } + } + } + Some("blocklist" | "B") => { + if let Some(ip) = fds.next() { + res = format!("{}\n", BLOCKLIST.read().await.get(ip).is_some()); + } else { + for ip in BLOCKLIST.read().await.clone().into_iter() { + res += &format!("{}\n", ip); + } + } + } + Some("downgrade-threshold" | "dt") => { + if let Some(v) = fds.next() { + if let Ok(v) = v.parse::<f64>() { + if v > 0. { + unsafe { + DOWNGRADE_THRESHOLD = v; + } + } + } + } else { + unsafe { + res = format!("{}\n", DOWNGRADE_THRESHOLD); + } + } + } + Some("downgrade-start-check" | "t") => { + if let Some(v) = fds.next() { + if let Ok(v) = v.parse::<usize>() { + if v > 0 { + unsafe { + DOWNGRADE_START_CHECK = v * 1000; + } + } + } + } else { + unsafe { + res = format!("{}s\n", DOWNGRADE_START_CHECK / 1000); + } + } + } + Some("limit-speed" | "ls") => { + if let Some(v) = fds.next() { + if let Ok(v) = v.parse::<f64>() { + if v > 0. { + unsafe { + LIMIT_SPEED = (v * 1024. * 1024.) as _; + } + } + } + } else { + unsafe { + res = format!("{}Mb/s\n", LIMIT_SPEED as f64 / 1024. / 1024.); + } + } + } + Some("total-bandwidth" | "tb") => { + if let Some(v) = fds.next() { + if let Ok(v) = v.parse::<f64>() { + if v > 0. { + unsafe { + TOTAL_BANDWIDTH = (v * 1024. * 1024.) as _; + limiter.set_speed_limit(TOTAL_BANDWIDTH as _); + } + } + } + } else { + unsafe { + res = format!("{}Mb/s\n", TOTAL_BANDWIDTH as f64 / 1024. / 1024.); + } + } + } + Some("single-bandwidth" | "sb") => { + if let Some(v) = fds.next() { + if let Ok(v) = v.parse::<f64>() { + if v > 0. { + unsafe { + SINGLE_BANDWIDTH = (v * 1024. * 1024.) as _; + } + } + } + } else { + unsafe { + res = format!("{}Mb/s\n", SINGLE_BANDWIDTH as f64 / 1024. / 1024.); + } + } + } + Some("usage" | "u") => { + let mut tmp: Vec<(String, Usage)> = USAGE + .read() + .await + .iter() + .map(|x| (x.0.clone(), x.1.clone())) + .collect(); + tmp.sort_by(|a, b| ((b.1).1).partial_cmp(&(a.1).1).unwrap()); + for (ip, (elapsed, total, highest, speed)) in tmp { + if elapsed <= 0 { + continue; + } + res += &format!( + "{}: {}s {:.2}MB {}kb/s {}kb/s {}kb/s\n", + ip, + elapsed / 1000, + total as f64 / 1024. / 1024. / 8., + highest, + total / elapsed, + speed + ); + } + } + _ => {} + } + res +} + +async fn io_loop(listener: TcpListener, listener2: TcpListener, key: &str) { + check_params(); + let limiter = <Limiter>::new(unsafe { TOTAL_BANDWIDTH as _ }); loop { tokio::select! { - Ok((stream, addr)) = listener.accept() => { - let key = key.to_owned(); - tokio::spawn(async move { - make_pair(FramedStream::from(stream), addr, &key).await.ok(); - }); + res = listener.accept() => { + match res { + Ok((stream, addr)) => { + stream.set_nodelay(true).ok(); + handle_connection(stream, addr, &limiter, key, false).await; + } + Err(err) => { + log::error!("listener.accept failed: {}", err); + break; + } + } } - _ = timer.tick() => { - if *stop.lock().unwrap() { - log::info!("Stopped"); - break; + res = listener2.accept() => { + match res { + Ok((stream, addr)) => { + stream.set_nodelay(true).ok(); + handle_connection(stream, addr, &limiter, key, true).await; + } + Err(err) => { + log::error!("listener2.accept failed: {}", err); + break; + } } } } } } -async fn make_pair(stream: FramedStream, addr: SocketAddr, key: &str) -> ResultType<()> { +async fn handle_connection( + stream: TcpStream, + addr: SocketAddr, + limiter: &Limiter, + key: &str, + ws: bool, +) { + let ip = addr.ip().to_string(); + if !ws && ip == "127.0.0.1" { + let limiter = limiter.clone(); + tokio::spawn(async move { + let mut stream = stream; + let mut buffer = [0; 64]; + if let Ok(Ok(n)) = timeout(1000, stream.read(&mut buffer[..])).await { + if let Ok(data) = std::str::from_utf8(&buffer[..n]) { + let res = check_cmd(data, limiter).await; + stream.write(res.as_bytes()).await.ok(); + } + } + }); + return; + } + if BLOCKLIST.read().await.get(&ip).is_some() { + log::info!("{} blocked", ip); + return; + } + let key = key.to_owned(); + let limiter = limiter.clone(); + tokio::spawn(async move { + allow_err!(make_pair(stream, addr, &key, limiter, ws).await); + }); +} + +async fn make_pair( + stream: TcpStream, + addr: SocketAddr, + key: &str, + limiter: Limiter, + ws: bool, +) -> ResultType<()> { + if ws { + make_pair_( + tokio_tungstenite::accept_async(stream).await?, + addr, + key, + limiter, + ) + .await; + } else { + make_pair_(FramedStream::from(stream, addr), addr, key, limiter).await; + } + Ok(()) +} + +async fn make_pair_(stream: impl StreamTrait, addr: SocketAddr, key: &str, limiter: Limiter) { let mut stream = stream; - if let Some(Ok(bytes)) = stream.next_timeout(30_000).await { + if let Ok(Some(Ok(bytes))) = timeout(30_000, stream.recv()).await { if let Ok(msg_in) = RendezvousMessage::parse_from_bytes(&bytes) { if let Some(rendezvous_message::Union::request_relay(rf)) = msg_in.union { if !key.is_empty() && rf.licence_key != key { - return Ok(()); + return; } if !rf.uuid.is_empty() { - let peer = PEERS.lock().unwrap().remove(&rf.uuid); - if let Some(peer) = peer { - log::info!("Forward request {} from {} got paired", rf.uuid, addr); - return relay(stream, peer).await; + let mut peer = PEERS.lock().await.remove(&rf.uuid); + if let Some(peer) = peer.as_mut() { + log::info!("Relayrequest {} from {} got paired", rf.uuid, addr); + let id = format!("{}:{}", addr.ip(), addr.port()); + USAGE.write().await.insert(id.clone(), Default::default()); + if !stream.is_ws() && !peer.is_ws() { + peer.set_raw(); + stream.set_raw(); + log::info!("Both are raw"); + } + if let Err(err) = relay(addr, &mut stream, peer, limiter, id.clone()).await + { + log::info!("Relay of {} closed: {}", addr, err); + } else { + log::info!("Relay of {} closed", addr); + } + USAGE.write().await.remove(&id); } else { log::info!("New relay request {} from {}", rf.uuid, addr); - PEERS.lock().unwrap().insert(rf.uuid.clone(), stream); + PEERS.lock().await.insert(rf.uuid.clone(), Box::new(stream)); sleep(30.).await; - PEERS.lock().unwrap().remove(&rf.uuid); + PEERS.lock().await.remove(&rf.uuid); } } } } } - Ok(()) } -async fn relay(stream: FramedStream, peer: FramedStream) -> ResultType<()> { - let mut peer = peer; - let mut stream = stream; - peer.set_raw(); - stream.set_raw(); +async fn relay( + addr: SocketAddr, + stream: &mut impl StreamTrait, + peer: &mut Box<dyn StreamTrait>, + total_limiter: Limiter, + id: String, +) -> ResultType<()> { + let ip = addr.ip().to_string(); + let mut tm = std::time::Instant::now(); + let mut elapsed = 0; + let mut total = 0; + let mut total_s = 0; + let mut highest_s = 0; + let mut downgrade: bool = false; + let mut blacked: bool = false; + let limiter = <Limiter>::new(unsafe { SINGLE_BANDWIDTH as _ }); + let blacklist_limiter = <Limiter>::new(unsafe { LIMIT_SPEED as _ }); + let downgrade_threshold = + (unsafe { SINGLE_BANDWIDTH as f64 * DOWNGRADE_THRESHOLD } / 1000.) as usize; // in bit/ms + let mut timer = interval(Duration::from_secs(3)); + let mut last_recv_time = std::time::Instant::now(); loop { tokio::select! { - res = peer.next() => { + res = peer.recv() => { if let Some(Ok(bytes)) = res { - stream.send_bytes(bytes.into()).await?; + last_recv_time = std::time::Instant::now(); + let nb = bytes.len() * 8; + if blacked || downgrade { + blacklist_limiter.consume(nb).await; + } else { + limiter.consume(nb).await; + } + total_limiter.consume(nb).await; + total += nb; + total_s += nb; + if bytes.len() > 0 { + stream.send_raw(bytes.into()).await?; + } } else { break; } }, - res = stream.next() => { + res = stream.recv() => { if let Some(Ok(bytes)) = res { - peer.send_bytes(bytes.into()).await?; + last_recv_time = std::time::Instant::now(); + let nb = bytes.len() * 8; + if blacked || downgrade { + blacklist_limiter.consume(nb).await; + } else { + limiter.consume(nb).await; + } + total_limiter.consume(nb).await; + total += nb; + total_s += nb; + if bytes.len() > 0 { + peer.send_raw(bytes.into()).await?; + } } else { break; } }, + _ = timer.tick() => { + if last_recv_time.elapsed().as_secs() > 30 { + bail!("Timeout"); + } + } + } + + let n = tm.elapsed().as_millis() as usize; + if n >= 1_000 { + if BLOCKLIST.read().await.get(&ip).is_some() { + log::info!("{} blocked", ip); + break; + } + blacked = BLACKLIST.read().await.get(&ip).is_some(); + tm = std::time::Instant::now(); + let speed = total_s / (n as usize); + if speed > highest_s { + highest_s = speed; + } + elapsed += n; + USAGE.write().await.insert( + id.clone(), + (elapsed as _, total as _, highest_s as _, speed as _), + ); + total_s = 0; + if elapsed > unsafe { DOWNGRADE_START_CHECK } && !downgrade { + if total > elapsed * downgrade_threshold { + downgrade = true; + log::info!( + "Downgrade {}, exceed downgrade threshold {}bit/ms in {}ms", + id, + downgrade_threshold, + elapsed + ); + } + } } } Ok(()) } + +fn get_server_sk(key: &str) -> String { + let mut key = key.to_owned(); + if let Ok(sk) = base64::decode(&key) { + if sk.len() == sign::SECRETKEYBYTES { + log::info!("The key is a crypto private key"); + key = base64::encode(&sk[(sign::SECRETKEYBYTES / 2)..]); + } + } + + if key == "-" || key == "_" { + let (pk, _) = crate::common::gen_sk(); + key = pk; + } + + if !key.is_empty() { + log::info!("Key: {}", key); + } + + key +} + +#[async_trait] +trait StreamTrait: Send + Sync + 'static { + async fn recv(&mut self) -> Option<Result<BytesMut, Error>>; + async fn send_raw(&mut self, bytes: Bytes) -> ResultType<()>; + fn is_ws(&self) -> bool; + fn set_raw(&mut self); +} + +#[async_trait] +impl StreamTrait for FramedStream { + async fn recv(&mut self) -> Option<Result<BytesMut, Error>> { + self.next().await + } + + async fn send_raw(&mut self, bytes: Bytes) -> ResultType<()> { + self.send_bytes(bytes).await + } + + fn is_ws(&self) -> bool { + false + } + + fn set_raw(&mut self) { + self.set_raw(); + } +} + +#[async_trait] +impl StreamTrait for tokio_tungstenite::WebSocketStream<TcpStream> { + async fn recv(&mut self) -> Option<Result<BytesMut, Error>> { + if let Some(msg) = self.next().await { + match msg { + Ok(msg) => { + match msg { + tungstenite::Message::Binary(bytes) => { + Some(Ok(bytes[..].into())) // to-do: poor performance + } + _ => Some(Ok(BytesMut::new())), + } + } + Err(err) => Some(Err(Error::new(std::io::ErrorKind::Other, err.to_string()))), + } + } else { + None + } + } + + async fn send_raw(&mut self, bytes: Bytes) -> ResultType<()> { + Ok(self + .send(tungstenite::Message::Binary(bytes.to_vec())) + .await?) // to-do: poor performance + } + + fn is_ws(&self) -> bool { + true + } + + fn set_raw(&mut self) {} +} diff --git a/src/rendezvous_server.rs b/src/rendezvous_server.rs index 8f9e5f1..abe319d 100644 --- a/src/rendezvous_server.rs +++ b/src/rendezvous_server.rs @@ -1,212 +1,193 @@ +use crate::common::*; +use crate::peer::*; use hbb_common::{ allow_err, bytes::{Bytes, BytesMut}, bytes_codec::BytesCodec, + futures::future::join_all, futures_util::{ sink::SinkExt, stream::{SplitSink, StreamExt}, }, log, protobuf::{Message as _, MessageField}, - rendezvous_proto::*, - sleep, + rendezvous_proto::{ + register_pk_response::Result::{TOO_FREQUENT, UUID_MISMATCH}, + *, + }, tcp::{new_listener, FramedStream}, timeout, tokio::{ self, + io::{AsyncReadExt, AsyncWriteExt}, net::{TcpListener, TcpStream}, - sync::mpsc, + sync::{mpsc, Mutex}, time::{interval, Duration}, }, tokio_util::codec::Framed, udp::FramedSocket, AddrMangle, ResultType, }; -use serde_derive::{Deserialize, Serialize}; +use sodiumoxide::crypto::sign; use std::{ collections::HashMap, - net::SocketAddr, - sync::{Arc, Mutex, RwLock}, + net::{IpAddr, Ipv4Addr, SocketAddr}, + sync::Arc, time::Instant, }; +const ADDR_127: IpAddr = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)); #[derive(Clone, Debug)] -struct Peer { - socket_addr: SocketAddr, - last_reg_time: Instant, - uuid: Vec<u8>, - pk: Vec<u8>, -} - -impl Default for Peer { - fn default() -> Self { - Self { - socket_addr: "0.0.0.0:0".parse().unwrap(), - last_reg_time: Instant::now() - .checked_sub(std::time::Duration::from_secs(3600)) - .unwrap(), - uuid: Vec::new(), - pk: Vec::new(), - } - } -} - -#[derive(Debug, Serialize, Deserialize, Default)] -struct PeerSerde { - #[serde(default)] - ip: String, - #[serde(default)] - uuid: Vec<u8>, - #[serde(default)] - pk: Vec<u8>, -} - -#[derive(Clone)] -struct PeerMap { - map: Arc<RwLock<HashMap<String, Peer>>>, - db: super::SledAsync, -} - -pub const DEFAULT_PORT: &'static str = "21116"; - -impl PeerMap { - fn new() -> ResultType<Self> { - let mut db: String = "hbbs.db".to_owned(); - #[cfg(windows)] - { - if let Some(path) = hbb_common::config::Config::icon_path().parent() { - db = format!("{}\\{}", path.to_str().unwrap_or("."), db); - } - } - #[cfg(not(windows))] - { - db = format!("./{}", db); - } - Ok(Self { - map: Default::default(), - db: super::SledAsync::new(&db, true)?, - }) - } - - #[inline] - fn update_pk(&mut self, id: String, socket_addr: SocketAddr, uuid: Vec<u8>, pk: Vec<u8>) { - log::info!("update_pk {} {:?} {:?} {:?}", id, socket_addr, uuid, pk); - let mut lock = self.map.write().unwrap(); - lock.insert( - id.clone(), - Peer { - socket_addr, - last_reg_time: Instant::now(), - uuid: uuid.clone(), - pk: pk.clone(), - }, - ); - drop(lock); - let ip = socket_addr.ip().to_string(); - self.db.insert(id, PeerSerde { ip, uuid, pk }); - } - - #[inline] - async fn get(&mut self, id: &str) -> Option<Peer> { - let p = self.map.read().unwrap().get(id).map(|x| x.clone()); - if p.is_some() { - return p; - } else { - let id = id.to_owned(); - let v = self.db.get(id.clone()).await; - if let Some(v) = super::SledAsync::deserialize::<PeerSerde>(&v) { - self.map.write().unwrap().insert( - id, - Peer { - uuid: v.uuid, - pk: v.pk, - ..Default::default() - }, - ); - return Some(Peer::default()); - } - } - None - } - - #[inline] - fn is_in_memory(&self, id: &str) -> bool { - self.map.read().unwrap().contains_key(id) - } +enum Data { + Msg(RendezvousMessage, SocketAddr), + RelayServers0(String), + RelayServers(RelayServers), } const REG_TIMEOUT: i32 = 30_000; -type Sink = SplitSink<Framed<TcpStream, BytesCodec>, Bytes>; -type Sender = mpsc::UnboundedSender<(RendezvousMessage, SocketAddr)>; -type Receiver = mpsc::UnboundedReceiver<(RendezvousMessage, SocketAddr)>; +type TcpStreamSink = SplitSink<Framed<TcpStream, BytesCodec>, Bytes>; +type WsSink = SplitSink<tokio_tungstenite::WebSocketStream<TcpStream>, tungstenite::Message>; +enum Sink { + TcpStream(TcpStreamSink), + Ws(WsSink), +} +type Sender = mpsc::UnboundedSender<Data>; +type Receiver = mpsc::UnboundedReceiver<Data>; static mut ROTATION_RELAY_SERVER: usize = 0; +type RelayServers = Vec<String>; +static CHECK_RELAY_TIMEOUT: u64 = 3_000; +static mut ALWAYS_USE_RELAY: bool = false; #[derive(Clone)] pub struct RendezvousServer { tcp_punch: Arc<Mutex<HashMap<SocketAddr, Sink>>>, pm: PeerMap, tx: Sender, - relay_servers: Vec<String>, + relay_servers: Arc<RelayServers>, + relay_servers0: Arc<RelayServers>, serial: i32, - rendezvous_servers: Vec<String>, + rendezvous_servers: Arc<Vec<String>>, version: String, software_url: String, + sk: Option<sign::SecretKey>, +} + +enum LoopFailure { + UdpSocket, + Listener3, + Listener2, + Listener, } impl RendezvousServer { - #[tokio::main(basic_scheduler)] + #[tokio::main(flavor = "multi_thread")] pub async fn start( - addr: &str, - addr2: &str, - relay_servers: Vec<String>, + port: i32, serial: i32, - rendezvous_servers: Vec<String>, - software_url: String, key: &str, - stop: Arc<Mutex<bool>>, id_change_support: bool, + rmem: usize, ) -> ResultType<()> { - if !key.is_empty() { - log::info!("Key: {}", key); + let addr = format!("0.0.0.0:{}", port); + let addr2 = format!("0.0.0.0:{}", port - 1); + let addr3 = format!("0.0.0.0:{}", port + 2); + let pm = PeerMap::new().await?; + #[cfg(not(debug_assertions))] + if !crate::lic::check_lic(&get_arg("email"), crate::version::VERSION) { + return Ok(()); } + log::info!("serial={}", serial); + let rendezvous_servers = get_servers(&get_arg("rendezvous-servers"), "rendezvous-servers"); log::info!("Listening on tcp/udp {}", addr); log::info!("Listening on tcp {}, extra port for NAT test", addr2); - log::info!("relay-servers={:?}", relay_servers); + log::info!("Listening on websocket {}", addr3); log::info!("change-id={:?}", id_change_support); - let mut socket = FramedSocket::new(addr).await?; - let (tx, mut rx) = mpsc::unbounded_channel::<(RendezvousMessage, SocketAddr)>(); + let mut socket = FramedSocket::new_with_buf_size(&addr, rmem).await?; + let (tx, mut rx) = mpsc::unbounded_channel::<Data>(); + let software_url = get_arg("software-url"); let version = hbb_common::get_version_from_url(&software_url); if !version.is_empty() { log::info!("software_url: {}, version: {}", software_url, version); } let mut rs = Self { tcp_punch: Arc::new(Mutex::new(HashMap::new())), - pm: PeerMap::new()?, + pm, tx: tx.clone(), - relay_servers, + relay_servers: Default::default(), + relay_servers0: Default::default(), serial, - rendezvous_servers, + rendezvous_servers: Arc::new(rendezvous_servers), version, software_url, + sk: None, }; - let mut listener = new_listener(addr, false).await?; - let mut listener2 = new_listener(addr2, false).await?; - loop { - if *stop.lock().unwrap() { - sleep(0.1).await; - continue; + let key = rs.get_server_sk(key); + std::env::set_var("PORT_FOR_API", port.to_string()); + rs.parse_relay_servers(&get_arg("relay-servers")); + let pm = rs.pm.clone(); + let mut listener = new_listener(&addr, false).await?; + let mut listener2 = new_listener(&addr2, false).await?; + let mut listener3 = new_listener(&addr3, false).await?; + let test_addr = std::env::var("TEST_HBBS").unwrap_or_default(); + if std::env::var("ALWAYS_USE_RELAY") + .unwrap_or_default() + .to_uppercase() + == "Y" + { + unsafe { + ALWAYS_USE_RELAY = true; + } + } + log::info!( + "ALWAYS_USE_RELAY={}", + if unsafe { ALWAYS_USE_RELAY } { + "Y" + } else { + "N" } + ); + if test_addr.to_lowercase() != "no" { + let test_addr = (if test_addr.is_empty() { + addr.replace("0.0.0.0", "127.0.0.1") + } else { + test_addr + }) + .parse::<SocketAddr>()?; + tokio::spawn(async move { + allow_err!(test_hbbs(test_addr).await); + }); + }; + loop { log::info!("Start"); - rs.io_loop( - &mut rx, - &mut listener, - &mut listener2, - &mut socket, - key, - stop.clone(), - id_change_support, - ) - .await; + match rs + .io_loop( + &mut rx, + &mut listener, + &mut listener2, + &mut listener3, + &mut socket, + &key, + id_change_support, + ) + .await + { + LoopFailure::UdpSocket => { + drop(socket); + socket = FramedSocket::new_with_buf_size(&addr, rmem).await?; + } + LoopFailure::Listener => { + drop(listener); + listener = new_listener(&addr, false).await?; + } + LoopFailure::Listener2 => { + drop(listener2); + listener2 = new_listener(&addr2, false).await?; + } + LoopFailure::Listener3 => { + drop(listener3); + listener3 = new_listener(&addr3, false).await?; + } + } } } @@ -215,161 +196,89 @@ impl RendezvousServer { rx: &mut Receiver, listener: &mut TcpListener, listener2: &mut TcpListener, + listener3: &mut TcpListener, socket: &mut FramedSocket, key: &str, - stop: Arc<Mutex<bool>>, id_change_support: bool, - ) { - let mut timer = interval(Duration::from_millis(100)); + ) -> LoopFailure { + let mut timer_check_relay = interval(Duration::from_millis(CHECK_RELAY_TIMEOUT)); loop { tokio::select! { - _ = timer.tick() => { - if *stop.lock().unwrap() { - log::info!("Stopped"); - break; - } - } - Some((msg, addr)) = rx.recv() => { - allow_err!(socket.send(&msg, addr).await); - } - Some(Ok((bytes, addr))) = socket.next() => { - allow_err!(self.handle_msg(&bytes, addr, socket, key).await); - } - Ok((stream, addr)) = listener2.accept() => { - let stream = FramedStream::from(stream); - tokio::spawn(async move { - let mut stream = stream; - if let Some(Ok(bytes)) = stream.next_timeout(30_000).await { - if let Ok(msg_in) = RendezvousMessage::parse_from_bytes(&bytes) { - if let Some(rendezvous_message::Union::test_nat_request(_)) = msg_in.union { - let mut msg_out = RendezvousMessage::new(); - msg_out.set_test_nat_response(TestNatResponse { - port: addr.port() as _, - ..Default::default() - }); - stream.send(&msg_out).await.ok(); - } + _ = timer_check_relay.tick() => { + if self.relay_servers0.len() > 1 { + let rs = self.relay_servers0.clone(); + let tx = self.tx.clone(); + tokio::spawn(async move { + check_relay_servers(rs, tx).await; + }); + } + } + Some(data) = rx.recv() => { + match data { + Data::Msg(msg, addr) => { allow_err!(socket.send(&msg, addr).await); } + Data::RelayServers0(rs) => { self.parse_relay_servers(&rs); } + Data::RelayServers(rs) => { self.relay_servers = Arc::new(rs); } + } + } + res = socket.next() => { + match res { + Some(Ok((bytes, addr))) => { + if let Err(err) = self.handle_udp(&bytes, addr.into(), socket, key).await { + log::error!("udp failure: {}", err); + return LoopFailure::UdpSocket; } } - }); + Some(Err(err)) => { + log::error!("udp failure: {}", err); + return LoopFailure::UdpSocket; + } + None => { + // unreachable!() ? + } + } } - Ok((stream, addr)) = listener.accept() => { - log::debug!("Tcp connection from {:?}", addr); - let (a, mut b) = Framed::new(stream, BytesCodec::new()).split(); - let tcp_punch = self.tcp_punch.clone(); - let mut rs = self.clone(); - let key = key.to_owned(); - tokio::spawn(async move { - let mut sender = Some(a); - while let Ok(Some(Ok(bytes))) = timeout(30_000, b.next()).await { - if let Ok(msg_in) = RendezvousMessage::parse_from_bytes(&bytes) { - match msg_in.union { - Some(rendezvous_message::Union::punch_hole_request(ph)) => { - // there maybe several attempt, so sender can be none - if let Some(sender) = sender.take() { - tcp_punch.lock().unwrap().insert(addr, sender); - } - allow_err!(rs.handle_tcp_punch_hole_request(addr, ph, &key).await); - } - Some(rendezvous_message::Union::request_relay(mut rf)) => { - // there maybe several attempt, so sender can be none - if let Some(sender) = sender.take() { - tcp_punch.lock().unwrap().insert(addr, sender); - } - if let Some(peer) = rs.pm.map.read().unwrap().get(&rf.id).map(|x| x.clone()) { - let mut msg_out = RendezvousMessage::new(); - rf.socket_addr = AddrMangle::encode(addr); - msg_out.set_request_relay(rf); - rs.tx.send((msg_out, peer.socket_addr)).ok(); - } - } - Some(rendezvous_message::Union::relay_response(mut rr)) => { - let addr_b = AddrMangle::decode(&rr.socket_addr); - rr.socket_addr = Default::default(); - let id = rr.get_id(); - if !id.is_empty() { - if let Some(peer) = rs.pm.get(&id).await { - rr.set_pk(peer.pk.clone()); - } - } - let mut msg_out = RendezvousMessage::new(); - msg_out.set_relay_response(rr); - allow_err!(rs.send_to_tcp_sync(&msg_out, addr_b).await); - break; - } - Some(rendezvous_message::Union::punch_hole_sent(phs)) => { - allow_err!(rs.handle_hole_sent(phs, addr, None).await); - break; - } - Some(rendezvous_message::Union::local_addr(la)) => { - allow_err!(rs.handle_local_addr(la, addr, None).await); - break; - } - Some(rendezvous_message::Union::test_nat_request(tar)) => { - let mut msg_out = RendezvousMessage::new(); - let mut res = TestNatResponse { - port: addr.port() as _, - ..Default::default() - }; - if rs.serial > tar.serial { - let mut cu = ConfigUpdate::new(); - cu.serial = rs.serial; - cu.rendezvous_servers = rs.rendezvous_servers.clone(); - res.cu = MessageField::from_option(Some(cu)); - } - msg_out.set_test_nat_response(res); - if let Some(tcp) = sender.as_mut() { - if let Ok(bytes) = msg_out.write_to_bytes() { - allow_err!(tcp.send(Bytes::from(bytes)).await); - } - } - break; - } - Some(rendezvous_message::Union::register_pk(rk)) => { - if rk.uuid.is_empty() { - break; - } - let mut res = register_pk_response::Result::OK; - if !id_change_support { - res = register_pk_response::Result::NOT_SUPPORT; - } else if !hbb_common::is_valid_custom_id(&rk.id) { - res = register_pk_response::Result::INVALID_ID_FORMAT; - } else if let Some(peer) = rs.pm.get(&rk.id).await { - if peer.uuid != rk.uuid { - res = register_pk_response::Result::ID_EXISTS; - } - } - let mut msg_out = RendezvousMessage::new(); - msg_out.set_register_pk_response(RegisterPkResponse { - result: res.into(), - ..Default::default() - }); - if let Some(tcp) = sender.as_mut() { - if let Ok(bytes) = msg_out.write_to_bytes() { - allow_err!(tcp.send(Bytes::from(bytes)).await); - } - } - } - _ => { - break; - } - } - } else { - break; - } + res = listener2.accept() => { + match res { + Ok((stream, addr)) => { + stream.set_nodelay(true).ok(); + self.handle_listener2(stream, addr).await; } - if sender.is_none() { - rs.tcp_punch.lock().unwrap().remove(&addr); + Err(err) => { + log::error!("listener2.accept failed: {}", err); + return LoopFailure::Listener2; } - log::debug!("Tcp connection from {:?} closed", addr); - }); + } + } + res = listener3.accept() => { + match res { + Ok((stream, addr)) => { + stream.set_nodelay(true).ok(); + self.handle_listener(stream, addr, key, id_change_support, true).await; + } + Err(err) => { + log::error!("listener3.accept failed: {}", err); + return LoopFailure::Listener3; + } + } + } + res = listener.accept() => { + match res { + Ok((stream, addr)) => { + stream.set_nodelay(true).ok(); + self.handle_listener(stream, addr, key, id_change_support, false).await; + } + Err(err) => { + log::error!("listener.accept failed: {}", err); + return LoopFailure::Listener; + } + } } } } } #[inline] - async fn handle_msg( + async fn handle_udp( &mut self, bytes: &BytesMut, addr: SocketAddr, @@ -387,7 +296,7 @@ impl RendezvousServer { let mut msg_out = RendezvousMessage::new(); msg_out.set_configure_update(ConfigUpdate { serial: self.serial, - rendezvous_servers: self.rendezvous_servers.clone(), + rendezvous_servers: (*self.rendezvous_servers).clone(), ..Default::default() }); socket.send(&msg_out, addr).await?; @@ -395,39 +304,94 @@ impl RendezvousServer { } } Some(rendezvous_message::Union::register_pk(rk)) => { - if rk.uuid.is_empty() { + if rk.uuid.is_empty() || rk.pk.is_empty() { return Ok(()); } let id = rk.id; - let mut res = register_pk_response::Result::OK; + let ip = addr.ip().to_string(); if id.len() < 6 { - res = register_pk_response::Result::UUID_MISMATCH; - } else if let Some(peer) = self.pm.get(&id).await { + return send_rk_res(socket, addr, UUID_MISMATCH).await; + } else if !self.check_ip_blocker(&ip, &id).await { + return send_rk_res(socket, addr, TOO_FREQUENT).await; + } + let peer = self.pm.get_or(&id).await; + let (changed, ip_changed) = { + let peer = peer.read().await; if peer.uuid.is_empty() { - self.pm.update_pk(id, addr, rk.uuid, rk.pk); - } else if peer.uuid != rk.uuid { - log::warn!( - "Peer {} uuid mismatch: {:?} vs {:?}", - id, - rk.uuid, - peer.uuid + (true, false) + } else { + if peer.uuid == rk.uuid { + if peer.info.ip != ip && peer.pk != rk.pk { + log::warn!( + "Peer {} ip/pk mismatch: {}/{:?} vs {}/{:?}", + id, + ip, + rk.pk, + peer.info.ip, + peer.pk, + ); + drop(peer); + return send_rk_res(socket, addr, UUID_MISMATCH).await; + } + } else { + log::warn!( + "Peer {} uuid mismatch: {:?} vs {:?}", + id, + rk.uuid, + peer.uuid + ); + drop(peer); + return send_rk_res(socket, addr, UUID_MISMATCH).await; + } + let ip_changed = peer.info.ip != ip; + ( + peer.uuid != rk.uuid || peer.pk != rk.pk || ip_changed, + ip_changed, + ) + } + }; + let mut req_pk = peer.read().await.reg_pk; + if req_pk.1.elapsed().as_secs() > 6 { + req_pk.0 = 0; + } else if req_pk.0 > 2 { + return send_rk_res(socket, addr, TOO_FREQUENT).await; + } + req_pk.0 += 1; + req_pk.1 = Instant::now(); + peer.write().await.reg_pk = req_pk; + if ip_changed { + let mut lock = IP_CHANGES.lock().await; + if let Some((tm, ips)) = lock.get_mut(&id) { + if tm.elapsed().as_secs() > IP_CHANGE_DUR { + *tm = Instant::now(); + ips.clear(); + ips.insert(ip.clone(), 1); + } else { + if let Some(v) = ips.get_mut(&ip) { + *v += 1; + } else { + ips.insert(ip.clone(), 1); + } + } + } else { + lock.insert( + id.clone(), + (Instant::now(), HashMap::from([(ip.clone(), 1)])), ); - res = register_pk_response::Result::UUID_MISMATCH; - } else if peer.pk != rk.pk { - self.pm.update_pk(id, addr, rk.uuid, rk.pk); } - } else { - self.pm.update_pk(id, addr, rk.uuid, rk.pk); + } + if changed { + self.pm.update_pk(id, peer, addr, rk.uuid, rk.pk, ip).await; } let mut msg_out = RendezvousMessage::new(); msg_out.set_register_pk_response(RegisterPkResponse { - result: res.into(), + result: register_pk_response::Result::OK.into(), ..Default::default() }); socket.send(&msg_out, addr).await? } Some(rendezvous_message::Union::punch_hole_request(ph)) => { - if self.pm.is_in_memory(&ph.id) { + if self.pm.is_in_memory(&ph.id).await { self.handle_udp_punch_hole_request(addr, ph, key).await?; } else { // not in memory, fetch from db with spawn in case blocking me @@ -445,18 +409,17 @@ impl RendezvousServer { self.handle_local_addr(la, addr, Some(socket)).await?; } Some(rendezvous_message::Union::configure_update(mut cu)) => { - if addr.ip() == std::net::IpAddr::V4(std::net::Ipv4Addr::new(127, 0, 0, 1)) - && cu.serial > self.serial - { + if addr.ip() == ADDR_127 && cu.serial > self.serial { self.serial = cu.serial; - self.rendezvous_servers = cu - .rendezvous_servers - .drain(..) - .filter(|x| { - !x.is_empty() - && test_if_valid_server(x, "rendezvous-server").is_ok() - }) - .collect(); + self.rendezvous_servers = Arc::new( + cu.rendezvous_servers + .drain(..) + .filter(|x| { + !x.is_empty() + && test_if_valid_server(x, "rendezvous-server").is_ok() + }) + .collect(), + ); log::info!( "configure updated: serial={} rendezvous-servers={:?}", self.serial, @@ -481,56 +444,129 @@ impl RendezvousServer { } #[inline] + async fn handle_tcp( + &mut self, + bytes: &[u8], + sink: &mut Option<Sink>, + addr: SocketAddr, + key: &str, + id_change_support: bool, + ws: bool, + ) -> bool { + if let Ok(msg_in) = RendezvousMessage::parse_from_bytes(&bytes) { + match msg_in.union { + Some(rendezvous_message::Union::punch_hole_request(ph)) => { + // there maybe several attempt, so sink can be none + if let Some(sink) = sink.take() { + self.tcp_punch.lock().await.insert(addr, sink); + } + allow_err!(self.handle_tcp_punch_hole_request(addr, ph, &key, ws).await); + return true; + } + Some(rendezvous_message::Union::request_relay(mut rf)) => { + // there maybe several attempt, so sink can be none + if let Some(sink) = sink.take() { + self.tcp_punch.lock().await.insert(addr, sink); + } + if let Some(peer) = self.pm.get_in_memory(&rf.id).await { + let mut msg_out = RendezvousMessage::new(); + rf.socket_addr = AddrMangle::encode(addr); + msg_out.set_request_relay(rf); + let peer_addr = peer.read().await.socket_addr; + self.tx.send(Data::Msg(msg_out, peer_addr)).ok(); + } + return true; + } + Some(rendezvous_message::Union::relay_response(mut rr)) => { + let addr_b = AddrMangle::decode(&rr.socket_addr); + rr.socket_addr = Default::default(); + let id = rr.get_id(); + if !id.is_empty() { + let pk = self.get_pk(&rr.version, id.to_owned()).await; + rr.set_pk(pk); + } + let mut msg_out = RendezvousMessage::new(); + msg_out.set_relay_response(rr); + allow_err!(self.send_to_tcp_sync(msg_out, addr_b).await); + } + Some(rendezvous_message::Union::punch_hole_sent(phs)) => { + allow_err!(self.handle_hole_sent(phs, addr, None).await); + } + Some(rendezvous_message::Union::local_addr(la)) => { + allow_err!(self.handle_local_addr(la, addr, None).await); + } + Some(rendezvous_message::Union::test_nat_request(tar)) => { + let mut msg_out = RendezvousMessage::new(); + let mut res = TestNatResponse { + port: addr.port() as _, + ..Default::default() + }; + if self.serial > tar.serial { + let mut cu = ConfigUpdate::new(); + cu.serial = self.serial; + cu.rendezvous_servers = (*self.rendezvous_servers).clone(); + res.cu = MessageField::from_option(Some(cu)); + } + msg_out.set_test_nat_response(res); + Self::send_to_sink(sink, msg_out).await; + } + Some(rendezvous_message::Union::register_pk(_rk)) => { + let res = register_pk_response::Result::NOT_SUPPORT; + let mut msg_out = RendezvousMessage::new(); + msg_out.set_register_pk_response(RegisterPkResponse { + result: res.into(), + ..Default::default() + }); + Self::send_to_sink(sink, msg_out).await; + } + _ => {} + } + } + false + } + + #[inline] async fn update_addr( &mut self, id: String, socket_addr: SocketAddr, socket: &mut FramedSocket, ) -> ResultType<()> { - let mut lock = self.pm.map.write().unwrap(); - let last_reg_time = Instant::now(); - if let Some(old) = lock.get_mut(&id) { - old.socket_addr = socket_addr; - old.last_reg_time = last_reg_time; - let request_pk = old.pk.is_empty(); - drop(lock); - let mut msg_out = RendezvousMessage::new(); - msg_out.set_register_peer_response(RegisterPeerResponse { - request_pk, - ..Default::default() - }); - socket.send(&msg_out, socket_addr).await?; + let (request_pk, ip_change) = if let Some(old) = self.pm.get_in_memory(&id).await { + let mut old = old.write().await; + let ip = socket_addr.ip(); + let ip_change = if old.socket_addr.port() != 0 { + ip != old.socket_addr.ip() + } else { + ip.to_string() != old.info.ip + } && ip != ADDR_127; + let request_pk = old.pk.is_empty() || ip_change; + if !request_pk { + old.socket_addr = socket_addr; + old.last_reg_time = Instant::now(); + } + let ip_change = if ip_change && old.reg_pk.0 <= 2 { + Some(if old.socket_addr.port() == 0 { + old.info.ip.clone() + } else { + old.socket_addr.to_string() + }) + } else { + None + }; + (request_pk, ip_change) } else { - drop(lock); - let mut pm = self.pm.clone(); - let tx = self.tx.clone(); - tokio::spawn(async move { - let v = pm.db.get(id.clone()).await; - let (uuid, pk) = { - if let Some(v) = super::SledAsync::deserialize::<PeerSerde>(&v) { - (v.uuid, v.pk) - } else { - (Vec::new(), Vec::new()) - } - }; - let mut msg_out = RendezvousMessage::new(); - msg_out.set_register_peer_response(RegisterPeerResponse { - request_pk: pk.is_empty(), - ..Default::default() - }); - tx.send((msg_out, socket_addr)).ok(); - pm.map.write().unwrap().insert( - id, - Peer { - socket_addr, - last_reg_time, - uuid, - pk, - }, - ); - }); + (true, None) + }; + if let Some(old) = ip_change { + log::info!("IP change of {} from {} to {}", id, old, socket_addr); } - Ok(()) + let mut msg_out = RendezvousMessage::new(); + msg_out.set_register_peer_response(RegisterPeerResponse { + request_pk, + ..Default::default() + }); + socket.send(&msg_out, socket_addr).await } #[inline] @@ -549,13 +585,9 @@ impl RendezvousServer { &addr ); let mut msg_out = RendezvousMessage::new(); - let pk = match self.pm.get(&phs.id).await { - Some(peer) => peer.pk, - _ => Vec::new(), - }; let mut p = PunchHoleResponse { socket_addr: AddrMangle::encode(addr), - pk, + pk: self.get_pk(&phs.version, phs.id).await, relay_server: phs.relay_server.clone(), ..Default::default() }; @@ -566,7 +598,7 @@ impl RendezvousServer { if let Some(socket) = socket { socket.send(&msg_out, addr_a).await?; } else { - self.send_to_tcp(&msg_out, addr_a).await; + self.send_to_tcp(msg_out, addr_a).await; } Ok(()) } @@ -587,17 +619,9 @@ impl RendezvousServer { &addr ); let mut msg_out = RendezvousMessage::new(); - let pk = if la.id.is_empty() { - Vec::new() - } else { - match self.pm.get(&la.id).await { - Some(peer) => peer.pk, - _ => Vec::new(), - } - }; let mut p = PunchHoleResponse { socket_addr: la.local_addr.clone(), - pk, + pk: self.get_pk(&la.version, la.id).await, relay_server: la.relay_server, ..Default::default() }; @@ -606,7 +630,7 @@ impl RendezvousServer { if let Some(socket) = socket { socket.send(&msg_out, addr_a).await?; } else { - self.send_to_tcp(&msg_out, addr_a).await; + self.send_to_tcp(msg_out, addr_a).await; } Ok(()) } @@ -617,11 +641,12 @@ impl RendezvousServer { addr: SocketAddr, ph: PunchHoleRequest, key: &str, + ws: bool, ) -> ResultType<(RendezvousMessage, Option<SocketAddr>)> { if !key.is_empty() && ph.licence_key != key { let mut msg_out = RendezvousMessage::new(); msg_out.set_punch_hole_response(PunchHoleResponse { - failure: punch_hole_response::Failure::LICENCE_MISMATCH.into(), + failure: punch_hole_response::Failure::LICENSE_MISMATCH.into(), ..Default::default() }); return Ok((msg_out, None)); @@ -633,7 +658,11 @@ impl RendezvousServer { // because punch hole won't work if in the same intranet, // all routers will drop such self-connections. if let Some(peer) = self.pm.get(&id).await { - if peer.last_reg_time.elapsed().as_millis() as i32 >= REG_TIMEOUT { + let (elapsed, peer_addr) = { + let r = peer.read().await; + (r.last_reg_time.elapsed().as_millis() as i32, r.socket_addr) + }; + if elapsed >= REG_TIMEOUT { let mut msg_out = RendezvousMessage::new(); msg_out.set_punch_hole_response(PunchHoleResponse { failure: punch_hole_response::Failure::OFFLINE.into(), @@ -642,34 +671,35 @@ impl RendezvousServer { return Ok((msg_out, None)); } let mut msg_out = RendezvousMessage::new(); - let same_intranet = match peer.socket_addr { - SocketAddr::V4(a) => match addr { - SocketAddr::V4(b) => a.ip() == b.ip(), - _ => false, - }, - SocketAddr::V6(a) => match addr { - SocketAddr::V6(b) => a.ip() == b.ip(), - _ => false, - }, - }; - let socket_addr = AddrMangle::encode(addr); - let relay_server = { - if self.relay_servers.is_empty() { - "".to_owned() - } else { - let i = unsafe { - ROTATION_RELAY_SERVER += 1; - ROTATION_RELAY_SERVER % self.relay_servers.len() - }; - self.relay_servers[i].clone() + if unsafe { ALWAYS_USE_RELAY } { + let relay_server = self.get_relay_server(addr.ip(), peer_addr.ip()); + if !relay_server.is_empty() { + msg_out.set_request_relay(RequestRelay { + relay_server, + ..Default::default() + }); + return Ok((msg_out, Some(peer_addr))); } - }; + } + let same_intranet = !ws + && match peer_addr { + SocketAddr::V4(a) => match addr { + SocketAddr::V4(b) => a.ip() == b.ip(), + _ => false, + }, + SocketAddr::V6(a) => match addr { + SocketAddr::V6(b) => a.ip() == b.ip(), + _ => false, + }, + }; + let socket_addr = AddrMangle::encode(addr); + let relay_server = self.get_relay_server(addr.ip(), peer_addr.ip()); if same_intranet { log::debug!( "Fetch local addr {:?} {:?} request from {:?}", id, - &peer.socket_addr, - &addr + peer_addr, + addr ); msg_out.set_fetch_local_addr(FetchLocalAddr { socket_addr, @@ -680,8 +710,8 @@ impl RendezvousServer { log::debug!( "Punch hole {:?} {:?} request from {:?}", id, - &peer.socket_addr, - &addr + peer_addr, + addr ); msg_out.set_punch_hole(PunchHole { socket_addr, @@ -690,7 +720,7 @@ impl RendezvousServer { ..Default::default() }); } - return Ok((msg_out, Some(peer.socket_addr))); + return Ok((msg_out, Some(peer_addr))); } else { let mut msg_out = RendezvousMessage::new(); msg_out.set_punch_hole_response(PunchHoleResponse { @@ -702,13 +732,25 @@ impl RendezvousServer { } #[inline] - async fn send_to_tcp(&mut self, msg: &RendezvousMessage, addr: SocketAddr) { - let tcp = self.tcp_punch.lock().unwrap().remove(&addr); - if let Some(mut tcp) = tcp { + async fn send_to_tcp(&mut self, msg: RendezvousMessage, addr: SocketAddr) { + let mut tcp = self.tcp_punch.lock().await.remove(&addr); + tokio::spawn(async move { + Self::send_to_sink(&mut tcp, msg).await; + }); + } + + #[inline] + async fn send_to_sink(sink: &mut Option<Sink>, msg: RendezvousMessage) { + if let Some(sink) = sink.as_mut() { if let Ok(bytes) = msg.write_to_bytes() { - tokio::spawn(async move { - allow_err!(tcp.send(Bytes::from(bytes)).await); - }); + match sink { + Sink::TcpStream(s) => { + allow_err!(s.send(Bytes::from(bytes)).await); + } + Sink::Ws(ws) => { + allow_err!(ws.send(tungstenite::Message::Binary(bytes)).await); + } + } } } } @@ -716,15 +758,11 @@ impl RendezvousServer { #[inline] async fn send_to_tcp_sync( &mut self, - msg: &RendezvousMessage, + msg: RendezvousMessage, addr: SocketAddr, ) -> ResultType<()> { - let tcp = self.tcp_punch.lock().unwrap().remove(&addr); - if let Some(mut tcp) = tcp { - if let Ok(bytes) = msg.write_to_bytes() { - tcp.send(Bytes::from(bytes)).await?; - } - } + let mut sink = self.tcp_punch.lock().await.remove(&addr); + Self::send_to_sink(&mut sink, msg).await; Ok(()) } @@ -734,12 +772,13 @@ impl RendezvousServer { addr: SocketAddr, ph: PunchHoleRequest, key: &str, + ws: bool, ) -> ResultType<()> { - let (msg, to_addr) = self.handle_punch_hole_request(addr, ph, key).await?; + let (msg, to_addr) = self.handle_punch_hole_request(addr, ph, key, ws).await?; if let Some(addr) = to_addr { - self.tx.send((msg, addr))?; + self.tx.send(Data::Msg(msg, addr))?; } else { - self.send_to_tcp_sync(&msg, addr).await?; + self.send_to_tcp_sync(msg, addr).await?; } Ok(()) } @@ -751,8 +790,8 @@ impl RendezvousServer { ph: PunchHoleRequest, key: &str, ) -> ResultType<()> { - let (msg, to_addr) = self.handle_punch_hole_request(addr, ph, key).await?; - self.tx.send(( + let (msg, to_addr) = self.handle_punch_hole_request(addr, ph, key, false).await?; + self.tx.send(Data::Msg( msg, match to_addr { Some(addr) => addr, @@ -761,16 +800,421 @@ impl RendezvousServer { ))?; Ok(()) } + + async fn check_ip_blocker(&self, ip: &str, id: &str) -> bool { + let mut lock = IP_BLOCKER.lock().await; + let now = Instant::now(); + if let Some(old) = lock.get_mut(ip) { + let counter = &mut old.0; + if counter.1.elapsed().as_secs() > IP_BLOCK_DUR { + counter.0 = 0; + } else if counter.0 > 30 { + return false; + } + counter.0 += 1; + counter.1 = now; + + let counter = &mut old.1; + let is_new = counter.0.get(id).is_none(); + if counter.1.elapsed().as_secs() > DAY_SECONDS { + counter.0.clear(); + } else if counter.0.len() > 300 { + return !is_new; + } + if is_new { + counter.0.insert(id.to_owned()); + } + counter.1 = now; + } else { + lock.insert(ip.to_owned(), ((0, now), (Default::default(), now))); + } + true + } + + fn parse_relay_servers(&mut self, relay_servers: &str) { + let rs = get_servers(relay_servers, "relay-servers"); + self.relay_servers0 = Arc::new(rs); + self.relay_servers = self.relay_servers0.clone(); + } + + fn get_relay_server(&self, pa: IpAddr, pb: IpAddr) -> String { + if self.relay_servers.is_empty() { + return "".to_owned(); + } else if self.relay_servers.len() == 1 { + return self.relay_servers[0].clone(); + } + let i = unsafe { + ROTATION_RELAY_SERVER += 1; + ROTATION_RELAY_SERVER % self.relay_servers.len() + }; + self.relay_servers[i].clone() + } + + async fn check_cmd(&self, cmd: &str) -> String { + let mut res = "".to_owned(); + let mut fds = cmd.trim().split(" "); + match fds.next() { + Some("h") => { + res = format!( + "{}\n{}\n{}\n{}\n{}\n{}\n", + "relay-servers(rs) <separated by ,>", + "reload-geo(rg)", + "ip-blocker(ib) [<ip>|<number>] [-]", + "ip-changes(ic) [<id>|<number>] [-]", + "always-use-relay(aur)", + "test-geo(tg) <ip1> <ip2>" + ) + } + Some("relay-servers" | "rs") => { + if let Some(rs) = fds.next() { + self.tx.send(Data::RelayServers0(rs.to_owned())).ok(); + } else { + for ip in self.relay_servers.iter() { + res += &format!("{}\n", ip); + } + } + } + Some("ip-blocker" | "ib") => { + let mut lock = IP_BLOCKER.lock().await; + lock.retain(|&_, (a, b)| { + a.1.elapsed().as_secs() <= IP_BLOCK_DUR + || b.1.elapsed().as_secs() <= DAY_SECONDS + }); + res = format!("{}\n", lock.len()); + let ip = fds.next(); + let mut start = ip.map(|x| x.parse::<i32>().unwrap_or(-1)).unwrap_or(-1); + if start < 0 { + if let Some(ip) = ip { + if let Some((a, b)) = lock.get(ip) { + res += &format!( + "{}/{}s {}/{}s\n", + a.0, + a.1.elapsed().as_secs(), + b.0.len(), + b.1.elapsed().as_secs() + ); + } + if fds.next() == Some("-") { + lock.remove(ip); + } + } else { + start = 0; + } + } + if start >= 0 { + let mut it = lock.iter(); + for i in 0..(start + 10) { + let x = it.next(); + if x.is_none() { + break; + } + if i < start { + continue; + } + if let Some((ip, (a, b))) = x { + res += &format!( + "{}: {}/{}s {}/{}s\n", + ip, + a.0, + a.1.elapsed().as_secs(), + b.0.len(), + b.1.elapsed().as_secs() + ); + } + } + } + } + Some("ip-changes" | "ic") => { + let mut lock = IP_CHANGES.lock().await; + lock.retain(|&_, v| v.0.elapsed().as_secs() < IP_CHANGE_DUR_X2 && v.1.len() > 1); + res = format!("{}\n", lock.len()); + let id = fds.next(); + let mut start = id.map(|x| x.parse::<i32>().unwrap_or(-1)).unwrap_or(-1); + if start < 0 || start > 10_000_000 { + if let Some(id) = id { + if let Some((tm, ips)) = lock.get(id) { + res += &format!("{}s {:?}\n", tm.elapsed().as_secs(), ips); + } + if fds.next() == Some("-") { + lock.remove(id); + } + } else { + start = 0; + } + } + if start >= 0 { + let mut it = lock.iter(); + for i in 0..(start + 10) { + let x = it.next(); + if x.is_none() { + break; + } + if i < start { + continue; + } + if let Some((id, (tm, ips))) = x { + res += &format!("{}: {}s {:?}\n", id, tm.elapsed().as_secs(), ips,); + } + } + } + } + Some("always-use-relay" | "aur") => { + if let Some(rs) = fds.next() { + if rs.to_uppercase() == "Y" { + unsafe { ALWAYS_USE_RELAY = true }; + } else { + unsafe { ALWAYS_USE_RELAY = false }; + } + self.tx.send(Data::RelayServers0(rs.to_owned())).ok(); + } else { + res += &format!("ALWAYS_USE_RELAY: {:?}\n", unsafe { ALWAYS_USE_RELAY }); + } + } + Some("test-geo" | "tg") => { + if let Some(rs) = fds.next() { + if let Ok(a) = rs.parse::<IpAddr>() { + if let Some(rs) = fds.next() { + if let Ok(b) = rs.parse::<IpAddr>() { + res = format!("{:?}", self.get_relay_server(a, b)); + } + } else { + res = format!("{:?}", self.get_relay_server(a, a)); + } + } + } + } + _ => {} + } + res + } + + async fn handle_listener2(&self, stream: TcpStream, addr: SocketAddr) { + if addr.ip().to_string() == "127.0.0.1" { + let rs = self.clone(); + tokio::spawn(async move { + let mut stream = stream; + let mut buffer = [0; 64]; + if let Ok(Ok(n)) = timeout(1000, stream.read(&mut buffer[..])).await { + if let Ok(data) = std::str::from_utf8(&buffer[..n]) { + let res = rs.check_cmd(data).await; + stream.write(res.as_bytes()).await.ok(); + } + } + }); + return; + } + let stream = FramedStream::from(stream, addr); + tokio::spawn(async move { + let mut stream = stream; + if let Some(Ok(bytes)) = stream.next_timeout(30_000).await { + if let Ok(msg_in) = RendezvousMessage::parse_from_bytes(&bytes) { + if let Some(rendezvous_message::Union::test_nat_request(_)) = msg_in.union { + let mut msg_out = RendezvousMessage::new(); + msg_out.set_test_nat_response(TestNatResponse { + port: addr.port() as _, + ..Default::default() + }); + stream.send(&msg_out).await.ok(); + } + } + } + }); + } + + async fn handle_listener( + &self, + stream: TcpStream, + addr: SocketAddr, + key: &str, + id_change_support: bool, + ws: bool, + ) { + log::debug!("Tcp connection from {:?}, ws: {}", addr, ws); + let mut rs = self.clone(); + let key = key.to_owned(); + tokio::spawn(async move { + allow_err!( + rs.handle_listener_inner(stream, addr, &key, id_change_support, ws) + .await + ); + }); + } + + #[inline] + async fn handle_listener_inner( + &mut self, + stream: TcpStream, + addr: SocketAddr, + key: &str, + id_change_support: bool, + ws: bool, + ) -> ResultType<()> { + let mut sink; + if ws { + let ws_stream = tokio_tungstenite::accept_async(stream).await?; + let (a, mut b) = ws_stream.split(); + sink = Some(Sink::Ws(a)); + while let Ok(Some(Ok(msg))) = timeout(30_000, b.next()).await { + match msg { + tungstenite::Message::Binary(bytes) => { + if !self + .handle_tcp(&bytes, &mut sink, addr, key, id_change_support, ws) + .await + { + break; + } + } + _ => {} + } + } + } else { + let (a, mut b) = Framed::new(stream, BytesCodec::new()).split(); + sink = Some(Sink::TcpStream(a)); + while let Ok(Some(Ok(bytes))) = timeout(30_000, b.next()).await { + if !self + .handle_tcp(&bytes, &mut sink, addr, key, id_change_support, ws) + .await + { + break; + } + } + } + if sink.is_none() { + self.tcp_punch.lock().await.remove(&addr); + } + log::debug!("Tcp connection from {:?} closed", addr); + Ok(()) + } + + #[inline] + async fn get_pk(&mut self, version: &str, id: String) -> Vec<u8> { + if version.is_empty() || self.sk.is_none() { + Vec::new() + } else { + match self.pm.get(&id).await { + Some(peer) => { + let pk = peer.read().await.pk.clone(); + sign::sign( + &hbb_common::message_proto::IdPk { + id, + pk, + ..Default::default() + } + .write_to_bytes() + .unwrap_or_default(), + &self.sk.as_ref().unwrap(), + ) + } + _ => Vec::new(), + } + } + } + + #[inline] + fn get_server_sk(&mut self, key: &str) -> String { + let mut key = key.to_owned(); + if let Ok(sk) = base64::decode(&key) { + if sk.len() == sign::SECRETKEYBYTES { + log::info!("The key is a crypto private key"); + key = base64::encode(&sk[(sign::SECRETKEYBYTES / 2)..]); + let mut tmp = [0u8; sign::SECRETKEYBYTES]; + tmp[..].copy_from_slice(&sk); + self.sk = Some(sign::SecretKey(tmp)); + } + } + + if key.is_empty() || key == "-" || key == "_" { + let (pk, sk) = crate::common::gen_sk(); + self.sk = sk; + if !key.is_empty() { + key = pk; + } else { + std::env::set_var("KEY_FOR_API", pk); + } + } + + if !key.is_empty() { + log::info!("Key: {}", key); + std::env::set_var("KEY_FOR_API", key.clone()); + } + key + } } -pub fn test_if_valid_server(host: &str, name: &str) -> ResultType<SocketAddr> { - let res = if host.contains(":") { - hbb_common::to_socket_addr(host) - } else { - hbb_common::to_socket_addr(&format!("{}:{}", host, 0)) - }; - if res.is_err() { - log::error!("Invalid {} {}: {:?}", name, host, res); +async fn check_relay_servers(rs0: Arc<RelayServers>, tx: Sender) { + let mut futs = Vec::new(); + let rs = Arc::new(Mutex::new(Vec::new())); + for x in rs0.iter() { + let mut host = x.to_owned(); + if !host.contains(":") { + host = format!("{}:{}", host, hbb_common::config::RELAY_PORT); + } + let rs = rs.clone(); + let x = x.clone(); + futs.push(tokio::spawn(async move { + if FramedStream::new(&host, "0.0.0.0:0", CHECK_RELAY_TIMEOUT) + .await + .is_ok() + { + rs.lock().await.push(x); + } + })); + } + join_all(futs).await; + log::debug!("check_relay_servers"); + let rs = std::mem::replace(&mut *rs.lock().await, Default::default()); + if !rs.is_empty() { + tx.send(Data::RelayServers(rs)).ok(); } - res +} + +// temp solution to solve udp socket failure +async fn test_hbbs(addr: SocketAddr) -> ResultType<()> { + let mut socket = FramedSocket::new("0.0.0.0:0").await?; + let mut msg_out = RendezvousMessage::new(); + msg_out.set_register_peer(RegisterPeer { + id: "(:test_hbbs:)".to_owned(), + ..Default::default() + }); + let mut last_time_recv = Instant::now(); + + let mut timer = interval(Duration::from_secs(1)); + loop { + tokio::select! { + _ = timer.tick() => { + if last_time_recv.elapsed().as_secs() > 12 { + log::error!("Timeout of test_hbbs"); + std::process::exit(1); + } + socket.send(&msg_out, addr).await?; + } + Some(Ok((bytes, _))) = socket.next() => { + if let Ok(msg_in) = RendezvousMessage::parse_from_bytes(&bytes) { + log::trace!("Recv {:?} of test_hbbs", msg_in); + last_time_recv = Instant::now(); + } + } + } + } +} + +#[inline] +fn distance(a: &(i32, i32), b: &(i32, i32)) -> i32 { + let dx = a.0 - b.0; + let dy = a.1 - b.1; + dx * dx + dy * dy +} + +#[inline] +async fn send_rk_res( + socket: &mut FramedSocket, + addr: SocketAddr, + res: register_pk_response::Result, +) -> ResultType<()> { + let mut msg_out = RendezvousMessage::new(); + msg_out.set_register_pk_response(RegisterPkResponse { + result: res.into(), + ..Default::default() + }); + socket.send(&msg_out, addr).await } diff --git a/src/sled_async.rs b/src/sled_async.rs deleted file mode 100644 index cabbe12..0000000 --- a/src/sled_async.rs +++ /dev/null @@ -1,101 +0,0 @@ -use hbb_common::{ - allow_err, log, - tokio::{self, sync::mpsc}, - ResultType, -}; -use rocksdb::DB; - -#[derive(Debug)] -enum Action { - Insert((String, Vec<u8>)), - Get((String, mpsc::Sender<Option<Vec<u8>>>)), - _Close, -} - -#[derive(Clone)] -pub struct SledAsync { - tx: Option<mpsc::UnboundedSender<Action>>, - path: String, -} - -impl SledAsync { - pub fn new(path: &str, run: bool) -> ResultType<Self> { - let mut res = Self { - tx: None, - path: path.to_owned(), - }; - if run { - res.run()?; - } - Ok(res) - } - - pub fn run(&mut self) -> ResultType<std::thread::JoinHandle<()>> { - let (tx, rx) = mpsc::unbounded_channel::<Action>(); - self.tx = Some(tx); - let db = DB::open_default(&self.path)?; - Ok(std::thread::spawn(move || { - Self::io_loop(db, rx); - log::debug!("Exit SledAsync loop"); - })) - } - - #[tokio::main(basic_scheduler)] - async fn io_loop(db: DB, rx: mpsc::UnboundedReceiver<Action>) { - let mut rx = rx; - while let Some(x) = rx.recv().await { - match x { - Action::Insert((key, value)) => { - allow_err!(db.put(&key, &value)); - } - Action::Get((key, sender)) => { - let mut sender = sender; - allow_err!( - sender - .send(if let Ok(v) = db.get(key) { v } else { None }) - .await - ); - } - Action::_Close => break, - } - } - } - - pub fn _close(self, j: std::thread::JoinHandle<()>) { - if let Some(tx) = &self.tx { - allow_err!(tx.send(Action::_Close)); - } - allow_err!(j.join()); - } - - pub async fn get(&mut self, key: String) -> Option<Vec<u8>> { - if let Some(tx) = &self.tx { - let (tx_once, mut rx) = mpsc::channel::<Option<Vec<u8>>>(1); - allow_err!(tx.send(Action::Get((key, tx_once)))); - if let Some(v) = rx.recv().await { - return v; - } - } - None - } - - #[inline] - pub fn deserialize<'a, T: serde::Deserialize<'a>>(v: &'a Option<Vec<u8>>) -> Option<T> { - if let Some(v) = v { - if let Ok(v) = std::str::from_utf8(v) { - if let Ok(v) = serde_json::from_str::<T>(&v) { - return Some(v); - } - } - } - None - } - - pub fn insert<T: serde::Serialize>(&mut self, key: String, v: T) { - if let Some(tx) = &self.tx { - if let Ok(v) = serde_json::to_vec(&v) { - allow_err!(tx.send(Action::Insert((key, v)))); - } - } - } -} diff --git a/src/version.rs b/src/version.rs new file mode 100644 index 0000000..75f232c --- /dev/null +++ b/src/version.rs @@ -0,0 +1 @@ +pub const VERSION: &str = "1.1.5";
\ No newline at end of file |