first pass tlv (bad!)
This commit is contained in:
parent
c2aa1e15c7
commit
0aef7feb32
151
homekit-controller/src/tlv8/data_types.rs
Normal file
151
homekit-controller/src/tlv8/data_types.rs
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
use super::Tlv;
|
||||||
|
|
||||||
|
pub enum TlvType {
|
||||||
|
Method,
|
||||||
|
Identifier,
|
||||||
|
Salt,
|
||||||
|
PublicKey,
|
||||||
|
Proof,
|
||||||
|
EncryptedData,
|
||||||
|
State,
|
||||||
|
Error,
|
||||||
|
RetryDelay,
|
||||||
|
Certificate,
|
||||||
|
Signature,
|
||||||
|
Permissions,
|
||||||
|
PermissionRegularUser,
|
||||||
|
PermissionAdminUser,
|
||||||
|
FragmentData,
|
||||||
|
FragmentLast,
|
||||||
|
SessionID,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<TlvType> for u8 {
|
||||||
|
fn from(value: TlvType) -> Self {
|
||||||
|
match value {
|
||||||
|
TlvType::Method => 0,
|
||||||
|
TlvType::Identifier => 1,
|
||||||
|
TlvType::Salt => 2,
|
||||||
|
TlvType::PublicKey => 3,
|
||||||
|
TlvType::Proof => 4,
|
||||||
|
TlvType::EncryptedData => 5,
|
||||||
|
TlvType::State => 6,
|
||||||
|
TlvType::Error => 7,
|
||||||
|
TlvType::RetryDelay => 8,
|
||||||
|
TlvType::Certificate => 9,
|
||||||
|
TlvType::Signature => 10,
|
||||||
|
TlvType::Permissions => 11,
|
||||||
|
TlvType::PermissionRegularUser => 0,
|
||||||
|
TlvType::PermissionAdminUser => 1,
|
||||||
|
TlvType::FragmentData => 12,
|
||||||
|
TlvType::FragmentLast => 13,
|
||||||
|
TlvType::SessionID => 14,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum TlvData {
|
||||||
|
Bytes(Vec<u8>),
|
||||||
|
Tlv8(Vec<Tlv>),
|
||||||
|
Integer(TlvInteger),
|
||||||
|
Float(f64),
|
||||||
|
String(String),
|
||||||
|
Uint(TlvUnsignedInteger),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum TlvInteger {
|
||||||
|
OneByte(i8),
|
||||||
|
TwoBytes(i16),
|
||||||
|
FourBytes(i32),
|
||||||
|
EightBytes(i64),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TlvInteger {
|
||||||
|
pub fn to_le_bytes(&self) -> Vec<u8> {
|
||||||
|
match self {
|
||||||
|
TlvInteger::OneByte(v) => v.to_le_bytes().to_vec(),
|
||||||
|
TlvInteger::TwoBytes(v) => v.to_le_bytes().to_vec(),
|
||||||
|
TlvInteger::FourBytes(v) => v.to_le_bytes().to_vec(),
|
||||||
|
TlvInteger::EightBytes(v) => v.to_le_bytes().to_vec(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> From<T> for TlvData
|
||||||
|
where
|
||||||
|
T: Into<TlvInteger>,
|
||||||
|
{
|
||||||
|
fn from(value: T) -> Self {
|
||||||
|
Self::Integer(value.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<i8> for TlvInteger {
|
||||||
|
fn from(value: i8) -> Self {
|
||||||
|
Self::OneByte(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<i16> for TlvInteger {
|
||||||
|
fn from(value: i16) -> Self {
|
||||||
|
Self::TwoBytes(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<i32> for TlvInteger {
|
||||||
|
fn from(value: i32) -> Self {
|
||||||
|
Self::FourBytes(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<i64> for TlvInteger {
|
||||||
|
fn from(value: i64) -> Self {
|
||||||
|
Self::EightBytes(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum TlvUnsignedInteger {
|
||||||
|
OneByte(u8),
|
||||||
|
TwoBytes(u16),
|
||||||
|
FourBytes(u32),
|
||||||
|
EightBytes(u64),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TlvUnsignedInteger {
|
||||||
|
pub fn to_le_bytes(&self) -> Vec<u8> {
|
||||||
|
match self {
|
||||||
|
TlvUnsignedInteger::OneByte(v) => v.to_le_bytes().to_vec(),
|
||||||
|
TlvUnsignedInteger::TwoBytes(v) => v.to_le_bytes().to_vec(),
|
||||||
|
TlvUnsignedInteger::FourBytes(v) => v.to_le_bytes().to_vec(),
|
||||||
|
TlvUnsignedInteger::EightBytes(v) => v.to_le_bytes().to_vec(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u8> for TlvUnsignedInteger {
|
||||||
|
fn from(value: u8) -> Self {
|
||||||
|
Self::OneByte(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u16> for TlvUnsignedInteger {
|
||||||
|
fn from(value: u16) -> Self {
|
||||||
|
Self::TwoBytes(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u32> for TlvUnsignedInteger {
|
||||||
|
fn from(value: u32) -> Self {
|
||||||
|
Self::FourBytes(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u64> for TlvUnsignedInteger {
|
||||||
|
fn from(value: u64) -> Self {
|
||||||
|
Self::EightBytes(value)
|
||||||
|
}
|
||||||
|
}
|
258
homekit-controller/src/tlv8/mod.rs
Normal file
258
homekit-controller/src/tlv8/mod.rs
Normal file
|
@ -0,0 +1,258 @@
|
||||||
|
mod data_types;
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
|
pub use data_types::{TlvData, TlvInteger, TlvType, TlvUnsignedInteger};
|
||||||
|
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
|
pub fn decode(data: &[u8]) -> Result<HashMap<u8, Vec<u8>>, TlvError> {
|
||||||
|
let mut tlvs = HashMap::new();
|
||||||
|
let mut data = data;
|
||||||
|
|
||||||
|
while data.len() > 0 {
|
||||||
|
let tlv_len = (data[1] as usize) + 2;
|
||||||
|
let current;
|
||||||
|
(current, data) = data.split_at(tlv_len);
|
||||||
|
|
||||||
|
if data.len() < 3 {
|
||||||
|
return Err(TlvError::TooShort);
|
||||||
|
}
|
||||||
|
|
||||||
|
if data.len() < tlv_len {
|
||||||
|
return Err(TlvError::WrongLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
let tlv_type = current[0];
|
||||||
|
let tlv_data = current[2..].to_vec();
|
||||||
|
tlvs.insert(tlv_type, tlv_data);
|
||||||
|
}
|
||||||
|
Ok(tlvs)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decode_single(data: &[u8]) -> Result<(u8, Vec<u8>), TlvError> {
|
||||||
|
let tlv_type = data[0];
|
||||||
|
let tlv_len = data[1];
|
||||||
|
let data = &data[2..];
|
||||||
|
Ok((tlv_type, if tlv_len == 0 { vec![] } else { data.to_vec() }))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
pub enum TlvError {
|
||||||
|
#[error("too short")]
|
||||||
|
TooShort,
|
||||||
|
#[error("wrong length")]
|
||||||
|
WrongLength,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait TlvEncode {
|
||||||
|
fn encode(&self) -> Vec<u8>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// impl<const N: usize> TlvEncode for &[(u8, Vec<u8>); N] {
|
||||||
|
// fn encode(&self) -> Vec<u8> {
|
||||||
|
// (*self as &[(u8, Vec<u8>)]).encode()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
impl<T> TlvEncode for T
|
||||||
|
where
|
||||||
|
T: AsRef<[(u8, Vec<u8>)]>,
|
||||||
|
{
|
||||||
|
fn encode(&self) -> Vec<u8> {
|
||||||
|
self.as_ref()
|
||||||
|
.iter()
|
||||||
|
.flat_map(|(tlv_type, tlv_data)| {
|
||||||
|
let length = tlv_data.len() as u32;
|
||||||
|
let packets = tlv_data
|
||||||
|
.chunks(255)
|
||||||
|
.enumerate()
|
||||||
|
.flat_map(|(packet_num, data)| {
|
||||||
|
let mut packet = vec![*tlv_type];
|
||||||
|
packet.push((length - 255 * (packet_num as u32)) as u8);
|
||||||
|
packet.extend_from_slice(data);
|
||||||
|
packet
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
if packets.is_empty() {
|
||||||
|
let mut first_packet = vec![*tlv_type];
|
||||||
|
first_packet.extend_from_slice(&length.to_le_bytes());
|
||||||
|
first_packet.push(0);
|
||||||
|
first_packet
|
||||||
|
} else {
|
||||||
|
packets
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Tlv(u8, TlvData);
|
||||||
|
|
||||||
|
impl Tlv {
|
||||||
|
pub fn new<A: Into<u8>>(tlv_type: A, tlv_data: TlvData) -> Self {
|
||||||
|
Self(tlv_type.into(), tlv_data)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn encode(&self) -> Vec<u8> {
|
||||||
|
let Tlv(tlv_type, data) = self;
|
||||||
|
let bytes = match data {
|
||||||
|
TlvData::Bytes(v) => v.clone(),
|
||||||
|
TlvData::Tlv8(v) => todo!(),
|
||||||
|
TlvData::Integer(v) => v.to_le_bytes(),
|
||||||
|
TlvData::Float(v) => v.to_le_bytes().to_vec(),
|
||||||
|
TlvData::String(v) => v.as_bytes().to_vec(),
|
||||||
|
TlvData::Uint(v) => v.to_le_bytes(),
|
||||||
|
};
|
||||||
|
let length = bytes.len() as u32;
|
||||||
|
let packets = bytes
|
||||||
|
.chunks(255)
|
||||||
|
.enumerate()
|
||||||
|
.flat_map(|(packet_num, data)| {
|
||||||
|
let mut packet = vec![*tlv_type];
|
||||||
|
packet.push((length - 255 * (packet_num as u32)) as u8);
|
||||||
|
packet.extend_from_slice(data);
|
||||||
|
packet
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
if packets.is_empty() {
|
||||||
|
let mut first_packet = vec![*tlv_type];
|
||||||
|
first_packet.extend_from_slice(&length.to_le_bytes());
|
||||||
|
first_packet.push(0);
|
||||||
|
first_packet
|
||||||
|
} else {
|
||||||
|
packets
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn decode_single(data: &[u8]) -> Result<Self, TlvError> {
|
||||||
|
let tlv_type = data[0];
|
||||||
|
let tlv_len = data[1];
|
||||||
|
let data = &data[2..];
|
||||||
|
Ok(Self(
|
||||||
|
tlv_type,
|
||||||
|
TlvData::Bytes(if tlv_len == 0 { vec![] } else { data.to_vec() }),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn tlv_type(&self) -> u8 {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn tlv_data(&self) -> &TlvData {
|
||||||
|
&self.1
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_type<T: Into<u8>>(&self, value: T) -> bool {
|
||||||
|
self.0 == value.into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TlvData {
|
||||||
|
pub fn as_bytes(&self) -> Vec<u8> {
|
||||||
|
match self {
|
||||||
|
TlvData::Bytes(val) => val.clone(),
|
||||||
|
TlvData::Tlv8(_val) => todo!(),
|
||||||
|
TlvData::Integer(val) => val.to_le_bytes(),
|
||||||
|
TlvData::Float(_val) => todo!(),
|
||||||
|
TlvData::String(val) => val.as_bytes().to_vec(),
|
||||||
|
TlvData::Uint(val) => val.to_le_bytes(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait TlvEncodableData {
|
||||||
|
fn encode_value(&self) -> Vec<u8>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const N: usize> TlvEncodableData for &[u8; N] {
|
||||||
|
fn encode_value(&self) -> Vec<u8> {
|
||||||
|
(*self as &[u8]).encode_value()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TlvEncodableData for &[u8] {
|
||||||
|
fn encode_value(&self) -> Vec<u8> {
|
||||||
|
self.to_vec()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TlvEncodableData for i8 {
|
||||||
|
fn encode_value(&self) -> Vec<u8> {
|
||||||
|
self.to_le_bytes().to_vec()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TlvEncodableData for i16 {
|
||||||
|
fn encode_value(&self) -> Vec<u8> {
|
||||||
|
self.to_le_bytes().to_vec()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TlvEncodableData for i32 {
|
||||||
|
fn encode_value(&self) -> Vec<u8> {
|
||||||
|
self.to_le_bytes().to_vec()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TlvEncodableData for i64 {
|
||||||
|
fn encode_value(&self) -> Vec<u8> {
|
||||||
|
self.to_le_bytes().to_vec()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TlvEncodableData for isize {
|
||||||
|
fn encode_value(&self) -> Vec<u8> {
|
||||||
|
self.to_le_bytes().to_vec()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TlvEncodableData for u8 {
|
||||||
|
fn encode_value(&self) -> Vec<u8> {
|
||||||
|
self.to_le_bytes().to_vec()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TlvEncodableData for u16 {
|
||||||
|
fn encode_value(&self) -> Vec<u8> {
|
||||||
|
self.to_le_bytes().to_vec()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TlvEncodableData for u32 {
|
||||||
|
fn encode_value(&self) -> Vec<u8> {
|
||||||
|
self.to_le_bytes().to_vec()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TlvEncodableData for u64 {
|
||||||
|
fn encode_value(&self) -> Vec<u8> {
|
||||||
|
self.to_le_bytes().to_vec()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TlvEncodableData for usize {
|
||||||
|
fn encode_value(&self) -> Vec<u8> {
|
||||||
|
self.to_le_bytes().to_vec()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TlvEncodableData for f32 {
|
||||||
|
fn encode_value(&self) -> Vec<u8> {
|
||||||
|
self.to_le_bytes().to_vec()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TlvEncodableData for f64 {
|
||||||
|
fn encode_value(&self) -> Vec<u8> {
|
||||||
|
self.to_le_bytes().to_vec()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TlvEncodableData for String {
|
||||||
|
fn encode_value(&self) -> Vec<u8> {
|
||||||
|
self.as_bytes().to_vec()
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue