diff --git a/src/ipc.rs b/src/ipc.rs index b551a1f..6a3d565 100644 --- a/src/ipc.rs +++ b/src/ipc.rs @@ -1,5 +1,7 @@ use binrw::binrw; +use crate::common::{read_string, write_string}; + #[binrw] #[brw(repr = u16)] #[derive(Clone, PartialEq, Debug)] @@ -9,3 +11,75 @@ pub enum IPCOpCode { /// Sent by the server to inform the client of service accounts. LobbyServiceAccountList = 0xC, } + +#[binrw] +#[derive(Debug, Clone)] +pub struct ServiceAccount { + pub id: u32, + pub unk1: u32, + pub index: u32, + #[bw(pad_size_to = 0x44)] + #[br(count = 0x44)] + #[br(map = read_string)] + #[bw(map = write_string)] + pub name: String, +} + +#[binrw] +#[br(import(magic: &IPCOpCode))] +#[derive(Debug, Clone)] +pub enum IPCStructData { + // Client->Server IPC + #[br(pre_assert(*magic == IPCOpCode::ClientVersionInfo))] + ClientVersionInfo { + #[brw(pad_before = 18)] // full of nonsense i don't understand yet + #[br(count = 64)] + #[br(map = read_string)] + #[bw(ignore)] + session_id: String, + + #[brw(pad_before = 8)] // empty + #[br(count = 128)] + #[br(map = read_string)] + #[bw(ignore)] + version_info: String, + // unknown stuff at the end, it's not completely empty' + }, + + // Server->Client IPC + LobbyServiceAccountList { + sequence: u64, + #[brw(pad_before = 4)] + num_service_accounts: u8, + unk1: u8, + #[brw(pad_after = 4)] + unk2: u8, + #[br(count = 8)] + service_accounts: Vec, + }, +} + +#[binrw] +#[derive(Debug, Clone)] +pub struct IPCSegment { + pub unk1: u8, + pub unk2: u8, + pub op_code: IPCOpCode, + #[brw(pad_before = 2)] // empty + pub server_id: u16, + pub timestamp: u32, + #[brw(pad_before = 4)] + #[br(args(&op_code))] + pub data: IPCStructData, +} + +impl IPCSegment { + pub fn calc_size(&self) -> u32 { + let header = 16; + header + + match self.data { + IPCStructData::ClientVersionInfo { .. } => todo!(), + IPCStructData::LobbyServiceAccountList { .. } => 19, + } + } +} diff --git a/src/packet.rs b/src/packet.rs index 369f5ae..b64759b 100644 --- a/src/packet.rs +++ b/src/packet.rs @@ -11,9 +11,9 @@ use tokio::{ }; use crate::{ - common::{read_bool_from, read_string, write_bool_as, write_string}, + common::{read_bool_from, read_string, write_bool_as}, encryption::{blowfish_encode, decrypt, encrypt, generate_encryption_key}, - ipc::IPCOpCode, + ipc::{IPCOpCode, IPCSegment, IPCStructData, ServiceAccount}, }; #[binrw] @@ -26,78 +26,6 @@ enum ConnectionType { Lobby = 0x3, } -#[binrw] -#[derive(Debug, Clone)] -struct ServiceAccount { - id: u32, - unk1: u32, - index: u32, - #[bw(pad_size_to = 0x44)] - #[br(count = 0x44)] - #[br(map = read_string)] - #[bw(map = write_string)] - name: String, -} - -#[binrw] -#[br(import(magic: &IPCOpCode))] -#[derive(Debug, Clone)] -enum IPCStructData { - // Client->Server IPC - #[br(pre_assert(*magic == IPCOpCode::ClientVersionInfo))] - ClientVersionInfo { - #[brw(pad_before = 18)] // full of nonsense i don't understand yet - #[br(count = 64)] - #[br(map = read_string)] - #[bw(ignore)] - session_id: String, - - #[brw(pad_before = 8)] // empty - #[br(count = 128)] - #[br(map = read_string)] - #[bw(ignore)] - version_info: String, - // unknown stuff at the end, it's not completely empty' - }, - - // Server->Client IPC - LobbyServiceAccountList { - sequence: u64, - #[brw(pad_before = 4)] - num_service_accounts: u8, - unk1: u8, - #[brw(pad_after = 4)] - unk2: u8, - #[br(count = 8)] - service_accounts: Vec, - }, -} - -#[binrw] -#[derive(Debug, Clone)] -struct IPCSegment { - unk1: u8, - unk2: u8, - op_code: IPCOpCode, - #[brw(pad_before = 2)] // empty - server_id: u16, - timestamp: u32, - #[brw(pad_before = 4)] - #[br(args(&op_code))] - pub data: IPCStructData, -} - -impl IPCSegment { - fn calc_size(&self) -> u32 { - let header = 16; - header - + match self.data { - IPCStructData::ClientVersionInfo { .. } => todo!(), - IPCStructData::LobbyServiceAccountList { .. } => 19, - } - } -} - #[binrw] #[brw(import(size: u32, encryption_key: Option<&[u8]>))] #[derive(Debug, Clone)]