#[cfg(test)]
#[path = "../../tests/tailer/structure.rs"]
mod tests;
use std::fmt::{Debug, Formatter, Result as FmtResult};
use std::marker::PhantomData;
use crate::bytes::{ByteBuffer, ByteBufferMut, DynamicByteBuffer, StaticByteBuffer};
use crate::settings::consts::{CD_OFFSET, FG_OFFSET, ID_OFFSET, PL_OFFSET, PN_OFFSET, TAILER_LENGTH, TM_OFFSET};
use crate::tailer::flags::{PacketFlags, ReturnCode};
use crate::utils::unix_timestamp_ms;
const TM_LENGTH: usize = 4;
const PN_LENGTH: usize = 8;
const PL_LENGTH: usize = 2;
pub trait IdentityType: Send + Sync {
fn from_bytes(bytes: &[u8]) -> Self;
fn to_bytes(&self) -> &[u8];
fn length() -> usize;
}
pub trait ServerConnectionHandler<T: IdentityType>: Send + Sync {
fn generate(&self, initial_data: &[u8]) -> T;
fn initial_data(&self, identity: &T) -> StaticByteBuffer;
fn verify_version(&self, version_bytes: &[u8]) -> bool;
}
pub trait ClientConnectionHandler: Send + Sync {
fn initial_data(&self) -> StaticByteBuffer;
fn version(&self, length: usize) -> StaticByteBuffer;
}
pub struct Tailer<T: IdentityType> {
buffer: DynamicByteBuffer,
_phantom: PhantomData<T>,
}
impl<T: IdentityType> Tailer<T> {
pub fn new(buffer: DynamicByteBuffer) -> Self {
let buffer = buffer.ensure_size(Self::len());
Self {
buffer,
_phantom: PhantomData,
}
}
pub fn validated(buffer: DynamicByteBuffer, body_len: usize) -> Option<Self> {
if buffer.len() < Self::len() {
return None;
}
let view = Self {
buffer,
_phantom: PhantomData,
};
let flags = view.flags();
if flags.is_empty() {
return None;
}
if flags.bits().count_ones() > 1 && !flags.is_shadowride() {
return None;
}
if (view.payload_length() as usize) > body_len {
return None;
}
Some(view)
}
pub fn data(buffer: DynamicByteBuffer, identity: &T, payload_length: u16, packet_number: u64) -> Self {
let view = Self::new(buffer);
view.set_flags(PacketFlags::DATA);
view.set_code(0);
view.set_time(0);
view.set_packet_number_raw(packet_number);
view.set_payload_length(payload_length);
view.set_identity(identity);
view
}
pub fn health_check(buffer: DynamicByteBuffer, identity: &T, next_in: u32, packet_number: u64) -> Self {
let view = Self::new(buffer);
view.set_flags(PacketFlags::HEALTH_CHECK);
view.set_code(0);
view.set_time(next_in);
view.set_packet_number_raw(packet_number);
view.set_payload_length(0);
view.set_identity(identity);
view
}
pub fn shadowride(buffer: DynamicByteBuffer, identity: &T, payload_length: u16, next_in: u32, packet_number: u64) -> Self {
let view = Self::new(buffer);
view.set_flags(PacketFlags::DATA | PacketFlags::HEALTH_CHECK);
view.set_code(0);
view.set_time(next_in);
view.set_packet_number_raw(packet_number);
view.set_payload_length(payload_length);
view.set_identity(identity);
view
}
pub fn handshake(buffer: DynamicByteBuffer, identity: &T, code: u8, next_in: u32, packet_number: u64, body_len: u16) -> Self {
let view = Self::new(buffer);
view.set_flags(PacketFlags::HANDSHAKE);
view.set_code(code);
view.set_time(next_in);
view.set_packet_number_raw(packet_number);
view.set_payload_length(body_len);
view.set_identity(identity);
view
}
pub fn decoy(buffer: DynamicByteBuffer, identity: &T, packet_number: u64) -> Self {
let view = Self::new(buffer);
view.set_flags(PacketFlags::DECOY);
view.set_code(0);
view.set_time(0);
view.set_packet_number_raw(packet_number);
view.set_payload_length(0);
view.set_identity(identity);
view
}
pub fn debug_probe(buffer: DynamicByteBuffer, identity: &T, ref_num: u8, send_time_ms: u32, sequence: u32, phase: u32, payload_len: u16) -> Self {
let view = Self::new(buffer);
view.set_flags(PacketFlags::DATA);
view.set_code(ref_num);
view.set_time(send_time_ms);
view.set_packet_number_raw(((sequence as u64) << 32) | (phase as u64));
view.set_payload_length(payload_len);
view.set_identity(identity);
view
}
pub fn termination(buffer: DynamicByteBuffer, identity: &T, code: ReturnCode, packet_number: u64) -> Self {
let view = Self::new(buffer);
view.set_flags(PacketFlags::TERMINATION);
view.set_code(code.into());
view.set_time(0);
view.set_packet_number_raw(packet_number);
view.set_payload_length(0);
view.set_identity(identity);
view
}
#[inline]
pub fn flags(&self) -> PacketFlags {
PacketFlags::from_bits_truncate(*self.buffer.get(FG_OFFSET))
}
#[inline]
pub fn code(&self) -> u8 {
*self.buffer.get(CD_OFFSET)
}
#[inline]
pub fn time(&self) -> u32 {
u32::from_be_bytes(self.buffer.slice_both(TM_OFFSET, TM_OFFSET + TM_LENGTH).try_into().unwrap())
}
#[inline]
pub fn packet_number(&self) -> u64 {
u64::from_be_bytes(self.buffer.slice_both(PN_OFFSET, PN_OFFSET + PN_LENGTH).try_into().unwrap())
}
#[inline]
pub fn payload_length(&self) -> u16 {
u16::from_be_bytes(self.buffer.slice_both(PL_OFFSET, PL_OFFSET + PL_LENGTH).try_into().unwrap())
}
#[inline]
pub fn identity(&self) -> T {
T::from_bytes(self.buffer.slice_both(ID_OFFSET, ID_OFFSET + T::length()))
}
#[inline]
pub fn timestamp(&self) -> u32 {
(self.packet_number() >> 32) as u32
}
#[inline]
pub fn incremental(&self) -> u32 {
self.packet_number() as u32
}
#[inline]
pub fn return_code(&self) -> ReturnCode {
ReturnCode::from(self.code())
}
#[inline]
pub fn debug_ref_num(&self) -> u8 {
self.code()
}
#[inline]
pub fn debug_send_time(&self) -> u32 {
self.time()
}
#[inline]
pub fn debug_sequence(&self) -> u32 {
(self.packet_number() >> 32) as u32
}
#[inline]
pub fn debug_phase(&self) -> u32 {
self.packet_number() as u32
}
#[inline]
pub fn buffer(&self) -> &DynamicByteBuffer {
&self.buffer
}
#[inline]
pub fn into_buffer(self) -> DynamicByteBuffer {
self.buffer
}
#[inline]
pub fn set_flags(&self, flags: PacketFlags) {
self.buffer.set(FG_OFFSET, flags.bits());
}
#[inline]
pub fn set_code(&self, code: u8) {
self.buffer.set(CD_OFFSET, code);
}
#[inline]
pub fn set_time(&self, time: u32) {
self.buffer.slice_both_mut(TM_OFFSET, TM_OFFSET + TM_LENGTH).copy_from_slice(&time.to_be_bytes());
}
#[inline]
pub fn set_packet_number_raw(&self, pn: u64) {
self.buffer.slice_both_mut(PN_OFFSET, PN_OFFSET + PN_LENGTH).copy_from_slice(&pn.to_be_bytes());
}
#[inline]
pub fn set_packet_number(&self, timestamp: u32, incremental: u32) {
let pn = ((timestamp as u64) << 32) | (incremental as u64);
self.set_packet_number_raw(pn);
}
pub fn set_packet_number_now(&self, incremental: u32) {
let timestamp = (unix_timestamp_ms() / 1000) as u32;
self.set_packet_number(timestamp, incremental);
}
#[inline]
pub fn set_payload_length(&self, len: u16) {
self.buffer.slice_both_mut(PL_OFFSET, PL_OFFSET + PL_LENGTH).copy_from_slice(&len.to_be_bytes());
}
#[inline]
pub fn set_identity(&self, identity: &T) {
self.buffer.slice_both_mut(ID_OFFSET, ID_OFFSET + T::length()).copy_from_slice(identity.to_bytes());
}
#[inline]
pub fn get_payload_length(buffer: &DynamicByteBuffer) -> u16 {
let correct_buffer = buffer.ensure_size(TAILER_LENGTH);
u16::from_be_bytes(correct_buffer.slice_both(PL_OFFSET, PL_OFFSET + PL_LENGTH).try_into().unwrap())
}
#[inline]
pub fn get_identity(buffer: &DynamicByteBuffer) -> T {
let correct_buffer = buffer.ensure_size(Self::len());
T::from_bytes(correct_buffer.slice_both(ID_OFFSET, ID_OFFSET + T::length()))
}
#[inline]
pub fn len() -> usize {
T::length() + TAILER_LENGTH
}
#[inline]
pub(crate) fn encrypted_len_c2s() -> usize {
Self::len() + crate::crypto::TAILER_C2S_OVERHEAD
}
#[inline]
pub(crate) fn encrypted_len_s2c() -> usize {
Self::len() + crate::crypto::TAILER_S2C_OVERHEAD
}
}
impl<T: IdentityType> Clone for Tailer<T> {
fn clone(&self) -> Self {
Self {
buffer: self.buffer.clone(),
_phantom: PhantomData,
}
}
}
impl<T: IdentityType + PartialEq> PartialEq for Tailer<T> {
fn eq(&self, other: &Self) -> bool {
self.buffer.slice() == other.buffer.slice()
}
}
impl<T: IdentityType> Debug for Tailer<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
f.debug_struct("Tailer").field("flags", &self.flags()).field("code", &self.code()).field("time", &self.time()).field("packet_number", &self.packet_number()).field("payload_length", &self.payload_length()).finish()
}
}