Compare commits
16 Commits
fbaf386ebb
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 368d6585c4 | |||
| 92f7e5aa5f | |||
| 6189b82bd3 | |||
| 152e7926ee | |||
| e661526e78 | |||
| c41bf83eb8 | |||
| daedfe72d0 | |||
| 4c0f571317 | |||
| bf84433d5b | |||
| 3ab9cedbcd | |||
| ab3c28ff37 | |||
| ab25fa0267 | |||
| 13fb9a9fdd | |||
| b6d54d086e | |||
| f28c9fee83 | |||
| 41175e487e |
400
Cargo.lock
generated
400
Cargo.lock
generated
@@ -50,34 +50,12 @@ version = "1.2.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db"
|
checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cc"
|
|
||||||
version = "1.0.73"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "core-foundation"
|
|
||||||
version = "0.9.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146"
|
|
||||||
dependencies = [
|
|
||||||
"core-foundation-sys",
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "core-foundation-sys"
|
|
||||||
version = "0.8.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cpufeatures"
|
name = "cpufeatures"
|
||||||
version = "0.2.5"
|
version = "0.2.5"
|
||||||
@@ -107,36 +85,12 @@ dependencies = [
|
|||||||
"crypto-common",
|
"crypto-common",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "fastrand"
|
|
||||||
version = "1.8.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499"
|
|
||||||
dependencies = [
|
|
||||||
"instant",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fnv"
|
name = "fnv"
|
||||||
version = "1.0.7"
|
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 = "foreign-types"
|
|
||||||
version = "0.3.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
|
|
||||||
dependencies = [
|
|
||||||
"foreign-types-shared",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "foreign-types-shared"
|
|
||||||
version = "0.1.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "form_urlencoded"
|
name = "form_urlencoded"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
@@ -146,6 +100,95 @@ dependencies = [
|
|||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures"
|
||||||
|
version = "0.3.24"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7f21eda599937fba36daeb58a22e8f5cee2d14c4a17b5b7739c7c8e5e3b8230c"
|
||||||
|
dependencies = [
|
||||||
|
"futures-channel",
|
||||||
|
"futures-core",
|
||||||
|
"futures-executor",
|
||||||
|
"futures-io",
|
||||||
|
"futures-sink",
|
||||||
|
"futures-task",
|
||||||
|
"futures-util",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-channel"
|
||||||
|
version = "0.3.24"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "30bdd20c28fadd505d0fd6712cdfcb0d4b5648baf45faef7f852afb2399bb050"
|
||||||
|
dependencies = [
|
||||||
|
"futures-core",
|
||||||
|
"futures-sink",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-core"
|
||||||
|
version = "0.3.24"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4e5aa3de05362c3fb88de6531e6296e85cde7739cccad4b9dfeeb7f6ebce56bf"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-executor"
|
||||||
|
version = "0.3.24"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9ff63c23854bee61b6e9cd331d523909f238fc7636290b96826e9cfa5faa00ab"
|
||||||
|
dependencies = [
|
||||||
|
"futures-core",
|
||||||
|
"futures-task",
|
||||||
|
"futures-util",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-io"
|
||||||
|
version = "0.3.24"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bbf4d2a7a308fd4578637c0b17c7e1c7ba127b8f6ba00b29f717e9655d85eb68"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-macro"
|
||||||
|
version = "0.3.24"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "42cd15d1c7456c04dbdf7e88bcd69760d74f3a798d6444e16974b505b0e62f17"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-sink"
|
||||||
|
version = "0.3.24"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "21b20ba5a92e727ba30e72834706623d94ac93a725410b6a6b6fbc1b07f7ba56"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-task"
|
||||||
|
version = "0.3.24"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a6508c467c73851293f390476d4491cf4d227dbabcd4170f3bb6044959b294f1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-util"
|
||||||
|
version = "0.3.24"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "44fb6cb1be61cc1d2e43b262516aafcf63b241cffdb1d3fa115f91d9c7b09c90"
|
||||||
|
dependencies = [
|
||||||
|
"futures-channel",
|
||||||
|
"futures-core",
|
||||||
|
"futures-io",
|
||||||
|
"futures-macro",
|
||||||
|
"futures-sink",
|
||||||
|
"futures-task",
|
||||||
|
"memchr",
|
||||||
|
"pin-project-lite",
|
||||||
|
"pin-utils",
|
||||||
|
"slab",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "generic-array"
|
name = "generic-array"
|
||||||
version = "0.14.6"
|
version = "0.14.6"
|
||||||
@@ -167,14 +210,26 @@ dependencies = [
|
|||||||
"wasi",
|
"wasi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hermit-abi"
|
||||||
|
version = "0.1.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hexland-server"
|
name = "hexland-server"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"futures",
|
||||||
|
"lazy_static",
|
||||||
"rand",
|
"rand",
|
||||||
"regex",
|
"regex",
|
||||||
"sha2",
|
"sha2",
|
||||||
"tungstenite",
|
"tokio",
|
||||||
|
"tokio-tungstenite",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -204,15 +259,6 @@ dependencies = [
|
|||||||
"unicode-normalization",
|
"unicode-normalization",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "instant"
|
|
||||||
version = "0.1.12"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "1.0.3"
|
version = "1.0.3"
|
||||||
@@ -231,6 +277,16 @@ version = "0.2.133"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c0f80d65747a3e43d1596c7c5492d95d5edddaabd45a7fcdb02b95f644164966"
|
checksum = "c0f80d65747a3e43d1596c7c5492d95d5edddaabd45a7fcdb02b95f644164966"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lock_api"
|
||||||
|
version = "0.4.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"scopeguard",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.17"
|
version = "0.4.17"
|
||||||
@@ -247,72 +303,48 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "native-tls"
|
name = "mio"
|
||||||
version = "0.2.10"
|
version = "0.8.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fd7e2f3618557f980e0b17e8856252eee3c97fa12c54dff0ca290fb6266ca4a9"
|
checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lazy_static",
|
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
"openssl",
|
"wasi",
|
||||||
"openssl-probe",
|
"windows-sys",
|
||||||
"openssl-sys",
|
|
||||||
"schannel",
|
|
||||||
"security-framework",
|
|
||||||
"security-framework-sys",
|
|
||||||
"tempfile",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "once_cell"
|
name = "num_cpus"
|
||||||
version = "1.14.0"
|
version = "1.13.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0"
|
checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
|
||||||
|
dependencies = [
|
||||||
|
"hermit-abi",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "openssl"
|
name = "parking_lot"
|
||||||
version = "0.10.41"
|
version = "0.12.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "618febf65336490dfcf20b73f885f5651a0c89c64c2d4a8c3662585a70bf5bd0"
|
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
|
||||||
|
dependencies = [
|
||||||
|
"lock_api",
|
||||||
|
"parking_lot_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot_core"
|
||||||
|
version = "0.9.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"foreign-types",
|
|
||||||
"libc",
|
"libc",
|
||||||
"once_cell",
|
"redox_syscall",
|
||||||
"openssl-macros",
|
"smallvec",
|
||||||
"openssl-sys",
|
"windows-sys",
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "openssl-macros"
|
|
||||||
version = "0.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "openssl-probe"
|
|
||||||
version = "0.1.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "openssl-sys"
|
|
||||||
version = "0.9.75"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e5f9bd0c2710541a3cda73d6f9ac4f1b240de4ae261065d309dbe73d9dceb42f"
|
|
||||||
dependencies = [
|
|
||||||
"autocfg",
|
|
||||||
"cc",
|
|
||||||
"libc",
|
|
||||||
"pkg-config",
|
|
||||||
"vcpkg",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -322,10 +354,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
|
checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pkg-config"
|
name = "pin-project-lite"
|
||||||
version = "0.3.25"
|
version = "0.2.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
|
checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pin-utils"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ppv-lite86"
|
name = "ppv-lite86"
|
||||||
@@ -408,46 +446,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
|
checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "remove_dir_all"
|
name = "scopeguard"
|
||||||
version = "0.5.3"
|
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 = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
|
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||||
dependencies = [
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "schannel"
|
|
||||||
version = "0.1.20"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2"
|
|
||||||
dependencies = [
|
|
||||||
"lazy_static",
|
|
||||||
"windows-sys",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "security-framework"
|
|
||||||
version = "2.7.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2bc1bb97804af6631813c55739f771071e0f2ed33ee20b68c86ec505d906356c"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags",
|
|
||||||
"core-foundation",
|
|
||||||
"core-foundation-sys",
|
|
||||||
"libc",
|
|
||||||
"security-framework-sys",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "security-framework-sys"
|
|
||||||
version = "2.6.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556"
|
|
||||||
dependencies = [
|
|
||||||
"core-foundation-sys",
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sha-1"
|
name = "sha-1"
|
||||||
@@ -471,6 +473,40 @@ dependencies = [
|
|||||||
"digest",
|
"digest",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "signal-hook-registry"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "slab"
|
||||||
|
version = "0.4.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "smallvec"
|
||||||
|
version = "1.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "socket2"
|
||||||
|
version = "0.4.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.100"
|
version = "1.0.100"
|
||||||
@@ -482,20 +518,6 @@ dependencies = [
|
|||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tempfile"
|
|
||||||
version = "3.3.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"fastrand",
|
|
||||||
"libc",
|
|
||||||
"redox_syscall",
|
|
||||||
"remove_dir_all",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "1.0.35"
|
version = "1.0.35"
|
||||||
@@ -531,6 +553,49 @@ 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 = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
|
checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio"
|
||||||
|
version = "1.21.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a9e03c497dc955702ba729190dc4aac6f2a0ce97f913e5b1b5912fc5039d9099"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"bytes",
|
||||||
|
"libc",
|
||||||
|
"memchr",
|
||||||
|
"mio",
|
||||||
|
"num_cpus",
|
||||||
|
"parking_lot",
|
||||||
|
"pin-project-lite",
|
||||||
|
"signal-hook-registry",
|
||||||
|
"socket2",
|
||||||
|
"tokio-macros",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio-macros"
|
||||||
|
version = "1.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio-tungstenite"
|
||||||
|
version = "0.17.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f714dd15bead90401d77e04243611caec13726c2408afd5b31901dfcdcb3b181"
|
||||||
|
dependencies = [
|
||||||
|
"futures-util",
|
||||||
|
"log",
|
||||||
|
"tokio",
|
||||||
|
"tungstenite",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tungstenite"
|
name = "tungstenite"
|
||||||
version = "0.17.3"
|
version = "0.17.3"
|
||||||
@@ -543,7 +608,6 @@ dependencies = [
|
|||||||
"http",
|
"http",
|
||||||
"httparse",
|
"httparse",
|
||||||
"log",
|
"log",
|
||||||
"native-tls",
|
|
||||||
"rand",
|
"rand",
|
||||||
"sha-1",
|
"sha-1",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
@@ -595,12 +659,6 @@ version = "0.7.6"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
|
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "vcpkg"
|
|
||||||
version = "0.2.15"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "version_check"
|
name = "version_check"
|
||||||
version = "0.9.4"
|
version = "0.9.4"
|
||||||
|
|||||||
@@ -6,7 +6,10 @@ edition = "2021"
|
|||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
tungstenite = { version = "0.17.3", features = ["native-tls"] }
|
|
||||||
sha2 = "0.10.6"
|
sha2 = "0.10.6"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
regex = "1.6.0"
|
regex = "1.6.0"
|
||||||
|
tokio = { version = "1.21.2", features = ["full"] }
|
||||||
|
tokio-tungstenite = "0.17.2"
|
||||||
|
futures = "0.3.24"
|
||||||
|
lazy_static = "1.4.0"
|
||||||
52
doc/flow.txt
Normal file
52
doc/flow.txt
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
Sign on process:
|
||||||
|
|
||||||
|
New client
|
||||||
|
client server
|
||||||
|
HELO
|
||||||
|
SIGNUP
|
||||||
|
PLAYER_CODE
|
||||||
|
|
||||||
|
Existing client
|
||||||
|
client server
|
||||||
|
HELO
|
||||||
|
LOGIN
|
||||||
|
LOGIN_OK
|
||||||
|
|
||||||
|
Expired login
|
||||||
|
client server
|
||||||
|
HELO
|
||||||
|
LOGIN
|
||||||
|
PLAYER_CODE
|
||||||
|
|
||||||
|
Anything else
|
||||||
|
client server
|
||||||
|
HELO
|
||||||
|
HOST
|
||||||
|
ERROR
|
||||||
|
<Close Frame>
|
||||||
|
This is the only scenario where an error is followed by
|
||||||
|
an immediate close frame.
|
||||||
|
|
||||||
|
Room join process:
|
||||||
|
|
||||||
|
Create new room
|
||||||
|
client server
|
||||||
|
HOSTJOIN
|
||||||
|
HOST
|
||||||
|
ROOM_CODE
|
||||||
|
|
||||||
|
Join an existing room
|
||||||
|
client server
|
||||||
|
HOSTJOIN
|
||||||
|
JOIN
|
||||||
|
JOIN_OK
|
||||||
|
|
||||||
|
Join an expired room
|
||||||
|
client server
|
||||||
|
HOSTJOIN
|
||||||
|
JOIN
|
||||||
|
BAD_ROOM
|
||||||
|
At this point the client is responsible for procuring
|
||||||
|
a new room code
|
||||||
|
|
||||||
|
|
||||||
68
public/index.html
Normal file
68
public/index.html
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<script
|
||||||
|
src="https://code.jquery.com/jquery-3.6.1.slim.min.js"
|
||||||
|
integrity="sha256-w8CvhFs7iHNVUtnSP0YKEg00p9Ih13rlL9zGqvLdePA="
|
||||||
|
crossorigin="anonymous"
|
||||||
|
></script>
|
||||||
|
<h1 id="roomName">
|
||||||
|
Not Connected
|
||||||
|
</h1>
|
||||||
|
<div>
|
||||||
|
<button id="hostBtn" disabled>Host</button>
|
||||||
|
<input id="roomTxt" type="text">
|
||||||
|
<button id="joinBtn" disabled>Join</button>
|
||||||
|
</div>
|
||||||
|
<textarea readonly></textarea>
|
||||||
|
<div>
|
||||||
|
<input id="chatTxt" type="text" disabled>
|
||||||
|
<button id="chatBtn" disabled>Chat</button>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
const ws = new WebSocket("ws://localhost:8080");
|
||||||
|
|
||||||
|
ws.addEventListener('open', e => {
|
||||||
|
$("#hostBtn").attr('disabled', false);
|
||||||
|
$("#joinBtn").attr('disabled', false);
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#hostBtn").on('click', e => ws.send("HOST:"));
|
||||||
|
$("#joinBtn").on('click', e => {
|
||||||
|
const roomCode = $('#roomTxt').val();
|
||||||
|
const msg = `JOIN: ${roomCode}`;
|
||||||
|
ws.send(msg);
|
||||||
|
$("#roomName").text(roomCode);
|
||||||
|
});
|
||||||
|
$("#chatBtn").on('click', e => {
|
||||||
|
let text = $('#chatTxt').val();
|
||||||
|
$('#chatTxt').val('');
|
||||||
|
msg = `CHAT: ${text}`;
|
||||||
|
ws.send(msg);
|
||||||
|
});
|
||||||
|
|
||||||
|
ws.addEventListener('message', e => {
|
||||||
|
const msg = e.data;
|
||||||
|
const pos = msg.indexOf(':');
|
||||||
|
const command = msg.substring(0, pos);
|
||||||
|
const args = msg.substring(pos+1).split(',');
|
||||||
|
|
||||||
|
switch(command) {
|
||||||
|
case "ROOM_CODE":
|
||||||
|
$("#roomName").text(args[0]);
|
||||||
|
// Fallthrough
|
||||||
|
case "JOIN_OK":
|
||||||
|
$("#chatTxt").attr('disabled', false);
|
||||||
|
$("#chatBtn").attr('disabled', false);
|
||||||
|
break;
|
||||||
|
case "CHAT":
|
||||||
|
let text = $("textarea").val();
|
||||||
|
text = text += `${args[0]}\n`;
|
||||||
|
$("textarea").val(text);
|
||||||
|
default:
|
||||||
|
console.log("Unhandled message", msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
97
src/client.rs
Normal file
97
src/client.rs
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use tokio::sync::Mutex;
|
||||||
|
use futures::{select, FutureExt};
|
||||||
|
|
||||||
|
use crate::{msg, GlobalState};
|
||||||
|
use crate::game::{channel_pair, Channel, GameController};
|
||||||
|
use crate::message::{Message, MessageWebSocket};
|
||||||
|
|
||||||
|
pub struct Client {
|
||||||
|
global_state: Arc<GlobalState>,
|
||||||
|
ws: MessageWebSocket,
|
||||||
|
channel: Option<Channel>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Client {
|
||||||
|
pub fn new(ws: MessageWebSocket, global_state: Arc<GlobalState>) -> Self {
|
||||||
|
Client {
|
||||||
|
global_state,
|
||||||
|
ws,
|
||||||
|
channel: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub async fn run(&mut self) {
|
||||||
|
loop {
|
||||||
|
match &mut self.channel {
|
||||||
|
Some(channel) => {
|
||||||
|
select! {
|
||||||
|
msg = channel.rx.recv().fuse() =>
|
||||||
|
self.handle_server_msg(msg.unwrap()).await,
|
||||||
|
msg = self.ws.next().fuse() =>
|
||||||
|
self.handle_client_msg(msg.unwrap()).await,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
let msg = self.ws.next().await;
|
||||||
|
self.handle_client_msg(msg.unwrap()).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async fn handle_client_msg(&mut self, msg: Message) {
|
||||||
|
// HOST and JOIN are handled by the client to set up a connection
|
||||||
|
// TODO add id support for reconnecting users
|
||||||
|
match msg.command.as_str() {
|
||||||
|
"HOST" => {
|
||||||
|
let room_code = self.global_state.code_generator.lock().await.generate();
|
||||||
|
let game_controller = Arc::new(Mutex::new(GameController::default()));
|
||||||
|
|
||||||
|
let (client_channel, server_channel) = channel_pair();
|
||||||
|
self.channel = Some(client_channel);
|
||||||
|
game_controller.lock().await.push(server_channel);
|
||||||
|
|
||||||
|
self.global_state
|
||||||
|
.rooms
|
||||||
|
.lock()
|
||||||
|
.await
|
||||||
|
.insert(room_code.clone(), Arc::clone(&game_controller));
|
||||||
|
tokio::spawn(async move {
|
||||||
|
loop {
|
||||||
|
game_controller.lock().await.poll().await;
|
||||||
|
tokio::task::yield_now().await;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
self.ws.send(msg!(ROOM_CODE, room_code)).await.unwrap();
|
||||||
|
}
|
||||||
|
"JOIN" => {
|
||||||
|
let room_code = &msg.args[0];
|
||||||
|
let rooms = self.global_state.rooms.lock().await;
|
||||||
|
let room = rooms.get(room_code);
|
||||||
|
|
||||||
|
match room {
|
||||||
|
Some(room) => {
|
||||||
|
let (client_channel, server_channel) = channel_pair();
|
||||||
|
self.channel = Some(client_channel);
|
||||||
|
room.lock().await.push(server_channel);
|
||||||
|
self.ws.send(msg!(JOIN_OK)).await.unwrap();
|
||||||
|
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
self.ws.send(msg!(JOIN_INVALID)).await.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
if let Some(channel) = &self.channel {
|
||||||
|
// Forward message to the server
|
||||||
|
channel.tx.send(msg).await.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async fn handle_server_msg(&mut self, msg: Message) {
|
||||||
|
// Forward the message via websocket
|
||||||
|
self.ws.send(msg).await.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
39
src/code_generator.rs
Normal file
39
src/code_generator.rs
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
use rand::RngCore;
|
||||||
|
use sha2::{Digest, Sha256};
|
||||||
|
|
||||||
|
pub struct CodeGenerator {
|
||||||
|
counter: u64,
|
||||||
|
salt: [u8; 32],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CodeGenerator {
|
||||||
|
pub fn generate(&mut self) -> String {
|
||||||
|
let count = self.counter;
|
||||||
|
self.counter += 1;
|
||||||
|
|
||||||
|
let mut hasher = Sha256::new();
|
||||||
|
hasher.update(self.salt);
|
||||||
|
hasher.update(count.to_be_bytes());
|
||||||
|
|
||||||
|
format!("{:x}", hasher.finalize())[..6].to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for CodeGenerator {
|
||||||
|
fn default() -> Self {
|
||||||
|
let mut salt = [0; 32];
|
||||||
|
rand::thread_rng().fill_bytes(&mut salt);
|
||||||
|
|
||||||
|
CodeGenerator { counter: 0, salt }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
#[test]
|
||||||
|
fn test_generate() {
|
||||||
|
let code = CodeGenerator::default().generate();
|
||||||
|
assert_eq!(code.len(), 6);
|
||||||
|
}
|
||||||
|
}
|
||||||
69
src/game.rs
Normal file
69
src/game.rs
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
use tokio::sync::mpsc;
|
||||||
|
use tokio::sync::mpsc::error::TryRecvError;
|
||||||
|
|
||||||
|
use crate::message::Message;
|
||||||
|
|
||||||
|
struct Player {
|
||||||
|
name: String,
|
||||||
|
channel: Option<Channel>,
|
||||||
|
seat: Option<usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct GameController {
|
||||||
|
players: Vec<Player>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Channel {
|
||||||
|
pub tx: mpsc::Sender<Message>,
|
||||||
|
pub rx: mpsc::Receiver<Message>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GameController {
|
||||||
|
pub fn try_recv(&mut self) -> Result<Message, TryRecvError> {
|
||||||
|
for player in self.players.iter_mut() {
|
||||||
|
if let Some(channel) = &mut player.channel {
|
||||||
|
let res = channel.rx.try_recv();
|
||||||
|
if !(res == Err(TryRecvError::Empty)) {
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(TryRecvError::Empty)
|
||||||
|
}
|
||||||
|
pub async fn broadcast(&mut self, msg: Message) {
|
||||||
|
for player in self.players.iter() {
|
||||||
|
if let Some(channel) = &player.channel {
|
||||||
|
channel.tx.send(msg.clone()).await.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn push(&mut self, channel: Channel) {
|
||||||
|
let player = Player {
|
||||||
|
name: "Guest".to_string(),
|
||||||
|
channel: Some(channel),
|
||||||
|
seat: None, // TODO
|
||||||
|
};
|
||||||
|
self.players.push(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn channel_pair() -> (Channel, Channel) {
|
||||||
|
let (atx, brx) = mpsc::channel(32);
|
||||||
|
let (btx, arx) = mpsc::channel(32);
|
||||||
|
(Channel { tx: atx, rx: arx }, Channel { tx: btx, rx: brx })
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GameController {
|
||||||
|
pub async fn poll(&mut self) {
|
||||||
|
if let Ok(msg) = self.try_recv() {
|
||||||
|
self.dispatch(msg).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async fn dispatch(&mut self, msg: Message) {
|
||||||
|
match msg.command.as_str() {
|
||||||
|
"CHAT" => self.broadcast(msg).await,
|
||||||
|
_ => ()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
18
src/lib.rs
Normal file
18
src/lib.rs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use tokio::sync::Mutex;
|
||||||
|
|
||||||
|
pub mod game;
|
||||||
|
pub mod message;
|
||||||
|
pub mod client;
|
||||||
|
|
||||||
|
use game::GameController;
|
||||||
|
mod code_generator;
|
||||||
|
use code_generator::CodeGenerator;
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct GlobalState {
|
||||||
|
pub code_generator: Arc<Mutex<CodeGenerator>>,
|
||||||
|
pub rooms: Arc<Mutex<HashMap<String, Arc<Mutex<GameController>>>>>,
|
||||||
|
}
|
||||||
111
src/main.rs
111
src/main.rs
@@ -1,95 +1,36 @@
|
|||||||
use std::net::TcpListener;
|
use std::{io::Error as IoError, sync::Arc};
|
||||||
use std::thread;
|
|
||||||
use std::sync::{Arc, Mutex};
|
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
mod message;
|
use tokio::net::TcpListener;
|
||||||
use message::Message;
|
|
||||||
|
|
||||||
use rand::RngCore;
|
use hexland_server::GlobalState;
|
||||||
|
use hexland_server::client::Client;
|
||||||
|
use hexland_server::message::MessageWebSocket;
|
||||||
|
|
||||||
use tungstenite::protocol::Message as WsMessage;
|
|
||||||
|
|
||||||
use sha2::{Sha256, Digest};
|
#[tokio::main]
|
||||||
|
async fn main() -> Result<(), IoError> {
|
||||||
|
let global_state = Arc::new(GlobalState::default());
|
||||||
|
|
||||||
fn main() {
|
// Bind socket
|
||||||
let code_generator = Arc::new(Mutex::new(CodeGenerator::default()));
|
let socket = TcpListener::bind("127.0.0.1:8080").await;
|
||||||
let server = TcpListener::bind("127.0.0.1:8080").unwrap();
|
let listener = socket.expect("Could not bind to localhost:8080");
|
||||||
|
println!("Server running");
|
||||||
|
|
||||||
let rooms = Arc::new(Mutex::new(HashMap::new()));
|
// Accept all incoming connections
|
||||||
|
while let Ok((stream, addr)) = listener.accept().await {
|
||||||
|
let global_state = Arc::clone(&global_state);
|
||||||
|
tokio::spawn(async move {
|
||||||
|
// Upgrade to a WS connection
|
||||||
|
let ws = MessageWebSocket(
|
||||||
|
tokio_tungstenite::accept_async(stream)
|
||||||
|
.await
|
||||||
|
.expect("Could not establish connection"),
|
||||||
|
);
|
||||||
|
println!("Connected to {}", addr);
|
||||||
|
Client::new(ws, global_state).run().await;
|
||||||
|
|
||||||
for stream in server.incoming() {
|
unreachable!();
|
||||||
let code_generator = Arc::clone(&code_generator);
|
|
||||||
let rooms = Arc::clone(&rooms);
|
|
||||||
thread::spawn (move || {
|
|
||||||
let mut ws = tungstenite::accept(stream.unwrap()).unwrap();
|
|
||||||
println!("New client!");
|
|
||||||
ws.write_message(WsMessage::Text("HOSTJOIN:".to_string())).unwrap();
|
|
||||||
loop {
|
|
||||||
let message = ws.read_message();
|
|
||||||
println!("{:?}", message);
|
|
||||||
match message {
|
|
||||||
Err(_) => break,
|
|
||||||
Ok(WsMessage::Close(_)) => break,
|
|
||||||
Ok(WsMessage::Text(msg)) => {
|
|
||||||
let msg = Message::parse(msg.as_str().trim());
|
|
||||||
match msg {
|
|
||||||
Ok(msg) =>
|
|
||||||
match msg.command {
|
|
||||||
"HOST" => {
|
|
||||||
let code = code_generator.lock().unwrap().generate();
|
|
||||||
let mut room = Room::default();
|
|
||||||
let player = Player { name: "Guest".to_string() };
|
|
||||||
room.players.push(player);
|
|
||||||
rooms.lock().unwrap().insert(code.clone(), room);
|
|
||||||
ws.write_message(WsMessage::Text(code)).unwrap();
|
|
||||||
}
|
|
||||||
_ => todo!(),
|
|
||||||
}
|
|
||||||
Err(_) => todo!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => unimplemented!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
Ok(())
|
||||||
#[derive(Default)]
|
|
||||||
struct Room {
|
|
||||||
players: Vec<Player>,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Player {
|
|
||||||
name: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct CodeGenerator {
|
|
||||||
counter: u64,
|
|
||||||
salt: [u8; 32],
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CodeGenerator {
|
|
||||||
fn generate(&mut self) -> String {
|
|
||||||
let count = self.counter;
|
|
||||||
self.counter += 1;
|
|
||||||
|
|
||||||
let mut hasher = Sha256::new();
|
|
||||||
hasher.update(self.salt);
|
|
||||||
hasher.update(count.to_be_bytes());
|
|
||||||
|
|
||||||
format!("{:x}", hasher.finalize())[..6].to_string()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for CodeGenerator {
|
|
||||||
fn default() -> Self {
|
|
||||||
let mut salt = [0; 32];
|
|
||||||
rand::thread_rng().fill_bytes(&mut salt);
|
|
||||||
|
|
||||||
CodeGenerator {
|
|
||||||
counter: 0,
|
|
||||||
salt,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
142
src/message.rs
142
src/message.rs
@@ -1,7 +1,14 @@
|
|||||||
#[derive(PartialEq, Debug)]
|
use std::convert::{From, TryFrom};
|
||||||
pub struct Message<'a> {
|
|
||||||
pub command: &'a str,
|
use futures::{SinkExt, StreamExt};
|
||||||
pub args: Vec<&'a str>,
|
use lazy_static::lazy_static;
|
||||||
|
use tokio::net::TcpStream;
|
||||||
|
use tokio_tungstenite::{tungstenite::Message as WsMessage, WebSocketStream};
|
||||||
|
|
||||||
|
#[derive(PartialEq, Debug, Clone)]
|
||||||
|
pub struct Message {
|
||||||
|
pub command: String,
|
||||||
|
pub args: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Result<T> = std::result::Result<T, Error>;
|
pub type Result<T> = std::result::Result<T, Error>;
|
||||||
@@ -10,26 +17,100 @@ pub type Result<T> = std::result::Result<T, Error>;
|
|||||||
#[derive(PartialEq, Debug)]
|
#[derive(PartialEq, Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
BadParse,
|
BadParse,
|
||||||
UnknownCommand,
|
NonText,
|
||||||
|
Unknown,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Message<'a> {
|
impl Message {
|
||||||
pub fn parse(text: &'a str) -> Result<Message<'a>> {
|
pub fn parse(text: String) -> Result<Message> {
|
||||||
let re = regex::Regex::new(r"^([A-Z_]+):\s*(.*)").unwrap();
|
use regex::Regex;
|
||||||
match re.captures(text) {
|
lazy_static! {
|
||||||
|
static ref RE: Regex = Regex::new(r"^([A-Z_]+):\s*(.*)").unwrap();
|
||||||
|
static ref ARGS_RE: Regex = Regex::new(r"((\\,|[^,])+)").unwrap();
|
||||||
|
}
|
||||||
|
match RE.captures(text.as_str()) {
|
||||||
Some(captures) => {
|
Some(captures) => {
|
||||||
if captures.len() < 3 {
|
if captures.len() < 3 {
|
||||||
Err(Error::BadParse)
|
Err(Error::BadParse)
|
||||||
} else {
|
} else {
|
||||||
let command = captures.get(1).unwrap().as_str();
|
let command = captures[1].to_string();
|
||||||
let args = captures.get(2).unwrap().as_str()
|
let args = &captures[2];
|
||||||
.split(',')
|
let args = ARGS_RE.captures_iter(args).map(|captures| {
|
||||||
.map(|s| s.trim())
|
captures[1]
|
||||||
.collect();
|
.replace("\\,", ",")
|
||||||
|
.trim()
|
||||||
|
.to_string()
|
||||||
|
}).collect();
|
||||||
Ok(Message { command, args })
|
Ok(Message { command, args })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => Err(Error::BadParse),
|
None => Err(Error::BadParse),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<WsMessage> for Message {
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
fn try_from(ws_message: WsMessage) -> Result<Self> {
|
||||||
|
let text = match ws_message {
|
||||||
|
WsMessage::Text(text) => text,
|
||||||
|
_ => return Err(Error::NonText),
|
||||||
|
};
|
||||||
|
Message::parse(text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Message> for WsMessage {
|
||||||
|
fn from(message: Message) -> Self {
|
||||||
|
WsMessage::Text(message.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct MessageWebSocket(pub WebSocketStream<TcpStream>);
|
||||||
|
|
||||||
|
impl MessageWebSocket {
|
||||||
|
pub async fn next(&mut self) -> Result<Message> {
|
||||||
|
if let Some(Ok(msg)) = self.0.next().await {
|
||||||
|
msg.try_into()
|
||||||
|
} else {
|
||||||
|
Err(Error::Unknown)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub async fn send(&mut self, msg: Message) -> Result<()> {
|
||||||
|
if self.0.send(msg.into()).await.is_err() {
|
||||||
|
Err(Error::Unknown)
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! msg {
|
||||||
|
( $command:ident) => {
|
||||||
|
{
|
||||||
|
let command = stringify!($command).to_string();
|
||||||
|
let args = vec![];
|
||||||
|
Message { command, args }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
( $command:ident, $( $arg:expr ),*) => {
|
||||||
|
{
|
||||||
|
let command = stringify!($command).to_string();
|
||||||
|
let args = vec![$($arg.to_string()),*];
|
||||||
|
Message { command, args }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for Message {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
|
||||||
|
if self.args.is_empty() {
|
||||||
|
write!(f, "{}:", self.command)
|
||||||
|
} else {
|
||||||
|
let args: Vec<_> = self.args.iter().map(|s| s.replace(",", "\\,")).collect();
|
||||||
|
write!(f, "{}: {}", self.command, args.join(", "))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -39,13 +120,24 @@ mod test {
|
|||||||
use super::*;
|
use super::*;
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse() -> Result<()> {
|
fn test_parse() -> Result<()> {
|
||||||
let text = "COMMAND: arg1, arg2";
|
// Simple test
|
||||||
let msg = Message::parse(text)?;
|
let text = "COMMAND: arg1, arg2";
|
||||||
assert_eq!(Message {
|
let msg = Message::parse(text.to_string())?;
|
||||||
command: "COMMAND",
|
assert_eq!(msg!(COMMAND, "arg1", "arg2"), msg);
|
||||||
args: vec!["arg1", "arg2"],
|
// With backtick delimited arguments
|
||||||
}, msg);
|
let text = "COMMAND: arg1\\, comment, arg2";
|
||||||
|
let msg = Message::parse(text.to_string())?;
|
||||||
|
assert_eq!(msg!(COMMAND, "arg1, comment", "arg2"), msg);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn test_to_string() {
|
||||||
|
// Simple test
|
||||||
|
let msg = msg!(COMMAND, "arg1", "arg2");
|
||||||
|
assert_eq!(msg.to_string(), "COMMAND: arg1, arg2".to_string());
|
||||||
|
|
||||||
Ok(())
|
// Escaped commas in arguments
|
||||||
|
let msg = msg!(COMMAND, "arg1, comment", "arg2");
|
||||||
|
assert_eq!(msg.to_string(), "COMMAND: arg1\\, comment, arg2");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ async def test():
|
|||||||
assert(response == "HOSTJOIN:")
|
assert(response == "HOSTJOIN:")
|
||||||
await ws.send("HOST:")
|
await ws.send("HOST:")
|
||||||
response = await ws.recv()
|
response = await ws.recv()
|
||||||
assert(re.match(r"(\d|[a-f]){6}", response))
|
assert(re.match(r"CODE: [a-f\d]{6}", response))
|
||||||
|
|
||||||
asyncio.get_event_loop().run_until_complete(test())
|
asyncio.get_event_loop().run_until_complete(test())
|
||||||
print("All tests passed")
|
print("All tests passed")
|
||||||
|
|||||||
Reference in New Issue
Block a user