diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 92c31eb..0981e92 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -41,6 +41,8 @@ jobs: - name: Checkout uses: actions/checkout@v3 + with: + submodules: recursive - name: Install toolchain uses: actions-rs/toolchain@v1 @@ -80,6 +82,8 @@ jobs: - name: Checkout uses: actions/checkout@v3 + with: + submodules: recursive - name: Install toolchain uses: actions-rs/toolchain@v1 @@ -222,6 +226,8 @@ jobs: - name: Checkout uses: actions/checkout@v3 + with: + submodules: recursive - name: Download binaries uses: actions/download-artifact@v3 @@ -343,6 +349,8 @@ jobs: - name: Checkout uses: actions/checkout@v3 + with: + submodules: recursive - name: Download binaries uses: actions/download-artifact@v3 @@ -462,7 +470,9 @@ jobs: - name: Checkout uses: actions/checkout@v3 - + with: + submodules: recursive + - name: Set up QEMU uses: docker/setup-qemu-action@v2 diff --git a/.github/workflows/ghcr.yml b/.github/workflows/ghcr.yml index 5069e26..f141118 100644 --- a/.github/workflows/ghcr.yml +++ b/.github/workflows/ghcr.yml @@ -36,6 +36,8 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 + with: + submodules: recursive - name: Install Rust toolchain uses: dtolnay/rust-toolchain@v1 @@ -85,6 +87,8 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 + with: + submodules: recursive - name: Download binaries uses: actions/download-artifact@v4 @@ -216,6 +220,8 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 + with: + submodules: recursive - name: Download binaries uses: actions/download-artifact@v4 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d112bc2..ec2c5a9 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -20,6 +20,7 @@ jobs: profile: minimal toolchain: stable override: true + submodules: recursive - uses: Swatinem/rust-cache@v2 - uses: actions-rs/cargo@v1 with: @@ -34,6 +35,7 @@ jobs: profile: minimal toolchain: stable override: true + submodules: recursive - uses: Swatinem/rust-cache@v2 - uses: actions-rs/cargo@v1 with: @@ -50,6 +52,7 @@ jobs: toolchain: stable override: true components: rustfmt + submodules: recursive - uses: Swatinem/rust-cache@v2 - uses: actions-rs/cargo@v1 with: @@ -69,6 +72,7 @@ jobs: toolchain: stable override: true components: clippy + submodules: recursive - uses: Swatinem/rust-cache@v2 - uses: actions-rs/cargo@v1 with: diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..d80e69a --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "libs/hbb_common"] + path = libs/hbb_common + url = https://github.com/rustdesk/hbb_common diff --git a/Cargo.lock b/Cargo.lock index eb4d034..7123e54 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,21 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 + +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "ahash" @@ -15,13 +30,28 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "0.7.18" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "ansi_term" version = "0.12.1" @@ -43,6 +73,19 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" +[[package]] +name = "async-compression" +version = "0.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df895a515f70646414f4b45c0b79082783b80552b373a68283012928df56f522" +dependencies = [ + "flate2", + "futures-core", + "memchr", + "pin-project-lite", + "tokio", +] + [[package]] name = "async-speed-limit" version = "0.3.1" @@ -60,9 +103,9 @@ version = "0.1.53" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed6aa3524a2dfcf9fe180c51eae2b58738348d819517ceadf95789c51fff7600" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.93", + "quote 1.0.38", + "syn 1.0.93", ] [[package]] @@ -80,7 +123,7 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "hermit-abi", + "hermit-abi 0.1.19", "libc", "winapi", ] @@ -99,7 +142,7 @@ checksum = "00f1e8a972137fad81e2a1a60b86ff17ce0338f8017264e45a9723d0083c39a1" dependencies = [ "async-trait", "axum-core", - "bitflags", + "bitflags 1.3.2", "bytes", "futures-util", "headers", @@ -137,30 +180,86 @@ dependencies = [ "mime", ] +[[package]] +name = "backtrace" +version = "0.3.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets 0.52.6", +] + [[package]] name = "base64" version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + [[package]] name = "bcrypt" version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7e7c93a3fb23b2fdde989b2c9ec4dd153063ec81f408507f84c090cd91c6641" dependencies = [ - "base64", + "base64 0.13.0", "blowfish", "getrandom", "zeroize", ] +[[package]] +name = "bindgen" +version = "0.59.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bd2a9a458e8f4304c52c43ebb0cfbd520289f8379a52e329a38afda99bf8eb8" +dependencies = [ + "bitflags 1.3.2", + "cexpr", + "clang-sys", + "clap", + "env_logger 0.9.0", + "lazy_static", + "lazycell", + "log", + "peeking_take_while", + "proc-macro2 1.0.93", + "quote 1.0.38", + "regex", + "rustc-hash", + "shlex", + "which", +] + [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1be3f42a67d6d345ecd59f675f3f012d6974981560836e938c22b424b85ce1be" + [[package]] name = "block-buffer" version = "0.10.2" @@ -194,20 +293,37 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.2.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0b3de4a0c5e67e16066a0715723abd91edc2f9001d09c46e1dca929351e130e" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" dependencies = [ "serde", ] [[package]] name = "cc" -version = "1.0.73" +version = "1.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" +checksum = "c8293772165d9345bdaaa39b45b2109591e63fe5e6fbc23c6ff930a048aa310b" dependencies = [ "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom 7.1.1", ] [[package]] @@ -218,15 +334,16 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.19" +version = "0.4.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" dependencies = [ - "libc", - "num-integer", + "android-tzdata", + "iana-time-zone", + "js-sys", "num-traits", - "time 0.1.43", - "winapi", + "wasm-bindgen", + "windows-targets 0.52.6", ] [[package]] @@ -239,6 +356,17 @@ dependencies = [ "inout", ] +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", +] + [[package]] name = "clap" version = "2.34.0" @@ -247,13 +375,23 @@ checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" dependencies = [ "ansi_term", "atty", - "bitflags", + "bitflags 1.3.2", "strsim", "textwrap", "unicode-width", "vec_map", ] +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + [[package]] name = "config" version = "0.11.0" @@ -267,20 +405,20 @@ dependencies = [ [[package]] name = "confy" -version = "0.4.0" -source = "git+https://github.com/open-trade/confy#630cc28a396cb7d01eefdd9f3824486fe4d8554b" +version = "0.4.0-2" +source = "git+https://github.com/rustdesk-org/confy#83db9ec19a2f97e9718aef69e4fc5611bb382479" dependencies = [ "directories-next", "serde", "thiserror", - "toml", + "toml 0.5.9", ] [[package]] name = "core-foundation" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" dependencies = [ "core-foundation-sys", "libc", @@ -288,9 +426,9 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.3" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" @@ -316,6 +454,15 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d0165d2900ae6778e36e80bbc4da3b5eefccee9ba939761f9c2882a5d9af3ff" +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + [[package]] name = "crossbeam" version = "0.8.1" @@ -408,6 +555,16 @@ dependencies = [ "tokio", ] +[[package]] +name = "default_net" +version = "0.1.0" +source = "git+https://github.com/rustdesk-org/default_net#a831d47bcacb4615b394968287697924a8f62be1" +dependencies = [ + "anyhow", + "regex", + "winapi", +] + [[package]] name = "digest" version = "0.10.3" @@ -449,6 +606,29 @@ dependencies = [ "winapi", ] +[[package]] +name = "dlopen" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e80ad39f814a9abe68583cd50a2d45c8a67561c3361ab8da240587dda80937" +dependencies = [ + "dlopen_derive", + "lazy_static", + "libc", + "winapi", +] + +[[package]] +name = "dlopen_derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f236d9e1b1fbd81cea0f9cbdc8dcc7e8ebcd80e6659cd7cb2ad5f6c05946c581" +dependencies = [ + "libc", + "quote 0.6.13", + "syn 0.15.44", +] + [[package]] name = "dlv-list" version = "0.3.0" @@ -484,9 +664,18 @@ dependencies = [ [[package]] name = "either" -version = "1.6.1" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] [[package]] name = "env_logger" @@ -501,6 +690,25 @@ dependencies = [ "termcolor", ] +[[package]] +name = "env_logger" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" +dependencies = [ + "humantime", + "is-terminal", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + [[package]] name = "event-listener" version = "2.5.2" @@ -528,6 +736,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "flate2" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + [[package]] name = "flexi_logger" version = "0.22.3" @@ -544,7 +762,25 @@ dependencies = [ "regex", "rustversion", "thiserror", - "time 0.3.9", + "time", +] + +[[package]] +name = "flexi_logger" +version = "0.27.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469e584c031833564840fb0cdbce99bdfe946fd45480a188545e73a76f45461c" +dependencies = [ + "chrono", + "crossbeam-channel", + "crossbeam-queue", + "glob", + "is-terminal", + "lazy_static", + "log", + "nu-ansi-term", + "regex", + "thiserror", ] [[package]] @@ -565,6 +801,21 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + [[package]] name = "form_urlencoded" version = "1.0.1" @@ -640,9 +891,9 @@ version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.93", + "quote 1.0.38", + "syn 1.0.93", ] [[package]] @@ -681,15 +932,6 @@ dependencies = [ "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" @@ -702,21 +944,46 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.6" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", - "wasi 0.10.2+wasi-snapshot-preview1", + "wasi", ] +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + [[package]] name = "glob" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" +[[package]] +name = "h2" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap 2.7.0", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "hashbrown" version = "0.11.2" @@ -732,6 +999,12 @@ dependencies = [ "ahash", ] +[[package]] +name = "hashbrown" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" + [[package]] name = "hashlink" version = "0.8.0" @@ -746,33 +1019,49 @@ name = "hbb_common" version = "0.1.0" dependencies = [ "anyhow", + "backtrace", + "base64 0.22.1", "bytes", "chrono", "confy", + "default_net", "directories-next", "dirs-next", - "env_logger", + "dlopen", + "env_logger 0.10.2", "filetime", + "flexi_logger 0.27.4", "futures", "futures-util", + "httparse", "lazy_static", + "libc", "log", "mac_address", - "machine-uid", + "machine-uid 0.3.0", + "osascript", "protobuf", "protobuf-codegen", - "quinn", "rand", "regex", + "rustls-pki-types", + "rustls-platform-verifier", "serde", "serde_derive", "serde_json", + "sha2", "socket2 0.3.19", "sodiumoxide", + "sysinfo", + "thiserror", "tokio", - "tokio-socks", - "tokio-util 0.7.1", - "toml", + "tokio-native-tls", + "tokio-rustls 0.26.1", + "tokio-socks 0.5.2-1", + "tokio-util", + "toml 0.7.8", + "url", + "uuid", "winapi", "zstd", ] @@ -784,13 +1073,13 @@ dependencies = [ "async-speed-limit", "async-trait", "axum", - "base64", + "base64 0.13.0", "bcrypt", "chrono", "clap", "deadpool", "dns-lookup", - "flexi_logger", + "flexi_logger 0.22.3", "hbb_common", "headers", "http", @@ -799,11 +1088,12 @@ dependencies = [ "lazy_static", "local-ip-address", "mac_address", - "machine-uid", + "machine-uid 0.2.0", "minreq", "once_cell", "ping", "regex", + "reqwest", "rust-ini", "serde", "serde_derive", @@ -823,8 +1113,8 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cff78e5788be1e0ab65b04d306b2ed5092c815ec97ec70f4ebd5aee158aa55d" dependencies = [ - "base64", - "bitflags", + "base64 0.13.0", + "bitflags 1.3.2", "bytes", "headers-core", "http", @@ -860,6 +1150,12 @@ dependencies = [ "libc", ] +[[package]] +name = "hermit-abi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" + [[package]] name = "hex" version = "0.4.3" @@ -896,9 +1192,9 @@ checksum = "0bfe8eed0a9285ef776bb792479ea3834e8b94e13d615c2f66d03dd50a435a29" [[package]] name = "httparse" -version = "1.7.1" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "496ce29bb5a52785b44e0f7ca2847ae0bb839c9bd28f69acac9b99d461c0c04c" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] name = "httpdate" @@ -914,27 +1210,78 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.18" +version = "0.14.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b26ae0a80afebe130861d90abf98e3814a4f28a4c6ffeb5ab8ebb2be311e0ef2" +checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" dependencies = [ "bytes", "futures-channel", "futures-core", "futures-util", + "h2", "http", "http-body", "httparse", "httpdate", "itoa", "pin-project-lite", - "socket2 0.4.4", + "socket2 0.5.8", "tokio", "tower-service", "tracing", "want", ] +[[package]] +name = "hyper-rustls" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" +dependencies = [ + "futures-util", + "http", + "hyper", + "rustls 0.21.12", + "tokio", + "tokio-rustls 0.24.1", +] + +[[package]] +name = "hyper-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +dependencies = [ + "bytes", + "hyper", + "native-tls", + "tokio", + "tokio-native-tls", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core 0.52.0", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + [[package]] name = "idna" version = "0.2.3" @@ -956,6 +1303,16 @@ dependencies = [ "hashbrown 0.11.2", ] +[[package]] +name = "indexmap" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" +dependencies = [ + "equivalent", + "hashbrown 0.15.2", +] + [[package]] name = "inout" version = "0.1.3" @@ -974,6 +1331,12 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "ipnet" +version = "2.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" + [[package]] name = "ipnetwork" version = "0.20.0" @@ -983,6 +1346,17 @@ dependencies = [ "serde", ] +[[package]] +name = "is-terminal" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" +dependencies = [ + "hermit-abi 0.4.0", + "libc", + "windows-sys 0.52.0", +] + [[package]] name = "itertools" version = "0.10.3" @@ -999,20 +1373,41 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" [[package]] -name = "jobserver" -version = "0.1.24" +name = "jni" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa" +checksum = "c6df18c2e3db7e453d3c6ac5b3e9d5182664d28788126d39b91f2d1e22b017ec" +dependencies = [ + "cesu8", + "combine", + "jni-sys", + "log", + "thiserror", + "walkdir", +] + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + +[[package]] +name = "jobserver" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" dependencies = [ "libc", ] [[package]] name = "js-sys" -version = "0.3.57" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "671a26f820db17c2a2750743f1dd03bafd15b98c9f30c7c2628c024c05d73397" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" dependencies = [ + "once_cell", "wasm-bindgen", ] @@ -1022,9 +1417,9 @@ version = "8.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc9051c17f81bae79440afa041b3a278e1de71bfb96d32454b477fd4703ccb6f" dependencies = [ - "base64", + "base64 0.13.0", "pem", - "ring", + "ring 0.16.20", "serde", "serde_json", "simple_asn1", @@ -1036,6 +1431,12 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + [[package]] name = "lexical-core" version = "0.7.6" @@ -1043,7 +1444,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe" dependencies = [ "arrayvec", - "bitflags", + "bitflags 1.3.2", "cfg-if", "ryu", "static_assertions", @@ -1051,9 +1452,19 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.125" +version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5916d2ae698f6de9bfb891ad7a8d65c09d232dc58cc4ac433c7da3b2fd84bc2b" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" + +[[package]] +name = "libloading" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" +dependencies = [ + "cfg-if", + "windows-targets 0.52.6", +] [[package]] name = "libsodium-sys" @@ -1125,7 +1536,17 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f1595709b0a7386bcd56ba34d250d626e5503917d05d32cdccddcd68603e212" dependencies = [ - "winreg", + "winreg 0.6.2", +] + +[[package]] +name = "machine-uid" +version = "0.3.0" +source = "git+https://github.com/rustdesk-org/machine-uid#381ff579c1dc3a6c54db9dfec47c44bcb0246542" +dependencies = [ + "bindgen", + "cc", + "winreg 0.11.0", ] [[package]] @@ -1142,9 +1563,9 @@ checksum = "73cbba799671b762df5a175adf59ce145165747bb891505c43d09aefbbf38beb" [[package]] name = "memchr" -version = "2.5.0" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memoffset" @@ -1177,6 +1598,15 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" +[[package]] +name = "miniz_oxide" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8402cab7aefae129c6977bb0ff1b8fd9a04eb5b51efc50a70bea51cda0c7924" +dependencies = [ + "adler2", +] + [[package]] name = "minreq" version = "2.6.0" @@ -1189,36 +1619,30 @@ dependencies = [ [[package]] name = "mio" -version = "0.7.14" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ "libc", - "log", - "miow", - "ntapi", - "winapi", + "wasi", + "windows-sys 0.52.0", ] [[package]] -name = "mio" -version = "0.8.3" +name = "native-tls" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "713d550d9b44d89174e066b7a6217ae06234c10cb47819a88290d2b353c31799" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" dependencies = [ "libc", "log", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.36.1", -] - -[[package]] -name = "miow" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" -dependencies = [ - "winapi", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", ] [[package]] @@ -1240,10 +1664,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c168194d373b1e134786274020dae7fc5513d565ea2ebb9bc9ff17ffb69106d4" dependencies = [ "either", - "proc-macro2", - "quote", + "proc-macro2 1.0.93", + "quote 1.0.38", "serde", - "syn", + "syn 1.0.93", ] [[package]] @@ -1252,7 +1676,7 @@ version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cc", "cfg-if", "libc", @@ -1282,39 +1706,46 @@ dependencies = [ [[package]] name = "ntapi" -version = "0.3.7" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f" +checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" dependencies = [ "winapi", ] [[package]] -name = "num-bigint" -version = "0.4.3" +name = "nu-ansi-term" +version = "0.49.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" +checksum = "c073d3c1930d0751774acf49e66653acecb416c3a54c6ec095a9b11caddb5a68" +dependencies = [ + "windows-sys 0.48.0", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ - "autocfg", "num-integer", "num-traits", ] [[package]] name = "num-integer" -version = "0.1.45" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg", "num-traits", ] [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] @@ -1325,7 +1756,7 @@ version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" dependencies = [ - "hermit-abi", + "hermit-abi 0.1.19", "libc", ] @@ -1339,10 +1770,45 @@ dependencies = [ ] [[package]] -name = "once_cell" -version = "1.10.0" +name = "object" +version = "0.36.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[package]] +name = "openssl" +version = "0.10.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5" +dependencies = [ + "bitflags 2.7.0", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2 1.0.93", + "quote 1.0.38", + "syn 2.0.96", +] [[package]] name = "openssl-probe" @@ -1350,6 +1816,18 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" +[[package]] +name = "openssl-sys" +version = "0.9.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "ordered-multimap" version = "0.4.3" @@ -1360,6 +1838,17 @@ dependencies = [ "hashbrown 0.12.1", ] +[[package]] +name = "osascript" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38731fa859ef679f1aec66ca9562165926b442f298467f76f5990f431efe87dc" +dependencies = [ + "serde", + "serde_derive", + "serde_json", +] + [[package]] name = "parking_lot" version = "0.11.2" @@ -1414,13 +1903,19 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c520e05135d6e763148b6426a837e239041653ba7becd2e538c076c738025fc" +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" + [[package]] name = "pem" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e9a3b09a20e374558580a4914d3b7d89bd61b954a5a5e1dcbea98753addb1947" dependencies = [ - "base64", + "base64 0.13.0", ] [[package]] @@ -1431,29 +1926,29 @@ checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" [[package]] name = "pin-project" -version = "1.0.10" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58ad3879ad3baf4e44784bc6a718a8698867bb991f8ce24d1bcbe2cfb4c3a75e" +checksum = "1e2ec53ad785f4d35dac0adea7f7dc6f1bb277ad84a680c7afefeae05d1f5916" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.0.10" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb" +checksum = "d56a66c0c55993aa927429d0f8a0abfd74f084e4d9c192cffed01e418d83eefb" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.93", + "quote 1.0.38", + "syn 2.0.96", ] [[package]] name = "pin-project-lite" -version = "0.2.9" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "pin-utils" @@ -1486,18 +1981,27 @@ checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" [[package]] name = "proc-macro2" -version = "1.0.38" +version = "0.4.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9027b48e9d4c9175fa2218adf3557f91c1137021739951d4932f5f8268ac48aa" +checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" dependencies = [ - "unicode-xid", + "unicode-xid 0.1.0", +] + +[[package]] +name = "proc-macro2" +version = "1.0.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" +dependencies = [ + "unicode-ident", ] [[package]] name = "protobuf" -version = "3.1.0" +version = "3.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ee4a7d8b91800c8f167a6268d1a1026607368e1adc84e98fe044aeb905302f7" +checksum = "a3a7c64d9bf75b1b8d981124c14c179074e8caa7dfe7b6a12e6222ddcd0c8f72" dependencies = [ "bytes", "once_cell", @@ -1507,9 +2011,9 @@ dependencies = [ [[package]] name = "protobuf-codegen" -version = "3.1.0" +version = "3.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07b893e5e7d3395545d5244f8c0d33674025bd566b26c03bfda49b82c6dec45e" +checksum = "e26b833f144769a30e04b1db0146b2aaa53fd2fd83acf10a6b5f996606c18144" dependencies = [ "anyhow", "once_cell", @@ -1522,12 +2026,12 @@ dependencies = [ [[package]] name = "protobuf-parse" -version = "3.1.0" +version = "3.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b1447dd751c434cc1b415579837ebd0411ed7d67d465f38010da5d7cd33af4d" +checksum = "322330e133eab455718444b4e033ebfac7c6528972c784fcde28d2cc783c6257" dependencies = [ "anyhow", - "indexmap", + "indexmap 2.7.0", "log", "protobuf", "protobuf-support", @@ -1538,9 +2042,9 @@ dependencies = [ [[package]] name = "protobuf-support" -version = "3.1.0" +version = "3.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ca157fe12fc7ee2e315f2f735e27df41b3d97cdd70ea112824dac1ffb08ee1c" +checksum = "b088fd20b938a875ea00843b6faf48579462630015c3788d397ad6a786663252" dependencies = [ "thiserror", ] @@ -1561,66 +2065,21 @@ dependencies = [ ] [[package]] -name = "quinn" -version = "0.8.2" +name = "quote" +version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d147472bc9a09f13b06c044787b6683cdffa02e2865b7f0fb53d67c49ed2988e" +checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "fxhash", - "quinn-proto", - "quinn-udp", - "rustls", - "thiserror", - "tokio", - "tracing", - "webpki", -] - -[[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", - "rustls-native-certs", - "rustls-pemfile 0.2.1", - "slab", - "thiserror", - "tinyvec", - "tracing", - "webpki", -] - -[[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", + "proc-macro2 0.4.30", ] [[package]] name = "quote" -version = "1.0.18" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" dependencies = [ - "proc-macro2", + "proc-macro2 1.0.93", ] [[package]] @@ -1653,13 +2112,33 @@ dependencies = [ "getrandom", ] +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + [[package]] name = "redox_syscall" version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -1675,9 +2154,21 @@ dependencies = [ [[package]] name = "regex" -version = "1.5.5" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -1686,9 +2177,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.25" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "remove_dir_all" @@ -1699,6 +2190,53 @@ dependencies = [ "winapi", ] +[[package]] +name = "reqwest" +version = "0.11.23" +source = "git+https://github.com/rustdesk-org/reqwest#9cb758c9fb2f4edc62eb790acfd45a6a3da21ed3" +dependencies = [ + "async-compression", + "base64 0.21.7", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-rustls", + "hyper-tls", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls 0.21.12", + "rustls-native-certs 0.6.2", + "rustls-pemfile 1.0.0", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "system-configuration", + "tokio", + "tokio-native-tls", + "tokio-rustls 0.24.1", + "tokio-socks 0.5.2", + "tokio-util", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "webpki-roots 0.25.4", + "winreg 0.50.0", +] + [[package]] name = "ring" version = "0.16.20" @@ -1709,11 +2247,25 @@ dependencies = [ "libc", "once_cell", "spin 0.5.2", - "untrusted", + "untrusted 0.7.1", "web-sys", "winapi", ] +[[package]] +name = "ring" +version = "0.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9babe80d5c16becf6594aa32ad2be8fe08498e7ae60b77de8df700e67f191d7e" +dependencies = [ + "cc", + "getrandom", + "libc", + "spin 0.9.3", + "untrusted 0.9.0", + "windows-sys 0.48.0", +] + [[package]] name = "rust-ini" version = "0.18.0" @@ -1724,6 +2276,18 @@ dependencies = [ "ordered-multimap", ] +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rustls" version = "0.20.4" @@ -1731,11 +2295,38 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fbfeb8d0ddb84706bc597a5574ab8912817c52a397f819e5b614e2265206921" dependencies = [ "log", - "ring", + "ring 0.16.20", "sct", "webpki", ] +[[package]] +name = "rustls" +version = "0.21.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" +dependencies = [ + "log", + "ring 0.17.3", + "rustls-webpki 0.101.7", + "sct", +] + +[[package]] +name = "rustls" +version = "0.23.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f287924602bf649d949c63dc8ac8b235fa5387d394020705b80c4eb597ce5b8" +dependencies = [ + "log", + "once_cell", + "ring 0.17.3", + "rustls-pki-types", + "rustls-webpki 0.102.8", + "subtle", + "zeroize", +] + [[package]] name = "rustls-native-certs" version = "0.6.2" @@ -1749,12 +2340,16 @@ dependencies = [ ] [[package]] -name = "rustls-pemfile" -version = "0.2.1" +name = "rustls-native-certs" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eebeaeb360c87bfb72e84abdb3447159c0eaececf1bef2aecd65a8be949d1c9" +checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5" dependencies = [ - "base64", + "openssl-probe", + "rustls-pemfile 2.2.0", + "rustls-pki-types", + "schannel", + "security-framework", ] [[package]] @@ -1763,7 +2358,70 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7522c9de787ff061458fe9a829dc790a3f5b22dc571694fc5883f448b94d9a9" dependencies = [ - "base64", + "base64 0.13.0", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2bf47e6ff922db3825eb750c4e2ff784c6ff8fb9e13046ef6a1d1c5401b0b37" + +[[package]] +name = "rustls-platform-verifier" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afbb878bdfdf63a336a5e63561b1835e7a8c91524f51621db870169eac84b490" +dependencies = [ + "core-foundation", + "core-foundation-sys", + "jni", + "log", + "once_cell", + "rustls 0.23.21", + "rustls-native-certs 0.7.3", + "rustls-platform-verifier-android", + "rustls-webpki 0.102.8", + "security-framework", + "security-framework-sys", + "webpki-roots 0.26.7", + "winapi", +] + +[[package]] +name = "rustls-platform-verifier-android" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" + +[[package]] +name = "rustls-webpki" +version = "0.101.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +dependencies = [ + "ring 0.17.3", + "untrusted 0.9.0", +] + +[[package]] +name = "rustls-webpki" +version = "0.102.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" +dependencies = [ + "ring 0.17.3", + "rustls-pki-types", + "untrusted 0.9.0", ] [[package]] @@ -1789,12 +2447,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.19" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" +checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" dependencies = [ - "lazy_static", - "winapi", + "windows-sys 0.59.0", ] [[package]] @@ -1809,28 +2466,29 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" dependencies = [ - "ring", - "untrusted", + "ring 0.16.20", + "untrusted 0.7.1", ] [[package]] name = "security-framework" -version = "2.6.1" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dc14f172faf8a0194a3aded622712b0de276821addc574fa54fc0a1167e10dc" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags", + "bitflags 2.7.0", "core-foundation", "core-foundation-sys", "libc", + "num-bigint", "security-framework-sys", ] [[package]] name = "security-framework-sys" -version = "2.6.1" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556" +checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" dependencies = [ "core-foundation-sys", "libc", @@ -1838,22 +2496,22 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.137" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.137" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.93", + "quote 1.0.38", + "syn 2.0.96", ] [[package]] @@ -1867,6 +2525,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_spanned" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +dependencies = [ + "serde", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -1901,6 +2568,12 @@ dependencies = [ "digest", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "signal-hook-registry" version = "1.4.0" @@ -1925,7 +2598,7 @@ dependencies = [ "num-bigint", "num-traits", "thiserror", - "time 0.3.9", + "time", ] [[package]] @@ -1961,6 +2634,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "socket2" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + [[package]] name = "sodiumoxide" version = "0.2.7" @@ -2017,7 +2700,7 @@ checksum = "6b69bf218860335ddda60d6ce85ee39f6cf6e5630e300e19757d1de15886a093" dependencies = [ "ahash", "atoi", - "bitflags", + "bitflags 1.3.2", "byteorder", "bytes", "chrono", @@ -2033,7 +2716,7 @@ dependencies = [ "futures-util", "hashlink", "hex", - "indexmap", + "indexmap 1.8.1", "itoa", "libc", "libsqlite3-sys", @@ -2042,7 +2725,7 @@ dependencies = [ "once_cell", "paste", "percent-encoding", - "rustls", + "rustls 0.20.4", "rustls-pemfile 1.0.0", "serde", "serde_json", @@ -2054,7 +2737,7 @@ dependencies = [ "thiserror", "tokio-stream", "url", - "webpki-roots", + "webpki-roots 0.22.4", ] [[package]] @@ -2067,13 +2750,13 @@ dependencies = [ "either", "heck", "once_cell", - "proc-macro2", - "quote", + "proc-macro2 1.0.93", + "quote 1.0.38", "serde_json", "sha2", "sqlx-core", "sqlx-rt", - "syn", + "syn 1.0.93", "url", ] @@ -2085,7 +2768,7 @@ checksum = "874e93a365a598dc3dadb197565952cb143ae4aa716f7bcc933a8d836f6bf89f" dependencies = [ "once_cell", "tokio", - "tokio-rustls", + "tokio-rustls 0.23.4", ] [[package]] @@ -2110,22 +2793,85 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "0.15.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" +dependencies = [ + "proc-macro2 0.4.30", + "quote 0.6.13", + "unicode-xid 0.1.0", +] + [[package]] name = "syn" version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04066589568b72ec65f42d65a1a52436e954b168773148893c020269563decf2" dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", + "proc-macro2 1.0.93", + "quote 1.0.38", + "unicode-xid 0.2.3", +] + +[[package]] +name = "syn" +version = "2.0.96" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" +dependencies = [ + "proc-macro2 1.0.93", + "quote 1.0.38", + "unicode-ident", ] [[package]] name = "sync_wrapper" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20518fe4a4c9acf048008599e464deb21beeae3d3578418951a189c235a7a9a8" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + +[[package]] +name = "sysinfo" +version = "0.29.10" +source = "git+https://github.com/rustdesk-org/sysinfo?branch=rlim_max#90b1705d909a4902dbbbdea37ee64db17841077d" +dependencies = [ + "cfg-if", + "core-foundation-sys", + "libc", + "ntapi", + "once_cell", + "rayon", + "windows", +] + +[[package]] +name = "system-configuration" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", +] [[package]] name = "tempfile" @@ -2174,19 +2920,9 @@ 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", + "proc-macro2 1.0.93", + "quote 1.0.38", + "syn 1.0.93", ] [[package]] @@ -2225,34 +2961,41 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.20.0" +version = "1.43.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57aec3cfa4c296db7255446efb4928a6be304b431a806216105542a67b6ca82e" +checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e" dependencies = [ - "autocfg", + "backtrace", "bytes", "libc", - "memchr", - "mio 0.8.3", - "num_cpus", - "once_cell", + "mio", "parking_lot 0.12.0", "pin-project-lite", "signal-hook-registry", - "socket2 0.4.4", + "socket2 0.5.8", "tokio-macros", - "winapi", + "windows-sys 0.52.0", ] [[package]] name = "tokio-macros" -version = "1.7.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.93", + "quote 1.0.38", + "syn 2.0.96", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", ] [[package]] @@ -2261,15 +3004,35 @@ version = "0.23.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" dependencies = [ - "rustls", + "rustls 0.20.4", "tokio", "webpki", ] +[[package]] +name = "tokio-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls 0.21.12", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f6d0975eaace0cf0fcadee4e4aaa5da15b5c079146f2cffb67c113be122bf37" +dependencies = [ + "rustls 0.23.21", + "tokio", +] + [[package]] name = "tokio-socks" -version = "0.5.1" -source = "git+https://github.com/open-trade/tokio-socks#3de8300fbce37e2cdaef042e016aa95058d007cf" +version = "0.5.2-1" +source = "git+https://github.com/rustdesk-org/tokio-socks#94e97c6d7c93b0bcbfa54f2dc397c1da0a6e43d3" dependencies = [ "bytes", "either", @@ -2279,7 +3042,19 @@ dependencies = [ "pin-project", "thiserror", "tokio", - "tokio-util 0.6.9", + "tokio-util", +] + +[[package]] +name = "tokio-socks" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d4770b8024672c1101b3f6733eab95b18007dbe0847a8afe341fcf79e06043f" +dependencies = [ + "either", + "futures-util", + "thiserror", + "tokio", ] [[package]] @@ -2305,20 +3080,6 @@ dependencies = [ "tungstenite", ] -[[package]] -name = "tokio-util" -version = "0.6.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e99e1983e5d376cd8eb4b66604d2e99e79f5bd988c3055891dcd8c9e2604cc0" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "log", - "pin-project-lite", - "tokio", -] - [[package]] name = "tokio-util" version = "0.7.1" @@ -2345,6 +3106,40 @@ dependencies = [ "serde", ] +[[package]] +name = "toml" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap 2.7.0", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + [[package]] name = "tower" version = "0.4.12" @@ -2356,7 +3151,7 @@ dependencies = [ "pin-project", "pin-project-lite", "tokio", - "tokio-util 0.7.1", + "tokio-util", "tower-layer", "tower-service", "tracing", @@ -2368,7 +3163,7 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d342c6d58709c0a6d48d48dabbb62d4ef955cf5f0f3bbfd845838e7ae88dbae" dependencies = [ - "bitflags", + "bitflags 1.3.2", "bytes", "futures-core", "futures-util", @@ -2381,7 +3176,7 @@ dependencies = [ "percent-encoding", "pin-project-lite", "tokio", - "tokio-util 0.7.1", + "tokio-util", "tower", "tower-layer", "tower-service", @@ -2402,11 +3197,10 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" [[package]] name = "tracing" -version = "0.1.34" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d0ecdcb44a79f0fe9844f0c4f33a342cbcbb5117de8001e6ba0dc2351327d09" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ - "cfg-if", "log", "pin-project-lite", "tracing-attributes", @@ -2415,22 +3209,22 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.21" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc6b8ad3567499f98a1db7a752b07a7c8c7c7c34c332ec00effb2b0027974b7c" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.93", + "quote 1.0.38", + "syn 2.0.96", ] [[package]] name = "tracing-core" -version = "0.1.26" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f54c8ca710e81886d498c2fd3331b56c93aa248d49de2222ad2742247c60072f" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ - "lazy_static", + "once_cell", ] [[package]] @@ -2445,7 +3239,7 @@ version = "0.17.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d96a2dea40e7570482f28eb57afbe42d97551905da6a9400acc5c328d24004f5" dependencies = [ - "base64", + "base64 0.13.0", "byteorder", "bytes", "http", @@ -2479,6 +3273,12 @@ version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" +[[package]] +name = "unicode-ident" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" + [[package]] name = "unicode-normalization" version = "0.1.19" @@ -2500,6 +3300,12 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" + [[package]] name = "unicode-xid" version = "0.2.3" @@ -2518,6 +3324,12 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "url" version = "2.2.2" @@ -2538,9 +3350,9 @@ checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" [[package]] name = "uuid" -version = "1.1.2" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd6469f4314d5f1ffec476e05f17cc9a78bc7a27a6a857842170bdf8d6f98d2f" +checksum = "744018581f9a3454a9e15beb8a33b017183f1e7c0cd170232a2d1453b23a51c4" dependencies = [ "getrandom", ] @@ -2584,12 +3396,6 @@ dependencies = [ "try-lock", ] -[[package]] -name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -2598,63 +3404,80 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.80" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27370197c907c55e3f1a9fbe26f44e937fe6451368324e009cba39e139dc08ad" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ "cfg-if", + "once_cell", + "rustversion", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.80" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53e04185bfa3a779273da532f5025e33398409573f348985af9a1cbf3774d3f4" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" dependencies = [ "bumpalo", - "lazy_static", "log", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.93", + "quote 1.0.38", + "syn 2.0.96", "wasm-bindgen-shared", ] [[package]] -name = "wasm-bindgen-macro" -version = "0.2.80" +name = "wasm-bindgen-futures" +version = "0.4.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17cae7ff784d7e83a2fe7611cfe766ecf034111b49deb850a3dc7699c08251f5" +checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" dependencies = [ - "quote", + "cfg-if", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +dependencies = [ + "quote 1.0.38", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.80" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.93", + "quote 1.0.38", + "syn 2.0.96", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.80" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d554b7f530dee5964d9a9468d95c1f8b8acae4f282807e7d27d4b03099a46744" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] [[package]] name = "web-sys" -version = "0.3.57" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b17e741662c70c8bd24ac5c5b18de314a2c26c32bf8346ee1e6f53de919c283" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" dependencies = [ "js-sys", "wasm-bindgen", @@ -2666,8 +3489,8 @@ version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" dependencies = [ - "ring", - "untrusted", + "ring 0.16.20", + "untrusted 0.7.1", ] [[package]] @@ -2679,6 +3502,21 @@ dependencies = [ "webpki", ] +[[package]] +name = "webpki-roots" +version = "0.25.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" + +[[package]] +name = "webpki-roots" +version = "0.26.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d642ff16b7e79272ae451b7322067cdc17cadf68c23264be9d94a32319efe7e" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "which" version = "4.2.5" @@ -2731,6 +3569,34 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.51.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca229916c5ee38c2f2bc1e9d8f04df975b4bd93f9955dc69fabb5d91270045c9" +dependencies = [ + "windows-core 0.51.1", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-core" +version = "0.51.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.6", +] + [[package]] name = "windows-sys" version = "0.36.1" @@ -2750,29 +3616,69 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", ] [[package]] name = "windows-targets" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc 0.48.0", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -2782,9 +3688,15 @@ checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" [[package]] name = "windows_aarch64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -2794,9 +3706,21 @@ checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" [[package]] name = "windows_i686_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -2806,9 +3730,15 @@ checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" [[package]] name = "windows_i686_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -2818,15 +3748,27 @@ checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" [[package]] name = "windows_x86_64_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -2836,9 +3778,24 @@ checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" [[package]] name = "windows_x86_64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] [[package]] name = "winreg" @@ -2850,36 +3807,55 @@ dependencies = [ ] [[package]] -name = "zeroize" -version = "1.5.5" +name = "winreg" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94693807d016b2f2d2e14420eb3bfcca689311ff775dcf113d74ea624b7cdf07" +checksum = "76a1a57ff50e9b408431e8f97d5456f2807f8eb2a2cd79b06068fc87f8ecf189" +dependencies = [ + "cfg-if", + "winapi", +] + +[[package]] +name = "winreg" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" [[package]] name = "zstd" -version = "0.9.2+zstd.1.5.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2390ea1bf6c038c39674f22d95f0564725fc06034a47129179810b2fc58caa54" +checksum = "fcf2b778a664581e31e389454a7072dab1647606d44f7feea22cd5abb9c9f3f9" dependencies = [ "zstd-safe", ] [[package]] name = "zstd-safe" -version = "4.1.3+zstd.1.5.1" +version = "7.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e99d81b99fb3c2c2c794e3fe56c305c63d5173a16a46b5850b07c935ffc7db79" +checksum = "54a3ab4db68cea366acc5c897c7b4d4d1b8994a9cd6e6f841f8964566a419059" dependencies = [ - "libc", "zstd-sys", ] [[package]] name = "zstd-sys" -version = "1.6.2+zstd.1.5.1" +version = "2.0.13+zstd.1.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2daf2f248d9ea44454bfcb2516534e8b8ad2fc91bf818a1885495fc42bc8ac9f" +checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" dependencies = [ "cc", - "libc", + "pkg-config", ] diff --git a/Cargo.toml b/Cargo.toml index c8ba248..0d677df 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -52,6 +52,13 @@ local-ip-address = "0.5.1" dns-lookup = "1.0.8" ping = "0.4.0" +[target.'cfg(any(target_os = "macos", target_os = "windows"))'.dependencies] +# https://github.com/rustdesk/rustdesk-server-pro/issues/189, using native-tls for better tls support +reqwest = { git = "https://github.com/rustdesk-org/reqwest", features = ["blocking", "socks", "json", "native-tls", "gzip"], default-features=false } + +[target.'cfg(not(any(target_os = "macos", target_os = "windows")))'.dependencies] +reqwest = { git = "https://github.com/rustdesk-org/reqwest", features = ["blocking", "socks", "json", "rustls-tls", "rustls-tls-native-roots", "gzip"], default-features=false } + [build-dependencies] hbb_common = { path = "libs/hbb_common" } diff --git a/libs/hbb_common b/libs/hbb_common new file mode 160000 index 0000000..49c6b24 --- /dev/null +++ b/libs/hbb_common @@ -0,0 +1 @@ +Subproject commit 49c6b24a7a8c39d4448e07b743007ef1a3febd43 diff --git a/libs/hbb_common/.gitignore b/libs/hbb_common/.gitignore deleted file mode 100644 index b1cf151..0000000 --- a/libs/hbb_common/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -/target -**/*.rs.bk -Cargo.lock -src/protos/ diff --git a/libs/hbb_common/Cargo.toml b/libs/hbb_common/Cargo.toml deleted file mode 100644 index 59f0896..0000000 --- a/libs/hbb_common/Cargo.toml +++ /dev/null @@ -1,51 +0,0 @@ -[package] -name = "hbb_common" -version = "0.1.0" -authors = ["open-trade "] -edition = "2018" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -protobuf = { version = "3.1", features = ["with-bytes"] } -tokio = { version = "1.20", features = ["full"] } -tokio-util = { version = "0.7", features = ["full"] } -futures = "0.3" -bytes = { version = "1.2", features = ["serde"] } -log = "0.4" -env_logger = "0.9" -socket2 = { version = "0.3", features = ["reuseport"] } -zstd = "0.9" -quinn = {version = "0.8", optional = true } -anyhow = "1.0" -futures-util = "0.3" -directories-next = "2.0" -rand = "0.8" -serde_derive = "1.0" -serde = "1.0" -lazy_static = "1.4" -confy = { git = "https://github.com/open-trade/confy" } -dirs-next = "2.0" -filetime = "0.2" -sodiumoxide = "0.2" -regex = "1.4" -tokio-socks = { git = "https://github.com/open-trade/tokio-socks" } -chrono = "0.4" - -[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies] -mac_address = "1.1" -machine-uid = "0.2" - -[features] -quic = [] -flatpak = [] - -[build-dependencies] -protobuf-codegen = { version = "3.1" } - -[target.'cfg(target_os = "windows")'.dependencies] -winapi = { version = "0.3", features = ["winuser"] } - -[dev-dependencies] -toml = "0.5" -serde_json = "1.0" diff --git a/libs/hbb_common/build.rs b/libs/hbb_common/build.rs deleted file mode 100644 index 5ebc3a2..0000000 --- a/libs/hbb_common/build.rs +++ /dev/null @@ -1,14 +0,0 @@ -fn main() { - let out_dir = format!("{}/protos", std::env::var("OUT_DIR").unwrap()); - - std::fs::create_dir_all(&out_dir).unwrap(); - - protobuf_codegen::Codegen::new() - .pure() - .out_dir(out_dir) - .inputs(["protos/rendezvous.proto", "protos/message.proto"]) - .include("protos") - .customize(protobuf_codegen::Customize::default().tokio_bytes(true)) - .run() - .expect("Codegen failed."); -} diff --git a/libs/hbb_common/protos/message.proto b/libs/hbb_common/protos/message.proto deleted file mode 100644 index ed27063..0000000 --- a/libs/hbb_common/protos/message.proto +++ /dev/null @@ -1,638 +0,0 @@ -syntax = "proto3"; -package hbb; - -message EncodedVideoFrame { - bytes data = 1; - bool key = 2; - int64 pts = 3; -} - -message EncodedVideoFrames { repeated EncodedVideoFrame frames = 1; } - -message RGB { bool compress = 1; } - -// planes data send directly in binary for better use arraybuffer on web -message YUV { - bool compress = 1; - int32 stride = 2; -} - -message VideoFrame { - oneof union { - EncodedVideoFrames vp9s = 6; - RGB rgb = 7; - YUV yuv = 8; - EncodedVideoFrames h264s = 10; - EncodedVideoFrames h265s = 11; - } - int64 timestamp = 9; -} - -message IdPk { - string id = 1; - bytes pk = 2; -} - -message DisplayInfo { - sint32 x = 1; - sint32 y = 2; - int32 width = 3; - int32 height = 4; - string name = 5; - bool online = 6; - bool cursor_embedded = 7; -} - -message PortForward { - string host = 1; - int32 port = 2; -} - -message FileTransfer { - string dir = 1; - bool show_hidden = 2; -} - -message LoginRequest { - string username = 1; - bytes password = 2; - string my_id = 4; - string my_name = 5; - OptionMessage option = 6; - oneof union { - FileTransfer file_transfer = 7; - PortForward port_forward = 8; - } - bool video_ack_required = 9; - uint64 session_id = 10; - string version = 11; -} - -message ChatMessage { string text = 1; } - -message Features { - bool privacy_mode = 1; -} - -message SupportedEncoding { - bool h264 = 1; - bool h265 = 2; -} - -message PeerInfo { - string username = 1; - string hostname = 2; - string platform = 3; - repeated DisplayInfo displays = 4; - int32 current_display = 5; - bool sas_enabled = 6; - string version = 7; - int32 conn_id = 8; - Features features = 9; - SupportedEncoding encoding = 10; -} - -message LoginResponse { - oneof union { - string error = 1; - PeerInfo peer_info = 2; - } -} - -message MouseEvent { - int32 mask = 1; - sint32 x = 2; - sint32 y = 3; - repeated ControlKey modifiers = 4; -} - -enum KeyboardMode{ - Legacy = 0; - Map = 1; - Translate = 2; - Auto = 3; -} - -enum ControlKey { - Unknown = 0; - Alt = 1; - Backspace = 2; - CapsLock = 3; - Control = 4; - Delete = 5; - DownArrow = 6; - End = 7; - Escape = 8; - F1 = 9; - F10 = 10; - F11 = 11; - F12 = 12; - F2 = 13; - F3 = 14; - F4 = 15; - F5 = 16; - F6 = 17; - F7 = 18; - F8 = 19; - F9 = 20; - Home = 21; - LeftArrow = 22; - /// meta key (also known as "windows"; "super"; and "command") - Meta = 23; - /// option key on macOS (alt key on Linux and Windows) - Option = 24; // deprecated, use Alt instead - PageDown = 25; - PageUp = 26; - Return = 27; - RightArrow = 28; - Shift = 29; - Space = 30; - Tab = 31; - UpArrow = 32; - Numpad0 = 33; - Numpad1 = 34; - Numpad2 = 35; - Numpad3 = 36; - Numpad4 = 37; - Numpad5 = 38; - Numpad6 = 39; - Numpad7 = 40; - Numpad8 = 41; - Numpad9 = 42; - Cancel = 43; - Clear = 44; - Menu = 45; // deprecated, use Alt instead - Pause = 46; - Kana = 47; - Hangul = 48; - Junja = 49; - Final = 50; - Hanja = 51; - Kanji = 52; - Convert = 53; - Select = 54; - Print = 55; - Execute = 56; - Snapshot = 57; - Insert = 58; - Help = 59; - Sleep = 60; - Separator = 61; - Scroll = 62; - NumLock = 63; - RWin = 64; - Apps = 65; - Multiply = 66; - Add = 67; - Subtract = 68; - Decimal = 69; - Divide = 70; - Equals = 71; - NumpadEnter = 72; - RShift = 73; - RControl = 74; - RAlt = 75; - CtrlAltDel = 100; - LockScreen = 101; -} - -message KeyEvent { - bool down = 1; - bool press = 2; - oneof union { - ControlKey control_key = 3; - uint32 chr = 4; - uint32 unicode = 5; - string seq = 6; - } - repeated ControlKey modifiers = 8; - KeyboardMode mode = 9; -} - -message CursorData { - uint64 id = 1; - sint32 hotx = 2; - sint32 hoty = 3; - int32 width = 4; - int32 height = 5; - bytes colors = 6; -} - -message CursorPosition { - sint32 x = 1; - sint32 y = 2; -} - -message Hash { - string salt = 1; - string challenge = 2; -} - -message Clipboard { - bool compress = 1; - bytes content = 2; -} - -enum FileType { - Dir = 0; - DirLink = 2; - DirDrive = 3; - File = 4; - FileLink = 5; -} - -message FileEntry { - FileType entry_type = 1; - string name = 2; - bool is_hidden = 3; - uint64 size = 4; - uint64 modified_time = 5; -} - -message FileDirectory { - int32 id = 1; - string path = 2; - repeated FileEntry entries = 3; -} - -message ReadDir { - string path = 1; - bool include_hidden = 2; -} - -message ReadAllFiles { - int32 id = 1; - string path = 2; - bool include_hidden = 3; -} - -message FileAction { - oneof union { - ReadDir read_dir = 1; - FileTransferSendRequest send = 2; - FileTransferReceiveRequest receive = 3; - FileDirCreate create = 4; - FileRemoveDir remove_dir = 5; - FileRemoveFile remove_file = 6; - ReadAllFiles all_files = 7; - FileTransferCancel cancel = 8; - FileTransferSendConfirmRequest send_confirm = 9; - } -} - -message FileTransferCancel { int32 id = 1; } - -message FileResponse { - oneof union { - FileDirectory dir = 1; - FileTransferBlock block = 2; - FileTransferError error = 3; - FileTransferDone done = 4; - FileTransferDigest digest = 5; - } -} - -message FileTransferDigest { - int32 id = 1; - sint32 file_num = 2; - uint64 last_modified = 3; - uint64 file_size = 4; - bool is_upload = 5; -} - -message FileTransferBlock { - int32 id = 1; - sint32 file_num = 2; - bytes data = 3; - bool compressed = 4; - uint32 blk_id = 5; -} - -message FileTransferError { - int32 id = 1; - string error = 2; - sint32 file_num = 3; -} - -message FileTransferSendRequest { - int32 id = 1; - string path = 2; - bool include_hidden = 3; - int32 file_num = 4; -} - -message FileTransferSendConfirmRequest { - int32 id = 1; - sint32 file_num = 2; - oneof union { - bool skip = 3; - uint32 offset_blk = 4; - } -} - -message FileTransferDone { - int32 id = 1; - sint32 file_num = 2; -} - -message FileTransferReceiveRequest { - int32 id = 1; - string path = 2; // path written to - repeated FileEntry files = 3; - int32 file_num = 4; -} - -message FileRemoveDir { - int32 id = 1; - string path = 2; - bool recursive = 3; -} - -message FileRemoveFile { - int32 id = 1; - string path = 2; - sint32 file_num = 3; -} - -message FileDirCreate { - int32 id = 1; - string path = 2; -} - -// main logic from freeRDP -message CliprdrMonitorReady { -} - -message CliprdrFormat { - int32 id = 2; - string format = 3; -} - -message CliprdrServerFormatList { - repeated CliprdrFormat formats = 2; -} - -message CliprdrServerFormatListResponse { - int32 msg_flags = 2; -} - -message CliprdrServerFormatDataRequest { - int32 requested_format_id = 2; -} - -message CliprdrServerFormatDataResponse { - int32 msg_flags = 2; - bytes format_data = 3; -} - -message CliprdrFileContentsRequest { - int32 stream_id = 2; - int32 list_index = 3; - int32 dw_flags = 4; - int32 n_position_low = 5; - int32 n_position_high = 6; - int32 cb_requested = 7; - bool have_clip_data_id = 8; - int32 clip_data_id = 9; -} - -message CliprdrFileContentsResponse { - int32 msg_flags = 3; - int32 stream_id = 4; - bytes requested_data = 5; -} - -message Cliprdr { - oneof union { - CliprdrMonitorReady ready = 1; - CliprdrServerFormatList format_list = 2; - CliprdrServerFormatListResponse format_list_response = 3; - CliprdrServerFormatDataRequest format_data_request = 4; - CliprdrServerFormatDataResponse format_data_response = 5; - CliprdrFileContentsRequest file_contents_request = 6; - CliprdrFileContentsResponse file_contents_response = 7; - } -} - -message SwitchDisplay { - int32 display = 1; - sint32 x = 2; - sint32 y = 3; - int32 width = 4; - int32 height = 5; - bool cursor_embedded = 6; -} - -message PermissionInfo { - enum Permission { - Keyboard = 0; - Clipboard = 2; - Audio = 3; - File = 4; - Restart = 5; - Recording = 6; - } - - Permission permission = 1; - bool enabled = 2; -} - -enum ImageQuality { - NotSet = 0; - Low = 2; - Balanced = 3; - Best = 4; -} - -message VideoCodecState { - enum PreferCodec { - Auto = 0; - VPX = 1; - H264 = 2; - H265 = 3; - } - - int32 score_vpx = 1; - int32 score_h264 = 2; - int32 score_h265 = 3; - PreferCodec prefer = 4; -} - -message OptionMessage { - enum BoolOption { - NotSet = 0; - No = 1; - Yes = 2; - } - ImageQuality image_quality = 1; - BoolOption lock_after_session_end = 2; - BoolOption show_remote_cursor = 3; - BoolOption privacy_mode = 4; - BoolOption block_input = 5; - int32 custom_image_quality = 6; - BoolOption disable_audio = 7; - BoolOption disable_clipboard = 8; - BoolOption enable_file_transfer = 9; - VideoCodecState video_codec_state = 10; - int32 custom_fps = 11; -} - -message TestDelay { - int64 time = 1; - bool from_client = 2; - uint32 last_delay = 3; - uint32 target_bitrate = 4; -} - -message PublicKey { - bytes asymmetric_value = 1; - bytes symmetric_value = 2; -} - -message SignedId { bytes id = 1; } - -message AudioFormat { - uint32 sample_rate = 1; - uint32 channels = 2; -} - -message AudioFrame { - bytes data = 1; - int64 timestamp = 2; -} - -// Notify peer to show message box. -message MessageBox { - // Message type. Refer to flutter/lib/common.dart/msgBox(). - string msgtype = 1; - string title = 2; - // English - string text = 3; - // If not empty, msgbox provides a button to following the link. - // The link here can't be directly http url. - // It must be the key of http url configed in peer side or "rustdesk://*" (jump in app). - string link = 4; -} - -message BackNotification { - // no need to consider block input by someone else - enum BlockInputState { - BlkStateUnknown = 0; - BlkOnSucceeded = 2; - BlkOnFailed = 3; - BlkOffSucceeded = 4; - BlkOffFailed = 5; - } - enum PrivacyModeState { - PrvStateUnknown = 0; - // Privacy mode on by someone else - PrvOnByOther = 2; - // Privacy mode is not supported on the remote side - PrvNotSupported = 3; - // Privacy mode on by self - PrvOnSucceeded = 4; - // Privacy mode on by self, but denied - PrvOnFailedDenied = 5; - // Some plugins are not found - PrvOnFailedPlugin = 6; - // Privacy mode on by self, but failed - PrvOnFailed = 7; - // Privacy mode off by self - PrvOffSucceeded = 8; - // Ctrl + P - PrvOffByPeer = 9; - // Privacy mode off by self, but failed - PrvOffFailed = 10; - PrvOffUnknown = 11; - } - - oneof union { - PrivacyModeState privacy_mode_state = 1; - BlockInputState block_input_state = 2; - } -} - -message ElevationRequestWithLogon { - string username = 1; - string password = 2; -} - -message ElevationRequest { - oneof union { - bool direct = 1; - ElevationRequestWithLogon logon = 2; - } -} - -message SwitchSidesRequest { - bytes uuid = 1; -} - -message SwitchSidesResponse { - bytes uuid = 1; - LoginRequest lr = 2; -} - -message SwitchBack {} - -message Misc { - oneof union { - ChatMessage chat_message = 4; - SwitchDisplay switch_display = 5; - PermissionInfo permission_info = 6; - OptionMessage option = 7; - AudioFormat audio_format = 8; - string close_reason = 9; - bool refresh_video = 10; - bool video_received = 12; - BackNotification back_notification = 13; - bool restart_remote_device = 14; - bool uac = 15; - bool foreground_window_elevated = 16; - bool stop_service = 17; - ElevationRequest elevation_request = 18; - string elevation_response = 19; - bool portable_service_running = 20; - SwitchSidesRequest switch_sides_request = 21; - SwitchBack switch_back = 22; - } -} - -message VoiceCallRequest { - int64 req_timestamp = 1; - // Indicates whether the request is a connect action or a disconnect action. - bool is_connect = 2; -} - -message VoiceCallResponse { - bool accepted = 1; - int64 req_timestamp = 2; // Should copy from [VoiceCallRequest::req_timestamp]. - int64 ack_timestamp = 3; -} - -message Message { - oneof union { - SignedId signed_id = 3; - PublicKey public_key = 4; - TestDelay test_delay = 5; - VideoFrame video_frame = 6; - LoginRequest login_request = 7; - LoginResponse login_response = 8; - Hash hash = 9; - MouseEvent mouse_event = 10; - AudioFrame audio_frame = 11; - CursorData cursor_data = 12; - CursorPosition cursor_position = 13; - uint64 cursor_id = 14; - KeyEvent key_event = 15; - Clipboard clipboard = 16; - FileAction file_action = 17; - FileResponse file_response = 18; - Misc misc = 19; - Cliprdr cliprdr = 20; - MessageBox message_box = 21; - SwitchSidesResponse switch_sides_response = 22; - VoiceCallRequest voice_call_request = 23; - VoiceCallResponse voice_call_response = 24; - } -} diff --git a/libs/hbb_common/protos/rendezvous.proto b/libs/hbb_common/protos/rendezvous.proto deleted file mode 100644 index 1ac60f3..0000000 --- a/libs/hbb_common/protos/rendezvous.proto +++ /dev/null @@ -1,182 +0,0 @@ -syntax = "proto3"; -package hbb; - -message RegisterPeer { - string id = 1; - int32 serial = 2; -} - -enum ConnType { - DEFAULT_CONN = 0; - FILE_TRANSFER = 1; - PORT_FORWARD = 2; - RDP = 3; -} - -message RegisterPeerResponse { bool request_pk = 2; } - -message PunchHoleRequest { - string id = 1; - NatType nat_type = 2; - string licence_key = 3; - ConnType conn_type = 4; - string token = 5; -} - -message PunchHole { - bytes socket_addr = 1; - string relay_server = 2; - NatType nat_type = 3; -} - -message TestNatRequest { - int32 serial = 1; -} - -// per my test, uint/int has no difference in encoding, int not good for negative, use sint for negative -message TestNatResponse { - int32 port = 1; - ConfigUpdate cu = 2; // for mobile -} - -enum NatType { - UNKNOWN_NAT = 0; - ASYMMETRIC = 1; - SYMMETRIC = 2; -} - -message PunchHoleSent { - bytes socket_addr = 1; - string id = 2; - string relay_server = 3; - NatType nat_type = 4; - string version = 5; -} - -message RegisterPk { - string id = 1; - bytes uuid = 2; - bytes pk = 3; - string old_id = 4; -} - -message RegisterPkResponse { - enum Result { - OK = 0; - UUID_MISMATCH = 2; - ID_EXISTS = 3; - TOO_FREQUENT = 4; - INVALID_ID_FORMAT = 5; - NOT_SUPPORT = 6; - SERVER_ERROR = 7; - } - Result result = 1; -} - -message PunchHoleResponse { - bytes socket_addr = 1; - bytes pk = 2; - enum Failure { - ID_NOT_EXIST = 0; - OFFLINE = 2; - LICENSE_MISMATCH = 3; - LICENSE_OVERUSE = 4; - } - Failure failure = 3; - string relay_server = 4; - oneof union { - NatType nat_type = 5; - bool is_local = 6; - } - string other_failure = 7; -} - -message ConfigUpdate { - int32 serial = 1; - repeated string rendezvous_servers = 2; -} - -message RequestRelay { - string id = 1; - string uuid = 2; - bytes socket_addr = 3; - string relay_server = 4; - bool secure = 5; - string licence_key = 6; - ConnType conn_type = 7; - string token = 8; -} - -message RelayResponse { - bytes socket_addr = 1; - string uuid = 2; - string relay_server = 3; - oneof union { - string id = 4; - bytes pk = 5; - } - string refuse_reason = 6; - string version = 7; -} - -message SoftwareUpdate { string url = 1; } - -// if in same intranet, punch hole won't work both for udp and tcp, -// even some router has below connection error if we connect itself, -// { kind: Other, error: "could not resolve to any address" }, -// so we request local address to connect. -message FetchLocalAddr { - bytes socket_addr = 1; - string relay_server = 2; -} - -message LocalAddr { - bytes socket_addr = 1; - bytes local_addr = 2; - string relay_server = 3; - string id = 4; - string version = 5; -} - -message PeerDiscovery { - string cmd = 1; - string mac = 2; - string id = 3; - string username = 4; - string hostname = 5; - string platform = 6; - string misc = 7; -} - -message OnlineRequest { - string id = 1; - repeated string peers = 2; -} - -message OnlineResponse { - bytes states = 1; -} - -message RendezvousMessage { - oneof union { - RegisterPeer register_peer = 6; - RegisterPeerResponse register_peer_response = 7; - PunchHoleRequest punch_hole_request = 8; - PunchHole punch_hole = 9; - PunchHoleSent punch_hole_sent = 10; - PunchHoleResponse punch_hole_response = 11; - FetchLocalAddr fetch_local_addr = 12; - LocalAddr local_addr = 13; - ConfigUpdate configure_update = 14; - RegisterPk register_pk = 15; - RegisterPkResponse register_pk_response = 16; - SoftwareUpdate software_update = 17; - RequestRelay request_relay = 18; - RelayResponse relay_response = 19; - TestNatRequest test_nat_request = 20; - TestNatResponse test_nat_response = 21; - PeerDiscovery peer_discovery = 22; - OnlineRequest online_request = 23; - OnlineResponse online_response = 24; - } -} diff --git a/libs/hbb_common/src/bytes_codec.rs b/libs/hbb_common/src/bytes_codec.rs deleted file mode 100644 index bfc7987..0000000 --- a/libs/hbb_common/src/bytes_codec.rs +++ /dev/null @@ -1,280 +0,0 @@ -use bytes::{Buf, BufMut, Bytes, BytesMut}; -use std::io; -use tokio_util::codec::{Decoder, Encoder}; - -#[derive(Debug, Clone, Copy)] -pub struct BytesCodec { - state: DecodeState, - raw: bool, - max_packet_length: usize, -} - -#[derive(Debug, Clone, Copy)] -enum DecodeState { - Head, - Data(usize), -} - -impl Default for BytesCodec { - fn default() -> Self { - Self::new() - } -} - -impl BytesCodec { - pub fn new() -> Self { - Self { - state: DecodeState::Head, - raw: false, - max_packet_length: usize::MAX, - } - } - - pub fn set_raw(&mut self) { - self.raw = true; - } - - pub fn set_max_packet_length(&mut self, n: usize) { - self.max_packet_length = n; - } - - fn decode_head(&mut self, src: &mut BytesMut) -> io::Result> { - if src.is_empty() { - return Ok(None); - } - let head_len = ((src[0] & 0x3) + 1) as usize; - if src.len() < head_len { - return Ok(None); - } - let mut n = src[0] as usize; - if head_len > 1 { - n |= (src[1] as usize) << 8; - } - if head_len > 2 { - n |= (src[2] as usize) << 16; - } - if head_len > 3 { - n |= (src[3] as usize) << 24; - } - n >>= 2; - if n > self.max_packet_length { - return Err(io::Error::new(io::ErrorKind::InvalidData, "Too big packet")); - } - src.advance(head_len); - src.reserve(n); - Ok(Some(n)) - } - - fn decode_data(&self, n: usize, src: &mut BytesMut) -> io::Result> { - if src.len() < n { - return Ok(None); - } - Ok(Some(src.split_to(n))) - } -} - -impl Decoder for BytesCodec { - type Item = BytesMut; - type Error = io::Error; - - fn decode(&mut self, src: &mut BytesMut) -> Result, io::Error> { - if self.raw { - if !src.is_empty() { - let len = src.len(); - return Ok(Some(src.split_to(len))); - } else { - return Ok(None); - } - } - let n = match self.state { - DecodeState::Head => match self.decode_head(src)? { - Some(n) => { - self.state = DecodeState::Data(n); - n - } - None => return Ok(None), - }, - DecodeState::Data(n) => n, - }; - - match self.decode_data(n, src)? { - Some(data) => { - self.state = DecodeState::Head; - Ok(Some(data)) - } - None => Ok(None), - } - } -} - -impl Encoder for BytesCodec { - type Error = io::Error; - - fn encode(&mut self, data: Bytes, buf: &mut BytesMut) -> Result<(), io::Error> { - if self.raw { - buf.reserve(data.len()); - buf.put(data); - return Ok(()); - } - if data.len() <= 0x3F { - buf.put_u8((data.len() << 2) as u8); - } else if data.len() <= 0x3FFF { - buf.put_u16_le((data.len() << 2) as u16 | 0x1); - } else if data.len() <= 0x3FFFFF { - let h = (data.len() << 2) as u32 | 0x2; - buf.put_u16_le((h & 0xFFFF) as u16); - buf.put_u8((h >> 16) as u8); - } else if data.len() <= 0x3FFFFFFF { - buf.put_u32_le((data.len() << 2) as u32 | 0x3); - } else { - return Err(io::Error::new(io::ErrorKind::InvalidInput, "Overflow")); - } - buf.extend(data); - Ok(()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - #[test] - fn test_codec1() { - let mut codec = BytesCodec::new(); - let mut buf = BytesMut::new(); - let mut bytes: Vec = Vec::new(); - bytes.resize(0x3F, 1); - assert!(codec.encode(bytes.into(), &mut buf).is_ok()); - let buf_saved = buf.clone(); - assert_eq!(buf.len(), 0x3F + 1); - if let Ok(Some(res)) = codec.decode(&mut buf) { - assert_eq!(res.len(), 0x3F); - assert_eq!(res[0], 1); - } else { - panic!(); - } - let mut codec2 = BytesCodec::new(); - let mut buf2 = BytesMut::new(); - if let Ok(None) = codec2.decode(&mut buf2) { - } else { - panic!(); - } - buf2.extend(&buf_saved[0..1]); - if let Ok(None) = codec2.decode(&mut buf2) { - } else { - panic!(); - } - buf2.extend(&buf_saved[1..]); - if let Ok(Some(res)) = codec2.decode(&mut buf2) { - assert_eq!(res.len(), 0x3F); - assert_eq!(res[0], 1); - } else { - panic!(); - } - } - - #[test] - fn test_codec2() { - let mut codec = BytesCodec::new(); - let mut buf = BytesMut::new(); - let mut bytes: Vec = Vec::new(); - assert!(codec.encode("".into(), &mut buf).is_ok()); - assert_eq!(buf.len(), 1); - bytes.resize(0x3F + 1, 2); - assert!(codec.encode(bytes.into(), &mut buf).is_ok()); - assert_eq!(buf.len(), 0x3F + 2 + 2); - if let Ok(Some(res)) = codec.decode(&mut buf) { - assert_eq!(res.len(), 0); - } else { - panic!(); - } - if let Ok(Some(res)) = codec.decode(&mut buf) { - assert_eq!(res.len(), 0x3F + 1); - assert_eq!(res[0], 2); - } else { - panic!(); - } - } - - #[test] - fn test_codec3() { - let mut codec = BytesCodec::new(); - let mut buf = BytesMut::new(); - let mut bytes: Vec = Vec::new(); - bytes.resize(0x3F - 1, 3); - assert!(codec.encode(bytes.into(), &mut buf).is_ok()); - assert_eq!(buf.len(), 0x3F + 1 - 1); - if let Ok(Some(res)) = codec.decode(&mut buf) { - assert_eq!(res.len(), 0x3F - 1); - assert_eq!(res[0], 3); - } else { - panic!(); - } - } - #[test] - fn test_codec4() { - let mut codec = BytesCodec::new(); - let mut buf = BytesMut::new(); - let mut bytes: Vec = Vec::new(); - bytes.resize(0x3FFF, 4); - assert!(codec.encode(bytes.into(), &mut buf).is_ok()); - assert_eq!(buf.len(), 0x3FFF + 2); - if let Ok(Some(res)) = codec.decode(&mut buf) { - assert_eq!(res.len(), 0x3FFF); - assert_eq!(res[0], 4); - } else { - panic!(); - } - } - - #[test] - fn test_codec5() { - let mut codec = BytesCodec::new(); - let mut buf = BytesMut::new(); - let mut bytes: Vec = Vec::new(); - bytes.resize(0x3FFFFF, 5); - assert!(codec.encode(bytes.into(), &mut buf).is_ok()); - assert_eq!(buf.len(), 0x3FFFFF + 3); - if let Ok(Some(res)) = codec.decode(&mut buf) { - assert_eq!(res.len(), 0x3FFFFF); - assert_eq!(res[0], 5); - } else { - panic!(); - } - } - - #[test] - fn test_codec6() { - let mut codec = BytesCodec::new(); - let mut buf = BytesMut::new(); - let mut bytes: Vec = Vec::new(); - bytes.resize(0x3FFFFF + 1, 6); - assert!(codec.encode(bytes.into(), &mut buf).is_ok()); - let buf_saved = buf.clone(); - assert_eq!(buf.len(), 0x3FFFFF + 4 + 1); - if let Ok(Some(res)) = codec.decode(&mut buf) { - assert_eq!(res.len(), 0x3FFFFF + 1); - assert_eq!(res[0], 6); - } else { - panic!(); - } - let mut codec2 = BytesCodec::new(); - let mut buf2 = BytesMut::new(); - buf2.extend(&buf_saved[0..1]); - if let Ok(None) = codec2.decode(&mut buf2) { - } else { - panic!(); - } - buf2.extend(&buf_saved[1..6]); - if let Ok(None) = codec2.decode(&mut buf2) { - } else { - panic!(); - } - buf2.extend(&buf_saved[6..]); - if let Ok(Some(res)) = codec2.decode(&mut buf2) { - assert_eq!(res.len(), 0x3FFFFF + 1); - assert_eq!(res[0], 6); - } else { - panic!(); - } - } -} diff --git a/libs/hbb_common/src/compress.rs b/libs/hbb_common/src/compress.rs deleted file mode 100644 index e7668a9..0000000 --- a/libs/hbb_common/src/compress.rs +++ /dev/null @@ -1,45 +0,0 @@ -use std::cell::RefCell; -use zstd::block::{Compressor, Decompressor}; - -thread_local! { - static COMPRESSOR: RefCell = RefCell::new(Compressor::new()); - static DECOMPRESSOR: RefCell = RefCell::new(Decompressor::new()); -} - -/// The library supports regular compression levels from 1 up to ZSTD_maxCLevel(), -/// which is currently 22. Levels >= 20 -/// Default level is ZSTD_CLEVEL_DEFAULT==3. -/// value 0 means default, which is controlled by ZSTD_CLEVEL_DEFAULT -pub fn compress(data: &[u8], level: i32) -> Vec { - let mut out = Vec::new(); - COMPRESSOR.with(|c| { - if let Ok(mut c) = c.try_borrow_mut() { - match c.compress(data, level) { - Ok(res) => out = res, - Err(err) => { - crate::log::debug!("Failed to compress: {}", err); - } - } - } - }); - out -} - -pub fn decompress(data: &[u8]) -> Vec { - let mut out = Vec::new(); - DECOMPRESSOR.with(|d| { - if let Ok(mut d) = d.try_borrow_mut() { - const MAX: usize = 1024 * 1024 * 64; - const MIN: usize = 1024 * 1024; - let mut n = 30 * data.len(); - n = n.clamp(MIN, MAX); - match d.decompress(data, n) { - Ok(res) => out = res, - Err(err) => { - crate::log::debug!("Failed to decompress: {}", err); - } - } - } - }); - out -} diff --git a/libs/hbb_common/src/config.rs b/libs/hbb_common/src/config.rs deleted file mode 100644 index 099a454..0000000 --- a/libs/hbb_common/src/config.rs +++ /dev/null @@ -1,1348 +0,0 @@ -use std::{ - collections::HashMap, - fs, - net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}, - path::{Path, PathBuf}, - sync::{Arc, Mutex, RwLock}, - time::SystemTime, -}; - -use anyhow::Result; -use rand::Rng; -use regex::Regex; -use serde as de; -use serde_derive::{Deserialize, Serialize}; -use sodiumoxide::base64; -use sodiumoxide::crypto::sign; - -use crate::{ - log, - password_security::{ - decrypt_str_or_original, decrypt_vec_or_original, encrypt_str_or_original, - encrypt_vec_or_original, - }, -}; - -pub const RENDEZVOUS_TIMEOUT: u64 = 12_000; -pub const CONNECT_TIMEOUT: u64 = 18_000; -pub const READ_TIMEOUT: u64 = 30_000; -pub const REG_INTERVAL: i64 = 12_000; -pub const COMPRESS_LEVEL: i32 = 3; -const SERIAL: i32 = 3; -const PASSWORD_ENC_VERSION: &str = "00"; - -#[cfg(target_os = "macos")] -lazy_static::lazy_static! { - pub static ref ORG: Arc> = Arc::new(RwLock::new("com.carriez".to_owned())); -} - -type Size = (i32, i32, i32, i32); -type KeyPair = (Vec, Vec); - -lazy_static::lazy_static! { - static ref CONFIG: Arc> = Arc::new(RwLock::new(Config::load())); - static ref CONFIG2: Arc> = Arc::new(RwLock::new(Config2::load())); - static ref LOCAL_CONFIG: Arc> = Arc::new(RwLock::new(LocalConfig::load())); - pub static ref ONLINE: Arc>> = Default::default(); - pub static ref PROD_RENDEZVOUS_SERVER: Arc> = Arc::new(RwLock::new(match option_env!("RENDEZVOUS_SERVER") { - Some(key) if !key.is_empty() => key, - _ => "", - }.to_owned())); - pub static ref APP_NAME: Arc> = Arc::new(RwLock::new("RustDesk".to_owned())); - static ref KEY_PAIR: Arc>> = Default::default(); - static ref HW_CODEC_CONFIG: Arc> = Arc::new(RwLock::new(HwCodecConfig::load())); -} - -lazy_static::lazy_static! { - pub static ref APP_DIR: Arc> = Default::default(); -} - -#[cfg(any(target_os = "android", target_os = "ios"))] -lazy_static::lazy_static! { - pub static ref APP_HOME_DIR: Arc> = Default::default(); -} - -// #[cfg(any(target_os = "android", target_os = "ios"))] -lazy_static::lazy_static! { - pub static ref HELPER_URL: HashMap<&'static str, &'static str> = HashMap::from([ - ("rustdesk docs home", "https://rustdesk.com/docs/en/"), - ("rustdesk docs x11-required", "https://rustdesk.com/docs/en/manual/linux/#x11-required"), - ]); -} - -const CHARS: &[char] = &[ - '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', - 'm', 'n', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', -]; - -pub const RENDEZVOUS_SERVERS: &[&str] = &[ - "rs-ny.rustdesk.com", - "rs-sg.rustdesk.com", - "rs-cn.rustdesk.com", -]; - -pub const RS_PUB_KEY: &str = match option_env!("RS_PUB_KEY") { - Some(key) if !key.is_empty() => key, - _ => "OeVuKk5nlHiXp+APNn0Y3pC1Iwpwn44JGqrQCsWqmBw=", -}; - -pub const RENDEZVOUS_PORT: i32 = 21116; -pub const RELAY_PORT: i32 = 21117; - -macro_rules! serde_field_string { - ($default_func:ident, $de_func:ident, $default_expr:expr) => { - fn $default_func() -> String { - $default_expr - } - - fn $de_func<'de, D>(deserializer: D) -> Result - where - D: de::Deserializer<'de>, - { - let s: &str = de::Deserialize::deserialize(deserializer)?; - Ok(if s.is_empty() { - Self::$default_func() - } else { - s.to_owned() - }) - } - }; -} - -macro_rules! serde_field_bool { - ($struct_name: ident, $field_name: literal, $func: ident) => { - #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] - pub struct $struct_name { - #[serde(rename = $field_name)] - pub v: bool, - } - impl Default for $struct_name { - fn default() -> Self { - Self { v: Self::$func() } - } - } - impl $struct_name { - pub fn $func() -> bool { - UserDefaultConfig::load().get($field_name) == "Y" - } - } - }; -} - -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub enum NetworkType { - Direct, - ProxySocks, -} - -#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq)] -pub struct Config { - #[serde(default)] - pub id: String, // use - #[serde(default)] - enc_id: String, // store - #[serde(default)] - password: String, - #[serde(default)] - salt: String, - #[serde(default)] - key_pair: KeyPair, // sk, pk - #[serde(default)] - key_confirmed: bool, - #[serde(default)] - keys_confirmed: HashMap, -} - -#[derive(Debug, Default, PartialEq, Serialize, Deserialize, Clone)] -pub struct Socks5Server { - #[serde(default)] - pub proxy: String, - #[serde(default)] - pub username: String, - #[serde(default)] - pub password: String, -} - -// more variable configs -#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq)] -pub struct Config2 { - #[serde(default)] - rendezvous_server: String, - #[serde(default)] - nat_type: i32, - #[serde(default)] - serial: i32, - - #[serde(default)] - socks: Option, - - // the other scalar value must before this - #[serde(default)] - pub options: HashMap, -} - -#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq)] -pub struct PeerConfig { - #[serde(default)] - pub password: Vec, - #[serde(default)] - pub size: Size, - #[serde(default)] - pub size_ft: Size, - #[serde(default)] - pub size_pf: Size, - #[serde( - default = "PeerConfig::default_view_style", - deserialize_with = "PeerConfig::deserialize_view_style" - )] - pub view_style: String, - #[serde( - default = "PeerConfig::default_scroll_style", - deserialize_with = "PeerConfig::deserialize_scroll_style" - )] - pub scroll_style: String, - #[serde( - default = "PeerConfig::default_image_quality", - deserialize_with = "PeerConfig::deserialize_image_quality" - )] - pub image_quality: String, - #[serde( - default = "PeerConfig::default_custom_image_quality", - deserialize_with = "PeerConfig::deserialize_custom_image_quality" - )] - pub custom_image_quality: Vec, - #[serde(flatten)] - pub show_remote_cursor: ShowRemoteCursor, - #[serde(flatten)] - pub lock_after_session_end: LockAfterSessionEnd, - #[serde(flatten)] - pub privacy_mode: PrivacyMode, - #[serde(default)] - pub port_forwards: Vec<(i32, String, i32)>, - #[serde(default)] - pub direct_failures: i32, - #[serde(flatten)] - pub disable_audio: DisableAudio, - #[serde(flatten)] - pub disable_clipboard: DisableClipboard, - #[serde(flatten)] - pub enable_file_transfer: EnableFileTransfer, - #[serde(flatten)] - pub show_quality_monitor: ShowQualityMonitor, - #[serde(default)] - pub keyboard_mode: String, - - // The other scalar value must before this - #[serde(default, deserialize_with = "PeerConfig::deserialize_options")] - pub options: HashMap, - // Various data for flutter ui - #[serde(default)] - pub ui_flutter: HashMap, - #[serde(default)] - pub info: PeerInfoSerde, - #[serde(default)] - pub transfer: TransferSerde, -} - -#[derive(Debug, PartialEq, Default, Serialize, Deserialize, Clone)] -pub struct PeerInfoSerde { - #[serde(default)] - pub username: String, - #[serde(default)] - pub hostname: String, - #[serde(default)] - pub platform: String, -} - -#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq)] -pub struct TransferSerde { - #[serde(default)] - pub write_jobs: Vec, - #[serde(default)] - pub read_jobs: Vec, -} - -fn patch(path: PathBuf) -> PathBuf { - if let Some(_tmp) = path.to_str() { - #[cfg(windows)] - return _tmp - .replace( - "system32\\config\\systemprofile", - "ServiceProfiles\\LocalService", - ) - .into(); - #[cfg(target_os = "macos")] - return _tmp.replace("Application Support", "Preferences").into(); - #[cfg(target_os = "linux")] - { - if _tmp == "/root" { - if let Ok(output) = std::process::Command::new("whoami").output() { - let user = String::from_utf8_lossy(&output.stdout) - .to_string() - .trim() - .to_owned(); - if user != "root" { - return format!("/home/{user}").into(); - } - } - } - } - } - path -} - -impl Config2 { - fn load() -> Config2 { - let mut config = Config::load_::("2"); - if let Some(mut socks) = config.socks { - let (password, _, store) = - decrypt_str_or_original(&socks.password, PASSWORD_ENC_VERSION); - socks.password = password; - config.socks = Some(socks); - if store { - config.store(); - } - } - config - } - - pub fn file() -> PathBuf { - Config::file_("2") - } - - fn store(&self) { - let mut config = self.clone(); - if let Some(mut socks) = config.socks { - socks.password = encrypt_str_or_original(&socks.password, PASSWORD_ENC_VERSION); - config.socks = Some(socks); - } - Config::store_(&config, "2"); - } - - pub fn get() -> Config2 { - return CONFIG2.read().unwrap().clone(); - } - - pub fn set(cfg: Config2) -> bool { - let mut lock = CONFIG2.write().unwrap(); - if *lock == cfg { - return false; - } - *lock = cfg; - lock.store(); - true - } -} - -pub fn load_path( - file: PathBuf, -) -> T { - match confy::load_path(file) { - Ok(config) => config, - Err(err) => { - log::error!("Failed to load config: {}", err); - T::default() - } - } -} - -#[inline] -pub fn store_path(path: PathBuf, cfg: T) -> crate::ResultType<()> { - Ok(confy::store_path(path, cfg)?) -} - -impl Config { - fn load_( - suffix: &str, - ) -> T { - let file = Self::file_(suffix); - log::debug!("Configuration path: {}", file.display()); - let cfg = load_path(file); - if suffix.is_empty() { - log::trace!("{:?}", cfg); - } - cfg - } - - fn store_(config: &T, suffix: &str) { - let file = Self::file_(suffix); - if let Err(err) = store_path(file, config) { - log::error!("Failed to store config: {}", err); - } - } - - fn load() -> Config { - let mut config = Config::load_::(""); - let mut store = false; - let (password, _, store1) = decrypt_str_or_original(&config.password, PASSWORD_ENC_VERSION); - config.password = password; - store |= store1; - let mut id_valid = false; - let (id, encrypted, store2) = decrypt_str_or_original(&config.enc_id, PASSWORD_ENC_VERSION); - if encrypted { - config.id = id; - id_valid = true; - store |= store2; - } else if crate::get_modified_time(&Self::file_("")) - .checked_sub(std::time::Duration::from_secs(30)) // allow modification during installation - .unwrap_or_else(crate::get_exe_time) - < crate::get_exe_time() - && !config.id.is_empty() - && config.enc_id.is_empty() - && !decrypt_str_or_original(&config.id, PASSWORD_ENC_VERSION).1 - { - id_valid = true; - store = true; - } - if !id_valid { - for _ in 0..3 { - if let Some(id) = Config::get_auto_id() { - config.id = id; - store = true; - break; - } else { - log::error!("Failed to generate new id"); - } - } - } - if store { - config.store(); - } - config - } - - fn store(&self) { - let mut config = self.clone(); - config.password = encrypt_str_or_original(&config.password, PASSWORD_ENC_VERSION); - config.enc_id = encrypt_str_or_original(&config.id, PASSWORD_ENC_VERSION); - config.id = "".to_owned(); - Config::store_(&config, ""); - } - - pub fn file() -> PathBuf { - Self::file_("") - } - - fn file_(suffix: &str) -> PathBuf { - let name = format!("{}{}", *APP_NAME.read().unwrap(), suffix); - Config::with_extension(Self::path(name)) - } - - pub fn is_empty(&self) -> bool { - (self.id.is_empty() && self.enc_id.is_empty()) || self.key_pair.0.is_empty() - } - - pub fn get_home() -> PathBuf { - #[cfg(any(target_os = "android", target_os = "ios"))] - return Self::path(APP_HOME_DIR.read().unwrap().as_str()); - #[cfg(not(any(target_os = "android", target_os = "ios")))] - { - if let Some(path) = dirs_next::home_dir() { - patch(path) - } else if let Ok(path) = std::env::current_dir() { - path - } else { - std::env::temp_dir() - } - } - } - - pub fn path>(p: P) -> PathBuf { - #[cfg(any(target_os = "android", target_os = "ios"))] - { - let mut path: PathBuf = APP_DIR.read().unwrap().clone().into(); - path.push(p); - return path; - } - #[cfg(not(any(target_os = "android", target_os = "ios")))] - { - #[cfg(not(target_os = "macos"))] - let org = "".to_owned(); - #[cfg(target_os = "macos")] - let org = ORG.read().unwrap().clone(); - // /var/root for root - if let Some(project) = - directories_next::ProjectDirs::from("", &org, &APP_NAME.read().unwrap()) - { - let mut path = patch(project.config_dir().to_path_buf()); - path.push(p); - return path; - } - "".into() - } - } - - #[allow(unreachable_code)] - pub fn log_path() -> PathBuf { - #[cfg(target_os = "macos")] - { - if let Some(path) = dirs_next::home_dir().as_mut() { - path.push(format!("Library/Logs/{}", *APP_NAME.read().unwrap())); - return path.clone(); - } - } - #[cfg(target_os = "linux")] - { - let mut path = Self::get_home(); - path.push(format!(".local/share/logs/{}", *APP_NAME.read().unwrap())); - std::fs::create_dir_all(&path).ok(); - return path; - } - if let Some(path) = Self::path("").parent() { - let mut path: PathBuf = path.into(); - path.push("log"); - return path; - } - "".into() - } - - pub fn ipc_path(postfix: &str) -> String { - #[cfg(windows)] - { - // \\ServerName\pipe\PipeName - // where ServerName is either the name of a remote computer or a period, to specify the local computer. - // https://docs.microsoft.com/en-us/windows/win32/ipc/pipe-names - format!( - "\\\\.\\pipe\\{}\\query{}", - *APP_NAME.read().unwrap(), - postfix - ) - } - #[cfg(not(windows))] - { - use std::os::unix::fs::PermissionsExt; - #[cfg(target_os = "android")] - let mut path: PathBuf = - format!("{}/{}", *APP_DIR.read().unwrap(), *APP_NAME.read().unwrap()).into(); - #[cfg(not(target_os = "android"))] - let mut path: PathBuf = format!("/tmp/{}", *APP_NAME.read().unwrap()).into(); - fs::create_dir(&path).ok(); - fs::set_permissions(&path, fs::Permissions::from_mode(0o0777)).ok(); - path.push(format!("ipc{postfix}")); - path.to_str().unwrap_or("").to_owned() - } - } - - pub fn icon_path() -> PathBuf { - let mut path = Self::path("icons"); - if fs::create_dir_all(&path).is_err() { - path = std::env::temp_dir(); - } - path - } - - #[inline] - pub fn get_any_listen_addr(is_ipv4: bool) -> SocketAddr { - if is_ipv4 { - SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 0) - } else { - SocketAddr::new(IpAddr::V6(Ipv6Addr::UNSPECIFIED), 0) - } - } - - pub fn get_rendezvous_server() -> String { - let mut rendezvous_server = Self::get_option("custom-rendezvous-server"); - if rendezvous_server.is_empty() { - rendezvous_server = PROD_RENDEZVOUS_SERVER.read().unwrap().clone(); - } - if rendezvous_server.is_empty() { - rendezvous_server = CONFIG2.read().unwrap().rendezvous_server.clone(); - } - if rendezvous_server.is_empty() { - rendezvous_server = Self::get_rendezvous_servers() - .drain(..) - .next() - .unwrap_or_default(); - } - if !rendezvous_server.contains(':') { - rendezvous_server = format!("{rendezvous_server}:{RENDEZVOUS_PORT}"); - } - rendezvous_server - } - - pub fn get_rendezvous_servers() -> Vec { - let s = Self::get_option("custom-rendezvous-server"); - if !s.is_empty() { - return vec![s]; - } - let s = PROD_RENDEZVOUS_SERVER.read().unwrap().clone(); - if !s.is_empty() { - return vec![s]; - } - let serial_obsolute = CONFIG2.read().unwrap().serial > SERIAL; - if serial_obsolute { - let ss: Vec = Self::get_option("rendezvous-servers") - .split(',') - .filter(|x| x.contains('.')) - .map(|x| x.to_owned()) - .collect(); - if !ss.is_empty() { - return ss; - } - } - return RENDEZVOUS_SERVERS.iter().map(|x| x.to_string()).collect(); - } - - pub fn reset_online() { - *ONLINE.lock().unwrap() = Default::default(); - } - - pub fn update_latency(host: &str, latency: i64) { - ONLINE.lock().unwrap().insert(host.to_owned(), latency); - let mut host = "".to_owned(); - let mut delay = i64::MAX; - for (tmp_host, tmp_delay) in ONLINE.lock().unwrap().iter() { - if tmp_delay > &0 && tmp_delay < &delay { - delay = *tmp_delay; - host = tmp_host.to_string(); - } - } - if !host.is_empty() { - let mut config = CONFIG2.write().unwrap(); - if host != config.rendezvous_server { - log::debug!("Update rendezvous_server in config to {}", host); - log::debug!("{:?}", *ONLINE.lock().unwrap()); - config.rendezvous_server = host; - config.store(); - } - } - } - - pub fn set_id(id: &str) { - let mut config = CONFIG.write().unwrap(); - if id == config.id { - return; - } - config.id = id.into(); - config.store(); - } - - pub fn set_nat_type(nat_type: i32) { - let mut config = CONFIG2.write().unwrap(); - if nat_type == config.nat_type { - return; - } - config.nat_type = nat_type; - config.store(); - } - - pub fn get_nat_type() -> i32 { - CONFIG2.read().unwrap().nat_type - } - - pub fn set_serial(serial: i32) { - let mut config = CONFIG2.write().unwrap(); - if serial == config.serial { - return; - } - config.serial = serial; - config.store(); - } - - pub fn get_serial() -> i32 { - std::cmp::max(CONFIG2.read().unwrap().serial, SERIAL) - } - - fn get_auto_id() -> Option { - #[cfg(any(target_os = "android", target_os = "ios"))] - { - return Some( - rand::thread_rng() - .gen_range(1_000_000_000..2_000_000_000) - .to_string(), - ); - } - - #[cfg(not(any(target_os = "android", target_os = "ios")))] - { - let mut id = 0u32; - if let Ok(Some(ma)) = mac_address::get_mac_address() { - for x in &ma.bytes()[2..] { - id = (id << 8) | (*x as u32); - } - id &= 0x1FFFFFFF; - Some(id.to_string()) - } else { - None - } - } - } - - pub fn get_auto_password(length: usize) -> String { - let mut rng = rand::thread_rng(); - (0..length) - .map(|_| CHARS[rng.gen::() % CHARS.len()]) - .collect() - } - - pub fn get_key_confirmed() -> bool { - CONFIG.read().unwrap().key_confirmed - } - - pub fn set_key_confirmed(v: bool) { - let mut config = CONFIG.write().unwrap(); - if config.key_confirmed == v { - return; - } - config.key_confirmed = v; - if !v { - config.keys_confirmed = Default::default(); - } - config.store(); - } - - pub fn get_host_key_confirmed(host: &str) -> bool { - matches!(CONFIG.read().unwrap().keys_confirmed.get(host), Some(true)) - } - - pub fn set_host_key_confirmed(host: &str, v: bool) { - if Self::get_host_key_confirmed(host) == v { - return; - } - let mut config = CONFIG.write().unwrap(); - config.keys_confirmed.insert(host.to_owned(), v); - config.store(); - } - - pub fn get_key_pair() -> KeyPair { - // lock here to make sure no gen_keypair more than once - // no use of CONFIG directly here to ensure no recursive calling in Config::load because of password dec which calling this function - let mut lock = KEY_PAIR.lock().unwrap(); - if let Some(p) = lock.as_ref() { - return p.clone(); - } - let mut config = Config::load_::(""); - if config.key_pair.0.is_empty() { - let (pk, sk) = sign::gen_keypair(); - let key_pair = (sk.0.to_vec(), pk.0.into()); - config.key_pair = key_pair.clone(); - std::thread::spawn(|| { - let mut config = CONFIG.write().unwrap(); - config.key_pair = key_pair; - config.store(); - }); - } - *lock = Some(config.key_pair.clone()); - config.key_pair - } - - pub fn get_id() -> String { - let mut id = CONFIG.read().unwrap().id.clone(); - if id.is_empty() { - if let Some(tmp) = Config::get_auto_id() { - id = tmp; - Config::set_id(&id); - } - } - id - } - - pub fn get_id_or(b: String) -> String { - let a = CONFIG.read().unwrap().id.clone(); - if a.is_empty() { - b - } else { - a - } - } - - pub fn get_options() -> HashMap { - CONFIG2.read().unwrap().options.clone() - } - - pub fn set_options(v: HashMap) { - let mut config = CONFIG2.write().unwrap(); - if config.options == v { - return; - } - config.options = v; - config.store(); - } - - pub fn get_option(k: &str) -> String { - if let Some(v) = CONFIG2.read().unwrap().options.get(k) { - v.clone() - } else { - "".to_owned() - } - } - - pub fn set_option(k: String, v: String) { - let mut config = CONFIG2.write().unwrap(); - let v2 = if v.is_empty() { None } else { Some(&v) }; - if v2 != config.options.get(&k) { - if v2.is_none() { - config.options.remove(&k); - } else { - config.options.insert(k, v); - } - config.store(); - } - } - - pub fn update_id() { - // to-do: how about if one ip register a lot of ids? - let id = Self::get_id(); - let mut rng = rand::thread_rng(); - let new_id = rng.gen_range(1_000_000_000..2_000_000_000).to_string(); - Config::set_id(&new_id); - log::info!("id updated from {} to {}", id, new_id); - } - - pub fn set_permanent_password(password: &str) { - let mut config = CONFIG.write().unwrap(); - if password == config.password { - return; - } - config.password = password.into(); - config.store(); - } - - pub fn get_permanent_password() -> String { - CONFIG.read().unwrap().password.clone() - } - - pub fn set_salt(salt: &str) { - let mut config = CONFIG.write().unwrap(); - if salt == config.salt { - return; - } - config.salt = salt.into(); - config.store(); - } - - pub fn get_salt() -> String { - let mut salt = CONFIG.read().unwrap().salt.clone(); - if salt.is_empty() { - salt = Config::get_auto_password(6); - Config::set_salt(&salt); - } - salt - } - - pub fn set_socks(socks: Option) { - let mut config = CONFIG2.write().unwrap(); - if config.socks == socks { - return; - } - config.socks = socks; - config.store(); - } - - pub fn get_socks() -> Option { - CONFIG2.read().unwrap().socks.clone() - } - - pub fn get_network_type() -> NetworkType { - match &CONFIG2.read().unwrap().socks { - None => NetworkType::Direct, - Some(_) => NetworkType::ProxySocks, - } - } - - pub fn get() -> Config { - return CONFIG.read().unwrap().clone(); - } - - pub fn set(cfg: Config) -> bool { - let mut lock = CONFIG.write().unwrap(); - if *lock == cfg { - return false; - } - *lock = cfg; - lock.store(); - true - } - - fn with_extension(path: PathBuf) -> PathBuf { - let ext = path.extension(); - if let Some(ext) = ext { - let ext = format!("{}.toml", ext.to_string_lossy()); - path.with_extension(ext) - } else { - path.with_extension("toml") - } - } -} - -const PEERS: &str = "peers"; - -impl PeerConfig { - pub fn load(id: &str) -> PeerConfig { - let _lock = CONFIG.read().unwrap(); - match confy::load_path(Self::path(id)) { - Ok(config) => { - let mut config: PeerConfig = config; - let mut store = false; - let (password, _, store2) = - decrypt_vec_or_original(&config.password, PASSWORD_ENC_VERSION); - config.password = password; - store = store || store2; - if let Some(v) = config.options.get_mut("rdp_password") { - let (password, _, store2) = decrypt_str_or_original(v, PASSWORD_ENC_VERSION); - *v = password; - store = store || store2; - } - if let Some(v) = config.options.get_mut("os-password") { - let (password, _, store2) = decrypt_str_or_original(v, PASSWORD_ENC_VERSION); - *v = password; - store = store || store2; - } - if store { - config.store(id); - } - config - } - Err(err) => { - log::error!("Failed to load config: {}", err); - Default::default() - } - } - } - - pub fn store(&self, id: &str) { - let _lock = CONFIG.read().unwrap(); - let mut config = self.clone(); - config.password = encrypt_vec_or_original(&config.password, PASSWORD_ENC_VERSION); - if let Some(v) = config.options.get_mut("rdp_password") { - *v = encrypt_str_or_original(v, PASSWORD_ENC_VERSION) - } - if let Some(v) = config.options.get_mut("os-password") { - *v = encrypt_str_or_original(v, PASSWORD_ENC_VERSION) - }; - if let Err(err) = store_path(Self::path(id), config) { - log::error!("Failed to store config: {}", err); - } - } - - pub fn remove(id: &str) { - fs::remove_file(Self::path(id)).ok(); - } - - fn path(id: &str) -> PathBuf { - //If the id contains invalid chars, encode it - let forbidden_paths = Regex::new(r".*[<>:/\\|\?\*].*").unwrap(); - let id_encoded = if forbidden_paths.is_match(id) { - "base64_".to_string() + base64::encode(id, base64::Variant::Original).as_str() - } else { - id.to_string() - }; - let path: PathBuf = [PEERS, id_encoded.as_str()].iter().collect(); - Config::with_extension(Config::path(path)) - } - - pub fn peers() -> Vec<(String, SystemTime, PeerConfig)> { - if let Ok(peers) = Config::path(PEERS).read_dir() { - if let Ok(peers) = peers - .map(|res| res.map(|e| e.path())) - .collect::, _>>() - { - let mut peers: Vec<_> = peers - .iter() - .filter(|p| { - p.is_file() - && p.extension().map(|p| p.to_str().unwrap_or("")) == Some("toml") - }) - .map(|p| { - let t = crate::get_modified_time(p); - let id = p - .file_stem() - .map(|p| p.to_str().unwrap_or("")) - .unwrap_or("") - .to_owned(); - - let id_decoded_string = if id.starts_with("base64_") && id.len() != 7 { - let id_decoded = base64::decode(&id[7..], base64::Variant::Original) - .unwrap_or_default(); - String::from_utf8_lossy(&id_decoded).as_ref().to_owned() - } else { - id - }; - - let c = PeerConfig::load(&id_decoded_string); - if c.info.platform.is_empty() { - fs::remove_file(p).ok(); - } - (id_decoded_string, t, c) - }) - .filter(|p| !p.2.info.platform.is_empty()) - .collect(); - peers.sort_unstable_by(|a, b| b.1.cmp(&a.1)); - return peers; - } - } - Default::default() - } - - serde_field_string!( - default_view_style, - deserialize_view_style, - UserDefaultConfig::load().get("view_style") - ); - serde_field_string!( - default_scroll_style, - deserialize_scroll_style, - UserDefaultConfig::load().get("scroll_style") - ); - serde_field_string!( - default_image_quality, - deserialize_image_quality, - UserDefaultConfig::load().get("image_quality") - ); - - fn default_custom_image_quality() -> Vec { - let f: f64 = UserDefaultConfig::load() - .get("custom_image_quality") - .parse() - .unwrap_or(50.0); - vec![f as _] - } - - fn deserialize_custom_image_quality<'de, D>(deserializer: D) -> Result, D::Error> - where - D: de::Deserializer<'de>, - { - let v: Vec = de::Deserialize::deserialize(deserializer)?; - if v.len() == 1 && v[0] >= 10 && v[0] <= 100 { - Ok(v) - } else { - Ok(Self::default_custom_image_quality()) - } - } - - fn deserialize_options<'de, D>(deserializer: D) -> Result, D::Error> - where - D: de::Deserializer<'de>, - { - let mut mp: HashMap = de::Deserialize::deserialize(deserializer)?; - let mut key = "codec-preference"; - if !mp.contains_key(key) { - mp.insert(key.to_owned(), UserDefaultConfig::load().get(key)); - } - key = "custom-fps"; - if !mp.contains_key(key) { - mp.insert(key.to_owned(), UserDefaultConfig::load().get(key)); - } - key = "zoom-cursor"; - if !mp.contains_key(key) { - mp.insert(key.to_owned(), UserDefaultConfig::load().get(key)); - } - Ok(mp) - } -} - -serde_field_bool!( - ShowRemoteCursor, - "show_remote_cursor", - default_show_remote_cursor -); -serde_field_bool!( - ShowQualityMonitor, - "show_quality_monitor", - default_show_quality_monitor -); -serde_field_bool!(DisableAudio, "disable_audio", default_disable_audio); -serde_field_bool!( - EnableFileTransfer, - "enable_file_transfer", - default_enable_file_transfer -); -serde_field_bool!( - DisableClipboard, - "disable_clipboard", - default_disable_clipboard -); -serde_field_bool!( - LockAfterSessionEnd, - "lock_after_session_end", - default_lock_after_session_end -); -serde_field_bool!(PrivacyMode, "privacy_mode", default_privacy_mode); - -#[derive(Debug, Default, Serialize, Deserialize, Clone)] -pub struct LocalConfig { - #[serde(default)] - remote_id: String, // latest used one - #[serde(default)] - kb_layout_type: String, - #[serde(default)] - size: Size, - #[serde(default)] - pub fav: Vec, - #[serde(default)] - options: HashMap, - // Various data for flutter ui - #[serde(default)] - ui_flutter: HashMap, -} - -impl LocalConfig { - fn load() -> LocalConfig { - Config::load_::("_local") - } - - fn store(&self) { - Config::store_(self, "_local"); - } - - pub fn get_kb_layout_type() -> String { - LOCAL_CONFIG.read().unwrap().kb_layout_type.clone() - } - - pub fn set_kb_layout_type(kb_layout_type: String) { - let mut config = LOCAL_CONFIG.write().unwrap(); - config.kb_layout_type = kb_layout_type; - config.store(); - } - - pub fn get_size() -> Size { - LOCAL_CONFIG.read().unwrap().size - } - - pub fn set_size(x: i32, y: i32, w: i32, h: i32) { - let mut config = LOCAL_CONFIG.write().unwrap(); - let size = (x, y, w, h); - if size == config.size || size.2 < 300 || size.3 < 300 { - return; - } - config.size = size; - config.store(); - } - - pub fn set_remote_id(remote_id: &str) { - let mut config = LOCAL_CONFIG.write().unwrap(); - if remote_id == config.remote_id { - return; - } - config.remote_id = remote_id.into(); - config.store(); - } - - pub fn get_remote_id() -> String { - LOCAL_CONFIG.read().unwrap().remote_id.clone() - } - - pub fn set_fav(fav: Vec) { - let mut lock = LOCAL_CONFIG.write().unwrap(); - if lock.fav == fav { - return; - } - lock.fav = fav; - lock.store(); - } - - pub fn get_fav() -> Vec { - LOCAL_CONFIG.read().unwrap().fav.clone() - } - - pub fn get_option(k: &str) -> String { - if let Some(v) = LOCAL_CONFIG.read().unwrap().options.get(k) { - v.clone() - } else { - "".to_owned() - } - } - - pub fn set_option(k: String, v: String) { - let mut config = LOCAL_CONFIG.write().unwrap(); - let v2 = if v.is_empty() { None } else { Some(&v) }; - if v2 != config.options.get(&k) { - if v2.is_none() { - config.options.remove(&k); - } else { - config.options.insert(k, v); - } - config.store(); - } - } - - pub fn get_flutter_config(k: &str) -> String { - if let Some(v) = LOCAL_CONFIG.read().unwrap().ui_flutter.get(k) { - v.clone() - } else { - "".to_owned() - } - } - - pub fn set_flutter_config(k: String, v: String) { - let mut config = LOCAL_CONFIG.write().unwrap(); - let v2 = if v.is_empty() { None } else { Some(&v) }; - if v2 != config.ui_flutter.get(&k) { - if v2.is_none() { - config.ui_flutter.remove(&k); - } else { - config.ui_flutter.insert(k, v); - } - config.store(); - } - } -} - -#[derive(Debug, Default, Serialize, Deserialize, Clone)] -pub struct DiscoveryPeer { - #[serde(default)] - pub id: String, - #[serde(default)] - pub username: String, - #[serde(default)] - pub hostname: String, - #[serde(default)] - pub platform: String, - #[serde(default)] - pub online: bool, - #[serde(default)] - pub ip_mac: HashMap, -} - -impl DiscoveryPeer { - pub fn is_same_peer(&self, other: &DiscoveryPeer) -> bool { - self.id == other.id && self.username == other.username - } -} - -#[derive(Debug, Default, Serialize, Deserialize, Clone)] -pub struct LanPeers { - pub peers: Vec, -} - -impl LanPeers { - pub fn load() -> LanPeers { - let _lock = CONFIG.read().unwrap(); - match confy::load_path(Config::file_("_lan_peers")) { - Ok(peers) => peers, - Err(err) => { - log::error!("Failed to load lan peers: {}", err); - Default::default() - } - } - } - - pub fn store(peers: &[DiscoveryPeer]) { - let f = LanPeers { - peers: peers.to_owned(), - }; - if let Err(err) = store_path(Config::file_("_lan_peers"), f) { - log::error!("Failed to store lan peers: {}", err); - } - } - - pub fn modify_time() -> crate::ResultType { - let p = Config::file_("_lan_peers"); - Ok(fs::metadata(p)? - .modified()? - .duration_since(SystemTime::UNIX_EPOCH)? - .as_millis() as _) - } -} - -#[derive(Debug, Default, Serialize, Deserialize, Clone)] -pub struct HwCodecConfig { - #[serde(default)] - pub options: HashMap, -} - -impl HwCodecConfig { - pub fn load() -> HwCodecConfig { - Config::load_::("_hwcodec") - } - - pub fn store(&self) { - Config::store_(self, "_hwcodec"); - } - - pub fn remove() { - std::fs::remove_file(Config::file_("_hwcodec")).ok(); - } - - /// refresh current global HW_CODEC_CONFIG, usually uesd after HwCodecConfig::remove() - pub fn refresh() { - *HW_CODEC_CONFIG.write().unwrap() = HwCodecConfig::load(); - log::debug!("HW_CODEC_CONFIG refreshed successfully"); - } - - pub fn get() -> HwCodecConfig { - return HW_CODEC_CONFIG.read().unwrap().clone(); - } -} - -#[derive(Debug, Default, Serialize, Deserialize, Clone)] -pub struct UserDefaultConfig { - #[serde(default)] - options: HashMap, -} - -impl UserDefaultConfig { - pub fn load() -> UserDefaultConfig { - Config::load_::("_default") - } - - #[inline] - fn store(&self) { - Config::store_(self, "_default"); - } - - pub fn get(&self, key: &str) -> String { - match key { - "view_style" => self.get_string(key, "original", vec!["adaptive"]), - "scroll_style" => self.get_string(key, "scrollauto", vec!["scrollbar"]), - "image_quality" => self.get_string(key, "balanced", vec!["best", "low", "custom"]), - "codec-preference" => self.get_string(key, "auto", vec!["vp9", "h264", "h265"]), - "custom_image_quality" => self.get_double_string(key, 50.0, 10.0, 100.0), - "custom-fps" => self.get_double_string(key, 30.0, 10.0, 120.0), - _ => self - .options - .get(key) - .map(|v| v.to_string()) - .unwrap_or_default(), - } - } - - pub fn set(&mut self, key: String, value: String) { - self.options.insert(key, value); - self.store(); - } - - #[inline] - fn get_string(&self, key: &str, default: &str, others: Vec<&str>) -> String { - match self.options.get(key) { - Some(option) => { - if others.contains(&option.as_str()) { - option.to_owned() - } else { - default.to_owned() - } - } - None => default.to_owned(), - } - } - - #[inline] - fn get_double_string(&self, key: &str, default: f64, min: f64, max: f64) -> String { - match self.options.get(key) { - Some(option) => { - let v: f64 = option.parse().unwrap_or(default); - if v >= min && v <= max { - v.to_string() - } else { - default.to_string() - } - } - None => default.to_string(), - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_serialize() { - let cfg: Config = Default::default(); - let res = toml::to_string_pretty(&cfg); - assert!(res.is_ok()); - let cfg: PeerConfig = Default::default(); - let res = toml::to_string_pretty(&cfg); - assert!(res.is_ok()); - } -} diff --git a/libs/hbb_common/src/fs.rs b/libs/hbb_common/src/fs.rs deleted file mode 100644 index ea54e11..0000000 --- a/libs/hbb_common/src/fs.rs +++ /dev/null @@ -1,839 +0,0 @@ -#[cfg(windows)] -use std::os::windows::prelude::*; -use std::path::{Path, PathBuf}; -use std::time::{Duration, SystemTime, UNIX_EPOCH}; - -use serde_derive::{Deserialize, Serialize}; -use tokio::{fs::File, io::*}; - -use crate::{bail, get_version_number, message_proto::*, ResultType, Stream}; -// https://doc.rust-lang.org/std/os/windows/fs/trait.MetadataExt.html -use crate::{ - compress::{compress, decompress}, - config::{Config, COMPRESS_LEVEL}, -}; - -pub fn read_dir(path: &Path, include_hidden: bool) -> ResultType { - let mut dir = FileDirectory { - path: get_string(path), - ..Default::default() - }; - #[cfg(windows)] - if "/" == &get_string(path) { - let drives = unsafe { winapi::um::fileapi::GetLogicalDrives() }; - for i in 0..32 { - if drives & (1 << i) != 0 { - let name = format!( - "{}:", - std::char::from_u32('A' as u32 + i as u32).unwrap_or('A') - ); - dir.entries.push(FileEntry { - name, - entry_type: FileType::DirDrive.into(), - ..Default::default() - }); - } - } - return Ok(dir); - } - for entry in path.read_dir()?.flatten() { - let p = entry.path(); - let name = p - .file_name() - .map(|p| p.to_str().unwrap_or("")) - .unwrap_or("") - .to_owned(); - if name.is_empty() { - continue; - } - let mut is_hidden = false; - let meta; - if let Ok(tmp) = std::fs::symlink_metadata(&p) { - meta = tmp; - } else { - continue; - } - // docs.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants - #[cfg(windows)] - if meta.file_attributes() & 0x2 != 0 { - is_hidden = true; - } - #[cfg(not(windows))] - if name.find('.').unwrap_or(usize::MAX) == 0 { - is_hidden = true; - } - if is_hidden && !include_hidden { - continue; - } - let (entry_type, size) = { - if p.is_dir() { - if meta.file_type().is_symlink() { - (FileType::DirLink.into(), 0) - } else { - (FileType::Dir.into(), 0) - } - } else if meta.file_type().is_symlink() { - (FileType::FileLink.into(), 0) - } else { - (FileType::File.into(), meta.len()) - } - }; - let modified_time = meta - .modified() - .map(|x| { - x.duration_since(std::time::SystemTime::UNIX_EPOCH) - .map(|x| x.as_secs()) - .unwrap_or(0) - }) - .unwrap_or(0); - dir.entries.push(FileEntry { - name: get_file_name(&p), - entry_type, - is_hidden, - size, - modified_time, - ..Default::default() - }); - } - Ok(dir) -} - -#[inline] -pub fn get_file_name(p: &Path) -> String { - p.file_name() - .map(|p| p.to_str().unwrap_or("")) - .unwrap_or("") - .to_owned() -} - -#[inline] -pub fn get_string(path: &Path) -> String { - path.to_str().unwrap_or("").to_owned() -} - -#[inline] -pub fn get_path(path: &str) -> PathBuf { - Path::new(path).to_path_buf() -} - -#[inline] -pub fn get_home_as_string() -> String { - get_string(&Config::get_home()) -} - -fn read_dir_recursive( - path: &PathBuf, - prefix: &Path, - include_hidden: bool, -) -> ResultType> { - let mut files = Vec::new(); - if path.is_dir() { - // to-do: symbol link handling, cp the link rather than the content - // to-do: file mode, for unix - let fd = read_dir(path, include_hidden)?; - for entry in fd.entries.iter() { - match entry.entry_type.enum_value() { - Ok(FileType::File) => { - let mut entry = entry.clone(); - entry.name = get_string(&prefix.join(entry.name)); - files.push(entry); - } - Ok(FileType::Dir) => { - if let Ok(mut tmp) = read_dir_recursive( - &path.join(&entry.name), - &prefix.join(&entry.name), - include_hidden, - ) { - for entry in tmp.drain(0..) { - files.push(entry); - } - } - } - _ => {} - } - } - Ok(files) - } else if path.is_file() { - let (size, modified_time) = if let Ok(meta) = std::fs::metadata(path) { - ( - meta.len(), - meta.modified() - .map(|x| { - x.duration_since(std::time::SystemTime::UNIX_EPOCH) - .map(|x| x.as_secs()) - .unwrap_or(0) - }) - .unwrap_or(0), - ) - } else { - (0, 0) - }; - files.push(FileEntry { - entry_type: FileType::File.into(), - size, - modified_time, - ..Default::default() - }); - Ok(files) - } else { - bail!("Not exists"); - } -} - -pub fn get_recursive_files(path: &str, include_hidden: bool) -> ResultType> { - read_dir_recursive(&get_path(path), &get_path(""), include_hidden) -} - -#[inline] -pub fn is_file_exists(file_path: &str) -> bool { - return Path::new(file_path).exists(); -} - -#[inline] -pub fn can_enable_overwrite_detection(version: i64) -> bool { - version >= get_version_number("1.1.10") -} - -#[derive(Default)] -pub struct TransferJob { - pub id: i32, - pub remote: String, - pub path: PathBuf, - pub show_hidden: bool, - pub is_remote: bool, - pub is_last_job: bool, - pub file_num: i32, - pub files: Vec, - - file: Option, - total_size: u64, - finished_size: u64, - transferred: u64, - enable_overwrite_detection: bool, - file_confirmed: bool, - // indicating the last file is skipped - file_skipped: bool, - file_is_waiting: bool, - default_overwrite_strategy: Option, -} - -#[derive(Debug, Default, Serialize, Deserialize, Clone)] -pub struct TransferJobMeta { - #[serde(default)] - pub id: i32, - #[serde(default)] - pub remote: String, - #[serde(default)] - pub to: String, - #[serde(default)] - pub show_hidden: bool, - #[serde(default)] - pub file_num: i32, - #[serde(default)] - pub is_remote: bool, -} - -#[derive(Debug, Default, Serialize, Deserialize, Clone)] -pub struct RemoveJobMeta { - #[serde(default)] - pub path: String, - #[serde(default)] - pub is_remote: bool, - #[serde(default)] - pub no_confirm: bool, -} - -#[inline] -fn get_ext(name: &str) -> &str { - if let Some(i) = name.rfind('.') { - return &name[i + 1..]; - } - "" -} - -#[inline] -fn is_compressed_file(name: &str) -> bool { - let ext = get_ext(name); - ext == "xz" - || ext == "gz" - || ext == "zip" - || ext == "7z" - || ext == "rar" - || ext == "bz2" - || ext == "tgz" - || ext == "png" - || ext == "jpg" -} - -impl TransferJob { - #[allow(clippy::too_many_arguments)] - pub fn new_write( - id: i32, - remote: String, - path: String, - file_num: i32, - show_hidden: bool, - is_remote: bool, - files: Vec, - enable_overwrite_detection: bool, - ) -> Self { - log::info!("new write {}", path); - let total_size = files.iter().map(|x| x.size).sum(); - Self { - id, - remote, - path: get_path(&path), - file_num, - show_hidden, - is_remote, - files, - total_size, - enable_overwrite_detection, - ..Default::default() - } - } - - pub fn new_read( - id: i32, - remote: String, - path: String, - file_num: i32, - show_hidden: bool, - is_remote: bool, - enable_overwrite_detection: bool, - ) -> ResultType { - log::info!("new read {}", path); - let files = get_recursive_files(&path, show_hidden)?; - let total_size = files.iter().map(|x| x.size).sum(); - Ok(Self { - id, - remote, - path: get_path(&path), - file_num, - show_hidden, - is_remote, - files, - total_size, - enable_overwrite_detection, - ..Default::default() - }) - } - - #[inline] - pub fn files(&self) -> &Vec { - &self.files - } - - #[inline] - pub fn set_files(&mut self, files: Vec) { - self.files = files; - } - - #[inline] - pub fn id(&self) -> i32 { - self.id - } - - #[inline] - pub fn total_size(&self) -> u64 { - self.total_size - } - - #[inline] - pub fn finished_size(&self) -> u64 { - self.finished_size - } - - #[inline] - pub fn transferred(&self) -> u64 { - self.transferred - } - - #[inline] - pub fn file_num(&self) -> i32 { - self.file_num - } - - pub fn modify_time(&self) { - let file_num = self.file_num as usize; - if file_num < self.files.len() { - let entry = &self.files[file_num]; - let path = self.join(&entry.name); - let download_path = format!("{}.download", get_string(&path)); - std::fs::rename(download_path, &path).ok(); - filetime::set_file_mtime( - &path, - filetime::FileTime::from_unix_time(entry.modified_time as _, 0), - ) - .ok(); - } - } - - pub fn remove_download_file(&self) { - let file_num = self.file_num as usize; - if file_num < self.files.len() { - let entry = &self.files[file_num]; - let path = self.join(&entry.name); - let download_path = format!("{}.download", get_string(&path)); - std::fs::remove_file(download_path).ok(); - } - } - - pub async fn write(&mut self, block: FileTransferBlock) -> ResultType<()> { - if block.id != self.id { - bail!("Wrong id"); - } - let file_num = block.file_num as usize; - if file_num >= self.files.len() { - bail!("Wrong file number"); - } - if file_num != self.file_num as usize || self.file.is_none() { - self.modify_time(); - if let Some(file) = self.file.as_mut() { - file.sync_all().await?; - } - self.file_num = block.file_num; - let entry = &self.files[file_num]; - let path = self.join(&entry.name); - if let Some(p) = path.parent() { - std::fs::create_dir_all(p).ok(); - } - let path = format!("{}.download", get_string(&path)); - self.file = Some(File::create(&path).await?); - } - if block.compressed { - let tmp = decompress(&block.data); - self.file.as_mut().unwrap().write_all(&tmp).await?; - self.finished_size += tmp.len() as u64; - } else { - self.file.as_mut().unwrap().write_all(&block.data).await?; - self.finished_size += block.data.len() as u64; - } - self.transferred += block.data.len() as u64; - Ok(()) - } - - #[inline] - pub fn join(&self, name: &str) -> PathBuf { - if name.is_empty() { - self.path.clone() - } else { - self.path.join(name) - } - } - - pub async fn read(&mut self, stream: &mut Stream) -> ResultType> { - let file_num = self.file_num as usize; - if file_num >= self.files.len() { - self.file.take(); - return Ok(None); - } - let name = &self.files[file_num].name; - if self.file.is_none() { - match File::open(self.join(name)).await { - Ok(file) => { - self.file = Some(file); - self.file_confirmed = false; - self.file_is_waiting = false; - } - Err(err) => { - self.file_num += 1; - self.file_confirmed = false; - self.file_is_waiting = false; - return Err(err.into()); - } - } - } - if self.enable_overwrite_detection && !self.file_confirmed() { - if !self.file_is_waiting() { - self.send_current_digest(stream).await?; - self.set_file_is_waiting(true); - } - return Ok(None); - } - const BUF_SIZE: usize = 128 * 1024; - let mut buf: Vec = vec![0; BUF_SIZE]; - let mut compressed = false; - let mut offset: usize = 0; - loop { - match self.file.as_mut().unwrap().read(&mut buf[offset..]).await { - Err(err) => { - self.file_num += 1; - self.file = None; - self.file_confirmed = false; - self.file_is_waiting = false; - return Err(err.into()); - } - Ok(n) => { - offset += n; - if n == 0 || offset == BUF_SIZE { - break; - } - } - } - } - unsafe { buf.set_len(offset) }; - if offset == 0 { - self.file_num += 1; - self.file = None; - self.file_confirmed = false; - self.file_is_waiting = false; - } else { - self.finished_size += offset as u64; - if !is_compressed_file(name) { - let tmp = compress(&buf, COMPRESS_LEVEL); - if tmp.len() < buf.len() { - buf = tmp; - compressed = true; - } - } - self.transferred += buf.len() as u64; - } - Ok(Some(FileTransferBlock { - id: self.id, - file_num: file_num as _, - data: buf.into(), - compressed, - ..Default::default() - })) - } - - async fn send_current_digest(&mut self, stream: &mut Stream) -> ResultType<()> { - let mut msg = Message::new(); - let mut resp = FileResponse::new(); - let meta = self.file.as_ref().unwrap().metadata().await?; - let last_modified = meta - .modified()? - .duration_since(SystemTime::UNIX_EPOCH)? - .as_secs(); - resp.set_digest(FileTransferDigest { - id: self.id, - file_num: self.file_num, - last_modified, - file_size: meta.len(), - ..Default::default() - }); - msg.set_file_response(resp); - stream.send(&msg).await?; - log::info!( - "id: {}, file_num:{}, digest message is sent. waiting for confirm. msg: {:?}", - self.id, - self.file_num, - msg - ); - Ok(()) - } - - pub fn set_overwrite_strategy(&mut self, overwrite_strategy: Option) { - self.default_overwrite_strategy = overwrite_strategy; - } - - pub fn default_overwrite_strategy(&self) -> Option { - self.default_overwrite_strategy - } - - pub fn set_file_confirmed(&mut self, file_confirmed: bool) { - log::info!("id: {}, file_confirmed: {}", self.id, file_confirmed); - self.file_confirmed = file_confirmed; - self.file_skipped = false; - } - - pub fn set_file_is_waiting(&mut self, file_is_waiting: bool) { - self.file_is_waiting = file_is_waiting; - } - - #[inline] - pub fn file_is_waiting(&self) -> bool { - self.file_is_waiting - } - - #[inline] - pub fn file_confirmed(&self) -> bool { - self.file_confirmed - } - - /// Indicating whether the last file is skipped - #[inline] - pub fn file_skipped(&self) -> bool { - self.file_skipped - } - - /// Indicating whether the whole task is skipped - #[inline] - pub fn job_skipped(&self) -> bool { - self.file_skipped() && self.files.len() == 1 - } - - /// Check whether the job is completed after `read` returns `None` - /// This is a helper function which gives additional lifecycle when the job reads `None`. - /// If returns `true`, it means we can delete the job automatically. `False` otherwise. - /// - /// [`Note`] - /// Conditions: - /// 1. Files are not waiting for confirmation by peers. - #[inline] - pub fn job_completed(&self) -> bool { - // has no error, Condition 2 - !self.enable_overwrite_detection || (!self.file_confirmed && !self.file_is_waiting) - } - - /// Get job error message, useful for getting status when job had finished - pub fn job_error(&self) -> Option { - if self.job_skipped() { - return Some("skipped".to_string()); - } - None - } - - pub fn set_file_skipped(&mut self) -> bool { - log::debug!("skip file {} in job {}", self.file_num, self.id); - self.file.take(); - self.set_file_confirmed(false); - self.set_file_is_waiting(false); - self.file_num += 1; - self.file_skipped = true; - true - } - - pub fn confirm(&mut self, r: &FileTransferSendConfirmRequest) -> bool { - if self.file_num() != r.file_num { - log::info!("file num truncated, ignoring"); - } else { - match r.union { - Some(file_transfer_send_confirm_request::Union::Skip(s)) => { - if s { - self.set_file_skipped(); - } else { - self.set_file_confirmed(true); - } - } - Some(file_transfer_send_confirm_request::Union::OffsetBlk(_offset)) => { - self.set_file_confirmed(true); - } - _ => {} - } - } - true - } - - #[inline] - pub fn gen_meta(&self) -> TransferJobMeta { - TransferJobMeta { - id: self.id, - remote: self.remote.to_string(), - to: self.path.to_string_lossy().to_string(), - file_num: self.file_num, - show_hidden: self.show_hidden, - is_remote: self.is_remote, - } - } -} - -#[inline] -pub fn new_error(id: i32, err: T, file_num: i32) -> Message { - let mut resp = FileResponse::new(); - resp.set_error(FileTransferError { - id, - error: err.to_string(), - file_num, - ..Default::default() - }); - let mut msg_out = Message::new(); - msg_out.set_file_response(resp); - msg_out -} - -#[inline] -pub fn new_dir(id: i32, path: String, files: Vec) -> Message { - let mut resp = FileResponse::new(); - resp.set_dir(FileDirectory { - id, - path, - entries: files, - ..Default::default() - }); - let mut msg_out = Message::new(); - msg_out.set_file_response(resp); - msg_out -} - -#[inline] -pub fn new_block(block: FileTransferBlock) -> Message { - let mut resp = FileResponse::new(); - resp.set_block(block); - let mut msg_out = Message::new(); - msg_out.set_file_response(resp); - msg_out -} - -#[inline] -pub fn new_send_confirm(r: FileTransferSendConfirmRequest) -> Message { - let mut msg_out = Message::new(); - let mut action = FileAction::new(); - action.set_send_confirm(r); - msg_out.set_file_action(action); - msg_out -} - -#[inline] -pub fn new_receive(id: i32, path: String, file_num: i32, files: Vec) -> Message { - let mut action = FileAction::new(); - action.set_receive(FileTransferReceiveRequest { - id, - path, - files, - file_num, - ..Default::default() - }); - let mut msg_out = Message::new(); - msg_out.set_file_action(action); - msg_out -} - -#[inline] -pub fn new_send(id: i32, path: String, file_num: i32, include_hidden: bool) -> Message { - log::info!("new send: {},id : {}", path, id); - let mut action = FileAction::new(); - action.set_send(FileTransferSendRequest { - id, - path, - include_hidden, - file_num, - ..Default::default() - }); - let mut msg_out = Message::new(); - msg_out.set_file_action(action); - msg_out -} - -#[inline] -pub fn new_done(id: i32, file_num: i32) -> Message { - let mut resp = FileResponse::new(); - resp.set_done(FileTransferDone { - id, - file_num, - ..Default::default() - }); - let mut msg_out = Message::new(); - msg_out.set_file_response(resp); - msg_out -} - -#[inline] -pub fn remove_job(id: i32, jobs: &mut Vec) { - *jobs = jobs.drain(0..).filter(|x| x.id() != id).collect(); -} - -#[inline] -pub fn get_job(id: i32, jobs: &mut [TransferJob]) -> Option<&mut TransferJob> { - jobs.iter_mut().find(|x| x.id() == id) -} - -pub async fn handle_read_jobs( - jobs: &mut Vec, - stream: &mut crate::Stream, -) -> ResultType<()> { - let mut finished = Vec::new(); - for job in jobs.iter_mut() { - if job.is_last_job { - continue; - } - match job.read(stream).await { - Err(err) => { - stream - .send(&new_error(job.id(), err, job.file_num())) - .await?; - } - Ok(Some(block)) => { - stream.send(&new_block(block)).await?; - } - Ok(None) => { - if job.job_completed() { - finished.push(job.id()); - let err = job.job_error(); - if err.is_some() { - stream - .send(&new_error(job.id(), err.unwrap(), job.file_num())) - .await?; - } else { - stream.send(&new_done(job.id(), job.file_num())).await?; - } - } else { - // waiting confirmation. - } - } - } - } - for id in finished { - remove_job(id, jobs); - } - Ok(()) -} - -pub fn remove_all_empty_dir(path: &PathBuf) -> ResultType<()> { - let fd = read_dir(path, true)?; - for entry in fd.entries.iter() { - match entry.entry_type.enum_value() { - Ok(FileType::Dir) => { - remove_all_empty_dir(&path.join(&entry.name)).ok(); - } - Ok(FileType::DirLink) | Ok(FileType::FileLink) => { - std::fs::remove_file(path.join(&entry.name)).ok(); - } - _ => {} - } - } - std::fs::remove_dir(path).ok(); - Ok(()) -} - -#[inline] -pub fn remove_file(file: &str) -> ResultType<()> { - std::fs::remove_file(get_path(file))?; - Ok(()) -} - -#[inline] -pub fn create_dir(dir: &str) -> ResultType<()> { - std::fs::create_dir_all(get_path(dir))?; - Ok(()) -} - -#[inline] -pub fn transform_windows_path(entries: &mut Vec) { - for entry in entries { - entry.name = entry.name.replace('\\', "/"); - } -} - -pub enum DigestCheckResult { - IsSame, - NeedConfirm(FileTransferDigest), - NoSuchFile, -} - -#[inline] -pub fn is_write_need_confirmation( - file_path: &str, - digest: &FileTransferDigest, -) -> ResultType { - let path = Path::new(file_path); - if path.exists() && path.is_file() { - let metadata = std::fs::metadata(path)?; - let modified_time = metadata.modified()?; - let remote_mt = Duration::from_secs(digest.last_modified); - let local_mt = modified_time.duration_since(UNIX_EPOCH)?; - if remote_mt == local_mt && digest.file_size == metadata.len() { - return Ok(DigestCheckResult::IsSame); - } - Ok(DigestCheckResult::NeedConfirm(FileTransferDigest { - id: digest.id, - file_num: digest.file_num, - last_modified: local_mt.as_secs(), - file_size: metadata.len(), - ..Default::default() - })) - } else { - Ok(DigestCheckResult::NoSuchFile) - } -} diff --git a/libs/hbb_common/src/keyboard.rs b/libs/hbb_common/src/keyboard.rs deleted file mode 100644 index 224f567..0000000 --- a/libs/hbb_common/src/keyboard.rs +++ /dev/null @@ -1,39 +0,0 @@ -use std::{fmt, slice::Iter, str::FromStr}; - -use crate::protos::message::KeyboardMode; - -impl fmt::Display for KeyboardMode { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - KeyboardMode::Legacy => write!(f, "legacy"), - KeyboardMode::Map => write!(f, "map"), - KeyboardMode::Translate => write!(f, "translate"), - KeyboardMode::Auto => write!(f, "auto"), - } - } -} - -impl FromStr for KeyboardMode { - type Err = (); - fn from_str(s: &str) -> Result { - match s { - "legacy" => Ok(KeyboardMode::Legacy), - "map" => Ok(KeyboardMode::Map), - "translate" => Ok(KeyboardMode::Translate), - "auto" => Ok(KeyboardMode::Auto), - _ => Err(()), - } - } -} - -impl KeyboardMode { - pub fn iter() -> Iter<'static, KeyboardMode> { - const KEYBOARD_MODES: [KeyboardMode; 4] = [ - KeyboardMode::Legacy, - KeyboardMode::Map, - KeyboardMode::Translate, - KeyboardMode::Auto, - ]; - KEYBOARD_MODES.iter() - } -} diff --git a/libs/hbb_common/src/lib.rs b/libs/hbb_common/src/lib.rs deleted file mode 100644 index cf1e45e..0000000 --- a/libs/hbb_common/src/lib.rs +++ /dev/null @@ -1,390 +0,0 @@ -pub mod compress; -pub mod protos; -pub use bytes; -use config::Config; -pub use futures; -pub use protobuf; -pub use protos::message as message_proto; -pub use protos::rendezvous as rendezvous_proto; -use std::{ - fs::File, - io::{self, BufRead}, - net::{IpAddr, Ipv4Addr, SocketAddr, SocketAddrV4}, - path::Path, - time::{self, SystemTime, UNIX_EPOCH}, -}; -pub use tokio; -pub use tokio_util; -pub mod socket_client; -pub mod tcp; -pub mod udp; -pub use env_logger; -pub use log; -pub mod bytes_codec; -#[cfg(feature = "quic")] -pub mod quic; -pub use anyhow::{self, bail}; -pub use futures_util; -pub mod config; -pub mod fs; -pub use lazy_static; -#[cfg(not(any(target_os = "android", target_os = "ios")))] -pub use mac_address; -pub use rand; -pub use regex; -pub use sodiumoxide; -pub use tokio_socks; -pub use tokio_socks::IntoTargetAddr; -pub use tokio_socks::TargetAddr; -pub mod password_security; -pub use chrono; -pub use directories_next; -pub mod keyboard; - -#[cfg(feature = "quic")] -pub type Stream = quic::Connection; -#[cfg(not(feature = "quic"))] -pub type Stream = tcp::FramedStream; - -#[inline] -pub async fn sleep(sec: f32) { - tokio::time::sleep(time::Duration::from_secs_f32(sec)).await; -} - -#[macro_export] -macro_rules! allow_err { - ($e:expr) => { - if let Err(err) = $e { - log::debug!( - "{:?}, {}:{}:{}:{}", - err, - module_path!(), - file!(), - line!(), - column!() - ); - } else { - } - }; - - ($e:expr, $($arg:tt)*) => { - if let Err(err) = $e { - log::debug!( - "{:?}, {}, {}:{}:{}:{}", - err, - format_args!($($arg)*), - module_path!(), - file!(), - line!(), - column!() - ); - } else { - } - }; -} - -#[inline] -pub fn timeout(ms: u64, future: T) -> tokio::time::Timeout { - tokio::time::timeout(std::time::Duration::from_millis(ms), future) -} - -pub type ResultType = anyhow::Result; - -/// Certain router and firewalls scan the packet and if they -/// find an IP address belonging to their pool that they use to do the NAT mapping/translation, so here we mangle the ip address - -pub struct AddrMangle(); - -#[inline] -pub fn try_into_v4(addr: SocketAddr) -> SocketAddr { - match addr { - SocketAddr::V6(v6) if !addr.ip().is_loopback() => { - if let Some(v4) = v6.ip().to_ipv4() { - SocketAddr::new(IpAddr::V4(v4), addr.port()) - } else { - addr - } - } - _ => addr, - } -} - -impl AddrMangle { - pub fn encode(addr: SocketAddr) -> Vec { - // not work with [:1]: - let addr = try_into_v4(addr); - match addr { - SocketAddr::V4(addr_v4) => { - let tm = (SystemTime::now() - .duration_since(UNIX_EPOCH) - .unwrap() - .as_micros() as u32) as u128; - let ip = u32::from_le_bytes(addr_v4.ip().octets()) as u128; - let port = addr.port() as u128; - let v = ((ip + tm) << 49) | (tm << 17) | (port + (tm & 0xFFFF)); - let bytes = v.to_le_bytes(); - let mut n_padding = 0; - for i in bytes.iter().rev() { - if i == &0u8 { - n_padding += 1; - } else { - break; - } - } - bytes[..(16 - n_padding)].to_vec() - } - SocketAddr::V6(addr_v6) => { - let mut x = addr_v6.ip().octets().to_vec(); - let port: [u8; 2] = addr_v6.port().to_le_bytes(); - x.push(port[0]); - x.push(port[1]); - x - } - } - } - - pub fn decode(bytes: &[u8]) -> SocketAddr { - use std::convert::TryInto; - - if bytes.len() > 16 { - if bytes.len() != 18 { - return Config::get_any_listen_addr(false); - } - let tmp: [u8; 2] = bytes[16..].try_into().unwrap(); - let port = u16::from_le_bytes(tmp); - let tmp: [u8; 16] = bytes[..16].try_into().unwrap(); - let ip = std::net::Ipv6Addr::from(tmp); - return SocketAddr::new(IpAddr::V6(ip), port); - } - let mut padded = [0u8; 16]; - padded[..bytes.len()].copy_from_slice(bytes); - let number = u128::from_le_bytes(padded); - let tm = (number >> 17) & (u32::max_value() as u128); - let ip = (((number >> 49) - tm) as u32).to_le_bytes(); - let port = (number & 0xFFFFFF) - (tm & 0xFFFF); - SocketAddr::V4(SocketAddrV4::new( - Ipv4Addr::new(ip[0], ip[1], ip[2], ip[3]), - port as u16, - )) - } -} - -pub fn get_version_from_url(url: &str) -> String { - let n = url.chars().count(); - let a = url.chars().rev().position(|x| x == '-'); - if let Some(a) = a { - let b = url.chars().rev().position(|x| x == '.'); - if let Some(b) = b { - if a > b { - if url - .chars() - .skip(n - b) - .collect::() - .parse::() - .is_ok() - { - return url.chars().skip(n - a).collect(); - } else { - return url.chars().skip(n - a).take(a - b - 1).collect(); - } - } else { - return url.chars().skip(n - a).collect(); - } - } - } - "".to_owned() -} - -pub fn gen_version() { - println!("cargo:rerun-if-changed=Cargo.toml"); - use std::io::prelude::*; - let mut file = File::create("./src/version.rs").unwrap(); - for line in read_lines("Cargo.toml").unwrap().flatten() { - let ab: Vec<&str> = line.split('=').map(|x| x.trim()).collect(); - if ab.len() == 2 && ab[0] == "version" { - file.write_all(format!("pub const VERSION: &str = {};\n", ab[1]).as_bytes()) - .ok(); - break; - } - } - // generate build date - let build_date = format!("{}", chrono::Local::now().format("%Y-%m-%d %H:%M")); - file.write_all( - format!("#[allow(dead_code)]\npub const BUILD_DATE: &str = \"{build_date}\";\n").as_bytes(), - ) - .ok(); - file.sync_all().ok(); -} - -fn read_lines

