117 lines
No EOL
3.3 KiB
Rust
117 lines
No EOL
3.3 KiB
Rust
pub mod data_types;
|
|
pub mod identifier;
|
|
pub mod packet_data;
|
|
|
|
use crate::prelude;
|
|
use identifier::Identifier;
|
|
use packet_data::PacketData;
|
|
use std::convert::TryFrom;
|
|
use std::fmt::Debug;
|
|
use std::io::Read;
|
|
|
|
#[derive(Debug)]
|
|
pub enum Packet {
|
|
V1 {
|
|
src: Identifier,
|
|
dest: Identifier,
|
|
packet_id: Identifier,
|
|
reply_to: Identifier,
|
|
command: u8,
|
|
data: PacketData,
|
|
},
|
|
}
|
|
|
|
impl Packet {
|
|
pub fn packet_id(&self) -> Identifier {
|
|
match self {
|
|
Packet::V1 { packet_id, .. } => packet_id.clone()
|
|
}
|
|
}
|
|
|
|
pub fn command(&self) -> u8 {
|
|
match self {
|
|
Packet::V1 { command, .. } => command.clone()
|
|
}
|
|
}
|
|
|
|
pub fn data(&self) -> PacketData {
|
|
match self {
|
|
Packet::V1 { data, .. } => data.clone()
|
|
}
|
|
}
|
|
|
|
/// Build packet **without** CRC32
|
|
pub fn build_base_packet(&self) -> Vec<u8> {
|
|
match self {
|
|
Packet::V1 {
|
|
src,
|
|
dest,
|
|
packet_id,
|
|
reply_to,
|
|
command,
|
|
data,
|
|
} => {
|
|
let mut buf = Vec::new();
|
|
let data_length = data.len();
|
|
buf.push(0x01);
|
|
buf.extend_from_slice(&src.bytes);
|
|
buf.extend_from_slice(&dest.bytes);
|
|
buf.extend_from_slice(&packet_id.bytes);
|
|
buf.extend_from_slice(&reply_to.bytes);
|
|
buf.push(command.clone());
|
|
buf.push((data_length >> 8) as u8);
|
|
buf.push((data_length & 0xFF) as u8);
|
|
buf.extend(data.get_data());
|
|
buf
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn build_full_packet(&self) -> Vec<u8> {
|
|
match self {
|
|
Packet::V1 { .. } => {
|
|
let mut buf = self.build_base_packet();
|
|
buf.extend_from_slice(crc32fast::hash(&buf.as_slice()).to_be_bytes().as_ref());
|
|
buf
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TryFrom<Vec<u8>> for Packet {
|
|
type Error = ();
|
|
|
|
fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
|
|
match value[0] {
|
|
0x01 => {
|
|
let header: Vec<u16> = value[..0x15].iter().map(|v| u16::from(*v)).collect();
|
|
let data_length = (header[0x12] << 8) | header[0x13];
|
|
let crc32 = prelude::as_u32_be(&value[(0x14 + data_length as usize)..]);
|
|
let packet = Packet::V1 {
|
|
src: Identifier::from(&value[0x01..0x05]),
|
|
dest: Identifier::from(&value[0x05..0x09]),
|
|
packet_id: Identifier::from(&value[0x09..0x0D]),
|
|
reply_to: Identifier::from(&value[0x0D..0x11]),
|
|
command: value[0x11],
|
|
data: PacketData::new(value[0x14..(data_length as usize + 0x14)].to_owned()),
|
|
};
|
|
if crc32fast::hash(packet.build_base_packet().as_slice()) != crc32 {
|
|
Err(())
|
|
} else {
|
|
Ok(packet)
|
|
}
|
|
}
|
|
_ => Err(()),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Into<Vec<u8>> for Packet {
|
|
fn into(self) -> Vec<u8> {
|
|
self.build_full_packet()
|
|
}
|
|
}
|
|
|
|
pub trait ToPacket {
|
|
fn to_v1_packet(self, src: Identifier, dest: Identifier, packet_id: Identifier, reply_to: Identifier) -> Packet;
|
|
} |