improve network error handling
This commit is contained in:
parent
62bc447f71
commit
1add8b500a
@ -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<CipherError> for NetworkError {
|
||||
fn from(err: CipherError) -> NetworkError {
|
||||
NetworkError::CipherError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::io::Error> for NetworkError {
|
||||
fn from(err: std::io::Error) -> NetworkError {
|
||||
NetworkError::IOError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PacketParseError> 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<R: RecvServerPacket + Send + std::fmt::Debug>(&mut self) -> Result<Vec<R>, PacketReceiverError> {
|
||||
async fn recv_pkts<R: RecvServerPacket + Send + std::fmt::Debug>(&mut self) -> Result<Vec<R>, NetworkError> {
|
||||
self.fill_recv_buffer().await?;
|
||||
|
||||
let mut result = Vec::new();
|
||||
@ -89,12 +114,15 @@ impl PacketReceiver {
|
||||
}
|
||||
}
|
||||
|
||||
async fn send_pkt<S: SendServerPacket + Send + std::fmt::Debug>(socket: Arc<async_std::net::TcpStream>, cipher: Arc<Mutex<Box<dyn PSOCipher + Send>>>, pkt: S) {
|
||||
async fn send_pkt<S: SendServerPacket + Send + std::fmt::Debug>(socket: Arc<async_std::net::TcpStream>,
|
||||
cipher: Arc<Mutex<Box<dyn PSOCipher + Send>>>, 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(())
|
||||
}
|
||||
|
||||
|
||||
@ -138,25 +166,34 @@ async fn server_state_loop<STATE, S, R, E>(mut state: STATE,
|
||||
}
|
||||
},
|
||||
ClientAction::Packet(client_id, pkt) => {
|
||||
let k = state.handle(client_id, &pkt);
|
||||
let pkts = k.unwrap().collect::<Vec<_>>();
|
||||
let pkts = state.handle(client_id, &pkt);
|
||||
match pkts {
|
||||
Ok(pkts) => {
|
||||
for (client_id, pkt) in pkts {
|
||||
let client = clients.get_mut(&client_id).unwrap();
|
||||
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();
|
||||
if let Some(client) = clients.get_mut(&client_id) {
|
||||
client.send(ServerStateAction::Packet(pkt)).await;
|
||||
}
|
||||
}
|
||||
|
||||
let client = clients.remove(&client_id).unwrap();
|
||||
if let Some(client) = clients.get_mut(&client_id) {
|
||||
client.send(ServerStateAction::Disconnect).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -182,11 +219,14 @@ async fn client_recv_loop<S, R>(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<S>(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;
|
||||
|
@ -1,5 +1,4 @@
|
||||
pub mod cipherkeys;
|
||||
pub mod network;
|
||||
pub mod serverstate;
|
||||
pub mod mainloop;
|
||||
pub mod leveltable;
|
||||
|
@ -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<CipherError> for PacketNetworkError {
|
||||
fn from(err: CipherError) -> PacketNetworkError {
|
||||
PacketNetworkError::CipherError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::io::Error> for PacketNetworkError {
|
||||
fn from(err: std::io::Error) -> PacketNetworkError {
|
||||
PacketNetworkError::IOError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PacketParseError> for PacketNetworkError {
|
||||
fn from(err: PacketParseError) -> PacketNetworkError {
|
||||
PacketNetworkError::PacketParseError(err)
|
||||
}
|
||||
}
|
@ -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<PacketNetworkError> for PatchError {
|
||||
fn from(err: PacketNetworkError) -> PatchError {
|
||||
PatchError::PacketNetworkError(err)
|
||||
impl From<NetworkError> for PatchError {
|
||||
fn from(err: NetworkError) -> PatchError {
|
||||
PatchError::NetworkError(err)
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user