summaryrefslogtreecommitdiff
path: root/floss
diff options
context:
space:
mode:
author Archie Pusaka <apusaka@google.com> 2024-08-15 03:26:10 +0000
committer Gerrit Code Review <noreply-gerritcodereview@google.com> 2024-08-15 03:26:10 +0000
commit2886d60f50c8ddfe3dbaafcb93b53d033fc32654 (patch)
treeaffa88e26aa4572a44c226e3561d6f8b633a1c1b /floss
parent8ba42e6bbb0fa94edab18e61c0ecbd7e7a54c7d7 (diff)
parent9d12639d7830038848815c6932ceed788d636b89 (diff)
Merge changes I05da6242,I272f8f04 into main
* changes: Floss: Hcidoc: Support AOSP snoop log Floss: Hcidoc: Refactor hcidoc parser to support other snoop types
Diffstat (limited to 'floss')
-rw-r--r--floss/hcidoc/src/main.rs46
-rw-r--r--floss/hcidoc/src/parser.rs384
2 files changed, 251 insertions, 179 deletions
diff --git a/floss/hcidoc/src/main.rs b/floss/hcidoc/src/main.rs
index 82ded2701c..4589c3ba18 100644
--- a/floss/hcidoc/src/main.rs
+++ b/floss/hcidoc/src/main.rs
@@ -7,7 +7,7 @@ mod parser;
use crate::engine::RuleEngine;
use crate::groups::{collisions, connections, controllers, informational};
-use crate::parser::{LinuxSnoopOpcodes, LogParser, LogType, Packet};
+use crate::parser::{LogParser, Packet, SnoopOpcodes};
fn main() {
let matches = Command::new("hcidoc")
@@ -63,7 +63,7 @@ fn main() {
report_signals = true;
}
- let mut parser = match LogParser::new(filename) {
+ let parser = match LogParser::new(filename) {
Ok(p) => p,
Err(e) => {
println!(
@@ -75,14 +75,6 @@ fn main() {
}
};
- let log_type = match parser.read_log_type() {
- Ok(v) => v,
- Err(e) => {
- println!("Parsing {} failed: {}", filename, e);
- return;
- }
- };
-
// Create engine with default rule groups.
let mut engine = RuleEngine::new();
engine.add_rule_group("Collisions".into(), collisions::get_collisions_group());
@@ -93,29 +85,27 @@ fn main() {
// Decide where to write output.
let mut writer: Box<dyn Write> = Box::new(std::io::stdout());
- if let LogType::LinuxSnoop(_header) = log_type {
- for (pos, v) in parser.get_snoop_iterator().expect("Not a linux snoop file").enumerate() {
- match Packet::try_from((pos, &v)) {
- Ok(p) => engine.process(p),
- Err(e) => {
- if !ignore_unknown_opcode {
- match v.opcode() {
- LinuxSnoopOpcodes::Command | LinuxSnoopOpcodes::Event => {
- eprintln!("#{}: {}", pos, e);
- }
- _ => (),
+ for (pos, v) in parser.get_snoop_iterator().enumerate() {
+ match Packet::try_from((pos, &*v)) {
+ Ok(p) => engine.process(p),
+ Err(e) => {
+ if !ignore_unknown_opcode {
+ match v.opcode() {
+ SnoopOpcodes::Command | SnoopOpcodes::Event => {
+ eprintln!("#{}: {}", pos, e);
}
+ _ => (),
}
}
}
}
+ }
- if !report_only_signals {
- engine.report(&mut writer);
- }
- if report_signals {
- let _ = writeln!(&mut writer, "### Signals ###");
- engine.report_signals(&mut writer);
- }
+ if !report_only_signals {
+ engine.report(&mut writer);
+ }
+ if report_signals {
+ let _ = writeln!(&mut writer, "### Signals ###");
+ engine.report_signals(&mut writer);
}
}
diff --git a/floss/hcidoc/src/parser.rs b/floss/hcidoc/src/parser.rs
index 4bba3aade3..26659bc424 100644
--- a/floss/hcidoc/src/parser.rs
+++ b/floss/hcidoc/src/parser.rs
@@ -1,5 +1,5 @@
//! Parsing of various Bluetooth packets.
-use chrono::NaiveDateTime;
+use chrono::{DateTime, NaiveDateTime};
use num_derive::{FromPrimitive, ToPrimitive};
use num_traits::cast::FromPrimitive;
use std::convert::TryFrom;
@@ -12,29 +12,32 @@ use hcidoc_packets::l2cap::{
LeControlFrameChild,
};
-/// Linux snoop file header format. This format is used by `btmon` on Linux systems that have bluez
-/// installed.
-#[derive(Clone, Copy, Debug)]
-pub struct LinuxSnoopHeader {
- id: [u8; 8],
- version: u32,
- data_type: u32,
+/// Snoop file header format.
+#[derive(Debug)]
+pub struct SnoopHeader {
+ _id: [u8; 8],
+ _version: u32,
+ datalink_type: SnoopDatalinkType,
}
-/// Identifier for a Linux snoop file. In ASCII, this is 'btsnoop\0'.
-const LINUX_SNOOP_MAGIC: [u8; 8] = [0x62, 0x74, 0x73, 0x6e, 0x6f, 0x6f, 0x70, 0x00];
+/// Identifier for a snoop file. In ASCII, this is 'btsnoop\0'.
+const SNOOP_MAGIC: [u8; 8] = [0x62, 0x74, 0x73, 0x6e, 0x6f, 0x6f, 0x70, 0x00];
-/// Snoop files in monitor format will have this value in link type.
-const LINUX_SNOOP_MONITOR_TYPE: u32 = 2001;
+/// Size of snoop header. 8 bytes for magic, 4 bytes for version, and 4 bytes for snoop type.
+const SNOOP_HEADER_SIZE: usize = 16;
-/// Size of snoop header. 8 bytes for magic and another 8 for additional info.
-const LINUX_SNOOP_HEADER_SIZE: usize = 16;
+#[derive(Debug, FromPrimitive, ToPrimitive)]
+#[repr(u32)]
+enum SnoopDatalinkType {
+ H4Uart = 1002,
+ LinuxMonitor = 2001,
+}
-impl TryFrom<&[u8]> for LinuxSnoopHeader {
+impl TryFrom<&[u8]> for SnoopHeader {
type Error = String;
fn try_from(item: &[u8]) -> Result<Self, Self::Error> {
- if item.len() != LINUX_SNOOP_HEADER_SIZE {
+ if item.len() != SNOOP_HEADER_SIZE {
return Err(format!("Invalid size for snoop header: {}", item.len()));
}
@@ -43,35 +46,31 @@ impl TryFrom<&[u8]> for LinuxSnoopHeader {
let (version_bytes, rest) = rest.split_at(std::mem::size_of::<u32>());
let (data_type_bytes, _rest) = rest.split_at(std::mem::size_of::<u32>());
- let header = LinuxSnoopHeader {
- id: id_bytes.try_into().unwrap(),
- version: u32::from_be_bytes(version_bytes.try_into().unwrap()),
- data_type: u32::from_be_bytes(data_type_bytes.try_into().unwrap()),
- };
+ let id = id_bytes.try_into().unwrap();
+ let version = u32::from_be_bytes(version_bytes.try_into().unwrap());
+ let data_type = u32::from_be_bytes(data_type_bytes.try_into().unwrap());
- if header.id != LINUX_SNOOP_MAGIC {
+ if id != SNOOP_MAGIC {
return Err(format!("Id is not 'btsnoop'."));
}
- if header.version != 1 {
- return Err(format!("Version is not supported. Got {}.", header.version));
+ if version != 1 {
+ return Err(format!("Version is not supported. Got {}.", version));
}
- if header.data_type != LINUX_SNOOP_MONITOR_TYPE {
- return Err(format!(
- "Invalid data type in snoop file. We want monitor type ({}) but got {}",
- LINUX_SNOOP_MONITOR_TYPE, header.data_type
- ));
- }
+ let datalink_type = match SnoopDatalinkType::from_u32(data_type) {
+ Some(datalink_type) => datalink_type,
+ None => return Err(format!("Unsupported datalink type {}", data_type)),
+ };
- Ok(header)
+ return Ok(SnoopHeader { _id: id, _version: version, datalink_type });
}
}
-/// Opcodes for Linux snoop packets.
+/// Opcodes for snoop packets.
#[derive(Debug, FromPrimitive, ToPrimitive)]
#[repr(u16)]
-pub enum LinuxSnoopOpcodes {
+pub enum SnoopOpcodes {
NewIndex = 0,
DeleteIndex,
Command,
@@ -96,9 +95,15 @@ pub enum LinuxSnoopOpcodes {
Invalid = 0xffff,
}
-/// Linux snoop file packet format.
+/// Size of packet preamble (everything except the data).
+const SNOOP_PACKET_PREAMBLE_SIZE: usize = 24;
+
+/// Number of microseconds from btsnoop zero to Linux epoch.
+const SNOOP_Y0_TO_Y1970_US: i64 = 62_168_256_000_000_000;
+
+/// Snoop file packet format.
#[derive(Debug, Clone)]
-pub struct LinuxSnoopPacket {
+pub struct SnoopPacketPreamble {
/// The original length of the captured packet as received via a network.
pub original_length: u32,
@@ -107,47 +112,39 @@ pub struct LinuxSnoopPacket {
pub included_length: u32,
pub flags: u32,
pub drops: u32,
- pub timestamp_magic_us: u64,
- pub data: Vec<u8>,
+ pub timestamp_us: u64,
}
-impl LinuxSnoopPacket {
- pub fn adapter_index(&self) -> u16 {
- (self.flags >> 16).try_into().unwrap_or(0u16)
- }
+impl SnoopPacketPreamble {
+ fn from_fd<'a>(fd: &mut Box<dyn BufRead + 'a>) -> Option<SnoopPacketPreamble> {
+ let mut buf = [0u8; SNOOP_PACKET_PREAMBLE_SIZE];
+ match fd.read_exact(&mut buf) {
+ Ok(()) => {}
+ Err(e) => {
+ // |UnexpectedEof| could be seen since we're trying to read more
+ // data than is available (i.e. end of file).
+ if e.kind() != ErrorKind::UnexpectedEof {
+ eprintln!("Error reading preamble: {:?}", e);
+ }
+ return None;
+ }
+ };
- pub fn opcode(&self) -> LinuxSnoopOpcodes {
- LinuxSnoopOpcodes::from_u32(self.flags & 0xffff).unwrap_or(LinuxSnoopOpcodes::Invalid)
+ match SnoopPacketPreamble::try_from(&buf[0..SNOOP_PACKET_PREAMBLE_SIZE]) {
+ Ok(preamble) => Some(preamble),
+ Err(e) => {
+ eprintln!("Error reading preamble: {}", e);
+ None
+ }
+ }
}
}
-/// Size of packet preamble (everything except the data).
-const LINUX_SNOOP_PACKET_PREAMBLE_SIZE: usize = 24;
-
-/// Maximum packet size for snoop is the max ACL size + 4 bytes.
-const LINUX_SNOOP_MAX_PACKET_SIZE: usize = 1486 + 4;
-
-/// Number of seconds from the year 1970 to the year 2000.
-const LINUX_SNOOP_Y2K_OFFSET_IN_SECS: i64 = 946684800i64;
-
-/// Snoop timestamps start at year 0 instead of 1970 like unix timestamps. This
-/// offset is used to represent Jan 1, 2000 AD and can be used to convert back
-/// to unixtime.
-const LINUX_SNOOP_Y2K_EPOCH_USECS: i64 = 0x00E03AB44A676000i64;
-
-/// Microseconds to seconds.
-const USECS_TO_SECS: i64 = 1_000_000i64;
-
-/// Offset from the snoop timestamp to unixtimestamp in seconds. This is a negative number.
-const LINUX_SNOOP_OFFSET_TO_UNIXTIME_SECS: i64 =
- LINUX_SNOOP_Y2K_OFFSET_IN_SECS - (LINUX_SNOOP_Y2K_EPOCH_USECS / USECS_TO_SECS);
-
-// Expect specifically the pre-amble to be read here (and no data).
-impl TryFrom<&[u8]> for LinuxSnoopPacket {
+impl TryFrom<&[u8]> for SnoopPacketPreamble {
type Error = String;
fn try_from(item: &[u8]) -> Result<Self, Self::Error> {
- if item.len() != LINUX_SNOOP_PACKET_PREAMBLE_SIZE {
+ if item.len() != SNOOP_PACKET_PREAMBLE_SIZE {
return Err(format!("Wrong size for snoop packet preamble: {}", item.len()));
}
@@ -159,19 +156,91 @@ impl TryFrom<&[u8]> for LinuxSnoopPacket {
let (ts_bytes, _rest) = rest.split_at(std::mem::size_of::<u64>());
// Note that all bytes are in big-endian because they're network order.
- let packet = LinuxSnoopPacket {
+ let preamble = SnoopPacketPreamble {
original_length: u32::from_be_bytes(orig_len_bytes.try_into().unwrap()),
included_length: u32::from_be_bytes(included_len_bytes.try_into().unwrap()),
flags: u32::from_be_bytes(flags_bytes.try_into().unwrap()),
drops: u32::from_be_bytes(drops_bytes.try_into().unwrap()),
- timestamp_magic_us: u64::from_be_bytes(ts_bytes.try_into().unwrap()),
- data: vec![],
+ timestamp_us: u64::from_be_bytes(ts_bytes.try_into().unwrap()),
};
- Ok(packet)
+ Ok(preamble)
}
}
+pub trait GeneralSnoopPacket {
+ fn adapter_index(&self) -> u16;
+ fn opcode(&self) -> SnoopOpcodes;
+ fn preamble(&self) -> &SnoopPacketPreamble;
+ fn data(&self) -> &Vec<u8>;
+
+ fn get_timestamp(&self) -> Option<NaiveDateTime> {
+ let preamble = self.preamble();
+ let ts_i64 = i64::try_from(preamble.timestamp_us).unwrap_or(i64::MAX);
+ DateTime::from_timestamp_micros(ts_i64 - SNOOP_Y0_TO_Y1970_US).map(|date| date.naive_utc())
+ }
+}
+
+pub struct LinuxSnoopPacket {
+ pub preamble: SnoopPacketPreamble,
+ pub data: Vec<u8>,
+}
+
+impl GeneralSnoopPacket for LinuxSnoopPacket {
+ fn adapter_index(&self) -> u16 {
+ (self.preamble.flags >> 16).try_into().unwrap_or(0u16)
+ }
+ fn opcode(&self) -> SnoopOpcodes {
+ SnoopOpcodes::from_u32(self.preamble.flags & 0xffff).unwrap_or(SnoopOpcodes::Invalid)
+ }
+ fn preamble(&self) -> &SnoopPacketPreamble {
+ &self.preamble
+ }
+ fn data(&self) -> &Vec<u8> {
+ &self.data
+ }
+}
+
+pub struct H4SnoopPacket {
+ pub preamble: SnoopPacketPreamble,
+ pub data: Vec<u8>,
+ pub pkt_type: u8,
+}
+
+impl GeneralSnoopPacket for H4SnoopPacket {
+ fn adapter_index(&self) -> u16 {
+ 0
+ }
+ fn opcode(&self) -> SnoopOpcodes {
+ match self.pkt_type {
+ 0x01 => SnoopOpcodes::Command,
+ 0x02 => match self.preamble.flags & 0x01 {
+ 0x00 => SnoopOpcodes::AclTxPacket,
+ _ => SnoopOpcodes::AclRxPacket,
+ },
+ 0x03 => match self.preamble.flags & 0x01 {
+ 0x00 => SnoopOpcodes::ScoTxPacket,
+ _ => SnoopOpcodes::ScoRxPacket,
+ },
+ 0x04 => SnoopOpcodes::Event,
+ 0x05 => match self.preamble.flags & 0x01 {
+ 0x00 => SnoopOpcodes::IsoTx,
+ _ => SnoopOpcodes::IsoRx,
+ },
+ _ => SnoopOpcodes::Invalid,
+ }
+ }
+ fn preamble(&self) -> &SnoopPacketPreamble {
+ &self.preamble
+ }
+ fn data(&self) -> &Vec<u8> {
+ &self.data
+ }
+}
+
+/// Maximum packet size for snoop is the max ACL size + 4 bytes.
+const SNOOP_MAX_PACKET_SIZE: usize = 1486 + 4;
+
/// Reader for Linux snoop files.
pub struct LinuxSnoopReader<'a> {
fd: Box<dyn BufRead + 'a>,
@@ -184,99 +253,116 @@ impl<'a> LinuxSnoopReader<'a> {
}
impl<'a> Iterator for LinuxSnoopReader<'a> {
- type Item = LinuxSnoopPacket;
+ type Item = Box<dyn GeneralSnoopPacket>;
fn next(&mut self) -> Option<Self::Item> {
- let mut data = [0u8; LINUX_SNOOP_PACKET_PREAMBLE_SIZE];
- match self.fd.read_exact(&mut data) {
- Ok(()) => {}
- Err(e) => {
- // |UnexpectedEof| could be seen since we're trying to read more
- // data than is available (i.e. end of file).
- if e.kind() != ErrorKind::UnexpectedEof {
- eprintln!("Error reading snoop file: {:?}", e);
- }
+ let preamble = match SnoopPacketPreamble::from_fd(&mut self.fd) {
+ Some(preamble) => preamble,
+ None => {
return None;
}
};
- match LinuxSnoopPacket::try_from(&data[0..LINUX_SNOOP_PACKET_PREAMBLE_SIZE]) {
- Ok(mut p) => {
- if p.included_length > 0 {
- let size: usize = p.included_length.try_into().unwrap();
- let mut rem_data = [0u8; LINUX_SNOOP_MAX_PACKET_SIZE];
- match self.fd.read_exact(&mut rem_data[0..size]) {
- Ok(()) => {
- p.data = rem_data[0..size].to_vec();
- Some(p)
- }
- Err(e) => {
- eprintln!("Couldn't read any packet data: {}", e);
- None
- }
- }
- } else {
- Some(p)
+ if preamble.included_length > 0 {
+ let size: usize = (preamble.included_length).try_into().unwrap();
+ let mut rem_data = [0u8; SNOOP_MAX_PACKET_SIZE];
+
+ match self.fd.read_exact(&mut rem_data[0..size]) {
+ Ok(()) => {
+ Some(Box::new(LinuxSnoopPacket { preamble, data: rem_data[0..size].to_vec() }))
+ }
+ Err(e) => {
+ eprintln!("Couldn't read any packet data: {}", e);
+ None
}
}
- Err(_) => None,
+ } else {
+ Some(Box::new(LinuxSnoopPacket { preamble, data: vec![] }))
}
}
}
-/// What kind of log file is this?
-#[derive(Clone, Debug)]
-pub enum LogType {
- /// Linux snoop file generated by something like `btmon`.
- LinuxSnoop(LinuxSnoopHeader),
+/// Reader for H4/UART/Android snoop files.
+pub struct H4SnoopReader<'a> {
+ fd: Box<dyn BufRead + 'a>,
+}
+
+impl<'a> H4SnoopReader<'a> {
+ fn new(fd: Box<dyn BufRead + 'a>) -> Self {
+ H4SnoopReader { fd }
+ }
+}
+
+impl<'a> Iterator for H4SnoopReader<'a> {
+ type Item = Box<dyn GeneralSnoopPacket>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ let preamble = match SnoopPacketPreamble::from_fd(&mut self.fd) {
+ Some(preamble) => preamble,
+ None => {
+ return None;
+ }
+ };
+
+ if preamble.included_length > 0 {
+ let size: usize = (preamble.included_length - 1).try_into().unwrap();
+ let mut type_buf = [0u8; 1];
+ match self.fd.read_exact(&mut type_buf) {
+ Ok(()) => {}
+ Err(e) => {
+ eprintln!("Couldn't read any packet data: {}", e);
+ return None;
+ }
+ };
+
+ let mut rem_data = [0u8; SNOOP_MAX_PACKET_SIZE];
+ match self.fd.read_exact(&mut rem_data[0..size]) {
+ Ok(()) => Some(Box::new(H4SnoopPacket {
+ preamble,
+ data: rem_data[0..size].to_vec(),
+ pkt_type: type_buf[0],
+ })),
+ Err(e) => {
+ eprintln!("Couldn't read any packet data: {}", e);
+ None
+ }
+ }
+ } else {
+ eprintln!("Non-positive packet size: {}", preamble.included_length);
+ None
+ }
+ }
}
-/// Parses different Bluetooth log types.
pub struct LogParser {
fd: Box<dyn BufRead>,
- log_type: Option<LogType>,
+ log_type: SnoopDatalinkType,
}
impl<'a> LogParser {
pub fn new(filepath: &str) -> std::io::Result<Self> {
- let fd: Box<dyn BufRead>;
+ let mut fd: Box<dyn BufRead>;
if filepath.len() == 0 {
fd = Box::new(BufReader::new(std::io::stdin()));
} else {
fd = Box::new(BufReader::new(File::open(filepath)?));
}
- Ok(Self { fd, log_type: None })
- }
-
- /// Check the log file type for the current log file. This advances the read pointer.
- /// For a non-intrusive query, use |get_log_type|.
- pub fn read_log_type(&mut self) -> std::io::Result<LogType> {
- let mut buf = [0; LINUX_SNOOP_HEADER_SIZE];
-
- self.fd.read_exact(&mut buf)?;
+ let mut buf = [0; SNOOP_HEADER_SIZE];
+ fd.read_exact(&mut buf)?;
- if let Ok(header) = LinuxSnoopHeader::try_from(&buf[0..LINUX_SNOOP_HEADER_SIZE]) {
- let log_type = LogType::LinuxSnoop(header);
- self.log_type = Some(log_type.clone());
- Ok(log_type)
- } else {
- Err(Error::new(ErrorKind::Other, "Unsupported log file type"))
+ match SnoopHeader::try_from(&buf[0..SNOOP_HEADER_SIZE]) {
+ Ok(header) => Ok(Self { fd, log_type: header.datalink_type }),
+ Err(e) => Err(Error::new(ErrorKind::Other, e)),
}
}
- /// Get cached log type. To initially read the log type, use |read_log_type|.
- pub fn get_log_type(&self) -> Option<LogType> {
- self.log_type.clone()
- }
-
- pub fn get_snoop_iterator(&mut self) -> Option<LinuxSnoopReader> {
- // Limit to LinuxSnoop files.
- if !matches!(self.get_log_type()?, LogType::LinuxSnoop(_)) {
- return None;
+ pub fn get_snoop_iterator(self) -> Box<dyn Iterator<Item = Box<dyn GeneralSnoopPacket>>> {
+ let reader = Box::new(BufReader::new(self.fd));
+ match self.log_type {
+ SnoopDatalinkType::H4Uart => Box::new(H4SnoopReader::new(reader)),
+ SnoopDatalinkType::LinuxMonitor => Box::new(LinuxSnoopReader::new(reader)),
}
-
- Some(LinuxSnoopReader::new(Box::new(BufReader::new(&mut self.fd))))
}
}
@@ -291,37 +377,37 @@ pub enum PacketChild {
SystemNote(String),
}
-impl<'a> TryFrom<&'a LinuxSnoopPacket> for PacketChild {
+impl<'a> TryFrom<&'a dyn GeneralSnoopPacket> for PacketChild {
type Error = String;
- fn try_from(item: &'a LinuxSnoopPacket) -> Result<Self, Self::Error> {
+ fn try_from(item: &'a dyn GeneralSnoopPacket) -> Result<Self, Self::Error> {
match item.opcode() {
- LinuxSnoopOpcodes::Command => match Command::parse(item.data.as_slice()) {
+ SnoopOpcodes::Command => match Command::parse(item.data().as_slice()) {
Ok(command) => Ok(PacketChild::HciCommand(command)),
Err(e) => Err(format!("Couldn't parse command: {:?}", e)),
},
- LinuxSnoopOpcodes::Event => match Event::parse(item.data.as_slice()) {
+ SnoopOpcodes::Event => match Event::parse(item.data().as_slice()) {
Ok(event) => Ok(PacketChild::HciEvent(event)),
Err(e) => Err(format!("Couldn't parse event: {:?}", e)),
},
- LinuxSnoopOpcodes::AclTxPacket => match Acl::parse(item.data.as_slice()) {
+ SnoopOpcodes::AclTxPacket => match Acl::parse(item.data().as_slice()) {
Ok(data) => Ok(PacketChild::AclTx(data)),
Err(e) => Err(format!("Couldn't parse acl tx: {:?}", e)),
},
- LinuxSnoopOpcodes::AclRxPacket => match Acl::parse(item.data.as_slice()) {
+ SnoopOpcodes::AclRxPacket => match Acl::parse(item.data().as_slice()) {
Ok(data) => Ok(PacketChild::AclRx(data)),
Err(e) => Err(format!("Couldn't parse acl rx: {:?}", e)),
},
- LinuxSnoopOpcodes::NewIndex => match NewIndex::parse(item.data.as_slice()) {
+ SnoopOpcodes::NewIndex => match NewIndex::parse(item.data().as_slice()) {
Ok(data) => Ok(PacketChild::NewIndex(data)),
Err(e) => Err(format!("Couldn't parse new index: {:?}", e)),
},
- LinuxSnoopOpcodes::SystemNote => match String::from_utf8(item.data.to_vec()) {
+ SnoopOpcodes::SystemNote => match String::from_utf8(item.data().to_vec()) {
Ok(data) => Ok(PacketChild::SystemNote(data)),
Err(e) => Err(format!("Couldn't parse system note: {:?}", e)),
},
@@ -348,22 +434,18 @@ pub struct Packet {
pub inner: PacketChild,
}
-impl<'a> TryFrom<(usize, &'a LinuxSnoopPacket)> for Packet {
+impl<'a> TryFrom<(usize, &'a dyn GeneralSnoopPacket)> for Packet {
type Error = String;
- fn try_from(item: (usize, &'a LinuxSnoopPacket)) -> Result<Self, Self::Error> {
+ fn try_from(item: (usize, &'a dyn GeneralSnoopPacket)) -> Result<Self, Self::Error> {
let (index, packet) = item;
match PacketChild::try_from(packet) {
Ok(inner) => {
- let base_ts = i64::try_from(packet.timestamp_magic_us)
- .map_err(|e| format!("u64 conversion error: {}", e))?;
-
- let ts_secs = (base_ts / USECS_TO_SECS) + LINUX_SNOOP_OFFSET_TO_UNIXTIME_SECS;
- let ts_nsecs = u32::try_from((base_ts % USECS_TO_SECS) * 1000).unwrap_or(0);
- let ts = NaiveDateTime::from_timestamp_opt(ts_secs, ts_nsecs)
- .ok_or(format!("timestamp conversion error: {}", base_ts))?;
+ let ts = packet.get_timestamp().ok_or(format!(
+ "timestamp conversion error: {}",
+ packet.preamble().timestamp_us
+ ))?;
let adapter_index = packet.adapter_index();
-
Ok(Packet { ts, adapter_index, index, inner })
}