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);