domo/domo_proto/src/packet/mod.rs

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;
}