use std::io::{Cursor, Read, Write, Seek};
use std::collections::VecDeque;
use std::fmt;
use byteorder::{ReadBytesExt, WriteBytesExt, LE};
use crate::util::BytesFmt;
pub const PACKET_MAX_LEN: usize = 1300;
pub const PACKET_PREFIX_LEN: usize = 4;
pub const PACKET_FLAGS_LEN: usize = 2;
pub const PACKET_MIN_LEN: usize = PACKET_PREFIX_LEN + PACKET_FLAGS_LEN;
pub const PACKET_MAX_FOOTER_LEN: usize = 8 + 4 + 4 + 1 + 4 + 4 + 8 + 4;
pub const PACKET_MAX_BODY_LEN: usize = PACKET_MAX_LEN - PACKET_MIN_LEN - PACKET_MAX_FOOTER_LEN;
#[derive(Clone)]
pub struct RawPacket {
data: [u8; PACKET_MAX_LEN],
len: usize,
}
impl RawPacket {
#[inline]
pub fn new() -> Self {
Self {
data: [0; PACKET_MAX_LEN],
len: PACKET_MIN_LEN,
}
}
#[inline]
pub fn raw_data(&self) -> &[u8] {
&self.data[..]
}
#[inline]
pub fn raw_data_mut(&mut self) -> &mut [u8] {
&mut self.data[..]
}
#[inline]
pub fn data_max_len(&self) -> usize {
self.data.len()
}
#[inline]
pub fn data_len(&self) -> usize {
self.len
}
#[inline]
pub fn data_available_len(&self) -> usize {
self.data_max_len() - self.data_len()
}
#[inline]
pub fn set_data_len(&mut self, len: usize) {
assert!(len >= PACKET_MIN_LEN, "given length too small");
assert!(len <= PACKET_MAX_LEN, "given length too high");
self.len = len;
}
#[inline]
pub fn data(&self) -> &[u8] {
&self.data[..self.len]
}
#[inline]
pub fn data_mut(&mut self) -> &mut [u8] {
&mut self.data[..self.len]
}
#[inline]
pub fn max_body_len(&self) -> usize {
self.data_max_len() - PACKET_PREFIX_LEN
}
#[inline]
pub fn body_len(&self) -> usize {
self.data_len() - PACKET_PREFIX_LEN
}
#[inline]
pub fn body(&self) -> &[u8] {
&self.data[PACKET_PREFIX_LEN..self.len]
}
#[inline]
pub fn body_mut(&mut self) -> &mut [u8] {
&mut self.data[PACKET_PREFIX_LEN..self.len]
}
#[inline]
pub fn reset(&mut self) {
self.len = PACKET_MIN_LEN;
self.data[..PACKET_MIN_LEN].fill(0);
}
#[inline]
pub fn grow(&mut self, len: usize) -> &mut [u8] {
assert!(self.data_available_len() >= len, "not enough available data");
let ptr = &mut self.data[self.len..][..len];
self.len += len;
ptr
}
#[inline]
pub fn grow_write(&mut self, len: usize) -> impl Write + Seek + '_ {
Cursor::new(self.grow(len))
}
#[inline]
pub fn shrink(&mut self, len: usize) -> &[u8] {
assert!(self.len - len >= PACKET_MIN_LEN, "not enough data to shrink");
self.len -= len;
&self.data[self.len..][..len]
}
#[inline]
pub fn shrink_read(&mut self, len: usize) -> impl Read + '_ {
Cursor::new(self.shrink(len))
}
#[inline]
pub fn read_prefix(&self) -> u32 {
u32::from_le_bytes(self.data[..PACKET_PREFIX_LEN].try_into().unwrap())
}
#[inline]
pub fn write_prefix(&mut self, prefix: u32) {
self.data[..PACKET_PREFIX_LEN].copy_from_slice(&prefix.to_le_bytes())
}
#[inline]
pub fn read_flags(&self) -> u16 {
u16::from_le_bytes(self.data[PACKET_PREFIX_LEN..][..PACKET_FLAGS_LEN].try_into().unwrap())
}
#[inline]
pub fn write_flags(&mut self, flags: u16) {
self.data[PACKET_PREFIX_LEN..][..PACKET_FLAGS_LEN].copy_from_slice(&flags.to_le_bytes())
}
}
impl fmt::Debug for RawPacket {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("RawPacket")
.field("raw_data", &format_args!("{:X}", BytesFmt(self.raw_data())))
.field("data", &format_args!("{:X}", BytesFmt(self.data())))
.field("len", &self.len)
.finish()
}
}
#[derive(Clone)]
pub struct Packet {
raw: RawPacket,
footer_offset: usize,
first_request_offset: usize,
}
impl Packet {
#[inline]
pub fn new() -> Self {
Self {
raw: RawPacket::new(),
footer_offset: PACKET_MIN_LEN,
first_request_offset: 0,
}
}
pub fn new_boxed() -> Box<Self> {
Box::new(Self::new())
}
#[inline]
pub fn raw(&self) -> &RawPacket {
&self.raw
}
#[inline]
pub fn raw_mut(&mut self) -> &mut RawPacket {
&mut self.raw
}
#[inline]
pub fn content_max_len(&self) -> usize {
self.raw.data_max_len() - PACKET_MIN_LEN - PACKET_MAX_FOOTER_LEN
}
#[inline]
pub fn content_len(&self) -> usize {
self.footer_offset - PACKET_MIN_LEN
}
#[inline]
pub fn content_available_len(&self) -> usize {
self.content_max_len() - self.content_len()
}
#[inline]
pub fn content(&self) -> &[u8] {
&self.raw.raw_data()[PACKET_MIN_LEN..self.footer_offset]
}
#[inline]
pub fn content_mut(&mut self) -> &mut [u8] {
&mut self.raw.raw_data_mut()[PACKET_MIN_LEN..self.footer_offset]
}
#[inline]
pub fn grow(&mut self, len: usize) -> &mut [u8] {
assert!(self.content_available_len() >= len, "not enough available data");
self.raw.set_data_len(self.footer_offset);
self.footer_offset += len;
self.raw.grow(len)
}
#[inline]
pub fn grow_write(&mut self, len: usize) -> impl Write + '_ {
Cursor::new(self.grow(len))
}
#[inline]
pub fn footer_len(&self) -> usize {
self.raw.data_len() - self.footer_offset
}
#[inline]
pub fn footer_available_len(&self) -> usize {
PACKET_MAX_FOOTER_LEN - self.footer_len()
}
#[inline]
pub fn first_request_offset(&self) -> Option<usize> {
(self.first_request_offset >= PACKET_FLAGS_LEN).then_some(self.first_request_offset)
}
#[inline]
pub fn set_first_request_offset(&mut self, offset: usize) {
assert!(offset >= PACKET_FLAGS_LEN, "invalid request offset");
self.first_request_offset = offset;
}
#[inline]
pub fn clear_first_request_offset(&mut self) {
self.first_request_offset = 0;
}
pub fn write_config(&mut self, config: &mut PacketConfig) {
if self.footer_offset < self.raw.data_len() {
self.raw.set_data_len(self.footer_offset);
}
let mut flags = 0u16;
if config.reliable() { flags |= flags::IS_RELIABLE; }
if config.on_channel() { flags |= flags::ON_CHANNEL; }
if let Some((first_num, last_num)) = config.sequence_range() {
flags |= flags::IS_FRAGMENT;
let mut cursor = self.raw.grow_write(8);
cursor.write_u32::<LE>(first_num).unwrap();
cursor.write_u32::<LE>(last_num).unwrap();
}
if let Some(request_offset) = self.first_request_offset() {
flags |= flags::HAS_REQUESTS;
self.raw.grow_write(2).write_u16::<LE>(request_offset as u16).unwrap();
}
if let Some(val) = config.unk_1000() {
flags |= flags::UNK_1000;
self.raw.grow_write(4).write_u32::<LE>(val).unwrap();
}
if config.reliable() || config.sequence_range().is_some() {
flags |= flags::HAS_SEQUENCE_NUMBER;
self.raw.grow_write(4).write_u32::<LE>(config.sequence_num()).unwrap();
}
if !config.single_acks().is_empty() {
flags |= flags::HAS_ACKS;
let available_len = self.footer_available_len()
- if config.cumulative_ack().is_some() { 4 } else { 0 }
- if config.indexed_channel().is_some() { 8 } else { 0 }
- if config.has_checksum() { 4 } else { 0 }
- 1;
let mut count = 0;
while let Some(ack) = config.single_acks_mut().pop_front() {
if available_len < 4 {
break
} else {
self.raw.grow_write(4).write_u32::<LE>(ack).unwrap();
count += 1;
}
}
debug_assert!(count != 0);
self.raw.grow(1)[0] = count as _;
}
if let Some(num) = config.cumulative_ack() {
flags |= flags::HAS_CUMULATIVE_ACK;
self.raw.grow_write(4).write_u32::<LE>(num).unwrap();
}
if let Some((id, version)) = config.indexed_channel() {
flags |= flags::INDEXED_CHANNEL;
let mut cursor = self.raw.grow_write(8);
cursor.write_u32::<LE>(version).unwrap();
cursor.write_u32::<LE>(id).unwrap();
}
if config.has_checksum() {
flags |= flags::HAS_CHECKSUM;
}
self.raw.write_flags(flags);
if config.has_checksum() {
let checksum = calc_checksum(Cursor::new(self.raw.body()));
self.raw.grow_write(4).write_u32::<LE>(checksum).unwrap();
}
}
pub fn read_config(&mut self, len: usize, config: &mut PacketConfig) -> Result<(), PacketConfigError> {
self.raw.set_data_len(len);
let flags = self.raw.read_flags();
const KNOWN_FLAGS: u16 =
flags::HAS_CHECKSUM |
flags::INDEXED_CHANNEL |
flags::HAS_CUMULATIVE_ACK |
flags::HAS_ACKS |
flags::HAS_SEQUENCE_NUMBER |
flags::UNK_1000 |
flags::HAS_REQUESTS |
flags::IS_FRAGMENT |
flags::ON_CHANNEL |
flags::IS_RELIABLE;
if flags & !KNOWN_FLAGS != 0 {
return Err(PacketConfigError::UnknownFlags(flags & !KNOWN_FLAGS));
}
if flags & flags::HAS_CHECKSUM != 0 {
let expected_checksum = self.raw.shrink_read(4).read_u32::<LE>().unwrap();
let computed_checksum = calc_checksum(Cursor::new(self.raw.body()));
if expected_checksum != computed_checksum {
return Err(PacketConfigError::InvalidChecksum)
}
}
if flags & flags::INDEXED_CHANNEL != 0 {
let mut cursor = self.raw.shrink_read(8);
let version = cursor.read_u32::<LE>().unwrap();
let id = cursor.read_u32::<LE>().unwrap();
config.set_indexed_channel(id, version);
} else {
config.clear_indexed_channel();
}
if flags & flags::HAS_CUMULATIVE_ACK != 0 {
config.set_cumulative_ack(self.raw.shrink_read(4).read_u32::<LE>().unwrap());
} else {
config.clear_cumulative_ack();
}
if flags & flags::HAS_ACKS != 0 {
let count = self.raw.shrink(1)[0];
if count == 0 {
return Err(PacketConfigError::Corrupted)
}
for _ in 0..count {
config.single_acks_mut().push_back(self.raw.shrink_read(4).read_u32::<LE>().unwrap());
}
}
if flags & flags::HAS_SEQUENCE_NUMBER != 0 {
config.set_sequence_num(self.raw.shrink_read(4).read_u32::<LE>().unwrap());
} else {
config.set_sequence_num(0);
}
if flags & flags::UNK_1000 != 0 {
config.set_unk_1000(self.raw.shrink_read(4).read_u32::<LE>().unwrap());
} else {
config.clear_unk_1000();
}
if flags & flags::HAS_REQUESTS != 0 {
let offset = self.raw.shrink_read(2).read_u16::<LE>().unwrap() as usize;
if offset < PACKET_FLAGS_LEN {
return Err(PacketConfigError::Corrupted)
} else {
self.set_first_request_offset(offset);
}
} else {
self.clear_first_request_offset();
}
if flags & flags::IS_FRAGMENT != 0 {
let mut cursor = self.raw.shrink_read(8);
let first_num = cursor.read_u32::<LE>().unwrap();
let last_num = cursor.read_u32::<LE>().unwrap();
if first_num >= last_num {
return Err(PacketConfigError::Corrupted)
} else {
config.set_sequence_range(first_num, last_num);
}
} else {
config.clear_sequence_range();
}
config.set_reliable(flags & flags::IS_RELIABLE != 0);
config.set_on_channel(flags & flags::ON_CHANNEL != 0);
self.footer_offset = self.raw.data_len();
self.raw.set_data_len(len);
debug_assert!(self.footer_len() <= PACKET_MAX_FOOTER_LEN);
Ok(())
}
}
impl fmt::Debug for Packet {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Packet")
.field("content", &format_args!("{:X}", BytesFmt(self.content())))
.field("content_len", &self.content_len())
.field("footer_len", &self.footer_len())
.field("first_request_offset", &self.first_request_offset())
.finish()
}
}
#[derive(Debug, Clone)]
pub struct PacketConfig {
sequence_num: u32,
sequence_first_num: u32,
sequence_last_num: u32,
reliable: bool,
cumulative_ack: Option<u32>,
single_acks: VecDeque<u32>,
on_channel: bool,
indexed_channel: Option<(u32, u32)>,
has_checksum: bool,
unk_1000: Option<u32>,
}
impl PacketConfig {
#[inline]
pub fn new() -> Self {
Self {
sequence_num: 0,
sequence_first_num: 0,
sequence_last_num: 0,
reliable: false,
cumulative_ack: None,
single_acks: VecDeque::new(),
on_channel: false,
indexed_channel: None,
has_checksum: false,
unk_1000: None,
}
}
#[inline]
pub fn sequence_num(&self) -> u32 {
self.sequence_num
}
#[inline]
pub fn set_sequence_num(&mut self, num: u32) {
self.sequence_num = num;
}
#[inline]
pub fn sequence_range(&self) -> Option<(u32, u32)> {
if self.sequence_first_num < self.sequence_last_num {
Some((self.sequence_first_num, self.sequence_last_num))
} else {
None
}
}
#[inline]
pub fn set_sequence_range(&mut self, first: u32, last: u32) {
assert!(first < last, "invalid range");
self.sequence_first_num = first;
self.sequence_last_num = last;
}
#[inline]
pub fn clear_sequence_range(&mut self) {
self.sequence_first_num = 0;
self.sequence_last_num = 0;
}
#[inline]
pub fn reliable(&self) -> bool {
self.reliable
}
#[inline]
pub fn set_reliable(&mut self, reliable: bool) {
self.reliable = reliable
}
#[inline]
pub fn cumulative_ack(&self) -> Option<u32> {
self.cumulative_ack
}
#[inline]
pub fn set_cumulative_ack(&mut self, num: u32) {
assert_ne!(num, 0, "cumulative ack is exclusive so it cannot be zero");
self.cumulative_ack = Some(num);
}
#[inline]
pub fn clear_cumulative_ack(&mut self) {
self.cumulative_ack = None;
}
#[inline]
pub fn single_acks(&self) -> &VecDeque<u32> {
&self.single_acks
}
#[inline]
pub fn single_acks_mut(&mut self) -> &mut VecDeque<u32> {
&mut self.single_acks
}
#[inline]
pub fn on_channel(&self) -> bool {
self.on_channel
}
#[inline]
pub fn indexed_channel(&self) -> Option<(u32, u32)> {
self.indexed_channel
}
#[inline]
pub fn set_indexed_channel(&mut self, id: u32, version: u32) {
self.indexed_channel = Some((id, version))
}
#[inline]
pub fn clear_indexed_channel(&mut self) {
self.indexed_channel = None;
}
#[inline]
pub fn set_on_channel(&mut self, on_channel: bool) {
self.on_channel = on_channel;
}
#[inline]
pub fn has_checksum(&self) -> bool {
self.has_checksum
}
#[inline]
pub fn set_checksum(&mut self, enabled: bool) {
self.has_checksum = enabled;
}
#[inline]
pub fn unk_1000(&self) -> Option<u32> {
self.unk_1000
}
#[inline]
pub fn set_unk_1000(&mut self, val: u32) {
self.unk_1000 = Some(val);
}
#[inline]
pub fn clear_unk_1000(&mut self) {
self.unk_1000 = None;
}
}
fn calc_checksum(mut reader: impl Read) -> u32 {
let mut checksum = 0;
while let Ok(num) = reader.read_u32::<LE>() {
checksum ^= num;
}
checksum
}
#[allow(unused)]
mod flags {
pub const HAS_REQUESTS: u16 = 0x0001;
pub const HAS_PIGGYBACKS: u16 = 0x0002;
pub const HAS_ACKS: u16 = 0x0004;
pub const ON_CHANNEL: u16 = 0x0008;
pub const IS_RELIABLE: u16 = 0x0010;
pub const IS_FRAGMENT: u16 = 0x0020;
pub const HAS_SEQUENCE_NUMBER: u16 = 0x0040;
pub const INDEXED_CHANNEL: u16 = 0x0080;
pub const HAS_CHECKSUM: u16 = 0x0100;
pub const CREATE_CHANNEL: u16 = 0x0200;
pub const HAS_CUMULATIVE_ACK: u16 = 0x0400;
pub const UNK_0800: u16 = 0x0800;
pub const UNK_1000: u16 = 0x1000;
}
#[derive(Debug, Clone, thiserror::Error)]
pub enum PacketConfigError {
#[error("unknown flags: {0:04X}")]
UnknownFlags(u16),
#[error("corrupted")]
Corrupted,
#[error("invalid checksum")]
InvalidChecksum
}