From dae20a1e0cff67a7756c51370aa7f5a9ce37fe66 Mon Sep 17 00:00:00 2001 From: Joshua Goins Date: Mon, 17 Mar 2025 17:12:40 -0400 Subject: [PATCH] Rename IpcSegmentTrait to ReadWriteIpcSegment, add docs This also adds a default calc_size() implementation so client packets don't have to implement it. --- src/lobby/ipc/mod.rs | 10 +++------- src/packet/compression.rs | 4 ++-- src/packet/encryption.rs | 6 +++--- src/packet/ipc.rs | 9 ++++++--- src/packet/mod.rs | 2 +- src/packet/packet.rs | 18 ++++++++++-------- src/world/ipc/mod.rs | 10 +++------- 7 files changed, 28 insertions(+), 31 deletions(-) diff --git a/src/lobby/ipc/mod.rs b/src/lobby/ipc/mod.rs index c6d74c5..aede873 100644 --- a/src/lobby/ipc/mod.rs +++ b/src/lobby/ipc/mod.rs @@ -16,16 +16,12 @@ pub use service_account_list::{LobbyServiceAccountList, ServiceAccount}; use crate::{ common::{read_string, write_string}, - packet::{IpcSegment, IpcSegmentTrait}, + packet::{IpcSegment, ReadWriteIpcSegment}, }; pub type ClientLobbyIpcSegment = IpcSegment; -impl IpcSegmentTrait for ClientLobbyIpcSegment { - fn calc_size(&self) -> u32 { - todo!() - } -} +impl ReadWriteIpcSegment for ClientLobbyIpcSegment {} // TODO: make generic impl Default for ClientLobbyIpcSegment { @@ -47,7 +43,7 @@ impl Default for ClientLobbyIpcSegment { pub type ServerLobbyIpcSegment = IpcSegment; -impl IpcSegmentTrait for ServerLobbyIpcSegment { +impl ReadWriteIpcSegment for ServerLobbyIpcSegment { fn calc_size(&self) -> u32 { // 16 is the size of the IPC header 16 + match self.op_code { diff --git a/src/packet/compression.rs b/src/packet/compression.rs index 79c0d02..4a94d74 100644 --- a/src/packet/compression.rs +++ b/src/packet/compression.rs @@ -8,7 +8,7 @@ use crate::{ packet::{PacketHeader, PacketSegment}, }; -use super::IpcSegmentTrait; +use super::ReadWriteIpcSegment; #[binrw] #[brw(repr = u8)] @@ -19,7 +19,7 @@ pub enum CompressionType { } #[binrw::parser(reader, endian)] -pub(crate) fn decompress( +pub(crate) fn decompress( oodle: &mut FFXIVOodle, header: &PacketHeader, encryption_key: Option<&[u8]>, diff --git a/src/packet/encryption.rs b/src/packet/encryption.rs index 2403d09..8164dd5 100644 --- a/src/packet/encryption.rs +++ b/src/packet/encryption.rs @@ -4,7 +4,7 @@ use binrw::BinResult; use crate::blowfish::Blowfish; -use super::IpcSegmentTrait; +use super::ReadWriteIpcSegment; const GAME_VERSION: u16 = 7000; @@ -19,7 +19,7 @@ pub fn generate_encryption_key(key: &[u8], phrase: &str) -> [u8; 16] { } #[binrw::parser(reader, endian)] -pub(crate) fn decrypt( +pub(crate) fn decrypt( size: u32, encryption_key: Option<&[u8]>, ) -> BinResult { @@ -42,7 +42,7 @@ pub(crate) fn decrypt( } #[binrw::writer(writer, endian)] -pub(crate) fn encrypt( +pub(crate) fn encrypt( value: &T, size: u32, encryption_key: Option<&[u8]>, diff --git a/src/packet/ipc.rs b/src/packet/ipc.rs index 0b3793e..d1c6025 100644 --- a/src/packet/ipc.rs +++ b/src/packet/ipc.rs @@ -1,11 +1,14 @@ use binrw::{BinRead, BinWrite, binrw}; -pub trait IpcSegmentTrait: +/// 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 = ()> + for<'a> BinWrite = ()> + std::fmt::Debug + 'static { /// Calculate the size of this Ipc segment *including* the 16 byte header. - /// When implementing this, please use the size as seen in retail. - fn calc_size(&self) -> u32; + /// When implementing this, please use the size seen in retail instead of guessing. + fn calc_size(&self) -> u32 { + unimplemented!() + } } /// An IPC packet segment. diff --git a/src/packet/mod.rs b/src/packet/mod.rs index 0906b83..dedb8cd 100644 --- a/src/packet/mod.rs +++ b/src/packet/mod.rs @@ -12,4 +12,4 @@ mod encryption; pub use encryption::generate_encryption_key; mod ipc; -pub use ipc::{IpcSegment, IpcSegmentTrait}; +pub use ipc::{IpcSegment, ReadWriteIpcSegment}; diff --git a/src/packet/packet.rs b/src/packet/packet.rs index 9faa0e1..31775c3 100644 --- a/src/packet/packet.rs +++ b/src/packet/packet.rs @@ -9,7 +9,9 @@ use tokio::{io::AsyncWriteExt, net::TcpStream}; use crate::{common::read_string, oodle::FFXIVOodle, packet::encryption::decrypt}; -use super::{CompressionType, compression::decompress, encryption::encrypt, ipc::IpcSegmentTrait}; +use super::{ + CompressionType, compression::decompress, encryption::encrypt, ipc::ReadWriteIpcSegment, +}; #[binrw] #[brw(repr = u16)] @@ -24,7 +26,7 @@ pub enum ConnectionType { #[binrw] #[brw(import(size: u32, encryption_key: Option<&[u8]>))] #[derive(Debug, Clone)] -pub enum SegmentType { +pub enum SegmentType { // Client->Server Packets #[brw(magic = 0x1u32)] InitializeSession { @@ -89,7 +91,7 @@ pub struct PacketHeader { #[binrw] #[brw(import(encryption_key: Option<&[u8]>))] #[derive(Debug, Clone)] -pub struct PacketSegment { +pub struct PacketSegment { #[bw(calc = self.calc_size())] pub size: u32, pub source_actor: u32, @@ -98,7 +100,7 @@ pub struct PacketSegment { pub segment_type: SegmentType, } -impl PacketSegment { +impl PacketSegment { fn calc_size(&self) -> u32 { let header = std::mem::size_of::() * 4; header as u32 @@ -117,7 +119,7 @@ impl PacketSegment { #[binrw] #[brw(import(oodle: &mut FFXIVOodle, encryption_key: Option<&[u8]>))] #[derive(Debug)] -struct Packet { +struct Packet { header: PacketHeader, #[bw(args(encryption_key))] #[br(parse_with = decompress, args(oodle, &header, encryption_key,))] @@ -129,7 +131,7 @@ fn dump(msg: &str, data: &[u8]) { panic!("{msg} Dumped to packet.bin."); } -pub async fn send_packet( +pub async fn send_packet( socket: &mut TcpStream, segments: &[PacketSegment], state: &mut PacketState, @@ -201,7 +203,7 @@ pub struct PacketState { pub clientbound_oodle: FFXIVOodle, } -pub async fn parse_packet( +pub async fn parse_packet( data: &[u8], state: &mut PacketState, ) -> (Vec>, ConnectionType) { @@ -224,7 +226,7 @@ pub async fn parse_packet( } } -pub async fn send_keep_alive( +pub async fn send_keep_alive( socket: &mut TcpStream, state: &mut PacketState, id: u32, diff --git a/src/world/ipc/mod.rs b/src/world/ipc/mod.rs index a2d9adf..3cfc755 100644 --- a/src/world/ipc/mod.rs +++ b/src/world/ipc/mod.rs @@ -37,15 +37,11 @@ pub use init_zone::InitZone; use crate::common::read_string; use crate::common::write_string; use crate::packet::IpcSegment; -use crate::packet::IpcSegmentTrait; +use crate::packet::ReadWriteIpcSegment; pub type ClientZoneIpcSegment = IpcSegment; -impl IpcSegmentTrait for ClientZoneIpcSegment { - fn calc_size(&self) -> u32 { - todo!() - } -} +impl ReadWriteIpcSegment for ClientZoneIpcSegment {} // TODO: make generic impl Default for ClientZoneIpcSegment { @@ -63,7 +59,7 @@ impl Default for ClientZoneIpcSegment { pub type ServerZoneIpcSegment = IpcSegment; -impl IpcSegmentTrait for ServerZoneIpcSegment { +impl ReadWriteIpcSegment for ServerZoneIpcSegment { fn calc_size(&self) -> u32 { // 16 is the size of the IPC header 16 + match self.op_code {