1use std::io;
2
3use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
4use tokio::sync::mpsc::{channel, Sender};
5
6use crate::floor::{rc_val, Val};
7use crate::sched::{addr, Addr};
8use crate::wire;
9use crate::world::{ConnId, Event};
10
11const HEADER: usize = 16;
12
13const LIMIT: usize = 16 << 20;
16
17#[derive(Debug, PartialEq)]
19pub struct Frame {
20 pub to: u64,
21 pub body: Vec<u8>,
22}
23
24pub const NODE: u64 = u64::MAX;
29
30pub async fn write_frame<W: AsyncWrite + Unpin>(w: &mut W, f: &Frame) -> io::Result<()> {
31 let mut head = [0u8; HEADER];
32 head[..8].copy_from_slice(&f.to.to_be_bytes());
33 head[8..].copy_from_slice(&(f.body.len() as u64).to_be_bytes());
34 w.write_all(&head).await?;
35 w.write_all(&f.body).await?;
36 w.flush().await
37}
38
39pub struct Wire<R> {
41 r: R,
42 buf: Vec<u8>,
43 filled: usize,
44}
45
46impl<R: AsyncRead + Unpin> Wire<R> {
47 pub fn new(r: R) -> Wire<R> {
48 Wire {
49 r,
50 buf: Vec::new(),
51 filled: 0,
52 }
53 }
54
55 pub async fn next(&mut self) -> io::Result<Option<Frame>> {
58 loop {
59 if let Some(f) = self.take()? {
60 return Ok(Some(f));
61 }
62 if self.fill().await? == 0 {
63 return if self.filled == 0 {
64 Ok(None)
65 } else {
66 Err(io::Error::new(
67 io::ErrorKind::UnexpectedEof,
68 "part of a frame",
69 ))
70 };
71 }
72 }
73 }
74
75 fn take(&mut self) -> io::Result<Option<Frame>> {
78 if self.filled < HEADER {
79 return Ok(None);
80 }
81 let to = u64::from_be_bytes(self.buf[..8].try_into().expect("eight bytes"));
82 let n = u64::from_be_bytes(self.buf[8..HEADER].try_into().expect("eight bytes"));
83 if n > LIMIT as u64 {
84 return Err(io::Error::new(
85 io::ErrorKind::InvalidData,
86 "frame too large",
87 ));
88 }
89 let n = n as usize;
90 if self.filled < HEADER + n {
91 return Ok(None);
92 }
93 let body = self.buf[HEADER..HEADER + n].to_vec();
94 self.buf.copy_within(HEADER + n..self.filled, 0);
95 self.filled -= HEADER + n;
96 Ok(Some(Frame { to, body }))
97 }
98
99 async fn fill(&mut self) -> io::Result<usize> {
102 if self.buf.len() - self.filled < HEADER {
103 self.buf.resize(self.filled + 8192, 0);
104 }
105 let n = self.r.read(&mut self.buf[self.filled..]).await?;
106 self.filled += n;
107 Ok(n)
108 }
109}
110
111pub fn across(v: &Val, conn: ConnId) -> Val {
120 enum Step<'a> {
121 Down(&'a Val),
122 Cons,
123 }
124 let mut work = vec![Step::Down(v)];
125 let mut out: Vec<Val> = Vec::new();
126 while let Some(s) = work.pop() {
127 match s {
128 Step::Down(Val::Pair(a, b)) => {
129 work.push(Step::Cons);
130 work.push(Step::Down(b));
131 work.push(Step::Down(a));
132 }
133 Step::Down(v) => out.push(match Addr::of(v) {
134 Some(Addr::Task(id)) => Addr::Remote(conn, *id).val(),
135 Some(Addr::Remote(_, id)) => Addr::Task(*id).val(),
136 None => v.clone(),
137 }),
138 Step::Cons => {
139 let b = out.pop().expect("a cdr");
140 let a = out.pop().expect("a car");
141 out.push(Val::Pair(rc_val(a), rc_val(b)));
142 }
143 }
144 }
145 out.pop().expect("one value")
146}
147
148pub fn departs(v: &Val, conn: ConnId) -> bool {
153 let mut work = vec![v];
154 while let Some(v) = work.pop() {
155 match v {
156 Val::Pair(a, b) => {
157 work.push(a);
158 work.push(b);
159 }
160 _ => match Addr::of(v) {
161 Some(Addr::Remote(c, _)) if *c != conn => return false,
162 _ => {}
163 },
164 }
165 }
166 true
167}
168
169const DEPTH: usize = 64;
170
171pub fn bridge<S>(conn: ConnId, stream: S, port: Sender<Event>) -> Sender<Frame>
182where
183 S: AsyncRead + AsyncWrite + Send + Unpin + 'static,
184{
185 let (tx, mut rx) = channel::<Frame>(DEPTH);
186 tokio::spawn(async move {
187 let (r, mut w) = tokio::io::split(stream);
188 let mut inbound = Wire::new(r);
189 let mut room = None;
190 let mut deaf = false;
194 loop {
195 tokio::select! {
196 got = port.reserve(), if !deaf && room.is_none() => match got {
197 Ok(p) => room = Some(p),
198 Err(_) => deaf = true,
199 },
200 got = inbound.next(), if !deaf && room.is_some() => {
201 let Ok(Some(f)) = got else { break };
202 let Ok(v) = wire::decode(&f.body) else { break };
205 let v = across(&v, conn);
206 let ev = match f.to {
207 NODE => Event::Node(conn, v),
208 to => Event::Post(addr(to as usize), v),
209 };
210 room.take().expect("guarded").send(ev);
211 }
212 got = rx.recv() => match got {
213 Some(f) => if write_frame(&mut w, &f).await.is_err() { break },
214 None => break,
215 },
216 }
217 }
218 match room {
219 Some(p) => p.send(Event::Down(conn)),
220 None => drop(port.send(Event::Down(conn)).await),
221 }
222 });
223 tx
224}
225
226#[cfg(test)]
227mod tests {
228 use super::*;
229 use crate::floor::list;
230
231 #[test]
232 fn an_address_swaps_sides_and_takes_this_links_number() {
233 assert_eq!(across(&addr(3), 7), Addr::Remote(7, 3).val());
234 assert_eq!(across(&Addr::Remote(9, 3).val(), 7), addr(3));
235 assert_eq!(across(&across(&addr(3), 7), 7), addr(3));
236 }
237
238 #[test]
239 fn nothing_but_an_address_is_rewritten() {
240 let decoy = list(&[Val::Sym("task".into()), Val::Num(3)]);
241 assert_eq!(across(&decoy, 7), decoy);
242 let msg = list(&[Val::Sym("req".into()), addr(1), Val::Num(9), decoy.clone()]);
243 assert_eq!(
244 across(&msg, 7),
245 list(&[
246 Val::Sym("req".into()),
247 Addr::Remote(7, 1).val(),
248 Val::Num(9),
249 decoy
250 ])
251 );
252 }
253
254 #[test]
255 fn only_an_address_for_a_third_node_is_refused() {
256 assert!(departs(&addr(1), 0));
257 assert!(departs(&list(&[Addr::Remote(0, 1).val(), Val::Num(2)]), 0));
258 assert!(!departs(&list(&[Addr::Remote(1, 1).val(), Val::Num(2)]), 0));
259 }
260
261 fn frame(to: u64, body: &[u8]) -> Frame {
262 Frame {
263 to,
264 body: body.to_vec(),
265 }
266 }
267
268 async fn round(frames: Vec<Frame>) -> Vec<Frame> {
269 let (mut a, b) = tokio::io::duplex(64);
270 let feed = tokio::spawn(async move {
271 for f in &frames {
272 write_frame(&mut a, f).await.expect("writes");
273 }
274 });
275 let mut w = Wire::new(b);
276 let mut out = Vec::new();
277 while let Some(f) = w.next().await.expect("reads") {
278 out.push(f);
279 }
280 feed.await.expect("no panic");
281 out
282 }
283
284 #[tokio::test]
285 async fn frames_arrive_whole_and_in_order() {
286 let big = vec![7u8; 5000];
287 let sent = vec![frame(0, b""), frame(1, b"x"), frame(u64::MAX, &big)];
288 let want = vec![frame(0, b""), frame(1, b"x"), frame(u64::MAX, &big)];
289 assert_eq!(round(sent).await, want);
290 }
291
292 #[tokio::test]
293 async fn a_truncated_frame_is_an_error_and_a_clean_end_is_not() {
294 let (a, b) = tokio::io::duplex(64);
295 drop(a);
296 assert_eq!(Wire::new(b).next().await.expect("reads"), None);
297
298 let (mut a, b) = tokio::io::duplex(64);
299 let mut w = Wire::new(b);
300 let feed = tokio::spawn(async move {
301 a.write_all(&[0, 0, 0, 0, 0, 0, 0, 1])
302 .await
303 .expect("writes");
304 });
305 assert_eq!(
306 w.next().await.expect_err("truncated").kind(),
307 io::ErrorKind::UnexpectedEof
308 );
309 feed.await.expect("no panic");
310 }
311
312 #[tokio::test]
313 async fn an_absurd_length_is_refused_rather_than_allocated() {
314 let (mut a, b) = tokio::io::duplex(64);
315 let mut w = Wire::new(b);
316 let feed = tokio::spawn(async move {
317 let mut head = [0u8; HEADER];
318 head[8..].copy_from_slice(&u64::MAX.to_be_bytes());
319 let _ = a.write_all(&head).await;
320 });
321 assert_eq!(
322 w.next().await.expect_err("refused").kind(),
323 io::ErrorKind::InvalidData
324 );
325 feed.await.expect("no panic");
326 }
327}