1use crate::transport::{Read, Stream, Write};
10use std::collections::VecDeque;
11use std::io;
12use std::sync::{Arc, Condvar, Mutex, MutexGuard};
13use std::time::{Duration, Instant};
14
15pub type Duplex = Stream<Reader, Writer>;
17
18impl Duplex {
19 pub fn into_halves(self) -> (Reader, Writer) {
39 let (reader, writer, _, _) = self.into_parts();
40 (reader, writer)
41 }
42}
43
44pub fn duplex(capacity: usize) -> (Duplex, Duplex) {
69 assert!(capacity > 0, "duplex capacity must be nonzero");
70 let incoming = Arc::new(Pipe::new(capacity));
71 let outgoing = Arc::new(Pipe::new(capacity));
72 (
73 endpoint(incoming.clone(), outgoing.clone()),
74 endpoint(outgoing, incoming),
75 )
76}
77
78fn endpoint(incoming: Arc<Pipe>, outgoing: Arc<Pipe>) -> Duplex {
80 Stream::new(
81 Reader {
82 pipe: incoming.clone(),
83 deadline: None,
84 },
85 Writer {
86 pipe: outgoing.clone(),
87 deadline: None,
88 },
89 move || {
90 incoming.close_reader();
91 outgoing.close_writer();
92 },
93 )
94}
95
96#[derive(Debug)]
98pub struct Reader {
99 pipe: Arc<Pipe>,
100 deadline: Option<Instant>,
101}
102
103impl io::Read for Reader {
104 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
105 let mut state = self.pipe.lock();
106 loop {
107 if buf.is_empty() || !state.reader_open {
108 return Ok(0);
109 }
110 if !state.bytes.is_empty() {
111 let count = buf.len().min(state.bytes.len());
112 for (out, byte) in buf.iter_mut().zip(state.bytes.drain(..count)) {
113 *out = byte;
114 }
115 drop(state);
116 self.pipe.changed.notify_all();
117 return Ok(count);
118 }
119 if !state.writer_open {
120 return Ok(0);
121 }
122 state = self.pipe.wait(state, time_left(self.deadline)?);
123 }
124 }
125}
126
127impl Read for Reader {
128 fn set_read_deadline(&mut self, deadline: Option<Instant>) -> io::Result<()> {
129 self.deadline = deadline;
130 Ok(())
131 }
132}
133
134impl Drop for Reader {
135 fn drop(&mut self) {
136 self.pipe.close_reader();
137 }
138}
139
140#[derive(Debug)]
142pub struct Writer {
143 pipe: Arc<Pipe>,
144 deadline: Option<Instant>,
145}
146
147impl io::Write for Writer {
148 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
149 let mut state = self.pipe.lock();
150 loop {
151 let timeout = time_left(self.deadline)?;
152 if buf.is_empty() {
153 return Ok(0);
154 }
155 if !state.reader_open || !state.writer_open {
156 return Err(io::ErrorKind::BrokenPipe.into());
157 }
158 let count = buf.len().min(self.pipe.capacity - state.bytes.len());
159 if count > 0 {
160 state.bytes.extend(&buf[..count]);
161 drop(state);
162 self.pipe.changed.notify_all();
163 return Ok(count);
164 }
165 state = self.pipe.wait(state, timeout);
166 }
167 }
168
169 fn flush(&mut self) -> io::Result<()> {
170 let state = self.pipe.lock();
171 time_left(self.deadline)?;
172 if !state.writer_open || state.lost {
173 return Err(io::ErrorKind::BrokenPipe.into());
174 }
175 Ok(())
176 }
177}
178
179impl Write for Writer {
180 fn set_write_deadline(&mut self, deadline: Instant) -> io::Result<()> {
181 self.deadline = Some(deadline);
182 Ok(())
183 }
184}
185
186impl Drop for Writer {
187 fn drop(&mut self) {
188 self.pipe.close_writer();
189 }
190}
191
192#[derive(Debug)]
194struct Pipe {
195 capacity: usize,
196 state: Mutex<State>,
197 changed: Condvar,
198}
199
200#[derive(Debug)]
201struct State {
202 bytes: VecDeque<u8>,
203 reader_open: bool,
204 writer_open: bool,
205 lost: bool, #[cfg(test)]
207 waiting: usize,
208}
209
210impl Pipe {
211 fn new(capacity: usize) -> Self {
212 Self {
213 capacity,
214 state: Mutex::new(State {
215 bytes: VecDeque::with_capacity(capacity),
216 reader_open: true,
217 writer_open: true,
218 lost: false,
219 #[cfg(test)]
220 waiting: 0,
221 }),
222 changed: Condvar::new(),
223 }
224 }
225
226 fn lock(&self) -> MutexGuard<'_, State> {
227 self.state.lock().unwrap_or_else(|err| err.into_inner())
229 }
230
231 fn wait<'a>(
232 &self,
233 state: MutexGuard<'a, State>,
234 timeout: Option<Duration>,
235 ) -> MutexGuard<'a, State> {
236 #[cfg(test)]
237 let state = {
238 let mut state = state;
239 state.waiting += 1;
240 self.changed.notify_all();
241 state
242 };
243 let state = match timeout {
244 Some(timeout) => {
245 self.changed
246 .wait_timeout(state, timeout)
247 .unwrap_or_else(|err| err.into_inner())
248 .0
249 }
250 None => self
251 .changed
252 .wait(state)
253 .unwrap_or_else(|err| err.into_inner()),
254 };
255 #[cfg(test)]
256 let state = {
257 let mut state = state;
258 state.waiting -= 1;
259 state
260 };
261 state
262 }
263
264 fn close_reader(&self) {
265 let mut state = self.lock();
266 state.reader_open = false;
267 state.lost |= !state.bytes.is_empty();
268 state.bytes.clear();
269 drop(state);
270 self.changed.notify_all();
271 }
272
273 fn close_writer(&self) {
274 self.lock().writer_open = false;
275 self.changed.notify_all();
276 }
277}
278
279fn time_left(deadline: Option<Instant>) -> io::Result<Option<Duration>> {
281 deadline
282 .map(|deadline| {
283 deadline
284 .checked_duration_since(Instant::now())
285 .filter(|left| !left.is_zero())
286 .ok_or_else(|| io::ErrorKind::TimedOut.into())
287 })
288 .transpose()
289}
290
291#[cfg(test)]
292#[cfg_attr(coverage_nightly, coverage(off))]
293mod tests {
294 use super::*;
295 use crate::transport::Closer;
296 use std::io::{Read as _, Write as _};
297 use std::sync::mpsc;
298 use std::thread;
299
300 const PATIENCE: Duration = Duration::from_secs(5);
301 const TIMEOUT: Duration = Duration::from_millis(50);
302
303 fn halves(stream: Duplex) -> (Reader, Writer, Closer) {
305 let closer = stream.closer();
306 let (reader, writer) = stream.into_halves();
307 (reader, writer, closer)
308 }
309
310 fn blocked(pipe: &Pipe) {
312 let deadline = Instant::now() + PATIENCE;
313 let mut state = pipe.lock();
314 while state.waiting == 0 {
315 let timeout = deadline.checked_duration_since(Instant::now()).unwrap();
316 state = pipe.changed.wait_timeout(state, timeout).unwrap().0;
317 }
318 }
319
320 #[test]
321 #[should_panic(expected = "duplex capacity must be nonzero")]
322 fn test_zero_capacity() {
323 duplex(0);
324 }
325
326 #[test]
329 fn test_byte_stream_and_independent_deadlines() {
330 let (host, ark) = duplex(4);
331 let (mut host_read, mut host_write, _host_close) = halves(host);
332 let (mut ark_read, mut ark_write, _ark_close) = halves(ark);
333
334 assert_eq!(host_read.read(&mut []).unwrap(), 0);
335 assert_eq!(host_write.write(b"abcdef").unwrap(), 4);
336 assert_eq!(host_write.write(&[]).unwrap(), 0);
337 host_write.flush().unwrap();
339 let mut first = [0; 2];
340 ark_read.read_exact(&mut first).unwrap();
341 assert_eq!(&first, b"ab");
342 host_write.write_all(b"ef").unwrap();
343 let mut rest = [0; 4];
344 ark_read.read_exact(&mut rest).unwrap();
345 assert_eq!(&rest, b"cdef");
346
347 ark_write.write_all(b"xy").unwrap();
348 host_read.set_read_deadline(Some(Instant::now())).unwrap();
349 host_read.read_exact(&mut first).unwrap();
350 assert_eq!(&first, b"xy");
351 assert_eq!(
352 host_read.read(&mut first).unwrap_err().kind(),
353 io::ErrorKind::TimedOut
354 );
355 assert_eq!(host_read.read(&mut []).unwrap(), 0);
356 host_write.write_all(b"q").unwrap();
357
358 host_write.set_write_deadline(Instant::now()).unwrap();
359 host_read.set_read_deadline(None).unwrap();
360 ark_write.write_all(b"uv").unwrap();
361 host_read.read_exact(&mut first).unwrap();
362 assert_eq!(&first, b"uv");
363 for bytes in [b"t".as_slice(), b""] {
364 assert_eq!(
365 host_write.write(bytes).unwrap_err().kind(),
366 io::ErrorKind::TimedOut
367 );
368 }
369 assert_eq!(
370 host_write.flush().unwrap_err().kind(),
371 io::ErrorKind::TimedOut
372 );
373
374 host_write
375 .set_write_deadline(Instant::now() + PATIENCE)
376 .unwrap();
377 host_write.write_all(b"rs").unwrap();
378 host_write.flush().unwrap();
379 let mut accepted = [0; 3];
380 ark_read.read_exact(&mut accepted).unwrap();
381 assert_eq!(&accepted, b"qrs");
382 }
383
384 #[test]
387 fn test_read_timeout_and_reuse() {
388 let (host, ark) = duplex(1);
389 let (mut reader, _host_write, _host_close) = halves(host);
390 let (_ark_read, mut writer, _ark_close) = halves(ark);
391 let pipe = reader.pipe.clone();
392 let (done, result) = mpsc::channel();
393 let timed = thread::spawn(move || {
394 let deadline = Instant::now() + TIMEOUT;
395 reader.set_read_deadline(Some(deadline)).unwrap();
396 let mut buf = [99];
397 let error = reader.read(&mut buf).unwrap_err();
398 assert!(Instant::now() >= deadline);
399 assert_eq!(buf, [99]);
400 done.send((reader, error.kind())).unwrap();
401 });
402 let (mut reader, kind) = result.recv_timeout(PATIENCE).unwrap();
403 timed.join().unwrap();
404 assert_eq!(kind, io::ErrorKind::TimedOut);
405
406 reader.set_read_deadline(None).unwrap();
407 let (done, result) = mpsc::channel();
408 let reading = thread::spawn(move || {
409 let mut buf = [0];
410 reader.read_exact(&mut buf).unwrap();
411 done.send(buf).unwrap();
412 });
413 blocked(&pipe);
414 writer.write_all(b"x").unwrap();
415 assert_eq!(&result.recv_timeout(PATIENCE).unwrap(), b"x");
416 reading.join().unwrap();
417 }
418
419 #[test]
422 fn test_write_timeout_and_reuse() {
423 let (host, ark) = duplex(3);
424 let (_host_read, mut writer, _host_close) = halves(host);
425 let (mut reader, _ark_write, _ark_close) = halves(ark);
426 let (done, result) = mpsc::channel();
427 let writing = thread::spawn(move || {
428 let deadline = Instant::now() + TIMEOUT;
429 writer.set_write_deadline(deadline).unwrap();
430 let error = writer.write_all(b"abcd").unwrap_err();
431 assert!(Instant::now() >= deadline);
432 done.send((writer, error.kind())).unwrap();
433 });
434 let (mut writer, kind) = result.recv_timeout(PATIENCE).unwrap();
435 writing.join().unwrap();
436 assert_eq!(kind, io::ErrorKind::TimedOut);
437 let mut prefix = [0; 3];
438 reader.read_exact(&mut prefix).unwrap();
439 assert_eq!(&prefix, b"abc");
440
441 writer
442 .set_write_deadline(Instant::now() + PATIENCE)
443 .unwrap();
444 writer.write_all(b"ef").unwrap();
445 drop(writer);
446 let mut suffix = Vec::new();
447 reader.read_to_end(&mut suffix).unwrap();
448 assert_eq!(&suffix, b"ef");
449 }
450
451 #[test]
454 fn test_backpressure_wakes_writer() {
455 let (host, ark) = duplex(3);
456 let (_host_read, mut writer, _host_close) = halves(host);
457 let (mut reader, _ark_write, _ark_close) = halves(ark);
458 writer.write_all(b"abc").unwrap();
459 let pipe = writer.pipe.clone();
460 let (done, result) = mpsc::channel();
461 let writing = thread::spawn(move || {
462 writer
463 .set_write_deadline(Instant::now() + PATIENCE)
464 .unwrap();
465 done.send(writer.write_all(b"defgh")).unwrap();
466 });
467 blocked(&pipe);
468 reader
469 .set_read_deadline(Some(Instant::now() + PATIENCE))
470 .unwrap();
471 let mut bytes = [0; 8];
472 reader.read_exact(&mut bytes).unwrap();
473 assert_eq!(&bytes, b"abcdefgh");
474 result.recv_timeout(PATIENCE).unwrap().unwrap();
475 writing.join().unwrap();
476 }
477
478 #[test]
481 fn test_shutdown_wakes_both_directions() {
482 for local in [false, true] {
483 let (host, ark) = duplex(1);
484 let (mut reader, mut writer, closer) = halves(host);
485 writer.write_all(b"a").unwrap();
486 let incoming = reader.pipe.clone();
487 let outgoing = writer.pipe.clone();
488 let (read_done, read_result) = mpsc::channel();
489 let reading = thread::spawn(move || {
490 read_done.send(reader.read(&mut [0])).unwrap();
491 });
492 let (write_done, write_result) = mpsc::channel();
493 let writing = thread::spawn(move || {
494 write_done.send(writer.write(b"b")).unwrap();
495 });
496 blocked(&incoming);
497 blocked(&outgoing);
498 if local {
499 closer.close();
500 } else {
501 drop(ark);
502 }
503 assert_eq!(read_result.recv_timeout(PATIENCE).unwrap().unwrap(), 0);
504 assert_eq!(
505 write_result
506 .recv_timeout(PATIENCE)
507 .unwrap()
508 .unwrap_err()
509 .kind(),
510 io::ErrorKind::BrokenPipe
511 );
512 reading.join().unwrap();
513 writing.join().unwrap();
514 }
515 }
516
517 #[test]
520 fn test_shutdown_drains_output_and_discards_input() {
521 let (host, ark) = duplex(3);
522 let (mut host_read, mut host_write, closer) = halves(host);
523 let (mut ark_read, mut ark_write, _ark_close) = halves(ark);
524 host_write.write_all(b"abc").unwrap();
525 ark_write.write_all(b"xy").unwrap();
526 host_read.set_read_deadline(Some(Instant::now())).unwrap();
527 ark_read.set_read_deadline(Some(Instant::now())).unwrap();
528 closer.close();
529 closer.close();
530 assert_eq!(host_read.read(&mut [0]).unwrap(), 0);
531 let mut bytes = Vec::new();
532 ark_read.read_to_end(&mut bytes).unwrap();
533 assert_eq!(&bytes, b"abc");
534 for writer in [&mut host_write, &mut ark_write] {
535 assert_eq!(
536 writer.write(b"z").unwrap_err().kind(),
537 io::ErrorKind::BrokenPipe
538 );
539 assert_eq!(
540 writer.flush().unwrap_err().kind(),
541 io::ErrorKind::BrokenPipe
542 );
543 }
544 }
545
546 #[test]
549 fn test_flush_after_peer_drained_and_closed() {
550 let (host, ark) = duplex(4);
551 let (_host_read, mut host_write) = host.into_halves();
552 let (mut ark_read, _ark_write) = ark.into_halves();
553 host_write.write_all(b"ab").unwrap();
554 let mut bytes = [0; 2];
555 ark_read.read_exact(&mut bytes).unwrap();
556 drop(ark_read);
557 host_write.flush().unwrap();
558 assert_eq!(
559 host_write.write(b"c").unwrap_err().kind(),
560 io::ErrorKind::BrokenPipe
561 );
562 }
563
564 #[test]
567 fn test_into_halves_and_independent_drop() {
568 let (host, ark) = duplex(4);
569 let (mut host_read, mut host_write) = host.set_write_timeout(Duration::ZERO).into_halves();
570 let (mut ark_read, mut ark_write) = ark.into_halves();
571
572 host_write.write_all(b"abc").unwrap();
573 drop(host_write);
574 let mut bytes = Vec::new();
575 ark_read.read_to_end(&mut bytes).unwrap();
576 assert_eq!(&bytes, b"abc");
577
578 ark_write.write_all(b"xy").unwrap();
579 let mut reply = [0; 2];
580 host_read.read_exact(&mut reply).unwrap();
581 assert_eq!(&reply, b"xy");
582 drop(host_read);
583 assert_eq!(
584 ark_write.write(b"z").unwrap_err().kind(),
585 io::ErrorKind::BrokenPipe
586 );
587 }
588
589 #[test]
592 fn test_protocol_round_trip() {
593 use crate::protocol::{self, Message};
594 use crate::transport::mock::self_attestation;
595 use darkbio_crypto::xdsa;
596
597 let signer = xdsa::SecretKey::generate();
598 let identity = signer.public_key();
599 let attestation = self_attestation(&signer);
600 let (host, ark) = duplex(64 * 1024);
601 let mut server = protocol::Server::new(ark, signer, attestation);
602 let (client, _) = protocol::connect(host, &identity).unwrap();
603 let mut session = server.accept().unwrap();
604 let payload: Vec<u8> = (0..256 * 1024).map(|n| n as u8).collect();
605 let deadline = Instant::now() + PATIENCE;
606 let answer = client
607 .requester()
608 .request(payload.clone(), deadline)
609 .unwrap();
610 let (message, responder) = session.recv().unwrap();
611 assert_eq!(message, Message::Develop(payload.clone()));
612 let written = responder.reply(message, deadline).unwrap();
613 assert_eq!(answer.wait::<Vec<u8>>().unwrap(), payload);
614 written.wait().unwrap();
615 client.close();
616 server.close();
617 }
618}