use std::borrow::Cow;
use std::io::Write;
use byteorder::{BigEndian, LittleEndian};
use packet::{Packet, PacketHeader};
use pcap_header::{DataLink, Endianness, PcapHeader};
use errors::*;
#[derive(Debug)]
pub struct PcapWriter<T: Write> {
pub header: PcapHeader,
writer: T,
}
impl<T: Write> PcapWriter<T> {
pub fn new(writer: T) -> ResultChain<PcapWriter<T>> {
let header = PcapHeader::with_datalink(DataLink::ETHERNET);
PcapWriter::with_header(header, writer)
}
pub fn with_endianness(endianness: Endianness, writer: T) -> ResultChain<PcapWriter<T>> {
let mut header = PcapHeader::with_datalink(DataLink::ETHERNET);
match endianness {
Endianness::Big => header.magic_number = 0xa1b2c3d4,
Endianness::Little => header.magic_number = 0xd4c3b2a1
}
PcapWriter::with_header(header, writer)
}
pub fn with_header(header: PcapHeader, mut writer: T) -> ResultChain<PcapWriter<T>> {
match header.endianness() {
Endianness::Big => writer.write_all(&header.to_array::<BigEndian>()?)?,
Endianness::Little => writer.write_all(&header.to_array::<LittleEndian>()?)?
}
Ok(
PcapWriter {
header: header,
writer: writer,
}
)
}
pub fn into_writer(self) -> T {
self.writer
}
pub fn get_ref(&self) -> &T {
&self.writer
}
pub fn get_mut(&mut self) -> &mut T {
&mut self.writer
}
pub fn write(&mut self, ts_sec: u32, ts_usec: u32, data: &[u8]) -> ResultChain<()> {
let packet = Packet {
header: PacketHeader::new(ts_sec, ts_usec, data.len() as u32),
data: Cow::Borrowed(data)
};
self.write_packet(&packet)
}
pub fn write_packet(&mut self, packet: &Packet) -> ResultChain<()> {
match self.header.endianness() {
Endianness::Big => self.writer.write_all(&packet.header.to_array::<BigEndian>()?)?,
Endianness::Little => self.writer.write_all(&packet.header.to_array::<LittleEndian>()?)?
}
self.writer.write_all(&packet.data).map_err(|err| err.into())
}
}