1use crate::transport::{Read, Stream, Write};
13use std::collections::VecDeque;
14use std::io;
15use std::sync::{Arc, Condvar, Mutex, MutexGuard};
16use std::time::{Duration, Instant};
17
18pub type Duplex = Stream<Reader, Writer>;
20
21impl Duplex {
22 pub fn into_halves(self) -> (Reader, Writer) {
42 let (reader, writer, _, _) = self.into_parts();
43 (reader, writer)
44 }
45}
46
47pub fn duplex(capacity: usize) -> (Duplex, Duplex) {
72 assert!(capacity > 0, "duplex capacity must be nonzero");
73 let incoming = Arc::new(Pipe::new(capacity));
74 let outgoing = Arc::new(Pipe::new(capacity));
75 (
76 endpoint(incoming.clone(), outgoing.clone()),
77 endpoint(outgoing, incoming),
78 )
79}
80
81fn endpoint(incoming: Arc<Pipe>, outgoing: Arc<Pipe>) -> Duplex {
83 Stream::new(
84 Reader {
85 pipe: incoming.clone(),
86 deadline: None,
87 },
88 Writer {
89 pipe: outgoing.clone(),
90 deadline: None,
91 },
92 move || {
93 incoming.close_reader();
94 outgoing.close_writer();
95 },
96 )
97}
98
99#[derive(Debug)]
101pub struct Reader {
102 pipe: Arc<Pipe>,
103 deadline: Option<Instant>,
104}
105
106impl io::Read for Reader {
107 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
108 let mut state = self.pipe.lock();
109 loop {
110 if buf.is_empty() || !state.reader_open {
111 return Ok(0);
112 }
113 if !state.bytes.is_empty() {
114 let count = buf.len().min(state.bytes.len());
115 for (out, byte) in buf.iter_mut().zip(state.bytes.drain(..count)) {
116 *out = byte;
117 }
118 drop(state);
119 self.pipe.changed.notify_all();
120 return Ok(count);
121 }
122 if !state.writer_open {
123 return Ok(0);
124 }
125 state = self.pipe.wait(state, time_left(self.deadline)?);
126 }
127 }
128}
129
130impl Read for Reader {
131 fn set_read_deadline(&mut self, deadline: Option<Instant>) -> io::Result<()> {
132 self.deadline = deadline;
133 Ok(())
134 }
135}
136
137impl Drop for Reader {
138 fn drop(&mut self) {
139 self.pipe.close_reader();
140 }
141}
142
143#[derive(Debug)]
145pub struct Writer {
146 pipe: Arc<Pipe>,
147 deadline: Option<Instant>,
148}
149
150impl io::Write for Writer {
151 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
152 let mut state = self.pipe.lock();
153 loop {
154 let timeout = time_left(self.deadline)?;
155 if buf.is_empty() {
156 return Ok(0);
157 }
158 if !state.reader_open || !state.writer_open {
159 return Err(io::ErrorKind::BrokenPipe.into());
160 }
161 let count = buf.len().min(self.pipe.capacity - state.bytes.len());
162 if count > 0 {
163 state.bytes.extend(&buf[..count]);
164 drop(state);
165 self.pipe.changed.notify_all();
166 return Ok(count);
167 }
168 state = self.pipe.wait(state, timeout);
169 }
170 }
171
172 fn flush(&mut self) -> io::Result<()> {
173 let state = self.pipe.lock();
174 time_left(self.deadline)?;
175 if !state.writer_open || state.lost {
176 return Err(io::ErrorKind::BrokenPipe.into());
177 }
178 Ok(())
179 }
180}
181
182impl Write for Writer {
183 fn set_write_deadline(&mut self, deadline: Instant) -> io::Result<()> {
184 self.deadline = Some(deadline);
185 Ok(())
186 }
187}
188
189impl Drop for Writer {
190 fn drop(&mut self) {
191 self.pipe.close_writer();
192 }
193}
194
195#[derive(Debug)]
197struct Pipe {
198 capacity: usize,
199 state: Mutex<State>,
200 changed: Condvar,
201}
202
203#[derive(Debug)]
204struct State {
205 bytes: VecDeque<u8>,
206 reader_open: bool,
207 writer_open: bool,
208 lost: bool, #[cfg(test)]
210 waiting: usize,
211}
212
213impl Pipe {
214 fn new(capacity: usize) -> Self {
215 Self {
216 capacity,
217 state: Mutex::new(State {
218 bytes: VecDeque::with_capacity(capacity),
219 reader_open: true,
220 writer_open: true,
221 lost: false,
222 #[cfg(test)]
223 waiting: 0,
224 }),
225 changed: Condvar::new(),
226 }
227 }
228
229 fn lock(&self) -> MutexGuard<'_, State> {
230 self.state.lock().unwrap_or_else(|err| err.into_inner())
232 }
233
234 fn wait<'a>(
235 &self,
236 state: MutexGuard<'a, State>,
237 timeout: Option<Duration>,
238 ) -> MutexGuard<'a, State> {
239 #[cfg(test)]
240 let state = {
241 let mut state = state;
242 state.waiting += 1;
243 self.changed.notify_all();
244 state
245 };
246 let state = match timeout {
247 Some(timeout) => {
248 self.changed
249 .wait_timeout(state, timeout)
250 .unwrap_or_else(|err| err.into_inner())
251 .0
252 }
253 None => self
254 .changed
255 .wait(state)
256 .unwrap_or_else(|err| err.into_inner()),
257 };
258 #[cfg(test)]
259 let state = {
260 let mut state = state;
261 state.waiting -= 1;
262 state
263 };
264 state
265 }
266
267 fn close_reader(&self) {
268 let mut state = self.lock();
269 state.reader_open = false;
270 state.lost |= !state.bytes.is_empty();
271 state.bytes.clear();
272 drop(state);
273 self.changed.notify_all();
274 }
275
276 fn close_writer(&self) {
277 self.lock().writer_open = false;
278 self.changed.notify_all();
279 }
280}
281
282fn time_left(deadline: Option<Instant>) -> io::Result<Option<Duration>> {
284 deadline
285 .map(|deadline| {
286 deadline
287 .checked_duration_since(Instant::now())
288 .filter(|left| !left.is_zero())
289 .ok_or_else(|| io::ErrorKind::TimedOut.into())
290 })
291 .transpose()
292}
293
294#[cfg(test)]
295#[cfg_attr(coverage_nightly, coverage(off))]
296mod tests {
297 use super::*;
298 use crate::transport::Closer;
299 use std::io::{Read as _, Write as _};
300 use std::sync::mpsc;
301 use std::thread;
302
303 const PATIENCE: Duration = Duration::from_secs(5);
304 const TIMEOUT: Duration = Duration::from_millis(50);
305
306 fn halves(stream: Duplex) -> (Reader, Writer, Closer) {
308 let closer = stream.closer();
309 let (reader, writer) = stream.into_halves();
310 (reader, writer, closer)
311 }
312
313 fn blocked(pipe: &Pipe) {
315 let deadline = Instant::now() + PATIENCE;
316 let mut state = pipe.lock();
317 while state.waiting == 0 {
318 let timeout = deadline.checked_duration_since(Instant::now()).unwrap();
319 state = pipe.changed.wait_timeout(state, timeout).unwrap().0;
320 }
321 }
322
323 #[test]
324 #[should_panic(expected = "duplex capacity must be nonzero")]
325 fn test_zero_capacity() {
326 duplex(0);
327 }
328
329 #[test]
332 fn test_byte_stream_and_independent_deadlines() {
333 let (host, ark) = duplex(4);
334 let (mut host_read, mut host_write, _host_close) = halves(host);
335 let (mut ark_read, mut ark_write, _ark_close) = halves(ark);
336
337 assert_eq!(host_read.read(&mut []).unwrap(), 0);
338 assert_eq!(host_write.write(b"abcdef").unwrap(), 4);
339 assert_eq!(host_write.write(&[]).unwrap(), 0);
340 host_write.flush().unwrap();
342 let mut first = [0; 2];
343 ark_read.read_exact(&mut first).unwrap();
344 assert_eq!(&first, b"ab");
345 host_write.write_all(b"ef").unwrap();
346 let mut rest = [0; 4];
347 ark_read.read_exact(&mut rest).unwrap();
348 assert_eq!(&rest, b"cdef");
349
350 ark_write.write_all(b"xy").unwrap();
351 host_read.set_read_deadline(Some(Instant::now())).unwrap();
352 host_read.read_exact(&mut first).unwrap();
353 assert_eq!(&first, b"xy");
354 assert_eq!(
355 host_read.read(&mut first).unwrap_err().kind(),
356 io::ErrorKind::TimedOut
357 );
358 assert_eq!(host_read.read(&mut []).unwrap(), 0);
359 host_write.write_all(b"q").unwrap();
360
361 host_write.set_write_deadline(Instant::now()).unwrap();
362 host_read.set_read_deadline(None).unwrap();
363 ark_write.write_all(b"uv").unwrap();
364 host_read.read_exact(&mut first).unwrap();
365 assert_eq!(&first, b"uv");
366 for bytes in [b"t".as_slice(), b""] {
367 assert_eq!(
368 host_write.write(bytes).unwrap_err().kind(),
369 io::ErrorKind::TimedOut
370 );
371 }
372 assert_eq!(
373 host_write.flush().unwrap_err().kind(),
374 io::ErrorKind::TimedOut
375 );
376
377 host_write
378 .set_write_deadline(Instant::now() + PATIENCE)
379 .unwrap();
380 host_write.write_all(b"rs").unwrap();
381 host_write.flush().unwrap();
382 let mut accepted = [0; 3];
383 ark_read.read_exact(&mut accepted).unwrap();
384 assert_eq!(&accepted, b"qrs");
385 }
386
387 #[test]
390 fn test_read_timeout_and_reuse() {
391 let (host, ark) = duplex(1);
392 let (mut reader, _host_write, _host_close) = halves(host);
393 let (_ark_read, mut writer, _ark_close) = halves(ark);
394 let pipe = reader.pipe.clone();
395 let (done, result) = mpsc::channel();
396 let timed = thread::spawn(move || {
397 let deadline = Instant::now() + TIMEOUT;
398 reader.set_read_deadline(Some(deadline)).unwrap();
399 let mut buf = [99];
400 let error = reader.read(&mut buf).unwrap_err();
401 assert!(Instant::now() >= deadline);
402 assert_eq!(buf, [99]);
403 done.send((reader, error.kind())).unwrap();
404 });
405 let (mut reader, kind) = result.recv_timeout(PATIENCE).unwrap();
406 timed.join().unwrap();
407 assert_eq!(kind, io::ErrorKind::TimedOut);
408
409 reader.set_read_deadline(None).unwrap();
410 let (done, result) = mpsc::channel();
411 let reading = thread::spawn(move || {
412 let mut buf = [0];
413 reader.read_exact(&mut buf).unwrap();
414 done.send(buf).unwrap();
415 });
416 blocked(&pipe);
417 writer.write_all(b"x").unwrap();
418 assert_eq!(&result.recv_timeout(PATIENCE).unwrap(), b"x");
419 reading.join().unwrap();
420 }
421
422 #[test]
425 fn test_write_timeout_and_reuse() {
426 let (host, ark) = duplex(3);
427 let (_host_read, mut writer, _host_close) = halves(host);
428 let (mut reader, _ark_write, _ark_close) = halves(ark);
429 let (done, result) = mpsc::channel();
430 let writing = thread::spawn(move || {
431 let deadline = Instant::now() + TIMEOUT;
432 writer.set_write_deadline(deadline).unwrap();
433 let error = writer.write_all(b"abcd").unwrap_err();
434 assert!(Instant::now() >= deadline);
435 done.send((writer, error.kind())).unwrap();
436 });
437 let (mut writer, kind) = result.recv_timeout(PATIENCE).unwrap();
438 writing.join().unwrap();
439 assert_eq!(kind, io::ErrorKind::TimedOut);
440 let mut prefix = [0; 3];
441 reader.read_exact(&mut prefix).unwrap();
442 assert_eq!(&prefix, b"abc");
443
444 writer
445 .set_write_deadline(Instant::now() + PATIENCE)
446 .unwrap();
447 writer.write_all(b"ef").unwrap();
448 drop(writer);
449 let mut suffix = Vec::new();
450 reader.read_to_end(&mut suffix).unwrap();
451 assert_eq!(&suffix, b"ef");
452 }
453
454 #[test]
457 fn test_backpressure_wakes_writer() {
458 let (host, ark) = duplex(3);
459 let (_host_read, mut writer, _host_close) = halves(host);
460 let (mut reader, _ark_write, _ark_close) = halves(ark);
461 writer.write_all(b"abc").unwrap();
462 let pipe = writer.pipe.clone();
463 let (done, result) = mpsc::channel();
464 let writing = thread::spawn(move || {
465 writer
466 .set_write_deadline(Instant::now() + PATIENCE)
467 .unwrap();
468 done.send(writer.write_all(b"defgh")).unwrap();
469 });
470 blocked(&pipe);
471 reader
472 .set_read_deadline(Some(Instant::now() + PATIENCE))
473 .unwrap();
474 let mut bytes = [0; 8];
475 reader.read_exact(&mut bytes).unwrap();
476 assert_eq!(&bytes, b"abcdefgh");
477 result.recv_timeout(PATIENCE).unwrap().unwrap();
478 writing.join().unwrap();
479 }
480
481 #[test]
484 fn test_shutdown_wakes_both_directions() {
485 for local in [false, true] {
486 let (host, ark) = duplex(1);
487 let (mut reader, mut writer, closer) = halves(host);
488 writer.write_all(b"a").unwrap();
489 let incoming = reader.pipe.clone();
490 let outgoing = writer.pipe.clone();
491 let (read_done, read_result) = mpsc::channel();
492 let reading = thread::spawn(move || {
493 read_done.send(reader.read(&mut [0])).unwrap();
494 });
495 let (write_done, write_result) = mpsc::channel();
496 let writing = thread::spawn(move || {
497 write_done.send(writer.write(b"b")).unwrap();
498 });
499 blocked(&incoming);
500 blocked(&outgoing);
501 if local {
502 closer.close();
503 } else {
504 drop(ark);
505 }
506 assert_eq!(read_result.recv_timeout(PATIENCE).unwrap().unwrap(), 0);
507 assert_eq!(
508 write_result
509 .recv_timeout(PATIENCE)
510 .unwrap()
511 .unwrap_err()
512 .kind(),
513 io::ErrorKind::BrokenPipe
514 );
515 reading.join().unwrap();
516 writing.join().unwrap();
517 }
518 }
519
520 #[test]
523 fn test_shutdown_drains_output_and_discards_input() {
524 let (host, ark) = duplex(3);
525 let (mut host_read, mut host_write, closer) = halves(host);
526 let (mut ark_read, mut ark_write, _ark_close) = halves(ark);
527 host_write.write_all(b"abc").unwrap();
528 ark_write.write_all(b"xy").unwrap();
529 host_read.set_read_deadline(Some(Instant::now())).unwrap();
530 ark_read.set_read_deadline(Some(Instant::now())).unwrap();
531 closer.close();
532 closer.close();
533 assert_eq!(host_read.read(&mut [0]).unwrap(), 0);
534 let mut bytes = Vec::new();
535 ark_read.read_to_end(&mut bytes).unwrap();
536 assert_eq!(&bytes, b"abc");
537 for writer in [&mut host_write, &mut ark_write] {
538 assert_eq!(
539 writer.write(b"z").unwrap_err().kind(),
540 io::ErrorKind::BrokenPipe
541 );
542 assert_eq!(
543 writer.flush().unwrap_err().kind(),
544 io::ErrorKind::BrokenPipe
545 );
546 }
547 }
548
549 #[test]
552 fn test_flush_after_peer_drained_and_closed() {
553 let (host, ark) = duplex(4);
554 let (_host_read, mut host_write) = host.into_halves();
555 let (mut ark_read, _ark_write) = ark.into_halves();
556 host_write.write_all(b"ab").unwrap();
557 let mut bytes = [0; 2];
558 ark_read.read_exact(&mut bytes).unwrap();
559 drop(ark_read);
560 host_write.flush().unwrap();
561 assert_eq!(
562 host_write.write(b"c").unwrap_err().kind(),
563 io::ErrorKind::BrokenPipe
564 );
565 }
566
567 #[test]
570 fn test_into_halves_and_independent_drop() {
571 let (host, ark) = duplex(4);
572 let (mut host_read, mut host_write) = host.set_write_timeout(Duration::ZERO).into_halves();
573 let (mut ark_read, mut ark_write) = ark.into_halves();
574
575 host_write.write_all(b"abc").unwrap();
576 drop(host_write);
577 let mut bytes = Vec::new();
578 ark_read.read_to_end(&mut bytes).unwrap();
579 assert_eq!(&bytes, b"abc");
580
581 ark_write.write_all(b"xy").unwrap();
582 let mut reply = [0; 2];
583 host_read.read_exact(&mut reply).unwrap();
584 assert_eq!(&reply, b"xy");
585 drop(host_read);
586 assert_eq!(
587 ark_write.write(b"z").unwrap_err().kind(),
588 io::ErrorKind::BrokenPipe
589 );
590 }
591
592 #[test]
595 fn test_protocol_round_trip() {
596 use crate::protocol::{self, Message};
597 use crate::transport::mock::self_attestation;
598 use darkbio_crypto::xdsa;
599
600 let signer = xdsa::SecretKey::generate();
601 let identity = signer.public_key();
602 let attestation = self_attestation(&signer);
603 let (host, ark) = duplex(64 * 1024);
604 let mut server = protocol::Server::new(ark, signer, attestation);
605 let (client, _) = protocol::connect(host, &identity).unwrap();
606 let mut session = server.accept().unwrap();
607 let payload: Vec<u8> = (0..256 * 1024).map(|n| n as u8).collect();
608 let deadline = Instant::now() + PATIENCE;
609 let answer = client
610 .requester()
611 .request(payload.clone(), deadline)
612 .unwrap();
613 let (message, responder) = session.recv().unwrap();
614 assert_eq!(message, Message::Develop(payload.clone()));
615 let written = responder.reply(message, deadline).unwrap();
616 assert_eq!(answer.wait::<Vec<u8>>().unwrap(), payload);
617 written.wait().unwrap();
618 client.close();
619 server.close();
620 }
621}