Split PacketError into 2 Structs

Much nicer now
This commit is contained in:
Snowiiii 2024-11-01 10:26:07 +01:00
parent 9b1e518556
commit 21dd9c194c
7 changed files with 75 additions and 82 deletions

View File

@ -49,6 +49,7 @@ and customizable experience. It prioritizes performance and player enjoyment whi
- [x] Entity Spawning - [x] Entity Spawning
- [x] Chunk Loading - [x] Chunk Loading
- [x] Chunk Generation - [x] Chunk Generation
- [ ] World Time
- [x] Scoreboard - [x] Scoreboard
- [x] World Borders - [x] World Borders
- [ ] World Saving - [ ] World Saving
@ -61,7 +62,7 @@ and customizable experience. It prioritizes performance and player enjoyment whi
- [x] Player Inventory - [x] Player Inventory
- [x] Player Combat - [x] Player Combat
- Server - Server
- [x] Plugins - [ ] Plugins
- [ ] Query - [ ] Query
- [x] RCON - [x] RCON
- [x] Inventories - [x] Inventories

View File

@ -15,7 +15,7 @@ pub enum DeserializerError {
UnknownPacket, UnknownPacket,
#[error("serializer error {0}")] #[error("serializer error {0}")]
Message(String), Message(String),
#[error("Stdio error")] #[error("Stdio error {0}")]
Stdio(std::io::Error), Stdio(std::io::Error),
} }

View File

