From b52ff724ab7f05d2e0dc2df0541cfd6a14857f1a Mon Sep 17 00:00:00 2001 From: Joshua Goins Date: Wed, 12 Mar 2025 18:44:05 -0400 Subject: [PATCH] Allow logging out of the client without destroying the world server This adds support for the IPC packets sent between the client & server when using the log out feature. --- src/bin/kawari-world.rs | 31 +++++++++++++++++++++++++++++++ src/ipc.rs | 24 ++++++++++++++++++++++++ src/packet.rs | 5 +++-- 3 files changed, 58 insertions(+), 2 deletions(-) diff --git a/src/bin/kawari-world.rs b/src/bin/kawari-world.rs index d4f6937..c391b33 100644 --- a/src/bin/kawari-world.rs +++ b/src/bin/kawari-world.rs @@ -411,6 +411,37 @@ async fn main() { IPCStructData::UpdatePositionHandler { .. } => { tracing::info!("Recieved UpdatePositionHandler!"); } + IPCStructData::LogOut { .. } => { + tracing::info!("Recieved log out from client!"); + + // tell the client to disconnect + { + let ipc = IPCSegment { + unk1: 0, + unk2: 0, + op_code: IPCOpCode::LogOutComplete, + server_id: 0, + timestamp: timestamp_secs(), + data: IPCStructData::LogOutComplete { unk: [0; 8] }, + }; + + let response_packet = PacketSegment { + source_actor: state.player_id.unwrap(), + target_actor: state.player_id.unwrap(), + segment_type: SegmentType::Ipc { data: ipc }, + }; + send_packet( + &mut write, + &[response_packet], + &mut state, + CompressionType::Oodle, + ) + .await; + } + } + IPCStructData::Disconnected { .. } => { + tracing::info!("Client disconnected!"); + } _ => panic!( "The server is recieving a IPC response or unknown packet!" ), diff --git a/src/ipc.rs b/src/ipc.rs index 128ad5c..ff17905 100644 --- a/src/ipc.rs +++ b/src/ipc.rs @@ -70,6 +70,12 @@ pub enum IPCOpCode { // FIXME: 32 bytes of something from the client, not sure what yet Unk7 = 0x2B5, UpdatePositionHandler = 0x249, // TODO: assumed + // Sent by the client when the user requests to log out + LogOut = 0x217, + // Sent by the server to indicate the log out is complete + LogOutComplete = 0x369, + // Sent by the client when it's actually disconnecting + Disconnected = 0x360, } #[binrw] @@ -259,6 +265,16 @@ pub enum IPCStructData { // TODO: full of possibly interesting information unk: [u8; 24], }, + #[br(pre_assert(*magic == IPCOpCode::LogOut))] + LogOut { + // TODO: full of possibly interesting information + unk: [u8; 8], + }, + #[br(pre_assert(*magic == IPCOpCode::Disconnected))] + Disconnected { + // TODO: full of possibly interesting information + unk: [u8; 8], + }, // Server->Client IPC #[br(pre_assert(false))] @@ -357,6 +373,11 @@ pub enum IPCStructData { UpdateClassInfo(UpdateClassInfo), #[br(pre_assert(false))] PlayerSpawn(PlayerSpawn), + #[br(pre_assert(false))] + LogOutComplete { + // TODO: guessed + unk: [u8; 8], + }, } #[binrw] @@ -409,6 +430,9 @@ impl IPCSegment { IPCStructData::Unk6 { .. } => todo!(), IPCStructData::Unk7 { .. } => todo!(), IPCStructData::UpdatePositionHandler { .. } => todo!(), + IPCStructData::LogOut { .. } => todo!(), + IPCStructData::LogOutComplete { .. } => 8, + IPCStructData::Disconnected { .. } => todo!(), } } } diff --git a/src/packet.rs b/src/packet.rs index aada8f8..5bc47d2 100644 --- a/src/packet.rs +++ b/src/packet.rs @@ -235,12 +235,13 @@ pub async fn parse_packet(data: &[u8], state: &mut State) -> (Vec Ok(packet) => { println!("{:#?}", packet); - if packet.header.size as usize != data.len() { + // don't really think this works like I think it does' + /*if packet.header.size as usize != data.len() { dump( "Packet size mismatch between what we're given and the header!", data, ); - } + }*/ (packet.segments, packet.header.connection_type) }