From 850f6097d327599d42879c72d6b6c90a4b390dbe Mon Sep 17 00:00:00 2001 From: dank_meme01 Date: Tue, 21 Nov 2023 14:11:16 +0100 Subject: [PATCH] even more optimization crimes --- server/game/src/bytebufferext.rs | 84 ++++-------------- .../src/data/packets/client/connection.rs | 38 ++------- server/game/src/data/packets/client/game.rs | 55 ++++-------- server/game/src/data/packets/mod.rs | 48 +++++------ .../src/data/packets/server/connection.rs | 19 +---- server/game/src/data/packets/server/game.rs | 9 -- server/game/src/data/types/audio_frame.rs | 19 +++-- server/game/src/data/types/cocos.rs | 38 ++++----- server/game/src/data/types/crypto.rs | 19 ++--- server/game/src/data/types/gd.rs | 73 +++++++--------- server/game/src/server.rs | 12 +-- server/game/src/server_thread.rs | 85 ++++++++----------- 12 files changed, 177 insertions(+), 322 deletions(-) diff --git a/server/game/src/bytebufferext.rs b/server/game/src/bytebufferext.rs index 21960def..ffc73a27 100644 --- a/server/game/src/bytebufferext.rs +++ b/server/game/src/bytebufferext.rs @@ -1,7 +1,5 @@ -use std::io::Read; - use crate::data::types::cocos; -use anyhow::{anyhow, Result}; +use anyhow::Result; use bytebuffer::{ByteBuffer, ByteReader}; type ByteVec = Vec; @@ -10,28 +8,15 @@ pub trait Encodable { fn encode(&self, buf: &mut ByteBuffer); } -// empty is similar to default but default does silly things i think -pub trait Empty { - fn empty() -> Self +pub trait Decodable { + fn decode(buf: &mut ByteBuffer) -> Result + where + Self: Sized; + fn decode_from_reader(buf: &mut ByteReader) -> Result where Self: Sized; } -pub trait Decodable: Empty { - fn decode(&mut self, buf: &mut ByteBuffer) -> Result<()>; - fn decode_from_reader(&mut self, buf: &mut ByteReader) -> Result<()>; -} - -// FastDecodable is a more efficient Decodable that has no Empty requirement, -// so the struct is constructed with all the appropriate values immediately, -// instead of making an ::empty() variant and then filling in the values. -pub trait FastDecodable: Sized { - fn decode_fast(buf: &mut ByteBuffer) -> Result; - fn decode_fast_from_reader(buf: &mut ByteReader) -> Result; -} - -pub trait Serializable: Encodable + Decodable {} - macro_rules! encode_impl { ($packet_type:ty, $buf:ident, $self:ident, $encode:expr) => { impl crate::bytebufferext::Encodable for $packet_type { @@ -43,32 +28,19 @@ macro_rules! encode_impl { } macro_rules! decode_impl { - ($packet_type:ty, $buf:ident, $self:ident, $decode:expr) => { + ($packet_type:ty, $buf:ident, $decode:expr) => { impl crate::bytebufferext::Decodable for $packet_type { - fn decode(&mut $self, $buf: &mut bytebuffer::ByteBuffer) -> anyhow::Result<()> { + fn decode($buf: &mut bytebuffer::ByteBuffer) -> anyhow::Result { $decode } - fn decode_from_reader(&mut $self, $buf: &mut bytebuffer::ByteReader) -> anyhow::Result<()> { + fn decode_from_reader($buf: &mut bytebuffer::ByteReader) -> anyhow::Result { $decode } } }; } -macro_rules! empty_impl { - ($typ:ty, $empty:expr) => { - impl crate::bytebufferext::Empty for $typ { - fn empty() -> Self - where - Self: Sized, - { - $empty - } - } - }; -} - macro_rules! encode_unimpl { ($packet_type:ty) => { impl crate::bytebufferext::Encodable for $packet_type { @@ -85,14 +57,14 @@ macro_rules! encode_unimpl { macro_rules! decode_unimpl { ($packet_type:ty) => { impl crate::bytebufferext::Decodable for $packet_type { - fn decode(&mut self, _: &mut bytebuffer::ByteBuffer) -> anyhow::Result<()> { + fn decode(_: &mut bytebuffer::ByteBuffer) -> anyhow::Result { Err(anyhow::anyhow!( "decoding unimplemented for {}", stringify!($packet_type) )) } - fn decode_from_reader(&mut self, _: &mut bytebuffer::ByteReader) -> anyhow::Result<()> { + fn decode_from_reader(_: &mut bytebuffer::ByteReader) -> anyhow::Result { Err(anyhow::anyhow!( "decoding unimplemented for {}", stringify!($packet_type) @@ -101,9 +73,9 @@ macro_rules! decode_unimpl { } }; } + pub(crate) use decode_impl; pub(crate) use decode_unimpl; -pub(crate) use empty_impl; pub(crate) use encode_impl; pub(crate) use encode_unimpl; @@ -130,10 +102,8 @@ pub trait ByteBufferExtRead { fn read_bool(&mut self) -> Result; // read a byte vector, prefixed with 4 bytes indicating length fn read_byte_array(&mut self) -> Result; - fn read_bytes_into(&mut self, dest: &mut [u8]) -> Result<()>; fn read_value(&mut self) -> Result; - fn read_value_fast(&mut self) -> Result; fn read_optional_value(&mut self) -> Result>; fn read_value_vec(&mut self) -> Result>; @@ -193,7 +163,7 @@ impl ByteBufferExtWrite for ByteBuffer { } macro_rules! impl_extread { - ($decode_fn:ident, $fast_fn:ident) => { + ($decode_fn:ident) => { fn read_bool(&mut self) -> Result { Ok(self.read_u8()? == 1u8) } @@ -203,26 +173,8 @@ macro_rules! impl_extread { Ok(self.read_bytes(length)?) } - fn read_bytes_into(&mut self, dest: &mut [u8]) -> Result<()> { - self.flush_bits(); - - if self.get_rpos() + dest.len() > self.len() { - return Err(anyhow!("could not read enough bytes from buffer")); - } - - self.read_exact(dest)?; - - Ok(()) - } - fn read_value(&mut self) -> Result { - let mut value = T::empty(); - value.$decode_fn(self)?; - Ok(value) - } - - fn read_value_fast(&mut self) -> Result { - T::$fast_fn(self) + T::$decode_fn(self) } fn read_optional_value(&mut self) -> Result> { @@ -236,9 +188,7 @@ macro_rules! impl_extread { let mut out = Vec::new(); let length = self.read_u32()? as usize; for _ in 0..length { - let mut value = T::empty(); - value.$decode_fn(self)?; - out.push(value); + out.push(self.read_value()?); } Ok(out) @@ -259,9 +209,9 @@ macro_rules! impl_extread { } impl ByteBufferExtRead for ByteBuffer { - impl_extread!(decode, decode_fast); + impl_extread!(decode); } impl<'a> ByteBufferExtRead for ByteReader<'a> { - impl_extread!(decode_from_reader, decode_fast_from_reader); + impl_extread!(decode_from_reader); } diff --git a/server/game/src/data/packets/client/connection.rs b/server/game/src/data/packets/client/connection.rs index 265a998d..a9a5210d 100644 --- a/server/game/src/data/packets/client/connection.rs +++ b/server/game/src/data/packets/client/connection.rs @@ -8,14 +8,9 @@ packet!(PingPacket, 10000, false, { id: u32, }); -empty_impl!(PingPacket, Self { id: 0 }); - encode_unimpl!(PingPacket); -decode_impl!(PingPacket, buf, self, { - self.id = buf.read_u32()?; - Ok(()) -}); +decode_impl!(PingPacket, buf, Ok(Self { id: buf.read_u32()? })); /* CryptoHandshakeStartPacket - 10001 */ @@ -26,17 +21,10 @@ packet!(CryptoHandshakeStartPacket, 10001, false, { encode_unimpl!(CryptoHandshakeStartPacket); -empty_impl!(CryptoHandshakeStartPacket, { - Self { - protocol: 0, - key: CryptoPublicKey::empty(), - } -}); - -decode_impl!(CryptoHandshakeStartPacket, buf, self, { - self.protocol = buf.read_u16()?; - self.key = buf.read_value()?; - Ok(()) +decode_impl!(CryptoHandshakeStartPacket, buf, { + let protocol = buf.read_u16()?; + let key = buf.read_value()?; + Ok(Self { protocol, key }) }); /* KeepalivePacket - 10002 */ @@ -52,18 +40,10 @@ packet!(LoginPacket, 10003, true, { encode_unimpl!(LoginPacket); -empty_impl!( - LoginPacket, - Self { - account_id: 0, - token: "".to_string(), - } -); - -decode_impl!(LoginPacket, buf, self, { - self.account_id = buf.read_i32()?; - self.token = buf.read_string()?; - Ok(()) +decode_impl!(LoginPacket, buf, { + let account_id = buf.read_i32()?; + let token = buf.read_string()?; + Ok(Self { account_id, token }) }); /* DisconnectPacket - 10004 */ diff --git a/server/game/src/data/packets/client/game.rs b/server/game/src/data/packets/client/game.rs index becedec2..f885103c 100644 --- a/server/game/src/data/packets/client/game.rs +++ b/server/game/src/data/packets/client/game.rs @@ -12,18 +12,14 @@ packet!(SyncIconsPacket, 11000, false, { encode_unimpl!(SyncIconsPacket); -empty_impl!( +decode_impl!( SyncIconsPacket, - Self { - icons: PlayerIconData::default() - } + buf, + Ok(Self { + icons: buf.read_value()? + }) ); -decode_impl!(SyncIconsPacket, buf, self, { - self.icons = buf.read_value()?; - Ok(()) -}); - /* RequestProfilesPacket - 11001 */ packet!(RequestProfilesPacket, 11001, false, { @@ -32,15 +28,14 @@ packet!(RequestProfilesPacket, 11001, false, { encode_unimpl!(RequestProfilesPacket); -empty_impl!(RequestProfilesPacket, Self { ids: Vec::new() }); - -decode_impl!(RequestProfilesPacket, buf, self, { +decode_impl!(RequestProfilesPacket, buf, { let len = buf.read_u32()?; + let mut ids = Vec::new(); for _ in 0..len { - self.ids.push(buf.read_i32()?); + ids.push(buf.read_i32()?); } - Ok(()) + Ok(Self { ids }) }); /* LevelJoinPacket - 11002 */ @@ -51,11 +46,10 @@ packet!(LevelJoinPacket, 11002, false, { encode_unimpl!(LevelJoinPacket); -empty_impl!(LevelJoinPacket, Self { level_id: 0 }); - -decode_impl!(LevelJoinPacket, buf, self, { - self.level_id = buf.read_i32()?; - Ok(()) +decode_impl!(LevelJoinPacket, buf, { + Ok(Self { + level_id: buf.read_i32()?, + }) }); /* LevelLeavePacket - 11003 */ @@ -70,17 +64,7 @@ packet!(PlayerDataPacket, 11004, false, { encode_unimpl!(PlayerDataPacket); -empty_impl!( - PlayerDataPacket, - Self { - data: PlayerData::default() // :( - } -); - -decode_impl!(PlayerDataPacket, buf, self, { - self.data = buf.read_value_fast()?; - Ok(()) -}); +decode_impl!(PlayerDataPacket, buf, Ok(Self { data: buf.read_value()? })); /* VoicePacket - 11010 */ @@ -90,13 +74,4 @@ packet!(VoicePacket, 11010, true, { encode_unimpl!(VoicePacket); -empty_impl!(VoicePacket, { - Self { - data: EncodedAudioFrame::empty(), - } -}); - -decode_impl!(VoicePacket, buf, self, { - self.data = buf.read_value()?; - Ok(()) -}); +decode_impl!(VoicePacket, buf, Ok(Self { data: buf.read_value()? })); diff --git a/server/game/src/data/packets/mod.rs b/server/game/src/data/packets/mod.rs index d60c1e08..e724bba6 100644 --- a/server/game/src/data/packets/mod.rs +++ b/server/game/src/data/packets/mod.rs @@ -3,7 +3,7 @@ pub mod server; use std::any::Any; -use crate::bytebufferext::{Decodable, Empty, Encodable}; +use crate::bytebufferext::{Decodable, Encodable}; use self::client::*; @@ -33,10 +33,10 @@ macro_rules! packet { fn as_any(&self) -> &dyn std::any::Any { self } + } - impl crate::data::packets::PacketWithId for $packet_type { - const PACKET_ID: crate::data::packets::PacketId = $packet_id; - } + impl crate::data::packets::PacketWithId for $packet_type { + const PACKET_ID: crate::data::packets::PacketId = $packet_id; } }; ($packet_type:ident, $packet_id:expr, $encrypted:expr, { $($field:ident: $field_type:ty),* $(,)? }) => { @@ -71,8 +71,6 @@ macro_rules! empty_server_packet { encode_impl!($packet_type, _buf, self, {}); - empty_impl!($packet_type, Self {}); - decode_unimpl!($packet_type); }; } @@ -83,12 +81,12 @@ macro_rules! empty_client_packet { encode_unimpl!($packet_type); - empty_impl!($packet_type, Self {}); - - decode_impl!($packet_type, _buf, self, Ok(())); + decode_impl!($packet_type, _buf, Ok(Self {})); }; } +use anyhow::anyhow; +use bytebuffer::ByteReader; pub(crate) use empty_client_packet; pub(crate) use empty_server_packet; pub(crate) use packet; @@ -107,27 +105,27 @@ pub trait PacketWithId { pub const PACKET_HEADER_LEN: usize = std::mem::size_of::() + std::mem::size_of::(); macro_rules! mpacket { - ($typ:ty) => {{ - Some(Box::new(<$typ>::empty())) + ($typ:ty,$br:expr) => {{ + Ok(Box::new(<$typ>::decode_from_reader($br)?)) }}; } -pub fn match_packet(packet_id: PacketId) -> Option> { +pub fn match_packet(packet_id: PacketId, data: &mut ByteReader<'_>) -> anyhow::Result> { match packet_id { - PingPacket::PACKET_ID => mpacket!(PingPacket), - CryptoHandshakeStartPacket::PACKET_ID => mpacket!(CryptoHandshakeStartPacket), - KeepalivePacket::PACKET_ID => mpacket!(KeepalivePacket), - LoginPacket::PACKET_ID => mpacket!(LoginPacket), - DisconnectPacket::PACKET_ID => mpacket!(DisconnectPacket), + PingPacket::PACKET_ID => mpacket!(PingPacket, data), + CryptoHandshakeStartPacket::PACKET_ID => mpacket!(CryptoHandshakeStartPacket, data), + KeepalivePacket::PACKET_ID => mpacket!(KeepalivePacket, data), + LoginPacket::PACKET_ID => mpacket!(LoginPacket, data), + DisconnectPacket::PACKET_ID => mpacket!(DisconnectPacket, data), // game related - SyncIconsPacket::PACKET_ID => mpacket!(SyncIconsPacket), - RequestProfilesPacket::PACKET_ID => mpacket!(RequestProfilesPacket), - LevelJoinPacket::PACKET_ID => mpacket!(LevelJoinPacket), - LevelLeavePacket::PACKET_ID => mpacket!(LevelLeavePacket), - PlayerDataPacket::PACKET_ID => mpacket!(PlayerDataPacket), - - VoicePacket::PACKET_ID => mpacket!(VoicePacket), - _ => None, + SyncIconsPacket::PACKET_ID => mpacket!(SyncIconsPacket, data), + RequestProfilesPacket::PACKET_ID => mpacket!(RequestProfilesPacket, data), + LevelJoinPacket::PACKET_ID => mpacket!(LevelJoinPacket, data), + LevelLeavePacket::PACKET_ID => mpacket!(LevelLeavePacket, data), + PlayerDataPacket::PACKET_ID => mpacket!(PlayerDataPacket, data), + + VoicePacket::PACKET_ID => mpacket!(VoicePacket, data), + _ => Err(anyhow!("no matching packet in 'match_packet' with id {packet_id}")), } } diff --git a/server/game/src/data/packets/server/connection.rs b/server/game/src/data/packets/server/connection.rs index c45317aa..39324bd3 100644 --- a/server/game/src/data/packets/server/connection.rs +++ b/server/game/src/data/packets/server/connection.rs @@ -1,5 +1,5 @@ use crate::{ - bytebufferext::{decode_unimpl, empty_impl, encode_impl, ByteBufferExtWrite}, + bytebufferext::{decode_unimpl, encode_impl, ByteBufferExtWrite}, data::{ packets::{empty_server_packet, packet}, types::CryptoPublicKey, @@ -18,8 +18,6 @@ encode_impl!(PingResponsePacket, buf, self, { buf.write_u32(self.player_count); }); -empty_impl!(PingResponsePacket, Self { id: 0, player_count: 0 }); - decode_unimpl!(PingResponsePacket); /* CryptoHandshakeResponsePacket - 20001 */ @@ -32,13 +30,6 @@ encode_impl!(CryptoHandshakeResponsePacket, buf, self, { buf.write_value(&self.key); }); -empty_impl!( - CryptoHandshakeResponsePacket, - Self { - key: CryptoPublicKey::empty() - } -); - decode_unimpl!(CryptoHandshakeResponsePacket); /* KeepaliveResponsePacket - 20002 */ @@ -51,8 +42,6 @@ encode_impl!(KeepaliveResponsePacket, buf, self, { buf.write_u32(self.player_count); }); -empty_impl!(KeepaliveResponsePacket, Self { player_count: 0 }); - decode_unimpl!(KeepaliveResponsePacket); /* ServerDisconnectPacket - 20003 */ @@ -65,8 +54,6 @@ encode_impl!(ServerDisconnectPacket, buf, self, { buf.write_string(&self.message); }); -empty_impl!(ServerDisconnectPacket, Self { message: "".to_string() }); - decode_unimpl!(ServerDisconnectPacket); /* LoggedInPacket - 20004 */ @@ -83,8 +70,6 @@ encode_impl!(LoginFailedPacket, buf, self, { buf.write_string(&self.message); }); -empty_impl!(LoginFailedPacket, Self { message: "".to_string() }); - decode_unimpl!(LoginFailedPacket); /* ServerNoticePacket - 20006 */ @@ -98,6 +83,4 @@ encode_impl!(ServerNoticePacket, buf, self, { buf.write_string(&self.message); }); -empty_impl!(ServerNoticePacket, Self { message: "".to_string() }); - decode_unimpl!(ServerNoticePacket); diff --git a/server/game/src/data/packets/server/game.rs b/server/game/src/data/packets/server/game.rs index 15e2c475..bc9f4986 100644 --- a/server/game/src/data/packets/server/game.rs +++ b/server/game/src/data/packets/server/game.rs @@ -13,8 +13,6 @@ encode_impl!(PlayerProfilesPacket, buf, self, { buf.write_value_vec(&self.profiles); }); -empty_impl!(PlayerProfilesPacket, Self { profiles: Vec::new() }); - decode_unimpl!(PlayerProfilesPacket); /* LevelDataPacket - 21001 @@ -36,11 +34,4 @@ encode_impl!(VoiceBroadcastPacket, buf, self, { buf.write_value(&self.data); }); -empty_impl!(VoiceBroadcastPacket, { - Self { - player_id: 0, - data: EncodedAudioFrame::empty(), - } -}); - decode_unimpl!(VoiceBroadcastPacket); diff --git a/server/game/src/data/types/audio_frame.rs b/server/game/src/data/types/audio_frame.rs index 96def0ad..59434d44 100644 --- a/server/game/src/data/types/audio_frame.rs +++ b/server/game/src/data/types/audio_frame.rs @@ -1,4 +1,6 @@ -use crate::bytebufferext::{decode_impl, empty_impl, encode_impl, ByteBufferExtRead, ByteBufferExtWrite}; +use anyhow::bail; + +use crate::bytebufferext::{decode_impl, encode_impl, ByteBufferExtRead, ByteBufferExtWrite}; type EncodedOpusData = Vec; #[derive(Clone, Default)] @@ -14,13 +16,18 @@ encode_impl!(EncodedAudioFrame, buf, self, { } }); -empty_impl!(EncodedAudioFrame, Self::default()); - -decode_impl!(EncodedAudioFrame, buf, self, { +decode_impl!(EncodedAudioFrame, buf, { let frames = buf.read_u16()?; + if frames > 64 { + bail!("failed to decode EncodedAudioFrame, way too many frames ({frames})"); + } + + let mut opus_frames = Vec::with_capacity(frames as usize); + for _ in 0..frames { let frame = buf.read_byte_array()?; - self.opus_frames.push(frame); + opus_frames.push(frame); } - Ok(()) + + Ok(Self { opus_frames }) }); diff --git a/server/game/src/data/types/cocos.rs b/server/game/src/data/types/cocos.rs index 52fc74d3..0ff6c43a 100644 --- a/server/game/src/data/types/cocos.rs +++ b/server/game/src/data/types/cocos.rs @@ -1,6 +1,6 @@ use anyhow::bail; -use crate::bytebufferext::{decode_impl, empty_impl, encode_impl}; +use crate::bytebufferext::{decode_impl, encode_impl}; #[derive(Copy, Clone, Default)] pub struct Color3B { @@ -15,13 +15,11 @@ encode_impl!(Color3B, buf, self, { buf.write_u8(self.b); }); -empty_impl!(Color3B, Self::default()); - -decode_impl!(Color3B, buf, self, { - self.r = buf.read_u8()?; - self.g = buf.read_u8()?; - self.b = buf.read_u8()?; - Ok(()) +decode_impl!(Color3B, buf, { + let r = buf.read_u8()?; + let g = buf.read_u8()?; + let b = buf.read_u8()?; + Ok(Self { r, g, b }) }); impl TryFrom for Color3B { @@ -58,14 +56,12 @@ encode_impl!(Color4B, buf, self, { buf.write_u8(self.a); }); -empty_impl!(Color4B, Self::default()); - -decode_impl!(Color4B, buf, self, { - self.r = buf.read_u8()?; - self.g = buf.read_u8()?; - self.b = buf.read_u8()?; - self.a = buf.read_u8()?; - Ok(()) +decode_impl!(Color4B, buf, { + let r = buf.read_u8()?; + let g = buf.read_u8()?; + let b = buf.read_u8()?; + let a = buf.read_u8()?; + Ok(Self { r, g, b, a }) }); impl TryFrom for Color4B { @@ -103,10 +99,8 @@ encode_impl!(Point, buf, self, { buf.write_f32(self.y); }); -empty_impl!(Point, Self::default()); - -decode_impl!(Point, buf, self, { - self.x = buf.read_f32()?; - self.y = buf.read_f32()?; - Ok(()) +decode_impl!(Point, buf, { + let x = buf.read_f32()?; + let y = buf.read_f32()?; + Ok(Self { x, y }) }); diff --git a/server/game/src/data/types/crypto.rs b/server/game/src/data/types/crypto.rs index e24e5df5..21918f6d 100644 --- a/server/game/src/data/types/crypto.rs +++ b/server/game/src/data/types/crypto.rs @@ -1,3 +1,5 @@ +use std::io::Read; + use crypto_box::{PublicKey, KEY_SIZE}; use crate::bytebufferext::*; @@ -9,18 +11,11 @@ pub struct CryptoPublicKey { encode_impl!(CryptoPublicKey, buf, self, buf.write_bytes(self.pubkey.as_bytes())); -empty_impl!( - CryptoPublicKey, - Self { - pubkey: PublicKey::from_bytes([0u8; 32]) - } -); - -decode_impl!(CryptoPublicKey, buf, self, { +decode_impl!(CryptoPublicKey, buf, { let mut key = [0u8; KEY_SIZE]; - buf.read_bytes_into(&mut key)?; - - self.pubkey = PublicKey::from_bytes(key); + buf.read_exact(&mut key)?; - Ok(()) + Ok(Self { + pubkey: PublicKey::from_bytes(key), + }) }); diff --git a/server/game/src/data/types/gd.rs b/server/game/src/data/types/gd.rs index 5ca02cea..7a2aabbc 100644 --- a/server/game/src/data/types/gd.rs +++ b/server/game/src/data/types/gd.rs @@ -1,9 +1,6 @@ -use bytebuffer::{ByteBuffer, ByteReader}; use globed_shared::SpecialUser; -use crate::bytebufferext::{ - decode_impl, decode_unimpl, empty_impl, encode_impl, ByteBufferExtWrite, Encodable, FastDecodable, -}; +use crate::bytebufferext::{decode_impl, decode_unimpl, encode_impl, ByteBufferExtWrite}; use super::Color3B; @@ -57,22 +54,33 @@ encode_impl!(PlayerIconData, buf, self, { buf.write_i32(self.color2); }); -empty_impl!(PlayerIconData, Self::default()); - -decode_impl!(PlayerIconData, buf, self, { - self.cube = buf.read_i32()?; - self.ship = buf.read_i32()?; - self.ball = buf.read_i32()?; - self.ufo = buf.read_i32()?; - self.wave = buf.read_i32()?; - self.robot = buf.read_i32()?; - self.spider = buf.read_i32()?; - self.swing = buf.read_i32()?; - self.jetpack = buf.read_i32()?; - self.death_effect = buf.read_i32()?; - self.color1 = buf.read_i32()?; - self.color2 = buf.read_i32()?; - Ok(()) +decode_impl!(PlayerIconData, buf, { + let cube = buf.read_i32()?; + let ship = buf.read_i32()?; + let ball = buf.read_i32()?; + let ufo = buf.read_i32()?; + let wave = buf.read_i32()?; + let robot = buf.read_i32()?; + let spider = buf.read_i32()?; + let swing = buf.read_i32()?; + let jetpack = buf.read_i32()?; + let death_effect = buf.read_i32()?; + let color1 = buf.read_i32()?; + let color2 = buf.read_i32()?; + Ok(Self { + cube, + ship, + ball, + ufo, + wave, + robot, + spider, + swing, + jetpack, + death_effect, + color1, + color2, + }) }); impl PlayerIconData { @@ -101,8 +109,6 @@ encode_impl!(SpecialUserData, buf, self, { buf.write_color3(self.name_color); }); -empty_impl!(SpecialUserData, Self::default()); - decode_unimpl!(SpecialUserData); impl TryFrom for SpecialUserData { @@ -131,8 +137,6 @@ encode_impl!(PlayerAccountData, buf, self, { buf.write_optional_value(self.special_user_data.as_ref()); }); -empty_impl!(PlayerAccountData, Self::default()); - decode_unimpl!(PlayerAccountData); /* PlayerData */ @@ -142,16 +146,7 @@ pub struct PlayerData {} encode_impl!(PlayerData, _buf, self, {}); -impl FastDecodable for PlayerData { - fn decode_fast(buf: &mut ByteBuffer) -> anyhow::Result { - let mut br = ByteReader::from_bytes(buf.as_bytes()); - Self::decode_fast_from_reader(&mut br) - } - - fn decode_fast_from_reader(_buf: &mut ByteReader) -> anyhow::Result { - Ok(Self {}) - } -} +decode_impl!(PlayerData, _buf, Ok(Self {})); impl PlayerData { const fn encoded_size() -> usize { @@ -167,12 +162,10 @@ pub struct AssociatedPlayerData { pub data: PlayerData, } -impl Encodable for AssociatedPlayerData { - fn encode(&self, buf: &mut ByteBuffer) { - buf.write_i32(self.account_id); - buf.write_value(&self.data); - } -} +encode_impl!(AssociatedPlayerData, buf, self, { + buf.write_i32(self.account_id); + buf.write_value(&self.data); +}); impl AssociatedPlayerData { pub const fn encoded_size() -> usize { diff --git a/server/game/src/server.rs b/server/game/src/server.rs index 2d3029a3..c6f5d896 100644 --- a/server/game/src/server.rs +++ b/server/game/src/server.rs @@ -116,8 +116,8 @@ impl GameServer { let thread = self.threads.read().get(&peer).cloned(); - if let Some(thread) = thread { - thread.send_message(ServerThreadMessage::Packet(buf[..len].to_vec())).await?; + let thread = if let Some(thread) = thread { + thread } else { let thread = Arc::new(GameServerThread::new(peer, self)); let thread_cl = thread.clone(); @@ -137,11 +137,13 @@ impl GameServer { self.post_disconnect_cleanup(thread).await; }); + self.threads.write().insert(peer, thread_cl.clone()); thread_cl - .send_message(ServerThreadMessage::Packet(buf[..len].to_vec())) - .await?; + }; - self.threads.write().insert(peer, thread_cl); + let packet = thread.parse_packet(&buf[..len]).map_err(|e| anyhow!("parsing failed: {e}"))?; + if let Some(packet) = packet { + thread.send_message(ServerThreadMessage::Packet(packet)).await?; } Ok(()) diff --git a/server/game/src/server_thread.rs b/server/game/src/server_thread.rs index 139dcba6..aee2cd61 100644 --- a/server/game/src/server_thread.rs +++ b/server/game/src/server_thread.rs @@ -20,7 +20,7 @@ use tokio::sync::{ }; use crate::{ - bytebufferext::{ByteBufferExt, ByteBufferExtWrite}, + bytebufferext::{ByteBufferExt, ByteBufferExtRead, ByteBufferExtWrite}, data::{ packets::{client::*, match_packet, server::*, Packet, PacketWithId, PACKET_HEADER_LEN}, types::{AssociatedPlayerData, CryptoPublicKey, PlayerAccountData}, @@ -29,7 +29,7 @@ use crate::{ }; pub enum ServerThreadMessage { - Packet(Vec), + Packet(Box), BroadcastVoice(VoiceBroadcastPacket), } @@ -145,25 +145,13 @@ impl GameServerThread { self.awaiting_termination.store(true, Ordering::Relaxed); } - /* private utilities */ - - async fn send_packet(&self, packet: &impl Packet) -> anyhow::Result<()> { - let serialized = self.serialize_packet(packet)?; - self.send_buffer(serialized.as_bytes()).await - } - - async fn send_buffer(&self, buffer: &[u8]) -> anyhow::Result<()> { - self.game_server.socket.send_to(buffer, self.peer).await?; - Ok(()) - } - - fn parse_packet(&self, message: &[u8]) -> anyhow::Result>> { + pub fn parse_packet(&self, message: &[u8]) -> anyhow::Result>> { gs_require!(message.len() >= PACKET_HEADER_LEN, "packet is missing a header"); let mut data = ByteReader::from_bytes(message); let packet_id = data.read_u16()?; - let encrypted = data.read_u8()? != 0u8; + let encrypted = data.read_bool()?; // for optimization, reject the voice packet immediately if the player is blocked from vc if packet_id == VoicePacket::PACKET_ID { @@ -174,40 +162,44 @@ impl GameServerThread { } } - let packet = match_packet(packet_id); - gs_require!( - packet.is_some(), - "packet was sent with an invalid id or the handler doesn't exist: {packet_id}" - ); + let cleartext_vec; + if encrypted { + let cbox = self.crypto_box.lock(); - let mut packet = packet.unwrap(); - if packet.get_encrypted() && !encrypted { - gs_require!(false, "client sent a cleartext packet when expected an encrypted one"); - } + gs_require!( + cbox.is_some(), + "attempting to decode an encrypted packet when no cryptobox was initialized" + ); + + let encrypted_data = data.read_bytes(data.len() - data.get_rpos())?; + let nonce = &encrypted_data[..24]; + let rest = &encrypted_data[24..]; + + let cbox = cbox.as_ref().unwrap(); + cleartext_vec = cbox.decrypt(nonce.into(), rest)?; - if !encrypted { - packet.decode_from_reader(&mut data)?; - return Ok(Some(packet)); + data = ByteReader::from_bytes(&cleartext_vec); } - let cbox = self.crypto_box.lock(); + let packet = match_packet(packet_id, &mut data)?; - gs_require!( - cbox.is_some(), - "attempting to decode an encrypted packet when no cryptobox was initialized" - ); + if packet.get_encrypted() && !encrypted { + gs_require!(false, "client sent a cleartext packet when expected an encrypted one"); + } - let encrypted_data = data.read_bytes(data.len() - data.get_rpos())?; - let nonce = &encrypted_data[..24]; - let rest = &encrypted_data[24..]; + Ok(Some(packet)) + } - let cbox = cbox.as_ref().unwrap(); - let cleartext = cbox.decrypt(nonce.into(), rest)?; + /* private utilities */ - let mut packetbuf = ByteReader::from_bytes(&cleartext); - packet.decode_from_reader(&mut packetbuf)?; + async fn send_packet(&self, packet: &impl Packet) -> anyhow::Result<()> { + let serialized = self.serialize_packet(packet)?; + self.send_buffer(serialized.as_bytes()).await + } - Ok(Some(packet)) + async fn send_buffer(&self, buffer: &[u8]) -> anyhow::Result<()> { + self.game_server.socket.send_to(buffer, self.peer).await?; + Ok(()) } fn serialize_packet(&self, packet: &impl Packet) -> anyhow::Result { @@ -244,13 +236,9 @@ impl GameServerThread { async fn handle_message(&self, message: ServerThreadMessage) -> anyhow::Result<()> { match message { - ServerThreadMessage::Packet(message) => match self.parse_packet(&message) { - Ok(Some(packet)) => match self.handle_packet(&*packet).await { - Ok(_) => {} - Err(err) => return Err(anyhow!("failed to handle packet: {}", err.to_string())), - }, - Ok(None) => {} - Err(err) => return Err(anyhow!("failed to parse packet: {}", err.to_string())), + ServerThreadMessage::Packet(packet) => match self.handle_packet(&*packet).await { + Ok(_) => {} + Err(err) => return Err(anyhow!("failed to handle packet: {}", err.to_string())), }, ServerThreadMessage::BroadcastVoice(voice_packet) => match self.send_packet(&voice_packet).await { @@ -422,7 +410,6 @@ impl GameServerThread { }); /* game related */ - gs_handler!(self, handle_sync_icons, SyncIconsPacket, packet, { gs_needauth!(self);