@ -1,7 +1,6 @@
use bytebuf::{packet_id::ClientPacketID, ByteBuffer, DeserializerError}; use bytebuf::{packet_id::ClientPacketID, ByteBuffer, DeserializerError};
use pumpkin_core::text::{style::Style, TextComponent}; use pumpkin_core::text::{style::Style, TextComponent};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use thiserror::Error;
pub mod bytebuf; pub mod bytebuf;
pub mod client; pub mod client;
@ -30,46 +29,6 @@ pub type FixedBitSet = bytes::Bytes;
pub struct BitSet<'a>(pub VarInt, pub &'a [i64]); pub struct BitSet<'a>(pub VarInt, pub &'a [i64]);
#[derive(Error, Debug)]
pub enum PacketError {
#[error("failed to decode packet ID")]
DecodeID,
#[error("failed to encode packet ID")]
EncodeID,
#[error("failed to encode packet Length")]
EncodeLength,
#[error("failed to encode packet data")]
EncodeData,
#[error("failed to write encoded packet")]
EncodeFailedWrite,
#[error("failed to write into decoder: {0}")]
FailedWrite(String),
#[error("failed to flush decoder")]
FailedFinish,
#[error("failed to write encoded packet to connection")]
ConnectionWrite,
#[error("packet exceeds maximum length")]
TooLong,
#[error("packet length is out of bounds")]
OutOfBounds,
#[error("malformed packet length VarInt")]
MalformedLength,
}
impl PacketError {
pub fn kickable(&self) -> bool {
// We no longer have a connection, so dont try to kick the player, just close
!matches!(
self,
Self::EncodeData
| Self::EncodeFailedWrite
| Self::FailedWrite(_)
| Self::FailedFinish
| Self::ConnectionWrite
)
}
}
#[derive(Debug, PartialEq, Clone, Copy)] #[derive(Debug, PartialEq, Clone, Copy)]
pub enum ConnectionState { pub enum ConnectionState {
HandShake, HandShake,

View File

@ -1,14 +1,13 @@
use aes::cipher::{generic_array::GenericArray, BlockDecryptMut, BlockSizeUser, KeyIvInit}; use aes::cipher::{generic_array::GenericArray, BlockDecryptMut, BlockSizeUser, KeyIvInit};
use bytes::{Buf, BytesMut}; use bytes::{Buf, BytesMut};
use thiserror::Error;
use std::io::Write; use std::io::Write;
use bytes::BufMut; use bytes::BufMut;
use flate2::write::ZlibDecoder; use flate2::write::ZlibDecoder;
use crate::{ use crate::{bytebuf::ByteBuffer, RawPacket, VarInt, VarIntDecodeError, MAX_PACKET_SIZE};
bytebuf::ByteBuffer, PacketError, RawPacket, VarInt, VarIntDecodeError, MAX_PACKET_SIZE,
};
type Cipher = cfb8::Decryptor<aes::Aes128>; type Cipher = cfb8::Decryptor<aes::Aes128>;
@ -24,17 +23,17 @@ pub struct PacketDecoder {
} }
impl PacketDecoder { impl PacketDecoder {
pub fn decode(&mut self) -> Result<Option<RawPacket>, PacketError> { pub fn decode(&mut self) -> Result<Option<RawPacket>, PacketDecodeError> {
let mut r = &self.buf[..]; let mut r = &self.buf[..];
let packet_len = match VarInt::decode_partial(&mut r) { let packet_len = match VarInt::decode_partial(&mut r) {
Ok(len) => len, Ok(len) => len,
Err(VarIntDecodeError::Incomplete) => return Ok(None), Err(VarIntDecodeError::Incomplete) => return Ok(None),
Err(VarIntDecodeError::TooLarge) => Err(PacketError::MalformedLength)?, Err(VarIntDecodeError::TooLarge) => Err(PacketDecodeError::MalformedLength)?,
}; };
if !(0..=MAX_PACKET_SIZE).contains(&packet_len) { if !(0..=MAX_PACKET_SIZE).contains(&packet_len) {
Err(PacketError::OutOfBounds)? Err(PacketDecodeError::OutOfBounds)?
} }
if r.len() < packet_len as usize { if r.len() < packet_len as usize {
@ -48,10 +47,12 @@ impl PacketDecoder {
if self.compression { if self.compression {
r = &r[..packet_len as usize]; r = &r[..packet_len as usize];
let data_len = VarInt::decode(&mut r).map_err(|_| PacketError::TooLong)?.0; let data_len = VarInt::decode(&mut r)
.map_err(|_| PacketDecodeError::TooLong)?
.0;
if !(0..=MAX_PACKET_SIZE).contains(&data_len) { if !(0..=MAX_PACKET_SIZE).contains(&data_len) {
Err(PacketError::OutOfBounds)? Err(PacketDecodeError::OutOfBounds)?
} }
// Is this packet compressed? // Is this packet compressed?
@ -64,8 +65,8 @@ impl PacketDecoder {
let mut z = ZlibDecoder::new(&mut self.decompress_buf[..]); let mut z = ZlibDecoder::new(&mut self.decompress_buf[..]);
z.write_all(r) z.write_all(r)
.map_err(|e| PacketError::FailedWrite(e.to_string()))?; .map_err(|e| PacketDecodeError::FailedWrite(e.to_string()))?;
z.finish().map_err(|_| PacketError::FailedFinish)?; z.finish().map_err(|_| PacketDecodeError::FailedFinish)?;
let total_packet_len = VarInt(packet_len).written_size() + packet_len as usize; let total_packet_len = VarInt(packet_len).written_size() + packet_len as usize;
@ -88,7 +89,7 @@ impl PacketDecoder {
} }
r = &data[..]; r = &data[..];
let packet_id = VarInt::decode(&mut r).map_err(|_| PacketError::DecodeID)?; let packet_id = VarInt::decode(&mut r).map_err(|_| PacketDecodeError::DecodeID)?;
data.advance(data.len() - r.len()); data.advance(data.len() - r.len());
Ok(Some(RawPacket { Ok(Some(RawPacket {
@ -158,3 +159,19 @@ impl PacketDecoder {
self.buf.reserve(additional); self.buf.reserve(additional);
} }
} }
#[derive(Error, Debug)]
pub enum PacketDecodeError {
#[error("failed to decode packet ID")]
DecodeID,
#[error("failed to write into decoder: {0}")]
FailedWrite(String),
#[error("failed to flush decoder")]
FailedFinish,
#[error("packet exceeds maximum length")]
TooLong,
#[error("packet length is out of bounds")]
OutOfBounds,
#[error("malformed packet length VarInt")]
MalformedLength,
}

View File

@ -3,13 +3,14 @@ use std::io::Write;
use aes::cipher::{generic_array::GenericArray, BlockEncryptMut, BlockSizeUser, KeyIvInit}; use aes::cipher::{generic_array::GenericArray, BlockEncryptMut, BlockSizeUser, KeyIvInit};
use bytes::{BufMut, BytesMut}; use bytes::{BufMut, BytesMut};
use pumpkin_config::compression::CompressionInfo; use pumpkin_config::compression::CompressionInfo;
use thiserror::Error;
use std::io::Read; use std::io::Read;
use flate2::bufread::ZlibEncoder; use flate2::bufread::ZlibEncoder;
use flate2::Compression; use flate2::Compression;
use crate::{bytebuf::ByteBuffer, ClientPacket, PacketError, VarInt, MAX_PACKET_SIZE}; use crate::{bytebuf::ByteBuffer, ClientPacket, VarInt, MAX_PACKET_SIZE};
type Cipher = cfb8::Encryptor<aes::Aes128>; type Cipher = cfb8::Encryptor<aes::Aes128>;
@ -25,19 +26,19 @@ pub struct PacketEncoder {
} }
impl PacketEncoder { impl PacketEncoder {
pub fn append_packet<P: ClientPacket>(&mut self, packet: &P) -> Result<(), PacketError> { pub fn append_packet<P: ClientPacket>(&mut self, packet: &P) -> Result<(), PacketEncodeError> {
let start_len = self.buf.len(); let start_len = self.buf.len();
let mut writer = (&mut self.buf).writer(); let mut writer = (&mut self.buf).writer();
let mut packet_buf = ByteBuffer::empty(); let mut packet_buf = ByteBuffer::empty();
VarInt(P::PACKET_ID) VarInt(P::PACKET_ID)
.encode(&mut writer) .encode(&mut writer)
.map_err(|_| PacketError::EncodeID)?; .map_err(|_| PacketEncodeError::EncodeID)?;
packet.write(&mut packet_buf); packet.write(&mut packet_buf);
writer writer
.write(packet_buf.buf()) .write(packet_buf.buf())
.map_err(|_| PacketError::EncodeFailedWrite)?; .map_err(|_| PacketEncodeError::EncodeFailedWrite)?;
let data_len = self.buf.len() - start_len; let data_len = self.buf.len() - start_len;
@ -53,7 +54,7 @@ impl PacketEncoder {
let packet_len = data_len_size + z.read_to_end(&mut self.compress_buf).unwrap(); let packet_len = data_len_size + z.read_to_end(&mut self.compress_buf).unwrap();
if packet_len >= MAX_PACKET_SIZE as usize { if packet_len >= MAX_PACKET_SIZE as usize {
Err(PacketError::TooLong)? Err(PacketEncodeError::TooLong)?
} }
drop(z); drop(z);
@ -64,17 +65,17 @@ impl PacketEncoder {
VarInt(packet_len as i32) VarInt(packet_len as i32)
.encode(&mut writer) .encode(&mut writer)
.map_err(|_| PacketError::EncodeLength)?; .map_err(|_| PacketEncodeError::EncodeLength)?;
VarInt(data_len as i32) VarInt(data_len as i32)
.encode(&mut writer) .encode(&mut writer)
.map_err(|_| PacketError::EncodeData)?; .map_err(|_| PacketEncodeError::EncodeData)?;
self.buf.extend_from_slice(&self.compress_buf); self.buf.extend_from_slice(&self.compress_buf);
} else { } else {
let data_len_size = 1; let data_len_size = 1;
let packet_len = data_len_size + data_len; let packet_len = data_len_size + data_len;
if packet_len >= MAX_PACKET_SIZE as usize { if packet_len >= MAX_PACKET_SIZE as usize {
Err(PacketError::TooLong)? Err(PacketEncodeError::TooLong)?
} }
let packet_len_size = VarInt(packet_len as i32).written_size(); let packet_len_size = VarInt(packet_len as i32).written_size();
@ -89,11 +90,11 @@ impl PacketEncoder {
VarInt(packet_len as i32) VarInt(packet_len as i32)
.encode(&mut front) .encode(&mut front)
.map_err(|_| PacketError::EncodeLength)?; .map_err(|_| PacketEncodeError::EncodeLength)?;
// Zero for no compression on this packet. // Zero for no compression on this packet.
VarInt(0) VarInt(0)
.encode(front) .encode(front)
.map_err(|_| PacketError::EncodeData)?; .map_err(|_| PacketEncodeError::EncodeData)?;
} }
return Ok(()); return Ok(());
@ -102,7 +103,7 @@ impl PacketEncoder {
let packet_len = data_len; let packet_len = data_len;
if packet_len >= MAX_PACKET_SIZE as usize { if packet_len >= MAX_PACKET_SIZE as usize {
Err(PacketError::TooLong)? Err(PacketEncodeError::TooLong)?
} }
let packet_len_size = VarInt(packet_len as i32).written_size(); let packet_len_size = VarInt(packet_len as i32).written_size();
@ -114,7 +115,7 @@ impl PacketEncoder {
let front = &mut self.buf[start_len..]; let front = &mut self.buf[start_len..];
VarInt(packet_len as i32) VarInt(packet_len as i32)
.encode(front) .encode(front)
.map_err(|_| PacketError::EncodeID)?; .map_err(|_| PacketEncodeError::EncodeID)?;
Ok(()) Ok(())
} }
@ -146,3 +147,24 @@ impl PacketEncoder {
self.buf.split() self.buf.split()
} }
} }
#[derive(Error, Debug)]
pub enum PacketEncodeError {
#[error("failed to encode packet ID")]
EncodeID,
#[error("failed to encode packet Length")]
EncodeLength,
#[error("failed to encode packet data")]
EncodeData,
#[error("failed to write encoded packet")]
EncodeFailedWrite,
#[error("packet exceeds maximum length")]
TooLong,
}
impl PacketEncodeError {
pub fn kickable(&self) -> bool {
// We no longer have a connection, so dont try to kick the player, just close
!matches!(self, Self::EncodeData | Self::EncodeFailedWrite)
}
}

View File

@ -147,7 +147,7 @@ pub enum AuthError {
#[derive(Error, Debug)] #[derive(Error, Debug)]
pub enum TextureError { pub enum TextureError {
#[error("Invalid URL")] #[error("Invalid URL {0}")]
InvalidURL(String), InvalidURL(String),
#[error("Invalid URL scheme for player texture: {0}")] #[error("Invalid URL scheme for player texture: {0}")]
DisallowedUrlScheme(String), DisallowedUrlScheme(String),

View File

@ -21,7 +21,7 @@ use pumpkin_protocol::{
bytebuf::DeserializerError, bytebuf::DeserializerError,
client::{config::CConfigDisconnect, login::CLoginDisconnect, play::CPlayDisconnect}, client::{config::CConfigDisconnect, login::CLoginDisconnect, play::CPlayDisconnect},
packet_decoder::PacketDecoder, packet_decoder::PacketDecoder,
packet_encoder::PacketEncoder, packet_encoder::{PacketEncodeError, PacketEncoder},
server::{ server::{
config::{ config::{
SAcknowledgeFinishConfig, SClientInformationConfig, SKnownPacks, SPluginMessage, SAcknowledgeFinishConfig, SClientInformationConfig, SKnownPacks, SPluginMessage,
@ -34,7 +34,7 @@ use pumpkin_protocol::{
}, },
status::{SStatusPingRequest, SStatusRequest, ServerboundStatusPackets}, status::{SStatusPingRequest, SStatusRequest, ServerboundStatusPackets},
}, },
ClientPacket, ConnectionState, PacketError, RawPacket, ServerPacket, ClientPacket, ConnectionState, RawPacket, ServerPacket,
}; };
use tokio::io::{AsyncReadExt, AsyncWriteExt}; use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::sync::Mutex; use tokio::sync::Mutex;
@ -231,14 +231,8 @@ impl Client {
} }
let mut writer = self.connection_writer.lock().await; let mut writer = self.connection_writer.lock().await;
if let Err(error) = writer if let Err(error) = writer.write_all(&enc.take()).await {
.write_all(&enc.take()) log::debug!("{}", error.to_string());
.await
.map_err(|_| PacketError::ConnectionWrite)
{
if error.kickable() {
self.kick(&error.to_string()).await;
}
} }
/* /*
@ -265,7 +259,10 @@ impl Client {
/// # Errors /// # Errors
/// ///
/// Returns an `PacketError` if the could not be Send. /// Returns an `PacketError` if the could not be Send.
pub async fn try_send_packet<P: ClientPacket>(&self, packet: &P) -> Result<(), PacketError> { pub async fn try_send_packet<P: ClientPacket>(
&self,
packet: &P,
) -> Result<(), PacketEncodeError> {
// assert!(!self.closed); // assert!(!self.closed);
/* /*
log::debug!( log::debug!(
@ -279,10 +276,7 @@ impl Client {
enc.append_packet(packet)?; enc.append_packet(packet)?;
let mut writer = self.connection_writer.lock().await; let mut writer = self.connection_writer.lock().await;
writer let _ = writer.write_all(&enc.take()).await;
.write_all(&enc.take())
.await
.map_err(|_| PacketError::ConnectionWrite)?;
/* /*
writer writer