1use alloc::collections::BTreeMap;
11use alloc::vec::Vec;
12
13use tpt_archon_bridge::capability::{Capability, Resource, Right, SharedIssuer};
14
15#[derive(Debug, Clone, PartialEq, Eq)]
17pub struct Message {
18 pub channel: u64,
20 pub payload: Vec<u8>,
22}
23
24#[derive(Debug, Clone, PartialEq, Eq)]
26pub enum IpcError {
27 Denied,
29 NoSuchChannel,
31}
32
33#[derive(Debug)]
38pub struct MessageRouter {
39 inboxes: BTreeMap<u64, Vec<Message>>,
40 issuer: SharedIssuer,
41}
42
43impl MessageRouter {
44 pub fn new(issuer: SharedIssuer) -> Self {
48 Self {
49 inboxes: BTreeMap::new(),
50 issuer,
51 }
52 }
53
54 pub fn register_channel(&mut self, channel: u64) {
56 self.inboxes.entry(channel).or_default();
57 }
58
59 pub fn send(&mut self, cap: &Capability, message: Message) -> Result<(), IpcError> {
61 if !self
62 .issuer
63 .borrow()
64 .authorizes(cap, Resource::Channel(message.channel), Right::Write)
65 {
66 return Err(IpcError::Denied);
67 }
68 let inbox = self
69 .inboxes
70 .get_mut(&message.channel)
71 .ok_or(IpcError::NoSuchChannel)?;
72 inbox.push(message);
73 Ok(())
74 }
75
76 pub fn receive(&mut self, cap: &Capability, channel: u64) -> Result<Vec<Message>, IpcError> {
79 if !self
80 .issuer
81 .borrow()
82 .authorizes(cap, Resource::Channel(channel), Right::Read)
83 {
84 return Err(IpcError::Denied);
85 }
86 let inbox = self
87 .inboxes
88 .get_mut(&channel)
89 .ok_or(IpcError::NoSuchChannel)?;
90 Ok(core::mem::take(inbox))
91 }
92}
93
94#[cfg(test)]
95mod tests {
96 use super::*;
97 use alloc::rc::Rc;
98 use core::cell::RefCell;
99 use tpt_archon_bridge::capability::CapabilityIssuer;
100
101 fn shared_issuer() -> Rc<RefCell<CapabilityIssuer>> {
102 Rc::new(RefCell::new(CapabilityIssuer::new()))
103 }
104
105 #[test]
106 fn authorized_send_and_receive() {
107 let issuer = shared_issuer();
108 let mut router = MessageRouter::new(issuer.clone());
109 router.register_channel(7);
110
111 let send_cap = issuer.borrow_mut().mint(Resource::Channel(7), Right::Write);
112 let recv_cap = issuer.borrow_mut().mint(Resource::Channel(7), Right::Read);
113
114 router
115 .send(
116 &send_cap,
117 Message {
118 channel: 7,
119 payload: alloc::vec![1, 2, 3],
120 },
121 )
122 .unwrap();
123
124 let msgs = router.receive(&recv_cap, 7).unwrap();
125 assert_eq!(msgs.len(), 1);
126 assert_eq!(msgs[0].payload, alloc::vec![1, 2, 3]);
127 assert!(router.receive(&recv_cap, 7).unwrap().is_empty());
129 }
130
131 #[test]
132 fn send_without_write_capability_is_denied() {
133 let issuer = shared_issuer();
134 let mut router = MessageRouter::new(issuer.clone());
135 router.register_channel(1);
136 let read_only = issuer.borrow_mut().mint(Resource::Channel(1), Right::Read);
137 assert_eq!(
138 router.send(
139 &read_only,
140 Message {
141 channel: 1,
142 payload: alloc::vec![]
143 }
144 ),
145 Err(IpcError::Denied)
146 );
147 }
148
149 #[test]
150 fn unknown_channel_errors() {
151 let issuer = shared_issuer();
152 let mut router = MessageRouter::new(issuer.clone());
153 let cap = issuer
154 .borrow_mut()
155 .mint(Resource::Channel(99), Right::Write);
156 assert_eq!(
157 router.send(
158 &cap,
159 Message {
160 channel: 99,
161 payload: alloc::vec![]
162 }
163 ),
164 Err(IpcError::NoSuchChannel)
165 );
166 }
167
168 #[test]
169 fn revoked_capability_is_denied_at_send_and_receive() {
170 let issuer = shared_issuer();
174 let mut router = MessageRouter::new(issuer.clone());
175 router.register_channel(3);
176 let cap = issuer
177 .borrow_mut()
178 .mint(Resource::Channel(3), Right::ReadWrite);
179
180 router
181 .send(
182 &cap,
183 Message {
184 channel: 3,
185 payload: alloc::vec![9],
186 },
187 )
188 .unwrap();
189
190 issuer.borrow_mut().revoke(&cap);
191 assert_eq!(
192 router.send(
193 &cap,
194 Message {
195 channel: 3,
196 payload: alloc::vec![9]
197 }
198 ),
199 Err(IpcError::Denied)
200 );
201 assert_eq!(router.receive(&cap, 3), Err(IpcError::Denied));
202 }
203}