From 2504a1da2e82237ebbd65cad5e8be4047c53006f Mon Sep 17 00:00:00 2001 From: Will Greenberg Date: Wed, 13 Dec 2023 13:05:47 -0800 Subject: [PATCH] add failsafe writer and reader --- Cargo.toml | 4 ++ src/diag_device.rs | 129 ++++++++++++++++++++++++++++++++--------- src/failsafe_reader.rs | 22 +++++++ src/main.rs | 2 +- 4 files changed, 129 insertions(+), 28 deletions(-) create mode 100644 src/failsafe_reader.rs diff --git a/Cargo.toml b/Cargo.toml index 38eabfd..2818110 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,6 +5,10 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[[bin]] +name = "failsafe_reader" +path = "src/failsafe_reader.rs" + [dependencies] bytes = "1.5.0" chrono = "0.4.31" diff --git a/src/diag_device.rs b/src/diag_device.rs index 9989fd3..0a5540f 100644 --- a/src/diag_device.rs +++ b/src/diag_device.rs @@ -3,7 +3,7 @@ use crate::diag::{Message, ResponsePayload, Request, LogConfigRequest, LogConfig use crate::log_codes; use std::fs::File; -use std::io::Read; +use std::io::{Read, Write, Seek}; use std::os::fd::AsRawFd; use thiserror::Error; use crc::{Crc, Algorithm}; @@ -41,6 +41,7 @@ pub const CRC_CCITT_ALG: Algorithm = Algorithm { check: 0x2189, residue: 0x0000, }; +pub const CRC_CCITT: Crc = Crc::::new(&CRC_CCITT_ALG); pub const LOG_CODES_FOR_RAW_PACKET_LOGGING: [u32; 11] = [ // Layer 2: @@ -68,33 +69,55 @@ const MEMORY_DEVICE_MODE: i32 = 2; const DIAG_IOCTL_REMOTE_DEV: u32 = 32; const DIAG_IOCTL_SWITCH_LOGGING: u32 = 7; +const FAILSAFE_PATH: &str = "/data/wavehunter-failsafe"; + pub struct DiagDevice<'a> { file: &'a File, + failsafe_file: File, read_buf: Vec, use_mdm: i32, - crc: Crc, } -impl<'a> DiagDevice<'a> { - pub fn new(file: &'a File) -> DiagResult { - let fd = file.as_raw_fd(); +#[derive(Debug, DekuRead, DekuWrite)] +#[deku(endian = "little")] +struct FailsafeReadBlock<'a> { + size: u32, + #[deku(count = "size")] + data: &'a [u8], +} - enable_frame_readwrite(fd, MEMORY_DEVICE_MODE)?; - let use_mdm = determine_use_mdm(fd)?; +pub struct FailsafeFileReader { + file: File, +} - Ok(DiagDevice { - read_buf: vec![0; BUFFER_LEN], - file, - crc: Crc::::new(&CRC_CCITT_ALG), - use_mdm, - }) +impl FailsafeFileReader { + pub fn new

(path: P) -> DiagResult where P: AsRef { + let file = std::fs::File::options() + .read(true) + .open(path)?; + Ok(FailsafeFileReader { file }) + } +} + +pub trait DiagInterface { + fn get_next_messages_container(&mut self) -> DiagResult; + + fn read_response(&mut self) -> DiagResult> { + loop { + let container = self.get_next_messages_container()?; + if container.data_type == DataType::UserSpace { + return self.parse_response_container(container); + } else { + println!("skipping non-userspace message...") + } + } } fn parse_response_container(&self, container: MessagesContainer) -> DiagResult> { let mut result = Vec::new(); for msg in container.messages { for sub_msg in msg.data.split_inclusive(|&b| b == 0x7e) { - match hdlc_decapsulate(&sub_msg, &self.crc) { + match hdlc_decapsulate(&sub_msg, &CRC_CCITT) { Ok(data) => match Message::from_bytes((&data, 0)) { Ok(((leftover_bytes, _), res)) => { if leftover_bytes.len() > 0 { @@ -116,28 +139,80 @@ impl<'a> DiagDevice<'a> { } Ok(result) } +} - pub fn read_response(&mut self) -> DiagResult> { - loop { - let bytes_read = self.file.read(&mut self.read_buf).unwrap(); - let ((leftover_bytes, _), res_container) = MessagesContainer::from_bytes((&self.read_buf[0..bytes_read], 0))?; - if leftover_bytes.len() > 0 { - println!("warning: {} leftover bytes when parsing MessagesContainer", leftover_bytes.len()); - } - if res_container.data_type == DataType::UserSpace { - return self.parse_response_container(res_container); - } else { - println!("skipping non-userspace message...") - } + +impl DiagInterface for FailsafeFileReader { + fn get_next_messages_container(&mut self) -> DiagResult { + let mut bytes_read_buf = [0; 4]; + match self.file.read_exact(&mut bytes_read_buf) { + Ok(_) => {}, + Err(e) => { + dbg!(e.kind()); + if e.kind() == std::io::ErrorKind::UnexpectedEof { + println!("reached end of failsafe file, exiting..."); + std::process::exit(0); + } + return Err(e.into()); + }, } + let bytes_read = u32::from_le_bytes(bytes_read_buf) as usize; + let mut data = vec![0; bytes_read as usize]; + self.file.read_exact(&mut data)?; + let ((leftover_bytes, _), container) = MessagesContainer::from_bytes((&data, 0))?; + if leftover_bytes.len() > 0 { + println!("warning: {} leftover bytes when parsing MessagesContainer", leftover_bytes.len()); + } + Ok(container) } +} + +impl<'a> DiagInterface for DiagDevice<'a> { + fn get_next_messages_container(&mut self) -> DiagResult { + let bytes_read = self.file.read(&mut self.read_buf).unwrap(); + { + let failsafe_block = FailsafeReadBlock { + size: bytes_read as u32, + data: &self.read_buf[0..bytes_read], + }; + let failsafe_block_bytes = failsafe_block.to_bytes().unwrap(); + self.failsafe_file.write_all(&failsafe_block_bytes).unwrap(); + } + let ((leftover_bytes, _), container) = MessagesContainer::from_bytes((&self.read_buf[0..bytes_read], 0))?; + if leftover_bytes.len() > 0 { + println!("warning: {} leftover bytes when parsing MessagesContainer", leftover_bytes.len()); + } + Ok(container) + } +} + +impl<'a> DiagDevice<'a> { + pub fn new(file: &'a File) -> DiagResult { + let fd = file.as_raw_fd(); + + enable_frame_readwrite(fd, MEMORY_DEVICE_MODE)?; + let use_mdm = determine_use_mdm(fd)?; + + let failsafe_file = std::fs::File::options() + .create(true) + .write(true) + .open(FAILSAFE_PATH)?; + + Ok(DiagDevice { + read_buf: vec![0; BUFFER_LEN], + file, + failsafe_file, + use_mdm, + }) + } + pub fn write_request(&mut self, req: &Request) -> DiagResult<()> { let buf = RequestContainer { data_type: DataType::UserSpace, use_mdm: self.use_mdm > 0, mdm_field: -1, - hdlc_encapsulated_request: hdlc_encapsulate(&req.to_bytes().unwrap(), &self.crc), + hdlc_encapsulated_request: hdlc_encapsulate(&req.to_bytes().unwrap(), &CRC_CCITT), }.to_bytes().unwrap(); unsafe { let fd = self.file.as_raw_fd(); diff --git a/src/failsafe_reader.rs b/src/failsafe_reader.rs new file mode 100644 index 0000000..7d57c39 --- /dev/null +++ b/src/failsafe_reader.rs @@ -0,0 +1,22 @@ +mod hdlc; +mod diag; +mod diag_device; +mod log_codes; + +use crate::diag_device::{FailsafeFileReader, DiagInterface}; + +fn main() -> diag_device::DiagResult<()> { + // this should eventually be removed for prod + env_logger::init(); + let args: Vec = std::env::args().collect(); + if args.len() != 2 { + println!("Usage: {} /path/to/failsafe/file", args[0]); + } + let mut failsafe_reader = FailsafeFileReader::new(&args[1])?; + + loop { + for msg in failsafe_reader.read_response()? { + println!("msg: {:?}", msg); + } + } +} diff --git a/src/main.rs b/src/main.rs index 1d56fa4..28b17ee 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,7 +3,7 @@ mod diag; mod diag_device; mod log_codes; -use crate::diag_device::DiagDevice; +use crate::diag_device::{DiagDevice, DiagInterface}; fn main() -> diag_device::DiagResult<()> { // this should eventually be removed for prod