mirror of
https://codeberg.org/demostf/sync.git
synced 2026-06-03 16:44:07 +02:00
rewrite with tokio-tungstenite
This commit is contained in:
parent
b0ae2c7927
commit
608a4a1bde
6 changed files with 541 additions and 1125 deletions
623
Cargo.lock
generated
623
Cargo.lock
generated
|
|
@ -30,7 +30,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a"
|
||||
dependencies = [
|
||||
"addr2line",
|
||||
"cfg-if 1.0.0",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"miniz_oxide",
|
||||
"object",
|
||||
|
|
@ -54,12 +54,6 @@ dependencies = [
|
|||
"console",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.6.0"
|
||||
|
|
@ -68,47 +62,19 @@ checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
|
|||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.7.3"
|
||||
version = "0.10.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
|
||||
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
|
||||
dependencies = [
|
||||
"block-padding",
|
||||
"byte-tools",
|
||||
"byteorder",
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-padding"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5"
|
||||
dependencies = [
|
||||
"byte-tools",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "byte-tools"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "0.4.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"iovec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "1.8.0"
|
||||
|
|
@ -124,12 +90,6 @@ dependencies = [
|
|||
"shlex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
|
|
@ -165,12 +125,58 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.8.1"
|
||||
name = "cpufeatures"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
|
||||
checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
|
||||
|
||||
[[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]]
|
||||
name = "dashmap"
|
||||
version = "6.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
"hashbrown",
|
||||
"lock_api",
|
||||
"once_cell",
|
||||
"parking_lot_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "data-encoding"
|
||||
version = "2.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2"
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.10.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
||||
dependencies = [
|
||||
"block-buffer",
|
||||
"crypto-common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -190,18 +196,6 @@ version = "0.3.6"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
|
||||
|
||||
[[package]]
|
||||
name = "enum_dispatch"
|
||||
version = "0.3.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa18ce2bc66555b3218614519ac839ddb759a7d6720732f979ef8d13be147ecd"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.9"
|
||||
|
|
@ -212,18 +206,18 @@ dependencies = [
|
|||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fake-simd"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
|
||||
|
||||
[[package]]
|
||||
name = "fastrand"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4"
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||
|
||||
[[package]]
|
||||
name = "foreign-types"
|
||||
version = "0.3.2"
|
||||
|
|
@ -248,22 +242,6 @@ dependencies = [
|
|||
"percent-encoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fuchsia-zircon"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"fuchsia-zircon-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fuchsia-zircon-sys"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
|
||||
|
||||
[[package]]
|
||||
name = "futures"
|
||||
version = "0.3.31"
|
||||
|
|
@ -355,22 +333,12 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.12.4"
|
||||
version = "0.14.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd"
|
||||
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.1.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"libc",
|
||||
"wasi 0.9.0+wasi-snapshot-preview1",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -379,9 +347,9 @@ version = "0.2.15"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -390,12 +358,29 @@ version = "0.31.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
|
||||
|
||||
[[package]]
|
||||
name = "http"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"fnv",
|
||||
"itoa",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "httparse"
|
||||
version = "1.9.5"
|
||||
|
|
@ -541,43 +526,18 @@ dependencies = [
|
|||
"icu_properties",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iovec"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "540654e97a3f4470a492cd30ff187bc95d89557a903a2bbf112e2fae98104ef2"
|
||||
|
||||
[[package]]
|
||||
name = "kernel32-sys"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
||||
dependencies = [
|
||||
"winapi 0.2.8",
|
||||
"winapi-build",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||
|
||||
[[package]]
|
||||
name = "lazycell"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.164"
|
||||
|
|
@ -592,9 +552,19 @@ checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
|
|||
|
||||
[[package]]
|
||||
name = "litemap"
|
||||
version = "0.7.3"
|
||||
version = "0.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704"
|
||||
checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
|
|
@ -602,6 +572,12 @@ version = "0.4.22"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
|
||||
|
||||
[[package]]
|
||||
name = "main_error"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "155db5e86c6e45ee456bf32fad5a290ee1f7151c2faca27ea27097568da67d1a"
|
||||
|
||||
[[package]]
|
||||
name = "maplit"
|
||||
version = "1.0.2"
|
||||
|
|
@ -623,25 +599,6 @@ dependencies = [
|
|||
"adler2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.6.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.10",
|
||||
"fuchsia-zircon",
|
||||
"fuchsia-zircon-sys",
|
||||
"iovec",
|
||||
"kernel32-sys",
|
||||
"libc",
|
||||
"log",
|
||||
"miow",
|
||||
"net2",
|
||||
"slab",
|
||||
"winapi 0.2.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "1.0.2"
|
||||
|
|
@ -650,34 +607,10 @@ checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec"
|
|||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
"wasi",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mio-extras"
|
||||
version = "2.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19"
|
||||
dependencies = [
|
||||
"lazycell",
|
||||
"log",
|
||||
"mio 0.6.23",
|
||||
"slab",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miow"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d"
|
||||
dependencies = [
|
||||
"kernel32-sys",
|
||||
"net2",
|
||||
"winapi 0.2.8",
|
||||
"ws2_32-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "native-tls"
|
||||
version = "0.2.12"
|
||||
|
|
@ -696,14 +629,13 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "net2"
|
||||
version = "0.2.39"
|
||||
name = "nu-ansi-term"
|
||||
version = "0.46.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b13b648036a2339d06de780866fbdfda0dde886de7b3af2ddeba8b14f4ee34ac"
|
||||
checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.10",
|
||||
"libc",
|
||||
"winapi 0.3.9",
|
||||
"overload",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -721,20 +653,14 @@ version = "1.20.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
|
||||
|
||||
[[package]]
|
||||
name = "opaque-debug"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
|
||||
|
||||
[[package]]
|
||||
name = "openssl"
|
||||
version = "0.10.68"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"cfg-if 1.0.0",
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
"foreign-types",
|
||||
"libc",
|
||||
"once_cell",
|
||||
|
|
@ -772,21 +698,22 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "parity-ws"
|
||||
version = "0.11.1"
|
||||
name = "overload"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5983d3929ad50f12c3eb9a6743f19d691866ecd44da74c0a3308c3f8a56df0c6"
|
||||
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.9.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"bytes 0.4.12",
|
||||
"httparse",
|
||||
"log",
|
||||
"mio 0.6.23",
|
||||
"mio-extras",
|
||||
"rand 0.7.3",
|
||||
"sha-1",
|
||||
"slab",
|
||||
"url",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"smallvec",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -819,7 +746,7 @@ version = "0.1.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "be97d76faf1bfab666e1375477b23fde79eccf0276e9b63b92a39d676a889ba9"
|
||||
dependencies = [
|
||||
"rand 0.8.5",
|
||||
"rand",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -849,19 +776,6 @@ dependencies = [
|
|||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
|
||||
dependencies = [
|
||||
"getrandom 0.1.16",
|
||||
"libc",
|
||||
"rand_chacha 0.2.2",
|
||||
"rand_core 0.5.1",
|
||||
"rand_hc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.5"
|
||||
|
|
@ -869,18 +783,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha 0.3.1",
|
||||
"rand_core 0.6.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core 0.5.1",
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -890,16 +794,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core 0.6.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
|
||||
dependencies = [
|
||||
"getrandom 0.1.16",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -908,16 +803,16 @@ version = "0.6.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
dependencies = [
|
||||
"getrandom 0.2.15",
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_hc"
|
||||
version = "0.2.0"
|
||||
name = "redox_syscall"
|
||||
version = "0.5.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
|
||||
checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f"
|
||||
dependencies = [
|
||||
"rand_core 0.5.1",
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -932,7 +827,7 @@ version = "0.38.41"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"bitflags",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
|
|
@ -954,13 +849,19 @@ dependencies = [
|
|||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "security-framework"
|
||||
version = "2.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"bitflags",
|
||||
"core-foundation",
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
|
|
@ -1009,18 +910,6 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha-1"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df"
|
||||
dependencies = [
|
||||
"block-buffer",
|
||||
"digest",
|
||||
"fake-simd",
|
||||
"opaque-debug",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha1"
|
||||
version = "0.6.1"
|
||||
|
|
@ -1030,12 +919,32 @@ dependencies = [
|
|||
"sha1_smol",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha1"
|
||||
version = "0.10.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha1_smol"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d"
|
||||
|
||||
[[package]]
|
||||
name = "sharded-slab"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.3.0"
|
||||
|
|
@ -1089,12 +998,19 @@ name = "sync"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"better-panic",
|
||||
"enum_dispatch",
|
||||
"dashmap",
|
||||
"futures-channel",
|
||||
"futures-util",
|
||||
"log",
|
||||
"main_error",
|
||||
"maplit",
|
||||
"parity-ws",
|
||||
"portpicker",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tokio",
|
||||
"tokio-tungstenite",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
"websocket-lite",
|
||||
]
|
||||
|
||||
|
|
@ -1115,13 +1031,43 @@ version = "3.14.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cfg-if",
|
||||
"fastrand",
|
||||
"once_cell",
|
||||
"rustix",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "1.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinystr"
|
||||
version = "0.7.6"
|
||||
|
|
@ -1139,14 +1085,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"bytes 1.8.0",
|
||||
"bytes",
|
||||
"libc",
|
||||
"mio 1.0.2",
|
||||
"mio",
|
||||
"pin-project-lite",
|
||||
"socket2",
|
||||
"tokio-macros",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-macros"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-native-tls"
|
||||
version = "0.3.1"
|
||||
|
|
@ -1157,19 +1115,106 @@ dependencies = [
|
|||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-tungstenite"
|
||||
version = "0.24.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "edc5f74e248dc973e0dbb7b74c7e0d6fcc301c694ff50049504004ef4d0cdcd9"
|
||||
dependencies = [
|
||||
"futures-util",
|
||||
"log",
|
||||
"tokio",
|
||||
"tungstenite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-util"
|
||||
version = "0.7.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a"
|
||||
dependencies = [
|
||||
"bytes 1.8.0",
|
||||
"bytes",
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
"pin-project-lite",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing"
|
||||
version = "0.1.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
|
||||
dependencies = [
|
||||
"pin-project-lite",
|
||||
"tracing-attributes",
|
||||
"tracing-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-attributes"
|
||||
version = "0.1.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-core"
|
||||
version = "0.1.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"valuable",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-log"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
|
||||
dependencies = [
|
||||
"log",
|
||||
"once_cell",
|
||||
"tracing-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-subscriber"
|
||||
version = "0.3.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b"
|
||||
dependencies = [
|
||||
"nu-ansi-term",
|
||||
"sharded-slab",
|
||||
"smallvec",
|
||||
"thread_local",
|
||||
"tracing-core",
|
||||
"tracing-log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tungstenite"
|
||||
version = "0.24.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "18e5b8366ee7a95b16d32197d0b2604b43a0be89dc5fac9f8e96ccafbaedda8a"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"bytes",
|
||||
"data-encoding",
|
||||
"http",
|
||||
"httparse",
|
||||
"log",
|
||||
"rand",
|
||||
"sha1 0.10.6",
|
||||
"thiserror",
|
||||
"utf-8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.17.0"
|
||||
|
|
@ -1184,15 +1229,21 @@ checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
|
|||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "2.5.3"
|
||||
version = "2.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8d157f1b96d14500ffdc1f10ba712e780825526c03d9a49b4d0324b0d9113ada"
|
||||
checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60"
|
||||
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]]
|
||||
name = "utf16_iter"
|
||||
version = "1.0.5"
|
||||
|
|
@ -1205,6 +1256,12 @@ version = "1.0.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
|
||||
|
||||
[[package]]
|
||||
name = "valuable"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
|
||||
|
||||
[[package]]
|
||||
name = "vcpkg"
|
||||
version = "0.2.15"
|
||||
|
|
@ -1212,10 +1269,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.9.0+wasi-snapshot-preview1"
|
||||
name = "version_check"
|
||||
version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
|
||||
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
|
|
@ -1231,10 +1288,10 @@ checksum = "2108c9c18a6e746addc085c18cedb66b672e8ffea6a993712decc295b0d8ae55"
|
|||
dependencies = [
|
||||
"base64",
|
||||
"byteorder",
|
||||
"bytes 1.8.0",
|
||||
"bytes",
|
||||
"httparse",
|
||||
"rand 0.8.5",
|
||||
"sha1",
|
||||
"rand",
|
||||
"sha1 0.6.1",
|
||||
"tokio-util",
|
||||
]
|
||||
|
||||
|
|
@ -1245,10 +1302,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "1d6cae39139c6e837afebd915935e7adc8af5c28425935de606d0e8c9d3268f6"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"bytes 1.8.0",
|
||||
"bytes",
|
||||
"futures",
|
||||
"native-tls",
|
||||
"rand 0.8.5",
|
||||
"rand",
|
||||
"tokio",
|
||||
"tokio-native-tls",
|
||||
"tokio-util",
|
||||
|
|
@ -1256,12 +1313,6 @@ dependencies = [
|
|||
"websocket-codec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
|
|
@ -1272,12 +1323,6 @@ dependencies = [
|
|||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-build"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
|
|
@ -1384,21 +1429,11 @@ version = "0.5.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51"
|
||||
|
||||
[[package]]
|
||||
name = "ws2_32-sys"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
|
||||
dependencies = [
|
||||
"winapi 0.2.8",
|
||||
"winapi-build",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yoke"
|
||||
version = "0.7.4"
|
||||
version = "0.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5"
|
||||
checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"stable_deref_trait",
|
||||
|
|
@ -1408,9 +1443,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "yoke-derive"
|
||||
version = "0.7.4"
|
||||
version = "0.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95"
|
||||
checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
|
@ -1441,18 +1476,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "zerofrom"
|
||||
version = "0.1.4"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55"
|
||||
checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e"
|
||||
dependencies = [
|
||||
"zerofrom-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerofrom-derive"
|
||||
version = "0.1.4"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5"
|
||||
checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
|
|
|||
13
Cargo.toml
13
Cargo.toml
|
|
@ -2,13 +2,20 @@
|
|||
name = "sync"
|
||||
version = "0.1.0"
|
||||
authors = ["Robin Appelman <robin@icewind.nl>"]
|
||||
edition = "2018"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
parity-ws = "0.11"
|
||||
tokio = { version = "1.41.1", features = ["rt-multi-thread", "macros", "sync"] }
|
||||
tokio-tungstenite = "0.24.0"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
enum_dispatch = "0.3"
|
||||
dashmap = "6.1.0"
|
||||
tracing = "0.1.40"
|
||||
tracing-subscriber = "0.3.18"
|
||||
main_error = "0.1.2"
|
||||
futures-channel = "0.3.31"
|
||||
log = "0.4.22"
|
||||
futures-util = "0.3.31"
|
||||
|
||||
[dev-dependencies]
|
||||
maplit = "1"
|
||||
|
|
|
|||
120
src/client.rs
120
src/client.rs
|
|
@ -1,120 +0,0 @@
|
|||
use enum_dispatch::enum_dispatch;
|
||||
use parity_ws::{util::Token, Result, Sender};
|
||||
|
||||
#[enum_dispatch(Client)]
|
||||
pub(crate) trait ClientTrait {
|
||||
#[allow(clippy::result_large_err)]
|
||||
fn send(&self, msg: &str) -> Result<()>;
|
||||
|
||||
fn token(&self) -> Token;
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Clone, Debug)]
|
||||
pub(crate) struct SenderClient(Sender);
|
||||
|
||||
impl ClientTrait for SenderClient {
|
||||
fn send(&self, msg: &str) -> Result<()> {
|
||||
self.0.send(msg)
|
||||
}
|
||||
|
||||
fn token(&self) -> Token {
|
||||
self.0.token()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Sender> for SenderClient {
|
||||
fn from(sender: Sender) -> Self {
|
||||
SenderClient(sender)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod mock {
|
||||
use crate::client::ClientTrait;
|
||||
use crate::SyncCommand;
|
||||
use parity_ws::{util::Token, Result};
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub(crate) struct MockClient {
|
||||
received: Rc<RefCell<Vec<String>>>,
|
||||
token: Token,
|
||||
}
|
||||
|
||||
impl PartialEq for MockClient {
|
||||
fn eq(&self, other: &MockClient) -> bool {
|
||||
self.token == other.token
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientTrait for MockClient {
|
||||
fn send(&self, msg: &str) -> Result<()> {
|
||||
self.received.borrow_mut().push(msg.into());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn token(&self) -> Token {
|
||||
self.token
|
||||
}
|
||||
}
|
||||
|
||||
impl MockClient {
|
||||
pub fn new(token: usize) -> Self {
|
||||
MockClient {
|
||||
received: Rc::new(RefCell::new(Vec::new())),
|
||||
token: Token(token),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn received_count(&self) -> usize {
|
||||
RefCell::borrow(&self.received).len()
|
||||
}
|
||||
|
||||
pub fn assert_received(&self, expected: Vec<SyncCommand>) {
|
||||
let map = RefCell::borrow(&self.received);
|
||||
|
||||
let received: Vec<_> = map
|
||||
.iter()
|
||||
.map(|msg| serde_json::from_str::<SyncCommand>(msg).expect("invalid message"))
|
||||
.collect();
|
||||
|
||||
assert_eq!(expected, received);
|
||||
}
|
||||
|
||||
pub fn clear(&self) {
|
||||
self.received.borrow_mut().clear()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) use mock::MockClient;
|
||||
|
||||
#[cfg(not(test))]
|
||||
#[enum_dispatch]
|
||||
#[derive(PartialEq, Clone, Debug)]
|
||||
pub(crate) enum Client {
|
||||
Sender(SenderClient),
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[enum_dispatch]
|
||||
#[derive(PartialEq, Clone, Debug)]
|
||||
pub(crate) enum Client {
|
||||
Sender(SenderClient),
|
||||
Mock(MockClient),
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
impl Client {
|
||||
pub fn mock(token: usize) -> Self {
|
||||
Client::Mock(MockClient::new(token))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Sender> for Client {
|
||||
fn from(sender: Sender) -> Self {
|
||||
Client::Sender(sender.into())
|
||||
}
|
||||
}
|
||||
|
|
@ -1,175 +0,0 @@
|
|||
use crate::{spawn_local_server, SyncCommand};
|
||||
use parity_ws::Sender;
|
||||
use portpicker::pick_unused_port;
|
||||
use std::thread::sleep;
|
||||
use std::time::Duration;
|
||||
use websocket_lite::{Client, ClientBuilder, Message, NetworkStream};
|
||||
|
||||
const DELAY: Duration = Duration::from_millis(50);
|
||||
|
||||
struct TestHandle {
|
||||
server_sender: Sender,
|
||||
connect: String,
|
||||
}
|
||||
|
||||
impl TestHandle {
|
||||
pub fn new() -> Self {
|
||||
better_panic::install();
|
||||
|
||||
let port = pick_unused_port().expect("No ports free");
|
||||
|
||||
let server_sender = spawn_local_server(port);
|
||||
|
||||
// give the server some time to start
|
||||
sleep(DELAY);
|
||||
|
||||
TestHandle {
|
||||
server_sender,
|
||||
connect: format!("ws://localhost:{}", port),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_client(&self) -> Client<Box<dyn NetworkStream + Sync + Send + 'static>> {
|
||||
ClientBuilder::new(&self.connect)
|
||||
.unwrap()
|
||||
.connect()
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for TestHandle {
|
||||
fn drop(&mut self) {
|
||||
self.server_sender.shutdown().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn integration_tests() {
|
||||
let test = TestHandle::new();
|
||||
let mut owner = test.get_client();
|
||||
let mut client = test.get_client();
|
||||
|
||||
send(
|
||||
&mut owner,
|
||||
SyncCommand::Create {
|
||||
session: "foo",
|
||||
token: "bar",
|
||||
},
|
||||
);
|
||||
send(
|
||||
&mut owner,
|
||||
SyncCommand::Tick {
|
||||
session: "foo",
|
||||
tick: 99,
|
||||
},
|
||||
);
|
||||
|
||||
send(&mut client, SyncCommand::Join { session: "foo" });
|
||||
|
||||
assert_receive(
|
||||
&mut client,
|
||||
SyncCommand::Tick {
|
||||
session: "foo",
|
||||
tick: 99,
|
||||
},
|
||||
);
|
||||
assert_receive(
|
||||
&mut client,
|
||||
SyncCommand::Play {
|
||||
session: "foo",
|
||||
play: false,
|
||||
},
|
||||
);
|
||||
|
||||
send(
|
||||
&mut owner,
|
||||
SyncCommand::Play {
|
||||
session: "foo",
|
||||
play: true,
|
||||
},
|
||||
);
|
||||
assert_receive(
|
||||
&mut client,
|
||||
SyncCommand::Play {
|
||||
session: "foo",
|
||||
play: true,
|
||||
},
|
||||
);
|
||||
|
||||
// should be ignored
|
||||
send(
|
||||
&mut client,
|
||||
SyncCommand::Tick {
|
||||
session: "foo",
|
||||
tick: 5,
|
||||
},
|
||||
);
|
||||
|
||||
let mut client2 = test.get_client();
|
||||
|
||||
send(&mut client2, SyncCommand::Join { session: "foo" });
|
||||
|
||||
assert_receive(
|
||||
&mut client2,
|
||||
SyncCommand::Tick {
|
||||
session: "foo",
|
||||
tick: 99,
|
||||
},
|
||||
);
|
||||
assert_receive(
|
||||
&mut client2,
|
||||
SyncCommand::Play {
|
||||
session: "foo",
|
||||
play: true,
|
||||
},
|
||||
);
|
||||
|
||||
// owner reconnecting
|
||||
std::mem::drop(owner);
|
||||
|
||||
let mut owner2 = test.get_client();
|
||||
|
||||
send(
|
||||
&mut owner2,
|
||||
SyncCommand::Create {
|
||||
session: "foo",
|
||||
token: "bar",
|
||||
},
|
||||
);
|
||||
|
||||
send(
|
||||
&mut owner2,
|
||||
SyncCommand::Play {
|
||||
session: "foo",
|
||||
play: false,
|
||||
},
|
||||
);
|
||||
|
||||
assert_receive(
|
||||
&mut client,
|
||||
SyncCommand::Play {
|
||||
session: "foo",
|
||||
play: false,
|
||||
},
|
||||
);
|
||||
assert_receive(
|
||||
&mut client2,
|
||||
SyncCommand::Play {
|
||||
session: "foo",
|
||||
play: false,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
fn send<T: std::io::Write>(client: &mut Client<T>, command: SyncCommand) {
|
||||
client
|
||||
.send(Message::text(serde_json::to_string(&command).unwrap()))
|
||||
.unwrap();
|
||||
sleep(DELAY);
|
||||
}
|
||||
|
||||
fn assert_receive<T: std::io::Read>(client: &mut Client<T>, expected: SyncCommand) {
|
||||
let message = client.receive().unwrap().unwrap();
|
||||
let text = message.as_text().unwrap();
|
||||
assert_eq!(expected, serde_json::from_str(text).unwrap());
|
||||
}
|
||||
723
src/main.rs
723
src/main.rs
|
|
@ -1,14 +1,25 @@
|
|||
mod session;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use parity_ws::{listen, util::Token, CloseCode, Error, Handler, Message, Result};
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
|
||||
mod client;
|
||||
|
||||
use client::{Client, ClientTrait};
|
||||
use std::cell::RefCell;
|
||||
use crate::session::Session;
|
||||
use dashmap::DashMap;
|
||||
use futures_channel::mpsc::{channel, Sender};
|
||||
use futures_util::future::select;
|
||||
use futures_util::StreamExt;
|
||||
use futures_util::TryStreamExt;
|
||||
use main_error::MainResult;
|
||||
use std::net::{Ipv4Addr, SocketAddr};
|
||||
use std::pin::pin;
|
||||
use std::sync::Arc;
|
||||
use std::time::{Duration, Instant};
|
||||
use tokio::net::{TcpListener, TcpStream};
|
||||
use tokio_tungstenite::tungstenite::Message;
|
||||
use tracing::{debug, error, info, instrument, warn};
|
||||
|
||||
type Tx = Sender<Message>;
|
||||
type PeerMap = DashMap<SocketAddr, Tx>;
|
||||
type Sessions = DashMap<String, Session>;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
|
||||
#[serde(tag = "type")]
|
||||
|
|
@ -20,573 +31,153 @@ pub enum SyncCommand<'a> {
|
|||
Play { session: &'a str, play: bool },
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
struct Session {
|
||||
owner: Token,
|
||||
owner_token: String,
|
||||
clients: HashMap<Token, Client>,
|
||||
tick: u64,
|
||||
playing: bool,
|
||||
owner_left: Option<Instant>,
|
||||
pub struct Server {
|
||||
peers: PeerMap,
|
||||
sessions: Sessions,
|
||||
}
|
||||
|
||||
impl Session {
|
||||
pub fn new(owner: Token, owner_token: String) -> Self {
|
||||
Session {
|
||||
owner,
|
||||
owner_token,
|
||||
clients: HashMap::new(),
|
||||
playing: false,
|
||||
tick: 0,
|
||||
owner_left: None,
|
||||
impl Server {
|
||||
fn new() -> Self {
|
||||
Server {
|
||||
peers: PeerMap::with_capacity(128),
|
||||
sessions: Sessions::with_capacity(64),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn join(&mut self, client: &Client) {
|
||||
self.clients.insert(client.token(), client.clone());
|
||||
}
|
||||
}
|
||||
|
||||
impl Session {
|
||||
pub fn send_command(&self, command: &SyncCommand) {
|
||||
let command_text = serde_json::to_string(command).unwrap();
|
||||
for client in self.clients.values() {
|
||||
client.send(&command_text).ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Server {
|
||||
out: Client,
|
||||
sessions: Rc<RefCell<HashMap<String, Session>>>,
|
||||
}
|
||||
|
||||
fn handle_command(
|
||||
command: SyncCommand,
|
||||
sender: &Client,
|
||||
sessions: &RefCell<HashMap<String, Session>>,
|
||||
) {
|
||||
match &command {
|
||||
SyncCommand::Create { session, token } => {
|
||||
sessions
|
||||
.borrow_mut()
|
||||
.entry(session.to_string())
|
||||
.and_modify(|session| {
|
||||
if token == &session.owner_token {
|
||||
session.owner = sender.token();
|
||||
session.owner_left = None;
|
||||
}
|
||||
})
|
||||
.or_insert_with(|| Session::new(sender.token(), token.to_string()));
|
||||
gc_sessions(sessions);
|
||||
}
|
||||
SyncCommand::Join {
|
||||
session: session_name,
|
||||
} => match sessions.borrow_mut().get_mut(*session_name) {
|
||||
Some(session) => {
|
||||
let _ = sender.send(
|
||||
&serde_json::to_string(&SyncCommand::Tick {
|
||||
tick: session.tick,
|
||||
session: session_name,
|
||||
})
|
||||
.unwrap(),
|
||||
);
|
||||
let _ = sender.send(
|
||||
&serde_json::to_string(&SyncCommand::Play {
|
||||
play: session.playing,
|
||||
session: session_name,
|
||||
})
|
||||
.unwrap(),
|
||||
);
|
||||
session.join(sender);
|
||||
fn send_text<S: Into<String>>(&self, peer: &SocketAddr, text: S) {
|
||||
if let Some(mut tx) = self.peers.get_mut(peer) {
|
||||
if let Err(e) = tx.try_send(Message::Text(text.into())) {
|
||||
error!(%peer, ?e, "failed to send message to client")
|
||||
}
|
||||
None => println!("session {} not found", session_name),
|
||||
},
|
||||
SyncCommand::Tick {
|
||||
tick,
|
||||
session: session_name,
|
||||
} => update_session_and_forward(
|
||||
sender,
|
||||
sessions,
|
||||
session_name,
|
||||
|session| session.tick = *tick,
|
||||
&command,
|
||||
),
|
||||
SyncCommand::Play {
|
||||
play,
|
||||
session: session_name,
|
||||
} => update_session_and_forward(
|
||||
sender,
|
||||
sessions,
|
||||
session_name,
|
||||
|session| session.playing = *play,
|
||||
&command,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn send_command(&self, peer: &SocketAddr, command: &SyncCommand) {
|
||||
self.send_text(peer, serde_json::to_string(command).unwrap())
|
||||
}
|
||||
|
||||
pub fn send_to_clients(&self, session: &Session, command: &SyncCommand) {
|
||||
let command_text = serde_json::to_string(command).unwrap();
|
||||
for peer in session.clients() {
|
||||
self.send_text(peer, &command_text);
|
||||
}
|
||||
}
|
||||
|
||||
async fn handle_command<'a>(&self, command: SyncCommand<'_>, sender: SocketAddr) {
|
||||
match &command {
|
||||
SyncCommand::Create { session, token } => {
|
||||
self.sessions
|
||||
.entry(session.to_string())
|
||||
.and_modify(|session| {
|
||||
if !session.set_owner(sender, token) {
|
||||
warn!(%sender, token, "invalid owner token");
|
||||
}
|
||||
})
|
||||
.or_insert_with(|| Session::new(sender, (*session).into(), token.to_string()));
|
||||
self.gc_sessions();
|
||||
}
|
||||
SyncCommand::Join {
|
||||
session: session_name,
|
||||
} => match self.sessions.get_mut(*session_name) {
|
||||
Some(mut session) => {
|
||||
for initial_command in session.initial_state() {
|
||||
self.send_command(&sender, &initial_command);
|
||||
}
|
||||
session.join(sender);
|
||||
}
|
||||
None => error!(session = session_name, "session not found for command"),
|
||||
},
|
||||
session_command @ (SyncCommand::Play { session, .. }
|
||||
| SyncCommand::Tick { session, .. }) => match self.sessions.get_mut(*session) {
|
||||
Some(mut session) => {
|
||||
if session.owner == sender {
|
||||
session.handle_command(session_command);
|
||||
self.send_to_clients(&session, &command);
|
||||
}
|
||||
}
|
||||
None => {
|
||||
error!(session, "session not found for command");
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// cleanup sessions where the owner hasn't reconnected in 15 minutes
|
||||
fn gc_sessions(&self) {
|
||||
let now = Instant::now();
|
||||
self.sessions
|
||||
.retain(|_, session| match session.inactive_time(now) {
|
||||
Some(inactive) => inactive > TIMEOUT,
|
||||
None => true,
|
||||
});
|
||||
}
|
||||
|
||||
#[instrument(skip(self, raw_stream))]
|
||||
async fn handle_connection(&self, raw_stream: TcpStream, addr: SocketAddr) {
|
||||
debug!("incoming connection");
|
||||
|
||||
let ws_stream = tokio_tungstenite::accept_async(raw_stream)
|
||||
.await
|
||||
.expect("Error during the websocket handshake occurred");
|
||||
info!("connection established");
|
||||
|
||||
// Insert the write part of this peer to the peer map.
|
||||
let (tx, rx) = channel(16);
|
||||
self.peers.insert(addr, tx);
|
||||
|
||||
let (outgoing, incoming) = ws_stream.split();
|
||||
|
||||
let handle_messages = incoming.try_for_each(|msg| async move {
|
||||
if let Ok(message) = msg.to_text() {
|
||||
match serde_json::from_str(message) {
|
||||
Ok(command) => {
|
||||
debug!(sender = %addr, message = ?command, "Received a message");
|
||||
self.handle_command(command, addr).await;
|
||||
}
|
||||
Err(e) => {
|
||||
warn!(sender = %addr, message, error = %e, "Error while decoding message");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
debug!("ignoring non-text message");
|
||||
}
|
||||
Ok(())
|
||||
});
|
||||
|
||||
let receive_from_others = rx.map(Ok).forward(outgoing);
|
||||
|
||||
let handle_messages = pin!(handle_messages);
|
||||
let receive_from_others = pin!(receive_from_others);
|
||||
select(handle_messages, receive_from_others).await;
|
||||
|
||||
info!(%addr, "disconnected");
|
||||
self.peers.remove(&addr);
|
||||
}
|
||||
}
|
||||
|
||||
const TIMEOUT: Duration = Duration::from_secs(15 * 60);
|
||||
|
||||
/// cleanup sessions where the owner hasn't reconnected in 15 minutes
|
||||
fn gc_sessions(sessions: &RefCell<HashMap<String, Session>>) {
|
||||
let now = Instant::now();
|
||||
sessions
|
||||
.borrow_mut()
|
||||
.retain(|_, session| match session.owner_left {
|
||||
Some(left) => now.duration_since(left) > TIMEOUT,
|
||||
None => true,
|
||||
});
|
||||
#[tokio::main]
|
||||
async fn main() -> MainResult {
|
||||
tracing_subscriber::fmt::init();
|
||||
|
||||
let port: u16 = std::env::var("PORT")
|
||||
.unwrap_or_else(|_| "80".to_string())
|
||||
.parse()?;
|
||||
let listen_address = SocketAddr::from((Ipv4Addr::UNSPECIFIED, port));
|
||||
|
||||
let state = Arc::new(Server::new());
|
||||
|
||||
// Create the event loop and TCP listener we'll accept connections on.
|
||||
let listener = TcpListener::bind(&listen_address).await.expect("Failed to bind");
|
||||
|
||||
info!("listening on: {:?}", listen_address);
|
||||
|
||||
// Let's spawn the handling of each connection in a separate task.
|
||||
while let Ok((stream, addr)) = listener.accept().await {
|
||||
let state = state.clone();
|
||||
tokio::spawn(async move { state.handle_connection(stream, addr).await });
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn update_session_and_forward<F>(
|
||||
sender: &Client,
|
||||
sessions: &RefCell<HashMap<String, Session>>,
|
||||
session_name: &str,
|
||||
mut update_fn: F,
|
||||
command: &SyncCommand,
|
||||
) where
|
||||
F: FnMut(&mut Session),
|
||||
{
|
||||
match sessions.borrow_mut().get_mut(session_name) {
|
||||
Some(session) => {
|
||||
if session.owner == sender.token() {
|
||||
update_fn(session);
|
||||
session.send_command(command);
|
||||
}
|
||||
}
|
||||
None => println!("session {} not found", session_name),
|
||||
}
|
||||
}
|
||||
|
||||
impl Handler for Server {
|
||||
fn on_message(&mut self, msg: Message) -> Result<()> {
|
||||
match serde_json::from_str::<SyncCommand>(msg.as_text().unwrap_or_default()) {
|
||||
Ok(command) => {
|
||||
handle_command(command, &self.out, &self.sessions);
|
||||
Ok(())
|
||||
}
|
||||
Err(_) => Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
fn on_close(&mut self, _: CloseCode, _: &str) {
|
||||
let mut sessions = self.sessions.borrow_mut();
|
||||
let token = self.out.token();
|
||||
|
||||
for session in sessions.values_mut() {
|
||||
if session.owner == token {
|
||||
session.owner_left = Some(Instant::now())
|
||||
}
|
||||
|
||||
session.clients.remove(&token);
|
||||
}
|
||||
}
|
||||
|
||||
fn on_error(&mut self, err: Error) {
|
||||
println!("The server encountered an error: {:?}", err);
|
||||
}
|
||||
}
|
||||
|
||||
/// Used to spawn a server in integration tests
|
||||
#[cfg(test)]
|
||||
pub fn spawn_local_server(port: u16) -> parity_ws::Sender {
|
||||
use parity_ws::WebSocket;
|
||||
use std::sync::mpsc::channel;
|
||||
use std::thread::spawn;
|
||||
|
||||
let listen_address = format!("localhost:{}", port);
|
||||
|
||||
let (tx, rx) = channel();
|
||||
|
||||
spawn(move || {
|
||||
let sessions: Rc<RefCell<HashMap<String, Session>>> = Rc::default();
|
||||
|
||||
let ws = WebSocket::new(|out: parity_ws::Sender| Server {
|
||||
out: out.into(),
|
||||
sessions: sessions.clone(),
|
||||
})
|
||||
.unwrap();
|
||||
let ws = ws.bind(listen_address).unwrap();
|
||||
|
||||
tx.send(ws.broadcaster()).unwrap();
|
||||
|
||||
ws.run().unwrap();
|
||||
});
|
||||
|
||||
rx.recv().unwrap()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let port = std::env::var("PORT").unwrap_or_else(|_| "80".to_string());
|
||||
let listen_address = format!("0.0.0.0:{}", port);
|
||||
|
||||
println!("listening on: {:?}", listen_address);
|
||||
|
||||
let sessions: Rc<RefCell<HashMap<String, Session>>> = Rc::default();
|
||||
|
||||
listen(listen_address, |out| Server {
|
||||
out: out.into(),
|
||||
sessions: sessions.clone(),
|
||||
})
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use maplit::hashmap;
|
||||
|
||||
#[test]
|
||||
fn test_deserialize() {
|
||||
let input = "{\"type\": \"create\", \"session\": \"foo\", \"token\": \"bar\"}";
|
||||
assert_eq!(
|
||||
SyncCommand::Create {
|
||||
session: "foo",
|
||||
token: "bar",
|
||||
},
|
||||
serde_json::from_str(input).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_create() {
|
||||
let sessions: RefCell<HashMap<String, Session>> = RefCell::new(HashMap::new());
|
||||
let sender = Client::mock(1);
|
||||
let command = SyncCommand::Create {
|
||||
session: "test",
|
||||
token: "bar",
|
||||
};
|
||||
|
||||
handle_command(command, &sender, &sessions);
|
||||
|
||||
assert_eq!(
|
||||
hashmap! {
|
||||
"test".into() => Session {
|
||||
owner: Token(1),
|
||||
clients: hashmap![],
|
||||
tick: 0,
|
||||
playing: false,
|
||||
owner_token: "bar".to_string(),
|
||||
owner_left: None
|
||||
}
|
||||
},
|
||||
sessions.into_inner()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_play_owner() {
|
||||
let sessions: RefCell<HashMap<String, Session>> = RefCell::new(hashmap! {
|
||||
"test".into() => Session {
|
||||
owner: Token(1),
|
||||
clients: hashmap![],
|
||||
tick: 0,
|
||||
playing: false,
|
||||
owner_token: "bar".to_string(),
|
||||
owner_left: None
|
||||
}
|
||||
});
|
||||
let sender = Client::mock(1);
|
||||
let command = SyncCommand::Play {
|
||||
session: "test",
|
||||
play: true,
|
||||
};
|
||||
|
||||
handle_command(command, &sender, &sessions);
|
||||
|
||||
assert_eq!(
|
||||
hashmap! {
|
||||
"test".into() => Session {
|
||||
owner: Token(1),
|
||||
clients: hashmap![],
|
||||
tick: 0,
|
||||
playing: true,
|
||||
owner_token: "bar".to_string(),
|
||||
owner_left: None
|
||||
}
|
||||
},
|
||||
sessions.into_inner()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_play_not_owner() {
|
||||
let sessions: RefCell<HashMap<String, Session>> = RefCell::new(hashmap! {
|
||||
"test".into() => Session {
|
||||
owner: Token(1),
|
||||
clients: hashmap![],
|
||||
tick: 0,
|
||||
playing: false,
|
||||
owner_token: "bar".to_string(),
|
||||
owner_left: None
|
||||
}
|
||||
});
|
||||
let sender = Client::mock(2);
|
||||
let command = SyncCommand::Play {
|
||||
session: "test",
|
||||
play: true,
|
||||
};
|
||||
|
||||
handle_command(command, &sender, &sessions);
|
||||
|
||||
assert_eq!(
|
||||
hashmap! {
|
||||
"test".into() => Session {
|
||||
owner: Token(1),
|
||||
clients: hashmap![],
|
||||
tick: 0,
|
||||
playing: false,
|
||||
owner_token: "bar".to_string(),
|
||||
owner_left: None
|
||||
}
|
||||
},
|
||||
sessions.into_inner()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tick_owner() {
|
||||
let sessions: RefCell<HashMap<String, Session>> = RefCell::new(hashmap! {
|
||||
"test".into() => Session {
|
||||
owner: Token(1),
|
||||
clients: hashmap![],
|
||||
tick: 0,
|
||||
playing: false,
|
||||
owner_token: "bar".to_string(),
|
||||
owner_left: None
|
||||
}
|
||||
});
|
||||
let sender = Client::mock(1);
|
||||
let command = SyncCommand::Tick {
|
||||
session: "test",
|
||||
tick: 99,
|
||||
};
|
||||
|
||||
handle_command(command, &sender, &sessions);
|
||||
|
||||
assert_eq!(
|
||||
hashmap! {
|
||||
"test".into() => Session {
|
||||
owner: Token(1),
|
||||
clients: hashmap![],
|
||||
tick: 99,
|
||||
playing: false,
|
||||
owner_token: "bar".to_string(),
|
||||
owner_left: None
|
||||
}
|
||||
},
|
||||
sessions.into_inner()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tick_not_owner() {
|
||||
let sessions: RefCell<HashMap<String, Session>> = RefCell::new(hashmap! {
|
||||
"test".into() => Session {
|
||||
owner: Token(1),
|
||||
clients: hashmap![],
|
||||
tick: 0,
|
||||
playing: false,
|
||||
owner_token: "bar".to_string(),
|
||||
owner_left: None
|
||||
}
|
||||
});
|
||||
let sender = Client::mock(2);
|
||||
let command = SyncCommand::Tick {
|
||||
session: "test",
|
||||
tick: 99,
|
||||
};
|
||||
|
||||
handle_command(command, &sender, &sessions);
|
||||
|
||||
assert_eq!(
|
||||
hashmap! {
|
||||
"test".into() => Session {
|
||||
owner: Token(1),
|
||||
clients: hashmap![],
|
||||
tick: 0,
|
||||
playing: false,
|
||||
owner_token: "bar".to_string(),
|
||||
owner_left: None
|
||||
}
|
||||
},
|
||||
sessions.into_inner()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_join() {
|
||||
let sessions: RefCell<HashMap<String, Session>> = RefCell::new(hashmap! {
|
||||
"test".into() => Session {
|
||||
owner: Token(1),
|
||||
clients: hashmap![],
|
||||
tick: 99,
|
||||
playing: true,
|
||||
owner_token: "bar".to_string(),
|
||||
owner_left: None
|
||||
}
|
||||
});
|
||||
let sender = Client::mock(2);
|
||||
let command = SyncCommand::Join { session: "test" };
|
||||
|
||||
handle_command(command, &sender, &sessions);
|
||||
|
||||
assert_eq!(
|
||||
hashmap! {
|
||||
"test".into() => Session {
|
||||
owner: Token(1),
|
||||
clients: hashmap![Token(2) => sender.clone()],
|
||||
tick: 99,
|
||||
playing: true,
|
||||
owner_token: "bar".to_string(),
|
||||
owner_left: None
|
||||
}
|
||||
},
|
||||
sessions.into_inner()
|
||||
);
|
||||
|
||||
if let Client::Mock(mock) = sender {
|
||||
mock.assert_received(vec![
|
||||
SyncCommand::Tick {
|
||||
session: "test",
|
||||
tick: 99,
|
||||
},
|
||||
SyncCommand::Play {
|
||||
session: "test",
|
||||
play: true,
|
||||
},
|
||||
]);
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_join_non_existing() {
|
||||
let sessions: RefCell<HashMap<String, Session>> = RefCell::new(hashmap! {
|
||||
"test".into() => Session {
|
||||
owner: Token(1),
|
||||
clients: hashmap![],
|
||||
tick: 0,
|
||||
playing: false,
|
||||
owner_token: "bar".to_string(),
|
||||
owner_left: None
|
||||
}
|
||||
});
|
||||
let sender = Client::mock(2);
|
||||
let command = SyncCommand::Join { session: "test2" };
|
||||
|
||||
handle_command(command, &sender, &sessions);
|
||||
|
||||
assert_eq!(
|
||||
hashmap! {
|
||||
"test".into() => Session {
|
||||
owner: Token(1),
|
||||
clients: hashmap![],
|
||||
tick: 0,
|
||||
playing: false,
|
||||
owner_token: "bar".to_string(),
|
||||
owner_left: None
|
||||
}
|
||||
},
|
||||
sessions.into_inner()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_forward() {
|
||||
let sessions: RefCell<HashMap<String, Session>> = RefCell::new(hashmap! {
|
||||
"test".into() => Session {
|
||||
owner: Token(1),
|
||||
clients: hashmap![],
|
||||
tick: 99,
|
||||
playing: true,
|
||||
owner_token: "bar".to_string(),
|
||||
owner_left: None
|
||||
},
|
||||
"test2".into() => Session {
|
||||
owner: Token(1),
|
||||
clients: hashmap![],
|
||||
tick: 99,
|
||||
playing: true,
|
||||
owner_token: "bar".to_string(),
|
||||
owner_left: None
|
||||
}
|
||||
});
|
||||
let owner = Client::mock(1);
|
||||
let sender1 = Client::mock(2);
|
||||
let sender2 = Client::mock(3);
|
||||
let command = SyncCommand::Join { session: "test" };
|
||||
|
||||
handle_command(command, &sender1, &sessions);
|
||||
|
||||
let command = SyncCommand::Join { session: "test2" };
|
||||
handle_command(command, &sender2, &sessions);
|
||||
|
||||
if let Client::Mock(mock) = &sender1 {
|
||||
mock.clear();
|
||||
}
|
||||
if let Client::Mock(mock) = &sender2 {
|
||||
mock.clear();
|
||||
}
|
||||
|
||||
let command = SyncCommand::Tick {
|
||||
session: "test",
|
||||
tick: 999,
|
||||
};
|
||||
|
||||
handle_command(command, &owner, &sessions);
|
||||
|
||||
if let Client::Mock(mock) = sender1 {
|
||||
mock.assert_received(vec![SyncCommand::Tick {
|
||||
session: "test",
|
||||
tick: 999,
|
||||
}]);
|
||||
};
|
||||
if let Client::Mock(mock) = sender2 {
|
||||
assert_eq!(0, mock.received_count());
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_forward_non_owner() {
|
||||
let sessions: RefCell<HashMap<String, Session>> = RefCell::new(hashmap! {
|
||||
"test".into() => Session {
|
||||
owner: Token(1),
|
||||
clients: hashmap![],
|
||||
tick: 99,
|
||||
playing: true,
|
||||
owner_token: "bar".to_string(),
|
||||
owner_left: None
|
||||
}
|
||||
});
|
||||
let sender1 = Client::mock(2);
|
||||
let sender2 = Client::mock(3);
|
||||
let command = SyncCommand::Join { session: "test" };
|
||||
|
||||
handle_command(command.clone(), &sender1, &sessions);
|
||||
handle_command(command.clone(), &sender2, &sessions);
|
||||
|
||||
if let Client::Mock(mock) = &sender1 {
|
||||
mock.clear();
|
||||
}
|
||||
if let Client::Mock(mock) = &sender2 {
|
||||
mock.clear();
|
||||
}
|
||||
|
||||
let command = SyncCommand::Tick {
|
||||
session: "test",
|
||||
tick: 999,
|
||||
};
|
||||
|
||||
handle_command(command, &sender1, &sessions);
|
||||
|
||||
if let Client::Mock(mock) = sender1 {
|
||||
assert_eq!(0, mock.received_count());
|
||||
};
|
||||
if let Client::Mock(mock) = sender2 {
|
||||
assert_eq!(0, mock.received_count());
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod integration_tests;
|
||||
|
|
|
|||
78
src/session.rs
Normal file
78
src/session.rs
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
use crate::SyncCommand;
|
||||
use std::net::SocketAddr;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Session {
|
||||
pub owner: SocketAddr,
|
||||
owner_token: String,
|
||||
clients: Vec<SocketAddr>,
|
||||
tick: u64,
|
||||
playing: bool,
|
||||
owner_left: Option<Instant>,
|
||||
token: String,
|
||||
}
|
||||
|
||||
impl PartialEq for Session {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.token.eq(&other.token)
|
||||
}
|
||||
}
|
||||
|
||||
impl Session {
|
||||
pub fn new(owner: SocketAddr, token: String, owner_token: String) -> Self {
|
||||
Session {
|
||||
owner,
|
||||
owner_token,
|
||||
clients: Vec::new(),
|
||||
playing: false,
|
||||
tick: 0,
|
||||
owner_left: None,
|
||||
token,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn join(&mut self, client: SocketAddr) {
|
||||
self.clients.push(client);
|
||||
}
|
||||
|
||||
pub fn set_owner(&mut self, owner: SocketAddr, owner_token: &str) -> bool {
|
||||
if owner_token == self.owner_token {
|
||||
self.owner = owner;
|
||||
self.owner_left = None;
|
||||
}
|
||||
owner_token == self.owner_token
|
||||
}
|
||||
|
||||
pub fn inactive_time(&self, now: Instant) -> Option<Duration> {
|
||||
self.owner_left.map(|left| left.duration_since(now))
|
||||
}
|
||||
|
||||
pub fn initial_state(&self) -> impl Iterator<Item = SyncCommand> {
|
||||
[
|
||||
SyncCommand::Tick {
|
||||
session: &self.token,
|
||||
tick: self.tick,
|
||||
},
|
||||
SyncCommand::Play {
|
||||
session: &self.token,
|
||||
play: self.playing,
|
||||
},
|
||||
]
|
||||
.into_iter()
|
||||
}
|
||||
|
||||
pub fn clients(&self) -> impl Iterator<Item = &SocketAddr> {
|
||||
self.clients.iter()
|
||||
}
|
||||
|
||||
pub fn handle_command(&mut self, command: &SyncCommand) {
|
||||
match command {
|
||||
SyncCommand::Tick { tick, .. } => {
|
||||
self.tick = *tick;
|
||||
}
|
||||
SyncCommand::Play { play, .. } => self.playing = *play,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue