ipc_queue/
lib.rs

1/* Copyright (c) Fortanix, Inc.
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7#![deny(warnings)]
8
9#![cfg_attr(target_env = "sgx", feature(sgx_platform))]
10
11use std::future::Future;
12use std::pin::Pin;
13use std::sync::atomic::AtomicU64;
14use std::sync::Arc;
15
16use fortanix_sgx_abi::FifoDescriptor;
17
18use self::fifo::Fifo;
19
20#[cfg(target_env = "sgx")]
21use std::os::fortanix_sgx::usercalls::alloc::{UserRef, UserSafeSized};
22
23#[cfg(not(target_env = "sgx"))]
24use {
25    std::ptr,
26    self::fifo::FifoBuffer,
27};
28
29mod fifo;
30mod interface_sync;
31mod interface_async;
32pub mod position;
33#[cfg(test)]
34mod test_support;
35
36#[cfg(target_env = "sgx")]
37pub trait Transmittable: UserSafeSized + Default {
38    unsafe fn write(ptr: *mut Self, val: &Self) {
39        UserRef::<Self>::from_mut_ptr(ptr).copy_from_enclave(val)
40    }
41
42    unsafe fn read(ptr: *const Self) -> Self {
43        let mut data = Default::default();
44        UserRef::<Self>::from_ptr(ptr).copy_to_enclave(&mut data);
45        data
46    }
47}
48
49#[cfg(target_env = "sgx")]
50impl<T> Transmittable for T where T: UserSafeSized + Default {}
51
52#[cfg(not(target_env = "sgx"))]
53pub trait Transmittable: Copy + Sized + Default {
54    unsafe fn write(ptr: *mut Self, val: &Self) {
55        ptr::write(ptr, *val);
56    }
57
58    unsafe fn read(ptr: *const Self) -> Self {
59        ptr::read(ptr)
60    }
61}
62
63#[cfg(not(target_env = "sgx"))]
64impl<T> Transmittable for T where T: Copy + Sized + Default {}
65
66#[cfg(not(target_env = "sgx"))]
67pub fn bounded<T, S>(len: usize, s: S) -> (Sender<T, S>, Receiver<T, S>)
68where
69    T: Transmittable,
70    S: Synchronizer,
71{
72    self::fifo::bounded(len, s)
73}
74
75#[cfg(not(target_env = "sgx"))]
76pub fn bounded_async<T, S>(len: usize, s: S) -> (AsyncSender<T, S>, AsyncReceiver<T, S>)
77where
78    T: Transmittable,
79    S: AsyncSynchronizer,
80{
81    self::fifo::bounded_async(len, s)
82}
83
84#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
85pub struct Identified<T> {
86    pub id: u64,
87    pub data: T,
88}
89
90#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
91pub enum QueueEvent {
92    NotEmpty,
93    NotFull,
94}
95
96#[derive(Debug, PartialEq, Eq)]
97pub enum TrySendError {
98    QueueFull,
99    Closed,
100}
101
102#[derive(Debug, PartialEq, Eq)]
103pub enum TryRecvError {
104    QueueEmpty,
105    Closed,
106}
107
108#[derive(Debug, PartialEq, Eq)]
109pub enum SendError {
110    Closed,
111}
112
113#[derive(Debug, PartialEq, Eq)]
114pub enum RecvError {
115    Closed,
116}
117
118#[derive(Debug, PartialEq, Eq)]
119pub enum SynchronizationError {
120    ChannelClosed,
121}
122
123pub trait Synchronizer: Clone {
124    /// block execution until the specified event happens.
125    fn wait(&self, event: QueueEvent) -> Result<(), SynchronizationError>;
126
127    /// notify all waiters blocked on the specified event for the same Fifo.
128    fn notify(&self, event: QueueEvent);
129}
130
131pub struct Sender<T: 'static, S> {
132    inner: Fifo<T>,
133    synchronizer: S,
134}
135
136pub struct Receiver<T: 'static, S> {
137    inner: Fifo<T>,
138    synchronizer: S,
139}
140
141pub trait AsyncSynchronizer: Clone {
142    /// block execution until the specified event happens.
143    fn wait(&self, event: QueueEvent) -> Pin<Box<dyn Future<Output = Result<(), SynchronizationError>> + '_>>;
144
145    /// notify all waiters blocked on the specified event for the same Fifo.
146    fn notify(&self, event: QueueEvent);
147}
148
149#[allow(dead_code)]
150pub struct AsyncSender<T: 'static, S> {
151    inner: Fifo<T>,
152    synchronizer: S,
153}
154
155#[allow(dead_code)]
156pub struct AsyncReceiver<T: 'static, S> {
157    inner: Fifo<T>,
158    synchronizer: S,
159    read_epoch: Arc<AtomicU64>,
160}
161
162/// `DescriptorGuard<T>` can produce a `FifoDescriptor<T>` that is guaranteed
163/// to remain valid as long as the DescriptorGuard is not dropped.
164#[allow(dead_code)]
165pub struct DescriptorGuard<T> {
166    descriptor: FifoDescriptor<T>,
167    #[cfg(not(target_env = "sgx"))]
168    _fifo: Arc<FifoBuffer<T>>,
169}
170
171impl<T> DescriptorGuard<T> {
172    pub fn fifo_descriptor(&self) -> FifoDescriptor<T> {
173        self.descriptor
174    }
175}