diff --git a/.github/workflows/build-nightly.yml b/.github/workflows/build-nightly.yml index 55787ee..d58a9d4 100644 --- a/.github/workflows/build-nightly.yml +++ b/.github/workflows/build-nightly.yml @@ -18,7 +18,10 @@ jobs: - aarch64-unknown-linux-musl steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 + + - name: Install Rust stable + uses: dtolnay/rust-toolchain@stable - name: Install cross run: cargo install cross @@ -48,23 +51,18 @@ jobs: - x86_64-apple-darwin - aarch64-apple-darwin steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Install GNU tar if: runner.os == 'macOS' run: | brew install gnu-tar - # echo "::add-path::/usr/local/opt/gnu-tar/libexec/gnubin" echo "/usr/local/opt/gnu-tar/libexec/gnubin" >> $GITHUB_PATH - name: Install Rust stable - uses: actions-rs/toolchain@v1 + uses: dtolnay/rust-toolchain@stable with: - profile: minimal - toolchain: stable - target: ${{ matrix.target }} - default: true - override: true + targets: ${{ matrix.target }} - name: Build release shell: bash @@ -83,15 +81,10 @@ jobs: RUSTFLAGS: "-Ctarget-feature=+crt-static" RUST_BACKTRACE: full steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Install Rust stable - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - default: true - override: true + uses: dtolnay/rust-toolchain@stable - name: Build release run: | diff --git a/.github/workflows/build-pr.yml b/.github/workflows/build-pr.yml index 8c638a9..cfcee63 100644 --- a/.github/workflows/build-pr.yml +++ b/.github/workflows/build-pr.yml @@ -19,7 +19,10 @@ jobs: - aarch64-unknown-linux-musl steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 + + - name: Install Rust stable + uses: dtolnay/rust-toolchain@stable - name: Install cross run: cargo install cross @@ -43,23 +46,18 @@ jobs: - x86_64-apple-darwin - aarch64-apple-darwin steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Install GNU tar if: runner.os == 'macOS' run: | brew install gnu-tar - # echo "::add-path::/usr/local/opt/gnu-tar/libexec/gnubin" echo "/usr/local/opt/gnu-tar/libexec/gnubin" >> $GITHUB_PATH - name: Install Rust stable - uses: actions-rs/toolchain@v1 + uses: dtolnay/rust-toolchain@stable with: - profile: minimal - toolchain: stable - target: ${{ matrix.target }} - default: true - override: true + targets: ${{ matrix.target }} - name: Build release shell: bash @@ -72,22 +70,17 @@ jobs: RUSTFLAGS: "-Ctarget-feature=+crt-static" RUST_BACKTRACE: full steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Install Rust stable - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - default: true - override: true + uses: dtolnay/rust-toolchain@stable - name: Build release run: | pwsh ./build/build-host-release.ps1 - name: Upload Artifacts - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: windows-native path: build/release/* diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..9dd0f83 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,79 @@ +name: CI + +on: + push: + branches: [master] + pull_request: + branches: [master] + +env: + CARGO_TERM_COLOR: always + +jobs: + test: + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + rust: [stable] + steps: + - uses: actions/checkout@v4 + + - name: Install Rust ${{ matrix.rust }} + uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ matrix.rust }} + + - name: Cache cargo registry and build + uses: actions/cache@v4 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + target + key: ${{ runner.os }}-cargo-${{ matrix.rust }}-${{ hashFiles('**/Cargo.lock') }} + restore-keys: | + ${{ runner.os }}-cargo-${{ matrix.rust }}- + + - name: Run tests + run: cargo test --verbose + + - name: Build + run: cargo build --verbose + + clippy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install Rust stable + uses: dtolnay/rust-toolchain@stable + with: + components: clippy + + - name: Cache cargo registry and build + uses: actions/cache@v4 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + target + key: ${{ runner.os }}-cargo-clippy-${{ hashFiles('**/Cargo.lock') }} + restore-keys: | + ${{ runner.os }}-cargo-clippy- + + - name: Run clippy + run: cargo clippy -- -D warnings + + fmt: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install Rust stable + uses: dtolnay/rust-toolchain@stable + with: + components: rustfmt + + - name: Check formatting + run: cargo fmt --all -- --check diff --git a/Cargo.lock b/Cargo.lock index 9af9c95..b0d4590 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" @@ -27,31 +27,61 @@ dependencies = [ ] [[package]] -name = "ansi_term" -version = "0.12.1" +name = "anstream" +version = "0.6.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" dependencies = [ - "winapi", + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", ] [[package]] -name = "anyhow" -version = "1.0.99" +name = "anstyle" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" [[package]] -name = "atty" -version = "0.2.14" +name = "anstyle-parse" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" dependencies = [ - "hermit-abi 0.1.19", - "libc", - "winapi", + "utf8parse", ] +[[package]] +name = "anstyle-query" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" +dependencies = [ + "windows-sys 0.60.2", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys 0.60.2", +] + +[[package]] +name = "anyhow" +version = "1.0.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100" + [[package]] name = "autocfg" version = "1.5.0" @@ -73,12 +103,6 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - [[package]] name = "bitflags" version = "2.9.4" @@ -127,19 +151,50 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "clap" -version = "2.34.0" +version = "4.5.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +checksum = "6899ea499e3fb9305a65d5ebf6e3d2248c5fab291f300ad0a704fbe142eae31a" dependencies = [ - "ansi_term", - "atty", - "bitflags 1.3.2", + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b12c8b680195a62a8364d16b8447b01b6c2c8f9aaf68bee653be34d4245e238" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", "strsim", - "textwrap", - "unicode-width", - "vec_map", ] +[[package]] +name = "clap_derive" +version = "4.5.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a92793da1a46a5f2a02a6f4c46c6496b28c43638adea8306fcb0caa1634f24e5" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3e64b0cc0439b12df2fa678eae89a1c56a529fd067a9115f7827f1fffd22b32" + +[[package]] +name = "colorchoice" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" + [[package]] name = "combine" version = "4.6.7" @@ -168,36 +223,46 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "dirs" -version = "5.0.1" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" dependencies = [ "dirs-sys", ] [[package]] name = "dirs-sys" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.48.0", + "windows-sys 0.60.2", ] [[package]] -name = "env_logger" -version = "0.10.2" +name = "env_filter" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" +checksum = "1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2" dependencies = [ - "humantime", - "is-terminal", "log", "regex", - "termcolor", +] + +[[package]] +name = "env_logger" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "jiff", + "log", ] [[package]] @@ -274,7 +339,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn", ] [[package]] @@ -342,54 +407,49 @@ checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "heck" -version = "0.3.3" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" -dependencies = [ - "unicode-segmentation", -] +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] -name = "hermit-abi" -version = "0.1.19" +name = "io-uring" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b" dependencies = [ + "bitflags", + "cfg-if", "libc", ] [[package]] -name = "hermit-abi" -version = "0.5.2" +name = "is_terminal_polyfill" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] -name = "humantime" -version = "2.2.0" +name = "jiff" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b112acc8b3adf4b107a8ec20977da0273a8c386765a3ec0229bd500a1443f9f" - -[[package]] -name = "io-uring" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b" +checksum = "d89a5b5e10d5a9ad6e5d1f4bd58225f655d6fe9767575a5e8ac5a6fe64e04495" dependencies = [ - "bitflags 2.9.4", - "cfg-if", - "libc", + "jiff-static", + "log", + "portable-atomic", + "portable-atomic-util", + "serde_core", ] [[package]] -name = "is-terminal" -version = "0.4.16" +name = "jiff-static" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" +checksum = "ff7a39c8862fc1369215ccf0a8f12dd4598c7f6484704359f0351bd617034dbf" dependencies = [ - "hermit-abi 0.5.2", - "libc", - "windows-sys 0.59.0", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -424,12 +484,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" - [[package]] name = "libc" version = "0.2.175" @@ -448,7 +502,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "391290121bad3d37fbddad76d8f5d1c1c314cfc646d143d7e07a3086ddff0ce3" dependencies = [ - "bitflags 2.9.4", + "bitflags", "libc", ] @@ -515,6 +569,12 @@ version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +[[package]] +name = "once_cell_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" + [[package]] name = "openssl-probe" version = "0.1.6" @@ -563,36 +623,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] -name = "ppv-lite86" -version = "0.2.21" +name = "portable-atomic" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" -dependencies = [ - "zerocopy", -] +checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" [[package]] -name = "proc-macro-error" -version = "1.0.4" +name = "portable-atomic-util" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +checksum = "7a9db96d7fa8782dd8c15ce32ffe8680bbd1e978a43bf51a34d39483540495f5" dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", + "portable-atomic", ] [[package]] -name = "proc-macro-error-attr" -version = "1.0.4" +name = "ppv-lite86" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ - "proc-macro2", - "quote", - "version_check", + "zerocopy", ] [[package]] @@ -610,6 +661,7 @@ version = "0.3.0" dependencies = [ "anyhow", "bytes", + "clap", "dirs", "env_logger", "futures", @@ -620,11 +672,10 @@ dependencies = [ "rustls-native-certs", "rustls-pemfile", "rustls-pki-types", - "rustls-platform-verifier 0.5.3", - "structopt", + "serial_test", "tokio", "tracing", - "webpki-roots 0.26.11", + "webpki-roots", ] [[package]] @@ -662,7 +713,7 @@ dependencies = [ "rustc-hash", "rustls", "rustls-pki-types", - "rustls-platform-verifier 0.6.1", + "rustls-platform-verifier", "slab", "thiserror 2.0.16", "tinyvec", @@ -734,18 +785,18 @@ version = "0.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" dependencies = [ - "bitflags 2.9.4", + "bitflags", ] [[package]] name = "redox_users" -version = "0.4.6" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" dependencies = [ "getrandom 0.2.16", "libredox", - "thiserror 1.0.69", + "thiserror 2.0.16", ] [[package]] @@ -848,27 +899,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "rustls-platform-verifier" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19787cda76408ec5404443dc8b31795c87cd8fec49762dc75fa727740d34acc1" -dependencies = [ - "core-foundation", - "core-foundation-sys", - "jni", - "log", - "once_cell", - "rustls", - "rustls-native-certs", - "rustls-platform-verifier-android", - "rustls-webpki", - "security-framework", - "security-framework-sys", - "webpki-root-certs 0.26.11", - "windows-sys 0.59.0", -] - [[package]] name = "rustls-platform-verifier" version = "0.6.1" @@ -886,7 +916,7 @@ dependencies = [ "rustls-webpki", "security-framework", "security-framework-sys", - "webpki-root-certs 1.0.2", + "webpki-root-certs", "windows-sys 0.59.0", ] @@ -916,6 +946,15 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "scc" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46e6f046b7fef48e2660c57ed794263155d713de679057f2d0c169bfc6e756cc" +dependencies = [ + "sdd", +] + [[package]] name = "schannel" version = "0.1.27" @@ -931,13 +970,19 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "sdd" +version = "3.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "490dcfcbfef26be6800d11870ff2df8774fa6e86d047e3e8c8a76b25655e41ca" + [[package]] name = "security-framework" version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80fb1d92c5028aa318b4b8bd7302a5bfcf48be96a37fc6fc790f806b0004ee0c" dependencies = [ - "bitflags 2.9.4", + "bitflags", "core-foundation", "core-foundation-sys", "libc", @@ -954,6 +999,52 @@ dependencies = [ "libc", ] +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serial_test" +version = "3.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d0b343e184fc3b7bb44dff0705fffcf4b3756ba6aff420dddd8b24ca145e555" +dependencies = [ + "futures-executor", + "futures-util", + "log", + "once_cell", + "parking_lot", + "scc", + "serial_test_derive", +] + +[[package]] +name = "serial_test_derive" +version = "3.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f50427f258fb77356e4cd4aa0e87e2bd2c66dbcee41dc405282cae2bfc26c83" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "shlex" version = "1.3.0" @@ -999,33 +1090,9 @@ dependencies = [ [[package]] name = "strsim" -version = "0.8.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" - -[[package]] -name = "structopt" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10" -dependencies = [ - "clap", - "lazy_static", - "structopt-derive", -] - -[[package]] -name = "structopt-derive" -version = "0.4.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" -dependencies = [ - "heck", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", -] +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "subtle" @@ -1033,17 +1100,6 @@ version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - [[package]] name = "syn" version = "2.0.106" @@ -1055,24 +1111,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "termcolor" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "textwrap" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -dependencies = [ - "unicode-width", -] - [[package]] name = "thiserror" version = "1.0.69" @@ -1099,7 +1137,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn", ] [[package]] @@ -1110,7 +1148,7 @@ checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn", ] [[package]] @@ -1156,7 +1194,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn", ] [[package]] @@ -1179,7 +1217,7 @@ checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn", ] [[package]] @@ -1197,18 +1235,6 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" -[[package]] -name = "unicode-segmentation" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" - -[[package]] -name = "unicode-width" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" - [[package]] name = "untrusted" version = "0.9.0" @@ -1216,16 +1242,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] -name = "vec_map" -version = "0.8.2" +name = "utf8parse" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" - -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "walkdir" @@ -1274,7 +1294,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.106", + "syn", "wasm-bindgen-shared", ] @@ -1296,7 +1316,7 @@ checksum = "7bb4ce89b08211f923caf51d527662b75bdc9c9c7aab40f86dcb9fb85ac552aa" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -1320,15 +1340,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "webpki-root-certs" -version = "0.26.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75c7f0ef91146ebfb530314f5f1d24528d7f0767efbfd31dce919275413e393e" -dependencies = [ - "webpki-root-certs 1.0.2", -] - [[package]] name = "webpki-root-certs" version = "1.0.2" @@ -1338,15 +1349,6 @@ dependencies = [ "rustls-pki-types", ] -[[package]] -name = "webpki-roots" -version = "0.26.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" -dependencies = [ - "webpki-roots 1.0.2", -] - [[package]] name = "webpki-roots" version = "1.0.2" @@ -1356,22 +1358,6 @@ dependencies = [ "rustls-pki-types", ] -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - [[package]] name = "winapi-util" version = "0.1.10" @@ -1381,12 +1367,6 @@ dependencies = [ "windows-sys 0.60.2", ] -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - [[package]] name = "windows-link" version = "0.1.3" @@ -1402,15 +1382,6 @@ dependencies = [ "windows-targets 0.42.2", ] -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - [[package]] name = "windows-sys" version = "0.52.0" @@ -1453,21 +1424,6 @@ dependencies = [ "windows_x86_64_msvc 0.42.2", ] -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "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" @@ -1507,12 +1463,6 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" @@ -1531,12 +1481,6 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - [[package]] name = "windows_aarch64_msvc" version = "0.52.6" @@ -1555,12 +1499,6 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -1591,12 +1529,6 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - [[package]] name = "windows_i686_msvc" version = "0.52.6" @@ -1615,12 +1547,6 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - [[package]] name = "windows_x86_64_gnu" version = "0.52.6" @@ -1639,12 +1565,6 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" @@ -1663,12 +1583,6 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - [[package]] name = "windows_x86_64_msvc" version = "0.52.6" @@ -1704,7 +1618,7 @@ checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 3b0eb4b..82a03b5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,19 +18,21 @@ path = "src/server.rs" [dependencies] tokio = { version = "1", features = ["full"] } -bytes = "1.2.1" +bytes = "1" futures = "0.3" -rustls = { version = "0.23.5", default-features = false, features = ["std"] } +rustls = { version = "0.23", default-features = false, features = ["std"] } rustls-pemfile = "2" -rustls-platform-verifier = "0.5" -rustls-pki-types = "1.7" -webpki-roots = "0.26.7" -quinn = "0.11.6" -quinn-proto = "0.11.9" -structopt = "0.3" -anyhow = "1.0" +rustls-pki-types = "1" +webpki-roots = "1" +quinn = "0.11" +quinn-proto = "0.11" +clap = { version = "4", features = ["derive"] } +anyhow = "1" tracing = "0.1" log = "0.4" -env_logger = "0.10.0" -dirs = "5.0.1" -rustls-native-certs = "0.8.1" +env_logger = "0.11" +dirs = "6" +rustls-native-certs = "0.8" + +[dev-dependencies] +serial_test = "3" diff --git a/src/args/mod.rs b/src/args/mod.rs index b1de4aa..0b078d2 100644 --- a/src/args/mod.rs +++ b/src/args/mod.rs @@ -49,3 +49,97 @@ fn parse_plugin_options(options: &str) -> HashMap { plugin_options } + +#[cfg(test)] +mod tests { + use super::*; + use serial_test::serial; + use std::env; + + #[test] + fn test_parse_plugin_options_single() { + let opts = parse_plugin_options("host=example.com"); + assert_eq!(opts.get("host").unwrap(), "example.com"); + assert_eq!(opts.len(), 1); + } + + #[test] + fn test_parse_plugin_options_multiple() { + let opts = parse_plugin_options("host=example.com;cert=/path/to/cert;key=/path/to/key"); + assert_eq!(opts.get("host").unwrap(), "example.com"); + assert_eq!(opts.get("cert").unwrap(), "/path/to/cert"); + assert_eq!(opts.get("key").unwrap(), "/path/to/key"); + assert_eq!(opts.len(), 3); + } + + #[test] + fn test_parse_plugin_options_value_with_equals() { + let opts = parse_plugin_options("key=value=with=equals"); + assert_eq!(opts.get("key").unwrap(), "value=with=equals"); + } + + #[test] + fn test_parse_plugin_options_duplicate_key_last_wins() { + let opts = parse_plugin_options("secret=first;secret=second"); + assert_eq!(opts.get("secret").unwrap(), "second"); + } + + #[test] + #[serial] + fn test_parse_env_addr_valid() { + // Set environment variables for the test + env::set_var("SS_LOCAL_HOST", "127.0.0.1"); + env::set_var("SS_LOCAL_PORT", "1080"); + env::set_var("SS_REMOTE_HOST", "127.0.0.1"); + env::set_var("SS_REMOTE_PORT", "8388"); + + let result = parse_env_addr(); + assert!(result.is_ok()); + + let (local, remote) = result.unwrap(); + assert_eq!(local.port(), 1080); + assert_eq!(remote.port(), 8388); + + // Clean up + env::remove_var("SS_LOCAL_HOST"); + env::remove_var("SS_LOCAL_PORT"); + env::remove_var("SS_REMOTE_HOST"); + env::remove_var("SS_REMOTE_PORT"); + } + + #[test] + #[serial] + fn test_parse_env_addr_missing_vars() { + env::remove_var("SS_REMOTE_HOST"); + env::remove_var("SS_REMOTE_PORT"); + env::remove_var("SS_LOCAL_HOST"); + env::remove_var("SS_LOCAL_PORT"); + + let result = parse_env_addr(); + assert!(result.is_err()); + } + + #[test] + #[serial] + fn test_parse_env_opts_valid() { + env::set_var("SS_PLUGIN_OPTIONS", "host=example.com;cert=/tmp/cert.pem"); + + let result = parse_env_opts(); + assert!(result.is_ok()); + + let opts = result.unwrap(); + assert_eq!(opts.get("host").unwrap(), "example.com"); + assert_eq!(opts.get("cert").unwrap(), "/tmp/cert.pem"); + + env::remove_var("SS_PLUGIN_OPTIONS"); + } + + #[test] + #[serial] + fn test_parse_env_opts_missing_var() { + env::remove_var("SS_PLUGIN_OPTIONS"); + + let result = parse_env_opts(); + assert!(result.is_err()); + } +} diff --git a/src/client.rs b/src/client.rs index 6392f63..d515a87 100644 --- a/src/client.rs +++ b/src/client.rs @@ -5,11 +5,11 @@ use quinn::crypto::rustls::QuicClientConfig; use tokio::net::{TcpListener, TcpStream}; use anyhow::{anyhow, Result}; +use clap::Parser; use futures::future::try_join; use log::{error, info}; use quinn::ConnectionError; use quinn::Endpoint; -use structopt::{self, StructOpt}; use env_logger::Builder; use log::LevelFilter; @@ -17,17 +17,17 @@ use log::LevelFilter; mod args; mod common; -#[derive(StructOpt, Debug)] -#[structopt(name = "qtun-client")] +#[derive(Parser, Debug)] +#[command(name = "qtun-client")] struct Opt { /// Address to listen on - #[structopt(long = "listen", default_value = "127.0.0.1:8138")] + #[arg(long = "listen", default_value = "127.0.0.1:8138")] listen: SocketAddr, - /// Address to listen on - #[structopt(long = "relay", default_value = "127.0.0.1:4433")] + /// Address to relay to + #[arg(long = "relay", default_value = "127.0.0.1:4433")] relay: SocketAddr, /// Override hostname used for certificate verification - #[structopt(long = "host", default_value = "bing.com")] + #[arg(long = "host", default_value = "bing.com")] host: String, } @@ -35,12 +35,12 @@ struct Opt { async fn main() -> Result<()> { // setup log let mut log_builder = Builder::new(); - log_builder.filter(None, LevelFilter::Info).default_format(); + log_builder.filter(None, LevelFilter::Info); log_builder.filter(Some("qtun-client"), LevelFilter::Debug); log_builder.init(); // parse command line args - let options = Opt::from_args(); + let options = Opt::parse(); // init all parameters let mut listen_addr = options.listen; diff --git a/src/common/mod.rs b/src/common/mod.rs index 17a3140..e36202e 100644 --- a/src/common/mod.rs +++ b/src/common/mod.rs @@ -1,2 +1,13 @@ #[allow(unused)] pub const ALPN_QUIC_HTTP: &[&[u8]] = &[b"hq-29"]; + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_alpn_protocol_value() { + assert_eq!(ALPN_QUIC_HTTP.len(), 1); + assert_eq!(ALPN_QUIC_HTTP[0], b"hq-29"); + } +} diff --git a/src/server.rs b/src/server.rs index c48fdf5..5aee92c 100644 --- a/src/server.rs +++ b/src/server.rs @@ -4,6 +4,7 @@ use std::path::PathBuf; use std::sync::Arc; use anyhow::{Context, Result}; +use clap::Parser; use dirs::home_dir; use env_logger::Builder; use futures::future::try_join; @@ -12,61 +13,58 @@ use log::LevelFilter; use log::{error, info}; use quinn_proto::crypto::rustls::QuicServerConfig; use rustls::pki_types::{CertificateDer, PrivateKeyDer, PrivatePkcs8KeyDer}; -use structopt::{self, StructOpt}; use tokio::net::TcpStream; mod args; mod common; -#[derive(StructOpt, Debug)] -#[structopt(name = "qtun-server")] +#[derive(Parser, Debug)] +#[command(name = "qtun-server")] struct Opt { /// TLS private key in PEM format - #[structopt( - parse(from_os_str), - short = "k", + #[arg( + short = 'k', long = "key", requires = "cert", default_value = "key.der" )] key: PathBuf, /// TLS certificate in PEM format - #[structopt( - parse(from_os_str), - short = "c", + #[arg( + short = 'c', long = "cert", requires = "key", default_value = "cert.der" )] cert: PathBuf, /// Enable stateless retries - #[structopt(long = "stateless-retry")] + #[arg(long = "stateless-retry")] stateless_retry: bool, /// Address to listen on - #[structopt(long = "listen", default_value = "0.0.0.0:4433")] + #[arg(long = "listen", default_value = "0.0.0.0:4433")] listen: SocketAddr, - /// Address to listen on - #[structopt(long = "relay", default_value = "127.0.0.1:8138")] + /// Address to relay to + #[arg(long = "relay", default_value = "127.0.0.1:8138")] relay: SocketAddr, /// Specify the host to load TLS certificates from ~/.acme.sh/host - #[structopt(long = "acme-host")] + #[arg(long = "acme-host")] acme_host: Option, /// Client address to block - #[structopt(long = "block")] + #[arg(long = "block")] block: Option, /// Maximum number of concurrent connections to allow - #[structopt(long = "connection-limit")] + #[arg(long = "connection-limit")] connection_limit: Option, } #[tokio::main] async fn main() -> Result<()> { let mut log_builder = Builder::new(); - log_builder.filter(None, LevelFilter::Info).default_format(); + log_builder.filter(None, LevelFilter::Info); log_builder.filter(Some("qtun-server"), LevelFilter::Debug); log_builder.init(); - let options = Opt::from_args(); + let options = Opt::parse(); // init all parameters let mut cert_path = options.cert; @@ -155,7 +153,7 @@ async fn main() -> Result<()> { let fut = handle_connection(remote.clone(), conn); tokio::spawn(async move { if let Err(e) = fut.await { - error!("connection failed: {reason}", reason = e.to_string()) + error!("connection failed: {reason}", reason = e) } }); } @@ -185,7 +183,7 @@ async fn handle_connection(remote: Arc, conn: quinn::Incoming) -> Re }; tokio::spawn( transfer(remote.clone(), stream) - .unwrap_or_else(move |e| error!("failed: {reason}", reason = e.to_string())), + .unwrap_or_else(move |e| error!("failed: {reason}", reason = e)), ); } }