Skip to main content

dope_sys/probe/
mod.rs

1use crate::{io::socket::addr, memory};
2pub mod accept;
3mod check;
4pub mod cleanup;
5mod failure;
6mod outcome;
7pub mod raw;
8pub mod receive;
9pub mod session;
10pub use check::Check;
11pub use failure::Failure;
12pub use outcome::Outcome;
13
14/// Exact syscall or local-address failure while constructing probe sockets.
15#[derive(Clone, Copy, Debug, Eq, PartialEq)]
16pub enum Creation {
17    Syscall(crate::Errno),
18    Local(addr::Local<crate::Errno>),
19}
20
21impl From<crate::Errno> for Creation {
22    fn from(error: crate::Errno) -> Self {
23        Self::Syscall(error)
24    }
25}
26
27impl From<addr::Local<crate::Errno>> for Creation {
28    fn from(error: addr::Local<crate::Errno>) -> Self {
29        Self::Local(error)
30    }
31}
32
33/// A probe operation and its exact syscall failure.
34#[derive(Clone, Copy, Debug, Eq, PartialEq)]
35pub struct Syscall<P, E> {
36    pub probe: P,
37    pub error: E,
38}
39use crate::{
40    io::{
41        Close,
42        reactor::{complete, submit},
43    },
44    ring,
45    ring::{Access, map},
46    table::{token, token::host},
47};
48
49/// Stable host identities used by native capability checks.
50pub trait Context: host::Context {
51    const RING: Self::Probe;
52    const SOCKET: Self::Probe;
53    const OPTION: Self::Probe;
54    const CLOSE: Self::Probe;
55    const RECEIVE: Self::Probe;
56    const MESSAGE: Self::Probe;
57    const LISTENER: Self::Probe;
58    const ACCEPT: Self::Probe;
59    const MULTISHOT: Self::Probe;
60    const ACCEPT_CLOSE: Self::Probe;
61    const MULTI_CLOSE: Self::Probe;
62    const RELEASE: Self::Probe;
63}
64
65/// Classifies native fixed-file removal failures without erasing their phase.
66pub trait Build<E>: Context {
67    type Primary: Copy;
68    type Removed: Copy;
69
70    fn remove(mode: receive::Mode, error: E) -> Self::Removed;
71    fn release(probe: Self::Probe, error: E) -> Self::Removed;
72}
73
74/// Selects native canary checks without exposing native completion layouts.
75pub trait Source: ring::Source + submit::Control {
76    type Range: accept::Range<Target = Self::Target>;
77    type Payload: receive::Receive;
78
79    type Release<T: token::Codec, L: memory::raw::Canary, P: Copy>: cleanup::Release<
80            P,
81            Ring = Self::Ring<T>,
82            File = <Self::Ring<T> as Access>::File,
83            Session = <Self::Session<T, L> as session::Empty>::Occupied,
84            Target = <Self::Ring<T> as Access>::Target,
85            Error = map::Storage<<<Self::Ring<T> as Close>::State as map::Unmap>::Error>,
86        >
87    where
88        Self: complete::Observe<T>;
89
90    type Cleanup<T: token::Codec, L: memory::raw::Canary, P: Copy>: cleanup::Cleanup<
91            Primary = P,
92            Ring = Self::Ring<T>,
93            File = <Self::Ring<T> as Access>::File,
94            Accept = Self::Accept<T>,
95            Session = Self::Session<T, L>,
96            Error = cleanup::Failure<
97                map::Storage<<<Self::Ring<T> as Close>::State as map::Unmap>::Error>,
98                Cause<
99                    <T::Context as host::Context>::Probe,
100                    <Self as complete::Observe<T>>::Observation,
101                    <Self::Accept<T> as accept::Accept>::Error,
102                >,
103            >,
104        >
105    where
106        Self: complete::Observe<T>;
107
108    type Accept<T: token::Codec>: accept::Accept<
109            Ring = Self::Ring<T>,
110            Owned = Self::Owned<T>,
111            Probe = <T::Context as host::Context>::Probe,
112            Outcome = Self::Outcome<T, <T::Context as host::Context>::Probe>,
113        >
114    where
115        Self: complete::Observe<T>;
116
117    type Session<T: token::Codec, L: memory::raw::Canary>: session::Empty<
118            Ring = Self::Ring<T>,
119            Layout = L,
120            Owned = Self::Owned<T>,
121            Probe = <T::Context as host::Context>::Probe,
122            Outcome = Self::Outcome<T, <T::Context as host::Context>::Probe>,
123        >
124    where
125        Self: complete::Observe<T>;
126
127    type Outcome<T: complete::raw::Token, P: Copy>: Outcome<
128            Probe = P,
129            Observation = <Self as complete::Observe<T>>::Observation,
130            Value = <Self::Range as accept::Range>::Value,
131        >
132    where
133        Self: complete::Observe<T>;
134
135    type Waiting<T: token::Codec, S>: raw::Wait<
136            S,
137            Ring = Self::Ring<T>,
138            Owned = Self::Owned<T>,
139            Probe = <T::Context as host::Context>::Probe,
140            Outcome = Self::Outcome<T, <T::Context as host::Context>::Probe>,
141        >
142    where
143        Self: complete::Observe<T>;
144}
145
146/// Validates an owned ring before its resources are exposed to a driver.
147pub trait Validate<L: memory::raw::Canary, P: Copy>: Sized {
148    type Probe: Copy;
149    type Cleanup;
150
151    fn support(self) -> Result<Self, Self::Cleanup>;
152    fn empty(self, probe: Self::Probe) -> Result<Self, Self::Cleanup>;
153}
154use o3::base::num::bounded;
155
156/// Exact kernel or completion evidence that stopped a capability canary.
157#[derive(Clone, Copy, Debug, Eq, PartialEq)]
158pub enum Cause<P, O, E> {
159    Enter {
160        probe: P,
161        error: E,
162    },
163    Missing(P),
164    Unexpected {
165        probe: P,
166        observed: O,
167    },
168    Residual {
169        probe: P,
170        submit: bounded::U32<0, { u32::MAX }>,
171        complete: bounded::U32<0, { u32::MAX }>,
172    },
173    Check(Failure<P, O>),
174}
175
176impl<P, O: Copy, E> Cause<P, O, E> {
177    /// Returns only evidence whose completion remains at the queue head.
178    pub fn unread(&self) -> Option<O> {
179        match self {
180            Self::Unexpected { observed, .. } => Some(*observed),
181            Self::Check(failure) => failure.unread(),
182            Self::Enter { .. } | Self::Missing(_) | Self::Residual { .. } => None,
183        }
184    }
185}
186
187/// The owner is returned only after the kernel reports terminal completion.
188#[derive(Debug)]
189#[must_use = "a submitted operation must be completed or canceled"]
190pub enum State<S, W> {
191    Idle(S),
192    Active(W),
193}
194
195/// A stopped transition retains its current owner and the exact cause.
196/// Unlike a rejected input, the owner may already contain committed progress.
197#[derive(Debug)]
198#[must_use = "resume or close the retained owner and report its cause"]
199pub struct Stopped<S, E> {
200    pub state: S,
201    pub cause: E,
202}
203
204impl<S, E> Stopped<S, E> {
205    pub fn attach<R>(state: S, result: Result<R, E>) -> Result<(S, R), Self> {
206        let cause = match result {
207            Ok(value) => return Ok((state, value)),
208            Err(cause) => cause,
209        };
210        Err(Self { state, cause })
211    }
212
213    pub fn map<T>(self, map: impl FnOnce(S) -> T) -> Stopped<T, E> {
214        Stopped {
215            state: map(self.state),
216            cause: self.cause,
217        }
218    }
219
220    pub fn idle<W>(self) -> Stopped<State<S, W>, E> {
221        self.map(State::Idle)
222    }
223
224    pub fn active<I>(self) -> Stopped<State<I, S>, E> {
225        self.map(State::Active)
226    }
227
228    pub fn convert<F: From<E>>(self) -> Stopped<S, F> {
229        Stopped {
230            state: self.state,
231            cause: F::from(self.cause),
232        }
233    }
234
235    pub fn into_parts(self) -> (S, E) {
236        (self.state, self.cause)
237    }
238}