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, io: Option<(R, W)>, closer: Closer,
41 timeout: Duration, }
43
44impl<R: Read, W: Write> Stream<R, W> {
45 pub fn new(reader: R, writer: W, shutdown: impl FnOnce() + Send + 'static) -> Self {
51 let clock = reader.clock();
53 assert_eq!(
54 clock,
55 writer.clock(),
56 "stream halves must use the same clock"
57 );
58
59 Self {
61 closer: Closer::new(&clock, shutdown),
62 clock,
63 io: Some((reader, writer)),
64 timeout: DEFAULT_WRITE_TIMEOUT,
65 }
66 }
67
68 pub fn clock(&self) -> Clock {
70 self.clock.clone()
71 }
72
73 pub fn set_write_timeout(mut self, timeout: Duration) -> Self {
83 self.timeout = timeout;
84 self
85 }
86
87 pub fn closer(&self) -> Closer {
89 self.closer.clone()
90 }
91
92 pub fn close(&self) {
95 self.closer.close();
96 }
97
98 pub(crate) fn into_parts(mut self) -> (R, W, Closer, Duration) {
100 let (reader, writer) = self.io.take().expect("stream consumed once");
101 (reader, writer, self.closer.clone(), self.timeout)
102 }
103}
104
105impl<R: Read, W: Write> Drop for Stream<R, W> {
106 fn drop(&mut self) {
107 if self.io.is_some() {
108 self.close();
109 }
110 }
111}
112
113impl<R: Read, W: Write> fmt::Debug for Stream<R, W> {
114 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
116 f.debug_struct("Stream")
117 .field("timeout", &self.timeout)
118 .field("closer", &self.closer)
119 .finish_non_exhaustive()
120 }
121}
122
123#[derive(Clone)]
125pub struct Closer(Arc<Shutdown>);
126
127struct Shutdown {
131 state: Mutex<State>,
132 changed: Condvar,
133}
134
135#[derive(Clone, Copy, Debug, PartialEq, Eq)]
138enum Phase {
139 Open,
141 Closing,
143 Closed,
145}
146
147struct State {
151 phase: Phase,
152 active: usize, action: Option<Box<dyn FnOnce() + Send>>,
154}
155
156impl Closer {
157 pub(super) fn new(clock: &Clock, shutdown: impl FnOnce() + Send + 'static) -> Self {
159 Self(Arc::new(Shutdown {
160 state: Mutex::new(State {
161 phase: Phase::Open,
162 active: 0,
163 action: Some(Box::new(shutdown)),
164 }),
165 changed: Condvar::new(clock),
166 }))
167 }
168
169 pub fn close(&self) {
179 let action = {
181 let mut state = self.0.state.lock().expect("stream state not poisoned");
182 loop {
183 match state.phase {
184 Phase::Closed => return,
186
187 Phase::Closing => {
189 state = self
190 .0
191 .changed
192 .wait(state)
193 .expect("stream state not poisoned");
194 }
195
196 Phase::Open => {
198 debug!("closing wire stream");
199 state.phase = Phase::Closing;
200 break state.action.take().expect("shutdown called once");
201 }
202 }
203 }
204 };
205
206 action();
208
209 let mut state = self.0.state.lock().expect("stream state not poisoned");
211 while state.active != 0 {
212 state = self
213 .0
214 .changed
215 .wait(state)
216 .expect("stream state not poisoned");
217 }
218
219 state.phase = Phase::Closed;
221 self.0.changed.notify_all();
222 }
223
224 fn enter(&self) -> Option<Activity<'_>> {
226 let mut state = self.0.state.lock().expect("stream state not poisoned");
227 if state.phase != Phase::Open {
228 return None;
229 }
230 state.active += 1;
231 Some(Activity(self))
232 }
233}
234
235impl fmt::Debug for Closer {
236 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
239 let mut closer = f.debug_struct("Closer");
240 match self.0.state.try_lock() {
241 Ok(state) => closer
242 .field("phase", &state.phase)
243 .field("active", &state.active),
244 Err(_) => closer.field("state", &format_args!("<locked>")),
245 };
246 closer.finish()
247 }
248}
249
250struct Activity<'a>(&'a Closer);
253
254impl Drop for Activity<'_> {
255 fn drop(&mut self) {
256 let mut state = self.0.0.state.lock().expect("stream state not poisoned");
257 state.active -= 1;
258 if state.active == 0 {
259 self.0.0.changed.notify_all();
260 }
261 }
262}
263
264pub(super) struct ReadHalf<R> {
266 pub(super) inner: R,
267 pub(super) closer: Closer,
268}
269
270impl<R: Read> ReadHalf<R> {
271 pub(super) fn read(&mut self, buf: &mut [u8], deadline: Option<Instant>) -> io::Result<usize> {
276 loop {
277 if let Some(deadline) = deadline {
279 check_deadline(&self.inner.clock(), deadline)?;
280 }
281 let result = {
283 let Some(_active) = self.closer.enter() else {
284 return Ok(0);
285 };
286 self.inner.set_read_deadline(deadline)?;
287 self.inner.read(buf)
288 };
289 match result {
291 Err(err)
292 if matches!(
293 err.kind(),
294 io::ErrorKind::TimedOut | io::ErrorKind::Interrupted
295 ) =>
296 {
297 continue;
298 }
299 result => return result,
300 }
301 }
302 }
303}
304
305pub(super) struct WriteHalf<W> {
307 pub(super) inner: W,
308 pub(super) closer: Closer,
309}
310
311impl<W: Write> WriteHalf<W> {
312 pub(super) fn write(&mut self, mut bytes: &[u8], deadline: Instant) -> io::Result<()> {
322 check_deadline(&self.inner.clock(), deadline)?;
324
325 {
327 let _active = self
328 .closer
329 .enter()
330 .ok_or_else(|| io::Error::new(io::ErrorKind::NotConnected, "stream closed"))?;
331 self.inner.set_write_deadline(deadline)?;
332 }
333 while !bytes.is_empty() {
335 check_deadline(&self.inner.clock(), deadline)?;
337
338 let result = {
340 let _active = self
341 .closer
342 .enter()
343 .ok_or_else(|| io::Error::new(io::ErrorKind::NotConnected, "stream closed"))?;
344 self.inner.write(bytes)
345 };
346 match result {
347 Ok(0) => return Err(io::ErrorKind::WriteZero.into()),
348 Ok(n) => bytes = &bytes[n..],
349 Err(err) if err.kind() == io::ErrorKind::Interrupted => continue,
350 Err(err) => return Err(err),
351 }
352 }
353 check_deadline(&self.inner.clock(), deadline)?;
355
356 let _active = self
357 .closer
358 .enter()
359 .ok_or_else(|| io::Error::new(io::ErrorKind::NotConnected, "stream closed"))?;
360 self.inner.flush()
361 }
362}
363
364#[cfg(test)]
365#[cfg_attr(coverage_nightly, coverage(off))]
366mod tests {
367 use super::*;
368 use crate::testing;
369 use crate::transport::Client;
370 use crate::transport::testing::{Memory, test_clock};
371 use std::sync::atomic::{AtomicUsize, Ordering};
372 use std::sync::mpsc;
373 use std::thread;
374 use std::time::Duration;
375
376 #[test]
378 fn test_concurrent_closers_wait_on_stream_clock() {
379 let tester = darkbio_clock::TestClock::new();
381 let (stream, _peer) = crate::memory::duplex(1, &tester.clock());
382 let closer = stream.closer();
383 let activity = closer.enter().unwrap();
384 thread::scope(|scope| {
385 let first = scope.spawn(|| closer.close());
386 let second = scope.spawn(|| closer.close());
387
388 tester.wait_blocked(2);
390 assert!(closer.enter().is_none());
391
392 drop(activity);
394 first.join().unwrap();
395 second.join().unwrap();
396 assert!(closer.enter().is_none());
397 });
398 }
399
400 #[test]
403 fn test_debug_capabilities() {
404 use crate::transport::{Attestation, Event, Roots, Sender, Server};
405
406 fn printable<T: fmt::Debug>() {}
408 printable::<Stream<Box<dyn Read>, Box<dyn Write>>>();
409 printable::<Closer>();
410 printable::<Client<Box<dyn Read>, Box<dyn Write>>>();
411 printable::<Server<Box<dyn Read>, Box<dyn Write>, Attestation>>();
412 printable::<Sender<Box<dyn Write>>>();
413 printable::<Event<Box<dyn Write>>>();
414 printable::<Attestation>();
415 printable::<Roots<'static>>();
416 }
417
418 #[test]
421 fn test_memory_reader_keeps_transport_deadline() {
422 let tester = test_clock();
424 let clock = tester.clock();
425 let (host, ark) = crate::memory::duplex(4, &clock);
426 let (_ark_read, mut ark_write) = ark.into_halves();
427 std::io::Write::write_all(&mut ark_write, b"abc").unwrap();
428 let (reader, _writer, closer, _) = host.into_parts();
429 let mut reader = ReadHalf {
430 inner: reader,
431 closer,
432 };
433 let mut bytes = [0; 3];
435 assert_eq!(
436 reader
437 .read(&mut bytes, Some(clock.now()))
438 .unwrap_err()
439 .kind(),
440 io::ErrorKind::TimedOut
441 );
442 assert_eq!(bytes, [0; 3]);
443 assert_eq!(reader.read(&mut bytes, None).unwrap(), 3);
444 assert_eq!(&bytes, b"abc");
445 }
446
447 struct Adapter {
450 clock: Clock,
452 entered: mpsc::Sender<()>,
453 released: testing::Gate,
454 fails: bool,
455 deadline: Option<Instant>,
456 }
457
458 impl Adapter {
459 fn wait(&self, deadline: Option<Instant>) -> io::Result<()> {
461 self.entered.send(()).unwrap();
462 self.released.wait(deadline)?;
463 if self.fails {
464 Err(io::Error::other("adapter failure"))
465 } else {
466 Ok(())
467 }
468 }
469 }
470
471 impl Read for Adapter {
472 fn clock(&self) -> Clock {
473 self.clock.clone()
474 }
475
476 fn set_read_deadline(&mut self, deadline: Option<Instant>) -> io::Result<()> {
477 self.deadline = deadline;
478 Ok(())
479 }
480 }
481
482 impl io::Read for Adapter {
483 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
484 self.wait(self.deadline)?;
485 buf[0] = 0x5a;
486 Ok(1)
487 }
488 }
489
490 impl Write for Adapter {
491 fn clock(&self) -> Clock {
492 self.clock.clone()
493 }
494
495 fn set_write_deadline(&mut self, deadline: Instant) -> io::Result<()> {
496 self.deadline = Some(deadline);
497 Ok(())
498 }
499 }
500
501 impl io::Write for Adapter {
502 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
503 self.wait(Some(self.deadline.expect("write deadline installed")))?;
504 Ok(buf.len())
505 }
506
507 fn flush(&mut self) -> io::Result<()> {
508 self.wait(Some(self.deadline.expect("write deadline installed")))
509 }
510 }
511
512 fn during_shutdown(
514 fails: bool,
515 operation: impl FnOnce(Adapter, Closer) -> io::Result<()> + Send + 'static,
516 ) {
517 let tester = test_clock();
519 let clock = tester.clock();
520 let (entered, entries) = mpsc::channel();
521 let released = testing::Gate::new(&clock);
522 let release = released.clone();
523 let closer = Closer::new(&clock, move || release.open());
524 let io = thread::spawn({
525 let closer = closer.clone();
526 move || {
527 operation(
528 Adapter {
529 clock,
530 entered,
531 released,
532 fails,
533 deadline: None,
534 },
535 closer,
536 )
537 }
538 });
539 entries.recv().unwrap();
541 tester.wait_blocked(1);
542 closer.close();
543 let result = io.join().unwrap();
544 if fails {
545 let err = result.unwrap_err();
546 assert_eq!(err.kind(), io::ErrorKind::Other);
547 assert_eq!(err.to_string(), "adapter failure");
548 } else {
549 result.unwrap();
550 }
551 }
552
553 #[test]
557 fn test_admitted_io_preserves_results_during_shutdown() {
558 for fails in [false, true] {
559 during_shutdown(fails, |inner, closer| {
561 let mut buf = [0];
562 assert_eq!(ReadHalf { inner, closer }.read(&mut buf, None)?, 1);
563 assert_eq!(buf, [0x5a]);
564 Ok(())
565 });
566 during_shutdown(fails, move |inner, closer| {
567 let deadline = inner.clock.now() + Duration::from_secs(5);
568 let result = WriteHalf { inner, closer }.write(&[1, 2, 3], deadline);
569 if fails {
570 result
571 } else {
572 assert_eq!(result.unwrap_err().kind(), io::ErrorKind::NotConnected);
573 Ok(())
574 }
575 });
576 during_shutdown(fails, |inner, closer| {
577 let deadline = inner.clock.now() + Duration::from_secs(5);
578 WriteHalf { inner, closer }.write(&[], deadline)
579 });
580 }
581 }
582
583 #[test]
587 fn test_ownership_and_repeated_close() {
588 let tester = test_clock();
590 let clock = tester.clock();
591 let calls = Arc::new(AtomicUsize::new(0));
592 let stream = Stream::new(
593 Memory::new(io::empty(), &clock),
594 Memory::new(io::sink(), &clock),
595 {
596 let calls = calls.clone();
597 move || {
598 calls.fetch_add(1, Ordering::SeqCst);
599 }
600 },
601 );
602 let closer = stream.closer();
603 let client = Client::new(stream);
604 assert_eq!(
605 calls.load(Ordering::SeqCst),
606 0,
607 "handoff must keep the stream open"
608 );
609 drop(client);
611 assert_eq!(calls.load(Ordering::SeqCst), 1);
612 closer.close();
613 drop(closer.clone());
614 assert_eq!(calls.load(Ordering::SeqCst), 1);
615
616 let stream = Stream::new(
618 Memory::new(io::empty(), &clock),
619 Memory::new(io::sink(), &clock),
620 {
621 let calls = calls.clone();
622 move || {
623 calls.fetch_add(1, Ordering::SeqCst);
624 }
625 },
626 );
627 drop(stream);
628 assert_eq!(
629 calls.load(Ordering::SeqCst),
630 2,
631 "unclaimed streams also close on drop"
632 );
633 }
634
635 #[test]
639 fn test_every_closer_waits_for_the_shutdown_callback() {
640 let tester = test_clock();
642 let clock = tester.clock();
643 let (entered, callback) = mpsc::channel();
644 let release = testing::Gate::new(&clock);
645 let released = release.clone();
646 let stream = Stream::new(
647 Memory::new(io::empty(), &clock),
648 Memory::new(io::sink(), &clock),
649 move || {
650 entered.send(()).unwrap();
651 released.wait(None).unwrap();
652 },
653 );
654 let closer = stream.closer();
655 let (finished, finishes) = mpsc::channel();
656 let first = thread::spawn({
657 let closer = closer.clone();
658 let finished = finished.clone();
659 move || {
660 closer.close();
661 finished.send(()).unwrap();
662 }
663 });
664 callback.recv().unwrap();
665
666 let (started, starts) = mpsc::channel();
668 let second = thread::spawn({
669 let closer = closer.clone();
670 let started = started.clone();
671 let finished = finished.clone();
672 move || {
673 started.send(()).unwrap();
674 closer.close();
675 finished.send(()).unwrap();
676 }
677 });
678 let owner = thread::spawn(move || {
679 started.send(()).unwrap();
680 drop(stream);
681 finished.send(()).unwrap();
682 });
683 starts.recv().unwrap();
684 starts.recv().unwrap();
685 tester.wait_blocked(3);
686 assert!(finishes.try_recv().is_err());
687
688 release.open();
690 finishes.recv().unwrap();
691 finishes.recv().unwrap();
692 finishes.recv().unwrap();
693 first.join().unwrap();
694 second.join().unwrap();
695 owner.join().unwrap();
696 }
697
698 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
700 enum BlockAt {
701 Read,
703 Write,
705 Flush,
707 }
708
709 struct Gate {
712 clock: Clock,
714 at: BlockAt,
715 entered: mpsc::Sender<()>,
716 released: testing::Gate,
717 calls: AtomicUsize,
718 }
719
720 impl Gate {
721 fn call(&self, at: BlockAt, deadline: Option<Instant>) -> io::Result<()> {
723 self.calls.fetch_add(1, Ordering::SeqCst);
724 if at == self.at {
725 self.entered.send(()).unwrap();
726 self.released.wait(deadline)?;
727 }
728 Ok(())
729 }
730
731 fn release(&self) {
733 self.released.open();
734 }
735 }
736
737 struct GatedAdapter {
739 gate: Arc<Gate>,
740 deadline: Option<Instant>,
741 }
742
743 impl Read for GatedAdapter {
744 fn clock(&self) -> Clock {
745 self.gate.clock.clone()
746 }
747
748 fn set_read_deadline(&mut self, deadline: Option<Instant>) -> io::Result<()> {
749 self.deadline = deadline;
750 Ok(())
751 }
752 }
753
754 impl io::Read for GatedAdapter {
755 fn read(&mut self, _: &mut [u8]) -> io::Result<usize> {
756 self.gate.call(BlockAt::Read, self.deadline)?;
757 Ok(0)
758 }
759 }
760
761 impl Write for GatedAdapter {
762 fn clock(&self) -> Clock {
763 self.gate.clock.clone()
764 }
765
766 fn set_write_deadline(&mut self, deadline: Instant) -> io::Result<()> {
767 self.deadline = Some(deadline);
768 Ok(())
769 }
770 }
771
772 impl io::Write for GatedAdapter {
773 fn write(&mut self, bytes: &[u8]) -> io::Result<usize> {
774 self.gate.call(
775 BlockAt::Write,
776 Some(self.deadline.expect("write deadline installed")),
777 )?;
778 Ok(bytes.len())
779 }
780
781 fn flush(&mut self) -> io::Result<()> {
782 self.gate.call(
783 BlockAt::Flush,
784 Some(self.deadline.expect("write deadline installed")),
785 )
786 }
787 }
788
789 #[test]
793 fn test_every_closer_waits_for_active_io_and_refuses_new_io() {
794 for at in [BlockAt::Read, BlockAt::Write, BlockAt::Flush] {
795 let tester = test_clock();
797 let clock = tester.clock();
798 let (entered, entries) = mpsc::channel();
799 let gate = Arc::new(Gate {
800 clock: clock.clone(),
801 at,
802 entered,
803 released: testing::Gate::new(&clock),
804 calls: AtomicUsize::new(0),
805 });
806 let (requested, requests) = mpsc::channel();
807 let stream = Stream::new(
808 GatedAdapter {
809 gate: gate.clone(),
810 deadline: None,
811 },
812 GatedAdapter {
813 gate: gate.clone(),
814 deadline: None,
815 },
816 move || {
817 requested.send(()).unwrap();
818 },
819 );
820 let (reader, writer, closer, _) = stream.into_parts();
821 let io_closer = closer.clone();
822 let deadline = clock.now() + Duration::from_secs(5);
823 let io = thread::spawn(move || {
824 let mut reader = ReadHalf {
825 inner: reader,
826 closer: io_closer.clone(),
827 };
828 let mut writer = WriteHalf {
829 inner: writer,
830 closer: io_closer,
831 };
832 match at {
833 BlockAt::Read => assert_eq!(reader.read(&mut [0], None).unwrap(), 0),
834 BlockAt::Write => assert_eq!(
835 writer.write(&[1], deadline).unwrap_err().kind(),
836 io::ErrorKind::NotConnected
837 ),
838 BlockAt::Flush => writer.write(&[], deadline).unwrap(),
839 }
840 (reader, writer)
841 });
842 entries.recv().unwrap();
843
844 let (finished, finishes) = mpsc::channel();
846 let closing = thread::spawn({
847 let closer = closer.clone();
848 move || {
849 closer.close();
850 finished.send(()).unwrap();
851 }
852 });
853 requests.recv().unwrap();
854 tester.wait_blocked(2);
855 assert!(finishes.try_recv().is_err());
856
857 gate.release();
859 finishes.recv().unwrap();
860 closing.join().unwrap();
861 let (mut reader, mut writer) = io.join().unwrap();
862 let calls = gate.calls.load(Ordering::SeqCst);
863 assert_eq!(reader.read(&mut [0], None).unwrap(), 0);
864 assert!(matches!(
865 writer.write(&[1], deadline),
866 Err(err) if err.kind() == io::ErrorKind::NotConnected
867 ));
868 assert_eq!(gate.calls.load(Ordering::SeqCst), calls);
869 closer.close();
870 assert!(requests.try_recv().is_err(), "shutdown called twice");
871 }
872 }
873
874 struct BudgetWriter {
877 clock: Clock,
879 bytes: Vec<u8>,
880 deadlines: Vec<Instant>,
881 stall_flush: bool,
882 deadline: Option<Instant>,
883 settings: usize,
884 }
885
886 impl Write for BudgetWriter {
887 fn clock(&self) -> Clock {
888 self.clock.clone()
889 }
890
891 fn set_write_deadline(&mut self, deadline: Instant) -> io::Result<()> {
892 self.deadline = Some(deadline);
893 self.settings += 1;
894 Ok(())
895 }
896 }
897
898 impl io::Write for BudgetWriter {
899 fn write(&mut self, bytes: &[u8]) -> io::Result<usize> {
900 let deadline = self.deadline.expect("write deadline installed");
901 check_deadline(&self.clock(), deadline)?;
902 self.deadlines.push(deadline);
903 self.bytes.push(bytes[0]);
904 Ok(1)
905 }
906
907 fn flush(&mut self) -> io::Result<()> {
908 let deadline = self.deadline.expect("write deadline installed");
909 self.deadlines.push(deadline);
910 if self.stall_flush {
911 self.clock.sleep_until(deadline);
912 return Err(io::ErrorKind::TimedOut.into());
913 }
914 check_deadline(&self.clock(), deadline)
915 }
916 }
917
918 #[test]
921 fn test_output_deadline_and_reuse() {
922 let mut tester = test_clock();
924 let clock = tester.clock();
925 let timeout = Duration::from_millis(40);
926 let stream = Stream::new(
927 Memory::new(io::empty(), &clock),
928 BudgetWriter {
929 clock: clock.clone(),
930 bytes: Vec::new(),
931 deadlines: Vec::new(),
932 stall_flush: true,
933 deadline: None,
934 settings: 0,
935 },
936 || {},
937 )
938 .set_write_timeout(timeout);
939 let (_, inner, closer, configured) = stream.into_parts();
940 assert_eq!(configured, timeout);
941 let mut writer = WriteHalf { inner, closer };
942 let deadline = clock.now() + configured;
943 let result = thread::scope(|scope| {
944 let writing = scope.spawn(|| writer.write(b"abc", deadline));
945 tester.wait_blocked(1);
946 assert_eq!(tester.next_deadline(), Some(deadline));
947 tester.advance_to(deadline);
948 writing.join().unwrap()
949 });
950 assert_eq!(result.unwrap_err().kind(), io::ErrorKind::TimedOut);
951 assert_eq!(writer.inner.deadlines, vec![deadline; 4]);
952 assert_eq!(writer.inner.settings, 1);
953
954 writer.inner.stall_flush = false;
956 let deadline = clock.now() + Duration::from_secs(5);
957 writer.write(b"d", deadline).unwrap();
958 assert_eq!(writer.inner.bytes, b"abcd");
959 assert_eq!(writer.inner.settings, 2);
960
961 let calls = writer.inner.deadlines.len();
963 let deadline = clock.now();
964 assert!(matches!(
965 writer.write(b"e", deadline),
966 Err(err) if err.kind() == io::ErrorKind::TimedOut
967 ));
968 assert_eq!(writer.inner.deadlines.len(), calls);
969 assert_eq!(writer.inner.settings, 2);
970 writer.closer.close();
971 }
972
973 #[test]
977 fn test_partial_write_retries_and_failures() {
978 struct Script {
980 clock: Clock,
982 results: std::collections::VecDeque<io::Result<usize>>,
983 offered: Vec<Vec<u8>>,
984 accepted: Vec<u8>,
985 interrupted_flush: bool,
986 flushes: usize,
987 settings: usize,
988 deadline: Option<Instant>,
989 }
990
991 impl Write for Script {
992 fn clock(&self) -> Clock {
993 self.clock.clone()
994 }
995
996 fn set_write_deadline(&mut self, deadline: Instant) -> io::Result<()> {
997 self.settings += 1;
998 self.deadline = Some(deadline);
999 Ok(())
1000 }
1001 }
1002
1003 impl io::Write for Script {
1004 fn write(&mut self, bytes: &[u8]) -> io::Result<usize> {
1005 check_deadline(
1006 &self.clock(),
1007 self.deadline.expect("write deadline installed"),
1008 )?;
1009 self.offered.push(bytes.to_vec());
1010 let result = self.results.pop_front().expect("unexpected write");
1011 if let Ok(size) = &result {
1012 self.accepted.extend_from_slice(&bytes[..*size]);
1013 }
1014 result
1015 }
1016
1017 fn flush(&mut self) -> io::Result<()> {
1018 check_deadline(
1019 &self.clock(),
1020 self.deadline.expect("write deadline installed"),
1021 )?;
1022 self.flushes += 1;
1023 assert_eq!(self.flushes, 1, "flush retried");
1024 if self.interrupted_flush {
1025 Err(io::ErrorKind::Interrupted.into())
1026 } else {
1027 Ok(())
1028 }
1029 }
1030 }
1031
1032 for (stalls, interrupted_flush) in [(false, false), (true, false), (false, true)] {
1033 let tester = test_clock();
1035 let clock = tester.clock();
1036 let mut writer = WriteHalf {
1037 inner: Script {
1038 clock: clock.clone(),
1039 results: [
1040 Err(io::ErrorKind::Interrupted.into()),
1041 Ok(1),
1042 Ok(usize::from(!stalls)),
1043 ]
1044 .into(),
1045 offered: Vec::new(),
1046 accepted: Vec::new(),
1047 interrupted_flush,
1048 flushes: 0,
1049 settings: 0,
1050 deadline: None,
1051 },
1052 closer: Closer::new(&clock, || {}),
1053 };
1054 let result = writer.write(b"ab", clock.now() + Duration::from_secs(5));
1055 if stalls {
1056 assert_eq!(result.unwrap_err().kind(), io::ErrorKind::WriteZero);
1057 } else if interrupted_flush {
1058 assert_eq!(result.unwrap_err().kind(), io::ErrorKind::Interrupted);
1059 } else {
1060 result.unwrap();
1061 }
1062 assert_eq!(
1064 writer.inner.offered,
1065 [b"ab".to_vec(), b"ab".to_vec(), b"b".to_vec()]
1066 );
1067 assert_eq!(
1068 writer.inner.accepted,
1069 if stalls { &b"a"[..] } else { &b"ab"[..] }
1070 );
1071 assert_eq!(writer.inner.flushes, usize::from(!stalls));
1072 assert_eq!(writer.inner.settings, 1);
1073 writer.closer.close();
1074 }
1075 }
1076
1077 #[test]
1081 fn test_deadline_setter_failure_prevents_io() {
1082 struct Refused {
1084 clock: Clock,
1086 settings: usize,
1087 kind: io::ErrorKind,
1088 }
1089
1090 impl Refused {
1091 fn reject(&mut self) -> io::Result<()> {
1093 self.settings += 1;
1094 assert_eq!(self.settings, 1, "deadline setter failure retried");
1095 Err(io::Error::new(self.kind, "deadline refused"))
1096 }
1097 }
1098
1099 impl Read for Refused {
1100 fn clock(&self) -> Clock {
1101 self.clock.clone()
1102 }
1103
1104 fn set_read_deadline(&mut self, _: Option<Instant>) -> io::Result<()> {
1105 self.reject()
1106 }
1107 }
1108
1109 impl io::Read for Refused {
1110 fn read(&mut self, _: &mut [u8]) -> io::Result<usize> {
1111 panic!("read after deadline setter failed")
1112 }
1113 }
1114
1115 impl Write for Refused {
1116 fn clock(&self) -> Clock {
1117 self.clock.clone()
1118 }
1119
1120 fn set_write_deadline(&mut self, _: Instant) -> io::Result<()> {
1121 self.reject()
1122 }
1123 }
1124
1125 impl io::Write for Refused {
1126 fn write(&mut self, _: &[u8]) -> io::Result<usize> {
1127 panic!("write after deadline setter failed")
1128 }
1129
1130 fn flush(&mut self) -> io::Result<()> {
1131 panic!("flush after deadline setter failed")
1132 }
1133 }
1134
1135 for kind in [io::ErrorKind::Interrupted, io::ErrorKind::TimedOut] {
1136 let tester = test_clock();
1138 let clock = tester.clock();
1139 let closer = Closer::new(&clock, || {});
1140 let mut reader = ReadHalf {
1141 inner: Refused {
1142 clock: clock.clone(),
1143 settings: 0,
1144 kind,
1145 },
1146 closer: closer.clone(),
1147 };
1148 let err = reader.read(&mut [0], None).unwrap_err();
1149 assert_eq!(err.kind(), kind);
1150 assert_eq!(err.to_string(), "deadline refused");
1151 let mut writer = WriteHalf {
1152 inner: Refused {
1153 clock: clock.clone(),
1154 settings: 0,
1155 kind,
1156 },
1157 closer: closer.clone(),
1158 };
1159 assert!(matches!(
1160 writer.write(&[1], clock.now() + Duration::from_secs(5)),
1161 Err(err) if err.kind() == kind && err.to_string() == "deadline refused"
1162 ));
1163
1164 closer.close();
1166 assert_eq!(reader.read(&mut [0], None).unwrap(), 0);
1167 assert!(matches!(
1168 writer.write(&[1], clock.now() + Duration::from_secs(5)),
1169 Err(err) if err.kind() == io::ErrorKind::NotConnected
1170 ));
1171 assert_eq!(reader.inner.settings, 1);
1172 assert_eq!(writer.inner.settings, 1);
1173 }
1174 }
1175
1176 #[test]
1180 fn test_late_write_preserves_progress() {
1181 struct LateWriter {
1183 clock: Clock,
1185 deadline: Option<Instant>,
1186 bytes: Vec<u8>,
1187 }
1188
1189 impl Write for LateWriter {
1190 fn clock(&self) -> Clock {
1191 self.clock.clone()
1192 }
1193
1194 fn set_write_deadline(&mut self, deadline: Instant) -> io::Result<()> {
1195 self.deadline = Some(deadline);
1196 Ok(())
1197 }
1198 }
1199
1200 impl io::Write for LateWriter {
1201 fn write(&mut self, bytes: &[u8]) -> io::Result<usize> {
1202 self.bytes.push(bytes[0]);
1203 self.clock
1204 .sleep_until(self.deadline.expect("write deadline installed"));
1205 Ok(1)
1206 }
1207
1208 fn flush(&mut self) -> io::Result<()> {
1209 panic!("flush admitted after deadline expired")
1210 }
1211 }
1212
1213 for bytes in [&b"a"[..], &b"ab"[..]] {
1214 let mut tester = test_clock();
1216 let clock = tester.clock();
1217 let mut writer = WriteHalf {
1218 inner: LateWriter {
1219 clock: clock.clone(),
1220 deadline: None,
1221 bytes: Vec::new(),
1222 },
1223 closer: Closer::new(&clock, || {}),
1224 };
1225 let deadline = clock.now() + Duration::from_millis(40);
1226 let result = thread::scope(|scope| {
1227 let writing = scope.spawn(|| writer.write(bytes, deadline));
1228 tester.wait_blocked(1);
1229 tester.advance_to(deadline);
1230 writing.join().unwrap()
1231 });
1232
1233 assert_eq!(result.unwrap_err().kind(), io::ErrorKind::TimedOut);
1235 assert_eq!(writer.inner.bytes, b"a");
1236 writer.closer.close();
1237 }
1238 }
1239}