1use super::io::check_deadline;
10use super::{DEFAULT_WRITE_TIMEOUT, Read, Write};
11use darkbio_clock::Clock;
12use darkbio_clock::sync::{Condvar, Mutex};
13use std::fmt;
14use std::io;
15use std::sync::Arc;
16use std::time::{Duration, Instant};
17use tracing::debug;
18
19pub struct Stream<R: Read, W: Write> {
38 clock: Clock,
40 io: Option<(R, W)>,
42 closer: Closer,
44 timeout: Duration,
46}
47
48impl<R: Read, W: Write> Stream<R, W> {
49 pub fn new(reader: R, writer: W, shutdown: impl FnOnce() + Send + 'static) -> Self {
58 let clock = reader.clock();
60 assert_eq!(
61 clock,
62 writer.clock(),
63 "stream halves must use the same clock"
64 );
65
66 Self {
68 closer: Closer::new(&clock, shutdown),
69 clock,
70 io: Some((reader, writer)),
71 timeout: DEFAULT_WRITE_TIMEOUT,
72 }
73 }
74
75 pub fn clock(&self) -> Clock {
77 self.clock.clone()
78 }
79
80 pub fn set_write_timeout(mut self, timeout: Duration) -> Self {
91 self.timeout = timeout;
92 self
93 }
94
95 pub fn closer(&self) -> Closer {
97 self.closer.clone()
98 }
99
100 pub fn close(&self) {
106 self.closer.close();
107 }
108
109 pub(crate) fn into_parts(mut self) -> (R, W, Closer, Duration) {
112 let (reader, writer) = self.io.take().expect("stream consumed once");
113 (reader, writer, self.closer.clone(), self.timeout)
114 }
115}
116
117impl<R: Read, W: Write> Drop for Stream<R, W> {
118 fn drop(&mut self) {
119 if self.io.is_some() {
120 self.close();
121 }
122 }
123}
124
125impl<R: Read, W: Write> fmt::Debug for Stream<R, W> {
126 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
128 f.debug_struct("Stream")
129 .field("timeout", &self.timeout)
130 .field("closer", &self.closer)
131 .finish_non_exhaustive()
132 }
133}
134
135#[derive(Clone)]
137pub struct Closer(
138 Arc<Shutdown>,
140);
141
142struct Shutdown {
147 state: Mutex<State>,
149 changed: Condvar,
151}
152
153#[derive(Clone, Copy, Debug, PartialEq, Eq)]
158enum Phase {
159 Open,
161 Closing,
164 Closed,
167}
168
169struct State {
174 phase: Phase,
176 active: usize,
178 action: Option<Box<dyn FnOnce() + Send>>,
180}
181
182impl Closer {
183 pub(super) fn new(clock: &Clock, shutdown: impl FnOnce() + Send + 'static) -> Self {
186 Self(Arc::new(Shutdown {
187 state: Mutex::new(State {
188 phase: Phase::Open,
189 active: 0,
190 action: Some(Box::new(shutdown)),
191 }),
192 changed: Condvar::new(clock),
193 }))
194 }
195
196 pub fn close(&self) {
208 let action = {
210 let mut state = self.0.state.lock().expect("stream state not poisoned");
211 loop {
212 match state.phase {
213 Phase::Closed => return,
215
216 Phase::Closing => {
218 state = self
219 .0
220 .changed
221 .wait(state)
222 .expect("stream state not poisoned");
223 }
224
225 Phase::Open => {
227 debug!("closing wire stream");
228 state.phase = Phase::Closing;
229 break state.action.take().expect("shutdown called once");
230 }
231 }
232 }
233 };
234
235 action();
237
238 let mut state = self.0.state.lock().expect("stream state not poisoned");
240 while state.active != 0 {
241 state = self
242 .0
243 .changed
244 .wait(state)
245 .expect("stream state not poisoned");
246 }
247
248 state.phase = Phase::Closed;
250 self.0.changed.notify_all();
251 }
252
253 fn enter(&self) -> Option<Activity<'_>> {
259 let mut state = self.0.state.lock().expect("stream state not poisoned");
260 if state.phase != Phase::Open {
261 return None;
262 }
263 state.active += 1;
264 Some(Activity(self))
265 }
266}
267
268impl fmt::Debug for Closer {
269 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
273 let mut closer = f.debug_struct("Closer");
274 match self.0.state.try_lock() {
275 Ok(state) => closer
276 .field("phase", &state.phase)
277 .field("active", &state.active),
278 Err(_) => closer.field("state", &format_args!("<locked>")),
279 };
280 closer.finish()
281 }
282}
283
284struct Activity<'a>(
288 &'a Closer,
290);
291
292impl Drop for Activity<'_> {
293 fn drop(&mut self) {
294 let mut state = self.0.0.state.lock().expect("stream state not poisoned");
295 state.active -= 1;
296 if state.active == 0 {
297 self.0.0.changed.notify_all();
298 }
299 }
300}
301
302pub(super) struct ReadHalf<R> {
304 pub(super) inner: R,
306 pub(super) closer: Closer,
308}
309
310impl<R: Read> ReadHalf<R> {
311 pub(super) fn read(&mut self, buf: &mut [u8], deadline: Option<Instant>) -> io::Result<usize> {
318 loop {
319 if let Some(deadline) = deadline {
321 check_deadline(&self.inner.clock(), deadline)?;
322 }
323
324 let result = {
326 let Some(_active) = self.closer.enter() else {
327 return Ok(0);
328 };
329 self.inner.set_read_deadline(deadline)?;
330 self.inner.read(buf)
331 };
332
333 match result {
335 Err(err)
336 if matches!(
337 err.kind(),
338 io::ErrorKind::TimedOut | io::ErrorKind::Interrupted
339 ) =>
340 {
341 continue;
342 }
343 result => return result,
344 }
345 }
346 }
347}
348
349pub(super) struct WriteHalf<W> {
352 pub(super) inner: W,
354 pub(super) closer: Closer,
356}
357
358impl<W: Write> WriteHalf<W> {
359 pub(super) fn write(&mut self, mut bytes: &[u8], deadline: Instant) -> io::Result<()> {
371 check_deadline(&self.inner.clock(), deadline)?;
373
374 {
376 let _active = self
377 .closer
378 .enter()
379 .ok_or_else(|| io::Error::new(io::ErrorKind::NotConnected, "stream closed"))?;
380 self.inner.set_write_deadline(deadline)?;
381 }
382
383 while !bytes.is_empty() {
385 check_deadline(&self.inner.clock(), deadline)?;
387
388 let result = {
390 let _active = self
391 .closer
392 .enter()
393 .ok_or_else(|| io::Error::new(io::ErrorKind::NotConnected, "stream closed"))?;
394 self.inner.write(bytes)
395 };
396 match result {
397 Ok(0) => return Err(io::ErrorKind::WriteZero.into()),
398 Ok(n) => bytes = &bytes[n..],
399 Err(err) if err.kind() == io::ErrorKind::Interrupted => continue,
400 Err(err) => return Err(err),
401 }
402 }
403
404 check_deadline(&self.inner.clock(), deadline)?;
406 let _active = self
407 .closer
408 .enter()
409 .ok_or_else(|| io::Error::new(io::ErrorKind::NotConnected, "stream closed"))?;
410 self.inner.flush()
411 }
412}
413
414#[cfg(test)]
416#[cfg_attr(coverage_nightly, coverage(off))]
417mod tests {
418 use super::*;
419 use crate::testing;
420 use crate::transport::Client;
421 use crate::transport::testing::{Memory, test_clock};
422 use std::sync::atomic::{AtomicUsize, Ordering};
423 use std::sync::mpsc;
424 use std::thread;
425 use std::time::Duration;
426
427 #[test]
430 fn test_concurrent_closers_wait_on_stream_clock() {
431 let tester = darkbio_clock::TestClock::new();
433 let (stream, _peer) = crate::memory::duplex(1, &tester.clock());
434 let closer = stream.closer();
435 let activity = closer.enter().unwrap();
436 thread::scope(|scope| {
437 let first = scope.spawn(|| closer.close());
438 let second = scope.spawn(|| closer.close());
439
440 tester.wait_registered(2);
442 assert!(closer.enter().is_none());
443
444 drop(activity);
446 first.join().unwrap();
447 second.join().unwrap();
448 assert!(closer.enter().is_none());
449 });
450 }
451
452 #[test]
455 fn test_debug_capabilities() {
456 use crate::transport::{Attestation, Event, Roots, Sender, Server};
457
458 fn printable<T: fmt::Debug>() {}
460 printable::<Stream<Box<dyn Read>, Box<dyn Write>>>();
461 printable::<Closer>();
462 printable::<Client<Box<dyn Read>, Box<dyn Write>>>();
463 printable::<Server<Box<dyn Read>, Box<dyn Write>, Attestation>>();
464 printable::<Sender<Box<dyn Write>>>();
465 printable::<Event<Box<dyn Write>>>();
466 printable::<Attestation>();
467 printable::<Roots<'static>>();
468 }
469
470 #[test]
473 fn test_memory_reader_keeps_transport_deadline() {
474 let tester = test_clock();
476 let clock = tester.clock();
477 let (host, ark) = crate::memory::duplex(4, &clock);
478 let (_ark_read, mut ark_write) = ark.into_halves();
479 std::io::Write::write_all(&mut ark_write, b"abc").unwrap();
480 let (reader, _writer, closer, _) = host.into_parts();
481 let mut reader = ReadHalf {
482 inner: reader,
483 closer,
484 };
485
486 let mut bytes = [0; 3];
488 assert_eq!(
489 reader
490 .read(&mut bytes, Some(clock.now()))
491 .unwrap_err()
492 .kind(),
493 io::ErrorKind::TimedOut
494 );
495 assert_eq!(bytes, [0; 3]);
496 assert_eq!(reader.read(&mut bytes, None).unwrap(), 3);
497 assert_eq!(&bytes, b"abc");
498 }
499
500 struct Adapter {
503 clock: Clock,
505 entered: mpsc::Sender<()>,
507 released: testing::Gate,
509 fails: bool,
511 deadline: Option<Instant>,
513 }
514
515 impl Adapter {
516 fn wait(&self, deadline: Option<Instant>) -> io::Result<()> {
519 self.entered.send(()).unwrap();
520 self.released.wait(deadline)?;
521 if self.fails {
522 Err(io::Error::other("adapter failure"))
523 } else {
524 Ok(())
525 }
526 }
527 }
528
529 impl Read for Adapter {
530 fn clock(&self) -> Clock {
531 self.clock.clone()
532 }
533
534 fn set_read_deadline(&mut self, deadline: Option<Instant>) -> io::Result<()> {
535 self.deadline = deadline;
536 Ok(())
537 }
538 }
539
540 impl io::Read for Adapter {
541 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
542 self.wait(self.deadline)?;
543 buf[0] = 0x5a;
544 Ok(1)
545 }
546 }
547
548 impl Write for Adapter {
549 fn clock(&self) -> Clock {
550 self.clock.clone()
551 }
552
553 fn set_write_deadline(&mut self, deadline: Instant) -> io::Result<()> {
554 self.deadline = Some(deadline);
555 Ok(())
556 }
557 }
558
559 impl io::Write for Adapter {
560 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
561 self.wait(Some(self.deadline.expect("write deadline installed")))?;
562 Ok(buf.len())
563 }
564
565 fn flush(&mut self) -> io::Result<()> {
566 self.wait(Some(self.deadline.expect("write deadline installed")))
567 }
568 }
569
570 fn during_shutdown(
572 fails: bool,
573 operation: impl FnOnce(Adapter, Closer) -> io::Result<()> + Send + 'static,
574 ) {
575 let tester = test_clock();
577 let clock = tester.clock();
578 let (entered, entries) = mpsc::channel();
579 let released = testing::Gate::new(&clock);
580 let release = released.clone();
581 let closer = Closer::new(&clock, move || release.open());
582 let io = thread::spawn({
583 let closer = closer.clone();
584 move || {
585 operation(
586 Adapter {
587 clock,
588 entered,
589 released,
590 fails,
591 deadline: None,
592 },
593 closer,
594 )
595 }
596 });
597
598 entries.recv().unwrap();
600 tester.wait_registered(1);
601 closer.close();
602 let result = io.join().unwrap();
603 if fails {
604 let err = result.unwrap_err();
605 assert_eq!(err.kind(), io::ErrorKind::Other);
606 assert_eq!(err.to_string(), "adapter failure");
607 } else {
608 result.unwrap();
609 }
610 }
611
612 #[test]
615 fn test_admitted_io_preserves_results_during_shutdown() {
616 for fails in [false, true] {
617 during_shutdown(fails, |inner, closer| {
619 let mut buf = [0];
620 assert_eq!(ReadHalf { inner, closer }.read(&mut buf, None)?, 1);
621 assert_eq!(buf, [0x5a]);
622 Ok(())
623 });
624
625 during_shutdown(fails, move |inner, closer| {
627 let deadline = inner.clock.now() + Duration::from_secs(5);
628 let result = WriteHalf { inner, closer }.write(&[1, 2, 3], deadline);
629 if fails {
630 result
631 } else {
632 assert_eq!(result.unwrap_err().kind(), io::ErrorKind::NotConnected);
633 Ok(())
634 }
635 });
636
637 during_shutdown(fails, |inner, closer| {
639 let deadline = inner.clock.now() + Duration::from_secs(5);
640 WriteHalf { inner, closer }.write(&[], deadline)
641 });
642 }
643 }
644
645 #[test]
648 fn test_ownership_and_repeated_close() {
649 let tester = test_clock();
651 let clock = tester.clock();
652 let calls = Arc::new(AtomicUsize::new(0));
653 let stream = Stream::new(
654 Memory::new(io::empty(), &clock),
655 Memory::new(io::sink(), &clock),
656 {
657 let calls = calls.clone();
658 move || {
659 calls.fetch_add(1, Ordering::SeqCst);
660 }
661 },
662 );
663 let closer = stream.closer();
664 let client = Client::new(stream);
665 assert_eq!(
666 calls.load(Ordering::SeqCst),
667 0,
668 "handoff must keep the stream open"
669 );
670
671 drop(client);
673 assert_eq!(calls.load(Ordering::SeqCst), 1);
674 closer.close();
675 drop(closer.clone());
676 assert_eq!(calls.load(Ordering::SeqCst), 1);
677
678 let stream = Stream::new(
680 Memory::new(io::empty(), &clock),
681 Memory::new(io::sink(), &clock),
682 {
683 let calls = calls.clone();
684 move || {
685 calls.fetch_add(1, Ordering::SeqCst);
686 }
687 },
688 );
689 drop(stream);
690 assert_eq!(
691 calls.load(Ordering::SeqCst),
692 2,
693 "unclaimed streams also close on drop"
694 );
695 }
696
697 #[test]
700 fn test_every_closer_waits_for_the_shutdown_callback() {
701 let tester = test_clock();
703 let clock = tester.clock();
704 let (entered, callback) = mpsc::channel();
705 let release = testing::Gate::new(&clock);
706 let released = release.clone();
707 let stream = Stream::new(
708 Memory::new(io::empty(), &clock),
709 Memory::new(io::sink(), &clock),
710 move || {
711 entered.send(()).unwrap();
712 released.wait(None).unwrap();
713 },
714 );
715 let closer = stream.closer();
716 let (finished, finishes) = mpsc::channel();
717 let first = thread::spawn({
718 let closer = closer.clone();
719 let finished = finished.clone();
720 move || {
721 closer.close();
722 finished.send(()).unwrap();
723 }
724 });
725 callback.recv().unwrap();
726
727 let (started, starts) = mpsc::channel();
729 let second = thread::spawn({
730 let closer = closer.clone();
731 let started = started.clone();
732 let finished = finished.clone();
733 move || {
734 started.send(()).unwrap();
735 closer.close();
736 finished.send(()).unwrap();
737 }
738 });
739 let owner = thread::spawn(move || {
740 started.send(()).unwrap();
741 drop(stream);
742 finished.send(()).unwrap();
743 });
744 starts.recv().unwrap();
745 starts.recv().unwrap();
746 tester.wait_registered(3);
747 assert!(finishes.try_recv().is_err());
748
749 release.open();
751 finishes.recv().unwrap();
752 finishes.recv().unwrap();
753 finishes.recv().unwrap();
754 first.join().unwrap();
755 second.join().unwrap();
756 owner.join().unwrap();
757 }
758
759 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
761 enum BlockAt {
762 Read,
764 Write,
766 Flush,
768 }
769
770 struct Gate {
774 clock: Clock,
776 at: BlockAt,
778 entered: mpsc::Sender<()>,
780 released: testing::Gate,
782 calls: AtomicUsize,
784 }
785
786 impl Gate {
787 fn call(&self, at: BlockAt, deadline: Option<Instant>) -> io::Result<()> {
790 self.calls.fetch_add(1, Ordering::SeqCst);
791 if at == self.at {
792 self.entered.send(()).unwrap();
793 self.released.wait(deadline)?;
794 }
795 Ok(())
796 }
797
798 fn release(&self) {
800 self.released.open();
801 }
802 }
803
804 struct GatedAdapter {
806 gate: Arc<Gate>,
808 deadline: Option<Instant>,
810 }
811
812 impl Read for GatedAdapter {
813 fn clock(&self) -> Clock {
814 self.gate.clock.clone()
815 }
816
817 fn set_read_deadline(&mut self, deadline: Option<Instant>) -> io::Result<()> {
818 self.deadline = deadline;
819 Ok(())
820 }
821 }
822
823 impl io::Read for GatedAdapter {
824 fn read(&mut self, _: &mut [u8]) -> io::Result<usize> {
825 self.gate.call(BlockAt::Read, self.deadline)?;
826 Ok(0)
827 }
828 }
829
830 impl Write for GatedAdapter {
831 fn clock(&self) -> Clock {
832 self.gate.clock.clone()
833 }
834
835 fn set_write_deadline(&mut self, deadline: Instant) -> io::Result<()> {
836 self.deadline = Some(deadline);
837 Ok(())
838 }
839 }
840
841 impl io::Write for GatedAdapter {
842 fn write(&mut self, bytes: &[u8]) -> io::Result<usize> {
843 self.gate.call(
844 BlockAt::Write,
845 Some(self.deadline.expect("write deadline installed")),
846 )?;
847 Ok(bytes.len())
848 }
849
850 fn flush(&mut self) -> io::Result<()> {
851 self.gate.call(
852 BlockAt::Flush,
853 Some(self.deadline.expect("write deadline installed")),
854 )
855 }
856 }
857
858 #[test]
861 fn test_every_closer_waits_for_active_io_and_refuses_new_io() {
862 for at in [BlockAt::Read, BlockAt::Write, BlockAt::Flush] {
863 let tester = test_clock();
865 let clock = tester.clock();
866 let (entered, entries) = mpsc::channel();
867 let gate = Arc::new(Gate {
868 clock: clock.clone(),
869 at,
870 entered,
871 released: testing::Gate::new(&clock),
872 calls: AtomicUsize::new(0),
873 });
874 let (requested, requests) = mpsc::channel();
875 let stream = Stream::new(
876 GatedAdapter {
877 gate: gate.clone(),
878 deadline: None,
879 },
880 GatedAdapter {
881 gate: gate.clone(),
882 deadline: None,
883 },
884 move || {
885 requested.send(()).unwrap();
886 },
887 );
888 let (reader, writer, closer, _) = stream.into_parts();
889 let io_closer = closer.clone();
890 let deadline = clock.now() + Duration::from_secs(5);
891 let io = thread::spawn(move || {
892 let mut reader = ReadHalf {
893 inner: reader,
894 closer: io_closer.clone(),
895 };
896 let mut writer = WriteHalf {
897 inner: writer,
898 closer: io_closer,
899 };
900 match at {
901 BlockAt::Read => assert_eq!(reader.read(&mut [0], None).unwrap(), 0),
902 BlockAt::Write => assert_eq!(
903 writer.write(&[1], deadline).unwrap_err().kind(),
904 io::ErrorKind::NotConnected
905 ),
906 BlockAt::Flush => writer.write(&[], deadline).unwrap(),
907 }
908 (reader, writer)
909 });
910 entries.recv().unwrap();
911
912 let (finished, finishes) = mpsc::channel();
914 let closing = thread::spawn({
915 let closer = closer.clone();
916 move || {
917 closer.close();
918 finished.send(()).unwrap();
919 }
920 });
921 requests.recv().unwrap();
922 tester.wait_registered(2);
923 assert!(finishes.try_recv().is_err());
924
925 gate.release();
927 finishes.recv().unwrap();
928 closing.join().unwrap();
929 let (mut reader, mut writer) = io.join().unwrap();
930 let calls = gate.calls.load(Ordering::SeqCst);
931 assert_eq!(reader.read(&mut [0], None).unwrap(), 0);
932 assert!(matches!(
933 writer.write(&[1], deadline),
934 Err(err) if err.kind() == io::ErrorKind::NotConnected
935 ));
936 assert_eq!(gate.calls.load(Ordering::SeqCst), calls);
937 closer.close();
938 assert!(requests.try_recv().is_err(), "shutdown called twice");
939 }
940 }
941
942 struct BudgetWriter {
947 clock: Clock,
949 bytes: Vec<u8>,
951 deadlines: Vec<Instant>,
953 stall_flush: bool,
955 deadline: Option<Instant>,
957 settings: usize,
959 }
960
961 impl Write for BudgetWriter {
962 fn clock(&self) -> Clock {
963 self.clock.clone()
964 }
965
966 fn set_write_deadline(&mut self, deadline: Instant) -> io::Result<()> {
967 self.deadline = Some(deadline);
968 self.settings += 1;
969 Ok(())
970 }
971 }
972
973 impl io::Write for BudgetWriter {
974 fn write(&mut self, bytes: &[u8]) -> io::Result<usize> {
975 let deadline = self.deadline.expect("write deadline installed");
976 check_deadline(&self.clock(), deadline)?;
977 self.deadlines.push(deadline);
978 self.bytes.push(bytes[0]);
979 Ok(1)
980 }
981
982 fn flush(&mut self) -> io::Result<()> {
983 let deadline = self.deadline.expect("write deadline installed");
984 self.deadlines.push(deadline);
985 if self.stall_flush {
986 self.clock.sleep_until(deadline);
987 return Err(io::ErrorKind::TimedOut.into());
988 }
989 check_deadline(&self.clock(), deadline)
990 }
991 }
992
993 #[test]
996 fn test_output_deadline_and_reuse() {
997 let mut tester = test_clock();
999 let clock = tester.clock();
1000 let timeout = Duration::from_millis(40);
1001 let stream = Stream::new(
1002 Memory::new(io::empty(), &clock),
1003 BudgetWriter {
1004 clock: clock.clone(),
1005 bytes: Vec::new(),
1006 deadlines: Vec::new(),
1007 stall_flush: true,
1008 deadline: None,
1009 settings: 0,
1010 },
1011 || {},
1012 )
1013 .set_write_timeout(timeout);
1014 let (_, inner, closer, configured) = stream.into_parts();
1015 assert_eq!(configured, timeout);
1016 let mut writer = WriteHalf { inner, closer };
1017 let deadline = clock.now() + configured;
1018 let result = thread::scope(|scope| {
1019 let writing = scope.spawn(|| writer.write(b"abc", deadline));
1020 tester.wait_registered(1);
1021 assert_eq!(tester.next_deadline(), Some(deadline));
1022 tester.advance_to(deadline);
1023 writing.join().unwrap()
1024 });
1025 assert_eq!(result.unwrap_err().kind(), io::ErrorKind::TimedOut);
1026 assert_eq!(writer.inner.deadlines, vec![deadline; 4]);
1027 assert_eq!(writer.inner.settings, 1);
1028
1029 writer.inner.stall_flush = false;
1031 let deadline = clock.now() + Duration::from_secs(5);
1032 writer.write(b"d", deadline).unwrap();
1033 assert_eq!(writer.inner.bytes, b"abcd");
1034 assert_eq!(writer.inner.settings, 2);
1035
1036 let calls = writer.inner.deadlines.len();
1038 let deadline = clock.now();
1039 assert!(matches!(
1040 writer.write(b"e", deadline),
1041 Err(err) if err.kind() == io::ErrorKind::TimedOut
1042 ));
1043 assert_eq!(writer.inner.deadlines.len(), calls);
1044 assert_eq!(writer.inner.settings, 2);
1045 writer.closer.close();
1046 }
1047
1048 #[test]
1051 fn test_partial_write_retries_and_failures() {
1052 struct Script {
1055 clock: Clock,
1057 results: std::collections::VecDeque<io::Result<usize>>,
1059 offered: Vec<Vec<u8>>,
1061 accepted: Vec<u8>,
1063 interrupted_flush: bool,
1065 flushes: usize,
1067 settings: usize,
1069 deadline: Option<Instant>,
1071 }
1072
1073 impl Write for Script {
1074 fn clock(&self) -> Clock {
1075 self.clock.clone()
1076 }
1077
1078 fn set_write_deadline(&mut self, deadline: Instant) -> io::Result<()> {
1079 self.settings += 1;
1080 self.deadline = Some(deadline);
1081 Ok(())
1082 }
1083 }
1084
1085 impl io::Write for Script {
1086 fn write(&mut self, bytes: &[u8]) -> io::Result<usize> {
1087 check_deadline(
1088 &self.clock(),
1089 self.deadline.expect("write deadline installed"),
1090 )?;
1091 self.offered.push(bytes.to_vec());
1092 let result = self.results.pop_front().expect("unexpected write");
1093 if let Ok(size) = &result {
1094 self.accepted.extend_from_slice(&bytes[..*size]);
1095 }
1096 result
1097 }
1098
1099 fn flush(&mut self) -> io::Result<()> {
1100 check_deadline(
1101 &self.clock(),
1102 self.deadline.expect("write deadline installed"),
1103 )?;
1104 self.flushes += 1;
1105 assert_eq!(self.flushes, 1, "flush retried");
1106 if self.interrupted_flush {
1107 Err(io::ErrorKind::Interrupted.into())
1108 } else {
1109 Ok(())
1110 }
1111 }
1112 }
1113
1114 for (stalls, interrupted_flush) in [(false, false), (true, false), (false, true)] {
1115 let tester = test_clock();
1117 let clock = tester.clock();
1118 let mut writer = WriteHalf {
1119 inner: Script {
1120 clock: clock.clone(),
1121 results: [
1122 Err(io::ErrorKind::Interrupted.into()),
1123 Ok(1),
1124 Ok(usize::from(!stalls)),
1125 ]
1126 .into(),
1127 offered: Vec::new(),
1128 accepted: Vec::new(),
1129 interrupted_flush,
1130 flushes: 0,
1131 settings: 0,
1132 deadline: None,
1133 },
1134 closer: Closer::new(&clock, || {}),
1135 };
1136 let result = writer.write(b"ab", clock.now() + Duration::from_secs(5));
1137 if stalls {
1138 assert_eq!(result.unwrap_err().kind(), io::ErrorKind::WriteZero);
1139 } else if interrupted_flush {
1140 assert_eq!(result.unwrap_err().kind(), io::ErrorKind::Interrupted);
1141 } else {
1142 result.unwrap();
1143 }
1144
1145 assert_eq!(
1147 writer.inner.offered,
1148 [b"ab".to_vec(), b"ab".to_vec(), b"b".to_vec()]
1149 );
1150 assert_eq!(
1151 writer.inner.accepted,
1152 if stalls { &b"a"[..] } else { &b"ab"[..] }
1153 );
1154 assert_eq!(writer.inner.flushes, usize::from(!stalls));
1155 assert_eq!(writer.inner.settings, 1);
1156 writer.closer.close();
1157 }
1158 }
1159
1160 #[test]
1165 fn test_deadline_setter_failure_prevents_io() {
1166 struct Refused {
1169 clock: Clock,
1171 settings: usize,
1173 kind: io::ErrorKind,
1175 }
1176
1177 impl Refused {
1178 fn reject(&mut self) -> io::Result<()> {
1181 self.settings += 1;
1182 assert_eq!(self.settings, 1, "deadline setter failure retried");
1183 Err(io::Error::new(self.kind, "deadline refused"))
1184 }
1185 }
1186
1187 impl Read for Refused {
1188 fn clock(&self) -> Clock {
1189 self.clock.clone()
1190 }
1191
1192 fn set_read_deadline(&mut self, _: Option<Instant>) -> io::Result<()> {
1193 self.reject()
1194 }
1195 }
1196
1197 impl io::Read for Refused {
1198 fn read(&mut self, _: &mut [u8]) -> io::Result<usize> {
1199 panic!("read after deadline setter failed")
1200 }
1201 }
1202
1203 impl Write for Refused {
1204 fn clock(&self) -> Clock {
1205 self.clock.clone()
1206 }
1207
1208 fn set_write_deadline(&mut self, _: Instant) -> io::Result<()> {
1209 self.reject()
1210 }
1211 }
1212
1213 impl io::Write for Refused {
1214 fn write(&mut self, _: &[u8]) -> io::Result<usize> {
1215 panic!("write after deadline setter failed")
1216 }
1217
1218 fn flush(&mut self) -> io::Result<()> {
1219 panic!("flush after deadline setter failed")
1220 }
1221 }
1222
1223 for kind in [io::ErrorKind::Interrupted, io::ErrorKind::TimedOut] {
1224 let tester = test_clock();
1226 let clock = tester.clock();
1227 let closer = Closer::new(&clock, || {});
1228 let mut reader = ReadHalf {
1229 inner: Refused {
1230 clock: clock.clone(),
1231 settings: 0,
1232 kind,
1233 },
1234 closer: closer.clone(),
1235 };
1236 let err = reader.read(&mut [0], None).unwrap_err();
1237 assert_eq!(err.kind(), kind);
1238 assert_eq!(err.to_string(), "deadline refused");
1239 let mut writer = WriteHalf {
1240 inner: Refused {
1241 clock: clock.clone(),
1242 settings: 0,
1243 kind,
1244 },
1245 closer: closer.clone(),
1246 };
1247 assert!(matches!(
1248 writer.write(&[1], clock.now() + Duration::from_secs(5)),
1249 Err(err) if err.kind() == kind && err.to_string() == "deadline refused"
1250 ));
1251
1252 closer.close();
1254 assert_eq!(reader.read(&mut [0], None).unwrap(), 0);
1255 assert!(matches!(
1256 writer.write(&[1], clock.now() + Duration::from_secs(5)),
1257 Err(err) if err.kind() == io::ErrorKind::NotConnected
1258 ));
1259 assert_eq!(reader.inner.settings, 1);
1260 assert_eq!(writer.inner.settings, 1);
1261 }
1262 }
1263
1264 #[test]
1270 fn test_late_write_preserves_progress() {
1271 struct LateWriter {
1274 clock: Clock,
1276 deadline: Option<Instant>,
1278 bytes: Vec<u8>,
1280 }
1281
1282 impl Write for LateWriter {
1283 fn clock(&self) -> Clock {
1284 self.clock.clone()
1285 }
1286
1287 fn set_write_deadline(&mut self, deadline: Instant) -> io::Result<()> {
1288 self.deadline = Some(deadline);
1289 Ok(())
1290 }
1291 }
1292
1293 impl io::Write for LateWriter {
1294 fn write(&mut self, bytes: &[u8]) -> io::Result<usize> {
1295 self.bytes.push(bytes[0]);
1296 self.clock
1297 .sleep_until(self.deadline.expect("write deadline installed"));
1298 Ok(1)
1299 }
1300
1301 fn flush(&mut self) -> io::Result<()> {
1302 panic!("flush admitted after deadline expired")
1303 }
1304 }
1305
1306 for bytes in [&b"a"[..], &b"ab"[..]] {
1307 let mut tester = test_clock();
1309 let clock = tester.clock();
1310 let mut writer = WriteHalf {
1311 inner: LateWriter {
1312 clock: clock.clone(),
1313 deadline: None,
1314 bytes: Vec::new(),
1315 },
1316 closer: Closer::new(&clock, || {}),
1317 };
1318 let deadline = clock.now() + Duration::from_millis(40);
1319 let result = thread::scope(|scope| {
1320 let writing = scope.spawn(|| writer.write(bytes, deadline));
1321 tester.wait_registered(1);
1322 tester.advance_to(deadline);
1323 writing.join().unwrap()
1324 });
1325
1326 assert_eq!(result.unwrap_err().kind(), io::ErrorKind::TimedOut);
1328 assert_eq!(writer.inner.bytes, b"a");
1329 writer.closer.close();
1330 }
1331 }
1332}