use crate::acknowledgement::Acknowledgement;
use crate::util::compile_u16;
use crate::util::compile_u32;
use std::convert::From;
use std::convert::TryInto;
use std::vec::Vec;
#[derive(Debug, Clone)]
pub enum PType {
Data,
AckOnly,
Initiation,
KeyExchange,
Extended,
}
impl From<PType> for u8 {
fn from(p_type: PType) -> u8 {
match p_type {
PType::Data => 0,
PType::AckOnly => 1,
PType::Initiation => 2,
PType::KeyExchange => 7,
PType::Extended => 15,
}
}
}
impl From<u8> for PType {
fn from(p_type: u8) -> PType {
match p_type {
0 => PType::Data,
1 => PType::AckOnly,
2 => PType::Initiation,
7 => PType::KeyExchange,
_ => PType::Extended,
}
}
}
impl PartialEq for PType {
fn eq(&self, other: &Self) -> bool {
(self.clone() as u8) == (other.clone() as u8)
}
}
#[derive(Debug)]
pub struct PacketFlags {
pub p_type: PType,
pub ack: bool,
pub enc: bool,
}
impl PacketFlags {
pub fn get_byte(&self) -> u8 {
let mut byte: u8 = 0;
let p_type: u8 = self.p_type.clone().into();
byte |= p_type << 4;
if self.ack {
byte |= 1 << 3;
}
if self.enc {
byte |= 1 << 2;
}
byte
}
}
#[derive(Debug)]
pub struct PacketMeta {
pub delay_ms: u64,
pub retry_count: i16,
}
#[derive(Debug)]
pub struct Packet {
pub flags: PacketFlags,
pub sequence: u32,
pub ack: Acknowledgement,
pub payload: Vec<u8>,
pub is_meta: bool,
pub meta: PacketMeta,
}
impl Packet {
pub fn new(p_type: PType, sequence: u32) -> Packet {
Packet {
flags: PacketFlags {
p_type,
ack: false,
enc: false,
},
sequence,
ack: Acknowledgement {
ack_begin: 0,
ack_end: 0,
miss_count: 0,
miss: Vec::new(),
},
payload: Vec::new(),
is_meta: false,
meta: PacketMeta {
delay_ms: 0,
retry_count: 0,
},
}
}
pub fn set_enc(&mut self, enc: bool) {
self.flags.enc = enc;
}
pub fn set_meta(&mut self, meta: PacketMeta) {
self.is_meta = true;
self.meta = meta;
}
pub fn add_ack(&mut self, ack: Acknowledgement) {
self.ack = ack;
self.flags.ack = true;
}
pub fn append_payload(&mut self, payload: Vec<u8>) {
self.payload.extend(payload);
}
pub fn compile(&self) -> Vec<u8> {
let mut packet_vector = Vec::<u8>::new();
let slice_sequence = compile_u32(self.sequence);
packet_vector.extend(slice_sequence);
let slice_ack_begin = compile_u32(self.ack.ack_begin);
packet_vector.extend(slice_ack_begin);
let slice_ack_end = compile_u16(self.ack.ack_end);
packet_vector.extend(slice_ack_end);
packet_vector.push(self.flags.get_byte());
let slice_miss_count = compile_u16(self.ack.miss_count);
packet_vector.extend(slice_miss_count);
let mut slice_miss: Vec<u8> = Vec::new();
self.ack
.miss
.clone()
.into_iter()
.map(compile_u16)
.for_each(|slice_part| slice_miss.extend(slice_part));
packet_vector.extend(slice_miss);
let slice_payload = self.payload.clone();
packet_vector.extend(slice_payload);
packet_vector
}
pub fn get_max_header_size(window_size: u16) -> usize {
(13 + window_size * 2) as usize
}
}
impl From<u8> for PacketFlags {
fn from(byte: u8) -> Self {
let mut flags = PacketFlags {
p_type: PType::Data,
ack: false,
enc: false,
};
flags.p_type = PType::from((byte >> 4) & 0x0F);
if (byte >> 3) & 0x01 == 1 {
flags.ack = true;
}
if (byte >> 2) & 0x01 == 1 {
flags.enc = true;
}
flags
}
}
impl From<Vec<u8>> for Packet {
fn from(bytes: Vec<u8>) -> Packet {
let mut packet_default = Packet {
flags: PacketFlags {
p_type: PType::Data,
ack: false,
enc: false,
},
sequence: 0,
ack: Acknowledgement {
ack_begin: 0,
ack_end: 0,
miss_count: 0,
miss: Vec::new(),
},
payload: Vec::new(),
is_meta: false,
meta: PacketMeta {
delay_ms: 0,
retry_count: 0,
},
};
let sequence_array = bytes[0..4].try_into().unwrap();
packet_default.sequence = u32::from_be_bytes(sequence_array);
let ack_begin_array = bytes[4..8].try_into().unwrap();
packet_default.ack.ack_begin = u32::from_be_bytes(ack_begin_array);
let ack_end_array = bytes[8..10].try_into().unwrap();
packet_default.ack.ack_end = u16::from_be_bytes(ack_end_array);
packet_default.flags = PacketFlags::from(bytes[10]);
let miss_count_array = bytes[11..13].try_into().unwrap();
packet_default.ack.miss_count = u16::from_be_bytes(miss_count_array);
packet_default.ack.miss = (13..(13 + packet_default.ack.miss_count * 2) as usize)
.step_by(2)
.into_iter()
.map(|i| u16::from_be_bytes(bytes[i..(i + 2)].try_into().unwrap()))
.collect();
let payload_start = 13 + (packet_default.ack.miss_count * 2) as usize;
let payload_length = bytes.len() - payload_start;
packet_default.payload = bytes[payload_start..payload_start + payload_length].to_vec();
packet_default
}
}
#[cfg(test)]
mod tests {
use crate::packet::PType;
use crate::{acknowledgement::AcknowledgementList, packet};
use super::Packet;
#[test]
fn range_test() {
let pack = packet::Packet::new(PType::Data, 0);
assert!(pack.ack.ack_begin <= pack.ack.ack_end.into());
assert!(pack.ack.miss_count as u32 <= (pack.ack.ack_end as u32 - pack.ack.ack_begin));
}
#[test]
fn compile_test() {
let mut pack = packet::Packet::new(PType::KeyExchange, 32850943);
let mut ack_list = AcknowledgementList::new(329965);
ack_list.insert(329966);
ack_list.insert(329967);
ack_list.insert(329969);
ack_list.insert(331000);
pack.add_ack(ack_list.get());
pack.append_payload(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
let compiled = pack.compile();
let pack_out = packet::Packet::from(compiled);
assert_eq!(pack.sequence, pack_out.sequence);
assert_eq!(pack.flags.p_type, pack_out.flags.p_type);
assert_eq!(pack.flags.ack, pack_out.flags.ack);
assert_eq!(pack.flags.enc, pack_out.flags.enc);
assert_eq!(pack.ack.ack_begin, pack_out.ack.ack_begin);
assert_eq!(pack.ack.ack_end, pack_out.ack.ack_end);
assert_eq!(pack.ack.miss_count, pack_out.ack.miss_count);
assert_eq!(pack.ack.miss, pack_out.ack.miss);
assert_eq!(pack.payload, pack_out.payload);
}
#[test]
fn size_test() {
let size = Packet::get_max_header_size(10000);
println!("size: {}", size);
assert_eq!(size, 20013);
}
}