1use crate::transport::{Read, Stream, Write};
13use darkbio_clock::Clock;
14use darkbio_clock::sync::{Condvar, Mutex, MutexGuard};
15use std::collections::VecDeque;
16use std::io;
17use std::sync::Arc;
18use std::time::Instant;
19
20pub type Duplex = Stream<Reader, Writer>;
23
24impl Duplex {
25 pub fn into_halves(self) -> (Reader, Writer) {
46 let (reader, writer, _, _) = self.into_parts();
47 (reader, writer)
48 }
49}
50
51pub fn duplex(capacity: usize, clock: &Clock) -> (Duplex, Duplex) {
81 assert!(capacity > 0, "duplex capacity must be nonzero");
83
84 let incoming = Arc::new(Pipe::new(capacity, clock));
86 let outgoing = Arc::new(Pipe::new(capacity, clock));
87 (
88 endpoint(incoming.clone(), outgoing.clone()),
89 endpoint(outgoing, incoming),
90 )
91}
92
93fn endpoint(incoming: Arc<Pipe>, outgoing: Arc<Pipe>) -> Duplex {
95 Stream::new(
96 Reader {
97 pipe: incoming.clone(),
98 deadline: None,
99 },
100 Writer {
101 pipe: outgoing.clone(),
102 deadline: None,
103 },
104 move || {
105 incoming.close_reader();
106 outgoing.close_writer();
107 },
108 )
109}
110
111#[derive(Debug)]
113pub struct Reader {
114 pipe: Arc<Pipe>,
116 deadline: Option<Instant>,
118}
119
120impl io::Read for Reader {
121 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
126 let mut state = self.pipe.lock();
128 loop {
129 if buf.is_empty() || !state.reader_open {
131 return Ok(0);
132 }
133
134 if !state.bytes.is_empty() {
136 let count = buf.len().min(state.bytes.len());
138 let (front, back) = state.bytes.as_slices();
139 let split = count.min(front.len());
140 buf[..split].copy_from_slice(&front[..split]);
141 buf[split..count].copy_from_slice(&back[..count - split]);
142 state.bytes.drain(..count);
143 drop(state);
144 self.pipe.changed.notify_all();
145 return Ok(count);
146 }
147
148 if !state.writer_open {
150 return Ok(0);
151 }
152 self.pipe.check_deadline(self.deadline)?;
153 state = self.pipe.wait(state, self.deadline);
154 }
155 }
156}
157
158impl Read for Reader {
159 fn clock(&self) -> Clock {
160 self.pipe.clock.clone()
161 }
162
163 fn set_read_deadline(&mut self, deadline: Option<Instant>) -> io::Result<()> {
164 self.deadline = deadline;
165 Ok(())
166 }
167}
168
169impl Drop for Reader {
170 fn drop(&mut self) {
172 self.pipe.close_reader();
173 }
174}
175
176#[cfg(test)]
177impl Reader {
178 pub(crate) fn forbid_waits(&self) {
181 self.pipe.lock().waits_forbidden = true;
182 }
183}
184
185#[derive(Debug)]
187pub struct Writer {
188 pipe: Arc<Pipe>,
190 deadline: Option<Instant>,
192}
193
194impl io::Write for Writer {
195 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
202 let mut state = self.pipe.lock();
204 loop {
205 self.pipe.check_deadline(self.deadline)?;
207 if buf.is_empty() {
208 return Ok(0);
209 }
210 if !state.reader_open || !state.writer_open {
211 return Err(io::ErrorKind::BrokenPipe.into());
212 }
213
214 let count = buf.len().min(self.pipe.capacity - state.bytes.len());
216 if count > 0 {
217 state.bytes.extend(&buf[..count]);
218 drop(state);
219 self.pipe.changed.notify_all();
220 return Ok(count);
221 }
222
223 state = self.pipe.wait(state, self.deadline);
225 }
226 }
227
228 fn flush(&mut self) -> io::Result<()> {
234 let state = self.pipe.lock();
236 self.pipe.check_deadline(self.deadline)?;
237
238 if !state.writer_open || state.lost {
240 return Err(io::ErrorKind::BrokenPipe.into());
241 }
242 Ok(())
243 }
244}
245
246impl Write for Writer {
247 fn clock(&self) -> Clock {
248 self.pipe.clock.clone()
249 }
250
251 fn set_write_deadline(&mut self, deadline: Instant) -> io::Result<()> {
252 self.deadline = Some(deadline);
253 Ok(())
254 }
255}
256
257impl Drop for Writer {
258 fn drop(&mut self) {
261 self.pipe.close_writer();
262 }
263}
264
265#[derive(Debug)]
269struct Pipe {
270 clock: Clock,
272 capacity: usize,
274 state: Mutex<State>,
276 changed: Condvar,
278}
279
280#[derive(Debug)]
282struct State {
283 bytes: VecDeque<u8>,
285 reader_open: bool,
287 writer_open: bool,
289 lost: bool,
291 #[cfg(test)]
293 waiting: usize,
294 #[cfg(test)]
296 waits_forbidden: bool,
297}
298
299impl Pipe {
300 fn new(capacity: usize, clock: &Clock) -> Self {
303 Self {
304 clock: clock.clone(),
305 capacity,
306 state: Mutex::new(State {
307 bytes: VecDeque::with_capacity(capacity),
308 reader_open: true,
309 writer_open: true,
310 lost: false,
311 #[cfg(test)]
312 waiting: 0,
313 #[cfg(test)]
314 waits_forbidden: false,
315 }),
316 changed: Condvar::new(clock),
317 }
318 }
319
320 fn lock(&self) -> MutexGuard<'_, State> {
322 self.state.lock().unwrap_or_else(|err| err.into_inner())
324 }
325
326 fn wait<'a>(
328 &self,
329 state: MutexGuard<'a, State>,
330 deadline: Option<Instant>,
331 ) -> MutexGuard<'a, State> {
332 #[cfg(test)]
334 let state = {
335 let mut state = state;
336 assert!(!state.waits_forbidden, "memory pipe waited");
337 state.waiting += 1;
338 self.changed.notify_all();
339 state
340 };
341
342 let state = match deadline {
344 Some(deadline) => {
345 self.changed
346 .wait_deadline(state, deadline)
347 .unwrap_or_else(|err| err.into_inner())
348 .0
349 }
350 None => self
351 .changed
352 .wait(state)
353 .unwrap_or_else(|err| err.into_inner()),
354 };
355
356 #[cfg(test)]
358 let state = {
359 let mut state = state;
360 state.waiting -= 1;
361 state
362 };
363 state
364 }
365
366 fn check_deadline(&self, deadline: Option<Instant>) -> io::Result<()> {
368 if deadline.is_some_and(|deadline| self.clock.now() >= deadline) {
369 return Err(io::ErrorKind::TimedOut.into());
370 }
371 Ok(())
372 }
373
374 fn close_reader(&self) {
377 let mut state = self.lock();
378 state.reader_open = false;
379 state.lost |= !state.bytes.is_empty();
380 state.bytes.clear();
381 drop(state);
382 self.changed.notify_all();
383 }
384
385 fn close_writer(&self) {
388 self.lock().writer_open = false;
389 self.changed.notify_all();
390 }
391}
392
393#[cfg(test)]
396#[cfg_attr(coverage_nightly, coverage(off))]
397mod tests {
398 use super::*;
399 use crate::transport::Closer;
400 use crate::transport::testing::test_clock;
401 use darkbio_clock::TestClock;
402 use std::io::{Read as _, Write as _};
403 use std::sync::mpsc;
404 use std::thread;
405 use std::time::Duration;
406
407 const TIMEOUT: Duration = Duration::from_millis(50);
409
410 fn halves(stream: Duplex) -> (Reader, Writer, Closer) {
412 let closer = stream.closer();
413 let (reader, writer) = stream.into_halves();
414 (reader, writer, closer)
415 }
416
417 fn blocked(pipe: &Pipe) {
419 let mut state = pipe.lock();
420 while state.waiting == 0 {
421 state = pipe.changed.wait(state).unwrap();
422 }
423 }
424
425 #[test]
428 fn test_blocked_read_expires_on_clock_deadline() {
429 let mut tester = TestClock::new();
431 tester.advance(Duration::from_secs(86400));
432 let clock = tester.clock();
433 let (host, _peer) = duplex(1, &clock);
434 let (mut reader, _writer) = host.into_halves();
435 let deadline = clock.now() + Duration::from_secs(5);
436 reader.set_read_deadline(Some(deadline)).unwrap();
437 let reading = thread::spawn(move || reader.read(&mut [0]));
438 tester.wait_registered(1);
439 assert_eq!(tester.next_deadline(), Some(deadline));
440
441 tester.advance_to(deadline);
443 assert_eq!(
444 reading.join().unwrap().unwrap_err().kind(),
445 io::ErrorKind::TimedOut
446 );
447 }
448
449 #[test]
452 fn test_blocked_write_expires_on_clock_deadline() {
453 let mut tester = TestClock::new();
455 tester.advance(Duration::from_secs(86400));
456 let clock = tester.clock();
457 let (host, _peer) = duplex(1, &clock);
458 let (_reader, mut writer) = host.into_halves();
459 writer.write_all(b"a").unwrap();
460 let deadline = clock.now() + Duration::from_secs(5);
461 writer.set_write_deadline(deadline).unwrap();
462 let writing = thread::spawn(move || writer.write(b"b"));
463 tester.wait_registered(1);
464 assert_eq!(tester.next_deadline(), Some(deadline));
465
466 tester.advance_to(deadline);
468 assert_eq!(
469 writing.join().unwrap().unwrap_err().kind(),
470 io::ErrorKind::TimedOut
471 );
472 }
473
474 #[test]
477 fn test_read_delivers_buffered_bytes_after_deadline() {
478 let mut tester = test_clock();
480 let clock = tester.clock();
481 let (host, peer) = duplex(1, &clock);
482 let (mut reader, _writer) = host.into_halves();
483 let (_peer_reader, mut writer) = peer.into_halves();
484 let deadline = clock.now() + Duration::from_secs(5);
485 reader.set_read_deadline(Some(deadline)).unwrap();
486 writer.write_all(b"a").unwrap();
487
488 tester.advance_to(deadline);
490 reader.forbid_waits();
491 let mut byte = [0];
492 assert_eq!(reader.read(&mut byte).unwrap(), 1);
493 assert_eq!(&byte, b"a");
494
495 assert_eq!(
497 reader.read(&mut byte).unwrap_err().kind(),
498 io::ErrorKind::TimedOut
499 );
500 }
501
502 #[test]
505 #[should_panic(expected = "duplex capacity must be nonzero")]
506 fn test_zero_capacity() {
507 duplex(0, &test_clock().clock());
508 }
509
510 #[test]
515 fn test_byte_stream_and_independent_deadlines() {
516 let tester = test_clock();
518 let clock = tester.clock();
519 let (host, ark) = duplex(4, &clock);
520 let (mut host_read, mut host_write, _host_close) = halves(host);
521 let (mut ark_read, mut ark_write, _ark_close) = halves(ark);
522
523 assert_eq!(host_read.read(&mut []).unwrap(), 0);
525 assert_eq!(host_write.write(b"abcdef").unwrap(), 4);
526 assert_eq!(host_write.write(&[]).unwrap(), 0);
527 host_write.flush().unwrap();
529 let mut first = [0; 2];
530 ark_read.read_exact(&mut first).unwrap();
531 assert_eq!(&first, b"ab");
532 host_write.write_all(b"ef").unwrap();
533 let mut rest = [0; 4];
534 ark_read.read_exact(&mut rest).unwrap();
535 assert_eq!(&rest, b"cdef");
536
537 ark_write.write_all(b"xy").unwrap();
539 host_read.set_read_deadline(Some(clock.now())).unwrap();
540 host_read.read_exact(&mut first).unwrap();
541 assert_eq!(&first, b"xy");
542 assert_eq!(
543 host_read.read(&mut first).unwrap_err().kind(),
544 io::ErrorKind::TimedOut
545 );
546 assert_eq!(host_read.read(&mut []).unwrap(), 0);
547 host_write.write_all(b"q").unwrap();
548
549 host_write.set_write_deadline(clock.now()).unwrap();
551 host_read.set_read_deadline(None).unwrap();
552 ark_write.write_all(b"uv").unwrap();
553 host_read.read_exact(&mut first).unwrap();
554 assert_eq!(&first, b"uv");
555 for bytes in [b"t".as_slice(), b""] {
556 assert_eq!(
557 host_write.write(bytes).unwrap_err().kind(),
558 io::ErrorKind::TimedOut
559 );
560 }
561 assert_eq!(
562 host_write.flush().unwrap_err().kind(),
563 io::ErrorKind::TimedOut
564 );
565
566 host_write
568 .set_write_deadline(clock.now() + Duration::from_secs(5))
569 .unwrap();
570 host_write.write_all(b"rs").unwrap();
571 host_write.flush().unwrap();
572 let mut accepted = [0; 3];
573 ark_read.read_exact(&mut accepted).unwrap();
574 assert_eq!(&accepted, b"qrs");
575 }
576
577 #[test]
580 fn test_read_across_wraparound() {
581 let tests: [(usize, usize, &[u8; 6], &[u8]); 5] = [
582 (1, 1, b"c-----", b"def"), (2, 2, b"cd----", b"ef"), (3, 3, b"cde---", b"f"), (4, 4, b"cdef--", b""), (6, 4, b"cdef--", b""), ];
588 for (i, (size, count, filled, rest)) in tests.into_iter().enumerate() {
589 let tester = test_clock();
591 let (host, ark) = duplex(4, &tester.clock());
592 let (_host_read, mut writer) = host.into_halves();
593 let (mut reader, _ark_write) = ark.into_halves();
594 writer.write_all(b"abcd").unwrap();
595 reader.read_exact(&mut [0; 2]).unwrap();
596 writer.write_all(b"ef").unwrap();
597 assert_eq!(
598 reader.pipe.lock().bytes.as_slices(),
599 (b"cd".as_slice(), b"ef".as_slice()),
600 "test {i}"
601 );
602
603 let mut buf = [b'-'; 6];
605 let copied = reader.read(&mut buf[..size]).unwrap();
606 assert_eq!(copied, count, "test {i}");
607 assert_eq!(&buf, filled, "test {i}");
608
609 drop(writer);
611 let mut left = Vec::new();
612 reader.read_to_end(&mut left).unwrap();
613 assert_eq!(left, rest, "test {i}");
614 }
615 }
616
617 #[test]
620 fn test_read_timeout_and_reuse() {
621 let mut tester = test_clock();
623 let clock = tester.clock();
624 let deadline = clock.now() + TIMEOUT;
625 let (host, ark) = duplex(1, &clock);
626 let (mut reader, _host_write, _host_close) = halves(host);
627 let (_ark_read, mut writer, _ark_close) = halves(ark);
628 let pipe = reader.pipe.clone();
629 let (done, result) = mpsc::channel();
630 let timed = thread::spawn(move || {
631 reader.set_read_deadline(Some(deadline)).unwrap();
632 let mut buf = [99];
633 let error = reader.read(&mut buf).unwrap_err();
634 assert!(clock.now() >= deadline);
635 assert_eq!(buf, [99]);
636 done.send((reader, error.kind())).unwrap();
637 });
638 tester.wait_registered(1);
639 tester.advance_to(deadline);
640 let (mut reader, kind) = result.recv().unwrap();
641 timed.join().unwrap();
642 assert_eq!(kind, io::ErrorKind::TimedOut);
643
644 reader.set_read_deadline(None).unwrap();
646 let (done, result) = mpsc::channel();
647 let reading = thread::spawn(move || {
648 let mut buf = [0];
649 reader.read_exact(&mut buf).unwrap();
650 done.send(buf).unwrap();
651 });
652 blocked(&pipe);
653 writer.write_all(b"x").unwrap();
654 assert_eq!(&result.recv().unwrap(), b"x");
655 reading.join().unwrap();
656 }
657
658 #[test]
661 fn test_write_timeout_and_reuse() {
662 let mut tester = test_clock();
664 let clock = tester.clock();
665 let deadline = clock.now() + TIMEOUT;
666 let (host, ark) = duplex(3, &clock);
667 let (_host_read, mut writer, _host_close) = halves(host);
668 let (mut reader, _ark_write, _ark_close) = halves(ark);
669 let (done, result) = mpsc::channel();
670 let writing = thread::spawn(move || {
671 writer.set_write_deadline(deadline).unwrap();
672 let error = writer.write_all(b"abcd").unwrap_err();
673 assert!(clock.now() >= deadline);
674 done.send((writer, error.kind())).unwrap();
675 });
676 tester.wait_registered(1);
677 tester.advance_to(deadline);
678 let (mut writer, kind) = result.recv().unwrap();
679 writing.join().unwrap();
680 assert_eq!(kind, io::ErrorKind::TimedOut);
681 let mut prefix = [0; 3];
682 reader.read_exact(&mut prefix).unwrap();
683 assert_eq!(&prefix, b"abc");
684
685 writer
687 .set_write_deadline(tester.clock().now() + Duration::from_secs(5))
688 .unwrap();
689 writer.write_all(b"ef").unwrap();
690 drop(writer);
691 let mut suffix = Vec::new();
692 reader.read_to_end(&mut suffix).unwrap();
693 assert_eq!(&suffix, b"ef");
694 }
695
696 #[test]
699 fn test_backpressure_wakes_writer() {
700 let tester = test_clock();
702 let deadline = tester.clock().now() + Duration::from_secs(5);
703 let (host, ark) = duplex(3, &tester.clock());
704 let (_host_read, mut writer, _host_close) = halves(host);
705 let (mut reader, _ark_write, _ark_close) = halves(ark);
706 writer.write_all(b"abc").unwrap();
707 let pipe = writer.pipe.clone();
708 let (done, result) = mpsc::channel();
709 let writing = thread::spawn(move || {
710 writer.set_write_deadline(deadline).unwrap();
711 done.send(writer.write_all(b"defgh")).unwrap();
712 });
713
714 blocked(&pipe);
716 reader.set_read_deadline(Some(deadline)).unwrap();
717 let mut bytes = [0; 8];
718 reader.read_exact(&mut bytes).unwrap();
719 assert_eq!(&bytes, b"abcdefgh");
720 result.recv().unwrap().unwrap();
721 writing.join().unwrap();
722 }
723
724 #[test]
727 fn test_shutdown_wakes_both_directions() {
728 for local in [false, true] {
729 let tester = test_clock();
731 let (host, ark) = duplex(1, &tester.clock());
732 let (mut reader, mut writer, closer) = halves(host);
733 writer.write_all(b"a").unwrap();
734 let incoming = reader.pipe.clone();
735 let outgoing = writer.pipe.clone();
736 let (read_done, read_result) = mpsc::channel();
737 let reading = thread::spawn(move || {
738 read_done.send(reader.read(&mut [0])).unwrap();
739 });
740 let (write_done, write_result) = mpsc::channel();
741 let writing = thread::spawn(move || {
742 write_done.send(writer.write(b"b")).unwrap();
743 });
744
745 blocked(&incoming);
747 blocked(&outgoing);
748 if local {
749 closer.close();
750 } else {
751 drop(ark);
752 }
753 assert_eq!(read_result.recv().unwrap().unwrap(), 0);
754 assert_eq!(
755 write_result.recv().unwrap().unwrap_err().kind(),
756 io::ErrorKind::BrokenPipe
757 );
758 reading.join().unwrap();
759 writing.join().unwrap();
760 }
761 }
762
763 #[test]
766 fn test_shutdown_drains_output_and_discards_input() {
767 let tester = test_clock();
769 let clock = tester.clock();
770 let (host, ark) = duplex(3, &clock);
771 let (mut host_read, mut host_write, closer) = halves(host);
772 let (mut ark_read, mut ark_write, _ark_close) = halves(ark);
773 host_write.write_all(b"abc").unwrap();
774 ark_write.write_all(b"xy").unwrap();
775 host_read.set_read_deadline(Some(clock.now())).unwrap();
776 ark_read.set_read_deadline(Some(clock.now())).unwrap();
777
778 closer.close();
780 closer.close();
781 assert_eq!(host_read.read(&mut [0]).unwrap(), 0);
782 let mut bytes = Vec::new();
783 ark_read.read_to_end(&mut bytes).unwrap();
784 assert_eq!(&bytes, b"abc");
785 for writer in [&mut host_write, &mut ark_write] {
786 assert_eq!(
787 writer.write(b"z").unwrap_err().kind(),
788 io::ErrorKind::BrokenPipe
789 );
790 assert_eq!(
791 writer.flush().unwrap_err().kind(),
792 io::ErrorKind::BrokenPipe
793 );
794 }
795 }
796
797 #[test]
800 fn test_flush_after_peer_drained_and_closed() {
801 let tester = test_clock();
803 let (host, ark) = duplex(4, &tester.clock());
804 let (_host_read, mut host_write) = host.into_halves();
805 let (mut ark_read, _ark_write) = ark.into_halves();
806 host_write.write_all(b"ab").unwrap();
807 let mut bytes = [0; 2];
808 ark_read.read_exact(&mut bytes).unwrap();
809 drop(ark_read);
810
811 host_write.flush().unwrap();
813 assert_eq!(
814 host_write.write(b"c").unwrap_err().kind(),
815 io::ErrorKind::BrokenPipe
816 );
817 }
818
819 #[test]
822 fn test_into_halves_and_independent_drop() {
823 let tester = test_clock();
825 let (host, ark) = duplex(4, &tester.clock());
826 let (mut host_read, mut host_write) = host.set_write_timeout(Duration::ZERO).into_halves();
827 let (mut ark_read, mut ark_write) = ark.into_halves();
828
829 host_write.write_all(b"abc").unwrap();
831 drop(host_write);
832 let mut bytes = Vec::new();
833 ark_read.read_to_end(&mut bytes).unwrap();
834 assert_eq!(&bytes, b"abc");
835
836 ark_write.write_all(b"xy").unwrap();
838 let mut reply = [0; 2];
839 host_read.read_exact(&mut reply).unwrap();
840 assert_eq!(&reply, b"xy");
841 drop(host_read);
842 assert_eq!(
843 ark_write.write(b"z").unwrap_err().kind(),
844 io::ErrorKind::BrokenPipe
845 );
846 }
847
848 #[test]
851 fn test_protocol_round_trip() {
852 use crate::protocol::{self, Message};
853 use crate::transport::mock::self_attestation;
854 use darkbio_crypto::xdsa;
855
856 let tester = test_clock();
858 let signer = xdsa::SecretKey::generate();
859 let identity = signer.public_key();
860 let attestation = self_attestation(&signer);
861 let (host, ark) = duplex(64 * 1024, &tester.clock());
862 let mut server = protocol::Server::new(ark, signer, attestation);
863 let (client, _) = protocol::connect(host, &identity).unwrap();
864 let mut session = server.accept().unwrap();
865
866 let payload: Vec<u8> = (0..256 * 1024).map(|n| n as u8).collect();
868 let deadline = tester.clock().now() + Duration::from_secs(5);
869 let answer = client
870 .requester()
871 .request(payload.clone(), deadline)
872 .unwrap();
873 let (message, responder) = session.recv().unwrap();
874 assert_eq!(message, Message::Develop(payload.clone()));
875 let written = responder.reply(message, deadline).unwrap();
876 assert_eq!(answer.wait::<Vec<u8>>().unwrap(), payload);
877 written.wait().unwrap();
878
879 client.close();
881 server.close();
882 }
883}