| // Copyright (C) 2023, Cloudflare, Inc. |
| // All rights reserved. |
| // |
| // Redistribution and use in source and binary forms, with or without |
| // modification, are permitted provided that the following conditions are |
| // met: |
| // |
| // * Redistributions of source code must retain the above copyright notice, |
| // this list of conditions and the following disclaimer. |
| // |
| // * Redistributions in binary form must reproduce the above copyright |
| // notice, this list of conditions and the following disclaimer in the |
| // documentation and/or other materials provided with the distribution. |
| // |
| // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS |
| // IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
| // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR |
| // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
| // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
| // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| use std::cmp; |
| use std::time; |
| |
| use std::collections::BTreeMap; |
| use std::collections::VecDeque; |
| |
| use crate::Error; |
| use crate::Result; |
| |
| use crate::flowcontrol; |
| |
| use super::RangeBuf; |
| use super::DEFAULT_STREAM_WINDOW; |
| |
| /// Receive-side stream buffer. |
| /// |
| /// Stream data received by the peer is buffered in a list of data chunks |
| /// ordered by offset in ascending order. Contiguous data can then be read |
| /// into a slice. |
| #[derive(Debug, Default)] |
| pub struct RecvBuf { |
| /// Chunks of data received from the peer that have not yet been read by |
| /// the application, ordered by offset. |
| data: BTreeMap<u64, RangeBuf>, |
| |
| /// The lowest data offset that has yet to be read by the application. |
| off: u64, |
| |
| /// The total length of data received on this stream. |
| len: u64, |
| |
| /// Receiver flow controller. |
| flow_control: flowcontrol::FlowControl, |
| |
| /// The final stream offset received from the peer, if any. |
| fin_off: Option<u64>, |
| |
| /// The error code received via RESET_STREAM. |
| error: Option<u64>, |
| |
| /// Whether incoming data is validated but not buffered. |
| drain: bool, |
| } |
| |
| impl RecvBuf { |
| /// Creates a new receive buffer. |
| pub fn new(max_data: u64, max_window: u64) -> RecvBuf { |
| RecvBuf { |
| flow_control: flowcontrol::FlowControl::new( |
| max_data, |
| cmp::min(max_data, DEFAULT_STREAM_WINDOW), |
| max_window, |
| ), |
| ..RecvBuf::default() |
| } |
| } |
| |
| /// Inserts the given chunk of data in the buffer. |
| /// |
| /// This also takes care of enforcing stream flow control limits, as well |
| /// as handling incoming data that overlaps data that is already in the |
| /// buffer. |
| pub fn write(&mut self, buf: RangeBuf) -> Result<()> { |
| if buf.max_off() > self.max_data() { |
| return Err(Error::FlowControl); |
| } |
| |
| if let Some(fin_off) = self.fin_off { |
| // Stream's size is known, forbid data beyond that point. |
| if buf.max_off() > fin_off { |
| return Err(Error::FinalSize); |
| } |
| |
| // Stream's size is already known, forbid changing it. |
| if buf.fin() && fin_off != buf.max_off() { |
| return Err(Error::FinalSize); |
| } |
| } |
| |
| // Stream's known size is lower than data already received. |
| if buf.fin() && buf.max_off() < self.len { |
| return Err(Error::FinalSize); |
| } |
| |
| // We already saved the final offset, so there's nothing else we |
| // need to keep from the RangeBuf if it's empty. |
| if self.fin_off.is_some() && buf.is_empty() { |
| return Ok(()); |
| } |
| |
| if buf.fin() { |
| self.fin_off = Some(buf.max_off()); |
| } |
| |
| // No need to store empty buffer that doesn't carry the fin flag. |
| if !buf.fin() && buf.is_empty() { |
| return Ok(()); |
| } |
| |
| // Check if data is fully duplicate, that is the buffer's max offset is |
| // lower or equal to the offset already stored in the recv buffer. |
| if self.off >= buf.max_off() { |
| // An exception is applied to empty range buffers, because an empty |
| // buffer's max offset matches the max offset of the recv buffer. |
| // |
| // By this point all spurious empty buffers should have already been |
| // discarded, so allowing empty buffers here should be safe. |
| if !buf.is_empty() { |
| return Ok(()); |
| } |
| } |
| |
| let mut tmp_bufs = VecDeque::with_capacity(2); |
| tmp_bufs.push_back(buf); |
| |
| 'tmp: while let Some(mut buf) = tmp_bufs.pop_front() { |
| // Discard incoming data below current stream offset. Bytes up to |
| // `self.off` have already been received so we should not buffer |
| // them again. This is also important to make sure `ready()` doesn't |
| // get stuck when a buffer with lower offset than the stream's is |
| // buffered. |
| if self.off_front() > buf.off() { |
| buf = buf.split_off((self.off_front() - buf.off()) as usize); |
| } |
| |
| // Handle overlapping data. If the incoming data's starting offset |
| // is above the previous maximum received offset, there is clearly |
| // no overlap so this logic can be skipped. However do still try to |
| // merge an empty final buffer (i.e. an empty buffer with the fin |
| // flag set, which is the only kind of empty buffer that should |
| // reach this point). |
| if buf.off() < self.max_off() || buf.is_empty() { |
| for (_, b) in self.data.range(buf.off()..) { |
| let off = buf.off(); |
| |
| // We are past the current buffer. |
| if b.off() > buf.max_off() { |
| break; |
| } |
| |
| // New buffer is fully contained in existing buffer. |
| if off >= b.off() && buf.max_off() <= b.max_off() { |
| continue 'tmp; |
| } |
| |
| // New buffer's start overlaps existing buffer. |
| if off >= b.off() && off < b.max_off() { |
| buf = buf.split_off((b.max_off() - off) as usize); |
| } |
| |
| // New buffer's end overlaps existing buffer. |
| if off < b.off() && buf.max_off() > b.off() { |
| tmp_bufs |
| .push_back(buf.split_off((b.off() - off) as usize)); |
| } |
| } |
| } |
| |
| self.len = cmp::max(self.len, buf.max_off()); |
| |
| if !self.drain { |
| self.data.insert(buf.max_off(), buf); |
| } |
| } |
| |
| Ok(()) |
| } |
| |
| /// Writes data from the receive buffer into the given output buffer. |
| /// |
| /// Only contiguous data is written to the output buffer, starting from |
| /// offset 0. The offset is incremented as data is read out of the receive |
| /// buffer into the application buffer. If there is no data at the expected |
| /// read offset, the `Done` error is returned. |
| /// |
| /// On success the amount of data read, and a flag indicating if there is |
| /// no more data in the buffer, are returned as a tuple. |
| pub fn emit(&mut self, out: &mut [u8]) -> Result<(usize, bool)> { |
| let mut len = 0; |
| let mut cap = out.len(); |
| |
| if !self.ready() { |
| return Err(Error::Done); |
| } |
| |
| // The stream was reset, so clear its data and return the error code |
| // instead. |
| if let Some(e) = self.error { |
| self.data.clear(); |
| return Err(Error::StreamReset(e)); |
| } |
| |
| while cap > 0 && self.ready() { |
| let mut entry = match self.data.first_entry() { |
| Some(entry) => entry, |
| None => break, |
| }; |
| |
| let buf = entry.get_mut(); |
| |
| let buf_len = cmp::min(buf.len(), cap); |
| |
| out[len..len + buf_len].copy_from_slice(&buf[..buf_len]); |
| |
| self.off += buf_len as u64; |
| |
| len += buf_len; |
| cap -= buf_len; |
| |
| if buf_len < buf.len() { |
| buf.consume(buf_len); |
| |
| // We reached the maximum capacity, so end here. |
| break; |
| } |
| |
| entry.remove(); |
| } |
| |
| // Update consumed bytes for flow control. |
| self.flow_control.add_consumed(len as u64); |
| |
| Ok((len, self.is_fin())) |
| } |
| |
| /// Resets the stream at the given offset. |
| pub fn reset(&mut self, error_code: u64, final_size: u64) -> Result<usize> { |
| // Stream's size is already known, forbid changing it. |
| if let Some(fin_off) = self.fin_off { |
| if fin_off != final_size { |
| return Err(Error::FinalSize); |
| } |
| } |
| |
| // Stream's known size is lower than data already received. |
| if final_size < self.len { |
| return Err(Error::FinalSize); |
| } |
| |
| // Calculate how many bytes need to be removed from the connection flow |
| // control. |
| let max_data_delta = final_size - self.len; |
| |
| if self.error.is_some() { |
| return Ok(max_data_delta as usize); |
| } |
| |
| self.error = Some(error_code); |
| |
| // Clear all data already buffered. |
| self.off = final_size; |
| |
| self.data.clear(); |
| |
| // In order to ensure the application is notified when the stream is |
| // reset, enqueue a zero-length buffer at the final size offset. |
| let buf = RangeBuf::from(b"", final_size, true); |
| self.write(buf)?; |
| |
| Ok(max_data_delta as usize) |
| } |
| |
| /// Commits the new max_data limit. |
| pub fn update_max_data(&mut self, now: time::Instant) { |
| self.flow_control.update_max_data(now); |
| } |
| |
| /// Return the new max_data limit. |
| pub fn max_data_next(&mut self) -> u64 { |
| self.flow_control.max_data_next() |
| } |
| |
| /// Return the current flow control limit. |
| pub fn max_data(&self) -> u64 { |
| self.flow_control.max_data() |
| } |
| |
| /// Return the current window. |
| pub fn window(&self) -> u64 { |
| self.flow_control.window() |
| } |
| |
| /// Autotune the window size. |
| pub fn autotune_window(&mut self, now: time::Instant, rtt: time::Duration) { |
| self.flow_control.autotune_window(now, rtt); |
| } |
| |
| /// Shuts down receiving data. |
| pub fn shutdown(&mut self) -> Result<()> { |
| if self.drain { |
| return Err(Error::Done); |
| } |
| |
| self.drain = true; |
| |
| self.data.clear(); |
| |
| self.off = self.max_off(); |
| |
| Ok(()) |
| } |
| |
| /// Returns the lowest offset of data buffered. |
| pub fn off_front(&self) -> u64 { |
| self.off |
| } |
| |
| /// Returns true if we need to update the local flow control limit. |
| pub fn almost_full(&self) -> bool { |
| self.fin_off.is_none() && self.flow_control.should_update_max_data() |
| } |
| |
| /// Returns the largest offset ever received. |
| pub fn max_off(&self) -> u64 { |
| self.len |
| } |
| |
| /// Returns true if the receive-side of the stream is complete. |
| /// |
| /// This happens when the stream's receive final size is known, and the |
| /// application has read all data from the stream. |
| pub fn is_fin(&self) -> bool { |
| if self.fin_off == Some(self.off) { |
| return true; |
| } |
| |
| false |
| } |
| |
| /// Returns true if the stream is not storing incoming data. |
| pub fn is_draining(&self) -> bool { |
| self.drain |
| } |
| |
| /// Returns true if the stream has data to be read. |
| pub fn ready(&self) -> bool { |
| let (_, buf) = match self.data.first_key_value() { |
| Some(v) => v, |
| None => return false, |
| }; |
| |
| buf.off() == self.off |
| } |
| } |
| |
| #[cfg(test)] |
| mod tests { |
| use super::*; |
| |
| #[test] |
| fn empty_read() { |
| let mut recv = RecvBuf::new(u64::MAX, DEFAULT_STREAM_WINDOW); |
| assert_eq!(recv.len, 0); |
| |
| let mut buf = [0; 32]; |
| |
| assert_eq!(recv.emit(&mut buf), Err(Error::Done)); |
| } |
| |
| #[test] |
| fn empty_stream_frame() { |
| let mut recv = RecvBuf::new(15, DEFAULT_STREAM_WINDOW); |
| assert_eq!(recv.len, 0); |
| |
| let buf = RangeBuf::from(b"hello", 0, false); |
| assert!(recv.write(buf).is_ok()); |
| assert_eq!(recv.len, 5); |
| assert_eq!(recv.off, 0); |
| assert_eq!(recv.data.len(), 1); |
| |
| let mut buf = [0; 32]; |
| assert_eq!(recv.emit(&mut buf), Ok((5, false))); |
| |
| // Don't store non-fin empty buffer. |
| let buf = RangeBuf::from(b"", 10, false); |
| assert!(recv.write(buf).is_ok()); |
| assert_eq!(recv.len, 5); |
| assert_eq!(recv.off, 5); |
| assert_eq!(recv.data.len(), 0); |
| |
| // Check flow control for empty buffer. |
| let buf = RangeBuf::from(b"", 16, false); |
| assert_eq!(recv.write(buf), Err(Error::FlowControl)); |
| |
| // Store fin empty buffer. |
| let buf = RangeBuf::from(b"", 5, true); |
| assert!(recv.write(buf).is_ok()); |
| assert_eq!(recv.len, 5); |
| assert_eq!(recv.off, 5); |
| assert_eq!(recv.data.len(), 1); |
| |
| // Don't store additional fin empty buffers. |
| let buf = RangeBuf::from(b"", 5, true); |
| assert!(recv.write(buf).is_ok()); |
| assert_eq!(recv.len, 5); |
| assert_eq!(recv.off, 5); |
| assert_eq!(recv.data.len(), 1); |
| |
| // Don't store additional fin non-empty buffers. |
| let buf = RangeBuf::from(b"aa", 3, true); |
| assert!(recv.write(buf).is_ok()); |
| assert_eq!(recv.len, 5); |
| assert_eq!(recv.off, 5); |
| assert_eq!(recv.data.len(), 1); |
| |
| // Validate final size with fin empty buffers. |
| let buf = RangeBuf::from(b"", 6, true); |
| assert_eq!(recv.write(buf), Err(Error::FinalSize)); |
| let buf = RangeBuf::from(b"", 4, true); |
| assert_eq!(recv.write(buf), Err(Error::FinalSize)); |
| |
| let mut buf = [0; 32]; |
| assert_eq!(recv.emit(&mut buf), Ok((0, true))); |
| } |
| |
| #[test] |
| fn ordered_read() { |
| let mut recv = RecvBuf::new(u64::MAX, DEFAULT_STREAM_WINDOW); |
| assert_eq!(recv.len, 0); |
| |
| let mut buf = [0; 32]; |
| |
| let first = RangeBuf::from(b"hello", 0, false); |
| let second = RangeBuf::from(b"world", 5, false); |
| let third = RangeBuf::from(b"something", 10, true); |
| |
| assert!(recv.write(second).is_ok()); |
| assert_eq!(recv.len, 10); |
| assert_eq!(recv.off, 0); |
| |
| assert_eq!(recv.emit(&mut buf), Err(Error::Done)); |
| |
| assert!(recv.write(third).is_ok()); |
| assert_eq!(recv.len, 19); |
| assert_eq!(recv.off, 0); |
| |
| assert_eq!(recv.emit(&mut buf), Err(Error::Done)); |
| |
| assert!(recv.write(first).is_ok()); |
| assert_eq!(recv.len, 19); |
| assert_eq!(recv.off, 0); |
| |
| let (len, fin) = recv.emit(&mut buf).unwrap(); |
| assert_eq!(len, 19); |
| assert!(fin); |
| assert_eq!(&buf[..len], b"helloworldsomething"); |
| assert_eq!(recv.len, 19); |
| assert_eq!(recv.off, 19); |
| |
| assert_eq!(recv.emit(&mut buf), Err(Error::Done)); |
| } |
| |
| #[test] |
| fn split_read() { |
| let mut recv = RecvBuf::new(u64::MAX, DEFAULT_STREAM_WINDOW); |
| assert_eq!(recv.len, 0); |
| |
| let mut buf = [0; 32]; |
| |
| let first = RangeBuf::from(b"something", 0, false); |
| let second = RangeBuf::from(b"helloworld", 9, true); |
| |
| assert!(recv.write(first).is_ok()); |
| assert_eq!(recv.len, 9); |
| assert_eq!(recv.off, 0); |
| |
| assert!(recv.write(second).is_ok()); |
| assert_eq!(recv.len, 19); |
| assert_eq!(recv.off, 0); |
| |
| let (len, fin) = recv.emit(&mut buf[..10]).unwrap(); |
| assert_eq!(len, 10); |
| assert!(!fin); |
| assert_eq!(&buf[..len], b"somethingh"); |
| assert_eq!(recv.len, 19); |
| assert_eq!(recv.off, 10); |
| |
| let (len, fin) = recv.emit(&mut buf[..5]).unwrap(); |
| assert_eq!(len, 5); |
| assert!(!fin); |
| assert_eq!(&buf[..len], b"ellow"); |
| assert_eq!(recv.len, 19); |
| assert_eq!(recv.off, 15); |
| |
| let (len, fin) = recv.emit(&mut buf[..10]).unwrap(); |
| assert_eq!(len, 4); |
| assert!(fin); |
| assert_eq!(&buf[..len], b"orld"); |
| assert_eq!(recv.len, 19); |
| assert_eq!(recv.off, 19); |
| } |
| |
| #[test] |
| fn incomplete_read() { |
| let mut recv = RecvBuf::new(u64::MAX, DEFAULT_STREAM_WINDOW); |
| assert_eq!(recv.len, 0); |
| |
| let mut buf = [0; 32]; |
| |
| let first = RangeBuf::from(b"something", 0, false); |
| let second = RangeBuf::from(b"helloworld", 9, true); |
| |
| assert!(recv.write(second).is_ok()); |
| assert_eq!(recv.len, 19); |
| assert_eq!(recv.off, 0); |
| |
| assert_eq!(recv.emit(&mut buf), Err(Error::Done)); |
| |
| assert!(recv.write(first).is_ok()); |
| assert_eq!(recv.len, 19); |
| assert_eq!(recv.off, 0); |
| |
| let (len, fin) = recv.emit(&mut buf).unwrap(); |
| assert_eq!(len, 19); |
| assert!(fin); |
| assert_eq!(&buf[..len], b"somethinghelloworld"); |
| assert_eq!(recv.len, 19); |
| assert_eq!(recv.off, 19); |
| } |
| |
| #[test] |
| fn zero_len_read() { |
| let mut recv = RecvBuf::new(u64::MAX, DEFAULT_STREAM_WINDOW); |
| assert_eq!(recv.len, 0); |
| |
| let mut buf = [0; 32]; |
| |
| let first = RangeBuf::from(b"something", 0, false); |
| let second = RangeBuf::from(b"", 9, true); |
| |
| assert!(recv.write(first).is_ok()); |
| assert_eq!(recv.len, 9); |
| assert_eq!(recv.off, 0); |
| assert_eq!(recv.data.len(), 1); |
| |
| assert!(recv.write(second).is_ok()); |
| assert_eq!(recv.len, 9); |
| assert_eq!(recv.off, 0); |
| assert_eq!(recv.data.len(), 1); |
| |
| let (len, fin) = recv.emit(&mut buf).unwrap(); |
| assert_eq!(len, 9); |
| assert!(fin); |
| assert_eq!(&buf[..len], b"something"); |
| assert_eq!(recv.len, 9); |
| assert_eq!(recv.off, 9); |
| } |
| |
| #[test] |
| fn past_read() { |
| let mut recv = RecvBuf::new(u64::MAX, DEFAULT_STREAM_WINDOW); |
| assert_eq!(recv.len, 0); |
| |
| let mut buf = [0; 32]; |
| |
| let first = RangeBuf::from(b"something", 0, false); |
| let second = RangeBuf::from(b"hello", 3, false); |
| let third = RangeBuf::from(b"ello", 4, true); |
| let fourth = RangeBuf::from(b"ello", 5, true); |
| |
| assert!(recv.write(first).is_ok()); |
| assert_eq!(recv.len, 9); |
| assert_eq!(recv.off, 0); |
| assert_eq!(recv.data.len(), 1); |
| |
| let (len, fin) = recv.emit(&mut buf).unwrap(); |
| assert_eq!(len, 9); |
| assert!(!fin); |
| assert_eq!(&buf[..len], b"something"); |
| assert_eq!(recv.len, 9); |
| assert_eq!(recv.off, 9); |
| |
| assert!(recv.write(second).is_ok()); |
| assert_eq!(recv.len, 9); |
| assert_eq!(recv.off, 9); |
| assert_eq!(recv.data.len(), 0); |
| |
| assert_eq!(recv.write(third), Err(Error::FinalSize)); |
| |
| assert!(recv.write(fourth).is_ok()); |
| assert_eq!(recv.len, 9); |
| assert_eq!(recv.off, 9); |
| assert_eq!(recv.data.len(), 0); |
| |
| assert_eq!(recv.emit(&mut buf), Err(Error::Done)); |
| } |
| |
| #[test] |
| fn fully_overlapping_read() { |
| let mut recv = RecvBuf::new(u64::MAX, DEFAULT_STREAM_WINDOW); |
| assert_eq!(recv.len, 0); |
| |
| let mut buf = [0; 32]; |
| |
| let first = RangeBuf::from(b"something", 0, false); |
| let second = RangeBuf::from(b"hello", 4, false); |
| |
| assert!(recv.write(first).is_ok()); |
| assert_eq!(recv.len, 9); |
| assert_eq!(recv.off, 0); |
| assert_eq!(recv.data.len(), 1); |
| |
| assert!(recv.write(second).is_ok()); |
| assert_eq!(recv.len, 9); |
| assert_eq!(recv.off, 0); |
| assert_eq!(recv.data.len(), 1); |
| |
| let (len, fin) = recv.emit(&mut buf).unwrap(); |
| assert_eq!(len, 9); |
| assert!(!fin); |
| assert_eq!(&buf[..len], b"something"); |
| assert_eq!(recv.len, 9); |
| assert_eq!(recv.off, 9); |
| assert_eq!(recv.data.len(), 0); |
| |
| assert_eq!(recv.emit(&mut buf), Err(Error::Done)); |
| } |
| |
| #[test] |
| fn fully_overlapping_read2() { |
| let mut recv = RecvBuf::new(u64::MAX, DEFAULT_STREAM_WINDOW); |
| assert_eq!(recv.len, 0); |
| |
| let mut buf = [0; 32]; |
| |
| let first = RangeBuf::from(b"something", 0, false); |
| let second = RangeBuf::from(b"hello", 4, false); |
| |
| assert!(recv.write(second).is_ok()); |
| assert_eq!(recv.len, 9); |
| assert_eq!(recv.off, 0); |
| assert_eq!(recv.data.len(), 1); |
| |
| assert!(recv.write(first).is_ok()); |
| assert_eq!(recv.len, 9); |
| assert_eq!(recv.off, 0); |
| assert_eq!(recv.data.len(), 2); |
| |
| let (len, fin) = recv.emit(&mut buf).unwrap(); |
| assert_eq!(len, 9); |
| assert!(!fin); |
| assert_eq!(&buf[..len], b"somehello"); |
| assert_eq!(recv.len, 9); |
| assert_eq!(recv.off, 9); |
| assert_eq!(recv.data.len(), 0); |
| |
| assert_eq!(recv.emit(&mut buf), Err(Error::Done)); |
| } |
| |
| #[test] |
| fn fully_overlapping_read3() { |
| let mut recv = RecvBuf::new(u64::MAX, DEFAULT_STREAM_WINDOW); |
| assert_eq!(recv.len, 0); |
| |
| let mut buf = [0; 32]; |
| |
| let first = RangeBuf::from(b"something", 0, false); |
| let second = RangeBuf::from(b"hello", 3, false); |
| |
| assert!(recv.write(second).is_ok()); |
| assert_eq!(recv.len, 8); |
| assert_eq!(recv.off, 0); |
| assert_eq!(recv.data.len(), 1); |
| |
| assert!(recv.write(first).is_ok()); |
| assert_eq!(recv.len, 9); |
| assert_eq!(recv.off, 0); |
| assert_eq!(recv.data.len(), 3); |
| |
| let (len, fin) = recv.emit(&mut buf).unwrap(); |
| assert_eq!(len, 9); |
| assert!(!fin); |
| assert_eq!(&buf[..len], b"somhellog"); |
| assert_eq!(recv.len, 9); |
| assert_eq!(recv.off, 9); |
| assert_eq!(recv.data.len(), 0); |
| |
| assert_eq!(recv.emit(&mut buf), Err(Error::Done)); |
| } |
| |
| #[test] |
| fn fully_overlapping_read_multi() { |
| let mut recv = RecvBuf::new(u64::MAX, DEFAULT_STREAM_WINDOW); |
| assert_eq!(recv.len, 0); |
| |
| let mut buf = [0; 32]; |
| |
| let first = RangeBuf::from(b"somethingsomething", 0, false); |
| let second = RangeBuf::from(b"hello", 3, false); |
| let third = RangeBuf::from(b"hello", 12, false); |
| |
| assert!(recv.write(second).is_ok()); |
| assert_eq!(recv.len, 8); |
| assert_eq!(recv.off, 0); |
| assert_eq!(recv.data.len(), 1); |
| |
| assert!(recv.write(third).is_ok()); |
| assert_eq!(recv.len, 17); |
| assert_eq!(recv.off, 0); |
| assert_eq!(recv.data.len(), 2); |
| |
| assert!(recv.write(first).is_ok()); |
| assert_eq!(recv.len, 18); |
| assert_eq!(recv.off, 0); |
| assert_eq!(recv.data.len(), 5); |
| |
| let (len, fin) = recv.emit(&mut buf).unwrap(); |
| assert_eq!(len, 18); |
| assert!(!fin); |
| assert_eq!(&buf[..len], b"somhellogsomhellog"); |
| assert_eq!(recv.len, 18); |
| assert_eq!(recv.off, 18); |
| assert_eq!(recv.data.len(), 0); |
| |
| assert_eq!(recv.emit(&mut buf), Err(Error::Done)); |
| } |
| |
| #[test] |
| fn overlapping_start_read() { |
| let mut recv = RecvBuf::new(u64::MAX, DEFAULT_STREAM_WINDOW); |
| assert_eq!(recv.len, 0); |
| |
| let mut buf = [0; 32]; |
| |
| let first = RangeBuf::from(b"something", 0, false); |
| let second = RangeBuf::from(b"hello", 8, true); |
| |
| assert!(recv.write(first).is_ok()); |
| assert_eq!(recv.len, 9); |
| assert_eq!(recv.off, 0); |
| assert_eq!(recv.data.len(), 1); |
| |
| assert!(recv.write(second).is_ok()); |
| assert_eq!(recv.len, 13); |
| assert_eq!(recv.off, 0); |
| assert_eq!(recv.data.len(), 2); |
| |
| let (len, fin) = recv.emit(&mut buf).unwrap(); |
| assert_eq!(len, 13); |
| assert!(fin); |
| assert_eq!(&buf[..len], b"somethingello"); |
| assert_eq!(recv.len, 13); |
| assert_eq!(recv.off, 13); |
| |
| assert_eq!(recv.emit(&mut buf), Err(Error::Done)); |
| } |
| |
| #[test] |
| fn overlapping_end_read() { |
| let mut recv = RecvBuf::new(u64::MAX, DEFAULT_STREAM_WINDOW); |
| assert_eq!(recv.len, 0); |
| |
| let mut buf = [0; 32]; |
| |
| let first = RangeBuf::from(b"hello", 0, false); |
| let second = RangeBuf::from(b"something", 3, true); |
| |
| assert!(recv.write(second).is_ok()); |
| assert_eq!(recv.len, 12); |
| assert_eq!(recv.off, 0); |
| assert_eq!(recv.data.len(), 1); |
| |
| assert!(recv.write(first).is_ok()); |
| assert_eq!(recv.len, 12); |
| assert_eq!(recv.off, 0); |
| assert_eq!(recv.data.len(), 2); |
| |
| let (len, fin) = recv.emit(&mut buf).unwrap(); |
| assert_eq!(len, 12); |
| assert!(fin); |
| assert_eq!(&buf[..len], b"helsomething"); |
| assert_eq!(recv.len, 12); |
| assert_eq!(recv.off, 12); |
| |
| assert_eq!(recv.emit(&mut buf), Err(Error::Done)); |
| } |
| |
| #[test] |
| fn overlapping_end_twice_read() { |
| let mut recv = RecvBuf::new(u64::MAX, DEFAULT_STREAM_WINDOW); |
| assert_eq!(recv.len, 0); |
| |
| let mut buf = [0; 32]; |
| |
| let first = RangeBuf::from(b"he", 0, false); |
| let second = RangeBuf::from(b"ow", 4, false); |
| let third = RangeBuf::from(b"rl", 7, false); |
| let fourth = RangeBuf::from(b"helloworld", 0, true); |
| |
| assert!(recv.write(third).is_ok()); |
| assert_eq!(recv.len, 9); |
| assert_eq!(recv.off, 0); |
| assert_eq!(recv.data.len(), 1); |
| |
| assert!(recv.write(second).is_ok()); |
| assert_eq!(recv.len, 9); |
| assert_eq!(recv.off, 0); |
| assert_eq!(recv.data.len(), 2); |
| |
| assert!(recv.write(first).is_ok()); |
| assert_eq!(recv.len, 9); |
| assert_eq!(recv.off, 0); |
| assert_eq!(recv.data.len(), 3); |
| |
| assert!(recv.write(fourth).is_ok()); |
| assert_eq!(recv.len, 10); |
| assert_eq!(recv.off, 0); |
| assert_eq!(recv.data.len(), 6); |
| |
| let (len, fin) = recv.emit(&mut buf).unwrap(); |
| assert_eq!(len, 10); |
| assert!(fin); |
| assert_eq!(&buf[..len], b"helloworld"); |
| assert_eq!(recv.len, 10); |
| assert_eq!(recv.off, 10); |
| |
| assert_eq!(recv.emit(&mut buf), Err(Error::Done)); |
| } |
| |
| #[test] |
| fn overlapping_end_twice_and_contained_read() { |
| let mut recv = RecvBuf::new(u64::MAX, DEFAULT_STREAM_WINDOW); |
| assert_eq!(recv.len, 0); |
| |
| let mut buf = [0; 32]; |
| |
| let first = RangeBuf::from(b"hellow", 0, false); |
| let second = RangeBuf::from(b"barfoo", 10, true); |
| let third = RangeBuf::from(b"rl", 7, false); |
| let fourth = RangeBuf::from(b"elloworldbarfoo", 1, true); |
| |
| assert!(recv.write(third).is_ok()); |
| assert_eq!(recv.len, 9); |
| assert_eq!(recv.off, 0); |
| assert_eq!(recv.data.len(), 1); |
| |
| assert!(recv.write(second).is_ok()); |
| assert_eq!(recv.len, 16); |
| assert_eq!(recv.off, 0); |
| assert_eq!(recv.data.len(), 2); |
| |
| assert!(recv.write(first).is_ok()); |
| assert_eq!(recv.len, 16); |
| assert_eq!(recv.off, 0); |
| assert_eq!(recv.data.len(), 3); |
| |
| assert!(recv.write(fourth).is_ok()); |
| assert_eq!(recv.len, 16); |
| assert_eq!(recv.off, 0); |
| assert_eq!(recv.data.len(), 5); |
| |
| let (len, fin) = recv.emit(&mut buf).unwrap(); |
| assert_eq!(len, 16); |
| assert!(fin); |
| assert_eq!(&buf[..len], b"helloworldbarfoo"); |
| assert_eq!(recv.len, 16); |
| assert_eq!(recv.off, 16); |
| |
| assert_eq!(recv.emit(&mut buf), Err(Error::Done)); |
| } |
| |
| #[test] |
| fn partially_multi_overlapping_reordered_read() { |
| let mut recv = RecvBuf::new(u64::MAX, DEFAULT_STREAM_WINDOW); |
| assert_eq!(recv.len, 0); |
| |
| let mut buf = [0; 32]; |
| |
| let first = RangeBuf::from(b"hello", 8, false); |
| let second = RangeBuf::from(b"something", 0, false); |
| let third = RangeBuf::from(b"moar", 11, true); |
| |
| assert!(recv.write(first).is_ok()); |
| assert_eq!(recv.len, 13); |
| assert_eq!(recv.off, 0); |
| assert_eq!(recv.data.len(), 1); |
| |
| assert!(recv.write(second).is_ok()); |
| assert_eq!(recv.len, 13); |
| assert_eq!(recv.off, 0); |
| assert_eq!(recv.data.len(), 2); |
| |
| assert!(recv.write(third).is_ok()); |
| assert_eq!(recv.len, 15); |
| assert_eq!(recv.off, 0); |
| assert_eq!(recv.data.len(), 3); |
| |
| let (len, fin) = recv.emit(&mut buf).unwrap(); |
| assert_eq!(len, 15); |
| assert!(fin); |
| assert_eq!(&buf[..len], b"somethinhelloar"); |
| assert_eq!(recv.len, 15); |
| assert_eq!(recv.off, 15); |
| assert_eq!(recv.data.len(), 0); |
| |
| assert_eq!(recv.emit(&mut buf), Err(Error::Done)); |
| } |
| |
| #[test] |
| fn partially_multi_overlapping_reordered_read2() { |
| let mut recv = RecvBuf::new(u64::MAX, DEFAULT_STREAM_WINDOW); |
| assert_eq!(recv.len, 0); |
| |
| let mut buf = [0; 32]; |
| |
| let first = RangeBuf::from(b"aaa", 0, false); |
| let second = RangeBuf::from(b"bbb", 2, false); |
| let third = RangeBuf::from(b"ccc", 4, false); |
| let fourth = RangeBuf::from(b"ddd", 6, false); |
| let fifth = RangeBuf::from(b"eee", 9, false); |
| let sixth = RangeBuf::from(b"fff", 11, false); |
| |
| assert!(recv.write(second).is_ok()); |
| assert_eq!(recv.len, 5); |
| assert_eq!(recv.off, 0); |
| assert_eq!(recv.data.len(), 1); |
| |
| assert!(recv.write(fourth).is_ok()); |
| assert_eq!(recv.len, 9); |
| assert_eq!(recv.off, 0); |
| assert_eq!(recv.data.len(), 2); |
| |
| assert!(recv.write(third).is_ok()); |
| assert_eq!(recv.len, 9); |
| assert_eq!(recv.off, 0); |
| assert_eq!(recv.data.len(), 3); |
| |
| assert!(recv.write(first).is_ok()); |
| assert_eq!(recv.len, 9); |
| assert_eq!(recv.off, 0); |
| assert_eq!(recv.data.len(), 4); |
| |
| assert!(recv.write(sixth).is_ok()); |
| assert_eq!(recv.len, 14); |
| assert_eq!(recv.off, 0); |
| assert_eq!(recv.data.len(), 5); |
| |
| assert!(recv.write(fifth).is_ok()); |
| assert_eq!(recv.len, 14); |
| assert_eq!(recv.off, 0); |
| assert_eq!(recv.data.len(), 6); |
| |
| let (len, fin) = recv.emit(&mut buf).unwrap(); |
| assert_eq!(len, 14); |
| assert!(!fin); |
| assert_eq!(&buf[..len], b"aabbbcdddeefff"); |
| assert_eq!(recv.len, 14); |
| assert_eq!(recv.off, 14); |
| assert_eq!(recv.data.len(), 0); |
| |
| assert_eq!(recv.emit(&mut buf), Err(Error::Done)); |
| } |
| } |