From 1add8b500afe1e55c7de53ce112bd8aceb29519a Mon Sep 17 00:00:00 2001 From: jake Date: Thu, 23 Jan 2020 23:03:28 -0800 Subject: [PATCH] improve network error handling --- src/common/mainloop.rs | 90 +++++++++++++++++++++++++++++++----------- src/common/mod.rs | 1 - src/common/network.rs | 33 ---------------- src/patch/patch.rs | 10 ++--- 4 files changed, 71 insertions(+), 63 deletions(-) delete mode 100644 src/common/network.rs diff --git a/src/common/mainloop.rs b/src/common/mainloop.rs index 8f235b4..b0d3783 100644 --- a/src/common/mainloop.rs +++ b/src/common/mainloop.rs @@ -5,13 +5,38 @@ use async_std::io::prelude::{ReadExt, WriteExt}; use async_std::prelude::{StreamExt}; use std::collections::HashMap; -use libpso::crypto::{PSOCipher, NullCipher}; +use libpso::crypto::{PSOCipher, NullCipher, CipherError}; +use libpso::PacketParseError; use crate::common::serverstate::ClientId; use crate::common::serverstate::{RecvServerPacket, SendServerPacket, ServerState, OnConnect}; -enum PacketReceiverError { - ClientDisconnect, +#[derive(Debug)] +pub enum NetworkError { + CouldNotSend, + CipherError(CipherError), + PacketParseError(PacketParseError), + IOError(std::io::Error), + DataNotReady, + ClientDisconnected, +} + +impl From for NetworkError { + fn from(err: CipherError) -> NetworkError { + NetworkError::CipherError(err) + } +} + +impl From for NetworkError { + fn from(err: std::io::Error) -> NetworkError { + NetworkError::IOError(err) + } +} + +impl From for NetworkError { + fn from(err: PacketParseError) -> NetworkError { + NetworkError::PacketParseError(err) + } } struct PacketReceiver { @@ -31,13 +56,13 @@ impl PacketReceiver { } } - async fn fill_recv_buffer(&mut self) -> Result<(), PacketReceiverError>{ + async fn fill_recv_buffer(&mut self) -> Result<(), NetworkError> { let mut data = [0u8; 0x8000]; let mut socket = &*self.socket; - let len = socket.read(&mut data).await.unwrap(); + let len = socket.read(&mut data).await?; if len == 0 { - return Err(PacketReceiverError::ClientDisconnect); + return Err(NetworkError::ClientDisconnected); } self.recv_buffer.extend_from_slice(&mut data[..len]); @@ -46,14 +71,14 @@ impl PacketReceiver { let mut cipher = self.cipher.lock().await; let block_chunk_len = self.recv_buffer.len() / cipher.block_size() * cipher.block_size(); let buf = self.recv_buffer.drain(..block_chunk_len).collect(); - cipher.decrypt(&buf).unwrap() + cipher.decrypt(&buf)? }; self.incoming_data.append(&mut dec_buf); Ok(()) } - async fn recv_pkts(&mut self) -> Result, PacketReceiverError> { + async fn recv_pkts(&mut self) -> Result, NetworkError> { self.fill_recv_buffer().await?; let mut result = Vec::new(); @@ -89,12 +114,15 @@ impl PacketReceiver { } } -async fn send_pkt(socket: Arc, cipher: Arc>>, pkt: S) { +async fn send_pkt(socket: Arc, + cipher: Arc>>, pkt: S) + -> Result<(), NetworkError> +{ let buf = pkt.as_bytes(); - let cbuf = cipher.lock().await.encrypt(&buf).unwrap(); + let cbuf = cipher.lock().await.encrypt(&buf)?; let mut ssock = &*socket; - ssock.write_all(&cbuf).await; - + ssock.write_all(&cbuf).await?; + Ok(()) } @@ -118,7 +146,7 @@ async fn server_state_loop(mut state: STATE, E: std::fmt::Debug + Send, { async_std::task::spawn(async move { - let mut clients = HashMap::new(); + let mut clients = HashMap::new(); loop { let action = server_state_receiver.recv().await.unwrap(); @@ -138,22 +166,31 @@ async fn server_state_loop(mut state: STATE, } }, ClientAction::Packet(client_id, pkt) => { - let k = state.handle(client_id, &pkt); - let pkts = k.unwrap().collect::>(); - for (client_id, pkt) in pkts { - let client = clients.get_mut(&client_id).unwrap(); - client.send(ServerStateAction::Packet(pkt)).await; + let pkts = state.handle(client_id, &pkt); + match pkts { + Ok(pkts) => { + for (client_id, pkt) in pkts { + if let Some(client) = clients.get_mut(&client_id) { + client.send(ServerStateAction::Packet(pkt)).await; + } + } + }, + Err(err) => { + warn!("[client {:?} state handler error] {:?}", client_id, err); + } } }, ClientAction::Disconnect(client_id) => { let pkts = state.on_disconnect(client_id); for (client_id, pkt) in pkts { - let client = clients.get_mut(&client_id).unwrap(); - client.send(ServerStateAction::Packet(pkt)).await; + if let Some(client) = clients.get_mut(&client_id) { + client.send(ServerStateAction::Packet(pkt)).await; + } } - let client = clients.remove(&client_id).unwrap(); - client.send(ServerStateAction::Disconnect).await; + if let Some(client) = clients.get_mut(&client_id) { + client.send(ServerStateAction::Disconnect).await; + } } } } @@ -182,11 +219,14 @@ async fn client_recv_loop(client_id: ClientId, }, Err(err) => { match err { - PacketReceiverError::ClientDisconnect => { + NetworkError::ClientDisconnected => { trace!("[client disconnected] {:?}", client_id); server_sender.send(ClientAction::Disconnect(client_id)); break; } + _ => { + warn!("[client {:?} recv error] {:?}", client_id, err); + } } } } @@ -213,7 +253,9 @@ async fn client_send_loop(client_id: ClientId, } ServerStateAction::Packet(pkt) => { trace!("[send to {:?}] {:?}", client_id, pkt); - send_pkt(socket.clone(), cipher_out.clone(), pkt).await + if let Err(err) = send_pkt(socket.clone(), cipher_out.clone(), pkt).await { + warn!("[client {:?} send error ] {:?}", client_id, err); + } }, ServerStateAction::Disconnect => { break; diff --git a/src/common/mod.rs b/src/common/mod.rs index 55a50a1..954e8d0 100644 --- a/src/common/mod.rs +++ b/src/common/mod.rs @@ -1,5 +1,4 @@ pub mod cipherkeys; -pub mod network; pub mod serverstate; pub mod mainloop; pub mod leveltable; diff --git a/src/common/network.rs b/src/common/network.rs deleted file mode 100644 index 713cf05..0000000 --- a/src/common/network.rs +++ /dev/null @@ -1,33 +0,0 @@ -use std::io::{Read}; -use log::trace; - -use libpso::crypto::{PSOCipher, CipherError}; -use libpso::PacketParseError; - -#[derive(Debug)] -pub enum PacketNetworkError { - CouldNotSend, - CipherError(CipherError), - PacketParseError(PacketParseError), - IOError(std::io::Error), - DataNotReady, - ClientDisconnected, -} - -impl From for PacketNetworkError { - fn from(err: CipherError) -> PacketNetworkError { - PacketNetworkError::CipherError(err) - } -} - -impl From for PacketNetworkError { - fn from(err: std::io::Error) -> PacketNetworkError { - PacketNetworkError::IOError(err) - } -} - -impl From for PacketNetworkError { - fn from(err: PacketParseError) -> PacketNetworkError { - PacketNetworkError::PacketParseError(err) - } -} diff --git a/src/patch/patch.rs b/src/patch/patch.rs index eafa771..a48faa7 100644 --- a/src/patch/patch.rs +++ b/src/patch/patch.rs @@ -11,18 +11,18 @@ use libpso::crypto::pc::PSOPCCipher; use ron::de::from_str; use serde::Deserialize; -use crate::common::network::{PacketNetworkError}; +use crate::common::mainloop::{NetworkError}; use crate::common::serverstate::{RecvServerPacket, SendServerPacket, ServerState, OnConnect, ClientId}; #[derive(Debug)] pub enum PatchError { - PacketNetworkError(PacketNetworkError), + NetworkError(NetworkError), IOError(std::io::Error), } -impl From for PatchError { - fn from(err: PacketNetworkError) -> PatchError { - PatchError::PacketNetworkError(err) +impl From for PatchError { + fn from(err: NetworkError) -> PatchError { + PatchError::NetworkError(err) } }