mirror of
https://github.com/Pumpkin-MC/Pumpkin.git
synced 2026-08-30 20:14:23 +00:00
Split PacketError into 2 Structs
Much nicer now
This commit is contained in:
@@ -49,6 +49,7 @@ and customizable experience. It prioritizes performance and player enjoyment whi
|
||||
- [x] Entity Spawning
|
||||
- [x] Chunk Loading
|
||||
- [x] Chunk Generation
|
||||
- [ ] World Time
|
||||
- [x] Scoreboard
|
||||
- [x] World Borders
|
||||
- [ ] World Saving
|
||||
@@ -61,7 +62,7 @@ and customizable experience. It prioritizes performance and player enjoyment whi
|
||||
- [x] Player Inventory
|
||||
- [x] Player Combat
|
||||
- Server
|
||||
- [x] Plugins
|
||||
- [ ] Plugins
|
||||
- [ ] Query
|
||||
- [x] RCON
|
||||
- [x] Inventories
|
||||
|
||||
@@ -15,7 +15,7 @@ pub enum DeserializerError {
|
||||
UnknownPacket,
|
||||
#[error("serializer error {0}")]
|
||||
Message(String),
|
||||
#[error("Stdio error")]
|
||||
#[error("Stdio error {0}")]
|
||||
Stdio(std::io::Error),
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use bytebuf::{packet_id::ClientPacketID, ByteBuffer, DeserializerError};
|
||||
use pumpkin_core::text::{style::Style, TextComponent};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use thiserror::Error;
|
||||
|
||||
pub mod bytebuf;
|
||||
pub mod client;
|
||||
@@ -30,46 +29,6 @@ pub type FixedBitSet = bytes::Bytes;
|
||||
|
||||
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)]
|
||||
pub enum ConnectionState {
|
||||
HandShake,
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
use aes::cipher::{generic_array::GenericArray, BlockDecryptMut, BlockSizeUser, KeyIvInit};
|
||||
use bytes::{Buf, BytesMut};
|
||||
use thiserror::Error;
|
||||
|
||||
use std::io::Write;
|
||||
|
||||
use bytes::BufMut;
|
||||
use flate2::write::ZlibDecoder;
|
||||
|
||||
use crate::{
|
||||
bytebuf::ByteBuffer, PacketError, RawPacket, VarInt, VarIntDecodeError, MAX_PACKET_SIZE,
|
||||
};
|
||||
use crate::{bytebuf::ByteBuffer, RawPacket, VarInt, VarIntDecodeError, MAX_PACKET_SIZE};
|
||||
|
||||
type Cipher = cfb8::Decryptor<aes::Aes128>;
|
||||
|
||||
@@ -24,17 +23,17 @@ pub struct 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 packet_len = match VarInt::decode_partial(&mut r) {
|
||||
Ok(len) => len,
|
||||
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) {
|
||||
Err(PacketError::OutOfBounds)?
|
||||
Err(PacketDecodeError::OutOfBounds)?
|
||||
}
|
||||
|
||||
if r.len() < packet_len as usize {
|
||||
@@ -48,10 +47,12 @@ impl PacketDecoder {
|
||||
if self.compression {
|
||||
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) {
|
||||
Err(PacketError::OutOfBounds)?
|
||||
Err(PacketDecodeError::OutOfBounds)?
|
||||
}
|
||||
|
||||
// Is this packet compressed?
|
||||
@@ -64,8 +65,8 @@ impl PacketDecoder {
|
||||
let mut z = ZlibDecoder::new(&mut self.decompress_buf[..]);
|
||||
|
||||
z.write_all(r)
|
||||
.map_err(|e| PacketError::FailedWrite(e.to_string()))?;
|
||||
z.finish().map_err(|_| PacketError::FailedFinish)?;
|
||||
.map_err(|e| PacketDecodeError::FailedWrite(e.to_string()))?;
|
||||
z.finish().map_err(|_| PacketDecodeError::FailedFinish)?;
|
||||
|
||||
let total_packet_len = VarInt(packet_len).written_size() + packet_len as usize;
|
||||
|
||||
@@ -88,7 +89,7 @@ impl PacketDecoder {
|
||||
}
|
||||
|
||||
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());
|
||||
Ok(Some(RawPacket {
|
||||
@@ -158,3 +159,19 @@ impl PacketDecoder {
|
||||
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,
|
||||
}
|
||||
|
||||
@@ -3,13 +3,14 @@ use std::io::Write;
|
||||
use aes::cipher::{generic_array::GenericArray, BlockEncryptMut, BlockSizeUser, KeyIvInit};
|
||||
use bytes::{BufMut, BytesMut};
|
||||
use pumpkin_config::compression::CompressionInfo;
|
||||
use thiserror::Error;
|
||||
|
||||
use std::io::Read;
|
||||
|
||||
use flate2::bufread::ZlibEncoder;
|
||||
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>;
|
||||
|
||||
@@ -25,19 +26,19 @@ pub struct 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 mut writer = (&mut self.buf).writer();
|
||||
|
||||
let mut packet_buf = ByteBuffer::empty();
|
||||
VarInt(P::PACKET_ID)
|
||||
.encode(&mut writer)
|
||||
.map_err(|_| PacketError::EncodeID)?;
|
||||
.map_err(|_| PacketEncodeError::EncodeID)?;
|
||||
packet.write(&mut packet_buf);
|
||||
|
||||
writer
|
||||
.write(packet_buf.buf())
|
||||
.map_err(|_| PacketError::EncodeFailedWrite)?;
|
||||
.map_err(|_| PacketEncodeError::EncodeFailedWrite)?;
|
||||
|
||||
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();
|
||||
|
||||
if packet_len >= MAX_PACKET_SIZE as usize {
|
||||
Err(PacketError::TooLong)?
|
||||
Err(PacketEncodeError::TooLong)?
|
||||
}
|
||||
|
||||
drop(z);
|
||||
@@ -64,17 +65,17 @@ impl PacketEncoder {
|
||||
|
||||
VarInt(packet_len as i32)
|
||||
.encode(&mut writer)
|
||||
.map_err(|_| PacketError::EncodeLength)?;
|
||||
.map_err(|_| PacketEncodeError::EncodeLength)?;
|
||||
VarInt(data_len as i32)
|
||||
.encode(&mut writer)
|
||||
.map_err(|_| PacketError::EncodeData)?;
|
||||
.map_err(|_| PacketEncodeError::EncodeData)?;
|
||||
self.buf.extend_from_slice(&self.compress_buf);
|
||||
} else {
|
||||
let data_len_size = 1;
|
||||
let packet_len = data_len_size + data_len;
|
||||
|
||||
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();
|
||||
@@ -89,11 +90,11 @@ impl PacketEncoder {
|
||||
|
||||
VarInt(packet_len as i32)
|
||||
.encode(&mut front)
|
||||
.map_err(|_| PacketError::EncodeLength)?;
|
||||
.map_err(|_| PacketEncodeError::EncodeLength)?;
|
||||
// Zero for no compression on this packet.
|
||||
VarInt(0)
|
||||
.encode(front)
|
||||
.map_err(|_| PacketError::EncodeData)?;
|
||||
.map_err(|_| PacketEncodeError::EncodeData)?;
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
@@ -102,7 +103,7 @@ impl PacketEncoder {
|
||||
let packet_len = data_len;
|
||||
|
||||
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();
|
||||
@@ -114,7 +115,7 @@ impl PacketEncoder {
|
||||
let front = &mut self.buf[start_len..];
|
||||
VarInt(packet_len as i32)
|
||||
.encode(front)
|
||||
.map_err(|_| PacketError::EncodeID)?;
|
||||
.map_err(|_| PacketEncodeError::EncodeID)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -146,3 +147,24 @@ impl PacketEncoder {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ pub enum AuthError {
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum TextureError {
|
||||
#[error("Invalid URL")]
|
||||
#[error("Invalid URL {0}")]
|
||||
InvalidURL(String),
|
||||
#[error("Invalid URL scheme for player texture: {0}")]
|
||||
DisallowedUrlScheme(String),
|
||||
|
||||
@@ -21,7 +21,7 @@ use pumpkin_protocol::{
|
||||
bytebuf::DeserializerError,
|
||||
client::{config::CConfigDisconnect, login::CLoginDisconnect, play::CPlayDisconnect},
|
||||
packet_decoder::PacketDecoder,
|
||||
packet_encoder::PacketEncoder,
|
||||
packet_encoder::{PacketEncodeError, PacketEncoder},
|
||||
server::{
|
||||
config::{
|
||||
SAcknowledgeFinishConfig, SClientInformationConfig, SKnownPacks, SPluginMessage,
|
||||
@@ -34,7 +34,7 @@ use pumpkin_protocol::{
|
||||
},
|
||||
status::{SStatusPingRequest, SStatusRequest, ServerboundStatusPackets},
|
||||
},
|
||||
ClientPacket, ConnectionState, PacketError, RawPacket, ServerPacket,
|
||||
ClientPacket, ConnectionState, RawPacket, ServerPacket,
|
||||
};
|
||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||
use tokio::sync::Mutex;
|
||||
@@ -231,14 +231,8 @@ impl Client {
|
||||
}
|
||||
|
||||
let mut writer = self.connection_writer.lock().await;
|
||||
if let Err(error) = writer
|
||||
.write_all(&enc.take())
|
||||
.await
|
||||
.map_err(|_| PacketError::ConnectionWrite)
|
||||
{
|
||||
if error.kickable() {
|
||||
self.kick(&error.to_string()).await;
|
||||
}
|
||||
if let Err(error) = writer.write_all(&enc.take()).await {
|
||||
log::debug!("{}", error.to_string());
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -265,7 +259,10 @@ impl Client {
|
||||
/// # Errors
|
||||
///
|
||||
/// 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);
|
||||
/*
|
||||
log::debug!(
|
||||
@@ -279,10 +276,7 @@ impl Client {
|
||||
enc.append_packet(packet)?;
|
||||
|
||||
let mut writer = self.connection_writer.lock().await;
|
||||
writer
|
||||
.write_all(&enc.take())
|
||||
.await
|
||||
.map_err(|_| PacketError::ConnectionWrite)?;
|
||||
let _ = writer.write_all(&enc.take()).await;
|
||||
|
||||
/*
|
||||
writer
|
||||
|
||||
Reference in New Issue
Block a user