use std::{
fs::File,
io::{BufReader, BufWriter},
path::PathBuf,
time::UNIX_EPOCH,
};
use dlt_parse::{
storage::{DltStorageWriter, StorageHeader},
SliceIterator,
};
use etherparse::{SlicedPacket, TransportSlice::Udp};
use rpcap::read::PcapReader;
use structopt::StructOpt;
#[derive(StructOpt, Debug)]
#[structopt(name = "pcap2dlt")]
struct CommandLineArguments {
#[structopt(short("u"), long("udp-dest-port"))]
udp_dest_port: u16,
#[structopt(short("o"), long("output-file"), parse(from_os_str))]
output_file: PathBuf,
#[structopt(parse(from_os_str))]
pcap_file: PathBuf,
}
#[derive(Debug)]
pub enum Error {
IoError(std::io::Error),
PcapError(rpcap::PcapError),
}
impl From<std::io::Error> for Error {
fn from(err: std::io::Error) -> Error {
Error::IoError(err)
}
}
impl From<rpcap::PcapError> for Error {
fn from(err: rpcap::PcapError) -> Error {
Error::PcapError(err)
}
}
fn main() -> Result<(), Error> {
let args = CommandLineArguments::from_args();
let dlt_file = File::create(args.output_file)?;
let mut dlt_writer = DltStorageWriter::new(BufWriter::new(dlt_file));
let pcap_file = File::open(args.pcap_file)?;
let (_, mut reader) = PcapReader::new(BufReader::new(pcap_file))?;
while let Some(packet) = reader.next()? {
let sliced = match SlicedPacket::from_ethernet(packet.data) {
Ok(value) => value,
Err(err) => {
eprintln!("Error parsing packet: {}", err);
continue;
}
};
if let Some(Udp(udp)) = sliced.transport {
if udp.destination_port() != args.udp_dest_port {
continue;
}
} else {
continue;
}
for dlt_packet in SliceIterator::new(sliced.payload) {
let dlt_packet = match dlt_packet {
Ok(value) => value,
Err(err) => {
eprintln!("Error parsing dlt: {}", err);
break;
}
};
let ecu_id = if let Some(ecu_id) = dlt_packet.header().ecu_id {
ecu_id
} else {
[0, 0, 0, 0]
};
let d = packet.time.duration_since(UNIX_EPOCH).unwrap();
dlt_writer.write_slice(
StorageHeader {
timestamp_seconds: d.as_secs() as u32,
timestamp_microseconds: d.subsec_micros(),
ecu_id,
},
dlt_packet,
)?;
}
}
Ok(())
}