memflow/mem/phys_mem/middleware/
delay.rs

1use ::std::{thread, time::Duration};
2
3use crate::error::Result;
4use crate::mem::{
5    PhysicalMemory, PhysicalMemoryMapping, PhysicalMemoryMetadata, PhysicalReadMemOps,
6    PhysicalWriteMemOps,
7};
8
9/// The delay middleware introduces delay and jitter into physical reads which allows
10/// users to simulate different connectors and setups.
11///
12/// Since this middleware implements [`PhysicalMemory`] it can be used as a replacement
13/// in all structs and functions that require the [`PhysicalMemory`] trait.
14pub struct DelayedPhysicalMemory<T> {
15    mem: T,
16    delay: Duration,
17}
18
19impl<T> Clone for DelayedPhysicalMemory<T>
20where
21    T: Clone,
22{
23    fn clone(&self) -> Self {
24        Self {
25            mem: self.mem.clone(),
26            delay: self.delay,
27        }
28    }
29}
30
31impl<T: PhysicalMemory> DelayedPhysicalMemory<T> {
32    /// Constructs a new middleware with the given delay.
33    ///
34    /// This function is used when manually constructing a middleware inside of the memflow crate itself.
35    ///
36    /// For general usage it is advised to just use the [builder](struct.DelayedPhysicalMemoryBuilder.html)
37    /// to construct the delay.
38    pub fn new(mem: T, delay: Duration) -> Self {
39        Self { mem, delay }
40    }
41
42    /// Consumes self and returns the containing memory object.
43    ///
44    /// This function can be useful in case the ownership over the memory object has been given to the cache
45    /// when it was being constructed.
46    /// It will destroy the `self` and return back the ownership of the underlying memory object.
47    ///
48    /// # Examples
49    /// ```
50    /// # const MAGIC_VALUE: u64 = 0x23bd_318f_f3a3_5821;
51    /// use memflow::architecture::x86::x64;
52    /// use memflow::mem::{PhysicalMemory, DelayedPhysicalMemory, MemoryView};
53    ///
54    /// fn build<T: PhysicalMemory>(mem: T) -> T {
55    ///     let mut middleware = DelayedPhysicalMemory::builder(mem)
56    ///         .build()
57    ///         .unwrap();
58    ///
59    ///     // use the middleware...
60    ///     let value: u64 = middleware.phys_view().read(0.into()).unwrap();
61    ///     assert_eq!(value, MAGIC_VALUE);
62    ///
63    ///     // retrieve ownership of mem and return it back
64    ///     middleware.into_inner()
65    /// }
66    /// # use memflow::dummy::DummyMemory;
67    /// # use memflow::types::size;
68    /// # let mut mem = DummyMemory::new(size::mb(4));
69    /// # mem.phys_write(0.into(), &MAGIC_VALUE).unwrap();
70    /// # build(mem);
71    /// ```
72    pub fn into_inner(self) -> T {
73        self.mem
74    }
75}
76
77impl<T: PhysicalMemory> DelayedPhysicalMemory<T> {
78    /// Returns a new builder for the delay middleware with default settings.
79    pub fn builder(mem: T) -> DelayedPhysicalMemoryBuilder<T> {
80        DelayedPhysicalMemoryBuilder::new(mem)
81    }
82}
83
84// forward PhysicalMemory trait fncs
85impl<T: PhysicalMemory> PhysicalMemory for DelayedPhysicalMemory<T> {
86    #[inline]
87    fn phys_read_raw_iter(&mut self, data: PhysicalReadMemOps) -> Result<()> {
88        thread::sleep(self.delay);
89        self.mem.phys_read_raw_iter(data)
90    }
91
92    #[inline]
93    fn phys_write_raw_iter(&mut self, data: PhysicalWriteMemOps) -> Result<()> {
94        thread::sleep(self.delay);
95        self.mem.phys_write_raw_iter(data)
96    }
97
98    #[inline]
99    fn metadata(&self) -> PhysicalMemoryMetadata {
100        self.mem.metadata()
101    }
102
103    #[inline]
104    fn set_mem_map(&mut self, mem_map: &[PhysicalMemoryMapping]) {
105        self.mem.set_mem_map(mem_map)
106    }
107}
108
109/// The builder interface for constructing a `DelayedPhysicalMemory` object.
110pub struct DelayedPhysicalMemoryBuilder<T> {
111    mem: T,
112    delay: Duration,
113}
114
115impl<T: PhysicalMemory> DelayedPhysicalMemoryBuilder<T> {
116    /// Creates a new `DelayedPhysicalMemory` builder.
117    /// The memory object is mandatory as the DelayedPhysicalMemory struct wraps around it.
118    ///
119    /// Without further adjustments this function creates a middleware with a delay of 10 milliseconds
120    /// for each read and write.
121    ///
122    /// It is also possible to either let the `DelayedPhysicalMemory` object own or just borrow the underlying memory object.
123    ///
124    /// # Examples
125    /// Moves ownership of a mem object and retrieves it back:
126    /// ```
127    /// # const MAGIC_VALUE: u64 = 0x23bd_318f_f3a3_5821;
128    /// use memflow::architecture::x86::x64;
129    /// use memflow::mem::{PhysicalMemory, DelayedPhysicalMemory, MemoryView};
130    ///
131    /// fn build<T: PhysicalMemory>(mem: T) {
132    ///     let mut middleware = DelayedPhysicalMemory::builder(mem)
133    ///         .build()
134    ///         .unwrap();
135    ///
136    ///     middleware.phys_write(0.into(), &MAGIC_VALUE);
137    ///
138    ///     let mut mem = middleware.into_inner();
139    ///
140    ///     let value: u64 = mem.phys_view().read(0.into()).unwrap();
141    ///     assert_eq!(value, MAGIC_VALUE);
142    /// }
143    /// # use memflow::dummy::DummyMemory;
144    /// # use memflow::types::size;
145    /// # let mut mem = DummyMemory::new(size::mb(4));
146    /// # mem.phys_write(0.into(), &0xffaaffaau64).unwrap();
147    /// # build(mem);
148    /// ```
149    ///
150    /// Borrowing a mem object:
151    /// ```
152    /// # const MAGIC_VALUE: u64 = 0x23bd_318f_f3a3_5821;
153    /// use memflow::architecture::x86::x64;
154    /// use memflow::mem::{PhysicalMemory, DelayedPhysicalMemory, MemoryView};
155    /// use memflow::cglue::{Fwd, ForwardMut};
156    ///
157    /// fn build<T: PhysicalMemory>(mem: Fwd<&mut T>)
158    ///     -> impl PhysicalMemory + '_ {
159    ///     DelayedPhysicalMemory::builder(mem)
160    ///         .build()
161    ///         .unwrap()
162    /// }
163    ///
164    /// # use memflow::dummy::DummyMemory;
165    /// # use memflow::types::size;
166    /// # let mut mem = DummyMemory::new(size::mb(4));
167    /// # mem.phys_write(0.into(), &MAGIC_VALUE).unwrap();
168    /// let mut middleware = build(mem.forward_mut());
169    ///
170    /// let value: u64 = middleware.phys_view().read(0.into()).unwrap();
171    /// assert_eq!(value, MAGIC_VALUE);
172    ///
173    /// middleware.phys_write(0.into(), &0u64).unwrap();
174    ///
175    /// // We drop the cache and are able to use mem again
176    /// std::mem::drop(middleware);
177    ///
178    /// let value: u64 = mem.phys_view().read(0.into()).unwrap();
179    /// assert_ne!(value, MAGIC_VALUE);
180    /// ```
181    pub fn new(mem: T) -> Self {
182        Self {
183            mem,
184            delay: Duration::from_millis(10),
185        }
186    }
187
188    /// Changes the delay of the middleware.
189    ///
190    /// # Examples
191    ///
192    /// ```
193    /// use memflow::types::size;
194    /// use memflow::mem::{PhysicalMemory, DelayedPhysicalMemory};
195    /// use std::time::Duration;
196    ///
197    /// fn build<T: PhysicalMemory>(mem: T) {
198    ///     let middleware = DelayedPhysicalMemory::builder(mem)
199    ///         .delay(Duration::from_millis(10))
200    ///         .build()
201    ///         .unwrap();
202    /// }
203    /// # use memflow::dummy::DummyMemory;
204    /// # let mut mem = DummyMemory::new(size::mb(4));
205    /// # build(mem);
206    /// ```
207    pub fn delay(mut self, delay: Duration) -> Self {
208        self.delay = delay;
209        self
210    }
211
212    /// Builds the `DelayedPhysicalMemory` object or returns an error.
213    pub fn build(self) -> Result<DelayedPhysicalMemory<T>> {
214        Ok(DelayedPhysicalMemory::new(self.mem, self.delay))
215    }
216}
217
218#[cfg(feature = "plugins")]
219::cglue::cglue_impl_group!(
220    DelayedPhysicalMemory<T: PhysicalMemory>,
221    crate::plugins::ConnectorInstance,
222    {}
223);