tracer.rs 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. use core::fmt;
  2. use crate::phy::{self, Device, DeviceCapabilities, Medium};
  3. use crate::time::Instant;
  4. use crate::wire::pretty_print::{PrettyIndent, PrettyPrint};
  5. /// A tracer device.
  6. ///
  7. /// A tracer is a device that pretty prints all packets traversing it
  8. /// using the provided writer function, and then passes them to another
  9. /// device.
  10. pub struct Tracer<D: Device> {
  11. inner: D,
  12. writer: fn(Instant, Packet),
  13. }
  14. impl<D: Device> Tracer<D> {
  15. /// Create a tracer device.
  16. pub fn new(inner: D, writer: fn(timestamp: Instant, packet: Packet)) -> Tracer<D> {
  17. Tracer { inner, writer }
  18. }
  19. /// Get a reference to the underlying device.
  20. ///
  21. /// Even if the device offers reading through a standard reference, it is inadvisable to
  22. /// directly read from the device as doing so will circumvent the tracing.
  23. pub fn get_ref(&self) -> &D {
  24. &self.inner
  25. }
  26. /// Get a mutable reference to the underlying device.
  27. ///
  28. /// It is inadvisable to directly read from the device as doing so will circumvent the tracing.
  29. pub fn get_mut(&mut self) -> &mut D {
  30. &mut self.inner
  31. }
  32. /// Return the underlying device, consuming the tracer.
  33. pub fn into_inner(self) -> D {
  34. self.inner
  35. }
  36. }
  37. impl<D: Device> Device for Tracer<D> {
  38. type RxToken<'a> = RxToken<D::RxToken<'a>>
  39. where
  40. Self: 'a;
  41. type TxToken<'a> = TxToken<D::TxToken<'a>>
  42. where
  43. Self: 'a;
  44. fn capabilities(&self) -> DeviceCapabilities {
  45. self.inner.capabilities()
  46. }
  47. fn receive(&mut self, timestamp: Instant) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> {
  48. let medium = self.inner.capabilities().medium;
  49. self.inner.receive(timestamp).map(|(rx_token, tx_token)| {
  50. let rx = RxToken {
  51. token: rx_token,
  52. writer: self.writer,
  53. medium,
  54. timestamp,
  55. };
  56. let tx = TxToken {
  57. token: tx_token,
  58. writer: self.writer,
  59. medium,
  60. timestamp,
  61. };
  62. (rx, tx)
  63. })
  64. }
  65. fn transmit(&mut self, timestamp: Instant) -> Option<Self::TxToken<'_>> {
  66. let medium = self.inner.capabilities().medium;
  67. self.inner.transmit(timestamp).map(|tx_token| TxToken {
  68. token: tx_token,
  69. medium,
  70. writer: self.writer,
  71. timestamp,
  72. })
  73. }
  74. }
  75. #[doc(hidden)]
  76. pub struct RxToken<Rx: phy::RxToken> {
  77. token: Rx,
  78. writer: fn(Instant, Packet),
  79. medium: Medium,
  80. timestamp: Instant,
  81. }
  82. impl<Rx: phy::RxToken> phy::RxToken for RxToken<Rx> {
  83. fn consume<R, F>(self, f: F) -> R
  84. where
  85. F: FnOnce(&[u8]) -> R,
  86. {
  87. self.token.consume(|buffer| {
  88. (self.writer)(
  89. self.timestamp,
  90. Packet {
  91. buffer,
  92. medium: self.medium,
  93. prefix: "<- ",
  94. },
  95. );
  96. f(buffer)
  97. })
  98. }
  99. fn meta(&self) -> phy::PacketMeta {
  100. self.token.meta()
  101. }
  102. }
  103. #[doc(hidden)]
  104. pub struct TxToken<Tx: phy::TxToken> {
  105. token: Tx,
  106. writer: fn(Instant, Packet),
  107. medium: Medium,
  108. timestamp: Instant,
  109. }
  110. impl<Tx: phy::TxToken> phy::TxToken for TxToken<Tx> {
  111. fn consume<R, F>(self, len: usize, f: F) -> R
  112. where
  113. F: FnOnce(&mut [u8]) -> R,
  114. {
  115. self.token.consume(len, |buffer| {
  116. let result = f(buffer);
  117. (self.writer)(
  118. self.timestamp,
  119. Packet {
  120. buffer,
  121. medium: self.medium,
  122. prefix: "-> ",
  123. },
  124. );
  125. result
  126. })
  127. }
  128. fn set_meta(&mut self, meta: phy::PacketMeta) {
  129. self.token.set_meta(meta)
  130. }
  131. }
  132. pub struct Packet<'a> {
  133. buffer: &'a [u8],
  134. medium: Medium,
  135. prefix: &'static str,
  136. }
  137. impl<'a> fmt::Display for Packet<'a> {
  138. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  139. let mut indent = PrettyIndent::new(self.prefix);
  140. match self.medium {
  141. #[cfg(feature = "medium-ethernet")]
  142. Medium::Ethernet => crate::wire::EthernetFrame::<&'static [u8]>::pretty_print(
  143. &self.buffer,
  144. f,
  145. &mut indent,
  146. ),
  147. #[cfg(feature = "medium-ip")]
  148. Medium::Ip => match crate::wire::IpVersion::of_packet(self.buffer) {
  149. #[cfg(feature = "proto-ipv4")]
  150. Ok(crate::wire::IpVersion::Ipv4) => {
  151. crate::wire::Ipv4Packet::<&'static [u8]>::pretty_print(
  152. &self.buffer,
  153. f,
  154. &mut indent,
  155. )
  156. }
  157. #[cfg(feature = "proto-ipv6")]
  158. Ok(crate::wire::IpVersion::Ipv6) => {
  159. crate::wire::Ipv6Packet::<&'static [u8]>::pretty_print(
  160. &self.buffer,
  161. f,
  162. &mut indent,
  163. )
  164. }
  165. _ => f.write_str("unrecognized IP version"),
  166. },
  167. #[cfg(feature = "medium-ieee802154")]
  168. Medium::Ieee802154 => Ok(()), // XXX
  169. }
  170. }
  171. }