1
Fork 0
mirror of https://github.com/redstrate/Kawari.git synced 2025-06-30 03:37:45 +00:00

Continue parsing when encountering unknown packets

This reads the unknown packet data, just throwing it in a byte
buffer. This allows us to read the rest of the segmenets in
the packet, and fixes parsing.

Note that this still log spams with "wrong size" as we can't
determine the size of the unknown packet ahead of time. This is
easy to fix, but it's not a high priority yet.

Fixes #73
This commit is contained in:
Joshua Goins 2025-06-28 08:48:59 -04:00
parent db2ee114a9
commit 6ecdae840c
9 changed files with 26 additions and 17 deletions

View file

@ -36,7 +36,7 @@ fn main() {
output_str.push_str(&format!("{name},\n"));
}
output_str.push_str(&format!("Unknown,\n"));
output_str.push_str(&format!("Unknown(u16),\n"));
// end
output_str.push_str("}\n\n");
@ -56,7 +56,7 @@ fn main() {
output_str.push_str(&format!("{key}::{name} => {size},\n"));
}
output_str.push_str(&format!("{key}::Unknown => 0,\n"));
output_str.push_str(&format!("{key}::Unknown(_) => 0,\n"));
output_str.push_str("}\n\n");
output_str.push_str("}\n\n");
@ -73,7 +73,7 @@ fn main() {
output_str.push_str(&format!("{key}::{name} => \"{name}\",\n"));
}
output_str.push_str(&format!("{key}::Unknown => \"Unknown\",\n"));
output_str.push_str(&format!("{key}::Unknown(_) => \"Unknown\",\n"));
output_str.push_str("}\n\n");
output_str.push_str("}\n\n");

View file

@ -939,7 +939,9 @@ async fn client_loop(
})
.await;
}
_ => {},
ClientZoneIpcData::Unknown { .. } => {
tracing::warn!("Unknown packet {:?} recieved, this should be handled!", data.op_code);
}
}
}
SegmentData::KeepAliveRequest { id, timestamp } => {

View file

@ -36,7 +36,7 @@ impl Default for ServerChatIpcSegment {
}
#[binrw]
#[br(import(magic: &ServerChatIpcType))]
#[br(import(magic: &ServerChatIpcType, _size: &u32))]
#[derive(Debug, Clone)]
pub enum ServerChatIpcData {
/// Sent by the server to Initialize something chat-related?

View file

@ -80,7 +80,7 @@ pub enum CustomIpcType {
}
#[binrw]
#[br(import(magic: &CustomIpcType))]
#[br(import(magic: &CustomIpcType, _size: &u32))]
#[derive(Debug, Clone)]
pub enum CustomIpcData {
#[br(pre_assert(*magic == CustomIpcType::RequestCreateCharacter))]

View file

@ -83,7 +83,7 @@ impl Default for ServerLobbyIpcSegment {
}
#[binrw]
#[br(import(magic: &ClientLobbyIpcType))]
#[br(import(magic: &ClientLobbyIpcType, _size: &u32))]
#[derive(Debug, Clone)]
pub enum ClientLobbyIpcData {
/// Sent by the client when it requests the character list in the lobby.
@ -131,7 +131,7 @@ pub enum ClientLobbyIpcData {
}
#[binrw]
#[br(import(magic: &ServerLobbyIpcType))]
#[br(import(magic: &ServerLobbyIpcType, _size: &u32))]
#[derive(Debug, Clone)]
pub enum ServerLobbyIpcData {
/// Sent by the server to indicate an lobby error occured.

View file

@ -167,7 +167,7 @@ pub enum GameMasterCommandType {
}
#[binrw]
#[br(import(magic: &ServerZoneIpcType))]
#[br(import(magic: &ServerZoneIpcType, _size: &u32))]
#[derive(Debug, Clone)]
pub enum ServerZoneIpcData {
/// Sent by the server as response to ZoneInitRequest.
@ -330,7 +330,7 @@ pub enum ServerZoneIpcData {
}
#[binrw]
#[br(import(magic: &ClientZoneIpcType))]
#[br(import(magic: &ClientZoneIpcType, size: &u32))]
#[derive(Debug, Clone)]
pub enum ClientZoneIpcData {
/// Sent by the client when they successfully initialize with the server, and they need several bits of information (e.g. what zone to load)
@ -476,7 +476,10 @@ pub enum ClientZoneIpcData {
#[brw(pad_after = 8)]
unk3: u8,
},
Unknown,
Unknown {
#[br(count = size - 32)]
unk: Vec<u8>,
},
}
#[cfg(test)]

View file

@ -31,9 +31,9 @@ pub(crate) fn decrypt<T: ReadWriteIpcSegment>(
blowfish.decrypt(&mut data);
let mut cursor = Cursor::new(&data);
T::read_options(&mut cursor, endian, ())
T::read_options(&mut cursor, endian, (&size,))
} else {
T::read_options(reader, endian, ())
T::read_options(reader, endian, (&size,))
}
}

View file

@ -2,7 +2,7 @@ use binrw::{BinRead, BinWrite, binrw};
/// Required to implement for specializations of `IpcSegment`. These should be read/writeable, however for client packets you can leave calc_size() unimplemented.
pub trait ReadWriteIpcSegment:
for<'a> BinRead<Args<'a> = ()> + for<'a> BinWrite<Args<'a> = ()> + std::fmt::Debug + 'static
for<'a> BinRead<Args<'a> = (&'a u32,)> + for<'a> BinWrite<Args<'a> = ()> + std::fmt::Debug + 'static
{
/// Calculate the size of this Ipc segment *including* the 16 byte header.
/// When implementing this, please use the size seen in retail instead of guessing.
@ -36,11 +36,12 @@ pub trait ReadWriteIpcSegment:
/// ```
#[binrw]
#[derive(Debug, Clone)]
#[br(import(size: &u32))]
pub struct IpcSegment<OpCode, Data>
where
for<'a> OpCode: BinRead<Args<'a> = ()> + 'a + std::fmt::Debug,
for<'a> OpCode: BinWrite<Args<'a> = ()> + 'a + std::fmt::Debug,
for<'a> Data: BinRead<Args<'a> = (&'a OpCode,)> + 'a + std::fmt::Debug,
for<'a> Data: BinRead<Args<'a> = (&'a OpCode, &'a u32)> + 'a + std::fmt::Debug,
for<'a> Data: BinWrite<Args<'a> = ()> + 'a + std::fmt::Debug,
{
/// Unknown purpose, but usually 20.
@ -56,6 +57,6 @@ where
pub timestamp: u32,
/// The data associated with the opcode.
#[brw(pad_before = 4)]
#[br(args(&op_code))]
#[br(args(&op_code, size))]
pub data: Data,
}

View file

@ -96,7 +96,10 @@ pub enum SegmentData<T: ReadWriteIpcSegment> {
KeepAliveResponse { id: u32, timestamp: u32 },
#[br(pre_assert(kind == SegmentType::KawariIpc))]
KawariIpc { data: CustomIpcSegment },
KawariIpc {
#[br(args(&0))] // this being zero is okay, custom ipc segments don't use the size arg
data: CustomIpcSegment,
},
}
impl<T: ReadWriteIpcSegment> Default for SegmentData<T> {