Fix packet buffer enqueue logic error

The size of the contiguous window should be prioritized over the size of
the contiguous window if padding were added.

For example, given the following packet buffer:

  1   2     3
|---|----|------|

If 2 is used and 1 and 3 are empty, enqueing a buffer of size 4 should
be placed in contiguous window 3 and the size of 1 should not cause
any issues in enqueue.

Closes: #247
Approved by: whitequark
This commit is contained in:
Dan Robertson 2018-06-21 12:49:34 +00:00 committed by Homu
parent 3d141489a2
commit 276acfb7ef
1 changed files with 22 additions and 6 deletions

View File

@ -84,13 +84,21 @@ impl<'a, 'b, H> PacketBuffer<'a, 'b, H> {
let window = self.payload_ring.window();
let contig_window = self.payload_ring.contiguous_window();
if window < size || (window != contig_window && window - contig_window < size) {
if window < size {
return Err(Error::Exhausted)
}
if contig_window < size {
*self.metadata_ring.enqueue_one()? = PacketMetadata::padding(size);
self.payload_ring.enqueue_many(size);
} else if contig_window < size {
if window - contig_window < size {
// The buffer length is larger than the current contiguous window
// and is larger than the contiguous window will be after adding
// the padding necessary to circle around to the beginning of the
// ring buffer.
return Err(Error::Exhausted)
} else {
// Add padding to the end of the ring buffer so that the
// contiguous window is at the beginning of the ring buffer.
*self.metadata_ring.enqueue_one()? = PacketMetadata::padding(size);
self.payload_ring.enqueue_many(size);
}
}
*self.metadata_ring.enqueue_one()? = PacketMetadata::packet(size, header);
@ -244,4 +252,12 @@ mod test {
let mut buffer = buffer();
assert_eq!(buffer.enqueue(32, ()), Err(Error::Truncated));
}
#[test]
fn test_contig_window_prioritized() {
let mut buffer = buffer();
assert!(buffer.enqueue(4, ()).is_ok());
assert!(buffer.dequeue().is_ok());
assert!(buffer.enqueue(5, ()).is_ok());
}
}