Split PacketError into 2 Structs
Much nicer now
This commit is contained in:
parent
9b1e518556
commit
21dd9c194c
@ -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
|
||||||
|
|||||||
@ -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),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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,
|
||||||
|
}
|
||||||
|
|||||||
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -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),
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user