use std::net::TcpListener; use std::thread; use std::sync::{Arc, Mutex}; use std::collections::HashMap; mod message; use message::Message; use rand::RngCore; use tungstenite::protocol::Message as WsMessage; use sha2::{Sha256, Digest}; fn main() { 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() { let code_generator = Arc::clone(&code_generator); let rooms = Arc::clone(&rooms); thread::spawn (move || { let mut ws = tungstenite::accept(stream.unwrap()).unwrap(); println!("New client!"); ws.write_message(WsMessage::Text("HOSTJOIN:".to_string())).unwrap(); loop { let message = ws.read_message(); println!("{:?}", message); match message { Err(_) => break, Ok(WsMessage::Close(_)) => break, Ok(WsMessage::Text(msg)) => { let msg = Message::parse(msg.as_str().trim()); match msg { Ok(msg) => match msg.command { "HOST" => { let code = code_generator.lock().unwrap().generate(); let mut room = Room::default(); let player = Player { name: "Guest".to_string() }; room.players.push(player); rooms.lock().unwrap().insert(code.clone(), room); ws.write_message(WsMessage::Text(code)).unwrap(); } _ => todo!(), } Err(_) => todo!(), } } _ => unimplemented!(), } } }); } } #[derive(Default)] struct Room { players: Vec, } struct Player { name: String, } struct CodeGenerator { counter: u64, salt: [u8; 32], } impl CodeGenerator { fn generate(&mut self) -> String { let count = self.counter; self.counter += 1; let mut hasher = Sha256::new(); hasher.update(self.salt); hasher.update(count.to_be_bytes()); format!("{:x}", hasher.finalize())[..6].to_string() } } impl Default for CodeGenerator { fn default() -> Self { let mut salt = [0; 32]; rand::thread_rng().fill_bytes(&mut salt); CodeGenerator { counter: 0, salt, } } }