From 2710dae2d886fd2a9e949e2a343de5f343bb340d Mon Sep 17 00:00:00 2001 From: Toby Vincent Date: Mon, 19 Aug 2024 17:15:40 -0500 Subject: feat: impl basic tplink message protocol --- .gitignore | 1 + Cargo.lock | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 9 ++++++ src/error.rs | 10 +++++++ src/lib.rs | 4 +++ src/main.rs | 3 ++ src/protocol.rs | 63 ++++++++++++++++++++++++++++++++++++++ 7 files changed, 183 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 src/error.rs create mode 100644 src/lib.rs create mode 100644 src/main.rs create mode 100644 src/protocol.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..daeaedf --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,93 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "main_error" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "155db5e86c6e45ee456bf32fad5a290ee1f7151c2faca27ea27097568da67d1a" + +[[package]] +name = "nrgmon" +version = "0.1.0" +dependencies = [ + "main_error", + "serde", + "thiserror", +] + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "serde" +version = "1.0.208" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cff085d2cb684faa248efb494c39b68e522822ac0de72ccf08109abde717cfb2" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.208" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24008e81ff7613ed8e5ba0cfaf24e2c2f1e5b8a0495711e44fcd4882fca62bcf" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "syn" +version = "2.0.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6af063034fc1935ede7be0122941bafa9bacb949334d090b77ca98b5817c7d9" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..9a2d0b0 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "nrgmon" +version = "0.1.0" +edition = "2021" + +[dependencies] +main_error = "0.1.2" +serde = { version = "1.0.208", features = ["derive"] } +thiserror = "1.0.63" diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 0000000..ec03758 --- /dev/null +++ b/src/error.rs @@ -0,0 +1,10 @@ +pub type Result = std::result::Result; + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("IO error: {0}")] + IO(#[from] std::io::Error), + + #[error("Invalid UTF-8: {0}")] + Utf8(#[from] std::str::Utf8Error), +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..faceb2c --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,4 @@ +pub use error::{Error, Result}; + +pub mod error; +pub mod protocol; diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..05ea213 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,3 @@ +fn main() -> Result<(), main_error::MainError> { + Ok(()) +} diff --git a/src/protocol.rs b/src/protocol.rs new file mode 100644 index 0000000..9e5edbe --- /dev/null +++ b/src/protocol.rs @@ -0,0 +1,63 @@ +use crate::Error; + +const KEY: u8 = 0xAB; + +pub fn encrypt(msg: &mut [u8]) { + let mut key = KEY; + msg.iter_mut().for_each(|b| { + key ^= *b; + *b = key; + }); +} + +pub fn decrypt(bytes: &mut [u8]) { + let mut key = KEY; + bytes.iter_mut().for_each(|b| { + let xor = *b ^ key; + key = *b; + *b = xor; + }); +} + +pub fn recv(r: &mut R) -> Result { + let mut buf = [0; 4]; + r.read_exact(&mut buf)?; + + let mut buf = vec![0; u32::from_be_bytes(buf) as usize]; + r.read_exact(&mut buf)?; + + decrypt(&mut buf); + + let msg = std::str::from_utf8(&buf)?.to_string(); + + Ok(msg) +} + +pub fn send(w: &mut W, msg: &str) -> Result<(), Error> { + let mut buf = msg.as_bytes().to_owned(); + encrypt(&mut buf); + + w.write_all(&(buf.len() as u32).to_be_bytes())?; + w.write_all(&buf)?; + Ok(()) +} + +#[cfg(test)] +pub(crate) mod tests { + use super::*; + + use std::net::TcpStream; + + #[test] + fn test_get_sysinfo() -> Result<(), Error> { + let mut stream = TcpStream::connect("10.42.0.119:9999")?; + send(&mut stream, r#"{"system":{"get_sysinfo":{}}}"#)?; + let msg = recv(&mut stream)?; + + assert!(!msg.is_empty()); + + println!("{msg}"); + + Ok(()) + } +} -- cgit v1.2.3-70-g09d2