sandbox_ipc/shm/
mod.rs

1use platform;
2
3use std::{io};
4use std::ops::{Range, RangeFull, RangeTo, RangeFrom};
5use std::collections::Bound;
6use std::sync::Arc;
7
8use uuid::Uuid;
9
10// TODO: make these public when ready for primetime
11#[cfg(test)]
12pub mod queue;
13#[cfg(test)]
14pub use self::queue::Queue;
15
16#[derive(Serialize, Deserialize, Clone, Debug)]
17pub struct SharedMem(Arc<_SharedMem>);
18
19#[derive(Debug)]
20#[derive(Serialize, Deserialize)]
21struct _SharedMem {
22    pub(crate) inner: platform::SharedMem,
23    pub(crate) token: Uuid,
24}
25
26#[derive(Clone, Debug)]
27pub struct SharedMemMap(Arc<_SharedMemMap>);
28
29#[derive(Debug)]
30struct _SharedMemMap {
31    object: SharedMem,
32    inner: platform::SharedMemMap,
33}
34
35#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
36pub enum Access {
37    Read,
38    ReadWrite,
39}
40
41impl SharedMem {
42    pub fn new(size: usize) -> io::Result<SharedMem> {
43        let inner = platform::SharedMem::new(size)?;
44        let token = Uuid::new_v4();
45        Ok(SharedMem(Arc::new(_SharedMem { inner, token })))
46    }
47
48    pub fn size(&self) -> usize { self.0.inner.size() }
49
50    pub fn clone_with_access(&self, access: Access) -> io::Result<SharedMem> {
51        let inner = self.0.inner.clone(access)?;
52        Ok(SharedMem(Arc::new(_SharedMem { inner, token: self.0.token })))
53    }
54
55    pub fn map<R: RangeArgument<usize>>(&self, range: R, access: Access) -> io::Result<SharedMemMap> where {
56        let inner = self.0.inner.map(range, access)?;
57        Ok(SharedMemMap(Arc::new(_SharedMemMap {
58            object: self.clone(),
59            inner,
60        })))
61    }
62}
63
64impl SharedMemMap {
65    pub unsafe fn pointer(&self) -> *mut u8 { self.0.inner.pointer() }
66    pub fn len(&self) -> usize { self.0.inner.len() }
67    pub fn access(&self) -> Access { self.0.inner.access() }
68    pub fn offset(&self) -> usize { self.0.inner.offset() }
69
70    pub(crate) fn token(&self) -> Uuid { self.0.object.0.token }
71}
72
73pub trait RangeArgument<T> {
74    fn start(&self) -> Bound<&T>;
75    fn end(&self) -> Bound<&T>;
76}
77
78impl<T> RangeArgument<T> for RangeFull {
79    fn start(&self) -> Bound<&T> { Bound::Unbounded }
80    fn end(&self) -> Bound<&T> { Bound::Unbounded }
81}
82
83impl<T> RangeArgument<T> for RangeFrom<T> {
84    fn start(&self) -> Bound<&T> { Bound::Included(&self.start) }
85    fn end(&self) -> Bound<&T> { Bound::Unbounded }
86}
87
88impl<T> RangeArgument<T> for RangeTo<T> {
89    fn start(&self) -> Bound<&T> { Bound::Unbounded }
90    fn end(&self) -> Bound<&T> { Bound::Excluded(&self.end) }
91}
92
93impl<T> RangeArgument<T> for Range<T> {
94    fn start(&self) -> Bound<&T> { Bound::Included(&self.start) }
95    fn end(&self) -> Bound<&T> { Bound::Excluded(&self.end) }
96}
97
98#[cfg(test)]
99mod tests {
100    use super::*;
101    use ::{MessageChannel, check_send};
102
103    use tokio::runtime::Runtime;
104    use futures::{Sink, Stream};
105
106    #[test]
107    fn shared_mem_map_is_send() {
108        let memory = SharedMem::new(4096).unwrap();
109        let memory = memory.map(.., Access::ReadWrite).unwrap();
110        check_send(&memory);
111    }
112
113    #[test]
114    fn shared_mem_is_send() {
115        let memory = SharedMem::new(4096).unwrap();
116        check_send(&memory);
117    }
118
119    #[test]
120    fn send_mem_same_process() {
121        let mut runtime = Runtime::new().unwrap();
122        let (a, b) = MessageChannel::pair(runtime.reactor(), 8192).unwrap();
123
124        let test_bytes: &[u8] = b"hello";
125
126        let memory = SharedMem::new(0x1000).unwrap();
127        unsafe {
128            let mapping = memory.map(.., Access::ReadWrite).unwrap();
129            let slice = ::std::slice::from_raw_parts_mut(mapping.pointer(), mapping.len());
130
131            slice[0..test_bytes.len()].copy_from_slice(test_bytes);
132        }
133
134        let _a = runtime.block_on(a.send(memory)).unwrap();
135        let (message, _b) = runtime.block_on(b.into_future()).map_err(|(err, _)| err).unwrap();
136        let memory: SharedMem = message.unwrap();
137
138        unsafe {
139            let mapping = memory.map(.., Access::Read).unwrap();
140            let slice = ::std::slice::from_raw_parts_mut(mapping.pointer(), mapping.len());
141
142            assert_eq!(&slice[0..test_bytes.len()], test_bytes);
143        }
144    }
145
146    #[test]
147    fn big_shm() {
148        let memory = SharedMem::new(64 * 1024 * 1024).unwrap();
149        let _mapping = memory.map(.., Access::ReadWrite).unwrap();
150    }
151}