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>;
22
23impl Duplex {
24 pub fn into_halves(self) -> (Reader, Writer) {
44 let (reader, writer, _, _) = self.into_parts();
45 (reader, writer)
46 }
47}
48
49pub fn duplex(capacity: usize, clock: &Clock) -> (Duplex, Duplex) {
75 assert!(capacity > 0, "duplex capacity must be nonzero");
77
78 let incoming = Arc::new(Pipe::new(capacity, clock));
80 let outgoing = Arc::new(Pipe::new(capacity, clock));
81 (
82 endpoint(incoming.clone(), outgoing.clone()),
83 endpoint(outgoing, incoming),
84 )
85}
86
87fn endpoint(incoming: Arc<Pipe>, outgoing: Arc<Pipe>) -> Duplex {
89 Stream::new(
90 Reader {
91 pipe: incoming.clone(),
92 deadline: None,
93 },
94 Writer {
95 pipe: outgoing.clone(),
96 deadline: None,
97 },
98 move || {
99 incoming.close_reader();
100 outgoing.close_writer();
101 },
102 )
103}
104
105#[derive(Debug)]
107pub struct Reader {
108 pipe: Arc<Pipe>,
109 deadline: Option<Instant>,
110}
111
112impl io::Read for Reader {
113 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
114 let mut state = self.pipe.lock();
116 loop {
117 if buf.is_empty() || !state.reader_open {
119 return Ok(0);
120 }
121
122 if !state.bytes.is_empty() {
124 let count = buf.len().min(state.bytes.len());
125 for (out, byte) in buf.iter_mut().zip(state.bytes.drain(..count)) {
126 *out = byte;
127 }
128 drop(state);
129 self.pipe.changed.notify_all();
130 return Ok(count);
131 }
132
133 if !state.writer_open {
135 return Ok(0);
136 }
137 self.pipe.check_deadline(self.deadline)?;
138 state = self.pipe.wait(state, self.deadline);
139 }
140 }
141}
142
143impl Read for Reader {
144 fn clock(&self) -> Clock {
145 self.pipe.clock.clone()
146 }
147
148 fn set_read_deadline(&mut self, deadline: Option<Instant>) -> io::Result<()> {
149 self.deadline = deadline;
150 Ok(())
151 }
152}
153
154impl Drop for Reader {
155 fn drop(&mut self) {
156 self.pipe.close_reader();
157 }
158}
159
160#[cfg(test)]
161impl Reader {
162 pub(crate) fn forbid_waits(&self) {
165 self.pipe.lock().waits_forbidden = true;
166 }
167}
168
169#[derive(Debug)]
171pub struct Writer {
172 pipe: Arc<Pipe>,
173 deadline: Option<Instant>,
174}
175
176impl io::Write for Writer {
177 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
178 let mut state = self.pipe.lock();
180 loop {
181 self.pipe.check_deadline(self.deadline)?;
183 if buf.is_empty() {
184 return Ok(0);
185 }
186 if !state.reader_open || !state.writer_open {
187 return Err(io::ErrorKind::BrokenPipe.into());
188 }
189
190 let count = buf.len().min(self.pipe.capacity - state.bytes.len());
192 if count > 0 {
193 state.bytes.extend(&buf[..count]);
194 drop(state);
195 self.pipe.changed.notify_all();
196 return Ok(count);
197 }
198
199 state = self.pipe.wait(state, self.deadline);
201 }
202 }
203
204 fn flush(&mut self) -> io::Result<()> {
205 let state = self.pipe.lock();
207 self.pipe.check_deadline(self.deadline)?;
208
209 if !state.writer_open || state.lost {
211 return Err(io::ErrorKind::BrokenPipe.into());
212 }
213 Ok(())
214 }
215}
216
217impl Write for Writer {
218 fn clock(&self) -> Clock {
219 self.pipe.clock.clone()
220 }
221
222 fn set_write_deadline(&mut self, deadline: Instant) -> io::Result<()> {
223 self.deadline = Some(deadline);
224 Ok(())
225 }
226}
227
228impl Drop for Writer {
229 fn drop(&mut self) {
230 self.pipe.close_writer();
231 }
232}
233
234#[derive(Debug)]
236struct Pipe {
237 clock: Clock,
239 capacity: usize,
240 state: Mutex<State>,
241 changed: Condvar,
242}
243
244#[derive(Debug)]
245struct State {
246 bytes: VecDeque<u8>,
247 reader_open: bool,
248 writer_open: bool,
249 lost: bool, #[cfg(test)]
251 waiting: usize,
252 #[cfg(test)]
253 waits_forbidden: bool, }
255
256impl Pipe {
257 fn new(capacity: usize, clock: &Clock) -> Self {
258 Self {
259 clock: clock.clone(),
260 capacity,
261 state: Mutex::new(State {
262 bytes: VecDeque::with_capacity(capacity),
263 reader_open: true,
264 writer_open: true,
265 lost: false,
266 #[cfg(test)]
267 waiting: 0,
268 #[cfg(test)]
269 waits_forbidden: false,
270 }),
271 changed: Condvar::new(clock),
272 }
273 }
274
275 fn lock(&self) -> MutexGuard<'_, State> {
276 self.state.lock().unwrap_or_else(|err| err.into_inner())
278 }
279
280 fn wait<'a>(
282 &self,
283 state: MutexGuard<'a, State>,
284 deadline: Option<Instant>,
285 ) -> MutexGuard<'a, State> {
286 #[cfg(test)]
288 let state = {
289 let mut state = state;
290 assert!(!state.waits_forbidden, "memory pipe waited");
291 state.waiting += 1;
292 self.changed.notify_all();
293 state
294 };
295
296 let state = match deadline {
298 Some(deadline) => {
299 self.changed
300 .wait_deadline(state, deadline)
301 .unwrap_or_else(|err| err.into_inner())
302 .0
303 }
304 None => self
305 .changed
306 .wait(state)
307 .unwrap_or_else(|err| err.into_inner()),
308 };
309
310 #[cfg(test)]
312 let state = {
313 let mut state = state;
314 state.waiting -= 1;
315 state
316 };
317 state
318 }
319
320 fn check_deadline(&self, deadline: Option<Instant>) -> io::Result<()> {
322 if deadline.is_some_and(|deadline| self.clock.now() >= deadline) {
323 return Err(io::ErrorKind::TimedOut.into());
324 }
325 Ok(())
326 }
327
328 fn close_reader(&self) {
329 let mut state = self.lock();
330 state.reader_open = false;
331 state.lost |= !state.bytes.is_empty();
332 state.bytes.clear();
333 drop(state);
334 self.changed.notify_all();
335 }
336
337 fn close_writer(&self) {
338 self.lock().writer_open = false;
339 self.changed.notify_all();
340 }
341}
342
343#[cfg(test)]
344#[cfg_attr(coverage_nightly, coverage(off))]
345mod tests {
346 use super::*;
347 use crate::transport::Closer;
348 use crate::transport::testing::test_clock;
349 use darkbio_clock::TestClock;
350 use std::io::{Read as _, Write as _};
351 use std::sync::mpsc;
352 use std::thread;
353 use std::time::Duration;
354
355 const TIMEOUT: Duration = Duration::from_millis(50);
357
358 fn halves(stream: Duplex) -> (Reader, Writer, Closer) {
360 let closer = stream.closer();
361 let (reader, writer) = stream.into_halves();
362 (reader, writer, closer)
363 }
364
365 fn blocked(pipe: &Pipe) {
367 let mut state = pipe.lock();
368 while state.waiting == 0 {
369 state = pipe.changed.wait(state).unwrap();
370 }
371 }
372
373 #[test]
375 fn test_blocked_read_expires_on_clock_deadline() {
376 let mut tester = TestClock::new();
378 tester.advance(Duration::from_secs(86400));
379 let clock = tester.clock();
380 let (host, _peer) = duplex(1, &clock);
381 let (mut reader, _writer) = host.into_halves();
382 let deadline = clock.now() + Duration::from_secs(5);
383 reader.set_read_deadline(Some(deadline)).unwrap();
384 let reading = thread::spawn(move || reader.read(&mut [0]));
385 tester.wait_blocked(1);
386 assert_eq!(tester.next_deadline(), Some(deadline));
387
388 tester.advance_to(deadline);
390 assert_eq!(
391 reading.join().unwrap().unwrap_err().kind(),
392 io::ErrorKind::TimedOut
393 );
394 }
395
396 #[test]
398 fn test_blocked_write_expires_on_clock_deadline() {
399 let mut tester = TestClock::new();
401 tester.advance(Duration::from_secs(86400));
402 let clock = tester.clock();
403 let (host, _peer) = duplex(1, &clock);
404 let (_reader, mut writer) = host.into_halves();
405 writer.write_all(b"a").unwrap();
406 let deadline = clock.now() + Duration::from_secs(5);
407 writer.set_write_deadline(deadline).unwrap();
408 let writing = thread::spawn(move || writer.write(b"b"));
409 tester.wait_blocked(1);
410 assert_eq!(tester.next_deadline(), Some(deadline));
411
412 tester.advance_to(deadline);
414 assert_eq!(
415 writing.join().unwrap().unwrap_err().kind(),
416 io::ErrorKind::TimedOut
417 );
418 }
419
420 #[test]
422 fn test_read_delivers_buffered_bytes_after_deadline() {
423 let mut tester = test_clock();
425 let clock = tester.clock();
426 let (host, peer) = duplex(1, &clock);
427 let (mut reader, _writer) = host.into_halves();
428 let (_peer_reader, mut writer) = peer.into_halves();
429 let deadline = clock.now() + Duration::from_secs(5);
430 reader.set_read_deadline(Some(deadline)).unwrap();
431 writer.write_all(b"a").unwrap();
432
433 tester.advance_to(deadline);
435 reader.forbid_waits();
436 let mut byte = [0];
437 assert_eq!(reader.read(&mut byte).unwrap(), 1);
438 assert_eq!(&byte, b"a");
439
440 assert_eq!(
442 reader.read(&mut byte).unwrap_err().kind(),
443 io::ErrorKind::TimedOut
444 );
445 }
446
447 #[test]
449 #[should_panic(expected = "duplex capacity must be nonzero")]
450 fn test_zero_capacity() {
451 duplex(0, &test_clock().clock());
452 }
453
454 #[test]
457 fn test_byte_stream_and_independent_deadlines() {
458 let tester = test_clock();
460 let clock = tester.clock();
461 let (host, ark) = duplex(4, &clock);
462 let (mut host_read, mut host_write, _host_close) = halves(host);
463 let (mut ark_read, mut ark_write, _ark_close) = halves(ark);
464
465 assert_eq!(host_read.read(&mut []).unwrap(), 0);
467 assert_eq!(host_write.write(b"abcdef").unwrap(), 4);
468 assert_eq!(host_write.write(&[]).unwrap(), 0);
469 host_write.flush().unwrap();
471 let mut first = [0; 2];
472 ark_read.read_exact(&mut first).unwrap();
473 assert_eq!(&first, b"ab");
474 host_write.write_all(b"ef").unwrap();
475 let mut rest = [0; 4];
476 ark_read.read_exact(&mut rest).unwrap();
477 assert_eq!(&rest, b"cdef");
478
479 ark_write.write_all(b"xy").unwrap();
481 host_read.set_read_deadline(Some(clock.now())).unwrap();
482 host_read.read_exact(&mut first).unwrap();
483 assert_eq!(&first, b"xy");
484 assert_eq!(
485 host_read.read(&mut first).unwrap_err().kind(),
486 io::ErrorKind::TimedOut
487 );
488 assert_eq!(host_read.read(&mut []).unwrap(), 0);
489 host_write.write_all(b"q").unwrap();
490
491 host_write.set_write_deadline(clock.now()).unwrap();
493 host_read.set_read_deadline(None).unwrap();
494 ark_write.write_all(b"uv").unwrap();
495 host_read.read_exact(&mut first).unwrap();
496 assert_eq!(&first, b"uv");
497 for bytes in [b"t".as_slice(), b""] {
498 assert_eq!(
499 host_write.write(bytes).unwrap_err().kind(),
500 io::ErrorKind::TimedOut
501 );
502 }
503 assert_eq!(
504 host_write.flush().unwrap_err().kind(),
505 io::ErrorKind::TimedOut
506 );
507
508 host_write
510 .set_write_deadline(clock.now() + Duration::from_secs(5))
511 .unwrap();
512 host_write.write_all(b"rs").unwrap();
513 host_write.flush().unwrap();
514 let mut accepted = [0; 3];
515 ark_read.read_exact(&mut accepted).unwrap();
516 assert_eq!(&accepted, b"qrs");
517 }
518
519 #[test]
522 fn test_read_timeout_and_reuse() {
523 let mut tester = test_clock();
525 let clock = tester.clock();
526 let deadline = clock.now() + TIMEOUT;
527 let (host, ark) = duplex(1, &clock);
528 let (mut reader, _host_write, _host_close) = halves(host);
529 let (_ark_read, mut writer, _ark_close) = halves(ark);
530 let pipe = reader.pipe.clone();
531 let (done, result) = mpsc::channel();
532 let timed = thread::spawn(move || {
533 reader.set_read_deadline(Some(deadline)).unwrap();
534 let mut buf = [99];
535 let error = reader.read(&mut buf).unwrap_err();
536 assert!(clock.now() >= deadline);
537 assert_eq!(buf, [99]);
538 done.send((reader, error.kind())).unwrap();
539 });
540 tester.wait_blocked(1);
541 tester.advance_to(deadline);
542 let (mut reader, kind) = result.recv().unwrap();
543 timed.join().unwrap();
544 assert_eq!(kind, io::ErrorKind::TimedOut);
545
546 reader.set_read_deadline(None).unwrap();
548 let (done, result) = mpsc::channel();
549 let reading = thread::spawn(move || {
550 let mut buf = [0];
551 reader.read_exact(&mut buf).unwrap();
552 done.send(buf).unwrap();
553 });
554 blocked(&pipe);
555 writer.write_all(b"x").unwrap();
556 assert_eq!(&result.recv().unwrap(), b"x");
557 reading.join().unwrap();
558 }
559
560 #[test]
563 fn test_write_timeout_and_reuse() {
564 let mut tester = test_clock();
566 let clock = tester.clock();
567 let deadline = clock.now() + TIMEOUT;
568 let (host, ark) = duplex(3, &clock);
569 let (_host_read, mut writer, _host_close) = halves(host);
570 let (mut reader, _ark_write, _ark_close) = halves(ark);
571 let (done, result) = mpsc::channel();
572 let writing = thread::spawn(move || {
573 writer.set_write_deadline(deadline).unwrap();
574 let error = writer.write_all(b"abcd").unwrap_err();
575 assert!(clock.now() >= deadline);
576 done.send((writer, error.kind())).unwrap();
577 });
578 tester.wait_blocked(1);
579 tester.advance_to(deadline);
580 let (mut writer, kind) = result.recv().unwrap();
581 writing.join().unwrap();
582 assert_eq!(kind, io::ErrorKind::TimedOut);
583 let mut prefix = [0; 3];
584 reader.read_exact(&mut prefix).unwrap();
585 assert_eq!(&prefix, b"abc");
586
587 writer
589 .set_write_deadline(tester.clock().now() + Duration::from_secs(5))
590 .unwrap();
591 writer.write_all(b"ef").unwrap();
592 drop(writer);
593 let mut suffix = Vec::new();
594 reader.read_to_end(&mut suffix).unwrap();
595 assert_eq!(&suffix, b"ef");
596 }
597
598 #[test]
601 fn test_backpressure_wakes_writer() {
602 let tester = test_clock();
604 let deadline = tester.clock().now() + Duration::from_secs(5);
605 let (host, ark) = duplex(3, &tester.clock());
606 let (_host_read, mut writer, _host_close) = halves(host);
607 let (mut reader, _ark_write, _ark_close) = halves(ark);
608 writer.write_all(b"abc").unwrap();
609 let pipe = writer.pipe.clone();
610 let (done, result) = mpsc::channel();
611 let writing = thread::spawn(move || {
612 writer.set_write_deadline(deadline).unwrap();
613 done.send(writer.write_all(b"defgh")).unwrap();
614 });
615 blocked(&pipe);
617 reader.set_read_deadline(Some(deadline)).unwrap();
618 let mut bytes = [0; 8];
619 reader.read_exact(&mut bytes).unwrap();
620 assert_eq!(&bytes, b"abcdefgh");
621 result.recv().unwrap().unwrap();
622 writing.join().unwrap();
623 }
624
625 #[test]
628 fn test_shutdown_wakes_both_directions() {
629 for local in [false, true] {
630 let tester = test_clock();
632 let (host, ark) = duplex(1, &tester.clock());
633 let (mut reader, mut writer, closer) = halves(host);
634 writer.write_all(b"a").unwrap();
635 let incoming = reader.pipe.clone();
636 let outgoing = writer.pipe.clone();
637 let (read_done, read_result) = mpsc::channel();
638 let reading = thread::spawn(move || {
639 read_done.send(reader.read(&mut [0])).unwrap();
640 });
641 let (write_done, write_result) = mpsc::channel();
642 let writing = thread::spawn(move || {
643 write_done.send(writer.write(b"b")).unwrap();
644 });
645 blocked(&incoming);
647 blocked(&outgoing);
648 if local {
649 closer.close();
650 } else {
651 drop(ark);
652 }
653 assert_eq!(read_result.recv().unwrap().unwrap(), 0);
654 assert_eq!(
655 write_result.recv().unwrap().unwrap_err().kind(),
656 io::ErrorKind::BrokenPipe
657 );
658 reading.join().unwrap();
659 writing.join().unwrap();
660 }
661 }
662
663 #[test]
666 fn test_shutdown_drains_output_and_discards_input() {
667 let tester = test_clock();
669 let clock = tester.clock();
670 let (host, ark) = duplex(3, &clock);
671 let (mut host_read, mut host_write, closer) = halves(host);
672 let (mut ark_read, mut ark_write, _ark_close) = halves(ark);
673 host_write.write_all(b"abc").unwrap();
674 ark_write.write_all(b"xy").unwrap();
675 host_read.set_read_deadline(Some(clock.now())).unwrap();
676 ark_read.set_read_deadline(Some(clock.now())).unwrap();
677
678 closer.close();
680 closer.close();
681 assert_eq!(host_read.read(&mut [0]).unwrap(), 0);
682 let mut bytes = Vec::new();
683 ark_read.read_to_end(&mut bytes).unwrap();
684 assert_eq!(&bytes, b"abc");
685 for writer in [&mut host_write, &mut ark_write] {
686 assert_eq!(
687 writer.write(b"z").unwrap_err().kind(),
688 io::ErrorKind::BrokenPipe
689 );
690 assert_eq!(
691 writer.flush().unwrap_err().kind(),
692 io::ErrorKind::BrokenPipe
693 );
694 }
695 }
696
697 #[test]
700 fn test_flush_after_peer_drained_and_closed() {
701 let tester = test_clock();
703 let (host, ark) = duplex(4, &tester.clock());
704 let (_host_read, mut host_write) = host.into_halves();
705 let (mut ark_read, _ark_write) = ark.into_halves();
706 host_write.write_all(b"ab").unwrap();
707 let mut bytes = [0; 2];
708 ark_read.read_exact(&mut bytes).unwrap();
709 drop(ark_read);
710 host_write.flush().unwrap();
712 assert_eq!(
713 host_write.write(b"c").unwrap_err().kind(),
714 io::ErrorKind::BrokenPipe
715 );
716 }
717
718 #[test]
721 fn test_into_halves_and_independent_drop() {
722 let tester = test_clock();
724 let (host, ark) = duplex(4, &tester.clock());
725 let (mut host_read, mut host_write) = host.set_write_timeout(Duration::ZERO).into_halves();
726 let (mut ark_read, mut ark_write) = ark.into_halves();
727
728 host_write.write_all(b"abc").unwrap();
730 drop(host_write);
731 let mut bytes = Vec::new();
732 ark_read.read_to_end(&mut bytes).unwrap();
733 assert_eq!(&bytes, b"abc");
734
735 ark_write.write_all(b"xy").unwrap();
737 let mut reply = [0; 2];
738 host_read.read_exact(&mut reply).unwrap();
739 assert_eq!(&reply, b"xy");
740 drop(host_read);
741 assert_eq!(
742 ark_write.write(b"z").unwrap_err().kind(),
743 io::ErrorKind::BrokenPipe
744 );
745 }
746
747 #[test]
750 fn test_protocol_round_trip() {
751 use crate::protocol::{self, Message};
752 use crate::transport::mock::self_attestation;
753 use darkbio_crypto::xdsa;
754
755 let tester = test_clock();
757 let signer = xdsa::SecretKey::generate();
758 let identity = signer.public_key();
759 let attestation = self_attestation(&signer);
760 let (host, ark) = duplex(64 * 1024, &tester.clock());
761 let mut server = protocol::Server::new(ark, signer, attestation);
762 let (client, _) = protocol::connect(host, &identity).unwrap();
763 let mut session = server.accept().unwrap();
764 let payload: Vec<u8> = (0..256 * 1024).map(|n| n as u8).collect();
766 let deadline = tester.clock().now() + Duration::from_secs(5);
767 let answer = client
768 .requester()
769 .request(payload.clone(), deadline)
770 .unwrap();
771 let (message, responder) = session.recv().unwrap();
772 assert_eq!(message, Message::Develop(payload.clone()));
773 let written = responder.reply(message, deadline).unwrap();
774 assert_eq!(answer.wait::<Vec<u8>>().unwrap(), payload);
775 written.wait().unwrap();
776 client.close();
778 server.close();
779 }
780}