diag_reader: raise parsing/hdlc error handling to caller

This'll let us unit test the reader more easily
This commit is contained in:
Will Greenberg
2023-12-24 13:24:37 -08:00
parent 0f2e4676e5
commit ef42dfe99f
4 changed files with 51 additions and 30 deletions

View File

@@ -75,12 +75,21 @@ fn main() -> Result<(), WavehunterError> {
.map_err(WavehunterError::PcapFileWriteError)?;
loop {
for msg in dev.read_response().map_err(WavehunterError::DiagReadError)? {
debug!("msg: {:?}", msg);
if let Some((timestamp, gsmtap_msg)) = gsmtap_parser.recv_message(msg).map_err(WavehunterError::GsmtapParsingError)? {
debug!("gsmtap_msg: {:?}", gsmtap_msg);
pcap_file.write_gsmtap_message(gsmtap_msg, timestamp)
.map_err(WavehunterError::PcapFileWriteError)?;
for maybe_msg in dev.read_response().map_err(WavehunterError::DiagReadError)? {
match maybe_msg {
Ok(msg) => {
debug!("msg: {:?}", msg);
let maybe_gsmtap_msg = gsmtap_parser.recv_message(msg)
.map_err(WavehunterError::GsmtapParsingError)?;
if let Some((timestamp, gsmtap_msg)) = maybe_gsmtap_msg {
debug!("gsmtap_msg: {:?}", gsmtap_msg);
pcap_file.write_gsmtap_message(gsmtap_msg, timestamp)
.map_err(WavehunterError::PcapFileWriteError)?;
}
},
Err(e) => {
dbg!("error parsing message: {:?}", e);
},
}
}
}

View File

@@ -20,21 +20,21 @@ fn main() {
pcap_file.write_iface_header().unwrap();
loop {
match qmdl_reader.read_response() {
Ok(msgs) => {
for msg in msgs {
for maybe_msg in qmdl_reader.read_response().expect("error reading qmdl file") {
match maybe_msg {
Ok(msg) => {
debug!("msg: {:?}", msg);
if let Some((timestamp, gsmtap_msg)) = gsmtap_parser.recv_message(msg).unwrap() {
let maybe_gsmtap_msg = gsmtap_parser.recv_message(msg).expect("error parsing gsmtap message");
if let Some((timestamp, gsmtap_msg)) = maybe_gsmtap_msg {
debug!("gsmtap_msg: {:?}", gsmtap_msg);
pcap_file.write_gsmtap_message(gsmtap_msg, timestamp).unwrap();
pcap_file.write_gsmtap_message(gsmtap_msg, timestamp)
.expect("error writing pcap packet");
}
}
},
Err(err) if err.kind() == std::io::ErrorKind::UnexpectedEof => {
println!("Reached end of QMDL file, exiting...");
std::process::exit(0);
},
Err(err) => panic!("Error reading QMDL file {}", err),
},
Err(e) => {
dbg!("error parsing message: {:?}", e);
},
}
}
}
}

View File

@@ -137,8 +137,8 @@ impl DiagDevice {
for msg in self.read_response()? {
match msg {
Message::Log { .. } => info!("skipping log response..."),
Message::Response { payload, status, .. } => match payload {
Ok(Message::Log { .. }) => info!("skipping log response..."),
Ok(Message::Response { payload, status, .. }) => match payload {
ResponsePayload::LogConfig(LogConfigResponse::RetrieveIdRanges { log_mask_sizes }) => {
if status != 0 {
return Err(DiagDeviceError::RequestFailed(status, req));
@@ -147,6 +147,7 @@ impl DiagDevice {
},
_ => info!("skipping non-LogConfigResponse response..."),
},
Err(e) => error!("error parsing message: {:?}", e),
}
}
@@ -159,8 +160,8 @@ impl DiagDevice {
for msg in self.read_response()? {
match msg {
Message::Log { .. } => info!("skipping log response..."),
Message::Response { payload, status, .. } => {
Ok(Message::Log { .. }) => info!("skipping log response..."),
Ok(Message::Response { payload, status, .. }) => {
if let ResponsePayload::LogConfig(LogConfigResponse::SetMask) = payload {
if status != 0 {
return Err(DiagDeviceError::RequestFailed(status, req));
@@ -168,6 +169,7 @@ impl DiagDevice {
return Ok(());
}
},
Err(e) => error!("error parsing message: {:?}", e),
}
}

View File

@@ -1,9 +1,11 @@
use crate::diag;
use crate::{diag::*, hdlc::hdlc_decapsulate};
use crate::hdlc;
use crc::{Crc, Algorithm};
use deku::prelude::*;
use log::{debug, info, warn, error};
use log::{info, warn, error};
use thiserror::Error;
// this is sorta based on the params qcsuper uses, plus what seems to be used in
// https://github.com/fgsect/scat/blob/f1538b397721df3ab8ba12acd26716abcf21f78b/util.py#L47
@@ -19,12 +21,22 @@ pub const CRC_CCITT_ALG: Algorithm<u16> = Algorithm {
};
pub const CRC_CCITT: Crc<u16> = Crc::<u16>::new(&CRC_CCITT_ALG);
#[derive(Debug, Error)]
pub enum DiagParsingError {
#[error("Failed to parse Message: {0}, data: {1:?}")]
MessageParsingError(deku::DekuError, Vec<u8>),
#[error("HDLC decapsulation of message failed: {0}, data: {1:?}")]
HdlcDecapsulationError(hdlc::HdlcError, Vec<u8>),
}
type MaybeMessage = Result<Message, DiagParsingError>;
pub trait DiagReader {
type Err;
fn get_next_messages_container(&mut self) -> Result<MessagesContainer, Self::Err>;
fn read_response(&mut self) -> Result<Vec<Message>, Self::Err> {
fn read_response(&mut self) -> Result<Vec<MaybeMessage>, Self::Err> {
loop {
let container = self.get_next_messages_container()?;
if container.data_type == DataType::UserSpace {
@@ -35,7 +47,7 @@ pub trait DiagReader {
}
}
fn parse_response_container(&self, container: MessagesContainer) -> Result<Vec<Message>, Self::Err> {
fn parse_response_container(&self, container: MessagesContainer) -> Result<Vec<MaybeMessage>, Self::Err> {
let mut result = Vec::new();
for msg in container.messages {
for sub_msg in msg.data.split_inclusive(|&b| b == diag::MESSAGE_TERMINATOR) {
@@ -45,16 +57,14 @@ pub trait DiagReader {
if leftover_bytes.len() > 0 {
warn!("warning: {} leftover bytes when parsing Message", leftover_bytes.len());
}
result.push(res);
result.push(Ok(res));
},
Err(e) => {
error!("error parsing response: {:?}", e);
debug!("{:?}", data);
result.push(Err(DiagParsingError::MessageParsingError(e, data)));
},
},
Err(err) => {
error!("error decapsulating response: {:?}", err);
debug!("{:?}", &sub_msg);
result.push(Err(DiagParsingError::HdlcDecapsulationError(err, sub_msg.to_vec())));
}
}
}