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!("{name},\n"));
} }
output_str.push_str(&format!("Unknown,\n")); output_str.push_str(&format!("Unknown(u16),\n"));
// end // end
output_str.push_str("}\n\n"); 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}::{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");
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}::{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");
output_str.push_str("}\n\n"); output_str.push_str("}\n\n");

View file

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

View file

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

View file

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

View file

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

View file

@ -167,7 +167,7 @@ pub enum GameMasterCommandType {
} }
#[binrw] #[binrw]
#[br(import(magic: &ServerZoneIpcType))] #[br(import(magic: &ServerZoneIpcType, _size: &u32))]
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum ServerZoneIpcData { pub enum ServerZoneIpcData {
/// Sent by the server as response to ZoneInitRequest. /// Sent by the server as response to ZoneInitRequest.
@ -330,7 +330,7 @@ pub enum ServerZoneIpcData {
} }
#[binrw] #[binrw]
#[br(import(magic: &ClientZoneIpcType))] #[br(import(magic: &ClientZoneIpcType, size: &u32))]
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum ClientZoneIpcData { 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) /// 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)] #[brw(pad_after = 8)]
unk3: u8, unk3: u8,
}, },
Unknown, Unknown {
#[br(count = size - 32)]
unk: Vec<u8>,
},
} }
#[cfg(test)] #[cfg(test)]

View file

@ -31,9 +31,9 @@ pub(crate) fn decrypt<T: ReadWriteIpcSegment>(
blowfish.decrypt(&mut data); blowfish.decrypt(&mut data);
let mut cursor = Cursor::new(&data); let mut cursor = Cursor::new(&data);
T::read_options(&mut cursor, endian, ()) T::read_options(&mut cursor, endian, (&size,))
} else { } 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. /// 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: 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. /// 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. /// When implementing this, please use the size seen in retail instead of guessing.
@ -36,11 +36,12 @@ pub trait ReadWriteIpcSegment:
/// ``` /// ```
#[binrw] #[binrw]
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
#[br(import(size: &u32))]
pub struct IpcSegment<OpCode, Data> pub struct IpcSegment<OpCode, Data>
where where
for<'a> OpCode: BinRead<Args<'a> = ()> + 'a + std::fmt::Debug, for<'a> OpCode: BinRead<Args<'a> = ()> + 'a + std::fmt::Debug,
for<'a> OpCode: BinWrite<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, for<'a> Data: BinWrite<Args<'a> = ()> + 'a + std::fmt::Debug,
{ {
/// Unknown purpose, but usually 20. /// Unknown purpose, but usually 20.
@ -56,6 +57,6 @@ where
pub timestamp: u32, pub timestamp: u32,
/// The data associated with the opcode. /// The data associated with the opcode.
#[brw(pad_before = 4)] #[brw(pad_before = 4)]
#[br(args(&op_code))] #[br(args(&op_code, size))]
pub data: Data, pub data: Data,
} }

View file

@ -96,7 +96,10 @@ pub enum SegmentData<T: ReadWriteIpcSegment> {
KeepAliveResponse { id: u32, timestamp: u32 }, KeepAliveResponse { id: u32, timestamp: u32 },
#[br(pre_assert(kind == SegmentType::KawariIpc))] #[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> { impl<T: ReadWriteIpcSegment> Default for SegmentData<T> {