docker support, move server to sibling folder
parent
7a615c4489
commit
5200ba7723
|
|
@ -1,4 +1,4 @@
|
||||||
/target
|
target/
|
||||||
.vscode
|
.vscode
|
||||||
main
|
main
|
||||||
main.exe
|
main.exe
|
||||||
|
|
@ -7,4 +7,5 @@ main.pdb
|
||||||
restarts.log
|
restarts.log
|
||||||
nohup.out
|
nohup.out
|
||||||
server.log
|
server.log
|
||||||
control_panel.log
|
control_panel.log
|
||||||
|
onefetch.out
|
||||||
|
|
@ -1,798 +0,0 @@
|
||||||
# This file is automatically @generated by Cargo.
|
|
||||||
# It is not intended for manual editing.
|
|
||||||
version = 3
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "async-attributes"
|
|
||||||
version = "1.1.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a3203e79f4dd9bdda415ed03cf14dae5a2bf775c683a00f94e9cd1faf0f596e5"
|
|
||||||
dependencies = [
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "async-channel"
|
|
||||||
version = "1.6.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2114d64672151c0c5eaa5e131ec84a74f06e1e559830dabba01ca30605d66319"
|
|
||||||
dependencies = [
|
|
||||||
"concurrent-queue",
|
|
||||||
"event-listener",
|
|
||||||
"futures-core",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "async-executor"
|
|
||||||
version = "1.4.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "871f9bb5e0a22eeb7e8cf16641feb87c9dc67032ccf8ff49e772eb9941d3a965"
|
|
||||||
dependencies = [
|
|
||||||
"async-task",
|
|
||||||
"concurrent-queue",
|
|
||||||
"fastrand",
|
|
||||||
"futures-lite",
|
|
||||||
"once_cell",
|
|
||||||
"slab",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "async-global-executor"
|
|
||||||
version = "2.0.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c026b7e44f1316b567ee750fea85103f87fcb80792b860e979f221259796ca0a"
|
|
||||||
dependencies = [
|
|
||||||
"async-channel",
|
|
||||||
"async-executor",
|
|
||||||
"async-io",
|
|
||||||
"async-mutex",
|
|
||||||
"blocking",
|
|
||||||
"futures-lite",
|
|
||||||
"num_cpus",
|
|
||||||
"once_cell",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "async-io"
|
|
||||||
version = "1.6.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a811e6a479f2439f0c04038796b5cfb3d2ad56c230e0f2d3f7b04d68cfee607b"
|
|
||||||
dependencies = [
|
|
||||||
"concurrent-queue",
|
|
||||||
"futures-lite",
|
|
||||||
"libc",
|
|
||||||
"log",
|
|
||||||
"once_cell",
|
|
||||||
"parking",
|
|
||||||
"polling",
|
|
||||||
"slab",
|
|
||||||
"socket2",
|
|
||||||
"waker-fn",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "async-lock"
|
|
||||||
version = "2.5.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e97a171d191782fba31bb902b14ad94e24a68145032b7eedf871ab0bc0d077b6"
|
|
||||||
dependencies = [
|
|
||||||
"event-listener",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "async-mutex"
|
|
||||||
version = "1.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "479db852db25d9dbf6204e6cb6253698f175c15726470f78af0d918e99d6156e"
|
|
||||||
dependencies = [
|
|
||||||
"event-listener",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "async-notify"
|
|
||||||
version = "0.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8356f653934a654817bceada97a857ef8d68ab8992753d23ed8e8ccd5fc8fa31"
|
|
||||||
dependencies = [
|
|
||||||
"futures-channel",
|
|
||||||
"futures-util",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "async-std"
|
|
||||||
version = "1.10.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f8056f1455169ab86dd47b47391e4ab0cbd25410a70e9fe675544f49bafaf952"
|
|
||||||
dependencies = [
|
|
||||||
"async-attributes",
|
|
||||||
"async-channel",
|
|
||||||
"async-global-executor",
|
|
||||||
"async-io",
|
|
||||||
"async-lock",
|
|
||||||
"crossbeam-utils",
|
|
||||||
"futures-channel",
|
|
||||||
"futures-core",
|
|
||||||
"futures-io",
|
|
||||||
"futures-lite",
|
|
||||||
"gloo-timers",
|
|
||||||
"kv-log-macro",
|
|
||||||
"log",
|
|
||||||
"memchr",
|
|
||||||
"num_cpus",
|
|
||||||
"once_cell",
|
|
||||||
"pin-project-lite",
|
|
||||||
"pin-utils",
|
|
||||||
"slab",
|
|
||||||
"wasm-bindgen-futures",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "async-task"
|
|
||||||
version = "4.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "30696a84d817107fc028e049980e09d5e140e8da8f1caeb17e8e950658a3cea9"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "atomic-waker"
|
|
||||||
version = "1.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "autocfg"
|
|
||||||
version = "1.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "blocking"
|
|
||||||
version = "1.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "046e47d4b2d391b1f6f8b407b1deb8dee56c1852ccd868becf2710f601b5f427"
|
|
||||||
dependencies = [
|
|
||||||
"async-channel",
|
|
||||||
"async-task",
|
|
||||||
"atomic-waker",
|
|
||||||
"fastrand",
|
|
||||||
"futures-lite",
|
|
||||||
"once_cell",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "bumpalo"
|
|
||||||
version = "3.9.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cache-padded"
|
|
||||||
version = "1.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c1db59621ec70f09c5e9b597b220c7a2b43611f4710dc03ceb8748637775692c"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cc"
|
|
||||||
version = "1.0.73"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cfg-if"
|
|
||||||
version = "1.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "chrono"
|
|
||||||
version = "0.4.19"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"num-integer",
|
|
||||||
"num-traits",
|
|
||||||
"time 0.1.44",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "concurrent-queue"
|
|
||||||
version = "1.2.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3"
|
|
||||||
dependencies = [
|
|
||||||
"cache-padded",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "crossbeam-utils"
|
|
||||||
version = "0.8.7"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b5e5bed1f1c269533fa816a0a5492b3545209a205ca1a54842be180eb63a16a6"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"lazy_static",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ctor"
|
|
||||||
version = "0.1.21"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ccc0a48a9b826acdf4028595adc9db92caea352f7af011a3034acd172a52a0aa"
|
|
||||||
dependencies = [
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "event-listener"
|
|
||||||
version = "2.5.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "77f3309417938f28bf8228fcff79a4a37103981e3e186d2ccd19c74b38f4eb71"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "fastrand"
|
|
||||||
version = "1.7.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf"
|
|
||||||
dependencies = [
|
|
||||||
"instant",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "futures"
|
|
||||||
version = "0.3.21"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e"
|
|
||||||
dependencies = [
|
|
||||||
"futures-channel",
|
|
||||||
"futures-core",
|
|
||||||
"futures-executor",
|
|
||||||
"futures-io",
|
|
||||||
"futures-sink",
|
|
||||||
"futures-task",
|
|
||||||
"futures-util",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "futures-channel"
|
|
||||||
version = "0.3.21"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010"
|
|
||||||
dependencies = [
|
|
||||||
"futures-core",
|
|
||||||
"futures-sink",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "futures-core"
|
|
||||||
version = "0.3.21"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "futures-executor"
|
|
||||||
version = "0.3.21"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6"
|
|
||||||
dependencies = [
|
|
||||||
"futures-core",
|
|
||||||
"futures-task",
|
|
||||||
"futures-util",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "futures-io"
|
|
||||||
version = "0.3.21"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "futures-lite"
|
|
||||||
version = "1.12.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48"
|
|
||||||
dependencies = [
|
|
||||||
"fastrand",
|
|
||||||
"futures-core",
|
|
||||||
"futures-io",
|
|
||||||
"memchr",
|
|
||||||
"parking",
|
|
||||||
"pin-project-lite",
|
|
||||||
"waker-fn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "futures-macro"
|
|
||||||
version = "0.3.21"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "futures-sink"
|
|
||||||
version = "0.3.21"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "futures-task"
|
|
||||||
version = "0.3.21"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "futures-util"
|
|
||||||
version = "0.3.21"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a"
|
|
||||||
dependencies = [
|
|
||||||
"futures-channel",
|
|
||||||
"futures-core",
|
|
||||||
"futures-io",
|
|
||||||
"futures-macro",
|
|
||||||
"futures-sink",
|
|
||||||
"futures-task",
|
|
||||||
"memchr",
|
|
||||||
"pin-project-lite",
|
|
||||||
"pin-utils",
|
|
||||||
"slab",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "gloo-timers"
|
|
||||||
version = "0.2.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4d12a7f4e95cfe710f1d624fb1210b7d961a5fb05c4fd942f4feab06e61f590e"
|
|
||||||
dependencies = [
|
|
||||||
"futures-channel",
|
|
||||||
"futures-core",
|
|
||||||
"js-sys",
|
|
||||||
"wasm-bindgen",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "hermit-abi"
|
|
||||||
version = "0.1.19"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "instant"
|
|
||||||
version = "0.1.12"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "itoa"
|
|
||||||
version = "1.0.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "js-sys"
|
|
||||||
version = "0.3.56"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a38fc24e30fd564ce974c02bf1d337caddff65be6cc4735a1f7eab22a7440f04"
|
|
||||||
dependencies = [
|
|
||||||
"wasm-bindgen",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "kv-log-macro"
|
|
||||||
version = "1.0.7"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f"
|
|
||||||
dependencies = [
|
|
||||||
"log",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "lazy_static"
|
|
||||||
version = "1.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "libc"
|
|
||||||
version = "0.2.117"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e74d72e0f9b65b5b4ca49a346af3976df0f9c61d550727f349ecd559f251a26c"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "log"
|
|
||||||
version = "0.4.14"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"value-bag",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "memchr"
|
|
||||||
version = "2.4.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "num-integer"
|
|
||||||
version = "0.1.44"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
|
|
||||||
dependencies = [
|
|
||||||
"autocfg",
|
|
||||||
"num-traits",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "num-traits"
|
|
||||||
version = "0.2.14"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
|
|
||||||
dependencies = [
|
|
||||||
"autocfg",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "num_cpus"
|
|
||||||
version = "1.13.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
|
|
||||||
dependencies = [
|
|
||||||
"hermit-abi",
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "num_threads"
|
|
||||||
version = "0.1.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "once_cell"
|
|
||||||
version = "1.10.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "parking"
|
|
||||||
version = "2.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pin-project-lite"
|
|
||||||
version = "0.2.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pin-utils"
|
|
||||||
version = "0.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "polling"
|
|
||||||
version = "2.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "685404d509889fade3e86fe3a5803bca2ec09b0c0778d5ada6ec8bf7a8de5259"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"libc",
|
|
||||||
"log",
|
|
||||||
"wepoll-ffi",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "proc-macro2"
|
|
||||||
version = "1.0.36"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029"
|
|
||||||
dependencies = [
|
|
||||||
"unicode-xid",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "quote"
|
|
||||||
version = "1.0.15"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ryu"
|
|
||||||
version = "1.0.9"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "serde"
|
|
||||||
version = "1.0.136"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789"
|
|
||||||
dependencies = [
|
|
||||||
"serde_derive",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "serde_derive"
|
|
||||||
version = "1.0.136"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "serde_json"
|
|
||||||
version = "1.0.79"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95"
|
|
||||||
dependencies = [
|
|
||||||
"itoa",
|
|
||||||
"ryu",
|
|
||||||
"serde",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "simplelog"
|
|
||||||
version = "0.12.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "48dfff04aade74dd495b007c831cd6f4e0cee19c344dd9dc0884c0289b70a786"
|
|
||||||
dependencies = [
|
|
||||||
"log",
|
|
||||||
"termcolor",
|
|
||||||
"time 0.3.11",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "slab"
|
|
||||||
version = "0.4.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "socket2"
|
|
||||||
version = "0.4.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "syn"
|
|
||||||
version = "1.0.86"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"unicode-xid",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "termcolor"
|
|
||||||
version = "1.1.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
|
|
||||||
dependencies = [
|
|
||||||
"winapi-util",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "time"
|
|
||||||
version = "0.1.44"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"wasi",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "time"
|
|
||||||
version = "0.3.11"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "72c91f41dcb2f096c05f0873d667dceec1087ce5bcf984ec8ffb19acddbb3217"
|
|
||||||
dependencies = [
|
|
||||||
"itoa",
|
|
||||||
"libc",
|
|
||||||
"num_threads",
|
|
||||||
"time-macros",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "time-macros"
|
|
||||||
version = "0.2.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "unicode-xid"
|
|
||||||
version = "0.2.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "value-bag"
|
|
||||||
version = "1.0.0-alpha.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "79923f7731dc61ebfba3633098bf3ac533bbd35ccd8c57e7088d9a5eebe0263f"
|
|
||||||
dependencies = [
|
|
||||||
"ctor",
|
|
||||||
"version_check",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "velnet_server"
|
|
||||||
version = "0.2.0"
|
|
||||||
dependencies = [
|
|
||||||
"async-notify",
|
|
||||||
"async-std",
|
|
||||||
"chrono",
|
|
||||||
"futures",
|
|
||||||
"log",
|
|
||||||
"serde",
|
|
||||||
"serde_json",
|
|
||||||
"simplelog",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "version_check"
|
|
||||||
version = "0.9.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "waker-fn"
|
|
||||||
version = "1.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wasi"
|
|
||||||
version = "0.10.0+wasi-snapshot-preview1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wasm-bindgen"
|
|
||||||
version = "0.2.79"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "25f1af7423d8588a3d840681122e72e6a24ddbcb3f0ec385cac0d12d24256c06"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"wasm-bindgen-macro",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wasm-bindgen-backend"
|
|
||||||
version = "0.2.79"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8b21c0df030f5a177f3cba22e9bc4322695ec43e7257d865302900290bcdedca"
|
|
||||||
dependencies = [
|
|
||||||
"bumpalo",
|
|
||||||
"lazy_static",
|
|
||||||
"log",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
"wasm-bindgen-shared",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wasm-bindgen-futures"
|
|
||||||
version = "0.4.29"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2eb6ec270a31b1d3c7e266b999739109abce8b6c87e4b31fcfcd788b65267395"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"js-sys",
|
|
||||||
"wasm-bindgen",
|
|
||||||
"web-sys",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wasm-bindgen-macro"
|
|
||||||
version = "0.2.79"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2f4203d69e40a52ee523b2529a773d5ffc1dc0071801c87b3d270b471b80ed01"
|
|
||||||
dependencies = [
|
|
||||||
"quote",
|
|
||||||
"wasm-bindgen-macro-support",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wasm-bindgen-macro-support"
|
|
||||||
version = "0.2.79"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "bfa8a30d46208db204854cadbb5d4baf5fcf8071ba5bf48190c3e59937962ebc"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
"wasm-bindgen-backend",
|
|
||||||
"wasm-bindgen-shared",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wasm-bindgen-shared"
|
|
||||||
version = "0.2.79"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3d958d035c4438e28c70e4321a2911302f10135ce78a9c7834c0cab4123d06a2"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "web-sys"
|
|
||||||
version = "0.3.56"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c060b319f29dd25724f09a2ba1418f142f539b2be99fbf4d2d5a8f7330afb8eb"
|
|
||||||
dependencies = [
|
|
||||||
"js-sys",
|
|
||||||
"wasm-bindgen",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wepoll-ffi"
|
|
||||||
version = "0.1.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb"
|
|
||||||
dependencies = [
|
|
||||||
"cc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "winapi"
|
|
||||||
version = "0.3.9"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
|
||||||
dependencies = [
|
|
||||||
"winapi-i686-pc-windows-gnu",
|
|
||||||
"winapi-x86_64-pc-windows-gnu",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "winapi-i686-pc-windows-gnu"
|
|
||||||
version = "0.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "winapi-util"
|
|
||||||
version = "0.1.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
|
|
||||||
dependencies = [
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "winapi-x86_64-pc-windows-gnu"
|
|
||||||
version = "0.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
|
||||||
16
Cargo.toml
16
Cargo.toml
|
|
@ -1,16 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "velnet_server"
|
|
||||||
version = "0.2.0"
|
|
||||||
edition = "2021"
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
chrono = "*"
|
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
|
||||||
serde_json = "1.0"
|
|
||||||
async-std = { version = "1.6", features = ["attributes"]}
|
|
||||||
futures = "*"
|
|
||||||
async-notify = "*"
|
|
||||||
simplelog = "^0.12.0"
|
|
||||||
log = "*"
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
{
|
|
||||||
"port": 5000,
|
|
||||||
"tcp_timeout": 30,
|
|
||||||
"log_file": "server.log"
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
/target
|
|
||||||
.vscode
|
|
||||||
main
|
|
||||||
main.exe
|
|
||||||
main.pdb
|
|
||||||
.idea/
|
|
||||||
onefetch.out
|
|
||||||
|
|
@ -6,7 +6,7 @@ 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]
|
||||||
actix-web = "4"
|
actix-web = "4.1.0"
|
||||||
handlebars = { version = "4.2.1", features = ["dir_source"] }
|
handlebars = { version = "4.2.1", features = ["dir_source"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
|
|
||||||
993
src/main.rs
993
src/main.rs
|
|
@ -1,993 +0,0 @@
|
||||||
use async_std::prelude::*;
|
|
||||||
use async_std::future;
|
|
||||||
use async_std::net::TcpListener;
|
|
||||||
use async_std::net::TcpStream;
|
|
||||||
use async_std::net::UdpSocket;
|
|
||||||
use async_notify::Notify;
|
|
||||||
use futures::stream::StreamExt;
|
|
||||||
use futures::join;
|
|
||||||
use futures::select;
|
|
||||||
use futures::pin_mut;
|
|
||||||
use futures::future::FutureExt;
|
|
||||||
use async_std::net::{IpAddr, SocketAddr};
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::rc::{Rc};
|
|
||||||
use std::cell::{RefCell};
|
|
||||||
use std::fs;
|
|
||||||
use chrono::Local;
|
|
||||||
use std::time::Duration;
|
|
||||||
use serde::{Serialize, Deserialize};
|
|
||||||
use std::error::Error;
|
|
||||||
use std::fs::OpenOptions;
|
|
||||||
use std::io::BufReader;
|
|
||||||
use std::ptr;
|
|
||||||
use simplelog::*;
|
|
||||||
|
|
||||||
enum ToClientTCPMessageType {
|
|
||||||
LoggedIn = 0,
|
|
||||||
RoomList = 1,
|
|
||||||
PlayerJoined = 2,
|
|
||||||
DataMessage = 3,
|
|
||||||
MasterMessage = 4,
|
|
||||||
YouJoined = 5,
|
|
||||||
PlayerLeft = 6,
|
|
||||||
YouLeft = 7,
|
|
||||||
RoomData = 8,
|
|
||||||
}
|
|
||||||
|
|
||||||
enum FromClientTCPMessageType {
|
|
||||||
LogIn = 0,
|
|
||||||
GetRooms = 1,
|
|
||||||
JoinRoom = 2,
|
|
||||||
SendMessageOthersUnbuffered = 3,
|
|
||||||
SendMessageAllUnbuffered = 4,
|
|
||||||
SendMessageGroupUnbuffered = 5,
|
|
||||||
CreateGroup = 6,
|
|
||||||
SendMessageOthersBuffered = 7,
|
|
||||||
SendMessageAllBuffered = 8,
|
|
||||||
GetRoomData = 9,
|
|
||||||
}
|
|
||||||
|
|
||||||
enum ToClientUDPMessageType {
|
|
||||||
Connected = 0,
|
|
||||||
DataMessage = ToClientTCPMessageType::DataMessage as isize,
|
|
||||||
}
|
|
||||||
|
|
||||||
enum FromClientUDPMessageType {
|
|
||||||
Connect = 0,
|
|
||||||
SendMessageOthersUnbuffered = FromClientTCPMessageType::SendMessageOthersUnbuffered as isize,
|
|
||||||
SendMessageAllUnbuffered = FromClientTCPMessageType::SendMessageAllUnbuffered as isize,
|
|
||||||
SendMessageGroupUnbuffered = FromClientTCPMessageType::SendMessageGroupUnbuffered as isize,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Client {
|
|
||||||
logged_in: bool,
|
|
||||||
id: u32,
|
|
||||||
username: String,
|
|
||||||
room_name: String,
|
|
||||||
application: String,
|
|
||||||
groups: HashMap<String, Vec<Rc<RefCell<Client>>>>,
|
|
||||||
ip: IpAddr,
|
|
||||||
udp_port: u16,
|
|
||||||
message_queue: Vec<u8>,
|
|
||||||
message_queue_udp: Vec<Vec<u8>>,
|
|
||||||
notify: Rc<Notify>,
|
|
||||||
notify_udp: Rc<Notify>,
|
|
||||||
is_master: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Room {
|
|
||||||
name: String,
|
|
||||||
clients: HashMap<u32, Rc<RefCell<Client>>>,
|
|
||||||
master_client: Rc<RefCell<Client>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
struct VelNetConfig {
|
|
||||||
port: u16,
|
|
||||||
tcp_timeout: u64,
|
|
||||||
log_file: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[async_std::main]
|
|
||||||
async fn main() {
|
|
||||||
let config = read_config_file().unwrap();
|
|
||||||
|
|
||||||
let f = OpenOptions::new()
|
|
||||||
.write(true)
|
|
||||||
.append(true)
|
|
||||||
.create(true)
|
|
||||||
.open(config.log_file)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
CombinedLogger::init(
|
|
||||||
vec![
|
|
||||||
TermLogger::new(LevelFilter::Info, Config::default(), TerminalMode::Mixed, ColorChoice::Auto),
|
|
||||||
WriteLogger::new(LevelFilter::Debug, Config::default(), f),
|
|
||||||
]
|
|
||||||
).unwrap();
|
|
||||||
|
|
||||||
log::info!("----------------------");
|
|
||||||
log::info!("VelNet Server Starting");
|
|
||||||
|
|
||||||
// read the config file
|
|
||||||
let foo = fs::read_to_string("config.json").unwrap();
|
|
||||||
let config: VelNetConfig = serde_json::from_str(&foo).unwrap();
|
|
||||||
log::info!("Running on port: {}", config.port);
|
|
||||||
|
|
||||||
let tcp_listener = TcpListener::bind(format!("0.0.0.0:{}", config.port)).await.unwrap();
|
|
||||||
let udp_socket = Rc::new(RefCell::new(UdpSocket::bind(format!("0.0.0.0:{}", config.port)).await.unwrap()));
|
|
||||||
|
|
||||||
let clients: Rc<RefCell<HashMap<u32, Rc<RefCell<Client>>>>> = Rc::new(RefCell::new(HashMap::new()));
|
|
||||||
let rooms: Rc<RefCell<HashMap<String, Rc<RefCell<Room>>>>> = Rc::new(RefCell::new(HashMap::new()));
|
|
||||||
let last_client_id = Rc::new(RefCell::new(0));
|
|
||||||
|
|
||||||
let tcp_future = tcp_listener
|
|
||||||
.incoming()
|
|
||||||
.for_each_concurrent(None, |tcpstream| process_client(tcpstream.unwrap(), udp_socket.clone(), clients.clone(), rooms.clone(), last_client_id.clone(), &config));
|
|
||||||
let udp_future = process_udp(udp_socket.clone(), clients.clone(), rooms.clone());
|
|
||||||
join!(tcp_future,udp_future);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fn read_config_file() -> Result<VelNetConfig, Box<dyn Error>> {
|
|
||||||
// Open the file in read-only mode with buffer.
|
|
||||||
let file = fs::File::open("config.json")?;
|
|
||||||
let reader = BufReader::new(file);
|
|
||||||
|
|
||||||
let config = serde_json::from_reader(reader)?;
|
|
||||||
|
|
||||||
Ok(config)
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn process_client(socket: TcpStream, udp_socket: Rc<RefCell<UdpSocket>>, clients: Rc<RefCell<HashMap<u32, Rc<RefCell<Client>>>>>, rooms: Rc<RefCell<HashMap<String, Rc<RefCell<Room>>>>>, last_client_id: Rc<RefCell<u32>>, config: &VelNetConfig) {
|
|
||||||
log::info!("Started TCP");
|
|
||||||
|
|
||||||
match socket.set_nodelay(true) {
|
|
||||||
Ok(_) => {}
|
|
||||||
Err(_) => {
|
|
||||||
log::error!("Could not set no delay");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//socket.set_read_timeout(Some(time::Duration::new(config.tcp_timeout,0))).unwrap();
|
|
||||||
//socket.set_write_timeout(Some(time::Duration::new(config.tcp_timeout,0))).unwrap();
|
|
||||||
|
|
||||||
let my_id;
|
|
||||||
{
|
|
||||||
let mut reference = last_client_id.borrow_mut();
|
|
||||||
*reference = *reference + 1;
|
|
||||||
my_id = *reference;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
let client_notify = Rc::new(Notify::new());
|
|
||||||
let client_notify_udp = Rc::new(Notify::new());
|
|
||||||
|
|
||||||
let ip;
|
|
||||||
|
|
||||||
match socket.peer_addr() {
|
|
||||||
Ok(p) => ip = p.ip(),
|
|
||||||
Err(_) => { return; }
|
|
||||||
}
|
|
||||||
|
|
||||||
let client = Rc::new(RefCell::new(Client {
|
|
||||||
id: my_id,
|
|
||||||
username: String::from(""),
|
|
||||||
logged_in: false,
|
|
||||||
room_name: String::from(""),
|
|
||||||
application: String::from(""),
|
|
||||||
groups: HashMap::new(),
|
|
||||||
ip: ip,
|
|
||||||
udp_port: 0 as u16,
|
|
||||||
message_queue: vec![],
|
|
||||||
message_queue_udp: vec![],
|
|
||||||
notify: client_notify.clone(),
|
|
||||||
notify_udp: client_notify_udp.clone(),
|
|
||||||
is_master: false,
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
log::info!("Spawned client handler = {}", my_id);
|
|
||||||
|
|
||||||
{
|
|
||||||
let temp_client = client.clone();
|
|
||||||
let mut clients_temp = clients.borrow_mut();
|
|
||||||
clients_temp.insert(my_id, temp_client);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
let read_async = client_read(client.clone(), socket.clone(), clients.clone(), rooms.clone(), config.tcp_timeout * 1000).fuse();
|
|
||||||
let write_async = client_write(client.clone(), socket, client_notify.clone(), config.tcp_timeout * 1000).fuse();
|
|
||||||
let write_async_udp = client_write_udp(client.clone(), udp_socket.clone(), client_notify_udp.clone()).fuse();
|
|
||||||
|
|
||||||
pin_mut!(read_async,write_async,write_async_udp); //not sure why this is necessary, since select
|
|
||||||
|
|
||||||
select! { //
|
|
||||||
() = read_async => log::debug!("read async ended"),
|
|
||||||
() = write_async => log::debug!("write async ended"),
|
|
||||||
() = write_async_udp => log::debug!("write async udp ended")
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
client_leave_room(client.clone(), false, rooms.clone());
|
|
||||||
let mut clients_temp = clients.borrow_mut();
|
|
||||||
clients_temp.remove(&client.borrow().id);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
log::info!("Client {} left", client.borrow().id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn read_timeout(mut socket: &TcpStream, buf: &mut [u8], duration: u64) -> Result<usize, Box<dyn Error>> {
|
|
||||||
|
|
||||||
//this is a read exact function. The buffer passed should be the exact size wanted
|
|
||||||
|
|
||||||
let num_to_read = buf.len();
|
|
||||||
|
|
||||||
let mut num_read = 0;
|
|
||||||
|
|
||||||
while num_read < num_to_read {
|
|
||||||
match future::timeout(Duration::from_millis(duration), socket.read(&mut buf[num_read..])).await {
|
|
||||||
Ok(r) => {
|
|
||||||
match r {
|
|
||||||
Ok(n) if n == 0 => {
|
|
||||||
return Err(format!("{}", "no bytes read"))?;
|
|
||||||
}
|
|
||||||
Ok(n) => {
|
|
||||||
num_read += n;
|
|
||||||
}
|
|
||||||
Err(e) => { return Err(format!("{}", e.to_string()))?; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Err(e) => { return Err(format!("{}", e.to_string()))?; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ok(num_read);
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn client_read(client: Rc<RefCell<Client>>, mut socket: TcpStream, clients: Rc<RefCell<HashMap<u32, Rc<RefCell<Client>>>>>, rooms: Rc<RefCell<HashMap<String, Rc<RefCell<Room>>>>>, duration: u64) {
|
|
||||||
let mut buf = [0; 1];
|
|
||||||
|
|
||||||
loop {
|
|
||||||
match read_timeout(&mut socket, &mut buf, duration).await {
|
|
||||||
Ok(_) => {
|
|
||||||
let t = buf[0];
|
|
||||||
if t == FromClientTCPMessageType::LogIn as u8 { //[0:u8][username.length():u8][username:shortstring][password.length():u8][password:shortstring]
|
|
||||||
match read_login_message(socket.clone(), client.clone(), duration).await {
|
|
||||||
Ok(_) => (),
|
|
||||||
Err(_) => {
|
|
||||||
log::error!("failed to read from socket");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} else if t == FromClientTCPMessageType::GetRooms as u8 {//[1:u8]
|
|
||||||
match read_rooms_message(socket.clone(), client.clone(), rooms.clone()).await {
|
|
||||||
Ok(_) => (),
|
|
||||||
Err(_) => {
|
|
||||||
log::error!("failed to read from socket");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} else if t == FromClientTCPMessageType::GetRoomData as u8 {
|
|
||||||
match read_roomdata_message(socket.clone(), client.clone(), rooms.clone(), duration).await {
|
|
||||||
Ok(_) => (),
|
|
||||||
Err(_) => {
|
|
||||||
log::error!("failed to read from socket");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} else if t == FromClientTCPMessageType::JoinRoom as u8 {//[2:u8][roomname.length():u8][roomname:shortstring]
|
|
||||||
match read_join_message(socket.clone(), client.clone(), rooms.clone(), duration).await {
|
|
||||||
Ok(_) => (),
|
|
||||||
Err(_) => {
|
|
||||||
log::error!("failed to read from socket");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} else if t == FromClientTCPMessageType::SendMessageOthersUnbuffered as u8 ||
|
|
||||||
t == FromClientTCPMessageType::SendMessageAllUnbuffered as u8 ||
|
|
||||||
t == FromClientTCPMessageType::SendMessageGroupUnbuffered as u8 ||
|
|
||||||
t == FromClientTCPMessageType::SendMessageOthersBuffered as u8 ||
|
|
||||||
t == FromClientTCPMessageType::SendMessageAllBuffered as u8 { //others,all,group[t:u8][message.length():i32][message:u8array]
|
|
||||||
match read_send_message(socket.clone(), client.clone(), rooms.clone(), t, duration).await {
|
|
||||||
Ok(_) => (),
|
|
||||||
Err(_) => {
|
|
||||||
log::error!("failed to read from socket");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} else if t == FromClientTCPMessageType::CreateGroup as u8 { //[t:u8][list.lengthbytes:i32][clients:i32array]
|
|
||||||
match read_group_message(socket.clone(), client.clone(), clients.clone(), duration).await {
|
|
||||||
Ok(_) => (),
|
|
||||||
Err(_) => {
|
|
||||||
log::error!("failed to read from socket");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
//die...not correct protocol
|
|
||||||
log::error!("Incorrect protocol, killing");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
log::error!("failed to read from socket; err = {:?}", e);
|
|
||||||
//remove the client
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
async fn write_timeout(mut socket: &TcpStream, buf: &[u8], duration: u64) -> Result<usize, Box<dyn Error>> {
|
|
||||||
return match future::timeout(Duration::from_millis(duration), socket.write(buf)).await {
|
|
||||||
Ok(r) => {
|
|
||||||
match r {
|
|
||||||
Ok(n) => {
|
|
||||||
Ok(n)
|
|
||||||
}
|
|
||||||
Err(e) => { Err(format!("{}", e.to_string()))? }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Err(e) => { Err(format!("{}", e.to_string()))? }
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
async fn client_write(client: Rc<RefCell<Client>>, mut socket: TcpStream, notify: Rc<Notify>, duration: u64) {
|
|
||||||
|
|
||||||
//wait on messages in my queue
|
|
||||||
loop {
|
|
||||||
notify.notified().await; //there is something to write
|
|
||||||
|
|
||||||
let mut to_write = vec![];
|
|
||||||
{
|
|
||||||
let client_ref = client.borrow();
|
|
||||||
to_write.extend_from_slice(&client_ref.message_queue); //must do this so that the borrow ends
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
let mut client_ref = client.borrow_mut();
|
|
||||||
client_ref.message_queue.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
match write_timeout(&mut socket, &to_write, duration).await {
|
|
||||||
Ok(_) => (),
|
|
||||||
Err(_) => {
|
|
||||||
log::error!("failed to write to the tcp socket");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn client_write_udp(client: Rc<RefCell<Client>>, socket: Rc<RefCell<UdpSocket>>, notify: Rc<Notify>) {
|
|
||||||
loop {
|
|
||||||
notify.notified().await; //there is something to write
|
|
||||||
|
|
||||||
let ip;
|
|
||||||
let port;
|
|
||||||
let mut messages = vec![];
|
|
||||||
{
|
|
||||||
let mut client_ref = client.borrow_mut();
|
|
||||||
ip = client_ref.ip;
|
|
||||||
port = client_ref.udp_port;
|
|
||||||
for msg in client_ref.message_queue_udp.iter() {
|
|
||||||
messages.push(msg.clone());
|
|
||||||
}
|
|
||||||
client_ref.message_queue_udp.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
for msg in messages.iter() {
|
|
||||||
let socket = socket.borrow();
|
|
||||||
match socket.send_to(&msg, SocketAddr::new(ip, port)).await {
|
|
||||||
Ok(_) => (),
|
|
||||||
Err(_) => {
|
|
||||||
log::error!("failed to write to the udp socket");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn process_udp(socket: Rc<RefCell<UdpSocket>>, clients: Rc<RefCell<HashMap<u32, Rc<RefCell<Client>>>>>, rooms: Rc<RefCell<HashMap<String, Rc<RefCell<Room>>>>>) {
|
|
||||||
let mut buf = [0u8; 1024];
|
|
||||||
loop {
|
|
||||||
let socket = socket.borrow();
|
|
||||||
let res = socket.recv_from(&mut buf).await;
|
|
||||||
|
|
||||||
match res {
|
|
||||||
Ok(_) => (),
|
|
||||||
Err(_) => continue
|
|
||||||
}
|
|
||||||
|
|
||||||
let (packet_size, addr) = res.unwrap();
|
|
||||||
let t = buf[0];
|
|
||||||
if packet_size >= 5 {
|
|
||||||
//get the client id, which has to be sent with every udp message, because you don't know where udp messages are coming from
|
|
||||||
let client_id_bytes = [buf[1], buf[2], buf[3], buf[4]];
|
|
||||||
let client_id = u32::from_be_bytes(client_id_bytes);
|
|
||||||
|
|
||||||
|
|
||||||
if t == FromClientUDPMessageType::Connect as u8 { //1 byte, 0. Nothing else. This is just to establish the udp port, Echos back the same thing sent
|
|
||||||
//connect message, respond back
|
|
||||||
|
|
||||||
|
|
||||||
let clients = clients.borrow();
|
|
||||||
if clients.contains_key(&client_id) {
|
|
||||||
let mut client = clients.get(&client_id).unwrap().borrow_mut();
|
|
||||||
client.udp_port = addr.port(); //set the udp port to send data to
|
|
||||||
client.message_queue_udp.push(vec![0]);
|
|
||||||
client.notify_udp.notify();
|
|
||||||
}
|
|
||||||
} else if t == FromClientUDPMessageType::SendMessageOthersUnbuffered as u8 { //[3:u8][from:i32][contents:u8array] note that it must fit into the packet of 1024 bytes
|
|
||||||
|
|
||||||
|
|
||||||
let clients = clients.borrow();
|
|
||||||
if clients.contains_key(&client_id) {
|
|
||||||
let client = clients.get(&client_id).unwrap().borrow();
|
|
||||||
let rooms_ref = rooms.borrow();
|
|
||||||
if client.room_name != "" {
|
|
||||||
let room = rooms_ref[&client.room_name].borrow();
|
|
||||||
buf[0] = ToClientUDPMessageType::DataMessage as u8; //technically unecessary, unless we change this number
|
|
||||||
for (_k, v) in room.clients.iter() {
|
|
||||||
if *_k != client_id {
|
|
||||||
let mut msg = vec![];
|
|
||||||
let mut v_ref = v.borrow_mut();
|
|
||||||
msg.extend_from_slice(&buf[0..packet_size]);
|
|
||||||
v_ref.message_queue_udp.push(msg);
|
|
||||||
v_ref.notify_udp.notify();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if t == FromClientUDPMessageType::SendMessageAllUnbuffered as u8 { //see above
|
|
||||||
let clients = clients.borrow();
|
|
||||||
if clients.contains_key(&client_id) {
|
|
||||||
let mut client = clients.get(&client_id).unwrap().borrow_mut();
|
|
||||||
let rooms_ref = rooms.borrow();
|
|
||||||
if client.room_name != "" {
|
|
||||||
let room = rooms_ref[&client.room_name].borrow();
|
|
||||||
buf[0] = ToClientUDPMessageType::DataMessage as u8; //technically unecessary, unless we change this number
|
|
||||||
for (_k, v) in room.clients.iter() {
|
|
||||||
if *_k != client_id {
|
|
||||||
let mut msg = vec![];
|
|
||||||
let mut v_ref = v.borrow_mut();
|
|
||||||
msg.extend_from_slice(&buf[0..packet_size]);
|
|
||||||
v_ref.message_queue_udp.push(msg);
|
|
||||||
v_ref.notify_udp.notify();
|
|
||||||
} else {
|
|
||||||
let mut msg = vec![];
|
|
||||||
msg.extend_from_slice(&buf[0..packet_size]);
|
|
||||||
client.message_queue_udp.push(msg);
|
|
||||||
client.notify_udp.notify();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if t == FromClientUDPMessageType::SendMessageGroupUnbuffered as u8 { //[5:byte][from:i32][group.length():u8][message:u8array]
|
|
||||||
//this one is a little different, because we don't send the group in the message, so we have to formulate another message (like a 3 message)
|
|
||||||
//send a message to a group
|
|
||||||
//read the group name
|
|
||||||
|
|
||||||
let group_name_size = buf[5];
|
|
||||||
let message_vec = buf[6..packet_size].to_vec();
|
|
||||||
let (group_name_bytes, message_bytes) = message_vec.split_at(group_name_size as usize);
|
|
||||||
|
|
||||||
let res = String::from_utf8(group_name_bytes.to_vec());
|
|
||||||
match res {
|
|
||||||
Ok(_) => {}
|
|
||||||
Err(_) => {
|
|
||||||
log::error!("Could not convert group name");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let group_name = res.unwrap();
|
|
||||||
|
|
||||||
let clients = clients.borrow();
|
|
||||||
|
|
||||||
let mut message_to_send = vec![];
|
|
||||||
message_to_send.push(ToClientUDPMessageType::DataMessage as u8);
|
|
||||||
message_to_send.extend([buf[1], buf[2], buf[3], buf[4]]);
|
|
||||||
message_to_send.extend(message_bytes);
|
|
||||||
|
|
||||||
let mut send_to_client = false;
|
|
||||||
if clients.contains_key(&client_id) {
|
|
||||||
{
|
|
||||||
{
|
|
||||||
let client = clients.get(&client_id).unwrap().borrow();
|
|
||||||
if client.groups.contains_key(&group_name) {
|
|
||||||
let clients = client.groups.get(&group_name).unwrap();
|
|
||||||
//we need to form a new message without the group name
|
|
||||||
|
|
||||||
|
|
||||||
for v in clients.iter() {
|
|
||||||
let mut skip_client = false;
|
|
||||||
|
|
||||||
{
|
|
||||||
let v_ref = v.borrow();
|
|
||||||
if v_ref.id == client.id {
|
|
||||||
skip_client = true;
|
|
||||||
send_to_client = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !skip_client {
|
|
||||||
let mut v_ref = v.borrow_mut();
|
|
||||||
v_ref.message_queue_udp.push(message_to_send.clone());
|
|
||||||
v_ref.notify_udp.notify();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if send_to_client {
|
|
||||||
let mut client = clients.get(&client_id).unwrap().borrow_mut();
|
|
||||||
client.message_queue_udp.push(message_to_send.clone());
|
|
||||||
client.notify_udp.notify();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//this is in response to someone asking to login (this is where usernames and passwords would be processed, in theory)
|
|
||||||
async fn read_login_message(mut stream: TcpStream, client: Rc<RefCell<Client>>, duration: u64) -> Result<(), Box<dyn Error>> {
|
|
||||||
//byte,shortstring,byte,shortstring
|
|
||||||
|
|
||||||
let username = read_short_string(&mut stream, duration).await?;
|
|
||||||
let application = read_short_string(&mut stream, duration).await?;
|
|
||||||
log::info!("{}: Got application {} and userid {}", Local::now().format("%Y-%m-%d %H:%M:%S"), application, username);
|
|
||||||
{
|
|
||||||
let mut client = client.borrow_mut();
|
|
||||||
client.username = username;
|
|
||||||
client.application = application;
|
|
||||||
client.logged_in = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
{
|
|
||||||
let mut client = client.borrow_mut();
|
|
||||||
let mut write_buf = vec![];
|
|
||||||
write_buf.push(ToClientTCPMessageType::LoggedIn as u8);
|
|
||||||
write_buf.extend_from_slice(&(client.id).to_be_bytes()); //send the client the id
|
|
||||||
client.message_queue.extend(write_buf);
|
|
||||||
client.notify.notify();
|
|
||||||
}
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn read_rooms_message(mut _stream: TcpStream, client: Rc<RefCell<Client>>, rooms: Rc<RefCell<HashMap<String, Rc<RefCell<Room>>>>>) -> Result<(), Box<dyn Error>> {
|
|
||||||
let mut write_buf = vec![];
|
|
||||||
write_buf.push(ToClientTCPMessageType::RoomList as u8);
|
|
||||||
//first we need to get the room names
|
|
||||||
|
|
||||||
let rooms = rooms.borrow();
|
|
||||||
let mut client = client.borrow_mut();
|
|
||||||
let mut rooms_vec = vec![];
|
|
||||||
for (k, v) in rooms.iter() {
|
|
||||||
if !k.starts_with(&client.application.to_string()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
let mut iter = k.chars();
|
|
||||||
|
|
||||||
iter.by_ref().nth(client.application.len());
|
|
||||||
let application_stripped_room = iter.as_str();
|
|
||||||
|
|
||||||
let room_string = format!("{}:{}", application_stripped_room, v.borrow().clients.len());
|
|
||||||
rooms_vec.push(room_string);
|
|
||||||
}
|
|
||||||
|
|
||||||
let rooms_message = rooms_vec.join(",");
|
|
||||||
let message_bytes = rooms_message.as_bytes();
|
|
||||||
let message_len = message_bytes.len() as u32;
|
|
||||||
write_buf.extend_from_slice(&(message_len).to_be_bytes());
|
|
||||||
write_buf.extend_from_slice(message_bytes);
|
|
||||||
client.message_queue.extend_from_slice(&write_buf);
|
|
||||||
client.notify.notify();
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn read_join_message(mut stream: TcpStream, client: Rc<RefCell<Client>>, rooms: Rc<RefCell<HashMap<String, Rc<RefCell<Room>>>>>, duration: u64) -> Result<(), Box<dyn Error>> {
|
|
||||||
//byte,shortstring
|
|
||||||
|
|
||||||
let short_room_name = read_short_string(&mut stream, duration).await?;
|
|
||||||
let extended_room_name;
|
|
||||||
let mut leave_room = false;
|
|
||||||
{
|
|
||||||
let client_ref = client.borrow();
|
|
||||||
extended_room_name = format!("{}_{}", client_ref.application, short_room_name);
|
|
||||||
if client_ref.room_name != "" {
|
|
||||||
leave_room = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if leave_room {
|
|
||||||
//todo
|
|
||||||
client_leave_room(client.clone(), true, rooms.clone());
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut client_ref = client.borrow_mut();
|
|
||||||
let mut rooms_ref = rooms.borrow_mut();
|
|
||||||
|
|
||||||
if short_room_name.trim() == "" || short_room_name == "-1" {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
if !rooms_ref.contains_key(&extended_room_name) { //new room, must create it
|
|
||||||
let map: HashMap<u32, Rc<RefCell<Client>>> = HashMap::new();
|
|
||||||
let r = Rc::new(RefCell::new(Room {
|
|
||||||
name: extended_room_name.to_string(),
|
|
||||||
clients: map,
|
|
||||||
master_client: client.clone(), //client is the master, since they joined first
|
|
||||||
}));
|
|
||||||
client_ref.is_master = true;
|
|
||||||
rooms_ref.insert(String::from(&extended_room_name), r);
|
|
||||||
log::info!("{}: {}: New room {} created", Local::now().format("%Y-%m-%d %H:%M:%S"), client_ref.application, &extended_room_name);
|
|
||||||
} else {
|
|
||||||
client_ref.is_master = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//the room is guaranteed to exist now, so this call can't fail
|
|
||||||
let mut room_to_join = rooms_ref[&extended_room_name].borrow_mut();
|
|
||||||
room_to_join.clients.insert(client_ref.id, client.clone());
|
|
||||||
log::info!("{}: {}: Client {} joined {}", Local::now().format("%Y-%m-%d %H:%M:%S"), client_ref.application, client_ref.id, &extended_room_name);
|
|
||||||
|
|
||||||
client_ref.room_name = extended_room_name; //we create an option and assign it back to the room
|
|
||||||
|
|
||||||
//send a join message to everyone in the room (except the client)
|
|
||||||
for (_k, v) in room_to_join.clients.iter() {
|
|
||||||
if *_k != client_ref.id {
|
|
||||||
send_client_join_message(v, client_ref.id, &short_room_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//send a join message to the client that has all of the ids in the room
|
|
||||||
let mut ids_in_room = vec![];
|
|
||||||
for (_k, _v) in room_to_join.clients.iter() {
|
|
||||||
ids_in_room.push(*_k);
|
|
||||||
}
|
|
||||||
send_you_joined_message(&mut *client_ref, ids_in_room, &short_room_name);
|
|
||||||
|
|
||||||
if client_ref.is_master {
|
|
||||||
let temp = client_ref.id;
|
|
||||||
send_client_master_message(&mut *client_ref, temp);
|
|
||||||
} else {
|
|
||||||
send_client_master_message(&mut *client_ref, room_to_join.master_client.borrow().id);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn read_roomdata_message(mut stream: TcpStream, client: Rc<RefCell<Client>>, rooms: Rc<RefCell<HashMap<String, Rc<RefCell<Room>>>>>, duration: u64) -> Result<(), Box<dyn Error>> {
|
|
||||||
//type, room_name
|
|
||||||
//will respond with type, numclients u32, id1 u32, name_len u8, name_bytes ...
|
|
||||||
|
|
||||||
//read the room name and append the client application
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let short_room_name = read_short_string(&mut stream, duration).await?;
|
|
||||||
let mut client_ref = client.borrow_mut();
|
|
||||||
let room_name = format!("{}_{}", client_ref.application, short_room_name);
|
|
||||||
|
|
||||||
//we need to access the rooms list
|
|
||||||
let rooms_ref = rooms.borrow();
|
|
||||||
if rooms_ref.contains_key(&room_name) {
|
|
||||||
let room = rooms_ref.get(&room_name).unwrap();
|
|
||||||
//form and send the message
|
|
||||||
let mut write_buf = vec![];
|
|
||||||
write_buf.push(ToClientTCPMessageType::RoomData as u8);
|
|
||||||
|
|
||||||
|
|
||||||
let roomname_bytes = short_room_name.as_bytes();
|
|
||||||
write_buf.push(roomname_bytes.len() as u8);
|
|
||||||
write_buf.extend_from_slice(&roomname_bytes);
|
|
||||||
|
|
||||||
let clients = &room.borrow().clients;
|
|
||||||
write_buf.extend_from_slice(&(clients.len() as u32).to_be_bytes());
|
|
||||||
for (_k, c) in clients.iter() {
|
|
||||||
write_buf.extend_from_slice(&(_k).to_be_bytes());
|
|
||||||
|
|
||||||
if *_k != client_ref.id {
|
|
||||||
let c_ref = c.borrow();
|
|
||||||
let username_bytes = c_ref.username.as_bytes();
|
|
||||||
write_buf.push(username_bytes.len() as u8);
|
|
||||||
write_buf.extend_from_slice(&username_bytes);
|
|
||||||
} else {
|
|
||||||
let username_bytes = client_ref.username.as_bytes();
|
|
||||||
write_buf.push(username_bytes.len() as u8);
|
|
||||||
write_buf.extend_from_slice(&username_bytes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
client_ref.message_queue.extend_from_slice(&write_buf);
|
|
||||||
client_ref.notify.notify();
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn read_send_message(mut stream: TcpStream, client: Rc<RefCell<Client>>, rooms: Rc<RefCell<HashMap<String, Rc<RefCell<Room>>>>>, message_type: u8, duration: u64) -> Result<(), Box<dyn Error>> {
|
|
||||||
//4 byte length, array
|
|
||||||
//this is a message for everyone in the room (maybe)
|
|
||||||
let to_send = read_vec(&mut stream, duration).await?;
|
|
||||||
if message_type == FromClientTCPMessageType::SendMessageOthersUnbuffered as u8 {
|
|
||||||
send_room_message(client, &to_send, rooms.clone(), false, false);
|
|
||||||
} else if message_type == FromClientTCPMessageType::SendMessageAllUnbuffered as u8 {
|
|
||||||
send_room_message(client, &to_send, rooms.clone(), true, false);
|
|
||||||
} else if message_type == FromClientTCPMessageType::SendMessageOthersBuffered as u8 { //ordered
|
|
||||||
send_room_message(client, &to_send, rooms.clone(), false, true);
|
|
||||||
} else if message_type == FromClientTCPMessageType::SendMessageAllBuffered as u8 { //ordered
|
|
||||||
send_room_message(client, &to_send, rooms.clone(), true, true);
|
|
||||||
} else if message_type == FromClientTCPMessageType::SendMessageGroupUnbuffered as u8 {
|
|
||||||
let group = read_short_string(&mut stream, duration).await?;
|
|
||||||
send_group_message(client, &to_send, &group);
|
|
||||||
}
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn read_group_message(mut stream: TcpStream, client: Rc<RefCell<Client>>, clients: Rc<RefCell<HashMap<u32, Rc<RefCell<Client>>>>>, duration: u64) -> Result<(), Box<dyn Error>> {
|
|
||||||
let group = read_short_string(&mut stream, duration).await?;
|
|
||||||
let id_bytes = read_vec(&mut stream, duration).await?;
|
|
||||||
let num = id_bytes.len();
|
|
||||||
|
|
||||||
let mut client_ref = client.borrow_mut();
|
|
||||||
|
|
||||||
let clients_ref = clients.borrow();
|
|
||||||
let mut group_clients = vec![];
|
|
||||||
let mut i = 0;
|
|
||||||
loop {
|
|
||||||
if i >= num {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
let mut slice = [0u8; 4];
|
|
||||||
slice[0] = id_bytes[i];
|
|
||||||
slice[1] = id_bytes[i + 1];
|
|
||||||
slice[2] = id_bytes[i + 2];
|
|
||||||
slice[3] = id_bytes[i + 3]; //probably a better way to do this
|
|
||||||
let id = u32::from_be_bytes(slice);
|
|
||||||
|
|
||||||
|
|
||||||
match clients_ref.get(&id) {
|
|
||||||
Some(client) => { group_clients.push(client.clone()); }
|
|
||||||
None => () //not there, so don't add it
|
|
||||||
}
|
|
||||||
|
|
||||||
i = i + 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
//delete the group if it exists
|
|
||||||
if client_ref.groups.contains_key(&group) {
|
|
||||||
client_ref.groups.remove(&group); //ensures the client references go away
|
|
||||||
}
|
|
||||||
|
|
||||||
client_ref.groups.insert(group.clone(), group_clients);
|
|
||||||
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
fn client_leave_room(client: Rc<RefCell<Client>>, send_to_client: bool, rooms: Rc<RefCell<HashMap<String, Rc<RefCell<Room>>>>>) {
|
|
||||||
//first remove the client from the room they are in
|
|
||||||
|
|
||||||
{
|
|
||||||
let mut client_ref = client.borrow_mut();
|
|
||||||
let roomname = String::from(client_ref.room_name.clone());
|
|
||||||
|
|
||||||
if roomname == "" { //client not in room, leave
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let mut new_master_id = 0;
|
|
||||||
{
|
|
||||||
log::info!("{}: {}: Client {} in room, leaving", Local::now().format("%Y-%m-%d %H:%M:%S"), client_ref.application, client_ref.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
let mut destroy_room = false;
|
|
||||||
{
|
|
||||||
let rooms_ref = rooms.borrow_mut();
|
|
||||||
let mut room_ref = rooms_ref.get(&roomname).unwrap().borrow_mut();
|
|
||||||
|
|
||||||
for (_k, v) in room_ref.clients.iter() {
|
|
||||||
if *_k != client_ref.id {
|
|
||||||
send_client_left_message(v, client_ref.id, &roomname);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if send_to_client && client_ref.room_name != "" {
|
|
||||||
send_you_left_message(&mut *client_ref, &roomname);
|
|
||||||
}
|
|
||||||
|
|
||||||
room_ref.clients.remove(&client_ref.id); //remove the client from that list in the room
|
|
||||||
if room_ref.clients.len() == 0 {
|
|
||||||
destroy_room = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//if the room is empty, destroy it as well
|
|
||||||
let mut rooms_ref = rooms.borrow_mut();
|
|
||||||
if destroy_room {
|
|
||||||
rooms_ref.remove(&roomname);
|
|
||||||
log::info!("{}: {}: Destroyed room {}", Local::now().format("%Y-%m-%d %H:%M:%S"), client_ref.application, &roomname)
|
|
||||||
} else if client_ref.is_master { //we need to change the master!
|
|
||||||
let mut room_ref = rooms_ref.get(&roomname).unwrap().borrow_mut();
|
|
||||||
for (_k, v) in room_ref.clients.iter() {
|
|
||||||
if *_k != client_ref.id {
|
|
||||||
new_master_id = v.borrow().id;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
log::info!("{}: {}: Changing master to {}", Local::now().format("%Y-%m-%d %H:%M:%S"), client_ref.application, new_master_id);
|
|
||||||
|
|
||||||
for (_k, v) in room_ref.clients.iter() {
|
|
||||||
let mut c = v.borrow_mut();
|
|
||||||
send_client_master_message(&mut *c, new_master_id);
|
|
||||||
}
|
|
||||||
room_ref.master_client = room_ref.clients.get(&new_master_id).unwrap().clone();
|
|
||||||
room_ref.master_client.borrow_mut().is_master = true;
|
|
||||||
client_ref.is_master = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let mut client_ref = client.borrow_mut();
|
|
||||||
client_ref.room_name = String::from("");
|
|
||||||
}
|
|
||||||
|
|
||||||
fn send_you_left_message(client_ref: &mut Client, room: &str) {
|
|
||||||
let mut write_buf = vec![];
|
|
||||||
write_buf.push(ToClientTCPMessageType::YouLeft as u8);
|
|
||||||
write_buf.push(room.as_bytes().len() as u8);
|
|
||||||
write_buf.extend_from_slice(room.as_bytes());
|
|
||||||
client_ref.message_queue.extend_from_slice(&write_buf);
|
|
||||||
client_ref.notify.notify();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn send_client_left_message(to: &Rc<RefCell<Client>>, from: u32, room: &str) {
|
|
||||||
let mut write_buf = vec![];
|
|
||||||
write_buf.push(ToClientTCPMessageType::PlayerLeft as u8);
|
|
||||||
write_buf.extend_from_slice(&(from).to_be_bytes()); //send everyone that the client id left the room
|
|
||||||
write_buf.push(room.as_bytes().len() as u8);
|
|
||||||
write_buf.extend_from_slice(room.as_bytes());
|
|
||||||
let mut client_ref = to.borrow_mut();
|
|
||||||
client_ref.message_queue.extend_from_slice(&write_buf);
|
|
||||||
client_ref.notify.notify();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn send_client_join_message(to: &Rc<RefCell<Client>>, from: u32, room: &str) {
|
|
||||||
//2u8, person_id_u32, room_name_len_u8, room_name_bytes
|
|
||||||
let mut write_buf = vec![];
|
|
||||||
write_buf.push(ToClientTCPMessageType::PlayerJoined as u8);
|
|
||||||
write_buf.extend_from_slice(&(from).to_be_bytes()); //send everyone that the client id joined the room
|
|
||||||
write_buf.push(room.as_bytes().len() as u8);
|
|
||||||
write_buf.extend_from_slice(room.as_bytes());
|
|
||||||
let mut client_ref = to.borrow_mut();
|
|
||||||
client_ref.message_queue.extend_from_slice(&write_buf);
|
|
||||||
client_ref.notify.notify();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn send_you_joined_message(client_ref: &mut Client, in_room: Vec<u32>, room: &str) {
|
|
||||||
//you_joined_u8, ids_len_u32, id_list_array_u32, room_name_len_u8, room_name_bytes
|
|
||||||
let mut write_buf = vec![];
|
|
||||||
write_buf.push(ToClientTCPMessageType::YouJoined as u8);
|
|
||||||
write_buf.extend_from_slice(&(in_room.len() as u32).to_be_bytes());
|
|
||||||
for id in in_room {
|
|
||||||
write_buf.extend_from_slice(&(id).to_be_bytes());
|
|
||||||
}
|
|
||||||
write_buf.push(room.as_bytes().len() as u8);
|
|
||||||
write_buf.extend_from_slice(room.as_bytes());
|
|
||||||
client_ref.message_queue.extend_from_slice(&write_buf);
|
|
||||||
client_ref.notify.notify();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn send_client_master_message(client_ref: &mut Client, master_id: u32) {
|
|
||||||
//2u8, person_id_u32, room_name_len_u8, room_name_bytes
|
|
||||||
let mut write_buf = vec![];
|
|
||||||
write_buf.push(ToClientTCPMessageType::MasterMessage as u8);
|
|
||||||
write_buf.extend_from_slice(&(master_id).to_be_bytes()); //send everyone that the client id joined the room
|
|
||||||
client_ref.message_queue.extend_from_slice(&write_buf);
|
|
||||||
client_ref.notify.notify();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn send_room_message(sender: Rc<RefCell<Client>>, message: &Vec<u8>, rooms: Rc<RefCell<HashMap<String, Rc<RefCell<Room>>>>>, include_sender: bool, _ordered: bool) {
|
|
||||||
//this message is 3u8, sender_id_u32, message_len_u32, message_bytes
|
|
||||||
|
|
||||||
let mut write_buf = vec![];
|
|
||||||
|
|
||||||
|
|
||||||
let mut sender_ref = sender.borrow_mut();
|
|
||||||
write_buf.push(ToClientTCPMessageType::DataMessage as u8);
|
|
||||||
write_buf.extend_from_slice(&sender_ref.id.to_be_bytes());
|
|
||||||
write_buf.extend_from_slice(&(message.len() as u32).to_be_bytes());
|
|
||||||
write_buf.extend_from_slice(message);
|
|
||||||
|
|
||||||
|
|
||||||
if sender_ref.room_name == "" {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if include_sender {
|
|
||||||
sender_ref.message_queue.extend_from_slice(&write_buf);
|
|
||||||
sender_ref.notify.notify();
|
|
||||||
}
|
|
||||||
|
|
||||||
let rooms_ref = rooms.borrow();
|
|
||||||
let room_ref = rooms_ref[&sender_ref.room_name].borrow();
|
|
||||||
|
|
||||||
for (_k, v) in room_ref.clients.iter() {
|
|
||||||
if *_k != sender_ref.id {
|
|
||||||
let mut temp_mut = v.borrow_mut();
|
|
||||||
temp_mut.message_queue.extend_from_slice(&write_buf);
|
|
||||||
temp_mut.notify.notify();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn send_group_message(sender: Rc<RefCell<Client>>, message: &Vec<u8>, group: &String) {
|
|
||||||
let mut write_buf = vec![];
|
|
||||||
let mut sender_ref = sender.borrow_mut();
|
|
||||||
write_buf.push(ToClientTCPMessageType::DataMessage as u8);
|
|
||||||
write_buf.extend_from_slice(&sender_ref.id.to_be_bytes());
|
|
||||||
write_buf.extend_from_slice(&(message.len() as u32).to_be_bytes());
|
|
||||||
write_buf.extend_from_slice(message);
|
|
||||||
|
|
||||||
//get the list of client ids for this group
|
|
||||||
let mut send_to_client = false;
|
|
||||||
if sender_ref.groups.contains_key(group) {
|
|
||||||
let group = sender_ref.groups.get(group).unwrap();
|
|
||||||
for c in group {
|
|
||||||
if ptr::eq(sender.as_ref(), c.as_ref()) {
|
|
||||||
send_to_client = true;
|
|
||||||
} else {
|
|
||||||
let mut temp_mut = c.borrow_mut();
|
|
||||||
temp_mut.message_queue.extend_from_slice(&write_buf);
|
|
||||||
temp_mut.notify.notify();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if send_to_client {
|
|
||||||
sender_ref.message_queue.extend_from_slice(&write_buf);
|
|
||||||
sender_ref.notify.notify();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn read_u8(stream: &mut TcpStream, duration: u64) -> Result<u8, Box<dyn Error>> {
|
|
||||||
let mut buf = [0; 1];
|
|
||||||
read_timeout(stream, &mut buf, duration).await?;
|
|
||||||
return Ok(buf[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn read_u32(stream: &mut TcpStream, duration: u64) -> Result<u32, Box<dyn Error>> {
|
|
||||||
let mut buf: [u8; 4] = [0; 4];
|
|
||||||
read_timeout(stream, &mut buf, duration).await?;
|
|
||||||
let size = u32::from_be_bytes(buf);
|
|
||||||
return Ok(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn _read_string(stream: &mut TcpStream, duration: u64) -> Result<String, Box<dyn Error>> {
|
|
||||||
let size = read_u32(stream, duration).await?;
|
|
||||||
let mut string_bytes = vec![0; size as usize];
|
|
||||||
read_timeout(stream, &mut string_bytes, duration).await?;
|
|
||||||
return Ok(String::from_utf8(string_bytes)?);
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn read_short_string(stream: &mut TcpStream, duration: u64) -> Result<String, Box<dyn Error>> {
|
|
||||||
let size = read_u8(stream, duration).await?;
|
|
||||||
let mut string_bytes = vec![0; size as usize];
|
|
||||||
read_timeout(stream, &mut string_bytes, duration).await?;
|
|
||||||
return Ok(String::from_utf8(string_bytes)?);
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn read_vec(stream: &mut TcpStream, duration: u64) -> Result<Vec<u8>, Box<dyn Error>> {
|
|
||||||
let message_size = read_u32(stream, duration).await?;
|
|
||||||
let mut message = vec![0u8; message_size as usize];
|
|
||||||
read_timeout(stream, &mut message, duration).await?;
|
|
||||||
return Ok(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
Loading…
Reference in New Issue