Refactor and restructure the WebTransport code.
Who knows if it actually works.
This commit is contained in:
parent
3f5bc39ffc
commit
5204dbc19c
|
@ -11,7 +11,7 @@ for (let c = 0; c < fingerprintHex.length-1; c += 2) {
|
|||
|
||||
const params = new URLSearchParams(window.location.search)
|
||||
|
||||
const url = params.get("url") || "https://localhost:4443/watch"
|
||||
const url = params.get("url") || "https://127.0.0.1:4443/watch"
|
||||
const canvas = document.querySelector<HTMLCanvasElement>("canvas#video")!
|
||||
|
||||
const player = new Player({
|
||||
|
|
|
@ -2,12 +2,87 @@
|
|||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e579a7752471abc2a8268df8b20005e3eadd975f585398f17efcfd8d4927371"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"anstyle-parse",
|
||||
"anstyle-query",
|
||||
"anstyle-wincon",
|
||||
"colorchoice",
|
||||
"is-terminal",
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41ed9a86bf92ae6580e0a31281f65a1b1d867c0cc68d5346e2ae128dddfa6a7d"
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-parse"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e765fd216e48e067936442276d1d57399e37bce53c264d6fefbe298080cb57ee"
|
||||
dependencies = [
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-query"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b"
|
||||
dependencies = [
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-wincon"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4bcd8291a340dd8ac70e18878bc4501dd7b4ff970cfa21c207d36ece51ea88fd"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
||||
dependencies = [
|
||||
"hermit-abi 0.1.19",
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.12.0"
|
||||
|
@ -26,6 +101,48 @@ version = "1.0.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b802d85aaf3a1cdb02b224ba472ebdea62014fccfcb269b95a4d76443b5ee5a"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14a1a858f532119338887a4b8e1af9c60de8249cd7bafd68036a489e261e37b6"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
"bitflags",
|
||||
"clap_lex",
|
||||
"strsim",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f9644cd56d6b87dbe899ef8b053e331c0637664e9e21a33dfcdc36093f5c5c4"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.15",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a2dd5a6fe8c6e3502f568a6353e5273bbb15193ad9a89e457b9970798efbea1"
|
||||
|
||||
[[package]]
|
||||
name = "cmake"
|
||||
version = "0.1.50"
|
||||
|
@ -35,6 +152,96 @@ dependencies = [
|
|||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colorchoice"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
|
||||
|
||||
[[package]]
|
||||
name = "env_logger"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"humantime",
|
||||
"log",
|
||||
"regex",
|
||||
"termcolor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
|
||||
dependencies = [
|
||||
"errno-dragonfly",
|
||||
"libc",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "errno-dragonfly"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
|
||||
|
||||
[[package]]
|
||||
name = "humantime"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
|
||||
|
||||
[[package]]
|
||||
name = "io-lifetimes"
|
||||
version = "1.0.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220"
|
||||
dependencies = [
|
||||
"hermit-abi 0.3.1",
|
||||
"libc",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "is-terminal"
|
||||
version = "0.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f"
|
||||
dependencies = [
|
||||
"hermit-abi 0.3.1",
|
||||
"io-lifetimes",
|
||||
"rustix",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.61"
|
||||
|
@ -62,6 +269,12 @@ version = "0.2.6"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb"
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.17"
|
||||
|
@ -71,6 +284,24 @@ dependencies = [
|
|||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.8.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"wasi",
|
||||
"windows-sys 0.45.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "octets"
|
||||
version = "0.2.0"
|
||||
|
@ -117,6 +348,23 @@ dependencies = [
|
|||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b1f693b24f6ac912f4893ef08244d70b6067480d2f1a46e950c9691e6749d1d"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.29"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
|
||||
|
||||
[[package]]
|
||||
name = "ring"
|
||||
version = "0.16.20"
|
||||
|
@ -132,6 +380,20 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.37.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85597d61f83914ddeba6a47b3b8ffe7365107221c2e557ed94426489fefb5f77"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"errno",
|
||||
"io-lifetimes",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.160"
|
||||
|
@ -162,6 +424,12 @@ version = "0.5.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.109"
|
||||
|
@ -173,6 +441,26 @@ dependencies = [
|
|||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.8"
|
||||
|
@ -186,12 +474,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
|
||||
|
||||
[[package]]
|
||||
name = "warp-server"
|
||||
name = "utf8parse"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
|
||||
|
||||
[[package]]
|
||||
name = "warp"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"env_logger",
|
||||
"log",
|
||||
"mio",
|
||||
"quiche",
|
||||
"ring",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.84"
|
||||
|
@ -213,7 +518,7 @@ dependencies = [
|
|||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 1.0.109",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
|
@ -235,7 +540,7 @@ checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 1.0.109",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
@ -272,8 +577,149 @@ version = "0.4.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[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-sys"
|
||||
version = "0.45.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
|
||||
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.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.42.2",
|
||||
"windows_aarch64_msvc 0.42.2",
|
||||
"windows_i686_gnu 0.42.2",
|
||||
"windows_i686_msvc 0.42.2",
|
||||
"windows_x86_64_gnu 0.42.2",
|
||||
"windows_x86_64_gnullvm 0.42.2",
|
||||
"windows_x86_64_msvc 0.42.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.48.0",
|
||||
"windows_aarch64_msvc 0.48.0",
|
||||
"windows_i686_gnu 0.48.0",
|
||||
"windows_i686_msvc 0.48.0",
|
||||
"windows_x86_64_gnu 0.48.0",
|
||||
"windows_x86_64_gnullvm 0.48.0",
|
||||
"windows_x86_64_msvc 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
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.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
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.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
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.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[package]
|
||||
name = "warp-server"
|
||||
name = "warp"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
|
@ -7,3 +7,8 @@ edition = "2021"
|
|||
|
||||
[dependencies]
|
||||
quiche = { git = "https://github.com/n8o/quiche.git", branch = "master" } # WebTransport fork
|
||||
clap = { version = "4.0", features = [ "derive" ] }
|
||||
log = { version = "0.4", features = ["std"] }
|
||||
mio = { version = "0.8", features = ["net", "os-poll"] }
|
||||
env_logger = "0.9.3"
|
||||
ring = "0.16"
|
|
@ -0,0 +1,44 @@
|
|||
use std::io;
|
||||
use quiche::h3::webtransport;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
Io(io::Error),
|
||||
Quiche(quiche::Error),
|
||||
WebTransport(webtransport::Error),
|
||||
Server(Server),
|
||||
}
|
||||
|
||||
impl From<io::Error> for Error {
|
||||
fn from(err: io::Error) -> Error {
|
||||
Error::Io(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<quiche::Error> for Error {
|
||||
fn from(err: quiche::Error) -> Error {
|
||||
Error::Quiche(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<webtransport::Error> for Error {
|
||||
fn from(err: webtransport::Error) -> Error {
|
||||
Error::WebTransport(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Custom server error messages.
|
||||
#[derive(Debug)]
|
||||
pub enum Server {
|
||||
InvalidToken,
|
||||
InvalidConnectionID,
|
||||
UnknownConnectionID,
|
||||
}
|
||||
|
||||
impl From<Server> for Error {
|
||||
fn from(err: Server) -> Error {
|
||||
Error::Server(err)
|
||||
}
|
||||
}
|
||||
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
|
@ -0,0 +1,3 @@
|
|||
pub mod error;
|
||||
pub mod server;
|
||||
pub mod session;
|
|
@ -1,3 +1,34 @@
|
|||
fn main() {
|
||||
println!("Hello, world!");
|
||||
use warp::server::Server;
|
||||
|
||||
use clap::Parser;
|
||||
|
||||
/// Search for a pattern in a file and display the lines that contain it.
|
||||
#[derive(Parser)]
|
||||
struct Cli {
|
||||
/// Listen on this address
|
||||
#[arg(short, long, default_value = "127.0.0.1:4443")]
|
||||
addr: String,
|
||||
|
||||
/// Use the certificate file at this path
|
||||
#[arg(short, long, default_value = "../cert/localhost.crt")]
|
||||
cert: String,
|
||||
|
||||
/// Use the private key at this path
|
||||
#[arg(short, long, default_value = "../cert/localhost.key")]
|
||||
key: String,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let args = Cli::parse();
|
||||
|
||||
let server_config = warp::server::Config{
|
||||
addr: args.addr,
|
||||
cert: args.cert,
|
||||
key: args.key,
|
||||
};
|
||||
|
||||
let mut server = Server::new(server_config).unwrap();
|
||||
loop {
|
||||
server.poll().unwrap()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,332 @@
|
|||
use crate::session;
|
||||
use crate::error;
|
||||
|
||||
use session::Session;
|
||||
use error::{Error, Result};
|
||||
|
||||
use std::{io, net};
|
||||
use log;
|
||||
|
||||
use quiche::h3::webtransport;
|
||||
|
||||
const MAX_DATAGRAM_SIZE: usize = 1350;
|
||||
|
||||
pub struct Server {
|
||||
// IO stuff
|
||||
socket: mio::net::UdpSocket,
|
||||
poll: mio::Poll,
|
||||
events: mio::Events,
|
||||
|
||||
// QUIC stuff
|
||||
quic: quiche::Config,
|
||||
sessions: session::Map,
|
||||
seed: ring::hmac::Key, // connection ID seed
|
||||
}
|
||||
|
||||
pub struct Config {
|
||||
pub addr: String,
|
||||
pub cert: String,
|
||||
pub key: String,
|
||||
}
|
||||
|
||||
impl Server {
|
||||
pub fn new(config: Config) -> io::Result<Server> {
|
||||
// Listen on the provided socket address
|
||||
let addr = config.addr.parse().unwrap();
|
||||
let mut socket = mio::net::UdpSocket::bind(addr).unwrap();
|
||||
|
||||
// Setup the event loop.
|
||||
let poll = mio::Poll::new().unwrap();
|
||||
let events = mio::Events::with_capacity(1024);
|
||||
let sessions = session::Map::new();
|
||||
|
||||
poll.registry().register(
|
||||
&mut socket,
|
||||
mio::Token(0),
|
||||
mio::Interest::READABLE,
|
||||
).unwrap();
|
||||
|
||||
// Generate random values for connection IDs.
|
||||
let rng = ring::rand::SystemRandom::new();
|
||||
let seed = ring::hmac::Key::generate(ring::hmac::HMAC_SHA256, &rng).unwrap();
|
||||
|
||||
// Create the configuration for the QUIC connections.
|
||||
let mut quic = quiche::Config::new(quiche::PROTOCOL_VERSION).unwrap();
|
||||
quic.load_cert_chain_from_pem_file(&config.cert).unwrap();
|
||||
quic.load_priv_key_from_pem_file(&config.key).unwrap();
|
||||
quic.set_application_protos(quiche::h3::APPLICATION_PROTOCOL).unwrap();
|
||||
quic.set_max_idle_timeout(5000);
|
||||
quic.set_max_recv_udp_payload_size(MAX_DATAGRAM_SIZE);
|
||||
quic.set_max_send_udp_payload_size(MAX_DATAGRAM_SIZE);
|
||||
quic.set_initial_max_data(10_000_000);
|
||||
quic.set_initial_max_stream_data_bidi_local(1_000_000);
|
||||
quic.set_initial_max_stream_data_bidi_remote(1_000_000);
|
||||
quic.set_initial_max_stream_data_uni(1_000_000);
|
||||
quic.set_initial_max_streams_bidi(100);
|
||||
quic.set_initial_max_streams_uni(100);
|
||||
quic.set_disable_active_migration(true);
|
||||
quic.enable_early_data();
|
||||
quic.enable_dgram(true, 65536, 65536);
|
||||
|
||||
Ok(Server {
|
||||
socket,
|
||||
poll,
|
||||
events,
|
||||
|
||||
quic,
|
||||
sessions,
|
||||
seed
|
||||
})
|
||||
}
|
||||
|
||||
pub fn poll(&mut self) -> io::Result<()> {
|
||||
self.receive().unwrap();
|
||||
self.send().unwrap();
|
||||
self.cleanup().unwrap();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn receive(&mut self) -> io::Result<()> {
|
||||
// Find the shorter timeout from all the active connections.
|
||||
//
|
||||
// TODO: use event loop that properly supports timers
|
||||
let timeout = self.sessions.values().filter_map(|c| c.conn.timeout()).min();
|
||||
|
||||
self.poll.poll(&mut self.events, timeout).unwrap();
|
||||
|
||||
// If the event loop reported no events, it means that the timeout
|
||||
// has expired, so handle it without attempting to read packets. We
|
||||
// will then proceed with the send loop.
|
||||
if self.events.is_empty() {
|
||||
self.sessions.values_mut().for_each(|session| {
|
||||
session.conn.on_timeout()
|
||||
});
|
||||
|
||||
return Ok(())
|
||||
}
|
||||
|
||||
// Read incoming UDP packets from the socket and feed them to quiche,
|
||||
// until there are no more packets to read.
|
||||
loop {
|
||||
match self.receive_once() {
|
||||
Err(Error::Io(e)) if e.kind() == io::ErrorKind::WouldBlock => return Ok(()),
|
||||
Err(e) => log::error!("{:?}", e),
|
||||
Ok(_) => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn receive_once(&mut self) -> Result<()> {
|
||||
let mut src= [0; MAX_DATAGRAM_SIZE];
|
||||
|
||||
let (len, from) = self.socket.recv_from(&mut src).unwrap();
|
||||
let src = &mut src[..len];
|
||||
|
||||
let info = quiche::RecvInfo {
|
||||
to: self.socket.local_addr().unwrap(),
|
||||
from,
|
||||
};
|
||||
|
||||
// Lookup a connection based on the packet's connection ID. If there
|
||||
// is no connection matching, create a new one.
|
||||
let pair = match self.accept(src, from).unwrap() {
|
||||
Some(v) => v,
|
||||
None => return Ok(()),
|
||||
};
|
||||
|
||||
let conn = &mut pair.conn;
|
||||
|
||||
// Process potentially coalesced packets.
|
||||
conn.recv(src, info).unwrap();
|
||||
|
||||
// Create a new HTTP/3 connection as soon as the QUIC connection
|
||||
// is established.
|
||||
if (conn.is_in_early_data() || conn.is_established()) && pair.session.is_none() {
|
||||
let session = webtransport::ServerSession::with_transport(conn).unwrap();
|
||||
pair.session = Some(session);
|
||||
}
|
||||
|
||||
// The `poll` can pull out the events that occurred according to the data passed here.
|
||||
for (_, session) in self.sessions.iter_mut() {
|
||||
session.poll().unwrap();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn accept(&mut self, src: &mut [u8], from: net::SocketAddr) -> error::Result<Option<&mut Session>> {
|
||||
// Parse the QUIC packet's header.
|
||||
let hdr = quiche::Header::from_slice(src, quiche::MAX_CONN_ID_LEN).unwrap();
|
||||
|
||||
let conn_id = ring::hmac::sign(&self.seed, &hdr.dcid);
|
||||
let conn_id = &conn_id.as_ref()[..quiche::MAX_CONN_ID_LEN];
|
||||
let conn_id = conn_id.to_vec().into();
|
||||
|
||||
if self.sessions.contains_key(&hdr.dcid) {
|
||||
let pair = self.sessions.get_mut(&hdr.dcid).unwrap();
|
||||
return Ok(Some(pair))
|
||||
} else if self.sessions.contains_key(&conn_id) {
|
||||
let pair = self.sessions.get_mut(&conn_id).unwrap();
|
||||
return Ok(Some(pair));
|
||||
}
|
||||
|
||||
if hdr.ty != quiche::Type::Initial {
|
||||
return Err(error::Server::UnknownConnectionID.into())
|
||||
}
|
||||
|
||||
let mut dst = [0; MAX_DATAGRAM_SIZE];
|
||||
|
||||
if !quiche::version_is_supported(hdr.version) {
|
||||
let len = quiche::negotiate_version(&hdr.scid, &hdr.dcid, &mut dst).unwrap();
|
||||
let dst= &dst[..len];
|
||||
|
||||
self.socket.send_to(dst, from).unwrap();
|
||||
return Ok(None)
|
||||
}
|
||||
|
||||
let mut scid = [0; quiche::MAX_CONN_ID_LEN];
|
||||
scid.copy_from_slice(&conn_id);
|
||||
|
||||
let scid = quiche::ConnectionId::from_ref(&scid);
|
||||
|
||||
// Token is always present in Initial packets.
|
||||
let token = hdr.token.as_ref().unwrap();
|
||||
|
||||
// Do stateless retry if the client didn't send a token.
|
||||
if token.is_empty() {
|
||||
let new_token = mint_token(&hdr, &from);
|
||||
|
||||
let len = quiche::retry(
|
||||
&hdr.scid,
|
||||
&hdr.dcid,
|
||||
&scid,
|
||||
&new_token,
|
||||
hdr.version,
|
||||
&mut dst,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let dst= &dst[..len];
|
||||
|
||||
self.socket.send_to(dst, from).unwrap();
|
||||
return Ok(None)
|
||||
}
|
||||
|
||||
let odcid = validate_token(&from, token);
|
||||
|
||||
// The token was not valid, meaning the retry failed, so
|
||||
// drop the packet.
|
||||
if odcid.is_none() {
|
||||
return Err(error::Server::InvalidToken.into())
|
||||
}
|
||||
|
||||
if scid.len() != hdr.dcid.len() {
|
||||
return Err(error::Server::InvalidConnectionID.into())
|
||||
}
|
||||
|
||||
// Reuse the source connection ID we sent in the Retry packet,
|
||||
// instead of changing it again.
|
||||
let conn_id= hdr.dcid.clone();
|
||||
let local_addr = self.socket.local_addr().unwrap();
|
||||
|
||||
let conn =
|
||||
quiche::accept(&conn_id, odcid.as_ref(), local_addr, from, &mut self.quic)
|
||||
.unwrap();
|
||||
|
||||
self.sessions.insert(
|
||||
conn_id.clone(),
|
||||
Session {
|
||||
conn,
|
||||
session: None,
|
||||
},
|
||||
);
|
||||
|
||||
let pair = self.sessions.get_mut(&conn_id).unwrap();
|
||||
Ok(Some(pair))
|
||||
}
|
||||
|
||||
fn send(&mut self) -> io::Result<()> {
|
||||
let mut pkt = [0; MAX_DATAGRAM_SIZE];
|
||||
|
||||
// Generate outgoing QUIC packets for all active connections and send
|
||||
// them on the UDP socket, until quiche reports that there are no more
|
||||
// packets to be sent.
|
||||
for session in self.sessions.values_mut() {
|
||||
loop {
|
||||
let (size , info) = session.conn.send(&mut pkt).unwrap();
|
||||
let pkt = &pkt[..size];
|
||||
|
||||
match self.socket.send_to(&pkt, info.to) {
|
||||
Err(err) if err.kind() == io::ErrorKind::WouldBlock => break,
|
||||
Err(err) => return Err(err),
|
||||
Ok(_) => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn cleanup(&mut self) -> io::Result<()> {
|
||||
// Garbage collect closed connections.
|
||||
self.sessions.retain(|_, session| !session.conn.is_closed() );
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Generate a stateless retry token.
|
||||
///
|
||||
/// The token includes the static string `"quiche"` followed by the IP address
|
||||
/// of the client and by the original destination connection ID generated by the
|
||||
/// client.
|
||||
///
|
||||
/// Note that this function is only an example and doesn't do any cryptographic
|
||||
/// authenticate of the token. *It should not be used in production system*.
|
||||
fn mint_token(hdr: &quiche::Header, src: &std::net::SocketAddr) -> Vec<u8> {
|
||||
let mut token = Vec::new();
|
||||
|
||||
token.extend_from_slice(b"quiche");
|
||||
|
||||
let addr = match src.ip() {
|
||||
std::net::IpAddr::V4(a) => a.octets().to_vec(),
|
||||
std::net::IpAddr::V6(a) => a.octets().to_vec(),
|
||||
};
|
||||
|
||||
token.extend_from_slice(&addr);
|
||||
token.extend_from_slice(&hdr.dcid);
|
||||
|
||||
token
|
||||
}
|
||||
|
||||
/// Validates a stateless retry token.
|
||||
///
|
||||
/// This checks that the ticket includes the `"quiche"` static string, and that
|
||||
/// the client IP address matches the address stored in the ticket.
|
||||
///
|
||||
/// Note that this function is only an example and doesn't do any cryptographic
|
||||
/// authenticate of the token. *It should not be used in production system*.
|
||||
fn validate_token<'a>(
|
||||
src: &std::net::SocketAddr, token: &'a [u8],
|
||||
) -> Option<quiche::ConnectionId<'a>> {
|
||||
if token.len() < 6 {
|
||||
return None;
|
||||
}
|
||||
|
||||
if &token[..6] != b"quiche" {
|
||||
return None;
|
||||
}
|
||||
|
||||
let token = &token[6..];
|
||||
|
||||
let addr = match src.ip() {
|
||||
std::net::IpAddr::V4(a) => a.octets().to_vec(),
|
||||
std::net::IpAddr::V6(a) => a.octets().to_vec(),
|
||||
};
|
||||
|
||||
if token.len() < addr.len() || &token[..addr.len()] != addr.as_slice() {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(quiche::ConnectionId::from_ref(&token[addr.len()..]))
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
use crate::error;
|
||||
use error::Result;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use quiche::h3::webtransport;
|
||||
|
||||
pub struct Session {
|
||||
pub conn: quiche::Connection,
|
||||
pub session: Option<webtransport::ServerSession>,
|
||||
}
|
||||
|
||||
pub type Map = HashMap<quiche::ConnectionId<'static>, Session>;
|
||||
|
||||
impl Session {
|
||||
// Process any updates to a session.
|
||||
pub fn poll(&mut self) -> Result<()> {
|
||||
let session = match &mut self.session {
|
||||
Some(s) => s,
|
||||
None => return Ok(()),
|
||||
};
|
||||
|
||||
loop {
|
||||
let event = match session.poll(&mut self.conn) {
|
||||
Err(webtransport::Error::Done) => return Ok(()),
|
||||
Err(e) => return Err(e.into()),
|
||||
Ok(e) => e,
|
||||
};
|
||||
|
||||
match event {
|
||||
webtransport::ServerEvent::ConnectRequest(_req) => {
|
||||
// you can handle request with
|
||||
// req.authority()
|
||||
// req.path()
|
||||
// and you can validate this request with req.origin()
|
||||
session.accept_connect_request(&mut self.conn, None).unwrap();
|
||||
},
|
||||
webtransport::ServerEvent::StreamData(stream_id) => {
|
||||
let mut buf = vec![0; 10000];
|
||||
while let Ok(len) =
|
||||
session.recv_stream_data(&mut self.conn, stream_id, &mut buf)
|
||||
{
|
||||
let stream_data = &buf[0..len];
|
||||
|
||||
// handle stream_data
|
||||
if (stream_id & 0x2) == 0 {
|
||||
// bidirectional stream
|
||||
// you can send data through this stream.
|
||||
session
|
||||
.send_stream_data(&mut self.conn, stream_id, stream_data)
|
||||
.unwrap();
|
||||
} else {
|
||||
// you cannot send data through client-initiated-unidirectional-stream.
|
||||
// so, open new server-initiated-unidirectional-stream, and send data
|
||||
// through it.
|
||||
let new_stream_id =
|
||||
session.open_stream(&mut self.conn, false).unwrap();
|
||||
session
|
||||
.send_stream_data(&mut self.conn, new_stream_id, stream_data)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
webtransport::ServerEvent::StreamFinished(_stream_id) => {
|
||||
// A WebTrnasport stream finished, handle it.
|
||||
}
|
||||
|
||||
webtransport::ServerEvent::Datagram => {
|
||||
let mut buf = vec![0; 1500];
|
||||
while let Ok((in_session, offset, total)) =
|
||||
session.recv_dgram(&mut self.conn, &mut buf)
|
||||
{
|
||||
if in_session {
|
||||
let dgram = &buf[offset..total];
|
||||
dbg!(std::string::String::from_utf8_lossy(dgram));
|
||||
// handle this dgram
|
||||
|
||||
// for instance, you can write echo-server like following
|
||||
session.send_dgram(&mut self.conn, dgram).unwrap();
|
||||
} else {
|
||||
// this dgram is not related to current WebTransport session. ignore.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
webtransport::ServerEvent::SessionReset(_e) => {
|
||||
// Peer reset session stream, handle it.
|
||||
}
|
||||
|
||||
webtransport::ServerEvent::SessionFinished => {
|
||||
// Peer finish session stream, handle it.
|
||||
}
|
||||
|
||||
webtransport::ServerEvent::SessionGoAway => {
|
||||
// Peer signalled it is going away, handle it.
|
||||
}
|
||||
|
||||
webtransport::ServerEvent::Other(_stream_id, _event) => {
|
||||
// Original h3::Event which is not related to WebTransport.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue