tracer.rs 5.2 KB

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