Skip to content

Commit dffa1bd

Browse files
authored
Merge pull request #111 from martinling/save-hitl-captures
Optionally save captures from hardware-in-the-loop testing
2 parents 7af5d7f + 8cf1203 commit dffa1bd

6 files changed

Lines changed: 82 additions & 47 deletions

File tree

src/capture.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1628,7 +1628,7 @@ mod tests {
16281628
use std::io::{BufReader, BufWriter, BufRead, Write};
16291629
use std::path::PathBuf;
16301630
use crate::decoder::Decoder;
1631-
use crate::loader::Loader;
1631+
use crate::pcap::Loader;
16321632
use itertools::Itertools;
16331633

16341634
fn summarize_item(cap: &mut CaptureReader, item: &TrafficItem, depth: usize)

src/main.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ mod decoder;
2020
mod expander;
2121
mod id;
2222
mod index_stream;
23-
mod loader;
2423
mod model;
24+
mod pcap;
2525
mod rcu;
2626
mod row_data;
2727
mod stream;
@@ -47,9 +47,14 @@ use ui::{
4747
stop_cynthion
4848
};
4949

50+
fn have_argument(name: &str) -> bool {
51+
std::env::args().any(|arg| arg == name)
52+
}
53+
5054
fn main() {
51-
if std::env::args().any(|arg| arg == "--test-cynthion") {
52-
test_cynthion::run_test();
55+
if have_argument("--test-cynthion") {
56+
let save_captures = have_argument("--save-captures");
57+
test_cynthion::run_test(save_captures);
5358
} else {
5459
let application = gtk::Application::new(
5560
Some("com.greatscottgadgets.packetry"),

src/loader.rs renamed to src/pcap.rs

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
1+
use std::borrow::Cow;
12
use std::fs::File;
2-
use std::io::BufReader;
3+
use std::io::{BufReader, BufWriter, Write};
34
use std::mem::size_of;
45
use std::path::PathBuf;
56

67
use pcap_file::{
7-
pcap::{PcapReader, PcapHeader, RawPcapPacket},
8+
pcap::{PcapReader, PcapWriter, PcapHeader, RawPcapPacket},
9+
DataLink,
810
TsResolution,
911
};
1012

11-
use anyhow::Error;
13+
use anyhow::{Context, Error};
1214

1315
pub struct Loader {
1416
pcap: PcapReader<BufReader<File>>,
@@ -18,6 +20,10 @@ pub struct Loader {
1820
start_time: Option<u64>,
1921
}
2022

23+
pub struct Writer {
24+
pcap: PcapWriter<BufWriter<File>>,
25+
}
26+
2127
impl Loader {
2228
pub fn open(path: PathBuf) -> Result<Loader, Error> {
2329
let file = File::open(path)?;
@@ -55,3 +61,37 @@ impl Loader {
5561
}
5662
}
5763
}
64+
65+
impl Writer {
66+
pub fn open(path: PathBuf) -> Result<Writer, Error> {
67+
let file = File::create(path)?;
68+
let writer = BufWriter::new(file);
69+
let header = PcapHeader {
70+
datalink: DataLink::USB_2_0,
71+
ts_resolution: TsResolution::NanoSecond,
72+
.. PcapHeader::default()
73+
};
74+
Ok(Writer{pcap: PcapWriter::with_header(writer, header)?})
75+
}
76+
77+
pub fn add_packet(&mut self, bytes: &[u8], timestamp_ns: u64) -> Result<(), Error> {
78+
let length: u32 = bytes
79+
.len()
80+
.try_into()
81+
.context("Packet too large for pcap file")?;
82+
let packet = RawPcapPacket {
83+
ts_sec: (timestamp_ns / 1_000_000_000) as u32,
84+
ts_frac: (timestamp_ns % 1_000_000_000) as u32,
85+
incl_len: length,
86+
orig_len: length,
87+
data: Cow::from(bytes)
88+
};
89+
self.pcap.write_raw_packet(&packet)?;
90+
Ok(())
91+
}
92+
93+
pub fn close(self) -> Result<(), Error> {
94+
self.pcap.into_writer().flush()?;
95+
Ok(())
96+
}
97+
}

src/test_cynthion.rs

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,25 +8,29 @@ use crate::capture::{
88
PacketId,
99
};
1010
use crate::decoder::Decoder;
11+
use crate::pcap::Writer;
1112

1213
use anyhow::{Context, Error};
1314
use futures_lite::future::block_on;
1415
use nusb::transfer::RequestBuffer;
1516

17+
use std::path::PathBuf;
1618
use std::thread::sleep;
1719
use std::time::Duration;
1820

19-
pub fn run_test() {
20-
for (speed, ep_addr, length, sof) in [
21-
(Speed::High, 0x81, 4096, Some((124500, 125500, 500))),
22-
(Speed::Full, 0x82, 512, Some((995000, 1005000, 50))),
23-
(Speed::Low, 0x83, 64, None)]
21+
pub fn run_test(save_captures: bool) {
22+
for (name, speed, ep_addr, length, sof) in [
23+
("HS", Speed::High, 0x81, 4096, Some((124500, 125500, 500))),
24+
("FS", Speed::Full, 0x82, 512, Some((995000, 1005000, 50))),
25+
("LS", Speed::Low, 0x83, 64, None)]
2426
{
25-
test(speed, ep_addr, length, sof).unwrap();
27+
test(save_captures, name, speed, ep_addr, length, sof).unwrap();
2628
}
2729
}
2830

29-
fn test(speed: Speed,
31+
fn test(save_capture: bool,
32+
name: &str,
33+
speed: Speed,
3034
ep_addr: u8,
3135
length: usize,
3236
sof: Option<(u64, u64, u64)>)
@@ -96,6 +100,19 @@ fn test(speed: Speed,
96100
.context("Error decoding packet")?;
97101
}
98102

103+
if save_capture {
104+
// Write the capture to a file.
105+
let path = PathBuf::from(format!("./HITL-{name}.pcap"));
106+
let mut writer = Writer::open(path)?;
107+
for i in 0..reader.packet_index.len() {
108+
let packet_id = PacketId::from(i);
109+
let packet = reader.packet(packet_id)?;
110+
let timestamp_ns = reader.packet_time(packet_id)?;
111+
writer.add_packet(&packet, timestamp_ns)?;
112+
}
113+
writer.close()?;
114+
}
115+
99116
// Look for the test device in the capture.
100117
let device_id = DeviceId::from(1);
101118
let device_data = reader.device_data(&device_id)?;

src/test_replay.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use itertools::assert_equal;
88
use serde_json::Deserializer;
99

1010
use crate::decoder::Decoder;
11-
use crate::loader::Loader;
11+
use crate::pcap::Loader;
1212
use crate::model::GenericModel;
1313
use crate::row_data::{GenericRowData, TrafficRowData, DeviceRowData};
1414
use crate::record_ui::UiAction;

src/ui.rs

Lines changed: 5 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
use std::borrow::Cow;
21
use std::cell::RefCell;
3-
use std::fs::File;
4-
use std::io::{BufWriter, Write};
52
use std::path::PathBuf;
63
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
74
use std::time::Duration;
@@ -46,12 +43,6 @@ use gtk::{
4643
ButtonsType,
4744
};
4845

49-
use pcap_file::{
50-
DataLink,
51-
TsResolution,
52-
pcap::{PcapWriter, PcapHeader, RawPcapPacket},
53-
};
54-
5546
use crate::backend::cynthion::{
5647
CynthionDevice,
5748
CynthionHandle,
@@ -70,7 +61,7 @@ use crate::capture::{
7061
};
7162
use crate::decoder::Decoder;
7263
use crate::expander::ExpanderWrapper;
73-
use crate::loader::Loader;
64+
use crate::pcap::{Loader, Writer};
7465
use crate::model::{GenericModel, TrafficModel, DeviceModel};
7566
use crate::row_data::{
7667
GenericRowData,
@@ -861,36 +852,18 @@ fn start_pcap(action: FileAction, path: PathBuf) -> Result<(), Error> {
861852
let packet_count = capture.packet_index.len();
862853
TOTAL.store(packet_count, Ordering::Relaxed);
863854
CURRENT.store(0, Ordering::Relaxed);
864-
let file = File::create(path)?;
865-
let writer = BufWriter::new(file);
866-
let header = PcapHeader {
867-
datalink: DataLink::USB_2_0,
868-
ts_resolution: TsResolution::NanoSecond,
869-
.. PcapHeader::default()
870-
};
871-
let mut pcap = PcapWriter::with_header(writer, header)?;
855+
let mut writer = Writer::open(path)?;
872856
for i in 0..packet_count {
873857
let packet_id = PacketId::from(i);
874-
let bytes = capture.packet(packet_id)?;
858+
let packet = capture.packet(packet_id)?;
875859
let timestamp_ns = capture.packet_time(packet_id)?;
876-
let length: u32 = bytes
877-
.len()
878-
.try_into()
879-
.context("Packet too large for pcap file")?;
880-
let packet = RawPcapPacket {
881-
ts_sec: (timestamp_ns / 1_000_000_000) as u32,
882-
ts_frac: (timestamp_ns % 1_000_000_000) as u32,
883-
incl_len: length,
884-
orig_len: length,
885-
data: Cow::from(bytes)
886-
};
887-
pcap.write_raw_packet(&packet)?;
860+
writer.add_packet(&packet, timestamp_ns)?;
888861
CURRENT.store(i + 1, Ordering::Relaxed);
889862
if STOP.load(Ordering::Relaxed) {
890863
break;
891864
}
892865
}
893-
pcap.into_writer().flush()?;
866+
writer.close()?;
894867
Ok(())
895868
},
896869
};

0 commit comments

Comments
 (0)