feat: improve packet::parse tracing

This commit is contained in:
Tamipes 2025-12-06 20:18:54 +01:00
parent 7461b8ea30
commit f1c1b2c122
3 changed files with 41 additions and 17 deletions

View file

@ -89,7 +89,7 @@ async fn process_connection(
} }
handshake = packets::serverbound::handshake::Handshake::parse(client_packet) handshake = packets::serverbound::handshake::Handshake::parse(client_packet)
.await .await
.ok_or_else(|| "handshake request from client failed to parse".to_string())?; .ok_or_else(|| "Client HANDSHAKE -> malformed packet; Disconnecting...".to_string())?;
next_server_state = handshake.get_next_state(); next_server_state = handshake.get_next_state();

View file

@ -82,11 +82,11 @@ impl From<&str> for OpaqueError {
} }
} }
impl From<crate::packets::ParseError> for OpaqueError { impl From<crate::packets::ParseErrorTrace> for OpaqueError {
fn from(value: crate::packets::ParseError) -> Self { fn from(value: crate::packets::ParseErrorTrace) -> Self {
Self { Self {
span_trace: SpanTrace::capture(), span_trace: value.context,
context: format!("{:?}", value), context: format!("packet parse error: {:?}", value.inner),
} }
} }
} }

View file

@ -58,8 +58,8 @@ impl Packet {
all, all,
}) })
} }
#[tracing::instrument(level = "info",skip(stream),fields(addr = stream.peer_addr().map(|x| x.to_string()).unwrap_or("unknown".to_string())))] #[tracing::instrument(level = "info", skip(stream))]
pub async fn parse(stream: &mut TcpStream) -> Result<Packet, ParseError> { pub async fn parse(stream: &mut TcpStream) -> Result<Packet, ParseErrorTrace> {
let length = VarInt::parse(stream) let length = VarInt::parse(stream)
.await .await
.ok_or(ParseError::IDParseError)?; .ok_or(ParseError::IDParseError)?;
@ -68,23 +68,25 @@ impl Packet {
let id = match VarInt::parse(stream).await { let id = match VarInt::parse(stream).await {
Some(x) => x, Some(x) => x,
None => { None => {
return Err(ParseError::IDParseError); return Err(ParseError::IDParseError.into());
} }
}; };
if id.get_int() == 122 { if id.get_int() == 122 {
return Err(ParseError::WeirdID); return Err(ParseError::WeirdID.into());
} }
// TODO: investigate this, becuase it is just a hunch // TODO: investigate this, becuase it is just a hunch
// but if it is too big, the vec![] macro panics // but if it is too big, the vec![] macro panics
if length.get_int() > u16::MAX.into() { let data_size = length.get_int() as usize - id.get_data().len();
return Err(ParseError::LengthIsTooBig(length.get_int())); if data_size > u16::MAX.into() {
return Err(ParseError::LengthIsTooBig(length.get_int()).into());
} }
// TODO: this is a bandaid fix; the above check *should* make sure the if data_size > 0 {
return Err(ParseError::PacketLengthInvalid(length.get_int()).into());
}
// TODO: this is a bandaid fix; the above checks *should* make sure the
// next line does not run into "capacity overflow", but it doesn't work // next line does not run into "capacity overflow", but it doesn't work
let mut data: Vec<u8> = match std::panic::catch_unwind(|| { let mut data: Vec<u8> = match std::panic::catch_unwind(|| vec![0; data_size]) {
vec![0; length.get_int() as usize - id.get_data().len()]
}) {
Ok(x) => x, Ok(x) => x,
Err(e) => { Err(e) => {
return Err(ParseError::BufferAllocationPanic(format!( return Err(ParseError::BufferAllocationPanic(format!(
@ -93,7 +95,7 @@ impl Packet {
length.get_int(), length.get_int(),
length.get_int() as usize - id.get_data().len(), length.get_int() as usize - id.get_data().len(),
e e
))); )).into());
} }
}; };
@ -116,7 +118,8 @@ impl Packet {
length.get_int(), length.get_int(),
length.get_data(), length.get_data(),
e e
))); ))
.into());
} }
} }
} }
@ -129,10 +132,26 @@ impl Packet {
} }
} }
pub struct ParseErrorTrace {
pub inner: ParseError,
pub context: tracing_error::SpanTrace,
}
impl From<ParseError> for ParseErrorTrace {
fn from(value: ParseError) -> Self {
Self {
inner: value,
context: tracing_error::SpanTrace::capture(),
}
}
}
pub enum ParseError { pub enum ParseError {
IDParseError, IDParseError,
WeirdID, WeirdID,
LengthIsTooBig(i32), LengthIsTooBig(i32),
DataIsZero,
PacketLengthInvalid(i32),
StreamReadError(String), StreamReadError(String),
BufferAllocationPanic(String), BufferAllocationPanic(String),
} }
@ -145,6 +164,11 @@ impl fmt::Debug for ParseError {
Self::LengthIsTooBig(x) => { Self::LengthIsTooBig(x) => {
write!(f, "LengthIsTooBig: packet length is too big; len={x}") write!(f, "LengthIsTooBig: packet length is too big; len={x}")
} }
Self::DataIsZero => write!(f, "DataIsZero: data portion of packet does not exist"),
Self::PacketLengthInvalid(x) => write!(
f,
"PacketLengthInvalid: packet lenght is smaller then packet len={x}"
),
Self::StreamReadError(str) => write!(f, "StreamReadError: {str}"), Self::StreamReadError(str) => write!(f, "StreamReadError: {str}"),
Self::BufferAllocationPanic(str) => write!(f, "BufferAllocationPanic: {str}"), Self::BufferAllocationPanic(str) => write!(f, "BufferAllocationPanic: {str}"),
} }