diff --git a/Cargo.lock b/Cargo.lock index 7730e9b..9f9dc64 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,15 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "aho-corasick" +version = "0.7.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e" +dependencies = [ + "memchr", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -162,6 +171,8 @@ dependencies = [ name = "hexland-server" version = "0.1.0" dependencies = [ + "rand", + "regex", "sha2", "tungstenite", ] @@ -229,6 +240,12 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + [[package]] name = "native-tls" version = "0.2.10" @@ -373,6 +390,23 @@ dependencies = [ "bitflags", ] +[[package]] +name = "regex" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" + [[package]] name = "remove_dir_all" version = "0.5.3" diff --git a/Cargo.toml b/Cargo.toml index 2a437ba..af955a6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,4 +7,6 @@ edition = "2021" [dependencies] tungstenite = { version = "0.17.3", features = ["native-tls"] } -sha2 = "0.10.6" \ No newline at end of file +sha2 = "0.10.6" +rand = "0.8.5" +regex = "1.6.0" \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index aa94e4f..4815ded 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,19 +1,24 @@ use std::net::TcpListener; use std::thread; use std::sync::{Arc, Mutex}; +use std::collections::HashMap; + +use rand::RngCore; use tungstenite::protocol::Message; use sha2::{Sha256, Digest}; fn main() { - let code_generator = Arc::new(Mutex::new(CodeGenerator { - counter: 0, - salt: [0; 32], // TODO have this be randomized on startup - })); + let code_generator = Arc::new(Mutex::new(CodeGenerator::default())); let server = TcpListener::bind("127.0.0.1:8080").unwrap(); + + let rooms = Arc::new(Mutex::new(HashMap::new())); + for stream in server.incoming() { - thread::spawn ( { let code_generator = Arc::clone(&code_generator); move || { + let code_generator = Arc::clone(&code_generator); + let rooms = Arc::clone(&rooms); + thread::spawn (move || { let mut ws = tungstenite::accept(stream.unwrap()).unwrap(); println!("New client!"); ws.write_message(Message::Text("HOSTJOIN:".to_string())).unwrap(); @@ -22,21 +27,34 @@ fn main() { println!("{:?}", message); match message { Err(_) => break, + Ok(Message::Close(_)) => break, Ok(Message::Text(msg)) => - match msg.as_str().trim() { - "HOST:" => { - ws.write_message(Message::Text(code_generator.lock().unwrap().generate())).unwrap(); + match parse(msg.as_str().trim()) { + Some(("HOST:", _)) => { + let code = code_generator.lock().unwrap().generate(); + let mut room = Room::default(); + let player = Player { name: "Guest".to_string() }; + room.players.push(player); + rooms.lock().unwrap().insert(code.clone(), room); + ws.write_message(Message::Text(code)).unwrap(); }, + Some(("JOIN:", args)) => { + let code = args[0]; + let room = rooms.lock().unwrap().get(&code.to_string()); + match room { + Some(mut room) => { + room. + } _ => unimplemented!(), }, _ => unimplemented!(), } } - }}); + }); } } - +#[derive(Default)] struct Room { players: Vec, } @@ -62,3 +80,32 @@ impl CodeGenerator { format!("{:x}", hasher.finalize())[..6].to_string() } } + +impl Default for CodeGenerator { + fn default() -> Self { + let mut salt = [0; 32]; + rand::thread_rng().fill_bytes(&mut salt); + + CodeGenerator { + counter: 0, + salt, + } + } +} + +fn parse(s: &str) -> Option<(&str, Vec<&str>)> { + let re = regex::Regex::new(r"(^[A-Z_]):\w*(.*)").unwrap(); + match re.captures(s) { + Some(captures) => { + if captures.len() < 3 { + None + } else { + Some(( + captures.get(1).unwrap().as_str(), + captures.get(2).unwrap().as_str().split(',').collect(), + )) + } + } + None => None, + } +}