basic broadcasting works!
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
This commit is contained in:
parent
2205d60f62
commit
dbc9a2d7a1
15 changed files with 1260 additions and 16 deletions
709
Cargo.lock
generated
709
Cargo.lock
generated
|
@ -35,12 +35,90 @@ dependencies = [
|
||||||
"backtrace",
|
"backtrace",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "async-trait"
|
||||||
|
version = "0.1.64"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1cd7fce9ba8c3c042128ce72d8b2ddbf3a05747efb67ea0313c635e10bda47a2"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "axum"
|
||||||
|
version = "0.6.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e5694b64066a2459918d8074c2ce0d5a88f409431994c2356617c8ae0c4721fc"
|
||||||
|
dependencies = [
|
||||||
|
"async-trait",
|
||||||
|
"axum-core",
|
||||||
|
"axum-macros",
|
||||||
|
"base64 0.20.0",
|
||||||
|
"bitflags",
|
||||||
|
"bytes",
|
||||||
|
"futures-util",
|
||||||
|
"headers",
|
||||||
|
"http",
|
||||||
|
"http-body",
|
||||||
|
"hyper",
|
||||||
|
"itoa",
|
||||||
|
"matchit",
|
||||||
|
"memchr",
|
||||||
|
"mime",
|
||||||
|
"percent-encoding",
|
||||||
|
"pin-project-lite",
|
||||||
|
"rustversion",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"serde_path_to_error",
|
||||||
|
"serde_urlencoded",
|
||||||
|
"sha1",
|
||||||
|
"sync_wrapper",
|
||||||
|
"tokio",
|
||||||
|
"tokio-tungstenite",
|
||||||
|
"tower",
|
||||||
|
"tower-http",
|
||||||
|
"tower-layer",
|
||||||
|
"tower-service",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "axum-core"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1cae3e661676ffbacb30f1a824089a8c9150e71017f7e1e38f2aa32009188d34"
|
||||||
|
dependencies = [
|
||||||
|
"async-trait",
|
||||||
|
"bytes",
|
||||||
|
"futures-util",
|
||||||
|
"http",
|
||||||
|
"http-body",
|
||||||
|
"mime",
|
||||||
|
"rustversion",
|
||||||
|
"tower-layer",
|
||||||
|
"tower-service",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "axum-macros"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9dbcf61bed07d554bd5c225cd07bc41b793eab63e79c6f0ceac7e1aed2f1c670"
|
||||||
|
dependencies = [
|
||||||
|
"heck",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "backtrace"
|
name = "backtrace"
|
||||||
version = "0.3.67"
|
version = "0.3.67"
|
||||||
|
@ -56,18 +134,45 @@ dependencies = [
|
||||||
"rustc-demangle",
|
"rustc-demangle",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "base64"
|
||||||
|
version = "0.13.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "base64"
|
||||||
|
version = "0.20.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0ea22880d78093b0cbe17c89f64a7d457941e65759157ec6cb31a31d652b05e5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "1.3.2"
|
version = "1.3.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "block-buffer"
|
||||||
|
version = "0.10.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bumpalo"
|
name = "bumpalo"
|
||||||
version = "3.11.1"
|
version = "3.11.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba"
|
checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "byteorder"
|
||||||
|
version = "1.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bytes"
|
name = "bytes"
|
||||||
version = "1.3.0"
|
version = "1.3.0"
|
||||||
|
@ -154,6 +259,15 @@ version = "0.8.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
|
checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cpufeatures"
|
||||||
|
version = "0.2.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-channel"
|
name = "crossbeam-channel"
|
||||||
version = "0.5.6"
|
version = "0.5.6"
|
||||||
|
@ -173,6 +287,16 @@ dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crypto-common"
|
||||||
|
version = "0.1.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array",
|
||||||
|
"typenum",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cxx"
|
name = "cxx"
|
||||||
version = "1.0.86"
|
version = "1.0.86"
|
||||||
|
@ -252,6 +376,19 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dashmap"
|
||||||
|
version = "5.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "907076dfda823b0b36d2a1bb5f90c96660a5bbcd7729e10727f07858f22c4edc"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"hashbrown",
|
||||||
|
"lock_api",
|
||||||
|
"once_cell",
|
||||||
|
"parking_lot_core",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "derive_builder"
|
name = "derive_builder"
|
||||||
version = "0.12.0"
|
version = "0.12.0"
|
||||||
|
@ -283,6 +420,16 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "digest"
|
||||||
|
version = "0.10.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f"
|
||||||
|
dependencies = [
|
||||||
|
"block-buffer",
|
||||||
|
"crypto-common",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "errno"
|
name = "errno"
|
||||||
version = "0.2.8"
|
version = "0.2.8"
|
||||||
|
@ -310,6 +457,15 @@ version = "1.0.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "form_urlencoded"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8"
|
||||||
|
dependencies = [
|
||||||
|
"percent-encoding",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures"
|
name = "futures"
|
||||||
version = "0.3.25"
|
version = "0.3.25"
|
||||||
|
@ -399,12 +555,83 @@ dependencies = [
|
||||||
"slab",
|
"slab",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "generic-array"
|
||||||
|
version = "0.14.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9"
|
||||||
|
dependencies = [
|
||||||
|
"typenum",
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getrandom"
|
||||||
|
version = "0.2.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gimli"
|
name = "gimli"
|
||||||
version = "0.27.0"
|
version = "0.27.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dec7af912d60cdbd3677c1af9352ebae6fb8394d165568a2234df0fa00f87793"
|
checksum = "dec7af912d60cdbd3677c1af9352ebae6fb8394d165568a2234df0fa00f87793"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "h2"
|
||||||
|
version = "0.3.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5f9f29bc9dda355256b2916cf526ab02ce0aeaaaf2bad60d65ef3f12f11dd0f4"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"fnv",
|
||||||
|
"futures-core",
|
||||||
|
"futures-sink",
|
||||||
|
"futures-util",
|
||||||
|
"http",
|
||||||
|
"indexmap",
|
||||||
|
"slab",
|
||||||
|
"tokio",
|
||||||
|
"tokio-util",
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.12.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "headers"
|
||||||
|
version = "0.3.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f3e372db8e5c0d213e0cd0b9be18be2aca3d44cf2fe30a9d46a65581cd454584"
|
||||||
|
dependencies = [
|
||||||
|
"base64 0.13.1",
|
||||||
|
"bitflags",
|
||||||
|
"bytes",
|
||||||
|
"headers-core",
|
||||||
|
"http",
|
||||||
|
"httpdate",
|
||||||
|
"mime",
|
||||||
|
"sha1",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "headers-core"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429"
|
||||||
|
dependencies = [
|
||||||
|
"http",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "heck"
|
name = "heck"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
|
@ -420,6 +647,70 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "http"
|
||||||
|
version = "0.2.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"fnv",
|
||||||
|
"itoa",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "http-body"
|
||||||
|
version = "0.4.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"http",
|
||||||
|
"pin-project-lite",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "http-range-header"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0bfe8eed0a9285ef776bb792479ea3834e8b94e13d615c2f66d03dd50a435a29"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "httparse"
|
||||||
|
version = "1.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "httpdate"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hyper"
|
||||||
|
version = "0.14.24"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5e011372fa0b68db8350aa7a248930ecc7839bf46d8485577d69f117a75f164c"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"futures-channel",
|
||||||
|
"futures-core",
|
||||||
|
"futures-util",
|
||||||
|
"h2",
|
||||||
|
"http",
|
||||||
|
"http-body",
|
||||||
|
"httparse",
|
||||||
|
"httpdate",
|
||||||
|
"itoa",
|
||||||
|
"pin-project-lite",
|
||||||
|
"socket2",
|
||||||
|
"tokio",
|
||||||
|
"tower-service",
|
||||||
|
"tracing",
|
||||||
|
"want",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "iana-time-zone"
|
name = "iana-time-zone"
|
||||||
version = "0.1.53"
|
version = "0.1.53"
|
||||||
|
@ -450,6 +741,26 @@ version = "1.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "idna"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-bidi",
|
||||||
|
"unicode-normalization",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "indexmap"
|
||||||
|
version = "1.9.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"hashbrown",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "io-lifetimes"
|
name = "io-lifetimes"
|
||||||
version = "1.0.3"
|
version = "1.0.3"
|
||||||
|
@ -519,24 +830,32 @@ name = "liveterm"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
"axum",
|
||||||
"chrono",
|
"chrono",
|
||||||
"clap",
|
"clap",
|
||||||
|
"dashmap",
|
||||||
"derive_builder",
|
"derive_builder",
|
||||||
"futures",
|
"futures",
|
||||||
|
"lazy_static",
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
"nix",
|
"nix",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
|
"rand",
|
||||||
"serde",
|
"serde",
|
||||||
|
"serde_bytes",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"signal-hook",
|
"signal-hook",
|
||||||
"termios",
|
"termios",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"tokio-tungstenite",
|
||||||
"tokio-util",
|
"tokio-util",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-appender",
|
"tracing-appender",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
|
"tungstenite",
|
||||||
|
"url",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -558,6 +877,12 @@ dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "matchit"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b87248edafb776e59e6ee64a79086f65890d3510f2c656c000bf2a7e8a0aea40"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "2.5.0"
|
version = "2.5.0"
|
||||||
|
@ -573,6 +898,12 @@ dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mime"
|
||||||
|
version = "0.3.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "miniz_oxide"
|
name = "miniz_oxide"
|
||||||
version = "0.6.2"
|
version = "0.6.2"
|
||||||
|
@ -697,6 +1028,32 @@ dependencies = [
|
||||||
"windows-sys",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "percent-encoding"
|
||||||
|
version = "2.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pin-project"
|
||||||
|
version = "1.0.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc"
|
||||||
|
dependencies = [
|
||||||
|
"pin-project-internal",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pin-project-internal"
|
||||||
|
version = "1.0.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pin-project-lite"
|
name = "pin-project-lite"
|
||||||
version = "0.2.9"
|
version = "0.2.9"
|
||||||
|
@ -709,6 +1066,12 @@ version = "0.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ppv-lite86"
|
||||||
|
version = "0.2.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro-error"
|
name = "proc-macro-error"
|
||||||
version = "1.0.4"
|
version = "1.0.4"
|
||||||
|
@ -751,6 +1114,36 @@ dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand"
|
||||||
|
version = "0.8.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"rand_chacha",
|
||||||
|
"rand_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[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",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.6.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_syscall"
|
name = "redox_syscall"
|
||||||
version = "0.2.16"
|
version = "0.2.16"
|
||||||
|
@ -760,6 +1153,21 @@ dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ring"
|
||||||
|
version = "0.16.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"libc",
|
||||||
|
"once_cell",
|
||||||
|
"spin",
|
||||||
|
"untrusted",
|
||||||
|
"web-sys",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-demangle"
|
name = "rustc-demangle"
|
||||||
version = "0.1.21"
|
version = "0.1.21"
|
||||||
|
@ -780,6 +1188,24 @@ dependencies = [
|
||||||
"windows-sys",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustls"
|
||||||
|
version = "0.20.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fff78fc74d175294f4e83b28343315ffcfb114b156f0185e9741cb5570f50e2f"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"ring",
|
||||||
|
"sct",
|
||||||
|
"webpki",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustversion"
|
||||||
|
version = "1.0.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
version = "1.0.12"
|
version = "1.0.12"
|
||||||
|
@ -798,12 +1224,31 @@ version = "1.0.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2"
|
checksum = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sct"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4"
|
||||||
|
dependencies = [
|
||||||
|
"ring",
|
||||||
|
"untrusted",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.152"
|
version = "1.0.152"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
|
checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_bytes"
|
||||||
|
version = "0.11.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "416bda436f9aab92e02c8e10d49a15ddd339cea90b6e340fe51ed97abb548294"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.152"
|
version = "1.0.152"
|
||||||
|
@ -826,6 +1271,38 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_path_to_error"
|
||||||
|
version = "0.1.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "26b04f22b563c91331a10074bda3dd5492e3cc39d56bd557e91c0af42b6c7341"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_urlencoded"
|
||||||
|
version = "0.7.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
|
||||||
|
dependencies = [
|
||||||
|
"form_urlencoded",
|
||||||
|
"itoa",
|
||||||
|
"ryu",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sha1"
|
||||||
|
version = "0.10.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"cpufeatures",
|
||||||
|
"digest",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sharded-slab"
|
name = "sharded-slab"
|
||||||
version = "0.1.4"
|
version = "0.1.4"
|
||||||
|
@ -879,6 +1356,12 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "spin"
|
||||||
|
version = "0.5.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "static_assertions"
|
name = "static_assertions"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
|
@ -902,6 +1385,12 @@ dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sync_wrapper"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "termcolor"
|
name = "termcolor"
|
||||||
version = "1.1.3"
|
version = "1.1.3"
|
||||||
|
@ -920,6 +1409,26 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror"
|
||||||
|
version = "1.0.38"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror-impl",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror-impl"
|
||||||
|
version = "1.0.38"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thread_local"
|
name = "thread_local"
|
||||||
version = "1.1.4"
|
version = "1.1.4"
|
||||||
|
@ -967,6 +1476,21 @@ dependencies = [
|
||||||
"time-core",
|
"time-core",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tinyvec"
|
||||||
|
version = "1.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
|
||||||
|
dependencies = [
|
||||||
|
"tinyvec_macros",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tinyvec_macros"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "tokio"
|
||||||
version = "1.24.1"
|
version = "1.24.1"
|
||||||
|
@ -998,6 +1522,33 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio-rustls"
|
||||||
|
version = "0.23.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59"
|
||||||
|
dependencies = [
|
||||||
|
"rustls",
|
||||||
|
"tokio",
|
||||||
|
"webpki",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio-tungstenite"
|
||||||
|
version = "0.18.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "54319c93411147bced34cb5609a80e0a8e44c5999c93903a81cd866630ec0bfd"
|
||||||
|
dependencies = [
|
||||||
|
"futures-util",
|
||||||
|
"log",
|
||||||
|
"rustls",
|
||||||
|
"tokio",
|
||||||
|
"tokio-rustls",
|
||||||
|
"tungstenite",
|
||||||
|
"webpki",
|
||||||
|
"webpki-roots",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio-util"
|
name = "tokio-util"
|
||||||
version = "0.7.4"
|
version = "0.7.4"
|
||||||
|
@ -1012,6 +1563,53 @@ dependencies = [
|
||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tower"
|
||||||
|
version = "0.4.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c"
|
||||||
|
dependencies = [
|
||||||
|
"futures-core",
|
||||||
|
"futures-util",
|
||||||
|
"pin-project",
|
||||||
|
"pin-project-lite",
|
||||||
|
"tokio",
|
||||||
|
"tower-layer",
|
||||||
|
"tower-service",
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tower-http"
|
||||||
|
version = "0.3.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f873044bf02dd1e8239e9c1293ea39dad76dc594ec16185d0a1bf31d8dc8d858"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"bytes",
|
||||||
|
"futures-core",
|
||||||
|
"futures-util",
|
||||||
|
"http",
|
||||||
|
"http-body",
|
||||||
|
"http-range-header",
|
||||||
|
"pin-project-lite",
|
||||||
|
"tower",
|
||||||
|
"tower-layer",
|
||||||
|
"tower-service",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tower-layer"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tower-service"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tracing"
|
name = "tracing"
|
||||||
version = "0.1.37"
|
version = "0.1.37"
|
||||||
|
@ -1019,6 +1617,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
|
checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
|
"log",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"tracing-attributes",
|
"tracing-attributes",
|
||||||
"tracing-core",
|
"tracing-core",
|
||||||
|
@ -1081,18 +1680,89 @@ dependencies = [
|
||||||
"tracing-log",
|
"tracing-log",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "try-lock"
|
||||||
|
version = "0.2.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tungstenite"
|
||||||
|
version = "0.18.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "30ee6ab729cd4cf0fd55218530c4522ed30b7b6081752839b68fcec8d0960788"
|
||||||
|
dependencies = [
|
||||||
|
"base64 0.13.1",
|
||||||
|
"byteorder",
|
||||||
|
"bytes",
|
||||||
|
"http",
|
||||||
|
"httparse",
|
||||||
|
"log",
|
||||||
|
"rand",
|
||||||
|
"rustls",
|
||||||
|
"sha1",
|
||||||
|
"thiserror",
|
||||||
|
"url",
|
||||||
|
"utf-8",
|
||||||
|
"webpki",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "typenum"
|
||||||
|
version = "1.16.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-bidi"
|
||||||
|
version = "0.3.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.6"
|
version = "1.0.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
|
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-normalization"
|
||||||
|
version = "0.1.22"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
|
||||||
|
dependencies = [
|
||||||
|
"tinyvec",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-width"
|
name = "unicode-width"
|
||||||
version = "0.1.10"
|
version = "0.1.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
|
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "untrusted"
|
||||||
|
version = "0.7.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "url"
|
||||||
|
version = "2.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643"
|
||||||
|
dependencies = [
|
||||||
|
"form_urlencoded",
|
||||||
|
"idna",
|
||||||
|
"percent-encoding",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "utf-8"
|
||||||
|
version = "0.7.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "valuable"
|
name = "valuable"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
@ -1105,6 +1775,16 @@ version = "0.9.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "want"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"try-lock",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasi"
|
name = "wasi"
|
||||||
version = "0.10.0+wasi-snapshot-preview1"
|
version = "0.10.0+wasi-snapshot-preview1"
|
||||||
|
@ -1171,6 +1851,35 @@ version = "0.2.83"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f"
|
checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "web-sys"
|
||||||
|
version = "0.3.60"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f"
|
||||||
|
dependencies = [
|
||||||
|
"js-sys",
|
||||||
|
"wasm-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "webpki"
|
||||||
|
version = "0.22.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd"
|
||||||
|
dependencies = [
|
||||||
|
"ring",
|
||||||
|
"untrusted",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "webpki-roots"
|
||||||
|
version = "0.22.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87"
|
||||||
|
dependencies = [
|
||||||
|
"webpki",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
|
|
|
@ -6,21 +6,29 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = { version = "1.0.68", features = ["backtrace"] }
|
anyhow = { version = "1.0.68", features = ["backtrace"] }
|
||||||
|
axum = { version = "0.6.4", features = ["ws", "http2", "macros", "headers"] }
|
||||||
chrono = "0.4.23"
|
chrono = "0.4.23"
|
||||||
clap = { version = "4.0.32", features = ["derive"] }
|
clap = { version = "4.0.32", features = ["derive"] }
|
||||||
|
dashmap = "5.4.0"
|
||||||
derive_builder = "0.12.0"
|
derive_builder = "0.12.0"
|
||||||
futures = "0.3.25"
|
futures = "0.3.25"
|
||||||
|
lazy_static = "1.4.0"
|
||||||
libc = "0.2.139"
|
libc = "0.2.139"
|
||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
nix = "0.26.1"
|
nix = "0.26.1"
|
||||||
parking_lot = "0.12.1"
|
parking_lot = "0.12.1"
|
||||||
|
rand = "0.8.5"
|
||||||
serde = "1.0.152"
|
serde = "1.0.152"
|
||||||
|
serde_bytes = "0.11.9"
|
||||||
serde_derive = "1.0.152"
|
serde_derive = "1.0.152"
|
||||||
serde_json = "1.0.91"
|
serde_json = "1.0.91"
|
||||||
signal-hook = "0.3.14"
|
signal-hook = "0.3.14"
|
||||||
termios = "0.3.3"
|
termios = "0.3.3"
|
||||||
tokio = { version = "1.24.1", features = ["full"] }
|
tokio = { version = "1.24.1", features = ["full"] }
|
||||||
|
tokio-tungstenite = { version = "0.18.0", features = ["rustls-tls-webpki-roots"] }
|
||||||
tokio-util = { version = "0.7.4", features = ["codec"] }
|
tokio-util = { version = "0.7.4", features = ["codec"] }
|
||||||
tracing = "0.1.37"
|
tracing = "0.1.37"
|
||||||
tracing-appender = "0.2.2"
|
tracing-appender = "0.2.2"
|
||||||
tracing-subscriber = "0.3.16"
|
tracing-subscriber = "0.3.16"
|
||||||
|
tungstenite = "0.18.0"
|
||||||
|
url = "2.3.1"
|
||||||
|
|
|
@ -10,8 +10,9 @@ use serde::{
|
||||||
},
|
},
|
||||||
ser::{Serialize, SerializeSeq, Serializer},
|
ser::{Serialize, SerializeSeq, Serializer},
|
||||||
};
|
};
|
||||||
|
use serde_bytes::ByteBuf;
|
||||||
|
|
||||||
#[derive(Debug, Builder, Serialize)]
|
#[derive(Clone, Debug, Builder, Serialize, Deserialize)]
|
||||||
pub struct Header {
|
pub struct Header {
|
||||||
#[builder(setter(skip))]
|
#[builder(setter(skip))]
|
||||||
pub version: Version,
|
pub version: Version,
|
||||||
|
@ -34,7 +35,7 @@ pub struct Header {
|
||||||
pub theme: Option<Theme>,
|
pub theme: Option<Theme>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Serialize)]
|
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
||||||
pub struct Version(u32);
|
pub struct Version(u32);
|
||||||
|
|
||||||
impl Default for Version {
|
impl Default for Version {
|
||||||
|
@ -43,7 +44,7 @@ impl Default for Version {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct Theme {
|
pub struct Theme {
|
||||||
fg: String,
|
fg: String,
|
||||||
bg: String,
|
bg: String,
|
||||||
|
@ -118,13 +119,13 @@ impl<'d> Deserialize<'d> for Event {
|
||||||
// Must first go through &[u8] then to Vec<u8> because serde_json treats
|
// Must first go through &[u8] then to Vec<u8> because serde_json treats
|
||||||
// &[u8] specially when it comes to deserializing from binary strings
|
// &[u8] specially when it comes to deserializing from binary strings
|
||||||
let data = {
|
let data = {
|
||||||
let data: &'de [u8] = match seq.next_element()? {
|
let data: ByteBuf = match seq.next_element()? {
|
||||||
Some(v) => v,
|
Some(v) => v,
|
||||||
None => {
|
None => {
|
||||||
return Err(A::Error::invalid_length(2, &"an array of length 3"))
|
return Err(A::Error::invalid_length(2, &"an array of length 3"))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
data.to_vec()
|
data.into_vec()
|
||||||
};
|
};
|
||||||
|
|
||||||
let event_kind = match io {
|
let event_kind = match io {
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
|
|
||||||
|
|
||||||
pub mod raw_term;
|
pub mod raw_term;
|
||||||
pub mod recorder;
|
pub mod recorder;
|
||||||
mod terminal;
|
pub mod stream;
|
||||||
|
pub mod terminal;
|
||||||
|
|
|
@ -8,6 +8,9 @@ pub struct RawTerm(RawFd, Termios);
|
||||||
|
|
||||||
impl RawTerm {
|
impl RawTerm {
|
||||||
/// Put the terminal into raw mode.
|
/// Put the terminal into raw mode.
|
||||||
|
///
|
||||||
|
/// I have no idea why these work yet, these are just copied from Python's
|
||||||
|
/// pty.py library
|
||||||
pub fn init(fd: RawFd) -> Result<Self> {
|
pub fn init(fd: RawFd) -> Result<Self> {
|
||||||
use nix::sys::termios::*;
|
use nix::sys::termios::*;
|
||||||
let saved_mode = tcgetattr(fd)?;
|
let saved_mode = tcgetattr(fd)?;
|
||||||
|
|
|
@ -20,7 +20,7 @@ pub struct RecordOpts {
|
||||||
output_file: PathBuf,
|
output_file: PathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn record(opts: RecordOpts) -> Result<()> {
|
pub fn record_main(opts: RecordOpts) -> Result<()> {
|
||||||
let mut file = File::create(&opts.output_file)?;
|
let mut file = File::create(&opts.output_file)?;
|
||||||
|
|
||||||
let mut command = Command::new("zsh");
|
let mut command = Command::new("zsh");
|
||||||
|
|
108
src/client/stream.rs
Normal file
108
src/client/stream.rs
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
use std::sync::mpsc;
|
||||||
|
use std::thread;
|
||||||
|
use std::{collections::HashMap, process::Command};
|
||||||
|
|
||||||
|
use anyhow::{Context, Result};
|
||||||
|
use futures::{SinkExt, StreamExt};
|
||||||
|
use tokio::runtime::Runtime;
|
||||||
|
use tokio_tungstenite::connect_async;
|
||||||
|
use tungstenite::Message as WsMessage;
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
|
use crate::asciicast::HeaderBuilder;
|
||||||
|
use crate::client::terminal::Terminal;
|
||||||
|
use crate::message::Message;
|
||||||
|
|
||||||
|
#[derive(Debug, Parser)]
|
||||||
|
pub struct StreamOpts {}
|
||||||
|
|
||||||
|
pub fn stream_main(opts: StreamOpts) -> Result<()> {
|
||||||
|
let runtime = Runtime::new()?;
|
||||||
|
|
||||||
|
runtime.block_on(stream_async_main(opts))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn stream_async_main(opts: StreamOpts) -> Result<()> {
|
||||||
|
println!("Hellosu {opts:?}");
|
||||||
|
|
||||||
|
// Open a new websocket connection to the server
|
||||||
|
let url = Url::parse(&"ws://localhost:8200/broadcast").unwrap();
|
||||||
|
|
||||||
|
let (ws, _) = connect_async(url).await.context("Failed to connect")?;
|
||||||
|
println!("WebSocket handshake has been successfully completed");
|
||||||
|
|
||||||
|
let (mut write, mut read) = ws.split();
|
||||||
|
|
||||||
|
let mut command = Command::new("zsh");
|
||||||
|
command.env("TERM", "xterm-256color");
|
||||||
|
|
||||||
|
// Write header
|
||||||
|
// TODO: Clean this up
|
||||||
|
let header = {
|
||||||
|
let command_str = format!("{command:?}");
|
||||||
|
let env = command
|
||||||
|
.get_envs()
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|(a, b)| b.map(|b| (a, b)))
|
||||||
|
.map(|(a, b)| {
|
||||||
|
(
|
||||||
|
a.to_string_lossy().to_string(),
|
||||||
|
b.to_string_lossy().to_string(),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect::<HashMap<_, _>>();
|
||||||
|
|
||||||
|
HeaderBuilder::default()
|
||||||
|
.width(30)
|
||||||
|
.height(30)
|
||||||
|
.command(command_str)
|
||||||
|
.env(env)
|
||||||
|
.build()?
|
||||||
|
};
|
||||||
|
|
||||||
|
// Step 1. Send header
|
||||||
|
{
|
||||||
|
let message = Message::AsciicastHeader(header);
|
||||||
|
let ws_message = WsMessage::Text(serde_json::to_string(&message).unwrap());
|
||||||
|
write.send(ws_message).await?;
|
||||||
|
}
|
||||||
|
|
||||||
|
// STep 2. Wait for hellosu
|
||||||
|
{
|
||||||
|
let msg = match read.next().await {
|
||||||
|
Some(v) => v?,
|
||||||
|
None => bail!("wtf bro"),
|
||||||
|
};
|
||||||
|
let msg: Message = match msg {
|
||||||
|
WsMessage::Text(v) => serde_json::from_str(&v)?,
|
||||||
|
_ => bail!("dont send me other Shit!!!"),
|
||||||
|
};
|
||||||
|
let server_hello = match msg {
|
||||||
|
Message::ServerHello(v) => v,
|
||||||
|
_ => bail!("DONT SEND ME OTHER SHIT"),
|
||||||
|
};
|
||||||
|
println!("URL: {:?}", server_hello.url);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 3. Produuuuuuce
|
||||||
|
let (tx, rx) = mpsc::channel();
|
||||||
|
let (pty, rxt) = Terminal::setup(command)?;
|
||||||
|
thread::spawn(move || {
|
||||||
|
for event in rxt.into_iter() {
|
||||||
|
let message = Message::AsciicastEvent(event);
|
||||||
|
let ws_message =
|
||||||
|
WsMessage::Text(serde_json::to_string(&message).unwrap());
|
||||||
|
tx.send(ws_message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
tokio::spawn(async move {
|
||||||
|
for ws_message in rx.into_iter() {
|
||||||
|
write.send(ws_message).await;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
pty.wait_until_complete()?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -114,14 +114,17 @@ impl Terminal {
|
||||||
|
|
||||||
// Set up recording function
|
// Set up recording function
|
||||||
let start_time = Instant::now();
|
let start_time = Instant::now();
|
||||||
let record = |now: Instant, output: bool, data: &[u8]| -> Result<()> {
|
let mut last_frame_time = start_time;
|
||||||
let elapsed = (now - start_time).as_secs_f64();
|
let mut record = |now: Instant, output: bool, data: &[u8]| -> Result<()> {
|
||||||
|
let elapsed = (now - last_frame_time).as_secs_f64();
|
||||||
let event_kind = (match output {
|
let event_kind = (match output {
|
||||||
true => EventKind::Output,
|
true => EventKind::Output,
|
||||||
false => EventKind::Input,
|
false => EventKind::Input,
|
||||||
})(data.to_vec());
|
})(data.to_vec());
|
||||||
let event = Event(elapsed, event_kind);
|
let event = Event(elapsed, event_kind);
|
||||||
self.event_tx.send(event)?;
|
self.event_tx.send(event)?;
|
||||||
|
|
||||||
|
last_frame_time = now;
|
||||||
Ok(())
|
Ok(())
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -11,3 +11,5 @@ extern crate tracing;
|
||||||
|
|
||||||
pub mod asciicast;
|
pub mod asciicast;
|
||||||
pub mod client;
|
pub mod client;
|
||||||
|
pub mod server;
|
||||||
|
pub mod message;
|
||||||
|
|
26
src/main.rs
26
src/main.rs
|
@ -1,6 +1,12 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use clap::{ArgAction, Parser};
|
use clap::{ArgAction, Parser};
|
||||||
use liveterm::client::recorder::{record, RecordOpts};
|
use liveterm::{
|
||||||
|
client::{
|
||||||
|
recorder::{record_main, RecordOpts},
|
||||||
|
stream::{stream_main, StreamOpts},
|
||||||
|
},
|
||||||
|
server::{server_main, ServerOpts},
|
||||||
|
};
|
||||||
use tracing::Level;
|
use tracing::Level;
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
|
@ -15,12 +21,16 @@ struct Opt {
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
enum Subcommand {
|
enum Subcommand {
|
||||||
/// Record terminal session.
|
/// Record terminal session.
|
||||||
#[structopt(name = "rec")]
|
#[structopt(name = "record", alias = "rec")]
|
||||||
Record(RecordOpts),
|
Record(RecordOpts),
|
||||||
|
|
||||||
|
/// Stream to the server
|
||||||
|
#[structopt(name = "stream")]
|
||||||
|
Stream(StreamOpts),
|
||||||
|
|
||||||
/// Run the server.
|
/// Run the server.
|
||||||
#[structopt(name = "server")]
|
#[structopt(name = "server")]
|
||||||
Server,
|
Server(ServerOpts),
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
|
@ -29,10 +39,16 @@ fn main() -> Result<()> {
|
||||||
|
|
||||||
match opt.subcommand {
|
match opt.subcommand {
|
||||||
Subcommand::Record(opts) => {
|
Subcommand::Record(opts) => {
|
||||||
record(opts)?;
|
record_main(opts)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Subcommand::Server => {}
|
Subcommand::Stream(opts) => {
|
||||||
|
stream_main(opts)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Subcommand::Server(opts) => {
|
||||||
|
server_main(opts)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
38
src/message.rs
Normal file
38
src/message.rs
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
use crate::asciicast::{Event, Header, HeaderBuilder, EventKind};
|
||||||
|
|
||||||
|
/// Message used by Liveterm for broadcasts
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
pub enum Message {
|
||||||
|
ServerHello(ServerHello),
|
||||||
|
AsciicastHeader(Header),
|
||||||
|
AsciicastEvent(Event),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
pub struct ServerHello {
|
||||||
|
pub url: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test() {
|
||||||
|
let msg = Message::AsciicastHeader(
|
||||||
|
HeaderBuilder::default()
|
||||||
|
.width(30)
|
||||||
|
.height(30)
|
||||||
|
.build()
|
||||||
|
.unwrap(),
|
||||||
|
);
|
||||||
|
println!("{}", serde_json::to_string(&msg).unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test2() {
|
||||||
|
const msg: &'static str = "{\"AsciicastEvent\":[0.058985141,\"o\",\"\\u001b[1m\\u001b[3m%\\u001b[23m\\u001b[1m\\u001b[0m \\r \\r\"]}";
|
||||||
|
let msg2: Message = serde_json::from_str(&msg).unwrap();
|
||||||
|
if let Message::AsciicastEvent(ref evt) = msg2 {
|
||||||
|
if let EventKind::Output(ref d) = evt.1 {
|
||||||
|
// println!("==> {} <==", String::from_utf8(d.to_vec()).unwrap());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println!("{msg2:?}");
|
||||||
|
}
|
162
src/server/broadcast.rs
Normal file
162
src/server/broadcast.rs
Normal file
|
@ -0,0 +1,162 @@
|
||||||
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
|
|
||||||
|
use anyhow::{Context, Result};
|
||||||
|
use axum::{
|
||||||
|
extract::{
|
||||||
|
ws::{Message as WsMessage, WebSocket},
|
||||||
|
WebSocketUpgrade,
|
||||||
|
},
|
||||||
|
response::Response,
|
||||||
|
};
|
||||||
|
use dashmap::{mapref::entry::Entry, DashMap};
|
||||||
|
use futures::{future::BoxFuture, FutureExt};
|
||||||
|
use rand::{prelude::Distribution, Rng};
|
||||||
|
use serde::Deserialize;
|
||||||
|
use tokio::sync::broadcast::{self, Receiver, Sender};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
asciicast::{Event, Header},
|
||||||
|
message::{Message, ServerHello},
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: Figure out a real data structure to use here
|
||||||
|
lazy_static::lazy_static! {
|
||||||
|
pub static ref BROADCASTS: DashMap<String, Sender<Message>> = DashMap::new();
|
||||||
|
pub static ref LEN: AtomicUsize = AtomicUsize::new(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
const CAPACITY: usize = 1024;
|
||||||
|
|
||||||
|
pub async fn broadcast(ws: WebSocketUpgrade) -> Response {
|
||||||
|
// Generate channels
|
||||||
|
// TODO: Handle lag situation, possibly need to choose different channel
|
||||||
|
// implementation?
|
||||||
|
let (tx, _) = broadcast::channel(CAPACITY);
|
||||||
|
|
||||||
|
// Allocate new room
|
||||||
|
let mut rng = rand::thread_rng();
|
||||||
|
let mut ct = 0;
|
||||||
|
let room_id = loop {
|
||||||
|
let len = LEN.load(Ordering::Relaxed);
|
||||||
|
let room_id = (&mut rng)
|
||||||
|
.sample_iter(RoomIdDistribution)
|
||||||
|
.take(len)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let room_id = unsafe {
|
||||||
|
// Distribution guarantees UTF-8-safety
|
||||||
|
String::from_utf8_unchecked(room_id)
|
||||||
|
};
|
||||||
|
let _entry = match BROADCASTS.entry(room_id.clone()) {
|
||||||
|
Entry::Occupied(_) => {
|
||||||
|
ct += 1;
|
||||||
|
|
||||||
|
// Generous amount for now
|
||||||
|
if ct > 10 {
|
||||||
|
LEN.fetch_add(1, Ordering::Relaxed);
|
||||||
|
ct = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Entry::Vacant(entry) => {
|
||||||
|
entry.insert(tx.clone());
|
||||||
|
break room_id;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
ws.on_upgrade(handle_websocket(room_id, tx))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_message<'d, T>(msg: &'d WsMessage) -> Result<T>
|
||||||
|
where
|
||||||
|
T: Deserialize<'d>,
|
||||||
|
{
|
||||||
|
Ok(match msg {
|
||||||
|
WsMessage::Text(data) => serde_json::from_str(data)?,
|
||||||
|
WsMessage::Binary(data) => serde_json::from_slice(data)?,
|
||||||
|
_ => bail!("for now, protocol does not allow for other message types"),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn handle_websocket_inner(
|
||||||
|
room_id: String,
|
||||||
|
tx: Sender<Message>,
|
||||||
|
mut socket: WebSocket,
|
||||||
|
) -> Result<()> {
|
||||||
|
// Step 1. Read the header
|
||||||
|
let msg: Message = match socket.recv().await {
|
||||||
|
Some(v) => deserialize_message(&v?)?,
|
||||||
|
None => bail!("send a header please..."),
|
||||||
|
};
|
||||||
|
let header: Header = match msg {
|
||||||
|
Message::AsciicastHeader(header) => header,
|
||||||
|
_ => bail!("please send header omg!!!"),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Step 2. Respond with Hellosu
|
||||||
|
let server_hello = Message::ServerHello(ServerHello {
|
||||||
|
url: format!("http://192.168.0.133:8200/watch/{room_id}"),
|
||||||
|
});
|
||||||
|
socket
|
||||||
|
.send(WsMessage::Text(serde_json::to_string(&server_hello)?))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
// Step 3. Consoooome
|
||||||
|
while let Some(msg) = socket.recv().await {
|
||||||
|
// TODO: Consume header
|
||||||
|
|
||||||
|
let msg = msg.context("could not read event message")?;
|
||||||
|
|
||||||
|
trace!(?msg, "parsed event message");
|
||||||
|
|
||||||
|
let msg: Message = match &msg {
|
||||||
|
WsMessage::Text(data) => serde_json::from_str(data),
|
||||||
|
WsMessage::Binary(data) => serde_json::from_slice(data),
|
||||||
|
_ => continue,
|
||||||
|
}
|
||||||
|
.context("could not parse event message from json")?;
|
||||||
|
|
||||||
|
// Ignoring this for now cus it'll error if there's no receivers
|
||||||
|
tx.send(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_websocket<'a>(
|
||||||
|
room_id: String,
|
||||||
|
tx: Sender<Message>,
|
||||||
|
) -> impl FnOnce(WebSocket) -> BoxFuture<'a, ()> {
|
||||||
|
move |socket: WebSocket| {
|
||||||
|
async {
|
||||||
|
match handle_websocket_inner(room_id, tx, socket).await {
|
||||||
|
Ok(_) => {}
|
||||||
|
Err(err) => {
|
||||||
|
eprintln!("Fuck! {err:?}");
|
||||||
|
eprintln!("{err}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.boxed()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cribbed from https://rust-random.github.io/rand/rand/distributions/struct.Alphanumeric.html
|
||||||
|
struct RoomIdDistribution;
|
||||||
|
|
||||||
|
impl Distribution<u8> for RoomIdDistribution {
|
||||||
|
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u8 {
|
||||||
|
const RANGE: u32 = 26 + 26 + 10;
|
||||||
|
const ALLOWED_CHARS: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\
|
||||||
|
abcdefghijklmnopqrstuvwxyz\
|
||||||
|
0123456789\
|
||||||
|
-";
|
||||||
|
loop {
|
||||||
|
let var = rng.next_u32() >> (32 - 6);
|
||||||
|
if var < RANGE {
|
||||||
|
return ALLOWED_CHARS[var as usize];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
34
src/server/error.rs
Normal file
34
src/server/error.rs
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
// Cribbed from https://github.com/tokio-rs/axum/blob/main/examples/anyhow-error-response/src/main.rs
|
||||||
|
|
||||||
|
use axum::{
|
||||||
|
http::StatusCode,
|
||||||
|
response::{IntoResponse, Response},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub type Result<T, E = AppError> = std::result::Result<T, E>;
|
||||||
|
|
||||||
|
/// Make our own error that wraps `anyhow::Error`.
|
||||||
|
pub struct AppError(anyhow::Error);
|
||||||
|
|
||||||
|
// Tell axum how to convert `AppError` into a response.
|
||||||
|
impl IntoResponse for AppError {
|
||||||
|
fn into_response(self) -> Response {
|
||||||
|
(
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
format!("Something went wrong: {}", self.0),
|
||||||
|
)
|
||||||
|
.into_response()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This enables using `?` on functions that return `Result<_, anyhow::Error>` to
|
||||||
|
// turn them into `Result<_, AppError>`. That way you don't need to do that
|
||||||
|
// manually.
|
||||||
|
impl<E> From<E> for AppError
|
||||||
|
where
|
||||||
|
E: Into<anyhow::Error>,
|
||||||
|
{
|
||||||
|
fn from(err: E) -> Self {
|
||||||
|
Self(err.into())
|
||||||
|
}
|
||||||
|
}
|
59
src/server/listen.rs
Normal file
59
src/server/listen.rs
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
use anyhow::{Context, Result};
|
||||||
|
use axum::{
|
||||||
|
extract::{
|
||||||
|
ws::{Message as WsMessage, WebSocket},
|
||||||
|
Path, WebSocketUpgrade,
|
||||||
|
},
|
||||||
|
http::StatusCode,
|
||||||
|
response::Response,
|
||||||
|
};
|
||||||
|
use futures::{future::BoxFuture, FutureExt};
|
||||||
|
use tokio::sync::broadcast::Receiver;
|
||||||
|
|
||||||
|
use crate::message::Message;
|
||||||
|
|
||||||
|
use super::broadcast::BROADCASTS;
|
||||||
|
|
||||||
|
pub async fn listen(
|
||||||
|
Path((room_id,)): Path<(String,)>,
|
||||||
|
ws: WebSocketUpgrade,
|
||||||
|
) -> Result<Response, StatusCode> {
|
||||||
|
let rx = match BROADCASTS.get(&room_id) {
|
||||||
|
Some(v) => (*v).subscribe(),
|
||||||
|
None => return Err(StatusCode::NOT_FOUND),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(ws.on_upgrade(handle_websocket(rx)))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn handle_ws_page_inner(
|
||||||
|
mut rx: Receiver<Message>,
|
||||||
|
mut socket: WebSocket,
|
||||||
|
) -> Result<()> {
|
||||||
|
info!("Started WS connection from website.");
|
||||||
|
|
||||||
|
while let Ok(message) = rx.recv().await {
|
||||||
|
let ws_message = WsMessage::Text(serde_json::to_string(&message)?);
|
||||||
|
info!("[DM->Web] Received WS message from dashmap, forwarding {ws_message:?}");
|
||||||
|
socket.send(ws_message).await?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_websocket<'a>(
|
||||||
|
rx: Receiver<Message>,
|
||||||
|
) -> impl FnOnce(WebSocket) -> BoxFuture<'a, ()> {
|
||||||
|
move |socket: WebSocket| {
|
||||||
|
async {
|
||||||
|
match handle_ws_page_inner(rx, socket).await {
|
||||||
|
Ok(_) => {}
|
||||||
|
Err(err) => {
|
||||||
|
eprintln!("Fuck! {err:?}");
|
||||||
|
eprintln!("{err}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.boxed()
|
||||||
|
}
|
||||||
|
}
|
102
src/server/mod.rs
Normal file
102
src/server/mod.rs
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
pub mod broadcast;
|
||||||
|
pub mod error;
|
||||||
|
pub mod listen;
|
||||||
|
|
||||||
|
use std::net::SocketAddr;
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
use axum::{
|
||||||
|
extract::{Path, WebSocketUpgrade},
|
||||||
|
http::Response,
|
||||||
|
response::Html,
|
||||||
|
routing::{get, post},
|
||||||
|
Router,
|
||||||
|
};
|
||||||
|
use tokio::runtime::Runtime;
|
||||||
|
|
||||||
|
use crate::server::{broadcast::broadcast, listen::listen};
|
||||||
|
|
||||||
|
#[derive(Debug, Parser)]
|
||||||
|
pub struct ServerOpts {
|
||||||
|
/// Address `host:port' to bind to
|
||||||
|
#[clap(long = "bind-addr")]
|
||||||
|
bind_addr: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn server_main(opts: ServerOpts) -> Result<()> {
|
||||||
|
let runtime = Runtime::new()?;
|
||||||
|
|
||||||
|
runtime.block_on(server_async_main(opts))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn server_async_main(opts: ServerOpts) -> Result<()> {
|
||||||
|
println!("Hellosu {opts:?}");
|
||||||
|
|
||||||
|
// build our application with a single route
|
||||||
|
let app = Router::new()
|
||||||
|
.route("/watch/:room_id", get(watch_page))
|
||||||
|
.route("/ws/:room_id", get(listen))
|
||||||
|
.route("/broadcast", get(broadcast));
|
||||||
|
|
||||||
|
// run it with hyper on localhost:8200
|
||||||
|
let addr: SocketAddr = opts
|
||||||
|
.bind_addr
|
||||||
|
.unwrap_or_else(|| String::from("127.0.0.1:8200"))
|
||||||
|
.parse()?;
|
||||||
|
println!("Listening on {addr:?}...");
|
||||||
|
axum::Server::bind(&addr)
|
||||||
|
.serve(app.into_make_service())
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn watch_page(Path((room_id,)): Path<(String,)>) -> Html<String> {
|
||||||
|
let html = format!(
|
||||||
|
r#"
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<link rel="stylesheet" href="https://unpkg.com/xterm@5.1.0/css/xterm.css" integrity="sha384-3K5+KOWDosY1TkoDWxPkGjncHOU5L57iOnkapqUQ7lPzlNYDE05ADJlUh4iRvtqu" crossorigin="anonymous">
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Iosevka/6.0.0/iosevka/iosevka.min.css" integrity="sha512-3hU20586NsplKRzjf2jQN5vTRTI2EsXObrHDOBLGdkiRkneg699BlmBXWGHHFHADCF3TOk2BREsVy7qTkmvQqQ==" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="terminal"></div>
|
||||||
|
|
||||||
|
<script src="https://unpkg.com/xterm@5.1.0/lib/xterm.js" integrity="sha384-ggxzZEYHgGhnf1GQFOr/yGjYsaR4nC7xAKLMxCPTDrd0/Ru8e4IjexJE7b+r1v+2" crossorigin="anonymous"></script>
|
||||||
|
<script>
|
||||||
|
let term = new Terminal({{
|
||||||
|
fontWeight: "400",
|
||||||
|
fontFamily: "Iosevka Web",
|
||||||
|
letterSpacing: 0,
|
||||||
|
}});
|
||||||
|
term.open(document.getElementById('terminal'));
|
||||||
|
term.write('Hello from \x1B[1;3;31mxterm.js\x1B[0m $ ');
|
||||||
|
|
||||||
|
let roomId = "{room_id}";
|
||||||
|
let ws = new WebSocket(`ws://${{location.host}}/ws/${{roomId}}`);
|
||||||
|
ws.addEventListener('open', (_) => {{
|
||||||
|
}});
|
||||||
|
|
||||||
|
ws.addEventListener('message', (msg) => {{
|
||||||
|
console.log('message', msg);
|
||||||
|
let msgdata = JSON.parse(msg.data);
|
||||||
|
if ("AsciicastEvent" in msgdata) {{
|
||||||
|
let [elapsed, type, data] = msgdata["AsciicastEvent"];
|
||||||
|
if (type === "o") {{
|
||||||
|
console.log("writing in", elapsed, "sec", data);
|
||||||
|
setTimeout(() => {{
|
||||||
|
term.write(data);
|
||||||
|
}}, elapsed * 1000)
|
||||||
|
}}
|
||||||
|
}}
|
||||||
|
}});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
|
||||||
|
Html(html)
|
||||||
|
}
|
Loading…
Reference in a new issue