mod container;
mod future;
pub use container::Container as Packets;
pub use future::PacketFuture;
use crate::Error;
use byteorder::{ByteOrder, WriteBytesExt};
use futures::AsyncWriteExt;
use std::io::Cursor;
#[derive(Clone, Debug)]
pub struct Packet {
pub(crate) timestamp: std::time::SystemTime,
pub(crate) actual_length: u32,
pub(crate) original_length: u32,
pub(crate) data: Vec<u8>,
}
impl Packet {
pub fn into_data(self) -> Vec<u8> {
self.data
}
pub fn into_pcap_record<T: ByteOrder>(self) -> Result<Vec<u8>, Error> {
self.as_pcap_record::<T>()
}
pub fn as_pcap_record<T: ByteOrder>(&self) -> Result<Vec<u8>, Error> {
let data = Vec::with_capacity(self.data.len() + 4 * std::mem::size_of::<u32>());
let mut cursor = Cursor::new(data);
self.write_pcap_record::<T, Cursor<Vec<u8>>>(&mut cursor)?;
Ok(cursor.into_inner())
}
pub fn write_pcap_record<B: ByteOrder, C: WriteBytesExt>(
&self,
cursor: &mut C,
) -> Result<(), Error> {
let dur = self
.timestamp
.duration_since(std::time::UNIX_EPOCH)
.map_err(Error::Time)?;
cursor
.write_u32::<B>(dur.as_secs() as _)
.map_err(Error::Io)?;
cursor
.write_u32::<B>(dur.subsec_micros())
.map_err(Error::Io)?;
cursor
.write_u32::<B>(self.actual_length)
.map_err(Error::Io)?;
cursor
.write_u32::<B>(self.original_length)
.map_err(Error::Io)?;
cursor.write(self.data.as_slice()).map_err(Error::Io)?;
Ok(())
}
pub fn timestamp(&self) -> &std::time::SystemTime {
&self.timestamp
}
pub fn data(&self) -> &[u8] {
self.data.as_slice()
}
pub fn actual_length(&self) -> u32 {
self.actual_length
}
pub fn original_length(&self) -> u32 {
self.original_length
}
pub fn new(
timestamp: std::time::SystemTime,
actual_length: u32,
original_length: u32,
data: Vec<u8>,
) -> Packet {
Packet {
timestamp: timestamp,
actual_length: actual_length,
original_length: original_length,
data,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use byteorder::ReadBytesExt;
use std::io::Read;
use std::time::SystemTime;
#[test]
fn converts_to_record() {
let ts = SystemTime::now();
let packet = Packet {
timestamp: ts,
actual_length: 100,
original_length: 200,
data: vec![0u8; 100],
};
let bytes = packet
.as_pcap_record::<byteorder::LittleEndian>()
.expect("Failed to convert to record");
let dur = ts
.duration_since(std::time::UNIX_EPOCH)
.expect("Could not convert to dur");
let mut cursor = Cursor::new(bytes);
assert_eq!(
cursor
.read_u32::<byteorder::LittleEndian>()
.expect("Failed to read"),
dur.as_secs() as u32
);
assert_eq!(
cursor
.read_u32::<byteorder::LittleEndian>()
.expect("Failed to read"),
dur.subsec_micros()
);
assert_eq!(
cursor
.read_u32::<byteorder::LittleEndian>()
.expect("Failed to read"),
100
);
assert_eq!(
cursor
.read_u32::<byteorder::LittleEndian>()
.expect("Failed to read"),
200
);
let mut read_data = vec![];
assert_eq!(
cursor.read_to_end(&mut read_data).expect("Failed to read"),
100
);
assert_eq!(read_data, packet.data);
}
}