diff options
author | metamuffin <metamuffin@disroot.org> | 2025-03-17 20:46:23 +0100 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2025-03-17 20:46:23 +0100 |
commit | 143fe969eb6225c2aa8694930114103f1d4f0c9c (patch) | |
tree | 7f430400b464413fc16bd0bb91aad0436685482b | |
parent | a76cab9f30a51b9b4d2377b2d25640c129bf3ab3 (diff) | |
download | gnix-143fe969eb6225c2aa8694930114103f1d4f0c9c.tar gnix-143fe969eb6225c2aa8694930114103f1d4f0c9c.tar.bz2 gnix-143fe969eb6225c2aa8694930114103f1d4f0c9c.tar.zst |
h3 ground work
-rw-r--r-- | Cargo.lock | 546 | ||||
-rw-r--r-- | Cargo.toml | 3 | ||||
-rw-r--r-- | src/error.rs | 3 | ||||
-rw-r--r-- | src/h3_support.rs | 30 | ||||
-rw-r--r-- | src/main.rs | 180 | ||||
-rw-r--r-- | src/modules/mod.rs | 2 |
6 files changed, 681 insertions, 83 deletions
@@ -98,7 +98,7 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" dependencies = [ - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -108,7 +108,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" dependencies = [ "anstyle", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -143,29 +143,25 @@ checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "aws-lc-rs" -version = "1.8.1" +version = "1.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ae74d9bd0a7530e8afd1770739ad34b36838829d6ad61818f9230f683f5ad77" +checksum = "dabb68eb3a7aa08b46fddfd59a3d55c978243557a90ab804769f7e20e67d2b01" dependencies = [ "aws-lc-sys", - "mirai-annotations", - "paste", "zeroize", ] [[package]] name = "aws-lc-sys" -version = "0.20.1" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f0e249228c6ad2d240c2dc94b714d711629d52bad946075d8e9b2f5391f0703" +checksum = "77926887776171ced7d662120a75998e444d3750c951abfe07f90da130514b1f" dependencies = [ "bindgen", "cc", "cmake", "dunce", "fs_extra", - "libc", - "paste", ] [[package]] @@ -203,9 +199,9 @@ checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" [[package]] name = "bindgen" -version = "0.69.4" +version = "0.69.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" +checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" dependencies = [ "bitflags", "cexpr", @@ -218,7 +214,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "rustc-hash", + "rustc-hash 1.1.0", "shlex", "syn", "which", @@ -258,6 +254,12 @@ dependencies = [ ] [[package]] +name = "bumpalo" +version = "3.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" + +[[package]] name = "byteorder" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -281,6 +283,12 @@ dependencies = [ ] [[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" @@ -296,6 +304,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] name = "cipher" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -332,12 +346,38 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" [[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + +[[package]] name = "const-oid" version = "0.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9adcf94f05e094fca3005698822ec791cb4433ced416afda1c5ca3b8dfc05a2f" [[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] name = "cpufeatures" version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -447,10 +487,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -568,8 +614,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi", + "wasm-bindgen", ] [[package]] @@ -596,6 +644,8 @@ dependencies = [ "env_logger", "futures", "futures-util", + "h3", + "h3-quinn", "headers", "hex", "http", @@ -610,17 +660,18 @@ dependencies = [ "mime_guess", "percent-encoding", "pin-project", - "rand", + "quinn", + "rand 0.9.0-alpha.2", "regex", "ring", "rustls", "rustls-pemfile", - "rustls-webpki", + "rustls-webpki 0.102.6", "serde", "serde_json", "serde_yml", "sha2", - "thiserror", + "thiserror 2.0.3", "tokio", "tokio-rustls", "tokio-util", @@ -647,6 +698,34 @@ dependencies = [ ] [[package]] +name = "h3" +version = "0.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dfb059a4f28a66f186ed16ad912d142f490676acba59353831d7cb45a96b0d3" +dependencies = [ + "bytes", + "fastrand", + "futures-util", + "http", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "h3-quinn" +version = "0.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "690cbdc6600db8490412edf5e2bbec0c88f4d4e83f9e0800428b51e6c23372dc" +dependencies = [ + "bytes", + "futures", + "h3", + "quinn", + "tokio", + "tokio-util", +] + +[[package]] name = "hashbrown" version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -694,7 +773,7 @@ version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" dependencies = [ - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -866,6 +945,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] +name = "jni" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6df18c2e3db7e453d3c6ac5b3e9d5182664d28788126d39b91f2d1e22b017ec" +dependencies = [ + "cesu8", + "combine", + "jni-sys", + "log", + "thiserror 1.0.69", + "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" @@ -875,6 +974,16 @@ dependencies = [ ] [[package]] +name = "js-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] name = "lazy_static" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1006,16 +1115,10 @@ dependencies = [ "hermit-abi", "libc", "wasi", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] -name = "mirai-annotations" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9be0862c1b3f26a88803c4a49de6889c10e608b3ee9344e6ef5b45fb37ad3d1" - -[[package]] name = "nom" version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1026,6 +1129,34 @@ dependencies = [ ] [[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] name = "object" version = "0.36.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1047,6 +1178,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] +name = "openssl-probe" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" + +[[package]] name = "parking_lot" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1081,12 +1218,6 @@ dependencies = [ ] [[package]] -name = "paste" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" - -[[package]] name = "percent-encoding" version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1165,6 +1296,60 @@ dependencies = [ ] [[package]] +name = "quinn" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62e96808277ec6f97351a2380e6c25114bc9e67037775464979f3037c92d05ef" +dependencies = [ + "bytes", + "futures-io", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash 2.1.1", + "rustls", + "socket2", + "thiserror 2.0.3", + "tokio", + "tracing", +] + +[[package]] +name = "quinn-proto" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2fe5ef3495d7d2e377ff17b1a8ce2ee2ec2a18cde8b6ad6619d65d0701c135d" +dependencies = [ + "bytes", + "getrandom", + "rand 0.8.5", + "ring", + "rustc-hash 2.1.1", + "rustls", + "rustls-pki-types", + "rustls-platform-verifier", + "slab", + "thiserror 2.0.3", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e46f3055866785f6b92bc6164b76be02ca8f2eb4b002c0354b28cf4c119e5944" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.59.0", +] + +[[package]] name = "quote" version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1175,17 +1360,38 @@ dependencies = [ [[package]] name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" version = "0.9.0-alpha.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3e256ff62cee3e03def855c4d4260106d2bb1696fdc01af03e9935b993720a5" dependencies = [ - "rand_chacha", + "rand_chacha 0.9.0-alpha.2", "rand_core 0.9.0-alpha.2", "zerocopy", ] [[package]] name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" version = "0.9.0-alpha.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d299e9db34f6623b2a9e86c015d6e173d5f46d64d4b9b8cc46ae8a982a50b04c" @@ -1263,7 +1469,7 @@ dependencies = [ "libc", "spin", "untrusted", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -1279,6 +1485,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] +name = "rustc-hash" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" + +[[package]] name = "rustix" version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1288,26 +1500,39 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] name = "rustls" -version = "0.23.12" +version = "0.23.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044" +checksum = "822ee9188ac4ec04a2f0531e55d035fb2de73f18b41a63c70c2712503b6fb13c" dependencies = [ "aws-lc-rs", "log", "once_cell", "ring", "rustls-pki-types", - "rustls-webpki", + "rustls-webpki 0.103.0", "subtle", "zeroize", ] [[package]] +name = "rustls-native-certs" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5" +dependencies = [ + "openssl-probe", + "rustls-pemfile", + "rustls-pki-types", + "schannel", + "security-framework", +] + +[[package]] name = "rustls-pemfile" version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1319,9 +1544,39 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.8.0" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c" +dependencies = [ + "web-time", +] + +[[package]] +name = "rustls-platform-verifier" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4c7dc240fec5517e6c4eab3310438636cfe6391dfc345ba013109909a90d136" +dependencies = [ + "core-foundation", + "core-foundation-sys", + "jni", + "log", + "once_cell", + "rustls", + "rustls-native-certs", + "rustls-platform-verifier-android", + "rustls-webpki 0.102.6", + "security-framework", + "security-framework-sys", + "webpki-root-certs", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustls-platform-verifier-android" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" +checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" [[package]] name = "rustls-webpki" @@ -1329,6 +1584,17 @@ version = "0.102.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e" dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0aa4eeac2588ffff23e9d7a7e9b3f971c5fb5b7ebc9452745e0c232c64f83b2f" +dependencies = [ "aws-lc-rs", "ring", "rustls-pki-types", @@ -1342,12 +1608,54 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "schannel" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] name = "scopeguard" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "num-bigint", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] name = "serde" version = "1.0.208" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1453,7 +1761,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -1481,11 +1789,31 @@ dependencies = [ [[package]] name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c006c85c7651b3cf2ada4584faa36773bd07bac24acfb39f3c431b36d7e667aa" dependencies = [ - "thiserror-impl", + "thiserror-impl 2.0.3", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -1500,6 +1828,21 @@ dependencies = [ ] [[package]] +name = "tinyvec" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] name = "tokio" version = "1.39.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1514,7 +1857,7 @@ dependencies = [ "signal-hook-registry", "socket2", "tokio-macros", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -1558,6 +1901,7 @@ version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ + "log", "pin-project-lite", "tracing-core", ] @@ -1637,6 +1981,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] name = "want" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1652,6 +2006,82 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] +name = "wasm-bindgen" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki-root-certs" +version = "0.26.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09aed61f5e8d2c18344b3faa33a4c837855fe56642757754775548fee21386c4" +dependencies = [ + "rustls-pki-types", +] + +[[package]] name = "which" version = "4.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1664,6 +2094,15 @@ dependencies = [ ] [[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] name = "windows-sys" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1673,6 +2112,15 @@ dependencies = [ ] [[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] name = "windows-targets" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1762,17 +2210,3 @@ name = "zeroize" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" -dependencies = [ - "zeroize_derive", -] - -[[package]] -name = "zeroize_derive" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] @@ -6,6 +6,9 @@ edition = "2021" [dependencies] # HTTP hyper = { version = "1.4.1", features = ["server", "client", "http1", "http2"] } +quinn = "0.11.6" +h3 = "0.0.7" +h3-quinn = "0.0.8" hyper-util = { version = "0.1.7", features = [ "server-auto", "server", diff --git a/src/error.rs b/src/error.rs index a518bfb..3950b80 100644 --- a/src/error.rs +++ b/src/error.rs @@ -8,6 +8,8 @@ pub enum ServiceError { Limit(#[from] tokio::sync::TryAcquireError), #[error("hyper error")] Hyper(hyper::Error), + #[error("h3 error: {0}")] + H3(h3::Error), #[error("host header missing")] NoHost, #[error("unknown host")] @@ -58,6 +60,7 @@ impl ServiceError { ServiceError::RequestTaken => StatusCode::INTERNAL_SERVER_ERROR, ServiceError::Limit(_) => StatusCode::TOO_MANY_REQUESTS, ServiceError::Hyper(_) => StatusCode::INTERNAL_SERVER_ERROR, + ServiceError::H3(_) => StatusCode::INTERNAL_SERVER_ERROR, ServiceError::NoHost => StatusCode::BAD_REQUEST, ServiceError::UnknownHost => StatusCode::NOT_FOUND, ServiceError::UnknownPath => StatusCode::NOT_FOUND, diff --git a/src/h3_support.rs b/src/h3_support.rs new file mode 100644 index 0000000..56286db --- /dev/null +++ b/src/h3_support.rs @@ -0,0 +1,30 @@ +use crate::error::ServiceError; +use bytes::{Buf, Bytes}; +use h3::server::RequestStream; +use h3_quinn::RecvStream; +use hyper::body::{Body, Frame}; +use std::{ + pin::Pin, + task::{Context, Poll}, +}; + +pub struct H3RequestBody(pub RequestStream<RecvStream, Bytes>); + +impl Body for H3RequestBody { + type Data = Bytes; + type Error = ServiceError; + + fn poll_frame( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>> { + match self.0.poll_recv_data(cx) { + Poll::Ready(Ok(Some(mut f))) => { + Poll::Ready(Some(Ok(Frame::data(f.copy_to_bytes(f.remaining()))))) + } + Poll::Ready(Ok(None)) => Poll::Ready(None), + Poll::Ready(Err(e)) => Poll::Ready(Some(Err(ServiceError::H3(e)))), + Poll::Pending => Poll::Pending, + } + } +} diff --git a/src/main.rs b/src/main.rs index d8e1407..de43a6b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,30 +1,38 @@ -#![feature(try_trait_v2)] -#![feature(slice_split_once)] -#![feature(iterator_try_collect)] -#![feature(path_add_extension)] +#![feature( + try_trait_v2, + slice_split_once, + iterator_try_collect, + path_add_extension, + never_type +)] pub mod certs; pub mod config; pub mod error; +pub mod h3_support; pub mod modules; use aes_gcm_siv::{aead::generic_array::GenericArray, Aes256GcmSiv, KeyInit}; use anyhow::{Context, Result}; +use bytes::Bytes; use certs::CertPool; use config::{setup_file_watch, Config, NODE_KINDS}; use error::ServiceError; use futures::future::try_join_all; +use h3::error::ErrorLevel; +use h3_support::H3RequestBody; use http_body_util::{combinators::BoxBody, BodyExt}; use hyper::{ body::Incoming, header::{CONTENT_TYPE, HOST, SERVER}, http::HeaderValue, service::service_fn, - Request, Response, StatusCode, Uri, + Request, Response, Uri, }; use hyper_util::rt::{TokioExecutor, TokioIo}; use log::{debug, error, info, warn, LevelFilter}; use modules::{NodeContext, MODULES}; +use quinn::crypto::rustls::QuicServerConfig; use std::{ collections::HashMap, net::SocketAddr, path::PathBuf, process::exit, str::FromStr, sync::Arc, }; @@ -107,6 +115,15 @@ async fn main() -> anyhow::Result<()> { } }); } + { + let state = state.clone(); + tokio::spawn(async move { + if let Err(e) = serve_h3(state).await { + error!("{e:?}"); + exit(1) + } + }); + } ctrl_c().await.unwrap(); Ok(()) @@ -180,6 +197,116 @@ async fn serve_https(state: Arc<State>) -> Result<()> { Ok(()) } +async fn serve_h3(state: Arc<State>) -> Result<()> { + let config = state.config.read().await.clone(); + let https_config = match &config.https { + Some(n) => n, + None => return Ok(()), + }; + let bind_addrs = https_config.bind.clone(); + let certs = CertPool::load(&https_config.cert_path, https_config.cert_fallback.clone())?; + let mut cfg = rustls::ServerConfig::builder() + .with_no_client_auth() + .with_cert_resolver(Arc::new(certs)); + cfg.alpn_protocols = vec![b"h3".to_vec()]; + let cfg = Arc::new(QuicServerConfig::try_from(cfg)?); + + try_join_all(bind_addrs.iter().map(|listen_addr| { + async { + let cfg = quinn::ServerConfig::with_crypto(cfg.clone()); + let endpoint = quinn::Endpoint::server(cfg, *listen_addr)?; + let listen_addr = *listen_addr; + info!("HTTPS (HTTP/3) listener bound to {listen_addr}"); + while let Some(conn) = endpoint.accept().await { + let state = state.clone(); + tokio::spawn(async move { + let addr = conn.remote_address(); // TODO wait for validatation (or not?) + let Ok(_sem) = state.l_incoming.try_acquire() else { + return conn.refuse(); + }; + let conn = match conn.await { + Ok(conn) => conn, + Err(e) => return warn!("quic connection failed: {e}"), + }; + let mut conn = match h3::server::Connection::<_, Bytes>::new( + h3_quinn::Connection::new(conn), + ) + .await + { + Ok(conn) => conn, + Err(e) => return warn!("h3 accept failed {e}"), + }; + loop { + match conn.accept().await { + Ok(Some((req, stream))) => { + let (mut send, recv) = stream.split(); + let req = req.map(|()| H3RequestBody(recv).boxed()); + + let resp = match service( + state.clone(), + req, + addr, + true, + listen_addr, + ) + .await + { + Ok(resp) => resp, + Err(error) => error_response(addr, error), + }; + + let (parts, mut body) = resp.into_parts(); + let resp = Response::from_parts(parts, ()); + + if let Err(e) = send.send_response(resp).await { + warn!("h3 response send error: {e}"); + return; + }; + while let Some(frame) = body.frame().await { + match frame { + Ok(frame) => { + if frame.is_data() { + let data = frame.into_data().unwrap(); + if let Err(e) = send.send_data(data).await { + warn!("h3 body send error: {e}"); + return; + } + } else if frame.is_trailers() { + let trailers = frame.into_trailers().unwrap(); + if let Err(e) = send.send_trailers(trailers).await { + warn!("h3 trailers send error: {e}"); + return; + } + } + } + Err(_) => todo!(), + } + } + if let Err(e) = send.finish().await { + warn!("h3 response finish error: {e}"); + return; + } + } + Ok(None) => break, + Err(e) => { + warn!("h3 error: {e}"); + match e.get_error_level() { + ErrorLevel::ConnectionError => break, + ErrorLevel::StreamError => continue, + } + } + } + } + drop(_sem); + }); + } + Ok::<_, anyhow::Error>(()) + } + })) + .await?; + Ok(()) +} + pub async fn serve_stream<T: Unpin + Send + 'static + hyper::rt::Read + hyper::rt::Write>( state: Arc<State>, stream: T, @@ -194,23 +321,11 @@ pub async fn serve_stream<T: Unpin + Send + 'static + hyper::rt::Read + hyper::r service_fn(|req| { let state = state.clone(); async move { - let config = state.config.read().await.clone(); - match service(state, config, req, addr, secure, listen_addr).await { + let req = req.map(|body: Incoming| body.map_err(ServiceError::Hyper).boxed()); + match service(state, req, addr, secure, listen_addr).await { Ok(r) => Ok(r), Err(ServiceError::Hyper(e)) => Err(e), - Err(error) => Ok({ - warn!("service error {addr} {error:?}"); - let mut resp = Response::new(format!( - "Sorry, we were unable to process your request: {error}" - )); - *resp.status_mut() = error.status_code(); - resp.headers_mut() - .insert(CONTENT_TYPE, HeaderValue::from_static("text/plain")); - resp.headers_mut() - .insert(SERVER, HeaderValue::from_static("gnix")); - resp - } - .map(|b| b.map_err(|e| match e {}).boxed())), + Err(error) => Ok(error_response(addr, error)), } } }), @@ -223,14 +338,30 @@ pub async fn serve_stream<T: Unpin + Send + 'static + hyper::rt::Read + hyper::r } } +fn error_response(addr: SocketAddr, error: ServiceError) -> Response<BoxBody<Bytes, ServiceError>> { + { + warn!("service error {addr} {error:?}"); + let mut resp = Response::new(format!( + "Sorry, we were unable to process your request: {error}" + )); + *resp.status_mut() = error.status_code(); + resp.headers_mut() + .insert(CONTENT_TYPE, HeaderValue::from_static("text/plain")); + resp.headers_mut() + .insert(SERVER, HeaderValue::from_static("gnix")); + resp + } + .map(|b| b.map_err(|e| match e {}).boxed()) +} + async fn service( state: Arc<State>, - config: Arc<Config>, - mut request: Request<Incoming>, + mut request: Request<BoxBody<Bytes, ServiceError>>, addr: SocketAddr, secure: bool, listen_addr: SocketAddr, ) -> Result<hyper::Response<BoxBody<bytes::Bytes, ServiceError>>, ServiceError> { + let config = state.config.read().await.clone(); // move uri authority used in HTTP/2 to Host header field { let uri = request.uri_mut(); @@ -257,10 +388,7 @@ async fn service( secure, listen_addr, }; - let mut resp = config - .handler - .handle(&mut context, request.map(|body| body.boxed())) - .await?; + let mut resp = config.handler.handle(&mut context, request).await?; let server_header = resp.headers().get(SERVER).cloned(); resp.headers_mut().insert( diff --git a/src/modules/mod.rs b/src/modules/mod.rs index 44b3c17..b751ba3 100644 --- a/src/modules/mod.rs +++ b/src/modules/mod.rs @@ -26,7 +26,7 @@ mod redirect; mod switch; mod upgrade_insecure; -pub type NodeRequest = Request<BoxBody<Bytes, hyper::Error>>; +pub type NodeRequest = Request<BoxBody<Bytes, ServiceError>>; pub type NodeResponse = Response<BoxBody<Bytes, ServiceError>>; pub static MODULES: &[&dyn NodeKind] = &[ |