migrate to tokio

This commit is contained in:
Dane Johnson 2022-10-04 16:59:12 -05:00
parent b6d54d086e
commit 13fb9a9fdd
6 changed files with 390 additions and 255 deletions

405
Cargo.lock generated
View File

@ -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,25 @@ 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",
"rand", "rand",
"regex", "regex",
"sha2", "sha2",
"tungstenite", "tokio",
"tokio-tungstenite",
] ]
[[package]] [[package]]
@ -204,33 +258,28 @@ 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"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754"
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.133" 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 +296,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 +347,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 +439,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 +466,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 +511,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 +546,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 +601,6 @@ dependencies = [
"http", "http",
"httparse", "httparse",
"log", "log",
"native-tls",
"rand", "rand",
"sha-1", "sha-1",
"thiserror", "thiserror",
@ -595,12 +652,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"

View File

@ -6,7 +6,9 @@ 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"

52
doc/flow.txt Normal file
View 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

View File

@ -1,53 +1,72 @@
use std::net::TcpListener; use std::{
use std::thread; sync::{Arc, Mutex},
use std::sync::{Arc, Mutex}; io::Error as IoError,
use std::collections::HashMap; collections::HashMap,
};
use tokio::net::{TcpListener};
mod message; mod message;
use message::Message; use message::{Message, MessageWebSocket};
mod code_generator; mod code_generator;
use code_generator::CodeGenerator; use code_generator::CodeGenerator;
mod websocket;
use websocket::WebsocketWrapper;
fn main() { #[tokio::main]
let code_generator = Arc::new(Mutex::new(CodeGenerator::default())); async fn main() -> Result<(), IoError> {
let server = TcpListener::bind("127.0.0.1:8080").unwrap(); let global_state = Arc::new(GlobalState::default());
let rooms = Arc::new(Mutex::new(HashMap::new()));
for stream in server.incoming() { let socket = TcpListener::bind("127.0.0.1:8080").await;
let code_generator = Arc::clone(&code_generator); let listener = socket.expect("Could not bind to localhost:8080");
let rooms = Arc::clone(&rooms); println!("Server running");
thread::spawn (move || {
let ws = tungstenite::accept(stream.unwrap()).unwrap();
let mut ws = WebsocketWrapper::new(ws);
ws.send(msg!("HOSTJOIN"));
let msg = ws.recv();
match msg {
None => (),
Some(msg) => match msg.command.as_str() {
"HOST" => {
let code = code_generator.lock().unwrap().generate();
let mut room = Room::default();
let player = Player {};
room.players.push(player);
rooms.lock().unwrap().insert(code.clone(), room);
ws.send(msg!("CODE", code));
}
_ => unimplemented!(),
}
}
while let Ok((stream, addr)) = listener.accept().await {
let global_state = Arc::clone(&global_state);
let mut local_state = LocalState::default();
tokio::spawn(async move {
// Upgrade to a WS connection
let mut ws = MessageWebSocket(tokio_tungstenite::accept_async(stream)
.await
.expect("Could not establish connection"));
println!("Connected to {}", addr);
while let Ok(msg) = ws.next().await {
dispatch(msg, &global_state, &mut local_state, &mut ws).await;
}
}); });
} }
Ok(())
}
async fn dispatch(
msg: Message,
global_state: &GlobalState,
local_state: &mut LocalState,
ws: &mut MessageWebSocket
) {
match msg.command.as_str() {
"HOST" => {
let room_code = global_state.code_generator.lock().unwrap().generate();
let game_controller = GameController::default();
global_state.rooms.lock().unwrap().insert(room_code, game_controller);
}
"JOIN" => {
let room_code = &msg.args[0];
let room = global_state.rooms.lock().unwrap().get(room_code);
}
_ => unimplemented!(),
}
} }
#[derive(Default)] #[derive(Default)]
struct Room { struct GlobalState {
players: Vec<Player>, code_generator: Arc<Mutex<CodeGenerator>>,
rooms: Arc<Mutex<HashMap<String, GameController>>>,
} }
struct Player { #[derive(Default)]
struct GameController {} // TODO
#[derive(Default)]
struct LocalState {
} }

View File

@ -1,3 +1,12 @@
use std::convert::{From, TryFrom};
use tokio::net::TcpStream;
use tokio_tungstenite::{
WebSocketStream,
tungstenite::Message as WsMessage,
};
use futures::{StreamExt, SinkExt};
#[derive(PartialEq, Debug)] #[derive(PartialEq, Debug)]
pub struct Message { pub struct Message {
pub command: String, pub command: String,
@ -10,6 +19,8 @@ pub type Result<T> = std::result::Result<T, Error>;
#[derive(PartialEq, Debug)] #[derive(PartialEq, Debug)]
pub enum Error { pub enum Error {
BadParse, BadParse,
NonText,
Unknown,
} }
impl Message { impl Message {
@ -33,12 +44,49 @@ impl Message {
} }
} }
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_export]
macro_rules! msg { macro_rules! msg {
( $command:expr) => { ( $command:expr) => {
{ {
let command = $command.to_string(); let command = $command.to_string();
let args = Vec::new(); let args = vec![];
Message { command, args } Message { command, args }
} }
}; };
@ -62,7 +110,6 @@ impl std::fmt::Display for Message {
} }
} }
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;

View File

@ -1,36 +0,0 @@
use std::net::TcpStream;
use tungstenite::protocol::{ WebSocket, Message as WsMessage };
use crate::message::Message;
pub struct WebsocketWrapper {
websocket: WebSocket<TcpStream>,
}
impl WebsocketWrapper {
pub fn new(websocket: WebSocket<TcpStream>) -> Self {
WebsocketWrapper { websocket }
}
pub fn send(&mut self, msg: Message) {
self.websocket.write_message(WsMessage::Text(msg.to_string())).unwrap();
}
pub fn recv(&mut self) -> Option<Message> {
match self.websocket.read_message() {
Err(_) | Ok(WsMessage::Close(_)) => None,
Ok(WsMessage::Text(text)) => match Message::parse(text) {
Ok(msg) => Some(msg),
Err(_) => {
self.websocket.write_message(WsMessage::Text("ERROR: bad_format".to_string())).unwrap();
self.recv()
}
}
_ => {
self.websocket.write_message(WsMessage::Text("ERROR: bad_command".to_string())).unwrap();
self.recv()
}
}
}
}