diff --git a/server/Cargo.lock b/server/Cargo.lock index d799894..027f4a3 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -2,6 +2,65 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "anstream" +version = "0.6.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" + +[[package]] +name = "anstyle-parse" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys 0.61.2", +] + [[package]] name = "anyhow" version = "1.0.100" @@ -47,6 +106,12 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +[[package]] +name = "colorchoice" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" + [[package]] name = "cpufeatures" version = "0.2.17" @@ -102,6 +167,29 @@ dependencies = [ "serde_json", ] +[[package]] +name = "env_filter" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_logger" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "jiff", + "log", +] + [[package]] name = "fnv" version = "1.0.7" @@ -313,12 +401,42 @@ dependencies = [ "icu_properties", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" + [[package]] name = "itoa" version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +[[package]] +name = "jiff" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49cce2b81f2098e7e3efc35bc2e0a6b7abec9d34128283d7a26fa8f32a6dbb35" +dependencies = [ + "jiff-static", + "log", + "portable-atomic", + "portable-atomic-util", + "serde_core", +] + +[[package]] +name = "jiff-static" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "980af8b43c3ad5d8d349ace167ec8170839f753a42d233ba19e08afe1850fa69" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "js-sys" version = "0.3.82" @@ -379,6 +497,12 @@ version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +[[package]] +name = "once_cell_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" + [[package]] name = "parking_lot" version = "0.12.5" @@ -420,6 +544,21 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "portable-atomic" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" + +[[package]] +name = "portable-atomic-util" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" +dependencies = [ + "portable-atomic", +] + [[package]] name = "potential_utf" version = "0.1.4" @@ -530,6 +669,35 @@ dependencies = [ "bitflags", ] +[[package]] +name = "regex" +version = "1.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" + [[package]] name = "rustversion" version = "1.0.22" @@ -597,6 +765,9 @@ version = "0.1.0" dependencies = [ "anyhow", "engine", + "env_logger", + "futures-util", + "log", "futures-util", "rand 0.9.2", "serde", @@ -803,6 +974,12 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + [[package]] name = "uuid" version = "1.18.1" diff --git a/server/Cargo.toml b/server/Cargo.toml index ab5f7bf..50abe59 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -15,6 +15,8 @@ uuid = {version = "1.18.1", features = ["v4", "serde"] } anyhow = "1.0.100" rand = "0.9.2" engine = {path = "../engine/"} +log = {version = "0.4.28"} +env_logger = "0.11.8" [[bin]] diff --git a/server/src/connection.rs b/server/src/connection.rs index 2afd928..828f0cf 100644 --- a/server/src/connection.rs +++ b/server/src/connection.rs @@ -4,6 +4,7 @@ use engine::chessmove::ChessMove; use engine::gameend::GameEnd::{self, *}; use engine::{get_available_moves, is_game_over}; use futures_util::{SinkExt, StreamExt}; +use log::{error, info, warn}; use serde::{Deserialize, Serialize}; use std::char::from_u32_unchecked; use std::collections::{HashMap, VecDeque}; @@ -25,14 +26,17 @@ pub async fn clean_up_match(matches: &MatchMap, match_id: &Uuid) { // Helper functions to create new instances pub fn new_connection_map() -> ConnectionMap { + warn!("Created new connection map"); Arc::new(Mutex::new(HashMap::new())) } pub fn new_match_map() -> MatchMap { + warn!("Created new match map"); Arc::new(Mutex::new(HashMap::new())) } pub fn new_waiting_queue() -> WaitingQueue { + warn!("Created new waiting queue"); Arc::new(Mutex::new(VecDeque::new())) } @@ -107,11 +111,11 @@ pub async fn send_message_to_player_connection( ) -> Result<(), tokio_tungstenite::tungstenite::Error> { match connection { Some(connection) => { - println!("sending message to: {}", connection.id); + info!("sending message to: {}", connection.id); connection.tx.send(Message::Text(message.to_string())).await } None => { - eprintln!("No connection provided"); + error!("No connection provided"); Err(tokio_tungstenite::tungstenite::Error::ConnectionClosed) } } @@ -123,7 +127,7 @@ pub async fn broadcast_to_all(connections: &ConnectionMap, message: &str) { for (id, connection) in connections_lock.iter_mut() { if let Err(e) = connection.tx.send(Message::Text(message.to_string())).await { - eprintln!("Failed to send to {}: {}", id, e); + error!("Failed to send to {}: {}", id, e); dead_connections.push(*id); } } @@ -140,6 +144,7 @@ pub async fn broadcast_to_match( match_id: Uuid, message: &str, ) -> Result<(), Box> { + info!("Broadcasting data to match: {}", &match_id); let matches_lock = matches.lock().await; if let Some(game_match) = matches_lock.get(&match_id) { send_message_to_player_connection( @@ -167,6 +172,7 @@ pub async fn handle_connection( let ws_stream = accept_async(stream).await?; let (write, mut read) = ws_stream.split(); + warn!("Accepted new connection"); let player_id = Uuid::new_v4(); @@ -184,13 +190,13 @@ pub async fn handle_connection( ); } - println!("New connection: {}", player_id); + info!("id: {}", &player_id); // Message processing loop while let Some(Ok(message)) = read.next().await { if message.is_text() { let text = message.to_text()?; - println!("Received from {}: {}", player_id, text); + info!("Received from {}: {}", player_id, text); let client_data: ClientEvent = serde_json::from_str(text) .expect("Failed to convert data into json at handle_connection"); @@ -200,7 +206,8 @@ pub async fn handle_connection( { let mut conn_map = connections.lock().await; let player = conn_map.get_mut(&player_id).unwrap(); - player.username = Some(username); + player.username = Some(username.clone()); + info!("player: {}, set username: {}", &player_id, username); } //respone to client @@ -216,8 +223,8 @@ pub async fn handle_connection( FindMatch => { let mut wait_queue = waiting_queue.lock().await; wait_queue.push_back(player_id.clone()); - println!("Appended {} to the waiting queue", player_id); - println!("queue {:?}", wait_queue); + info!("Appended {} to the waiting queue", player_id); + info!("queue {:?}", wait_queue); } Move { step } => { let match_id = connections @@ -229,6 +236,7 @@ pub async fn handle_connection( .unwrap(); { + info!("updating board state in match: {}", &match_id); let mut matches = matches.lock().await; matches.get_mut(&match_id).unwrap().board_state = engine::get_board_after_move( @@ -261,6 +269,7 @@ pub async fn handle_connection( match is_game_end { Some(res) => { + warn!("A player won the match: {}", &match_id); let message = ServerMessage2::GameEnd { winner: res }; let _ = broadcast_to_match( &connections, @@ -272,21 +281,23 @@ pub async fn handle_connection( clean_up_match(&matches, &match_id); } None => { - println!("No winner match continues.") + info!("No winner match continues. Id: {}", &match_id); } } } } RequestLegalMoves { fen } => { + info!("Requesting legal moves player: {}", &player_id); let moves = get_available_moves(&fen); let _ = send_message_to_player_connection( connections.lock().await.get_mut(&player_id), &serde_json::to_string(&moves).unwrap(), ) .await; - println!("Sent moves to player: {}", player_id); + info!("Sent moves to player: {}", player_id); } Resign => { + warn!("Resigned!"); let (fuck, fuck_id): (ServerMessage2, &Uuid) = { let matches = matches.lock().await; @@ -347,7 +358,7 @@ pub async fn handle_connection( clean_up_match(&matches, fuck_id); } _ => { - println!("Not known client event"); + warn!("Not known client event"); } } } @@ -355,7 +366,7 @@ pub async fn handle_connection( // Cleanup on disconnect cleanup_player(player_id, &connections, &matches, &waiting_queue).await; - println!("Connection {} closed", player_id); + warn!("Connection {} closed", player_id); Ok(()) } @@ -372,7 +383,7 @@ async fn cleanup_player( // Remove from connections connections.lock().await.remove(&player_id); - println!("Cleaned up player {}", player_id); + warn!("Cleaned up player {}", player_id); } #[cfg(test)] diff --git a/server/src/main.rs b/server/src/main.rs index c7f09d6..e3876a5 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -1,12 +1,18 @@ mod connection; mod matchmaking; +use env_logger::{Env, Logger}; +use log::{error, info, warn}; +use std::env; use tokio::net::TcpListener; #[tokio::main] async fn main() -> anyhow::Result<()> { + let env = Env::default().filter_or("MY_LOG_LEVEL", "INFO"); + env_logger::init_from_env(env); + let address = "0.0.0.0:9001"; let listener = TcpListener::bind(address).await?; - println!("Server running on ws://{}", address); + info!("Server running on ws://{}", address); // Shared state initialization using the new helper functions let connections = connection::new_connection_map(); @@ -33,7 +39,7 @@ async fn main() -> anyhow::Result<()> { if let Err(e) = connection::handle_connection(stream, connections, matches, waiting_queue).await { - eprintln!("Connection error: {}", e); + error!("Connection error: {}", e); } }); } diff --git a/server/src/matchmaking.rs b/server/src/matchmaking.rs index 0bf5cfa..b1514c9 100644 --- a/server/src/matchmaking.rs +++ b/server/src/matchmaking.rs @@ -1,5 +1,6 @@ use crate::connection::ServerMessage2; -use crate::connection::{ConnectionMap, GameMatch, MatchMap, WaitingQueue}; +use crate::connection::{ConnectionMap, GameMatch, MatchMap, WaitingQueue, broadcast_to_match}; +use log::{error, info, warn}; use rand::random; use uuid::Uuid; @@ -30,16 +31,21 @@ impl MatchmakingSystem { } async fn try_create_match(&self) { + info!("Checking for new matches!"); let mut queue = self.waiting_queue.lock().await; while queue.len() >= 2 { let player1 = queue.pop_front().unwrap(); let player2 = queue.pop_front().unwrap(); + info!("Creating new match. Players: {}, {}", &player1, &player2); + let match_id = Uuid::new_v4(); let (white_player, black_player) = if random::() { + info!("player1 is white, player2 is black"); (player1, player2) } else { + info!("player2 is white, player1 is black"); (player2, player1) }; @@ -51,6 +57,8 @@ impl MatchmakingSystem { move_history: Vec::new(), }; + info!("Match id: {}", &game_match.id); + // Store the match self.matches.lock().await.insert(match_id, game_match); @@ -59,14 +67,18 @@ impl MatchmakingSystem { let mut conn_map = self.connections.lock().await; if let Some(player) = conn_map.get_mut(&white_player) { player.current_match = Some(match_id); + } else { + error!("Could not store match id for white player"); } if let Some(player) = conn_map.get_mut(&black_player) { player.current_match = Some(match_id); + } else { + error!("Could not store match id for black player"); } } // Notify players - println!( + info!( "Notifying player for a match: {:?} | {:?}", white_player, black_player ); @@ -116,7 +128,7 @@ impl MatchmakingSystem { .await; } - println!("Match created: {} (white) vs {} (black)", white, black); + info!("Match created: {} (white) vs {} (black)", white, black); } }