1use std::collections::hash_map::Entry;
9use std::mem;
10
11use thiserror::Error;
12use tracing::debug;
13
14use super::state::get_or_insert_recv;
15use super::{ClosedStream, Retransmits, ShouldTransmit, StreamId, StreamsState};
16use crate::connection::assembler::{Assembler, Chunk, IllegalOrderedRead};
17use crate::connection::streams::state::StreamRecv;
18use crate::{TransportError, VarInt, frame};
19
20#[derive(Debug, Default)]
21pub(super) struct Recv {
22 state: RecvState,
24 pub(super) assembler: Assembler,
25 sent_max_stream_data: u64,
26 pub(super) end: u64,
27 pub(super) stopped: bool,
28}
29
30impl Recv {
31 pub(super) fn new(initial_max_data: u64) -> Box<Self> {
32 Box::new(Self {
33 state: RecvState::default(),
34 assembler: Assembler::new(),
35 sent_max_stream_data: initial_max_data,
36 end: 0,
37 stopped: false,
38 })
39 }
40
41 pub(super) fn reinit(&mut self, initial_max_data: u64) {
43 self.state = RecvState::default();
44 self.assembler.reinit();
45 self.sent_max_stream_data = initial_max_data;
46 self.end = 0;
47 self.stopped = false;
48 }
49
50 pub(super) fn ingest(
54 &mut self,
55 frame: frame::Stream,
56 payload_len: usize,
57 received: u64,
58 max_data: u64,
59 ) -> Result<(u64, bool), TransportError> {
60 let end = frame.offset + frame.data.len() as u64;
61 if end >= 2u64.pow(62) {
62 return Err(TransportError::FLOW_CONTROL_ERROR(
63 "maximum stream offset too large",
64 ));
65 }
66
67 if let Some(final_offset) = self.final_offset() {
68 if end > final_offset || (frame.fin && end != final_offset) {
69 debug!(end, final_offset, "final size error");
70 return Err(TransportError::FINAL_SIZE_ERROR(""));
71 }
72 }
73
74 let new_bytes = self.credit_consumed_by(end, received, max_data)?;
75
76 if frame.fin && !self.stopped {
79 if let RecvState::Recv { ref mut size } = self.state {
80 *size = Some(end);
81 }
82 }
83
84 self.end = self.end.max(end);
85 if !self.stopped {
88 self.assembler
89 .insert(frame.offset, frame.data, payload_len)
90 .map_err(|_| TransportError::INTERNAL_ERROR("too many gaps in stream buffer"))?;
91 }
92
93 Ok((new_bytes, frame.fin && self.stopped))
94 }
95
96 pub(super) fn stop(&mut self) -> Result<(u64, ShouldTransmit), ClosedStream> {
97 if self.stopped {
98 return Err(ClosedStream { _private: () });
99 }
100
101 self.stopped = true;
102 self.assembler.clear();
103 let read_credits = self.end - self.assembler.bytes_read();
105 Ok((read_credits, ShouldTransmit(self.is_receiving())))
110 }
111
112 pub(super) fn max_stream_data(&mut self, stream_receive_window: u64) -> (u64, ShouldTransmit) {
120 let max_stream_data = self.assembler.bytes_read() + stream_receive_window;
121
122 let diff = max_stream_data - self.sent_max_stream_data;
130 let transmit = self.can_send_flow_control() && diff >= (stream_receive_window / 8);
131 (max_stream_data, ShouldTransmit(transmit))
132 }
133
134 pub(super) fn record_sent_max_stream_data(&mut self, sent_value: u64) {
140 if sent_value > self.sent_max_stream_data {
141 self.sent_max_stream_data = sent_value;
142 }
143 }
144
145 pub(super) fn final_offset_unknown(&self) -> bool {
153 matches!(self.state, RecvState::Recv { size: None })
154 }
155
156 pub(super) fn can_send_flow_control(&self) -> bool {
158 self.final_offset_unknown() && !self.stopped
161 }
162
163 pub(super) fn is_receiving(&self) -> bool {
165 matches!(self.state, RecvState::Recv { .. })
166 }
167
168 fn final_offset(&self) -> Option<u64> {
169 match self.state {
170 RecvState::Recv { size } => size,
171 RecvState::ResetRecvd { size, .. } => Some(size),
172 }
173 }
174
175 pub(super) fn reset(
177 &mut self,
178 error_code: VarInt,
179 final_offset: VarInt,
180 received: u64,
181 max_data: u64,
182 ) -> Result<bool, TransportError> {
183 if let Some(offset) = self.final_offset() {
185 if offset != final_offset.into_inner() {
186 return Err(TransportError::FINAL_SIZE_ERROR("inconsistent value"));
187 }
188 } else if self.end > u64::from(final_offset) {
189 return Err(TransportError::FINAL_SIZE_ERROR(
190 "lower than high water mark",
191 ));
192 }
193 self.credit_consumed_by(final_offset.into(), received, max_data)?;
194
195 if matches!(self.state, RecvState::ResetRecvd { .. }) {
196 return Ok(false);
197 }
198 self.state = RecvState::ResetRecvd {
199 size: final_offset.into(),
200 error_code,
201 };
202 self.assembler.clear();
207 Ok(true)
208 }
209
210 pub(super) fn reset_code(&self) -> Option<VarInt> {
211 match self.state {
212 RecvState::ResetRecvd { error_code, .. } => Some(error_code),
213 _ => None,
214 }
215 }
216
217 fn credit_consumed_by(
220 &self,
221 offset: u64,
222 received: u64,
223 max_data: u64,
224 ) -> Result<u64, TransportError> {
225 let prev_end = self.end;
226 let new_bytes = offset.saturating_sub(prev_end);
227 if offset > self.sent_max_stream_data || received + new_bytes > max_data {
228 debug!(
229 received,
230 new_bytes,
231 max_data,
232 offset,
233 stream_max_data = self.sent_max_stream_data,
234 "flow control error"
235 );
236 return Err(TransportError::FLOW_CONTROL_ERROR(""));
237 }
238
239 Ok(new_bytes)
240 }
241}
242
243pub struct Chunks<'a> {
255 id: StreamId,
256 ordered: bool,
257 streams: &'a mut StreamsState,
258 pending: &'a mut Retransmits,
259 state: ChunksState,
260 read: u64,
261}
262
263impl<'a> Chunks<'a> {
264 pub(super) fn new(
265 id: StreamId,
266 ordered: bool,
267 streams: &'a mut StreamsState,
268 pending: &'a mut Retransmits,
269 ) -> Result<Self, ReadableError> {
270 let mut entry = match streams.recv.entry(id) {
271 Entry::Occupied(entry) => entry,
272 Entry::Vacant(_) => return Err(ReadableError::ClosedStream),
273 };
274
275 let mut recv =
276 match get_or_insert_recv(streams.stream_receive_window)(entry.get_mut()).stopped {
277 true => return Err(ReadableError::ClosedStream),
278 false => entry.remove().unwrap().into_inner(), };
280
281 recv.assembler.ensure_ordering(ordered)?;
282 Ok(Self {
283 id,
284 ordered,
285 streams,
286 pending,
287 state: ChunksState::Readable(recv),
288 read: 0,
289 })
290 }
291
292 pub fn next(&mut self, max_length: usize) -> Result<Option<Chunk>, ReadError> {
296 let rs = match self.state {
297 ChunksState::Readable(ref mut rs) => rs,
298 ChunksState::Reset(error_code) => {
299 return Err(ReadError::Reset(error_code));
300 }
301 ChunksState::Finished => {
302 return Ok(None);
303 }
304 ChunksState::Finalized => panic!("must not call next() after finalize()"),
305 };
306
307 if let Some(chunk) = rs.assembler.read(max_length, self.ordered) {
308 self.read += chunk.bytes.len() as u64;
309 return Ok(Some(chunk));
310 }
311
312 match rs.state {
313 RecvState::ResetRecvd { error_code, .. } => {
314 debug_assert_eq!(self.read, 0, "reset streams have empty buffers");
315 let state = mem::replace(&mut self.state, ChunksState::Reset(error_code));
316 let recv = match state {
318 ChunksState::Readable(recv) => StreamRecv::Open(recv),
319 _ => unreachable!("state must be ChunkState::Readable"),
320 };
321 self.streams.stream_recv_freed(self.id, recv);
322 Err(ReadError::Reset(error_code))
323 }
324 RecvState::Recv { size } => {
325 if size == Some(rs.end) && rs.assembler.bytes_read() == rs.end {
326 let state = mem::replace(&mut self.state, ChunksState::Finished);
327 let recv = match state {
329 ChunksState::Readable(recv) => StreamRecv::Open(recv),
330 _ => unreachable!("state must be ChunkState::Readable"),
331 };
332 self.streams.stream_recv_freed(self.id, recv);
333 Ok(None)
334 } else {
335 Err(ReadError::Blocked)
340 }
341 }
342 }
343 }
344
345 pub fn finalize(mut self) -> ShouldTransmit {
355 self.finalize_inner()
356 }
357
358 fn finalize_inner(&mut self) -> ShouldTransmit {
359 let state = mem::replace(&mut self.state, ChunksState::Finalized);
360 if let ChunksState::Finalized = state {
361 return ShouldTransmit(false);
363 }
364
365 let mut should_transmit = self.streams.queue_max_stream_id(self.pending);
369
370 if let ChunksState::Readable(mut rs) = state {
372 let (_, max_stream_data) = rs.max_stream_data(self.streams.stream_receive_window);
373 should_transmit |= max_stream_data.0;
374 if max_stream_data.0 {
375 self.pending.max_stream_data.insert(self.id);
376 }
377 self.streams
379 .recv
380 .insert(self.id, Some(StreamRecv::Open(rs)));
381 }
382
383 let max_data = self.streams.add_read_credits(self.read);
385 self.pending.max_data |= max_data.0;
386 should_transmit |= max_data.0;
387 ShouldTransmit(should_transmit)
388 }
389}
390
391impl Drop for Chunks<'_> {
392 fn drop(&mut self) {
393 let _ = self.finalize_inner();
394 }
395}
396
397enum ChunksState {
398 Readable(Box<Recv>),
399 Reset(VarInt),
400 Finished,
401 Finalized,
402}
403
404#[derive(Debug, Error, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
406pub enum ReadError {
407 #[error("blocked")]
412 Blocked,
413 #[error("reset by peer: code {0}")]
417 Reset(VarInt),
418 #[error("stream closed due to connection error")]
420 ConnectionClosed,
421}
422
423#[derive(Debug, Error, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
425pub enum ReadableError {
426 #[error("closed stream")]
428 ClosedStream,
429 #[error("ordered read after unordered read")]
434 IllegalOrderedRead,
435 #[error("stream closed due to connection error")]
437 ConnectionClosed,
438}
439
440impl From<IllegalOrderedRead> for ReadableError {
441 fn from(_: IllegalOrderedRead) -> Self {
442 Self::IllegalOrderedRead
443 }
444}
445
446#[derive(Debug, Copy, Clone, Eq, PartialEq)]
447enum RecvState {
448 Recv { size: Option<u64> },
449 ResetRecvd { size: u64, error_code: VarInt },
450}
451
452impl Default for RecvState {
453 fn default() -> Self {
454 Self::Recv { size: None }
455 }
456}
457
458#[cfg(test)]
459mod tests {
460 use bytes::Bytes;
461
462 use crate::{Dir, Side};
463
464 use super::*;
465
466 #[test]
467 fn reordered_frames_while_stopped() {
468 const INITIAL_BYTES: u64 = 3;
469 const INITIAL_OFFSET: u64 = 3;
470 const RECV_WINDOW: u64 = 8;
471 let mut s = Recv::new(RECV_WINDOW);
472 let mut data_recvd = 0;
473 let (new_bytes, is_closed) = s
475 .ingest(
476 frame::Stream {
477 id: StreamId::new(Side::Client, Dir::Uni, 0),
478 offset: INITIAL_OFFSET,
479 fin: false,
480 data: Bytes::from_static(&[0; INITIAL_BYTES as usize]),
481 },
482 123,
483 data_recvd,
484 data_recvd + 1024,
485 )
486 .unwrap();
487 data_recvd += new_bytes;
488 assert_eq!(new_bytes, INITIAL_OFFSET + INITIAL_BYTES);
489 assert!(!is_closed);
490
491 let (credits, transmit) = s.stop().unwrap();
492 assert!(transmit.should_transmit());
493 assert_eq!(
494 credits,
495 INITIAL_OFFSET + INITIAL_BYTES,
496 "full connection flow control credit is issued by stop"
497 );
498
499 let (max_stream_data, transmit) = s.max_stream_data(RECV_WINDOW);
500 assert!(!transmit.should_transmit());
501 assert_eq!(
502 max_stream_data, RECV_WINDOW,
503 "stream flow control credit isn't issued by stop"
504 );
505
506 let (new_bytes, is_closed) = s
508 .ingest(
509 frame::Stream {
510 id: StreamId::new(Side::Client, Dir::Uni, 0),
511 offset: RECV_WINDOW - 1,
512 fin: false,
513 data: Bytes::from_static(&[0; 1]),
514 },
515 123,
516 data_recvd,
517 data_recvd + 1024,
518 )
519 .unwrap();
520 data_recvd += new_bytes;
521 assert_eq!(new_bytes, RECV_WINDOW - (INITIAL_OFFSET + INITIAL_BYTES));
522 assert!(!is_closed);
523
524 let (max_stream_data, transmit) = s.max_stream_data(RECV_WINDOW);
525 assert!(!transmit.should_transmit());
526 assert_eq!(
527 max_stream_data, RECV_WINDOW,
528 "stream flow control credit isn't issued after stop"
529 );
530
531 let (new_bytes, is_closed) = s
533 .ingest(
534 frame::Stream {
535 id: StreamId::new(Side::Client, Dir::Uni, 0),
536 offset: 0,
537 fin: false,
538 data: Bytes::from_static(&[0; INITIAL_OFFSET as usize]),
539 },
540 123,
541 data_recvd,
542 data_recvd + 1024,
543 )
544 .unwrap();
545 assert_eq!(
546 new_bytes, 0,
547 "reordered frames don't issue connection-level flow control for stopped streams"
548 );
549 assert!(!is_closed);
550
551 let (max_stream_data, transmit) = s.max_stream_data(RECV_WINDOW);
552 assert!(!transmit.should_transmit());
553 assert_eq!(
554 max_stream_data, RECV_WINDOW,
555 "stream flow control credit isn't issued after stop"
556 );
557 }
558}