1#![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 fn wait(&self, event: QueueEvent) -> Result<(), SynchronizationError>;
126
127 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 fn wait(&self, event: QueueEvent) -> Pin<Box<dyn Future<Output = Result<(), SynchronizationError>> + '_>>;
144
145 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#[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}