diff --git a/domo_proto/Cargo.lock b/domo_proto/Cargo.lock index e2a74fd..a09f7b4 100644 --- a/domo_proto/Cargo.lock +++ b/domo_proto/Cargo.lock @@ -22,4 +22,64 @@ name = "domo_proto" version = "0.1.0" dependencies = [ "crc32fast", + "rand", ] + +[[package]] +name = "getrandom" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "libc" +version = "0.2.149" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" diff --git a/domo_proto/Cargo.toml b/domo_proto/Cargo.toml index d861428..dc53571 100644 --- a/domo_proto/Cargo.toml +++ b/domo_proto/Cargo.toml @@ -6,4 +6,5 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -crc32fast = "1.3.2" \ No newline at end of file +crc32fast = "1.3.2" +rand = "0.8.5" \ No newline at end of file diff --git a/domo_proto/src/commands/mod.rs b/domo_proto/src/commands/mod.rs index 07461e3..0ab4552 100644 --- a/domo_proto/src/commands/mod.rs +++ b/domo_proto/src/commands/mod.rs @@ -1,6 +1,4 @@ -use crate::packet::packet_data::PacketData; +use crate::packet::Packet; pub mod node_management; pub mod property_control; - -pub trait Command: Into + From {} diff --git a/domo_proto/src/commands/node_management.rs b/domo_proto/src/commands/node_management.rs index 8029d4c..1436d04 100644 --- a/domo_proto/src/commands/node_management.rs +++ b/domo_proto/src/commands/node_management.rs @@ -1,4 +1,6 @@ use crate::packet::identifier::Identifier; +use crate::packet::{Packet, ToPacket}; +use crate::packet::packet_data::PacketData; pub enum NodeManagement { Ping, @@ -7,14 +9,105 @@ pub enum NodeManagement { RegisterProperty { property_name: String, data_type: u8, - read_only: bool + read_only: bool, }, RemoveProperty { property_name: String, }, Error { error_code: u8, - metadata: [u8; 0xFFFF] + metadata: [u8; 0xFFFF], + }, +} + +impl NodeManagement { + fn get_command(&self) -> u8 { + match self { + NodeManagement::Ping => 0x00, + NodeManagement::RegisterNode { .. } => 0x01, + NodeManagement::RemoveNode => 0x02, + NodeManagement::RegisterProperty { .. } => 0x03, + NodeManagement::RemoveProperty { .. } => 0x04, + NodeManagement::Error { .. } => 0x0E + } + } +} + +impl Into for Packet { + fn into(self) -> NodeManagement { + match self { + Packet::V1 { + src, + dest, + packet_id, + reply_to, + command, + data, + } => match command { + 0x00 => NodeManagement::Ping, + 0x01 => NodeManagement::RegisterNode { device_id: src }, + 0x02 => NodeManagement::RemoveNode, + 0x03 => NodeManagement::RegisterProperty { + property_name: String::from_utf8(data.get_data()[..32].to_vec()).unwrap(), + data_type: data.get_data()[33], + read_only: data.get_data()[34] != 0 + }, + 0x04 => NodeManagement::RemoveProperty { + property_name: String::from_utf8(data.get_data()[..32].to_vec()).unwrap() + }, + 0x0E => NodeManagement::Error { + error_code: data.get_data()[0], + metadata: { + let mut metadata = [0_u8; 0xFFFF]; + let data_slice = data.get_data(); + let metadata_length = u16::from_be_bytes([data_slice[1], data_slice[2]]) as usize; + if metadata_length <= 0xFFFF { + metadata[..metadata_length].copy_from_slice(&data_slice[3..(3 + metadata_length)]); + } + metadata + } + }, + _ => unreachable!("Invalid command in Packet::V1"), + }, + } + } +} + + +impl Into for NodeManagement { + fn into(self) -> PacketData { + match self { + NodeManagement::Ping => PacketData::default(), + NodeManagement::RegisterNode { device_id } => PacketData::new(Vec::from(device_id.bytes)), + NodeManagement::RemoveNode => PacketData::default(), + NodeManagement::RegisterProperty { property_name, data_type, read_only } => PacketData::new({ + let mut vec = vec![]; + vec.extend(property_name.into_bytes()); + vec.push(data_type); + vec.push(read_only as u8); + vec + }), + NodeManagement::RemoveProperty { property_name } => PacketData::new(property_name.into_bytes()), + NodeManagement::Error { error_code, metadata } => PacketData::new({ + let mut vec = vec![]; + vec.push(error_code); + vec.extend_from_slice(metadata.as_ref()); + vec + }) + } + } +} + +impl ToPacket for NodeManagement { + fn to_v1_packet(self, src: Identifier, dest: Identifier, packet_id: Identifier, reply_to: Identifier) -> Packet { + Packet::V1 { + src, + dest, + packet_id, + reply_to, + command: self.get_command(), + data: self.into() + } } } @@ -24,7 +117,9 @@ pub enum NodeManagementError { net_broken_packet, net_invalid_packet, - errc_not_registered + errc_not_registered, + + errs_not_delivered, } impl NodeManagementError { @@ -33,7 +128,8 @@ impl NodeManagementError { NodeManagementError::net_duplicate_packet => 0x00, NodeManagementError::net_broken_packet => 0x01, NodeManagementError::net_invalid_packet => 0x02, - NodeManagementError::errc_not_registered => 0x10 + NodeManagementError::errc_not_registered => 0x10, + NodeManagementError::errs_not_delivered => 0x20 } } } diff --git a/domo_proto/src/packet/data_types.rs b/domo_proto/src/packet/data_types.rs index 6304f9d..e8d0f84 100644 --- a/domo_proto/src/packet/data_types.rs +++ b/domo_proto/src/packet/data_types.rs @@ -1,5 +1,5 @@ use crate::packet::identifier::Identifier; -use crate::prelude::{as_u32_be, as_u64_be}; +use crate::prelude::as_u64_be; #[derive(Debug, Eq, PartialEq)] pub enum DataType { diff --git a/domo_proto/src/packet/identifier.rs b/domo_proto/src/packet/identifier.rs index a89da1c..acf5da4 100644 --- a/domo_proto/src/packet/identifier.rs +++ b/domo_proto/src/packet/identifier.rs @@ -1,10 +1,17 @@ use std::fmt::{Display, Formatter, LowerHex}; +use rand::random; #[derive(Debug, Eq, PartialEq, Copy, Clone)] pub struct Identifier { pub bytes: [u8; 4], } +impl Identifier { + pub fn random() -> Identifier { + Identifier::from(random::()) + } +} + impl Display for Identifier { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { write!( diff --git a/domo_proto/src/packet/mod.rs b/domo_proto/src/packet/mod.rs index 8160c05..1207ceb 100644 --- a/domo_proto/src/packet/mod.rs +++ b/domo_proto/src/packet/mod.rs @@ -7,6 +7,7 @@ use identifier::Identifier; use packet_data::PacketData; use std::convert::TryFrom; use std::fmt::Debug; +use std::io::Read; #[derive(Debug)] pub enum Packet { @@ -23,7 +24,19 @@ pub enum Packet { impl Packet { pub fn packet_id(&self) -> Identifier { match self { - Packet::V1 { packet_id, ..} => packet_id.clone() + 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() } } @@ -98,3 +111,7 @@ impl Into> for Packet { self.build_full_packet() } } + +pub trait ToPacket { + fn to_v1_packet(self, src: Identifier, dest: Identifier, packet_id: Identifier, reply_to: Identifier) -> Packet; +} \ No newline at end of file diff --git a/domo_proto/src/packet/packet_data.rs b/domo_proto/src/packet/packet_data.rs index 2c83b8e..0e4d008 100644 --- a/domo_proto/src/packet/packet_data.rs +++ b/domo_proto/src/packet/packet_data.rs @@ -1,4 +1,4 @@ -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct PacketData { data: Vec, }