Skip to content

Commit 3aca40b

Browse files
djcRalith
authored andcommitted
quinn-proto: split ordering check out of read() path
1 parent 2610577 commit 3aca40b

File tree

3 files changed

+48
-51
lines changed

3 files changed

+48
-51
lines changed

quinn-proto/src/connection/assembler.rs

+39-40
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,9 @@ impl Assembler {
2525
Self::default()
2626
}
2727

28-
// Get the the next ordered chunk
29-
pub(crate) fn read(
30-
&mut self,
31-
max_length: usize,
32-
ordered: bool,
33-
) -> Result<Option<Chunk>, AssembleError> {
28+
pub(crate) fn ensure_ordering(&mut self, ordered: bool) -> Result<(), IllegalOrderedRead> {
3429
if ordered && !self.state.is_ordered() {
35-
return Err(AssembleError::IllegalOrderedRead);
30+
return Err(IllegalOrderedRead);
3631
} else if !ordered && self.state.is_ordered() {
3732
// Enter unordered mode
3833
let mut recvd = RangeSet::new();
@@ -42,17 +37,21 @@ impl Assembler {
4237
}
4338
self.state = State::Unordered { recvd };
4439
}
40+
Ok(())
41+
}
4542

43+
/// Get the the next chunk
44+
pub(crate) fn read(&mut self, max_length: usize, ordered: bool) -> Option<Chunk> {
4645
loop {
4746
let mut chunk = match self.data.peek_mut() {
4847
Some(chunk) => chunk,
49-
None => return Ok(None),
48+
None => return None,
5049
};
5150

5251
if ordered {
5352
if chunk.offset > self.bytes_read {
5453
// Next chunk is after current read index
55-
return Ok(None);
54+
return None;
5655
} else if (chunk.offset + chunk.bytes.len() as u64) <= self.bytes_read {
5756
// Next chunk is useless as the read index is beyond its end
5857
PeekMut::pop(chunk);
@@ -68,7 +67,7 @@ impl Assembler {
6867
}
6968
}
7069

71-
return Ok(Some(if max_length < chunk.bytes.len() {
70+
return Some(if max_length < chunk.bytes.len() {
7271
self.bytes_read += max_length as u64;
7372
let offset = chunk.offset;
7473
chunk.offset += max_length as u64;
@@ -78,7 +77,7 @@ impl Assembler {
7877
self.defragmented = self.defragmented.saturating_sub(1);
7978
let chunk = PeekMut::pop(chunk);
8079
Chunk::new(chunk.offset, chunk.bytes)
81-
}));
80+
});
8281
}
8382
}
8483

@@ -242,11 +241,8 @@ impl Default for State {
242241
}
243242

244243
/// Error indicating that an ordered read was performed on a stream after an unordered read
245-
#[derive(Debug, Copy, Clone)]
246-
pub enum AssembleError {
247-
IllegalOrderedRead,
248-
UnknownStream,
249-
}
244+
#[derive(Debug)]
245+
pub struct IllegalOrderedRead;
250246

251247
#[cfg(test)]
252248
mod test {
@@ -272,6 +268,7 @@ mod test {
272268
#[test]
273269
fn assemble_unordered() {
274270
let mut x = Assembler::new();
271+
x.ensure_ordering(false).unwrap();
275272
x.insert(3, Bytes::from_static(b"456"));
276273
assert_matches!(next(&mut x, 32), None);
277274
x.insert(0, Bytes::from_static(b"123"));
@@ -426,42 +423,44 @@ mod test {
426423
x.insert(7, Bytes::from_static(b"hij"));
427424
x.insert(11, Bytes::from_static(b"lmn"));
428425
x.defragment();
429-
assert_matches!(x.read(usize::MAX, true), Ok(Some(ref y)) if &y.bytes[..] == b"abcdef");
426+
assert_matches!(x.read(usize::MAX, true), Some(ref y) if &y.bytes[..] == b"abcdef");
430427
x.insert(5, Bytes::from_static(b"fghijklmn"));
431-
assert_matches!(x.read(usize::MAX, true), Ok(Some(ref y)) if &y.bytes[..] == b"ghijklmn");
428+
assert_matches!(x.read(usize::MAX, true), Some(ref y) if &y.bytes[..] == b"ghijklmn");
432429
x.insert(13, Bytes::from_static(b"nopq"));
433-
assert_matches!(x.read(usize::MAX, true), Ok(Some(ref y)) if &y.bytes[..] == b"opq");
430+
assert_matches!(x.read(usize::MAX, true), Some(ref y) if &y.bytes[..] == b"opq");
434431
x.insert(15, Bytes::from_static(b"pqrs"));
435-
assert_matches!(x.read(usize::MAX, true), Ok(Some(ref y)) if &y.bytes[..] == b"rs");
436-
assert_matches!(x.read(usize::MAX, true), Ok(None));
432+
assert_matches!(x.read(usize::MAX, true), Some(ref y) if &y.bytes[..] == b"rs");
433+
assert_matches!(x.read(usize::MAX, true), None);
437434
}
438435

439436
#[test]
440437
fn unordered_happy_path() {
441438
let mut x = Assembler::new();
439+
x.ensure_ordering(false).unwrap();
442440
x.insert(0, Bytes::from_static(b"abc"));
443441
assert_eq!(
444442
next_unordered(&mut x),
445443
Chunk::new(0, Bytes::from_static(b"abc"))
446444
);
447-
assert_eq!(x.read(usize::MAX, false).unwrap(), None);
445+
assert_eq!(x.read(usize::MAX, false), None);
448446
x.insert(3, Bytes::from_static(b"def"));
449447
assert_eq!(
450448
next_unordered(&mut x),
451449
Chunk::new(3, Bytes::from_static(b"def"))
452450
);
453-
assert_eq!(x.read(usize::MAX, false).unwrap(), None);
451+
assert_eq!(x.read(usize::MAX, false), None);
454452
}
455453

456454
#[test]
457455
fn unordered_dedup() {
458456
let mut x = Assembler::new();
457+
x.ensure_ordering(false).unwrap();
459458
x.insert(3, Bytes::from_static(b"def"));
460459
assert_eq!(
461460
next_unordered(&mut x),
462461
Chunk::new(3, Bytes::from_static(b"def"))
463462
);
464-
assert_eq!(x.read(usize::MAX, false).unwrap(), None);
463+
assert_eq!(x.read(usize::MAX, false), None);
465464
x.insert(0, Bytes::from_static(b"a"));
466465
x.insert(0, Bytes::from_static(b"abcdefghi"));
467466
x.insert(0, Bytes::from_static(b"abcd"));
@@ -477,54 +476,54 @@ mod test {
477476
next_unordered(&mut x),
478477
Chunk::new(6, Bytes::from_static(b"ghi"))
479478
);
480-
assert_eq!(x.read(usize::MAX, false).unwrap(), None);
479+
assert_eq!(x.read(usize::MAX, false), None);
481480
x.insert(8, Bytes::from_static(b"ijkl"));
482481
assert_eq!(
483482
next_unordered(&mut x),
484483
Chunk::new(9, Bytes::from_static(b"jkl"))
485484
);
486-
assert_eq!(x.read(usize::MAX, false).unwrap(), None);
485+
assert_eq!(x.read(usize::MAX, false), None);
487486
x.insert(12, Bytes::from_static(b"mno"));
488487
assert_eq!(
489488
next_unordered(&mut x),
490489
Chunk::new(12, Bytes::from_static(b"mno"))
491490
);
492-
assert_eq!(x.read(usize::MAX, false).unwrap(), None);
491+
assert_eq!(x.read(usize::MAX, false), None);
493492
x.insert(2, Bytes::from_static(b"cde"));
494-
assert_eq!(x.read(usize::MAX, false).unwrap(), None);
493+
assert_eq!(x.read(usize::MAX, false), None);
495494
}
496495

497496
#[test]
498497
fn chunks_dedup() {
499498
let mut x = Assembler::new();
500499
x.insert(3, Bytes::from_static(b"def"));
501-
assert_eq!(x.read(usize::MAX, true).unwrap(), None);
500+
assert_eq!(x.read(usize::MAX, true), None);
502501
x.insert(0, Bytes::from_static(b"a"));
503502
x.insert(1, Bytes::from_static(b"bcdefghi"));
504503
x.insert(0, Bytes::from_static(b"abcd"));
505504
assert_eq!(
506-
x.read(usize::MAX, true).unwrap(),
505+
x.read(usize::MAX, true),
507506
Some(Chunk::new(0, Bytes::from_static(b"abcd")))
508507
);
509508
assert_eq!(
510-
x.read(usize::MAX, true).unwrap(),
509+
x.read(usize::MAX, true),
511510
Some(Chunk::new(4, Bytes::from_static(b"efghi")))
512511
);
513-
assert_eq!(x.read(usize::MAX, true).unwrap(), None);
512+
assert_eq!(x.read(usize::MAX, true), None);
514513
x.insert(8, Bytes::from_static(b"ijkl"));
515514
assert_eq!(
516-
x.read(usize::MAX, true).unwrap(),
515+
x.read(usize::MAX, true),
517516
Some(Chunk::new(9, Bytes::from_static(b"jkl")))
518517
);
519-
assert_eq!(x.read(usize::MAX, true).unwrap(), None);
518+
assert_eq!(x.read(usize::MAX, true), None);
520519
x.insert(12, Bytes::from_static(b"mno"));
521520
assert_eq!(
522-
x.read(usize::MAX, true).unwrap(),
521+
x.read(usize::MAX, true),
523522
Some(Chunk::new(12, Bytes::from_static(b"mno")))
524523
);
525-
assert_eq!(x.read(usize::MAX, true).unwrap(), None);
524+
assert_eq!(x.read(usize::MAX, true), None);
526525
x.insert(2, Bytes::from_static(b"cde"));
527-
assert_eq!(x.read(usize::MAX, true).unwrap(), None);
526+
assert_eq!(x.read(usize::MAX, true), None);
528527
}
529528

530529
#[test]
@@ -533,7 +532,7 @@ mod test {
533532
x.insert(0, Bytes::from_static(b"abc"));
534533
assert_eq!(x.data.len(), 1);
535534
assert_eq!(
536-
x.read(usize::MAX, true).unwrap(),
535+
x.read(usize::MAX, true),
537536
Some(Chunk::new(0, Bytes::from_static(b"abc")))
538537
);
539538
x.insert(0, Bytes::from_static(b"ab"));
@@ -549,10 +548,10 @@ mod test {
549548
}
550549

551550
fn next_unordered(x: &mut Assembler) -> Chunk {
552-
x.read(usize::MAX, false).unwrap().unwrap()
551+
x.read(usize::MAX, false).unwrap()
553552
}
554553

555554
fn next(x: &mut Assembler, size: usize) -> Option<Bytes> {
556-
x.read(size, true).unwrap().map(|chunk| chunk.bytes)
555+
x.read(size, true).map(|chunk| chunk.bytes)
557556
}
558557
}

quinn-proto/src/connection/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1760,7 +1760,7 @@ where
17601760
space
17611761
.crypto_stream
17621762
.insert(crypto.offset, crypto.data.clone());
1763-
while let Some(chunk) = space.crypto_stream.read(usize::MAX, true).unwrap() {
1763+
while let Some(chunk) = space.crypto_stream.read(usize::MAX, true) {
17641764
trace!("consumed {} CRYPTO bytes", chunk.bytes.len());
17651765
if self.crypto.read_handshake(&chunk.bytes)? {
17661766
self.events.push_back(Event::HandshakeDataReady);

quinn-proto/src/connection/streams/recv.rs

+8-10
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use thiserror::Error;
33
use tracing::debug;
44

55
use super::{ShouldTransmit, UnknownStream};
6-
use crate::connection::assembler::{AssembleError, Assembler, Chunk};
6+
use crate::connection::assembler::{Assembler, Chunk, IllegalOrderedRead};
77
use crate::{frame, TransportError, VarInt};
88

99
#[derive(Debug, Default)]
@@ -73,7 +73,8 @@ impl Recv {
7373
return Err(ReadError::UnknownStream);
7474
}
7575

76-
match self.assembler.read(max_length, ordered)? {
76+
self.assembler.ensure_ordering(ordered)?;
77+
match self.assembler.read(max_length, ordered) {
7778
Some(chunk) => Ok(Some(chunk)),
7879
None => self.read_blocked().map(|()| None),
7980
}
@@ -92,7 +93,8 @@ impl Recv {
9293
return Ok(Some(out));
9394
}
9495

95-
while let Some(chunk) = self.assembler.read(usize::MAX, true)? {
96+
self.assembler.ensure_ordering(true)?;
97+
while let Some(chunk) = self.assembler.read(usize::MAX, true) {
9698
chunks[out.bufs] = chunk.bytes;
9799
out.read += chunks[out.bufs].len();
98100
out.bufs += 1;
@@ -314,13 +316,9 @@ pub enum ReadError {
314316
IllegalOrderedRead,
315317
}
316318

317-
impl From<AssembleError> for ReadError {
318-
fn from(e: AssembleError) -> Self {
319-
use AssembleError::*;
320-
match e {
321-
IllegalOrderedRead => ReadError::IllegalOrderedRead,
322-
UnknownStream => ReadError::UnknownStream,
323-
}
319+
impl From<IllegalOrderedRead> for ReadError {
320+
fn from(_: IllegalOrderedRead) -> Self {
321+
ReadError::IllegalOrderedRead
324322
}
325323
}
326324

0 commit comments

Comments
 (0)