(filename: P) -> io::Result>> -where - P: AsRef, -{ - let file = File::open(filename)?; - Ok(io::BufReader::new(file).lines()) -} - -pub fn is_valid_custom_id(id: &str) -> bool { - regex::Regex::new(r"^[a-zA-Z]\w{5,15}$") - .unwrap() - .is_match(id) -} - -pub fn get_version_number(v: &str) -> i64 { - let mut n = 0; - for x in v.split('.') { - n = n * 1000 + x.parse::().unwrap_or(0); - } - n -} - -pub fn get_modified_time(path: &std::path::Path) -> SystemTime { - std::fs::metadata(path) - .map(|m| m.modified().unwrap_or(UNIX_EPOCH)) - .unwrap_or(UNIX_EPOCH) -} - -pub fn get_created_time(path: &std::path::Path) -> SystemTime { - std::fs::metadata(path) - .map(|m| m.created().unwrap_or(UNIX_EPOCH)) - .unwrap_or(UNIX_EPOCH) -} - -pub fn get_exe_time() -> SystemTime { - std::env::current_exe().map_or(UNIX_EPOCH, |path| { - let m = get_modified_time(&path); - let c = get_created_time(&path); - if m > c { - m - } else { - c - } - }) -} - -pub fn get_uuid() -> Vec { - #[cfg(not(any(target_os = "android", target_os = "ios")))] - if let Ok(id) = machine_uid::get() { - return id.into(); - } - Config::get_key_pair().1 -} - -#[inline] -pub fn get_time() -> i64 { - std::time::SystemTime::now() - .duration_since(std::time::UNIX_EPOCH) - .map(|d| d.as_millis()) - .unwrap_or(0) as _ -} - -#[inline] -pub fn is_ipv4_str(id: &str) -> bool { - regex::Regex::new(r"^\d+\.\d+\.\d+\.\d+(:\d+)?$") - .unwrap() - .is_match(id) -} - -#[inline] -pub fn is_ipv6_str(id: &str) -> bool { - regex::Regex::new(r"^((([a-fA-F0-9]{1,4}:{1,2})+[a-fA-F0-9]{1,4})|(\[([a-fA-F0-9]{1,4}:{1,2})+[a-fA-F0-9]{1,4}\]:\d+))$") - .unwrap() - .is_match(id) -} - -#[inline] -pub fn is_ip_str(id: &str) -> bool { - is_ipv4_str(id) || is_ipv6_str(id) -} - -#[inline] -pub fn is_domain_port_str(id: &str) -> bool { - // modified regex for RFC1123 hostname. check https://stackoverflow.com/a/106223 for original version for hostname. - // according to [TLD List](https://data.iana.org/TLD/tlds-alpha-by-domain.txt) version 2023011700, - // there is no digits in TLD, and length is 2~63. - regex::Regex::new( - r"(?i)^([a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z][a-z-]{0,61}[a-z]:\d{1,5}$", - ) - .unwrap() - .is_match(id) -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn test_mangle() { - let addr = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(192, 168, 16, 32), 21116)); - assert_eq!(addr, AddrMangle::decode(&AddrMangle::encode(addr))); - - let addr = "[2001:db8::1]:8080".parse::().unwrap(); - assert_eq!(addr, AddrMangle::decode(&AddrMangle::encode(addr))); - - let addr = "[2001:db8:ff::1111]:80".parse::().unwrap(); - assert_eq!(addr, AddrMangle::decode(&AddrMangle::encode(addr))); - } - - #[test] - fn test_allow_err() { - allow_err!(Err("test err") as Result<(), &str>); - allow_err!( - Err("test err with msg") as Result<(), &str>, - "prompt {}", - "failed" - ); - } - - #[test] - fn test_ipv6() { - assert!(is_ipv6_str("1:2:3")); - assert!(is_ipv6_str("[ab:2:3]:12")); - assert!(is_ipv6_str("[ABEF:2a:3]:12")); - assert!(!is_ipv6_str("[ABEG:2a:3]:12")); - assert!(!is_ipv6_str("1[ab:2:3]:12")); - assert!(!is_ipv6_str("1.1.1.1")); - assert!(is_ip_str("1.1.1.1")); - assert!(!is_ipv6_str("1:2:")); - assert!(is_ipv6_str("1:2::0")); - assert!(is_ipv6_str("[1:2::0]:1")); - assert!(!is_ipv6_str("[1:2::0]:")); - assert!(!is_ipv6_str("1:2::0]:1")); - } - - #[test] - fn test_hostname_port() { - assert!(!is_domain_port_str("a:12")); - assert!(!is_domain_port_str("a.b.c:12")); - assert!(is_domain_port_str("test.com:12")); - assert!(is_domain_port_str("test-UPPER.com:12")); - assert!(is_domain_port_str("some-other.domain.com:12")); - assert!(!is_domain_port_str("under_score:12")); - assert!(!is_domain_port_str("a@bc:12")); - assert!(!is_domain_port_str("1.1.1.1:12")); - assert!(!is_domain_port_str("1.2.3:12")); - assert!(!is_domain_port_str("1.2.3.45:12")); - assert!(!is_domain_port_str("a.b.c:123456")); - assert!(!is_domain_port_str("---:12")); - assert!(!is_domain_port_str(".:12")); - // todo: should we also check for these edge cases? - // out-of-range port - assert!(is_domain_port_str("test.com:0")); - assert!(is_domain_port_str("test.com:98989")); - } - - #[test] - fn test_mangle2() { - let addr = "[::ffff:127.0.0.1]:8080".parse().unwrap(); - let addr_v4 = "127.0.0.1:8080".parse().unwrap(); - assert_eq!(AddrMangle::decode(&AddrMangle::encode(addr)), addr_v4); - assert_eq!( - AddrMangle::decode(&AddrMangle::encode("[::127.0.0.1]:8080".parse().unwrap())), - addr_v4 - ); - assert_eq!(AddrMangle::decode(&AddrMangle::encode(addr_v4)), addr_v4); - let addr_v6 = "[ef::fe]:8080".parse().unwrap(); - assert_eq!(AddrMangle::decode(&AddrMangle::encode(addr_v6)), addr_v6); - let addr_v6 = "[::1]:8080".parse().unwrap(); - assert_eq!(AddrMangle::decode(&AddrMangle::encode(addr_v6)), addr_v6); - } -} diff --git a/libs/hbb_common/src/password_security.rs b/libs/hbb_common/src/password_security.rs deleted file mode 100644 index ddfe28b..0000000 --- a/libs/hbb_common/src/password_security.rs +++ /dev/null @@ -1,242 +0,0 @@ -use crate::config::Config; -use sodiumoxide::base64; -use std::sync::{Arc, RwLock}; - -lazy_static::lazy_static! { - pub static ref TEMPORARY_PASSWORD:Arc> = Arc::new(RwLock::new(Config::get_auto_password(temporary_password_length()))); -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -enum VerificationMethod { - OnlyUseTemporaryPassword, - OnlyUsePermanentPassword, - UseBothPasswords, -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum ApproveMode { - Both, - Password, - Click, -} - -// Should only be called in server -pub fn update_temporary_password() { - *TEMPORARY_PASSWORD.write().unwrap() = Config::get_auto_password(temporary_password_length()); -} - -// Should only be called in server -pub fn temporary_password() -> String { - TEMPORARY_PASSWORD.read().unwrap().clone() -} - -fn verification_method() -> VerificationMethod { - let method = Config::get_option("verification-method"); - if method == "use-temporary-password" { - VerificationMethod::OnlyUseTemporaryPassword - } else if method == "use-permanent-password" { - VerificationMethod::OnlyUsePermanentPassword - } else { - VerificationMethod::UseBothPasswords // default - } -} - -pub fn temporary_password_length() -> usize { - let length = Config::get_option("temporary-password-length"); - if length == "8" { - 8 - } else if length == "10" { - 10 - } else { - 6 // default - } -} - -pub fn temporary_enabled() -> bool { - verification_method() != VerificationMethod::OnlyUsePermanentPassword -} - -pub fn permanent_enabled() -> bool { - verification_method() != VerificationMethod::OnlyUseTemporaryPassword -} - -pub fn has_valid_password() -> bool { - temporary_enabled() && !temporary_password().is_empty() - || permanent_enabled() && !Config::get_permanent_password().is_empty() -} - -pub fn approve_mode() -> ApproveMode { - let mode = Config::get_option("approve-mode"); - if mode == "password" { - ApproveMode::Password - } else if mode == "click" { - ApproveMode::Click - } else { - ApproveMode::Both - } -} - -pub fn hide_cm() -> bool { - approve_mode() == ApproveMode::Password - && verification_method() == VerificationMethod::OnlyUsePermanentPassword - && !Config::get_option("allow-hide-cm").is_empty() -} - -const VERSION_LEN: usize = 2; - -pub fn encrypt_str_or_original(s: &str, version: &str) -> String { - if decrypt_str_or_original(s, version).1 { - log::error!("Duplicate encryption!"); - return s.to_owned(); - } - if version == "00" { - if let Ok(s) = encrypt(s.as_bytes()) { - return version.to_owned() + &s; - } - } - s.to_owned() -} - -// String: password -// bool: whether decryption is successful -// bool: whether should store to re-encrypt when load -pub fn decrypt_str_or_original(s: &str, current_version: &str) -> (String, bool, bool) { - if s.len() > VERSION_LEN { - let version = &s[..VERSION_LEN]; - if version == "00" { - if let Ok(v) = decrypt(s[VERSION_LEN..].as_bytes()) { - return ( - String::from_utf8_lossy(&v).to_string(), - true, - version != current_version, - ); - } - } - } - - (s.to_owned(), false, !s.is_empty()) -} - -pub fn encrypt_vec_or_original(v: &[u8], version: &str) -> Vec { - if decrypt_vec_or_original(v, version).1 { - log::error!("Duplicate encryption!"); - return v.to_owned(); - } - if version == "00" { - if let Ok(s) = encrypt(v) { - let mut version = version.to_owned().into_bytes(); - version.append(&mut s.into_bytes()); - return version; - } - } - v.to_owned() -} - -// Vec: password -// bool: whether decryption is successful -// bool: whether should store to re-encrypt when load -pub fn decrypt_vec_or_original(v: &[u8], current_version: &str) -> (Vec, bool, bool) { - if v.len() > VERSION_LEN { - let version = String::from_utf8_lossy(&v[..VERSION_LEN]); - if version == "00" { - if let Ok(v) = decrypt(&v[VERSION_LEN..]) { - return (v, true, version != current_version); - } - } - } - - (v.to_owned(), false, !v.is_empty()) -} - -fn encrypt(v: &[u8]) -> Result { - if !v.is_empty() { - symmetric_crypt(v, true).map(|v| base64::encode(v, base64::Variant::Original)) - } else { - Err(()) - } -} - -fn decrypt(v: &[u8]) -> Result, ()> { - if !v.is_empty() { - base64::decode(v, base64::Variant::Original).and_then(|v| symmetric_crypt(&v, false)) - } else { - Err(()) - } -} - -fn symmetric_crypt(data: &[u8], encrypt: bool) -> Result, ()> { - use sodiumoxide::crypto::secretbox; - use std::convert::TryInto; - - let mut keybuf = crate::get_uuid(); - keybuf.resize(secretbox::KEYBYTES, 0); - let key = secretbox::Key(keybuf.try_into().map_err(|_| ())?); - let nonce = secretbox::Nonce([0; secretbox::NONCEBYTES]); - - if encrypt { - Ok(secretbox::seal(data, &nonce, &key)) - } else { - secretbox::open(data, &nonce, &key) - } -} - -mod test { - - #[test] - fn test() { - use super::*; - - let version = "00"; - - println!("test str"); - let data = "Hello World"; - let encrypted = encrypt_str_or_original(data, version); - let (decrypted, succ, store) = decrypt_str_or_original(&encrypted, version); - println!("data: {data}"); - println!("encrypted: {encrypted}"); - println!("decrypted: {decrypted}"); - assert_eq!(data, decrypted); - assert_eq!(version, &encrypted[..2]); - assert!(succ); - assert!(!store); - let (_, _, store) = decrypt_str_or_original(&encrypted, "99"); - assert!(store); - assert!(!decrypt_str_or_original(&decrypted, version).1); - assert_eq!(encrypt_str_or_original(&encrypted, version), encrypted); - - println!("test vec"); - let data: Vec = vec![1, 2, 3, 4, 5, 6]; - let encrypted = encrypt_vec_or_original(&data, version); - let (decrypted, succ, store) = decrypt_vec_or_original(&encrypted, version); - println!("data: {data:?}"); - println!("encrypted: {encrypted:?}"); - println!("decrypted: {decrypted:?}"); - assert_eq!(data, decrypted); - assert_eq!(version.as_bytes(), &encrypted[..2]); - assert!(!store); - assert!(succ); - let (_, _, store) = decrypt_vec_or_original(&encrypted, "99"); - assert!(store); - assert!(!decrypt_vec_or_original(&decrypted, version).1); - assert_eq!(encrypt_vec_or_original(&encrypted, version), encrypted); - - println!("test original"); - let data = version.to_string() + "Hello World"; - let (decrypted, succ, store) = decrypt_str_or_original(&data, version); - assert_eq!(data, decrypted); - assert!(store); - assert!(!succ); - let verbytes = version.as_bytes(); - let data: Vec = vec![verbytes[0], verbytes[1], 1, 2, 3, 4, 5, 6]; - let (decrypted, succ, store) = decrypt_vec_or_original(&data, version); - assert_eq!(data, decrypted); - assert!(store); - assert!(!succ); - let (_, succ, store) = decrypt_str_or_original("", version); - assert!(!store); - assert!(!succ); - let (_, succ, store) = decrypt_vec_or_original(&[], version); - assert!(!store); - assert!(!succ); - } -} diff --git a/libs/hbb_common/src/protos/mod.rs b/libs/hbb_common/src/protos/mod.rs deleted file mode 100644 index 57d9b68..0000000 --- a/libs/hbb_common/src/protos/mod.rs +++ /dev/null @@ -1 +0,0 @@ -include!(concat!(env!("OUT_DIR"), "/protos/mod.rs")); diff --git a/libs/hbb_common/src/quic.rs b/libs/hbb_common/src/quic.rs deleted file mode 100644 index ada2acd..0000000 --- a/libs/hbb_common/src/quic.rs +++ /dev/null @@ -1,135 +0,0 @@ -use crate::{allow_err, anyhow::anyhow, ResultType}; -use protobuf::Message; -use std::{net::SocketAddr, sync::Arc}; -use tokio::{self, stream::StreamExt, sync::mpsc}; - -const QUIC_HBB: &[&[u8]] = &[b"hbb"]; -const SERVER_NAME: &str = "hbb"; - -type Sender = mpsc::UnboundedSender; -type Receiver = mpsc::UnboundedReceiver; - -pub fn new_server(socket: std::net::UdpSocket) -> ResultType<(Server, SocketAddr)> { - let mut transport_config = quinn::TransportConfig::default(); - transport_config.stream_window_uni(0); - let mut server_config = quinn::ServerConfig::default(); - server_config.transport = Arc::new(transport_config); - let mut server_config = quinn::ServerConfigBuilder::new(server_config); - server_config.protocols(QUIC_HBB); - // server_config.enable_keylog(); - // server_config.use_stateless_retry(true); - let mut endpoint = quinn::Endpoint::builder(); - endpoint.listen(server_config.build()); - let (end, incoming) = endpoint.with_socket(socket)?; - Ok((Server { incoming }, end.local_addr()?)) -} - -pub async fn new_client(local_addr: &SocketAddr, peer: &SocketAddr) -> ResultType { - let mut endpoint = quinn::Endpoint::builder(); - let mut client_config = quinn::ClientConfigBuilder::default(); - client_config.protocols(QUIC_HBB); - //client_config.enable_keylog(); - endpoint.default_client_config(client_config.build()); - let (endpoint, _) = endpoint.bind(local_addr)?; - let new_conn = endpoint.connect(peer, SERVER_NAME)?.await?; - Connection::new_for_client(new_conn.connection).await -} - -pub struct Server { - incoming: quinn::Incoming, -} - -impl Server { - #[inline] - pub async fn next(&mut self) -> ResultType> { - Connection::new_for_server(&mut self.incoming).await - } -} - -pub struct Connection { - conn: quinn::Connection, - tx: quinn::SendStream, - rx: Receiver, -} - -type Value = ResultType>; - -impl Connection { - async fn new_for_server(incoming: &mut quinn::Incoming) -> ResultType> { - if let Some(conn) = incoming.next().await { - let quinn::NewConnection { - connection: conn, - // uni_streams, - mut bi_streams, - .. - } = conn.await?; - let (tx, rx) = mpsc::unbounded_channel::(); - tokio::spawn(async move { - loop { - let stream = bi_streams.next().await; - if let Some(stream) = stream { - let stream = match stream { - Err(e) => { - tx.send(Err(e.into())).ok(); - break; - } - Ok(s) => s, - }; - let cloned = tx.clone(); - tokio::spawn(async move { - allow_err!(handle_request(stream.1, cloned).await); - }); - } else { - tx.send(Err(anyhow!("Reset by the peer"))).ok(); - break; - } - } - log::info!("Exit connection outer loop"); - }); - let tx = conn.open_uni().await?; - Ok(Some(Self { conn, tx, rx })) - } else { - Ok(None) - } - } - - async fn new_for_client(conn: quinn::Connection) -> ResultType { - let (tx, rx_quic) = conn.open_bi().await?; - let (tx_mpsc, rx) = mpsc::unbounded_channel::(); - tokio::spawn(async move { - allow_err!(handle_request(rx_quic, tx_mpsc).await); - }); - Ok(Self { conn, tx, rx }) - } - - #[inline] - pub async fn next(&mut self) -> Option { - // None is returned when all Sender halves have dropped, - // indicating that no further values can be sent on the channel. - self.rx.recv().await - } - - #[inline] - pub fn remote_address(&self) -> SocketAddr { - self.conn.remote_address() - } - - #[inline] - pub async fn send_raw(&mut self, bytes: &[u8]) -> ResultType<()> { - self.tx.write_all(bytes).await?; - Ok(()) - } - - #[inline] - pub async fn send(&mut self, msg: &dyn Message) -> ResultType<()> { - match msg.write_to_bytes() { - Ok(bytes) => self.send_raw(&bytes).await?, - err => allow_err!(err), - } - Ok(()) - } -} - -async fn handle_request(rx: quinn::RecvStream, tx: Sender) -> ResultType<()> { - Ok(()) -} diff --git a/libs/hbb_common/src/socket_client.rs b/libs/hbb_common/src/socket_client.rs deleted file mode 100644 index 2d9b5a9..0000000 --- a/libs/hbb_common/src/socket_client.rs +++ /dev/null @@ -1,281 +0,0 @@ -use crate::{ - config::{Config, NetworkType}, - tcp::FramedStream, - udp::FramedSocket, - ResultType, -}; -use anyhow::Context; -use std::net::SocketAddr; -use tokio::net::ToSocketAddrs; -use tokio_socks::{IntoTargetAddr, TargetAddr}; - -#[inline] -pub fn check_port(host: T, port: i32) -> String { - let host = host.to_string(); - if crate::is_ipv6_str(&host) { - if host.starts_with('[') { - return host; - } - return format!("[{host}]:{port}"); - } - if !host.contains(':') { - return format!("{host}:{port}"); - } - host -} - -#[inline] -pub fn increase_port(host: T, offset: i32) -> String { - let host = host.to_string(); - if crate::is_ipv6_str(&host) { - if host.starts_with('[') { - let tmp: Vec<&str> = host.split("]:").collect(); - if tmp.len() == 2 { - let port: i32 = tmp[1].parse().unwrap_or(0); - if port > 0 { - return format!("{}]:{}", tmp[0], port + offset); - } - } - } - } else if host.contains(':') { - let tmp: Vec<&str> = host.split(':').collect(); - if tmp.len() == 2 { - let port: i32 = tmp[1].parse().unwrap_or(0); - if port > 0 { - return format!("{}:{}", tmp[0], port + offset); - } - } - } - host -} - -pub fn test_if_valid_server(host: &str) -> String { - let host = check_port(host, 0); - - use std::net::ToSocketAddrs; - match Config::get_network_type() { - NetworkType::Direct => match host.to_socket_addrs() { - Err(err) => err.to_string(), - Ok(_) => "".to_owned(), - }, - NetworkType::ProxySocks => match &host.into_target_addr() { - Err(err) => err.to_string(), - Ok(_) => "".to_owned(), - }, - } -} - -pub trait IsResolvedSocketAddr { - fn resolve(&self) -> Option<&SocketAddr>; -} - -impl IsResolvedSocketAddr for SocketAddr { - fn resolve(&self) -> Option<&SocketAddr> { - Some(self) - } -} - -impl IsResolvedSocketAddr for String { - fn resolve(&self) -> Option<&SocketAddr> { - None - } -} - -impl IsResolvedSocketAddr for &str { - fn resolve(&self) -> Option<&SocketAddr> { - None - } -} - -#[inline] -pub async fn connect_tcp< - 't, - T: IntoTargetAddr<'t> + ToSocketAddrs + IsResolvedSocketAddr + std::fmt::Display, ->( - target: T, - ms_timeout: u64, -) -> ResultType { - connect_tcp_local(target, None, ms_timeout).await -} - -pub async fn connect_tcp_local< - 't, - T: IntoTargetAddr<'t> + ToSocketAddrs + IsResolvedSocketAddr + std::fmt::Display, ->( - target: T, - local: Option, - ms_timeout: u64, -) -> ResultType { - if let Some(conf) = Config::get_socks() { - return FramedStream::connect( - conf.proxy.as_str(), - target, - local, - conf.username.as_str(), - conf.password.as_str(), - ms_timeout, - ) - .await; - } - if let Some(target) = target.resolve() { - if let Some(local) = local { - if local.is_ipv6() && target.is_ipv4() { - let target = query_nip_io(target).await?; - return FramedStream::new(target, Some(local), ms_timeout).await; - } - } - } - FramedStream::new(target, local, ms_timeout).await -} - -#[inline] -pub fn is_ipv4(target: &TargetAddr<'_>) -> bool { - match target { - TargetAddr::Ip(addr) => addr.is_ipv4(), - _ => true, - } -} - -#[inline] -pub async fn query_nip_io(addr: &SocketAddr) -> ResultType { - tokio::net::lookup_host(format!("{}.nip.io:{}", addr.ip(), addr.port())) - .await? - .find(|x| x.is_ipv6()) - .context("Failed to get ipv6 from nip.io") -} - -#[inline] -pub fn ipv4_to_ipv6(addr: String, ipv4: bool) -> String { - if !ipv4 && crate::is_ipv4_str(&addr) { - if let Some(ip) = addr.split(':').next() { - return addr.replace(ip, &format!("{ip}.nip.io")); - } - } - addr -} - -async fn test_target(target: &str) -> ResultType { - if let Ok(Ok(s)) = super::timeout(1000, tokio::net::TcpStream::connect(target)).await { - if let Ok(addr) = s.peer_addr() { - return Ok(addr); - } - } - tokio::net::lookup_host(target) - .await? - .next() - .context(format!("Failed to look up host for {target}")) -} - -#[inline] -pub async fn new_udp_for( - target: &str, - ms_timeout: u64, -) -> ResultType<(FramedSocket, TargetAddr<'static>)> { - let (ipv4, target) = if NetworkType::Direct == Config::get_network_type() { - let addr = test_target(target).await?; - (addr.is_ipv4(), addr.into_target_addr()?) - } else { - (true, target.into_target_addr()?) - }; - Ok(( - new_udp(Config::get_any_listen_addr(ipv4), ms_timeout).await?, - target.to_owned(), - )) -} - -async fn new_udp(local: T, ms_timeout: u64) -> ResultType { - match Config::get_socks() { - None => Ok(FramedSocket::new(local).await?), - Some(conf) => { - let socket = FramedSocket::new_proxy( - conf.proxy.as_str(), - local, - conf.username.as_str(), - conf.password.as_str(), - ms_timeout, - ) - .await?; - Ok(socket) - } - } -} - -pub async fn rebind_udp_for( - target: &str, -) -> ResultType)>> { - if Config::get_network_type() != NetworkType::Direct { - return Ok(None); - } - let addr = test_target(target).await?; - let v4 = addr.is_ipv4(); - Ok(Some(( - FramedSocket::new(Config::get_any_listen_addr(v4)).await?, - addr.into_target_addr()?.to_owned(), - ))) -} - -#[cfg(test)] -mod tests { - use std::net::ToSocketAddrs; - - use super::*; - - #[test] - fn test_nat64() { - test_nat64_async(); - } - - #[tokio::main(flavor = "current_thread")] - async fn test_nat64_async() { - assert_eq!(ipv4_to_ipv6("1.1.1.1".to_owned(), true), "1.1.1.1"); - assert_eq!(ipv4_to_ipv6("1.1.1.1".to_owned(), false), "1.1.1.1.nip.io"); - assert_eq!( - ipv4_to_ipv6("1.1.1.1:8080".to_owned(), false), - "1.1.1.1.nip.io:8080" - ); - assert_eq!( - ipv4_to_ipv6("rustdesk.com".to_owned(), false), - "rustdesk.com" - ); - if ("rustdesk.com:80") - .to_socket_addrs() - .unwrap() - .next() - .unwrap() - .is_ipv6() - { - assert!(query_nip_io(&"1.1.1.1:80".parse().unwrap()) - .await - .unwrap() - .is_ipv6()); - return; - } - assert!(query_nip_io(&"1.1.1.1:80".parse().unwrap()).await.is_err()); - } - - #[test] - fn test_test_if_valid_server() { - assert!(!test_if_valid_server("a").is_empty()); - // on Linux, "1" is resolved to "0.0.0.1" - assert!(test_if_valid_server("1.1.1.1").is_empty()); - assert!(test_if_valid_server("1.1.1.1:1").is_empty()); - } - - #[test] - fn test_check_port() { - assert_eq!(check_port("[1:2]:12", 32), "[1:2]:12"); - assert_eq!(check_port("1:2", 32), "[1:2]:32"); - assert_eq!(check_port("z1:2", 32), "z1:2"); - assert_eq!(check_port("1.1.1.1", 32), "1.1.1.1:32"); - assert_eq!(check_port("1.1.1.1:32", 32), "1.1.1.1:32"); - assert_eq!(check_port("test.com:32", 0), "test.com:32"); - assert_eq!(increase_port("[1:2]:12", 1), "[1:2]:13"); - assert_eq!(increase_port("1.2.2.4:12", 1), "1.2.2.4:13"); - assert_eq!(increase_port("1.2.2.4", 1), "1.2.2.4"); - assert_eq!(increase_port("test.com", 1), "test.com"); - assert_eq!(increase_port("test.com:13", 4), "test.com:17"); - assert_eq!(increase_port("1:13", 4), "1:13"); - assert_eq!(increase_port("22:1:13", 4), "22:1:13"); - assert_eq!(increase_port("z1:2", 1), "z1:3"); - } -} diff --git a/libs/hbb_common/src/tcp.rs b/libs/hbb_common/src/tcp.rs deleted file mode 100644 index e483abf..0000000 --- a/libs/hbb_common/src/tcp.rs +++ /dev/null @@ -1,335 +0,0 @@ -use crate::{bail, bytes_codec::BytesCodec, ResultType}; -use anyhow::Context as AnyhowCtx; -use bytes::{BufMut, Bytes, BytesMut}; -use futures::{SinkExt, StreamExt}; -use protobuf::Message; -use sodiumoxide::crypto::secretbox::{self, Key, Nonce}; -use std::{ - io::{self, Error, ErrorKind}, - net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}, - ops::{Deref, DerefMut}, - pin::Pin, - task::{Context, Poll}, -}; -use tokio::{ - io::{AsyncRead, AsyncWrite, ReadBuf}, - net::{lookup_host, TcpListener, TcpSocket, ToSocketAddrs}, -}; -use tokio_socks::{tcp::Socks5Stream, IntoTargetAddr, ToProxyAddrs}; -use tokio_util::codec::Framed; - -pub trait TcpStreamTrait: AsyncRead + AsyncWrite + Unpin {} -pub struct DynTcpStream(Box); - -pub struct FramedStream( - Framed, - SocketAddr, - Option<(Key, u64, u64)>, - u64, -); - -impl Deref for FramedStream { - type Target = Framed; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl DerefMut for FramedStream { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 - } -} - -impl Deref for DynTcpStream { - type Target = Box; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl DerefMut for DynTcpStream { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 - } -} - -fn new_socket(addr: std::net::SocketAddr, reuse: bool) -> Result { - let socket = match addr { - std::net::SocketAddr::V4(..) => TcpSocket::new_v4()?, - std::net::SocketAddr::V6(..) => TcpSocket::new_v6()?, - }; - if reuse { - // windows has no reuse_port, but its reuse_address - // almost equals to unix's reuse_port + reuse_address, - // though may introduce nondeterministic behavior. - // illumos has no support for SO_REUSEPORT - #[cfg(all(unix, not(target_os = "illumos")))] - socket.set_reuseport(true)?; - socket.set_reuseaddr(true)?; - } - socket.bind(addr)?; - Ok(socket) -} - -impl FramedStream { - pub async fn new( - remote_addr: T, - local_addr: Option, - ms_timeout: u64, - ) -> ResultType { - for remote_addr in lookup_host(&remote_addr).await? { - let local = if let Some(addr) = local_addr { - addr - } else { - crate::config::Config::get_any_listen_addr(remote_addr.is_ipv4()) - }; - if let Ok(socket) = new_socket(local, true) { - if let Ok(Ok(stream)) = - super::timeout(ms_timeout, socket.connect(remote_addr)).await - { - stream.set_nodelay(true).ok(); - let addr = stream.local_addr()?; - return Ok(Self( - Framed::new(DynTcpStream(Box::new(stream)), BytesCodec::new()), - addr, - None, - 0, - )); - } - } - } - bail!(format!("Failed to connect to {remote_addr}")); - } - - pub async fn connect<'a, 't, P, T>( - proxy: P, - target: T, - local_addr: Option, - username: &'a str, - password: &'a str, - ms_timeout: u64, - ) -> ResultType - where - P: ToProxyAddrs, - T: IntoTargetAddr<'t>, - { - if let Some(Ok(proxy)) = proxy.to_proxy_addrs().next().await { - let local = if let Some(addr) = local_addr { - addr - } else { - crate::config::Config::get_any_listen_addr(proxy.is_ipv4()) - }; - let stream = - super::timeout(ms_timeout, new_socket(local, true)?.connect(proxy)).await??; - stream.set_nodelay(true).ok(); - let stream = if username.trim().is_empty() { - super::timeout( - ms_timeout, - Socks5Stream::connect_with_socket(stream, target), - ) - .await?? - } else { - super::timeout( - ms_timeout, - Socks5Stream::connect_with_password_and_socket( - stream, target, username, password, - ), - ) - .await?? - }; - let addr = stream.local_addr()?; - return Ok(Self( - Framed::new(DynTcpStream(Box::new(stream)), BytesCodec::new()), - addr, - None, - 0, - )); - } - bail!("could not resolve to any address"); - } - - pub fn local_addr(&self) -> SocketAddr { - self.1 - } - - pub fn set_send_timeout(&mut self, ms: u64) { - self.3 = ms; - } - - pub fn from(stream: impl TcpStreamTrait + Send + Sync + 'static, addr: SocketAddr) -> Self { - Self( - Framed::new(DynTcpStream(Box::new(stream)), BytesCodec::new()), - addr, - None, - 0, - ) - } - - pub fn set_raw(&mut self) { - self.0.codec_mut().set_raw(); - self.2 = None; - } - - pub fn is_secured(&self) -> bool { - self.2.is_some() - } - - #[inline] - pub async fn send(&mut self, msg: &impl Message) -> ResultType<()> { - self.send_raw(msg.write_to_bytes()?).await - } - - #[inline] - pub async fn send_raw(&mut self, msg: Vec) -> ResultType<()> { - let mut msg = msg; - if let Some(key) = self.2.as_mut() { - key.1 += 1; - let nonce = Self::get_nonce(key.1); - msg = secretbox::seal(&msg, &nonce, &key.0); - } - self.send_bytes(bytes::Bytes::from(msg)).await?; - Ok(()) - } - - #[inline] - pub async fn send_bytes(&mut self, bytes: Bytes) -> ResultType<()> { - if self.3 > 0 { - super::timeout(self.3, self.0.send(bytes)).await??; - } else { - self.0.send(bytes).await?; - } - Ok(()) - } - - #[inline] - pub async fn next(&mut self) -> Option> { - let mut res = self.0.next().await; - if let Some(key) = self.2.as_mut() { - if let Some(Ok(bytes)) = res.as_mut() { - key.2 += 1; - let nonce = Self::get_nonce(key.2); - match secretbox::open(bytes, &nonce, &key.0) { - Ok(res) => { - bytes.clear(); - bytes.put_slice(&res); - } - Err(()) => { - return Some(Err(Error::new(ErrorKind::Other, "decryption error"))); - } - } - } - } - res - } - - #[inline] - pub async fn next_timeout(&mut self, ms: u64) -> Option> { - if let Ok(res) = super::timeout(ms, self.next()).await { - res - } else { - None - } - } - - pub fn set_key(&mut self, key: Key) { - self.2 = Some((key, 0, 0)); - } - - fn get_nonce(seqnum: u64) -> Nonce { - let mut nonce = Nonce([0u8; secretbox::NONCEBYTES]); - nonce.0[..std::mem::size_of_val(&seqnum)].copy_from_slice(&seqnum.to_le_bytes()); - nonce - } -} - -const DEFAULT_BACKLOG: u32 = 128; - -pub async fn new_listener(addr: T, reuse: bool) -> ResultType { - if !reuse { - Ok(TcpListener::bind(addr).await?) - } else { - let addr = lookup_host(&addr) - .await? - .next() - .context("could not resolve to any address")?; - new_socket(addr, true)? - .listen(DEFAULT_BACKLOG) - .map_err(anyhow::Error::msg) - } -} - -pub async fn listen_any(port: u16, reuse: bool) -> ResultType { - if let Ok(mut socket) = TcpSocket::new_v6() { - if reuse { - // windows has no reuse_port, but its reuse_address - // almost equals to unix's reuse_port + reuse_address, - // though may introduce nondeterministic behavior. - // illumos has no support for SO_REUSEPORT - #[cfg(all(unix, not(target_os = "illumos")))] - socket.set_reuseport(true).ok(); - socket.set_reuseaddr(true).ok(); - } - #[cfg(unix)] - { - use std::os::unix::io::{FromRawFd, IntoRawFd}; - let raw_fd = socket.into_raw_fd(); - let sock2 = unsafe { socket2::Socket::from_raw_fd(raw_fd) }; - sock2.set_only_v6(false).ok(); - socket = unsafe { TcpSocket::from_raw_fd(sock2.into_raw_fd()) }; - } - #[cfg(windows)] - { - use std::os::windows::prelude::{FromRawSocket, IntoRawSocket}; - let raw_socket = socket.into_raw_socket(); - let sock2 = unsafe { socket2::Socket::from_raw_socket(raw_socket) }; - sock2.set_only_v6(false).ok(); - socket = unsafe { TcpSocket::from_raw_socket(sock2.into_raw_socket()) }; - } - if socket - .bind(SocketAddr::new(IpAddr::V6(Ipv6Addr::UNSPECIFIED), port)) - .is_ok() - { - if let Ok(l) = socket.listen(DEFAULT_BACKLOG) { - return Ok(l); - } - } - } - let s = TcpSocket::new_v4()?; - s.bind(SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), port))?; - Ok(s.listen(DEFAULT_BACKLOG)?) -} - -impl Unpin for DynTcpStream {} - -impl AsyncRead for DynTcpStream { - fn poll_read( - mut self: Pin<&mut Self>, - cx: &mut Context<'_>, - buf: &mut ReadBuf<'_>, - ) -> Poll> { - AsyncRead::poll_read(Pin::new(&mut self.0), cx, buf) - } -} - -impl AsyncWrite for DynTcpStream { - fn poll_write( - mut self: Pin<&mut Self>, - cx: &mut Context<'_>, - buf: &[u8], - ) -> Poll> { - AsyncWrite::poll_write(Pin::new(&mut self.0), cx, buf) - } - - fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - AsyncWrite::poll_flush(Pin::new(&mut self.0), cx) - } - - fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - AsyncWrite::poll_shutdown(Pin::new(&mut self.0), cx) - } -} - -impl TcpStreamTrait for R {} diff --git a/libs/hbb_common/src/udp.rs b/libs/hbb_common/src/udp.rs deleted file mode 100644 index c18be89..0000000 --- a/libs/hbb_common/src/udp.rs +++ /dev/null @@ -1,171 +0,0 @@ -use crate::ResultType; -use anyhow::{anyhow, Context}; -use bytes::{Bytes, BytesMut}; -use futures::{SinkExt, StreamExt}; -use protobuf::Message; -use socket2::{Domain, Socket, Type}; -use std::net::SocketAddr; -use tokio::net::{lookup_host, ToSocketAddrs, UdpSocket}; -use tokio_socks::{udp::Socks5UdpFramed, IntoTargetAddr, TargetAddr, ToProxyAddrs}; -use tokio_util::{codec::BytesCodec, udp::UdpFramed}; - -pub enum FramedSocket { - Direct(UdpFramed), - ProxySocks(Socks5UdpFramed), -} - -fn new_socket(addr: SocketAddr, reuse: bool, buf_size: usize) -> Result { - let socket = match addr { - SocketAddr::V4(..) => Socket::new(Domain::ipv4(), Type::dgram(), None), - SocketAddr::V6(..) => Socket::new(Domain::ipv6(), Type::dgram(), None), - }?; - if reuse { - // windows has no reuse_port, but its reuse_address - // almost equals to unix's reuse_port + reuse_address, - // though may introduce nondeterministic behavior. - // illumos has no support for SO_REUSEPORT - #[cfg(all(unix, not(target_os = "illumos")))] - socket.set_reuse_port(true)?; - socket.set_reuse_address(true)?; - } - // only nonblocking work with tokio, https://stackoverflow.com/questions/64649405/receiver-on-tokiompscchannel-only-receives-messages-when-buffer-is-full - socket.set_nonblocking(true)?; - if buf_size > 0 { - socket.set_recv_buffer_size(buf_size).ok(); - } - log::info!( - "Receive buf size of udp {}: {:?}", - addr, - socket.recv_buffer_size() - ); - if addr.is_ipv6() && addr.ip().is_unspecified() && addr.port() > 0 { - socket.set_only_v6(false).ok(); - } - socket.bind(&addr.into())?; - Ok(socket) -} - -impl FramedSocket { - pub async fn new(addr: T) -> ResultType { - Self::new_reuse(addr, false, 0).await - } - - pub async fn new_reuse( - addr: T, - reuse: bool, - buf_size: usize, - ) -> ResultType { - let addr = lookup_host(&addr) - .await? - .next() - .context("could not resolve to any address")?; - Ok(Self::Direct(UdpFramed::new( - UdpSocket::from_std(new_socket(addr, reuse, buf_size)?.into_udp_socket())?, - BytesCodec::new(), - ))) - } - - pub async fn new_proxy<'a, 't, P: ToProxyAddrs, T: ToSocketAddrs>( - proxy: P, - local: T, - username: &'a str, - password: &'a str, - ms_timeout: u64, - ) -> ResultType { - let framed = if username.trim().is_empty() { - super::timeout(ms_timeout, Socks5UdpFramed::connect(proxy, Some(local))).await?? - } else { - super::timeout( - ms_timeout, - Socks5UdpFramed::connect_with_password(proxy, Some(local), username, password), - ) - .await?? - }; - log::trace!( - "Socks5 udp connected, local addr: {:?}, target addr: {}", - framed.local_addr(), - framed.socks_addr() - ); - Ok(Self::ProxySocks(framed)) - } - - #[inline] - pub async fn send( - &mut self, - msg: &impl Message, - addr: impl IntoTargetAddr<'_>, - ) -> ResultType<()> { - let addr = addr.into_target_addr()?.to_owned(); - let send_data = Bytes::from(msg.write_to_bytes()?); - match self { - Self::Direct(f) => { - if let TargetAddr::Ip(addr) = addr { - f.send((send_data, addr)).await? - } - } - Self::ProxySocks(f) => f.send((send_data, addr)).await?, - }; - Ok(()) - } - - // https://stackoverflow.com/a/68733302/1926020 - #[inline] - pub async fn send_raw( - &mut self, - msg: &'static [u8], - addr: impl IntoTargetAddr<'static>, - ) -> ResultType<()> { - let addr = addr.into_target_addr()?.to_owned(); - - match self { - Self::Direct(f) => { - if let TargetAddr::Ip(addr) = addr { - f.send((Bytes::from(msg), addr)).await? - } - } - Self::ProxySocks(f) => f.send((Bytes::from(msg), addr)).await?, - }; - Ok(()) - } - - #[inline] - pub async fn next(&mut self) -> Option)>> { - match self { - Self::Direct(f) => match f.next().await { - Some(Ok((data, addr))) => { - Some(Ok((data, addr.into_target_addr().ok()?.to_owned()))) - } - Some(Err(e)) => Some(Err(anyhow!(e))), - None => None, - }, - Self::ProxySocks(f) => match f.next().await { - Some(Ok((data, _))) => Some(Ok((data.data, data.dst_addr))), - Some(Err(e)) => Some(Err(anyhow!(e))), - None => None, - }, - } - } - - #[inline] - pub async fn next_timeout( - &mut self, - ms: u64, - ) -> Option)>> { - if let Ok(res) = - tokio::time::timeout(std::time::Duration::from_millis(ms), self.next()).await - { - res - } else { - None - } - } - - pub fn local_addr(&self) -> Option { - if let FramedSocket::Direct(x) = self { - if let Ok(v) = x.get_ref().local_addr() { - return Some(v); - } - } - None - } -} diff --git a/src/common.rs b/src/common.rs index 2045177..9c76f41 100644 --- a/src/common.rs +++ b/src/common.rs @@ -1,7 +1,6 @@ use clap::App; use hbb_common::{ - anyhow::{Context, Result}, - log, ResultType, + allow_err, anyhow::{Context, Result}, get_version_number, log, tokio, ResultType }; use ini::Ini; use sodiumoxide::crypto::sign; @@ -189,3 +188,31 @@ pub async fn listen_signal() -> Result<()> { let () = std::future::pending().await; unreachable!(); } + + +pub fn check_software_update() { + const ONE_DAY_IN_SECONDS: u64 = 60 * 60 * 24; + std::thread::spawn(move || loop { + std::thread::spawn(move || allow_err!(check_software_update_())); + std::thread::sleep(std::time::Duration::from_secs(ONE_DAY_IN_SECONDS)); + }); +} + +#[tokio::main(flavor = "current_thread")] +async fn check_software_update_() -> hbb_common::ResultType<()> { + let (request, url) = hbb_common::version_check_request(hbb_common::VER_TYPE_RUSTDESK_SERVER.to_string()); + let latest_release_response = reqwest::Client::builder().build()? + .post(url) + .json(&request) + .send() + .await?; + + let bytes = latest_release_response.bytes().await?; + let resp: hbb_common::VersionCheckResponse = serde_json::from_slice(&bytes)?; + let response_url = resp.url; + let latest_release_version = response_url.rsplit('/').next().unwrap_or_default(); + if get_version_number(&latest_release_version) > get_version_number(crate::version::VERSION) { + log::info!("new version is available: {}", latest_release_version); + } + Ok(()) +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 2cbd9c9..8a0ff24 100644 --- a/src/main.rs +++ b/src/main.rs @@ -31,6 +31,7 @@ fn main() -> ResultType<()> { } let rmem = get_arg("rmem").parse::().unwrap_or(RMEM); let serial: i32 = get_arg("serial").parse().unwrap_or(0); + crate::common::check_software_update(); RendezvousServer::start(port, serial, &get_arg_or("key", "-".to_owned()), rmem)?; Ok(()) } diff --git a/src/relay_server.rs b/src/relay_server.rs index abe6fc2..bc379f4 100644 --- a/src/relay_server.rs +++ b/src/relay_server.rs @@ -85,7 +85,7 @@ pub async fn start(port: &str, key: &str) -> ResultType<()> { let main_task = async move { loop { log::info!("Start"); - io_loop(listen_any(port, true).await?, listen_any(port2, true).await?, &key).await; + io_loop(listen_any(port).await?, listen_any(port2).await?, &key).await; } }; let listen_signal = crate::common::listen_signal(); diff --git a/src/rendezvous_server.rs b/src/rendezvous_server.rs index 65c8022..a7e8727 100644 --- a/src/rendezvous_server.rs +++ b/src/rendezvous_server.rs @@ -1319,7 +1319,7 @@ async fn create_udp_listener(port: i32, rmem: usize) -> ResultType #[inline] async fn create_tcp_listener(port: i32) -> ResultType { - let s = listen_any(port as _, true).await?; + let s = listen_any(port as _).await?; log::debug!("listen on tcp {:?}", s.local_addr()); Ok(s) }