From 434bfab1340ecf679cd395ae27ff72b93442c5de Mon Sep 17 00:00:00 2001 From: ThePerkinrex Date: Tue, 13 Jul 2021 22:41:04 +0200 Subject: [PATCH] Cleanup & add better error handling --- server/src/server.rs | 171 +++++++++++++++++++++------- server/src/server/socket_manager.rs | 5 +- 2 files changed, 130 insertions(+), 46 deletions(-) diff --git a/server/src/server.rs b/server/src/server.rs index 9b8800f..854b71f 100644 --- a/server/src/server.rs +++ b/server/src/server.rs @@ -1,19 +1,28 @@ // use tonic::transport::Server; use anyhow::Result; -use log::info; +use log::warn; use tokio::{ - io::{AsyncReadExt, AsyncWriteExt, BufReader, BufWriter}, - net::{tcp::OwnedWriteHalf, TcpListener}, + io::{AsyncReadExt, BufReader}, + net::TcpListener, sync::RwLock, }; use uuid::Uuid; -use std::{collections::HashMap, net::SocketAddr, sync::Arc}; +use std::{collections::HashMap, io::ErrorKind, net::SocketAddr, sync::Arc}; -use crate::{db, games::RunningGame, server::{connection::{ - connect, create_lobby, disconnect, get_public_lobbies, join_lobby_with_code, name, - }, game::{on_click, get_card_image}, lobby::{leave, ready, users, vote}}, server_properties::ServerProperties}; +use crate::{ + db, + games::RunningGame, + server::{ + connection::{ + connect, create_lobby, disconnect, get_public_lobbies, join_lobby_with_code, name, + }, + game::{get_card_image, on_click}, + lobby::{leave, ready, users, vote}, + }, + server_properties::ServerProperties, +}; use prost::Message; @@ -23,8 +32,8 @@ mod connection; mod game; mod lobby; mod protos; -mod votes; mod socket_manager; +mod votes; // use connection::{ConnectionServer, ConnectionService}; // use game::{GameServer, GameService}; @@ -106,7 +115,7 @@ pub async fn serve( let (reader, writer) = stream.into_split(); let mut writer = Some(writer); let mut reader = BufReader::new(reader); - + let mut service_data = ServiceData { user_id: UserId::new_empty(), properties: properties.clone(), @@ -119,19 +128,57 @@ pub async fn serve( let socket_manager = socket_manager.clone(); tokio::spawn(async move { loop { - let length = reader - .read_u32_le() - .await - .expect("Unexpected inability to read the length of a packet (U32 LE)"); + let length = match reader.read_u32_le().await { + Err(e) => match e.kind() { + ErrorKind::UnexpectedEof => { + if let Some(user) = service_data.user_id.0 { + warn!( + "Unexpected EOF for {} from {}, disconnecting", + user, service_data.addr + ); + } else { + warn!("Unexpected EOF from {}, disconnecting", service_data.addr); + } + break; + } + _ => Err(e), + }, + x => x, + } + .expect("Unexpected inability to read the length of a packet (U32 LE)"); let mut data = vec![0; length as usize]; - reader - .read_exact(&mut data) - .await - .expect("Error reading packet"); - let packet = protos::protocol::ClientServerPacket::decode(data.as_slice()) - .expect("Error decoding the data") - .data - .expect("Unexpected data in packet recieved"); + match reader.read_exact(&mut data).await { + Err(e) => match e.kind() { + ErrorKind::UnexpectedEof => { + if let Some(user) = service_data.user_id.0 { + warn!( + "Unexpected EOF for {} from {}, disconnecting", + user, service_data.addr + ); + } else { + warn!("Unexpected EOF from {}, disconnecting", service_data.addr); + } + break; + } + _ => Err(e), + }, + x => x, + } + .expect("Error reading packet"); + let packet = match protos::protocol::ClientServerPacket::decode(data.as_slice()) { + Err(e) => { + warn!("Error decoding the packet, skipping ({})", e); + continue; + } + Ok(d) => d, + }; + let packet = match packet.data { + Some(packet) => packet, + None => { + warn!("Unexpected data in packet ({:?}), skipping", packet); + continue; + } + }; use protos::protocol::client_server_packet::Data; match packet { @@ -139,36 +186,72 @@ pub async fn serve( Data::QueryName(()) => name(&mut service_data, &socket_manager) .await .expect("Error handling name query"), - Data::Connect(name) => connect(&mut service_data, writer.take().ok_or(anyhow::anyhow!("Connect shouldn't be called more than once")).unwrap(), &socket_manager, name) - .await - .expect("Error handling connect"), - Data::Disconnect(()) => disconnect(&mut service_data) - .await - .expect("Error handling disconnect"), + Data::Connect(name) => connect( + &mut service_data, + writer + .take() + .ok_or(anyhow::anyhow!( + "Connect shouldn't be called more than once" + )) + .unwrap(), + &socket_manager, + name, + ) + .await + .expect("Error handling connect"), + Data::Disconnect(()) => { + break; + } Data::JoinLobby(code) => join_lobby_with_code(&mut service_data, code) .await .expect("Error handling join with code"), - Data::CreateLobby(config) => create_lobby(&mut service_data, &socket_manager, config) - .await - .expect("Error handling create lobby"), + Data::CreateLobby(config) => { + create_lobby(&mut service_data, &socket_manager, config) + .await + .expect("Error handling create lobby") + } Data::QueryGames(()) => connection::games(&mut service_data, &socket_manager) .await .expect("Error handling games query"), - Data::QueryPublicLobbies(()) => get_public_lobbies(&mut service_data, &socket_manager) - .await - .expect("Error handling public lobbies query"), + Data::QueryPublicLobbies(()) => { + get_public_lobbies(&mut service_data, &socket_manager) + .await + .expect("Error handling public lobbies query") + } // LOBBY - Data::QueryUsers(()) => users(&mut service_data, &socket_manager).await.expect("Error handling users query"), - Data::Vote(v) => vote(&mut service_data, &socket_manager, v).await.expect("Error handling vote"), - Data::Ready(()) => ready(&mut service_data, &socket_manager).await.expect("Error handling ready"), - Data::Leave(()) => leave(&mut service_data, &socket_manager).await.expect("Error handling leave"), + Data::QueryUsers(()) => users(&mut service_data, &socket_manager) + .await + .expect("Error handling users query"), + Data::Vote(v) => vote(&mut service_data, &socket_manager, v) + .await + .expect("Error handling vote"), + Data::Ready(()) => ready(&mut service_data, &socket_manager) + .await + .expect("Error handling ready"), + Data::Leave(()) => leave(&mut service_data, &socket_manager) + .await + .expect("Error handling leave"), // GAME - Data::QueryCardImage(card_kind) => get_card_image(&mut service_data, &socket_manager, card_kind).await.expect("Error handling card image query"), - Data::CallOnClick(card_id) => on_click(&mut service_data, &socket_manager, card_id).await.expect("Error handling on_click call") + Data::QueryCardImage(card_kind) => { + get_card_image(&mut service_data, &socket_manager, card_kind) + .await + .expect("Error handling card image query") + } + Data::CallOnClick(card_id) => { + on_click(&mut service_data, &socket_manager, card_id) + .await + .expect("Error handling on_click call") + } } } + if let Some(user) = service_data.user_id.0 { + disconnect(&mut service_data) + .await + .expect("Error handling disconnect"); + socket_manager.disconnect(&user).await; + } }); } } @@ -202,9 +285,9 @@ impl UserId { Self(None) } - pub fn new_filled(uuid: Uuid) -> Self { - Self(Some(uuid)) - } + // pub fn new_filled(uuid: Uuid) -> Self { + // Self(Some(uuid)) + // } pub fn set(&mut self, uuid: Uuid) { self.0 = Some(uuid); @@ -215,6 +298,8 @@ impl UserId { } pub fn get_ref(&self) -> Result<&Uuid> { - self.0.as_ref().ok_or(anyhow::anyhow!("User should have connected")) + self.0 + .as_ref() + .ok_or(anyhow::anyhow!("User should have connected")) } } diff --git a/server/src/server/socket_manager.rs b/server/src/server/socket_manager.rs index 0429bb0..6f7491e 100644 --- a/server/src/server/socket_manager.rs +++ b/server/src/server/socket_manager.rs @@ -1,10 +1,9 @@ use std::collections::HashMap; use tokio::{ - io::{AsyncReadExt, AsyncWriteExt, BufReader, BufWriter}, - net::{tcp::OwnedWriteHalf, TcpListener}, + io::{AsyncWriteExt, BufWriter}, + net::{tcp::OwnedWriteHalf}, sync::RwLock, }; -use log::info; use uuid::Uuid; use anyhow::Result; use prost::Message;