123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206 |
- #[cfg(feature = "std")]
- use std::cell::RefCell;
- #[cfg(feature = "std")]
- use std::io::Write;
- use byteorder::{ByteOrder, NativeEndian};
- use Result;
- use phy::{self, DeviceCapabilities, Device};
- use time::Instant;
- enum_with_unknown! {
-
- pub doc enum PcapLinkType(u32) {
-
- Ethernet = 1,
-
- Ip = 101
- }
- }
- #[derive(Debug, Clone, Copy, PartialEq, Eq)]
- pub enum PcapMode {
-
- Both,
-
- RxOnly,
-
- TxOnly
- }
- pub trait PcapSink {
-
- fn write(&self, data: &[u8]);
-
- fn write_u16(&self, value: u16) {
- let mut bytes = [0u8; 2];
- NativeEndian::write_u16(&mut bytes, value);
- self.write(&bytes[..])
- }
-
- fn write_u32(&self, value: u32) {
- let mut bytes = [0u8; 4];
- NativeEndian::write_u32(&mut bytes, value);
- self.write(&bytes[..])
- }
-
-
-
- fn global_header(&self, link_type: PcapLinkType) {
- self.write_u32(0xa1b2c3d4);
- self.write_u16(2);
- self.write_u16(4);
- self.write_u32(0);
- self.write_u32(0);
- self.write_u32(65535);
- self.write_u32(link_type.into());
- }
-
-
-
-
-
-
- fn packet_header(&self, timestamp: Instant, length: usize) {
- assert!(length <= 65535);
- self.write_u32(timestamp.secs() as u32);
- self.write_u32(timestamp.millis() as u32);
- self.write_u32(length as u32);
- self.write_u32(length as u32);
- }
-
-
-
- fn packet(&self, timestamp: Instant, packet: &[u8]) {
- self.packet_header(timestamp, packet.len());
- self.write(packet)
- }
- }
- impl<T: AsRef<PcapSink>> PcapSink for T {
- fn write(&self, data: &[u8]) {
- self.as_ref().write(data)
- }
- }
- #[cfg(feature = "std")]
- impl<T: Write> PcapSink for RefCell<T> {
- fn write(&self, data: &[u8]) {
- self.borrow_mut().write_all(data).expect("cannot write")
- }
- fn packet(&self, timestamp: Instant, packet: &[u8]) {
- self.packet_header(timestamp, packet.len());
- PcapSink::write(self, packet);
- self.borrow_mut().flush().expect("cannot flush")
- }
- }
- #[derive(Debug)]
- pub struct PcapWriter<D, S>
- where D: for<'a> Device<'a>,
- S: PcapSink + Clone,
- {
- lower: D,
- sink: S,
- mode: PcapMode,
- }
- impl<D: for<'a> Device<'a>, S: PcapSink + Clone> PcapWriter<D, S> {
-
- pub fn new(lower: D, sink: S, mode: PcapMode, link_type: PcapLinkType) -> PcapWriter<D, S> {
- sink.global_header(link_type);
- PcapWriter { lower, sink, mode }
- }
- }
- impl<'a, D, S> Device<'a> for PcapWriter<D, S>
- where D: for<'b> Device<'b>,
- S: PcapSink + Clone + 'a,
- {
- type RxToken = RxToken<<D as Device<'a>>::RxToken, S>;
- type TxToken = TxToken<<D as Device<'a>>::TxToken, S>;
- fn capabilities(&self) -> DeviceCapabilities { self.lower.capabilities() }
- fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> {
- let &mut Self { ref mut lower, ref sink, mode, .. } = self;
- lower.receive().map(|(rx_token, tx_token)| {
- let rx = RxToken { token: rx_token, sink: sink.clone(), mode: mode };
- let tx = TxToken { token: tx_token, sink: sink.clone(), mode: mode };
- (rx, tx)
- })
- }
- fn transmit(&'a mut self) -> Option<Self::TxToken> {
- let &mut Self { ref mut lower, ref sink, mode } = self;
- lower.transmit().map(|token| {
- TxToken { token, sink: sink.clone(), mode: mode }
- })
- }
- }
- #[doc(hidden)]
- pub struct RxToken<Rx: phy::RxToken, S: PcapSink> {
- token: Rx,
- sink: S,
- mode: PcapMode,
- }
- impl<Rx: phy::RxToken, S: PcapSink> phy::RxToken for RxToken<Rx, S> {
- fn consume<R, F: FnOnce(&[u8]) -> Result<R>>(self, timestamp: Instant, f: F) -> Result<R> {
- let Self { token, sink, mode } = self;
- token.consume(timestamp, |buffer| {
- match mode {
- PcapMode::Both | PcapMode::RxOnly =>
- sink.packet(timestamp, buffer.as_ref()),
- PcapMode::TxOnly => ()
- }
- f(buffer)
- })
- }
- }
- #[doc(hidden)]
- pub struct TxToken<Tx: phy::TxToken, S: PcapSink> {
- token: Tx,
- sink: S,
- mode: PcapMode
- }
- impl<Tx: phy::TxToken, S: PcapSink> phy::TxToken for TxToken<Tx, S> {
- fn consume<R, F>(self, timestamp: Instant, len: usize, f: F) -> Result<R>
- where F: FnOnce(&mut [u8]) -> Result<R>
- {
- let Self { token, sink, mode } = self;
- token.consume(timestamp, len, |buffer| {
- let result = f(buffer);
- match mode {
- PcapMode::Both | PcapMode::TxOnly =>
- sink.packet(timestamp, &buffer),
- PcapMode::RxOnly => ()
- };
- result
- })
- }
- }
|