vmi_core/ctx/
session.rs

1use std::{io::ErrorKind, time::Duration};
2
3use super::{VmiState, context::VmiContext};
4use crate::{
5    Architecture, VmiCore, VmiDriver, VmiError, VmiHandler,
6    os::{NoOS, VmiOs},
7};
8
9/// A VMI session.
10///
11/// The session combines a [`VmiCore`] with an OS-specific [`VmiOs`]
12/// implementation to provide unified access to both low-level VMI operations
13/// and higher-level OS abstractions.
14pub struct VmiSession<'a, Driver, Os = NoOS>
15where
16    Driver: VmiDriver,
17    Os: VmiOs<Driver>,
18{
19    /// The VMI core providing low-level VM introspection capabilities.
20    core: &'a VmiCore<Driver>,
21
22    /// The OS-specific operations and abstractions.
23    os: &'a Os,
24}
25
26impl<Driver, Os> Clone for VmiSession<'_, Driver, Os>
27where
28    Driver: VmiDriver,
29    Os: VmiOs<Driver>,
30{
31    fn clone(&self) -> Self {
32        *self
33    }
34}
35
36impl<Driver, Os> Copy for VmiSession<'_, Driver, Os>
37where
38    Driver: VmiDriver,
39    Os: VmiOs<Driver>,
40{
41}
42
43impl<Driver, Os> std::ops::Deref for VmiSession<'_, Driver, Os>
44where
45    Driver: VmiDriver,
46    Os: VmiOs<Driver>,
47{
48    type Target = VmiCore<Driver>;
49
50    fn deref(&self) -> &Self::Target {
51        self.core
52    }
53}
54
55impl<'a, Driver, Os> VmiSession<'a, Driver, Os>
56where
57    Driver: VmiDriver,
58    Os: VmiOs<Driver>,
59{
60    /// Creates a new VMI session.
61    pub fn new(core: &'a VmiCore<Driver>, os: &'a Os) -> Self {
62        Self { core, os }
63    }
64
65    /// Creates a new VMI state with the specified registers.
66    pub fn with_registers(
67        &'a self,
68        registers: &'a <Driver::Architecture as Architecture>::Registers,
69    ) -> VmiState<'a, Driver, Os> {
70        VmiState::new(self, registers)
71    }
72
73    /// Creates a new VMI session without an OS-specific implementation.
74    pub fn without_os(&self) -> VmiSession<'a, Driver, NoOS> {
75        VmiSession {
76            core: self.core,
77            os: &NoOS,
78        }
79    }
80
81    /// Returns the VMI core.
82    pub fn core(&self) -> &'a VmiCore<Driver> {
83        self.core
84    }
85
86    /// Returns the underlying OS-specific implementation.
87    pub fn underlying_os(&self) -> &'a Os {
88        self.os
89    }
90
91    /// Waits for an event to occur and processes it with the provided handler.
92    ///
93    /// This method blocks until an event occurs or the specified timeout is
94    /// reached. When an event occurs, it is passed to the provided callback
95    /// function for processing.
96    pub fn wait_for_event(
97        &self,
98        timeout: Duration,
99        handler: &mut impl VmiHandler<Driver, Os>,
100    ) -> Result<(), VmiError> {
101        self.core.wait_for_event(timeout, |event| {
102            let state = VmiState::new(self, event.registers());
103            handler.handle_event(VmiContext::new(&state, event))
104        })
105    }
106
107    /// Enters the main event handling loop that processes VMI events until
108    /// finished.
109    pub fn handle<Handler>(
110        &self,
111        handler_factory: impl FnOnce(&VmiSession<Driver, Os>) -> Result<Handler, VmiError>,
112    ) -> Result<Option<Handler::Output>, VmiError>
113    where
114        Handler: VmiHandler<Driver, Os>,
115    {
116        self.handle_with_timeout(Duration::from_millis(5000), handler_factory)
117    }
118
119    /// Enters the main event handling loop that processes VMI events until
120    /// finished, with a timeout for each event.
121    pub fn handle_with_timeout<Handler>(
122        &self,
123        timeout: Duration,
124        handler_factory: impl FnOnce(&VmiSession<Driver, Os>) -> Result<Handler, VmiError>,
125    ) -> Result<Option<Handler::Output>, VmiError>
126    where
127        Handler: VmiHandler<Driver, Os>,
128    {
129        let mut result;
130        let mut handler = handler_factory(self)?;
131
132        loop {
133            result = handler.check_completion();
134
135            if result.is_some() {
136                break;
137            }
138
139            match self.wait_for_event(timeout, &mut handler) {
140                Err(VmiError::Timeout) => {
141                    tracing::trace!("timeout");
142                    handler.handle_timeout(self);
143                }
144                Err(VmiError::Io(err)) if err.kind() == ErrorKind::Interrupted => {
145                    tracing::trace!("interrupted");
146                    handler.handle_interrupted(self);
147                    break;
148                }
149                Err(err) => return Err(err),
150                Ok(_) => {}
151            }
152        }
153
154        tracing::trace!("disabling monitor");
155        self.core.reset_state()?;
156        tracing::trace!(pending_events = self.events_pending());
157
158        let _pause_guard = self.pause_guard()?;
159        if self.events_pending() > 0 {
160            match self.wait_for_event(Duration::from_millis(0), &mut handler) {
161                Err(VmiError::Timeout) => {
162                    tracing::trace!("timeout");
163                }
164                Err(err) => return Err(err),
165                Ok(_) => {}
166            }
167        }
168
169        Ok(result)
170    }
171}