1
Fork 0
mirror of https://github.com/redstrate/Kawari.git synced 2025-04-25 16:27:46 +00:00

Rename IpcSegmentTrait to ReadWriteIpcSegment, add docs

This also adds a default calc_size() implementation so client packets don't have
to implement it.
This commit is contained in:
Joshua Goins 2025-03-17 17:12:40 -04:00
parent ee1b79ee56
commit dae20a1e0c
7 changed files with 28 additions and 31 deletions

View file

@ -16,16 +16,12 @@ pub use service_account_list::{LobbyServiceAccountList, ServiceAccount};
use crate::{ use crate::{
common::{read_string, write_string}, common::{read_string, write_string},
packet::{IpcSegment, IpcSegmentTrait}, packet::{IpcSegment, ReadWriteIpcSegment},
}; };
pub type ClientLobbyIpcSegment = IpcSegment<ClientLobbyIpcType, ClientLobbyIpcData>; pub type ClientLobbyIpcSegment = IpcSegment<ClientLobbyIpcType, ClientLobbyIpcData>;
impl IpcSegmentTrait for ClientLobbyIpcSegment { impl ReadWriteIpcSegment for ClientLobbyIpcSegment {}
fn calc_size(&self) -> u32 {
todo!()
}
}
// TODO: make generic // TODO: make generic
impl Default for ClientLobbyIpcSegment { impl Default for ClientLobbyIpcSegment {
@ -47,7 +43,7 @@ impl Default for ClientLobbyIpcSegment {
pub type ServerLobbyIpcSegment = IpcSegment<ServerLobbyIpcType, ServerLobbyIpcData>; pub type ServerLobbyIpcSegment = IpcSegment<ServerLobbyIpcType, ServerLobbyIpcData>;
impl IpcSegmentTrait for ServerLobbyIpcSegment { impl ReadWriteIpcSegment for ServerLobbyIpcSegment {
fn calc_size(&self) -> u32 { fn calc_size(&self) -> u32 {
// 16 is the size of the IPC header // 16 is the size of the IPC header
16 + match self.op_code { 16 + match self.op_code {

View file

@ -8,7 +8,7 @@ use crate::{
packet::{PacketHeader, PacketSegment}, packet::{PacketHeader, PacketSegment},
}; };
use super::IpcSegmentTrait; use super::ReadWriteIpcSegment;
#[binrw] #[binrw]
#[brw(repr = u8)] #[brw(repr = u8)]
@ -19,7 +19,7 @@ pub enum CompressionType {
} }
#[binrw::parser(reader, endian)] #[binrw::parser(reader, endian)]
pub(crate) fn decompress<T: IpcSegmentTrait>( pub(crate) fn decompress<T: ReadWriteIpcSegment>(
oodle: &mut FFXIVOodle, oodle: &mut FFXIVOodle,
header: &PacketHeader, header: &PacketHeader,
encryption_key: Option<&[u8]>, encryption_key: Option<&[u8]>,

View file

@ -4,7 +4,7 @@ use binrw::BinResult;
use crate::blowfish::Blowfish; use crate::blowfish::Blowfish;
use super::IpcSegmentTrait; use super::ReadWriteIpcSegment;
const GAME_VERSION: u16 = 7000; const GAME_VERSION: u16 = 7000;
@ -19,7 +19,7 @@ pub fn generate_encryption_key(key: &[u8], phrase: &str) -> [u8; 16] {
} }
#[binrw::parser(reader, endian)] #[binrw::parser(reader, endian)]
pub(crate) fn decrypt<T: IpcSegmentTrait>( pub(crate) fn decrypt<T: ReadWriteIpcSegment>(
size: u32, size: u32,
encryption_key: Option<&[u8]>, encryption_key: Option<&[u8]>,
) -> BinResult<T> { ) -> BinResult<T> {
@ -42,7 +42,7 @@ pub(crate) fn decrypt<T: IpcSegmentTrait>(
} }
#[binrw::writer(writer, endian)] #[binrw::writer(writer, endian)]
pub(crate) fn encrypt<T: IpcSegmentTrait>( pub(crate) fn encrypt<T: ReadWriteIpcSegment>(
value: &T, value: &T,
size: u32, size: u32,
encryption_key: Option<&[u8]>, encryption_key: Option<&[u8]>,

View file

@ -1,11 +1,14 @@
use binrw::{BinRead, BinWrite, binrw}; 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<Args<'a> = ()> + for<'a> BinWrite<Args<'a> = ()> + std::fmt::Debug + 'static for<'a> BinRead<Args<'a> = ()> + 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 as seen in retail. /// When implementing this, please use the size seen in retail instead of guessing.
fn calc_size(&self) -> u32; fn calc_size(&self) -> u32 {
unimplemented!()
}
} }
/// An IPC packet segment. /// An IPC packet segment.

View file

@ -12,4 +12,4 @@ mod encryption;
pub use encryption::generate_encryption_key; pub use encryption::generate_encryption_key;
mod ipc; mod ipc;
pub use ipc::{IpcSegment, IpcSegmentTrait}; pub use ipc::{IpcSegment, ReadWriteIpcSegment};

View file

@ -9,7 +9,9 @@ use tokio::{io::AsyncWriteExt, net::TcpStream};
use crate::{common::read_string, oodle::FFXIVOodle, packet::encryption::decrypt}; 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] #[binrw]
#[brw(repr = u16)] #[brw(repr = u16)]
@ -24,7 +26,7 @@ pub enum ConnectionType {
#[binrw] #[binrw]
#[brw(import(size: u32, encryption_key: Option<&[u8]>))] #[brw(import(size: u32, encryption_key: Option<&[u8]>))]
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum SegmentType<T: IpcSegmentTrait> { pub enum SegmentType<T: ReadWriteIpcSegment> {
// Client->Server Packets // Client->Server Packets
#[brw(magic = 0x1u32)] #[brw(magic = 0x1u32)]
InitializeSession { InitializeSession {
@ -89,7 +91,7 @@ pub struct PacketHeader {
#[binrw] #[binrw]
#[brw(import(encryption_key: Option<&[u8]>))] #[brw(import(encryption_key: Option<&[u8]>))]
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct PacketSegment<T: IpcSegmentTrait> { pub struct PacketSegment<T: ReadWriteIpcSegment> {
#[bw(calc = self.calc_size())] #[bw(calc = self.calc_size())]
pub size: u32, pub size: u32,
pub source_actor: u32, pub source_actor: u32,
@ -98,7 +100,7 @@ pub struct PacketSegment<T: IpcSegmentTrait> {
pub segment_type: SegmentType<T>, pub segment_type: SegmentType<T>,
} }
impl<T: IpcSegmentTrait> PacketSegment<T> { impl<T: ReadWriteIpcSegment> PacketSegment<T> {
fn calc_size(&self) -> u32 { fn calc_size(&self) -> u32 {
let header = std::mem::size_of::<u32>() * 4; let header = std::mem::size_of::<u32>() * 4;
header as u32 header as u32
@ -117,7 +119,7 @@ impl<T: IpcSegmentTrait> PacketSegment<T> {
#[binrw] #[binrw]
#[brw(import(oodle: &mut FFXIVOodle, encryption_key: Option<&[u8]>))] #[brw(import(oodle: &mut FFXIVOodle, encryption_key: Option<&[u8]>))]
#[derive(Debug)] #[derive(Debug)]
struct Packet<T: IpcSegmentTrait> { struct Packet<T: ReadWriteIpcSegment> {
header: PacketHeader, header: PacketHeader,
#[bw(args(encryption_key))] #[bw(args(encryption_key))]
#[br(parse_with = decompress, args(oodle, &header, 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."); panic!("{msg} Dumped to packet.bin.");
} }
pub async fn send_packet<T: IpcSegmentTrait>( pub async fn send_packet<T: ReadWriteIpcSegment>(
socket: &mut TcpStream, socket: &mut TcpStream,
segments: &[PacketSegment<T>], segments: &[PacketSegment<T>],
state: &mut PacketState, state: &mut PacketState,
@ -201,7 +203,7 @@ pub struct PacketState {
pub clientbound_oodle: FFXIVOodle, pub clientbound_oodle: FFXIVOodle,
} }
pub async fn parse_packet<T: IpcSegmentTrait>( pub async fn parse_packet<T: ReadWriteIpcSegment>(
data: &[u8], data: &[u8],
state: &mut PacketState, state: &mut PacketState,
) -> (Vec<PacketSegment<T>>, ConnectionType) { ) -> (Vec<PacketSegment<T>>, ConnectionType) {
@ -224,7 +226,7 @@ pub async fn parse_packet<T: IpcSegmentTrait>(
} }
} }
pub async fn send_keep_alive<T: IpcSegmentTrait>( pub async fn send_keep_alive<T: ReadWriteIpcSegment>(
socket: &mut TcpStream, socket: &mut TcpStream,
state: &mut PacketState, state: &mut PacketState,
id: u32, id: u32,

View file

@ -37,15 +37,11 @@ pub use init_zone::InitZone;
use crate::common::read_string; use crate::common::read_string;
use crate::common::write_string; use crate::common::write_string;
use crate::packet::IpcSegment; use crate::packet::IpcSegment;
use crate::packet::IpcSegmentTrait; use crate::packet::ReadWriteIpcSegment;
pub type ClientZoneIpcSegment = IpcSegment<ClientZoneIpcType, ClientZoneIpcData>; pub type ClientZoneIpcSegment = IpcSegment<ClientZoneIpcType, ClientZoneIpcData>;
impl IpcSegmentTrait for ClientZoneIpcSegment { impl ReadWriteIpcSegment for ClientZoneIpcSegment {}
fn calc_size(&self) -> u32 {
todo!()
}
}
// TODO: make generic // TODO: make generic
impl Default for ClientZoneIpcSegment { impl Default for ClientZoneIpcSegment {
@ -63,7 +59,7 @@ impl Default for ClientZoneIpcSegment {
pub type ServerZoneIpcSegment = IpcSegment<ServerZoneIpcType, ServerZoneIpcData>; pub type ServerZoneIpcSegment = IpcSegment<ServerZoneIpcType, ServerZoneIpcData>;
impl IpcSegmentTrait for ServerZoneIpcSegment { impl ReadWriteIpcSegment for ServerZoneIpcSegment {
fn calc_size(&self) -> u32 { fn calc_size(&self) -> u32 {
// 16 is the size of the IPC header // 16 is the size of the IPC header
16 + match self.op_code { 16 + match self.op_code {