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());
137 for (out, byte) in buf.iter_mut().zip(state.bytes.drain(..count)) {
138 *out = byte;
139 }
140 drop(state);
141 self.pipe.changed.notify_all();
142 return Ok(count);
143 }
144
145 if !state.writer_open {
147 return Ok(0);
148 }
149 self.pipe.check_deadline(self.deadline)?;
150 state = self.pipe.wait(state, self.deadline);
151 }
152 }
153}
154
155impl Read for Reader {
156 fn clock(&self) -> Clock {
157 self.pipe.clock.clone()
158 }
159
160 fn set_read_deadline(&mut self, deadline: Option<Instant>) -> io::Result<()> {
161 self.deadline = deadline;
162 Ok(())
163 }
164}
165
166impl Drop for Reader {
167 fn drop(&mut self) {
169 self.pipe.close_reader();
170 }
171}
172
173#[cfg(test)]
174impl Reader {
175 pub(crate) fn forbid_waits(&self) {
178 self.pipe.lock().waits_forbidden = true;
179 }
180}
181
182#[derive(Debug)]
184pub struct Writer {
185 pipe: Arc<Pipe>,
187 deadline: Option<Instant>,
189}
190
191impl io::Write for Writer {
192 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
199 let mut state = self.pipe.lock();
201 loop {
202 self.pipe.check_deadline(self.deadline)?;
204 if buf.is_empty() {
205 return Ok(0);
206 }
207 if !state.reader_open || !state.writer_open {
208 return Err(io::ErrorKind::BrokenPipe.into());
209 }
210
211 let count = buf.len().min(self.pipe.capacity - state.bytes.len());
213 if count > 0 {
214 state.bytes.extend(&buf[..count]);
215 drop(state);
216 self.pipe.changed.notify_all();
217 return Ok(count);
218 }
219
220 state = self.pipe.wait(state, self.deadline);
222 }
223 }
224
225 fn flush(&mut self) -> io::Result<()> {
231 let state = self.pipe.lock();
233 self.pipe.check_deadline(self.deadline)?;
234
235 if !state.writer_open || state.lost {
237 return Err(io::ErrorKind::BrokenPipe.into());
238 }
239 Ok(())
240 }
241}
242
243impl Write for Writer {
244 fn clock(&self) -> Clock {
245 self.pipe.clock.clone()
246 }
247
248 fn set_write_deadline(&mut self, deadline: Instant) -> io::Result<()> {
249 self.deadline = Some(deadline);
250 Ok(())
251 }
252}
253
254impl Drop for Writer {
255 fn drop(&mut self) {
258 self.pipe.close_writer();
259 }
260}
261
262#[derive(Debug)]
266struct Pipe {
267 clock: Clock,
269 capacity: usize,
271 state: Mutex<State>,
273 changed: Condvar,
275}
276
277#[derive(Debug)]
279struct State {
280 bytes: VecDeque<u8>,
282 reader_open: bool,
284 writer_open: bool,
286 lost: bool,
288 #[cfg(test)]
290 waiting: usize,
291 #[cfg(test)]
293 waits_forbidden: bool,
294}
295
296impl Pipe {
297 fn new(capacity: usize, clock: &Clock) -> Self {
300 Self {
301 clock: clock.clone(),
302 capacity,
303 state: Mutex::new(State {
304 bytes: VecDeque::with_capacity(capacity),
305 reader_open: true,
306 writer_open: true,
307 lost: false,
308 #[cfg(test)]
309 waiting: 0,
310 #[cfg(test)]
311 waits_forbidden: false,
312 }),
313 changed: Condvar::new(clock),
314 }
315 }
316
317 fn lock(&self) -> MutexGuard<'_, State> {
319 self.state.lock().unwrap_or_else(|err| err.into_inner())
321 }
322
323 fn wait<'a>(
325 &self,
326 state: MutexGuard<'a, State>,
327 deadline: Option<Instant>,
328 ) -> MutexGuard<'a, State> {
329 #[cfg(test)]
331 let state = {
332 let mut state = state;
333 assert!(!state.waits_forbidden, "memory pipe waited");
334 state.waiting += 1;
335 self.changed.notify_all();
336 state
337 };
338
339 let state = match deadline {
341 Some(deadline) => {
342 self.changed
343 .wait_deadline(state, deadline)
344 .unwrap_or_else(|err| err.into_inner())
345 .0
346 }
347 None => self
348 .changed
349 .wait(state)
350 .unwrap_or_else(|err| err.into_inner()),
351 };
352
353 #[cfg(test)]
355 let state = {
356 let mut state = state;
357 state.waiting -= 1;
358 state
359 };
360 state
361 }
362
363 fn check_deadline(&self, deadline: Option<Instant>) -> io::Result<()> {
365 if deadline.is_some_and(|deadline| self.clock.now() >= deadline) {
366 return Err(io::ErrorKind::TimedOut.into());
367 }
368 Ok(())
369 }
370
371 fn close_reader(&self) {
374 let mut state = self.lock();
375 state.reader_open = false;
376 state.lost |= !state.bytes.is_empty();
377 state.bytes.clear();
378 drop(state);
379 self.changed.notify_all();
380 }
381
382 fn close_writer(&self) {
385 self.lock().writer_open = false;
386 self.changed.notify_all();
387 }
388}
389
390#[cfg(test)]
393#[cfg_attr(coverage_nightly, coverage(off))]
394mod tests {
395 use super::*;
396 use crate::transport::Closer;
397 use crate::transport::testing::test_clock;
398 use darkbio_clock::TestClock;
399 use std::io::{Read as _, Write as _};
400 use std::sync::mpsc;
401 use std::thread;
402 use std::time::Duration;
403
404 const TIMEOUT: Duration = Duration::from_millis(50);
406
407 fn halves(stream: Duplex) -> (Reader, Writer, Closer) {
409 let closer = stream.closer();
410 let (reader, writer) = stream.into_halves();
411 (reader, writer, closer)
412 }
413
414 fn blocked(pipe: &Pipe) {
416 let mut state = pipe.lock();
417 while state.waiting == 0 {
418 state = pipe.changed.wait(state).unwrap();
419 }
420 }
421
422 #[test]
425 fn test_blocked_read_expires_on_clock_deadline() {
426 let mut tester = TestClock::new();
428 tester.advance(Duration::from_secs(86400));
429 let clock = tester.clock();
430 let (host, _peer) = duplex(1, &clock);
431 let (mut reader, _writer) = host.into_halves();
432 let deadline = clock.now() + Duration::from_secs(5);
433 reader.set_read_deadline(Some(deadline)).unwrap();
434 let reading = thread::spawn(move || reader.read(&mut [0]));
435 tester.wait_blocked(1);
436 assert_eq!(tester.next_deadline(), Some(deadline));
437
438 tester.advance_to(deadline);
440 assert_eq!(
441 reading.join().unwrap().unwrap_err().kind(),
442 io::ErrorKind::TimedOut
443 );
444 }
445
446 #[test]
449 fn test_blocked_write_expires_on_clock_deadline() {
450 let mut tester = TestClock::new();
452 tester.advance(Duration::from_secs(86400));
453 let clock = tester.clock();
454 let (host, _peer) = duplex(1, &clock);
455 let (_reader, mut writer) = host.into_halves();
456 writer.write_all(b"a").unwrap();
457 let deadline = clock.now() + Duration::from_secs(5);
458 writer.set_write_deadline(deadline).unwrap();
459 let writing = thread::spawn(move || writer.write(b"b"));
460 tester.wait_blocked(1);
461 assert_eq!(tester.next_deadline(), Some(deadline));
462
463 tester.advance_to(deadline);
465 assert_eq!(
466 writing.join().unwrap().unwrap_err().kind(),
467 io::ErrorKind::TimedOut
468 );
469 }
470
471 #[test]
474 fn test_read_delivers_buffered_bytes_after_deadline() {
475 let mut tester = test_clock();
477 let clock = tester.clock();
478 let (host, peer) = duplex(1, &clock);
479 let (mut reader, _writer) = host.into_halves();
480 let (_peer_reader, mut writer) = peer.into_halves();
481 let deadline = clock.now() + Duration::from_secs(5);
482 reader.set_read_deadline(Some(deadline)).unwrap();
483 writer.write_all(b"a").unwrap();
484
485 tester.advance_to(deadline);
487 reader.forbid_waits();
488 let mut byte = [0];
489 assert_eq!(reader.read(&mut byte).unwrap(), 1);
490 assert_eq!(&byte, b"a");
491
492 assert_eq!(
494 reader.read(&mut byte).unwrap_err().kind(),
495 io::ErrorKind::TimedOut
496 );
497 }
498
499 #[test]
502 #[should_panic(expected = "duplex capacity must be nonzero")]
503 fn test_zero_capacity() {
504 duplex(0, &test_clock().clock());
505 }
506
507 #[test]
512 fn test_byte_stream_and_independent_deadlines() {
513 let tester = test_clock();
515 let clock = tester.clock();
516 let (host, ark) = duplex(4, &clock);
517 let (mut host_read, mut host_write, _host_close) = halves(host);
518 let (mut ark_read, mut ark_write, _ark_close) = halves(ark);
519
520 assert_eq!(host_read.read(&mut []).unwrap(), 0);
522 assert_eq!(host_write.write(b"abcdef").unwrap(), 4);
523 assert_eq!(host_write.write(&[]).unwrap(), 0);
524 host_write.flush().unwrap();
526 let mut first = [0; 2];
527 ark_read.read_exact(&mut first).unwrap();
528 assert_eq!(&first, b"ab");
529 host_write.write_all(b"ef").unwrap();
530 let mut rest = [0; 4];
531 ark_read.read_exact(&mut rest).unwrap();
532 assert_eq!(&rest, b"cdef");
533
534 ark_write.write_all(b"xy").unwrap();
536 host_read.set_read_deadline(Some(clock.now())).unwrap();
537 host_read.read_exact(&mut first).unwrap();
538 assert_eq!(&first, b"xy");
539 assert_eq!(
540 host_read.read(&mut first).unwrap_err().kind(),
541 io::ErrorKind::TimedOut
542 );
543 assert_eq!(host_read.read(&mut []).unwrap(), 0);
544 host_write.write_all(b"q").unwrap();
545
546 host_write.set_write_deadline(clock.now()).unwrap();
548 host_read.set_read_deadline(None).unwrap();
549 ark_write.write_all(b"uv").unwrap();
550 host_read.read_exact(&mut first).unwrap();
551 assert_eq!(&first, b"uv");
552 for bytes in [b"t".as_slice(), b""] {
553 assert_eq!(
554 host_write.write(bytes).unwrap_err().kind(),
555 io::ErrorKind::TimedOut
556 );
557 }
558 assert_eq!(
559 host_write.flush().unwrap_err().kind(),
560 io::ErrorKind::TimedOut
561 );
562
563 host_write
565 .set_write_deadline(clock.now() + Duration::from_secs(5))
566 .unwrap();
567 host_write.write_all(b"rs").unwrap();
568 host_write.flush().unwrap();
569 let mut accepted = [0; 3];
570 ark_read.read_exact(&mut accepted).unwrap();
571 assert_eq!(&accepted, b"qrs");
572 }
573
574 #[test]
577 fn test_read_timeout_and_reuse() {
578 let mut tester = test_clock();
580 let clock = tester.clock();
581 let deadline = clock.now() + TIMEOUT;
582 let (host, ark) = duplex(1, &clock);
583 let (mut reader, _host_write, _host_close) = halves(host);
584 let (_ark_read, mut writer, _ark_close) = halves(ark);
585 let pipe = reader.pipe.clone();
586 let (done, result) = mpsc::channel();
587 let timed = thread::spawn(move || {
588 reader.set_read_deadline(Some(deadline)).unwrap();
589 let mut buf = [99];
590 let error = reader.read(&mut buf).unwrap_err();
591 assert!(clock.now() >= deadline);
592 assert_eq!(buf, [99]);
593 done.send((reader, error.kind())).unwrap();
594 });
595 tester.wait_blocked(1);
596 tester.advance_to(deadline);
597 let (mut reader, kind) = result.recv().unwrap();
598 timed.join().unwrap();
599 assert_eq!(kind, io::ErrorKind::TimedOut);
600
601 reader.set_read_deadline(None).unwrap();
603 let (done, result) = mpsc::channel();
604 let reading = thread::spawn(move || {
605 let mut buf = [0];
606 reader.read_exact(&mut buf).unwrap();
607 done.send(buf).unwrap();
608 });
609 blocked(&pipe);
610 writer.write_all(b"x").unwrap();
611 assert_eq!(&result.recv().unwrap(), b"x");
612 reading.join().unwrap();
613 }
614
615 #[test]
618 fn test_write_timeout_and_reuse() {
619 let mut tester = test_clock();
621 let clock = tester.clock();
622 let deadline = clock.now() + TIMEOUT;
623 let (host, ark) = duplex(3, &clock);
624 let (_host_read, mut writer, _host_close) = halves(host);
625 let (mut reader, _ark_write, _ark_close) = halves(ark);
626 let (done, result) = mpsc::channel();
627 let writing = thread::spawn(move || {
628 writer.set_write_deadline(deadline).unwrap();
629 let error = writer.write_all(b"abcd").unwrap_err();
630 assert!(clock.now() >= deadline);
631 done.send((writer, error.kind())).unwrap();
632 });
633 tester.wait_blocked(1);
634 tester.advance_to(deadline);
635 let (mut writer, kind) = result.recv().unwrap();
636 writing.join().unwrap();
637 assert_eq!(kind, io::ErrorKind::TimedOut);
638 let mut prefix = [0; 3];
639 reader.read_exact(&mut prefix).unwrap();
640 assert_eq!(&prefix, b"abc");
641
642 writer
644 .set_write_deadline(tester.clock().now() + Duration::from_secs(5))
645 .unwrap();
646 writer.write_all(b"ef").unwrap();
647 drop(writer);
648 let mut suffix = Vec::new();
649 reader.read_to_end(&mut suffix).unwrap();
650 assert_eq!(&suffix, b"ef");
651 }
652
653 #[test]
656 fn test_backpressure_wakes_writer() {
657 let tester = test_clock();
659 let deadline = tester.clock().now() + Duration::from_secs(5);
660 let (host, ark) = duplex(3, &tester.clock());
661 let (_host_read, mut writer, _host_close) = halves(host);
662 let (mut reader, _ark_write, _ark_close) = halves(ark);
663 writer.write_all(b"abc").unwrap();
664 let pipe = writer.pipe.clone();
665 let (done, result) = mpsc::channel();
666 let writing = thread::spawn(move || {
667 writer.set_write_deadline(deadline).unwrap();
668 done.send(writer.write_all(b"defgh")).unwrap();
669 });
670
671 blocked(&pipe);
673 reader.set_read_deadline(Some(deadline)).unwrap();
674 let mut bytes = [0; 8];
675 reader.read_exact(&mut bytes).unwrap();
676 assert_eq!(&bytes, b"abcdefgh");
677 result.recv().unwrap().unwrap();
678 writing.join().unwrap();
679 }
680
681 #[test]
684 fn test_shutdown_wakes_both_directions() {
685 for local in [false, true] {
686 let tester = test_clock();
688 let (host, ark) = duplex(1, &tester.clock());
689 let (mut reader, mut writer, closer) = halves(host);
690 writer.write_all(b"a").unwrap();
691 let incoming = reader.pipe.clone();
692 let outgoing = writer.pipe.clone();
693 let (read_done, read_result) = mpsc::channel();
694 let reading = thread::spawn(move || {
695 read_done.send(reader.read(&mut [0])).unwrap();
696 });
697 let (write_done, write_result) = mpsc::channel();
698 let writing = thread::spawn(move || {
699 write_done.send(writer.write(b"b")).unwrap();
700 });
701
702 blocked(&incoming);
704 blocked(&outgoing);
705 if local {
706 closer.close();
707 } else {
708 drop(ark);
709 }
710 assert_eq!(read_result.recv().unwrap().unwrap(), 0);
711 assert_eq!(
712 write_result.recv().unwrap().unwrap_err().kind(),
713 io::ErrorKind::BrokenPipe
714 );
715 reading.join().unwrap();
716 writing.join().unwrap();
717 }
718 }
719
720 #[test]
723 fn test_shutdown_drains_output_and_discards_input() {
724 let tester = test_clock();
726 let clock = tester.clock();
727 let (host, ark) = duplex(3, &clock);
728 let (mut host_read, mut host_write, closer) = halves(host);
729 let (mut ark_read, mut ark_write, _ark_close) = halves(ark);
730 host_write.write_all(b"abc").unwrap();
731 ark_write.write_all(b"xy").unwrap();
732 host_read.set_read_deadline(Some(clock.now())).unwrap();
733 ark_read.set_read_deadline(Some(clock.now())).unwrap();
734
735 closer.close();
737 closer.close();
738 assert_eq!(host_read.read(&mut [0]).unwrap(), 0);
739 let mut bytes = Vec::new();
740 ark_read.read_to_end(&mut bytes).unwrap();
741 assert_eq!(&bytes, b"abc");
742 for writer in [&mut host_write, &mut ark_write] {
743 assert_eq!(
744 writer.write(b"z").unwrap_err().kind(),
745 io::ErrorKind::BrokenPipe
746 );
747 assert_eq!(
748 writer.flush().unwrap_err().kind(),
749 io::ErrorKind::BrokenPipe
750 );
751 }
752 }
753
754 #[test]
757 fn test_flush_after_peer_drained_and_closed() {
758 let tester = test_clock();
760 let (host, ark) = duplex(4, &tester.clock());
761 let (_host_read, mut host_write) = host.into_halves();
762 let (mut ark_read, _ark_write) = ark.into_halves();
763 host_write.write_all(b"ab").unwrap();
764 let mut bytes = [0; 2];
765 ark_read.read_exact(&mut bytes).unwrap();
766 drop(ark_read);
767
768 host_write.flush().unwrap();
770 assert_eq!(
771 host_write.write(b"c").unwrap_err().kind(),
772 io::ErrorKind::BrokenPipe
773 );
774 }
775
776 #[test]
779 fn test_into_halves_and_independent_drop() {
780 let tester = test_clock();
782 let (host, ark) = duplex(4, &tester.clock());
783 let (mut host_read, mut host_write) = host.set_write_timeout(Duration::ZERO).into_halves();
784 let (mut ark_read, mut ark_write) = ark.into_halves();
785
786 host_write.write_all(b"abc").unwrap();
788 drop(host_write);
789 let mut bytes = Vec::new();
790 ark_read.read_to_end(&mut bytes).unwrap();
791 assert_eq!(&bytes, b"abc");
792
793 ark_write.write_all(b"xy").unwrap();
795 let mut reply = [0; 2];
796 host_read.read_exact(&mut reply).unwrap();
797 assert_eq!(&reply, b"xy");
798 drop(host_read);
799 assert_eq!(
800 ark_write.write(b"z").unwrap_err().kind(),
801 io::ErrorKind::BrokenPipe
802 );
803 }
804
805 #[test]
808 fn test_protocol_round_trip() {
809 use crate::protocol::{self, Message};
810 use crate::transport::mock::self_attestation;
811 use darkbio_crypto::xdsa;
812
813 let tester = test_clock();
815 let signer = xdsa::SecretKey::generate();
816 let identity = signer.public_key();
817 let attestation = self_attestation(&signer);
818 let (host, ark) = duplex(64 * 1024, &tester.clock());
819 let mut server = protocol::Server::new(ark, signer, attestation);
820 let (client, _) = protocol::connect(host, &identity).unwrap();
821 let mut session = server.accept().unwrap();
822
823 let payload: Vec<u8> = (0..256 * 1024).map(|n| n as u8).collect();
825 let deadline = tester.clock().now() + Duration::from_secs(5);
826 let answer = client
827 .requester()
828 .request(payload.clone(), deadline)
829 .unwrap();
830 let (message, responder) = session.recv().unwrap();
831 assert_eq!(message, Message::Develop(payload.clone()));
832 let written = responder.reply(message, deadline).unwrap();
833 assert_eq!(answer.wait::<Vec<u8>>().unwrap(), payload);
834 written.wait().unwrap();
835
836 client.close();
838 server.close();
839 }
840}