Loading system/gd/rust/hal/src/snoop.rs +127 −17 Original line number Diff line number Diff line Loading @@ -3,8 +3,15 @@ use crate::internal::RawHalExports; use crate::HalExports; use bt_common::sys_prop; use bt_packet::{HciCommand, HciEvent, RawPacket}; use bytes::{BufMut, Bytes, BytesMut}; use gddi::{module, provides, Stoppable}; use log::error; use std::convert::TryFrom; use std::sync::Arc; use std::time::SystemTime; use tokio::fs::{remove_file, rename, File}; use tokio::io::AsyncWriteExt; use tokio::runtime::Runtime; use tokio::select; use tokio::sync::mpsc::{channel, UnboundedReceiver}; Loading Loading @@ -96,30 +103,30 @@ async fn provide_snooped_hal( hal_exports: RawHalExports, rt: Arc<Runtime>, ) -> HalExports { let (cmd_down_tx, mut cmd_down_rx) = channel(10); let (evt_up_tx, evt_up_rx) = channel(10); let (acl_down_tx, mut acl_down_rx) = channel(10); let (acl_up_tx, acl_up_rx) = channel(10); let (cmd_down_tx, mut cmd_down_rx) = channel::<HciCommand>(10); let (evt_up_tx, evt_up_rx) = channel::<HciEvent>(10); let (acl_down_tx, mut acl_down_rx) = channel::<RawPacket>(10); let (acl_up_tx, acl_up_rx) = channel::<RawPacket>(10); rt.spawn(async move { let logger = SnoopLogger::new(config); let mut logger = SnoopLogger::new(config).await; loop { select! { Some(evt) = consume(&hal_exports.evt_rx) => { logger.log(Type::Evt, Direction::Up, &evt); evt_up_tx.send(evt).await.unwrap(); evt_up_tx.send(evt.clone()).await.unwrap(); logger.log(Type::Evt, Direction::Up, evt).await; }, Some(cmd) = cmd_down_rx.recv() => { logger.log(Type::Cmd, Direction::Down, &cmd); hal_exports.cmd_tx.send(cmd).unwrap(); hal_exports.cmd_tx.send(cmd.clone()).unwrap(); logger.log(Type::Cmd, Direction::Down, cmd).await; }, Some(acl) = acl_down_rx.recv() => { logger.log(Type::Acl, Direction::Down, &acl); hal_exports.acl_tx.send(acl).unwrap(); hal_exports.acl_tx.send(acl.clone()).unwrap(); logger.log(Type::Acl, Direction::Down, acl).await; }, Some(acl) = consume(&hal_exports.acl_rx) => { logger.log(Type::Acl, Direction::Up, &acl); acl_up_tx.send(acl).await.unwrap(); acl_up_tx.send(acl.clone()).await.unwrap(); logger.log(Type::Acl, Direction::Up, acl).await; } } } Loading Loading @@ -151,12 +158,115 @@ enum Direction { Down, } struct SnoopLogger; struct SnoopLogger { config: SnoopConfig, file: Option<File>, packets: u32, } // micros since 0000-01-01 const SNOOP_EPOCH_DELTA: u64 = 0x00dcddb30f2f8000; impl SnoopLogger { fn new(_config: SnoopConfig) -> Self { Self {} async fn new(mut config: SnoopConfig) -> Self { // filtered snoop is not available at this time if let SnoopMode::Filtered = config.mode { config.mode = SnoopMode::Disabled; } remove_file(&config.path).await.ok(); remove_file(config.path.clone() + ".last").await.ok(); if let SnoopMode::Disabled = config.mode { remove_file(config.path.clone() + ".filtered").await.ok(); remove_file(config.path.clone() + ".filtered.last") .await .ok(); } let mut ret = Self { config, file: None, packets: 0, }; ret.open_next_file().await; ret } async fn log(&mut self, t: Type, dir: Direction, bytes: Bytes) { if let SnoopMode::Disabled = self.config.mode { return; } let mut flags = 0; if let Direction::Up = dir { flags |= 0b01; } if let Type::Cmd | Type::Evt = t { flags |= 0b10; } let timestamp: u64 = u64::try_from( SystemTime::now() .duration_since(SystemTime::UNIX_EPOCH) .unwrap() .as_micros(), ) .unwrap() + SNOOP_EPOCH_DELTA; // Add one for the type byte let length = u32::try_from(bytes.len()).unwrap() + 1; let mut buffer = BytesMut::new(); buffer.put_u32(length); // original length buffer.put_u32(length); // captured length buffer.put_u32(flags); // flags buffer.put_u32(0); // dropped packets buffer.put_u64(timestamp); // timestamp buffer.put_u8(t as u8); // type buffer.put(bytes); self.packets += 1; if self.packets > self.config.max_packets_per_file { self.open_next_file().await; } fn log(&self, _t: Type, _dir: Direction, _bytes: &bytes::Bytes) {} if let Some(file) = &mut self.file { if file.write_all(&buffer).await.is_err() { error!("Failed to write"); } if file.flush().await.is_err() { error!("Failed to flush"); } } else { panic!("Logging without a backing file"); } } async fn close_file(&mut self) { if let Some(file) = &mut self.file { file.flush().await.ok(); self.file = None; } self.packets = 0; } async fn open_next_file(&mut self) { self.close_file().await; rename(&self.config.path, self.config.path.clone() + ".last") .await .ok(); let mut file = File::create(&self.config.path) .await .expect("could not open snoop log"); file.write_all(b"btsnoop\x00\x00\x00\x00\x01\x00\x00\x03\xea") .await .expect("could not write snoop header"); if file.flush().await.is_err() { error!("Failed to flush"); } self.file = Some(file); } } Loading
system/gd/rust/hal/src/snoop.rs +127 −17 Original line number Diff line number Diff line Loading @@ -3,8 +3,15 @@ use crate::internal::RawHalExports; use crate::HalExports; use bt_common::sys_prop; use bt_packet::{HciCommand, HciEvent, RawPacket}; use bytes::{BufMut, Bytes, BytesMut}; use gddi::{module, provides, Stoppable}; use log::error; use std::convert::TryFrom; use std::sync::Arc; use std::time::SystemTime; use tokio::fs::{remove_file, rename, File}; use tokio::io::AsyncWriteExt; use tokio::runtime::Runtime; use tokio::select; use tokio::sync::mpsc::{channel, UnboundedReceiver}; Loading Loading @@ -96,30 +103,30 @@ async fn provide_snooped_hal( hal_exports: RawHalExports, rt: Arc<Runtime>, ) -> HalExports { let (cmd_down_tx, mut cmd_down_rx) = channel(10); let (evt_up_tx, evt_up_rx) = channel(10); let (acl_down_tx, mut acl_down_rx) = channel(10); let (acl_up_tx, acl_up_rx) = channel(10); let (cmd_down_tx, mut cmd_down_rx) = channel::<HciCommand>(10); let (evt_up_tx, evt_up_rx) = channel::<HciEvent>(10); let (acl_down_tx, mut acl_down_rx) = channel::<RawPacket>(10); let (acl_up_tx, acl_up_rx) = channel::<RawPacket>(10); rt.spawn(async move { let logger = SnoopLogger::new(config); let mut logger = SnoopLogger::new(config).await; loop { select! { Some(evt) = consume(&hal_exports.evt_rx) => { logger.log(Type::Evt, Direction::Up, &evt); evt_up_tx.send(evt).await.unwrap(); evt_up_tx.send(evt.clone()).await.unwrap(); logger.log(Type::Evt, Direction::Up, evt).await; }, Some(cmd) = cmd_down_rx.recv() => { logger.log(Type::Cmd, Direction::Down, &cmd); hal_exports.cmd_tx.send(cmd).unwrap(); hal_exports.cmd_tx.send(cmd.clone()).unwrap(); logger.log(Type::Cmd, Direction::Down, cmd).await; }, Some(acl) = acl_down_rx.recv() => { logger.log(Type::Acl, Direction::Down, &acl); hal_exports.acl_tx.send(acl).unwrap(); hal_exports.acl_tx.send(acl.clone()).unwrap(); logger.log(Type::Acl, Direction::Down, acl).await; }, Some(acl) = consume(&hal_exports.acl_rx) => { logger.log(Type::Acl, Direction::Up, &acl); acl_up_tx.send(acl).await.unwrap(); acl_up_tx.send(acl.clone()).await.unwrap(); logger.log(Type::Acl, Direction::Up, acl).await; } } } Loading Loading @@ -151,12 +158,115 @@ enum Direction { Down, } struct SnoopLogger; struct SnoopLogger { config: SnoopConfig, file: Option<File>, packets: u32, } // micros since 0000-01-01 const SNOOP_EPOCH_DELTA: u64 = 0x00dcddb30f2f8000; impl SnoopLogger { fn new(_config: SnoopConfig) -> Self { Self {} async fn new(mut config: SnoopConfig) -> Self { // filtered snoop is not available at this time if let SnoopMode::Filtered = config.mode { config.mode = SnoopMode::Disabled; } remove_file(&config.path).await.ok(); remove_file(config.path.clone() + ".last").await.ok(); if let SnoopMode::Disabled = config.mode { remove_file(config.path.clone() + ".filtered").await.ok(); remove_file(config.path.clone() + ".filtered.last") .await .ok(); } let mut ret = Self { config, file: None, packets: 0, }; ret.open_next_file().await; ret } async fn log(&mut self, t: Type, dir: Direction, bytes: Bytes) { if let SnoopMode::Disabled = self.config.mode { return; } let mut flags = 0; if let Direction::Up = dir { flags |= 0b01; } if let Type::Cmd | Type::Evt = t { flags |= 0b10; } let timestamp: u64 = u64::try_from( SystemTime::now() .duration_since(SystemTime::UNIX_EPOCH) .unwrap() .as_micros(), ) .unwrap() + SNOOP_EPOCH_DELTA; // Add one for the type byte let length = u32::try_from(bytes.len()).unwrap() + 1; let mut buffer = BytesMut::new(); buffer.put_u32(length); // original length buffer.put_u32(length); // captured length buffer.put_u32(flags); // flags buffer.put_u32(0); // dropped packets buffer.put_u64(timestamp); // timestamp buffer.put_u8(t as u8); // type buffer.put(bytes); self.packets += 1; if self.packets > self.config.max_packets_per_file { self.open_next_file().await; } fn log(&self, _t: Type, _dir: Direction, _bytes: &bytes::Bytes) {} if let Some(file) = &mut self.file { if file.write_all(&buffer).await.is_err() { error!("Failed to write"); } if file.flush().await.is_err() { error!("Failed to flush"); } } else { panic!("Logging without a backing file"); } } async fn close_file(&mut self) { if let Some(file) = &mut self.file { file.flush().await.ok(); self.file = None; } self.packets = 0; } async fn open_next_file(&mut self) { self.close_file().await; rename(&self.config.path, self.config.path.clone() + ".last") .await .ok(); let mut file = File::create(&self.config.path) .await .expect("could not open snoop log"); file.write_all(b"btsnoop\x00\x00\x00\x00\x01\x00\x00\x03\xea") .await .expect("could not write snoop header"); if file.flush().await.is_err() { error!("Failed to flush"); } self.file = Some(file); } }