summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2025-03-17 20:46:23 +0100
committermetamuffin <metamuffin@disroot.org>2025-03-17 20:46:23 +0100
commit143fe969eb6225c2aa8694930114103f1d4f0c9c (patch)
tree7f430400b464413fc16bd0bb91aad0436685482b
parenta76cab9f30a51b9b4d2377b2d25640c129bf3ab3 (diff)
downloadgnix-143fe969eb6225c2aa8694930114103f1d4f0c9c.tar
gnix-143fe969eb6225c2aa8694930114103f1d4f0c9c.tar.bz2
gnix-143fe969eb6225c2aa8694930114103f1d4f0c9c.tar.zst
h3 ground work
-rw-r--r--Cargo.lock546
-rw-r--r--Cargo.toml3
-rw-r--r--src/error.rs3
-rw-r--r--src/h3_support.rs30
-rw-r--r--src/main.rs180
-rw-r--r--src/modules/mod.rs2
6 files changed, 681 insertions, 83 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 1d53164..470bd68 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -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",
-]
diff --git a/Cargo.toml b/Cargo.toml
index a74ea42..bfcbd30 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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] = &[