|
@@ -1,6 +1,7 @@
|
|
|
-use crate::Result;
|
|
|
-use crate::wire::pretty_print::{PrettyPrint, PrettyPrinter};
|
|
|
-use crate::phy::{self, DeviceCapabilities, Device};
|
|
|
+use core::fmt;
|
|
|
+
|
|
|
+use crate::{Result, wire::pretty_print::{PrettyIndent, PrettyPrint}};
|
|
|
+use crate::phy::{self, DeviceCapabilities, Device, Medium};
|
|
|
use crate::time::Instant;
|
|
|
|
|
|
/// A tracer device.
|
|
@@ -8,14 +9,14 @@ use crate::time::Instant;
|
|
|
/// A tracer is a device that pretty prints all packets traversing it
|
|
|
/// using the provided writer function, and then passes them to another
|
|
|
/// device.
|
|
|
-pub struct Tracer<D: for<'a> Device<'a>, P: PrettyPrint> {
|
|
|
+pub struct Tracer<D: for<'a> Device<'a>> {
|
|
|
inner: D,
|
|
|
- writer: fn(Instant, PrettyPrinter<P>),
|
|
|
+ writer: fn(Instant, Packet),
|
|
|
}
|
|
|
|
|
|
-impl<D: for<'a> Device<'a>, P: PrettyPrint> Tracer<D, P> {
|
|
|
+impl<D: for<'a> Device<'a>> Tracer<D> {
|
|
|
/// Create a tracer device.
|
|
|
- pub fn new(inner: D, writer: fn(timestamp: Instant, printer: PrettyPrinter<P>)) -> Tracer<D, P> {
|
|
|
+ pub fn new(inner: D, writer: fn(timestamp: Instant, packet: Packet)) -> Tracer<D> {
|
|
|
Tracer { inner, writer }
|
|
|
}
|
|
|
|
|
@@ -40,65 +41,100 @@ impl<D: for<'a> Device<'a>, P: PrettyPrint> Tracer<D, P> {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-impl<'a, D, P> Device<'a> for Tracer<D, P>
|
|
|
+impl<'a, D> Device<'a> for Tracer<D>
|
|
|
where D: for<'b> Device<'b>,
|
|
|
- P: PrettyPrint + 'a,
|
|
|
{
|
|
|
- type RxToken = RxToken<<D as Device<'a>>::RxToken, P>;
|
|
|
- type TxToken = TxToken<<D as Device<'a>>::TxToken, P>;
|
|
|
+ type RxToken = RxToken<<D as Device<'a>>::RxToken>;
|
|
|
+ type TxToken = TxToken<<D as Device<'a>>::TxToken>;
|
|
|
|
|
|
fn capabilities(&self) -> DeviceCapabilities { self.inner.capabilities() }
|
|
|
|
|
|
fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> {
|
|
|
let &mut Self { ref mut inner, writer, .. } = self;
|
|
|
+ let medium = inner.capabilities().medium;
|
|
|
inner.receive().map(|(rx_token, tx_token)| {
|
|
|
- let rx = RxToken { token: rx_token, writer };
|
|
|
- let tx = TxToken { token: tx_token, writer };
|
|
|
+ let rx = RxToken { token: rx_token, writer, medium };
|
|
|
+ let tx = TxToken { token: tx_token, writer, medium };
|
|
|
(rx, tx)
|
|
|
})
|
|
|
}
|
|
|
|
|
|
fn transmit(&'a mut self) -> Option<Self::TxToken> {
|
|
|
let &mut Self { ref mut inner, writer } = self;
|
|
|
+ let medium = inner.capabilities().medium;
|
|
|
inner.transmit().map(|tx_token| {
|
|
|
- TxToken { token: tx_token, writer }
|
|
|
+ TxToken { token: tx_token, medium, writer }
|
|
|
})
|
|
|
}
|
|
|
}
|
|
|
|
|
|
#[doc(hidden)]
|
|
|
-pub struct RxToken<Rx: phy::RxToken, P: PrettyPrint> {
|
|
|
+pub struct RxToken<Rx: phy::RxToken> {
|
|
|
token: Rx,
|
|
|
- writer: fn(Instant, PrettyPrinter<P>)
|
|
|
+ writer: fn(Instant, Packet),
|
|
|
+ medium: Medium,
|
|
|
}
|
|
|
|
|
|
-impl<Rx: phy::RxToken, P: PrettyPrint> phy::RxToken for RxToken<Rx, P> {
|
|
|
+impl<Rx: phy::RxToken> phy::RxToken for RxToken<Rx> {
|
|
|
fn consume<R, F>(self, timestamp: Instant, f: F) -> Result<R>
|
|
|
where F: FnOnce(&mut [u8]) -> Result<R>
|
|
|
{
|
|
|
- let Self { token, writer } = self;
|
|
|
+ let Self { token, writer, medium } = self;
|
|
|
token.consume(timestamp, |buffer| {
|
|
|
- writer(timestamp, PrettyPrinter::<P>::new("<- ", &buffer));
|
|
|
+ writer(timestamp, Packet{
|
|
|
+ buffer,
|
|
|
+ medium,
|
|
|
+ prefix: "<- ",
|
|
|
+ });
|
|
|
f(buffer)
|
|
|
})
|
|
|
}
|
|
|
}
|
|
|
|
|
|
#[doc(hidden)]
|
|
|
-pub struct TxToken<Tx: phy::TxToken, P: PrettyPrint> {
|
|
|
+pub struct TxToken<Tx: phy::TxToken> {
|
|
|
token: Tx,
|
|
|
- writer: fn(Instant, PrettyPrinter<P>)
|
|
|
+ writer: fn(Instant, Packet),
|
|
|
+ medium: Medium,
|
|
|
}
|
|
|
|
|
|
-impl<Tx: phy::TxToken, P: PrettyPrint> phy::TxToken for TxToken<Tx, P> {
|
|
|
+impl<Tx: phy::TxToken> phy::TxToken for TxToken<Tx> {
|
|
|
fn consume<R, F>(self, timestamp: Instant, len: usize, f: F) -> Result<R>
|
|
|
where F: FnOnce(&mut [u8]) -> Result<R>
|
|
|
{
|
|
|
- let Self { token, writer } = self;
|
|
|
+ let Self { token, writer, medium } = self;
|
|
|
token.consume(timestamp, len, |buffer| {
|
|
|
let result = f(buffer);
|
|
|
- writer(timestamp, PrettyPrinter::<P>::new("-> ", &buffer));
|
|
|
+ writer(timestamp, Packet{
|
|
|
+ buffer,
|
|
|
+ medium,
|
|
|
+ prefix: "-> ",
|
|
|
+ });
|
|
|
result
|
|
|
})
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+pub struct Packet<'a> {
|
|
|
+ buffer: &'a [u8],
|
|
|
+ medium: Medium,
|
|
|
+ prefix: &'static str,
|
|
|
+}
|
|
|
+
|
|
|
+impl<'a> fmt::Display for Packet<'a> {
|
|
|
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
+ let mut indent = PrettyIndent::new(self.prefix);
|
|
|
+ match self.medium {
|
|
|
+ #[cfg(feature = "medium-ethernet")]
|
|
|
+ Medium::Ethernet => crate::wire::EthernetFrame::<&'static [u8]>::pretty_print(&self.buffer, f, &mut indent),
|
|
|
+ #[cfg(feature = "medium-ip")]
|
|
|
+ Medium::Ip => match crate::wire::IpVersion::of_packet(&self.buffer) {
|
|
|
+ #[cfg(feature = "proto-ipv4")]
|
|
|
+ Ok(crate::wire::IpVersion::Ipv4) => crate::wire::Ipv4Packet::<&'static [u8]>::pretty_print(&self.buffer, f, &mut indent),
|
|
|
+ #[cfg(feature = "proto-ipv6")]
|
|
|
+ Ok(crate::wire::IpVersion::Ipv6) => crate::wire::Ipv6Packet::<&'static [u8]>::pretty_print(&self.buffer, f, &mut indent),
|
|
|
+ _ => f.write_str("unrecognized IP version")
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|