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:
parent
db2ee114a9
commit
6ecdae840c
9 changed files with 26 additions and 17 deletions
6
build.rs
6
build.rs
|
@ -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");
|
||||||
|
|
|
@ -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 } => {
|
||||||
|
|
|
@ -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?
|
||||||
|
|
|
@ -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))]
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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)]
|
||||||
|
|
|
@ -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,))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
|
|
|
@ -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> {
|
||||||
|
|
Loading…
Add table
Reference in a new issue