- add: utils library

- add: packet-service to handle game client packets
- fix: health check for database-service
- fix: health check for auth-service
This commit is contained in:
2024-12-09 23:10:26 -05:00
parent 20e86dd117
commit e5c961d1b4
25 changed files with 1176 additions and 120 deletions

View File

@@ -1,31 +1,103 @@
use serde::{Serialize, Deserialize};
use bincode::{Encode, Decode};
use std::error::Error;
use tracing::debug;
use tokio::io::AsyncWriteExt;
use tokio::net::TcpStream;
use tracing::{debug, error};
use crate::packet_type::PacketType;
#[derive(Debug, Serialize, Deserialize)]
#[derive(Debug)]
pub struct Packet {
pub packet_size: u16,
pub packet_type: u16,
pub packet_type: PacketType,
pub packet_crc: u16,
pub payload: Vec<u8>,
}
pub trait PacketPayload: Encode + Decode {
fn encode(&self) -> Result<Vec<u8>, Box<dyn std::error::Error + Send + Sync>> {
let config = bincode::config::standard()
.with_fixed_int_encoding();
Ok(bincode::encode_to_vec(self, config)?)
}
fn decode(data: &[u8]) -> Result<Self, Box<dyn std::error::Error + Send + Sync>>
where
Self: Sized,
{
let config = bincode::config::standard()
.with_fixed_int_encoding();
Ok(bincode::decode_from_slice(data, config)?.0)
}
}
impl Packet {
pub fn parse(data: &[u8]) -> Result<Self, Box<dyn Error>> {
pub fn new<T: PacketPayload>(packet_type: PacketType, payload: &T) -> Result<Self, Box<dyn Error + Send + Sync>> {
let encoded_payload = <T as PacketPayload>::encode(payload)?;
let packet_size = (6 + encoded_payload.len()) as u16;
// let packet_crc = crc::crc16::checksum_x25(&encoded_payload);
let packet_crc = 0;
Ok(Self {
packet_size,
packet_type,
packet_crc,
payload: encoded_payload,
})
}
pub fn from_raw(data: &[u8]) -> Result<Self, Box<dyn Error + Send + Sync>> {
if data.len() < 6 {
return Err("Invalid packet: Too short".into());
}
let packet_size = u16::from_be_bytes(data[0..2].try_into()?);
let packet_type = u16::from_be_bytes(data[2..4].try_into()?);
let packet_crc = u16::from_be_bytes(data[4..6].try_into()?);
// Extract packet fields
let packet_size = u16::from_le_bytes(data[0..2].try_into()?);
let raw_packet_type = u16::from_le_bytes(data[2..4].try_into()?);
let packet_crc = u16::from_le_bytes(data[4..6].try_into()?);
// Validate the size
if packet_size as usize != data.len() {
error!("Invalid packet: Size mismatch, expected: {}, actual: {}", packet_size, data.len());
return Err("Invalid packet: Size mismatch".into());
}
debug!("size: {:#X}, raw_type: {:#X}, crc: {:#X}", packet_size, raw_packet_type, packet_crc);
// Convert raw packet type into `PacketType` enum
let packet_type = PacketType::try_from(raw_packet_type)?;
// Extract the payload
let payload = data[6..].to_vec();
debug!("Packet Size: {}", packet_size);
debug!("Packet Type: {}", packet_type);
debug!("Packet CRC: {}", packet_crc);
debug!("Payload: {:?}", String::from_utf8(payload.clone())?);
Ok(Packet { packet_size, packet_type, packet_crc, payload })
Ok(Self {
packet_size,
packet_type,
packet_crc,
payload,
})
}
/// Serialize the `Packet` back to raw bytes
pub fn to_raw(&self) -> Vec<u8> {
let mut raw = Vec::with_capacity(self.packet_size as usize);
// Serialize fields
raw.extend(&self.packet_size.to_le_bytes());
raw.extend(&(self.packet_type as u16).to_le_bytes());
raw.extend(&self.packet_crc.to_le_bytes());
raw.extend(&self.payload);
raw
}
pub fn parse<T: PacketPayload>(&self) -> Result<T, Box<dyn Error + Send + Sync>> {
<T as PacketPayload>::decode(&self.payload)
}
}
pub async fn send_packet(stream: &mut TcpStream, packet: &Packet) -> Result<(), std::io::Error> {
let data = packet.to_raw();
debug!("Sending data: {:?}", data);
stream.write_all(&data).await?;
Ok(())
}