pub trait Packet: Sized {
fn packet_type(&self) -> PacketType;
fn header(&self) -> PacketHeader;
}
#[repr(u8)]
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
pub enum PacketType {
#[default]
Default = 0,
ConnectionRequest = 1,
Challenge,
ChallengeResponse,
Data,
Disconnect,
}
#[repr(C)]
#[derive(PartialEq, Eq, Clone, Copy, Debug, Default)]
pub struct PacketHeader {
pub protocol_id: [u8; 4],
pub r#type: PacketType,
}
impl PacketHeader {
pub fn new(r#type: PacketType) -> Self {
Self {
protocol_id: *b"BETP",
r#type,
}
}
pub fn get_protocol_id(&self) -> [u8; 4] {
self.protocol_id
}
pub fn get_type(&self) -> PacketType {
self.r#type
}
}
#[repr(C)]
#[derive(PartialEq, Eq, Debug)]
pub struct ConnectionRequestPacket {
header: PacketHeader,
client_salt: u64,
}
impl ConnectionRequestPacket {
pub fn new(client_salt: u64) -> Self {
Self {
header: PacketHeader::new(PacketType::ConnectionRequest),
client_salt,
}
}
pub fn get_client_salt(&self) -> u64 {
self.client_salt
}
}
impl Packet for ConnectionRequestPacket {
fn packet_type(&self) -> PacketType {
self.header.r#type
}
fn header(&self) -> PacketHeader {
self.header
}
}
impl From<ConnectionRequestPacket> for Packets {
fn from(val: ConnectionRequestPacket) -> Self {
Packets::ConnectionRequest(val)
}
}
#[repr(C)]
#[derive(PartialEq, Eq, Debug)]
pub struct ChallengePacket {
header: PacketHeader,
client_salt: u64,
server_salt: u64,
}
impl ChallengePacket {
pub fn new(client_salt: u64, server_salt: u64) -> Self {
Self {
header: PacketHeader::new(PacketType::Challenge),
client_salt,
server_salt,
}
}
pub fn get_client_salt(&self) -> u64 {
self.client_salt
}
pub fn get_server_salt(&self) -> u64 {
self.server_salt
}
}
impl Packet for ChallengePacket {
fn packet_type(&self) -> PacketType {
self.header.r#type
}
fn header(&self) -> PacketHeader {
self.header
}
}
impl From<ChallengePacket> for Packets {
fn from(val: ChallengePacket) -> Self {
Packets::Challenge(val)
}
}
#[repr(C)]
#[derive(PartialEq, Eq, Debug)]
pub struct ChallengeResponsePacket {
header: PacketHeader,
connection_id: u64,
}
impl ChallengeResponsePacket {
pub fn new(connection_id: u64) -> Self {
Self {
header: PacketHeader::new(PacketType::ChallengeResponse),
connection_id,
}
}
pub fn get_connection_id(&self) -> u64 {
self.connection_id
}
}
impl Packet for ChallengeResponsePacket {
fn packet_type(&self) -> PacketType {
self.header.r#type
}
fn header(&self) -> PacketHeader {
self.header
}
}
impl From<ChallengeResponsePacket> for Packets {
fn from(val: ChallengeResponsePacket) -> Self {
Packets::ChallengeResponse(val)
}
}
#[repr(C)]
#[derive(PartialEq, Eq, Clone, Copy, Debug, Default)]
pub struct ConnectionStatus {
pub sequence: u16,
pub ack: u16,
pub ack_bitfield: u32,
}
impl ConnectionStatus {
pub fn new(sequence: u16, ack: u16, ack_bitfield: u32) -> Self {
Self {
sequence,
ack,
ack_bitfield,
}
}
}
#[repr(C)]
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub struct DataPacket<const S: usize> {
pub header: PacketHeader,
pub connection_id: u64,
pub connection_status: ConnectionStatus,
pub data: [u8; S],
}
impl<const S: usize> DataPacket<S> {
pub fn new(connection_id: u64, connection_status: ConnectionStatus, data: [u8; S]) -> Self {
Self {
header: PacketHeader::new(PacketType::Data),
connection_id,
connection_status,
data,
}
}
pub fn get_connection_id(&self) -> u64 {
self.connection_id
}
pub fn get_connection_status(&self) -> ConnectionStatus {
self.connection_status
}
}
impl<const S: usize> Packet for DataPacket<S> {
fn packet_type(&self) -> PacketType {
self.header.r#type
}
fn header(&self) -> PacketHeader {
self.header
}
}
impl<const S: usize> Default for DataPacket<S> {
fn default() -> Self {
Self {
header: PacketHeader::default(),
connection_id: 0,
connection_status: ConnectionStatus::default(),
data: [0; S],
}
}
}
#[repr(C)]
#[derive(PartialEq, Eq, Debug)]
pub struct DisconnectPacket {
header: PacketHeader,
connection_id: u64,
}
impl DisconnectPacket {
pub fn new(connection_id: u64) -> Self {
Self {
header: PacketHeader::new(PacketType::Disconnect),
connection_id,
}
}
pub fn get_connection_id(&self) -> u64 {
self.connection_id
}
}
impl Packet for DisconnectPacket {
fn packet_type(&self) -> PacketType {
self.header.r#type
}
fn header(&self) -> PacketHeader {
self.header
}
}
impl From<DisconnectPacket> for Packets {
fn from(val: DisconnectPacket) -> Self {
Packets::Disconnect(val)
}
}
#[repr(C)]
#[derive(PartialEq, Eq, Debug)]
#[allow(clippy::large_enum_variant)]
pub enum Packets {
ConnectionRequest(ConnectionRequestPacket),
Challenge(ChallengePacket),
ChallengeResponse(ChallengeResponsePacket),
Data(DataPacket<1024>),
Disconnect(DisconnectPacket),
}
impl Packet for Packets {
fn packet_type(&self) -> PacketType {
match self {
Packets::ConnectionRequest(packet) => packet.packet_type(),
Packets::Challenge(packet) => packet.packet_type(),
Packets::ChallengeResponse(packet) => packet.packet_type(),
Packets::Data(packet) => packet.packet_type(),
Packets::Disconnect(packet) => packet.packet_type(),
}
}
fn header(&self) -> PacketHeader {
match self {
Packets::ConnectionRequest(packet) => packet.header(),
Packets::Challenge(packet) => packet.header(),
Packets::ChallengeResponse(packet) => packet.header(),
Packets::Data(packet) => packet.header(),
Packets::Disconnect(packet) => packet.header(),
}
}
}