1use std::collections::hash_map::Entry;
2use std::mem;
3
4use thiserror::Error;
5use tracing::debug;
6
7use super::state::get_or_insert_recv;
8use super::{ClosedStream, Retransmits, ShouldTransmit, StreamId, StreamsState};
9use crate::connection::assembler::{Assembler, Chunk, IllegalOrderedRead};
10use crate::connection::streams::state::StreamRecv;
11use crate::{TransportError, VarInt, frame};
12
13#[derive(Debug, Default)]
14pub(super) struct Recv {
15 state: RecvState,
17 pub(super) assembler: Assembler,
18 sent_max_stream_data: u64,
19 pub(super) end: u64,
20 pub(super) stopped: bool,
21}
22
23impl Recv {
24 pub(super) fn new(initial_max_data: u64) -> Box<Self> {
25 Box::new(Self {
26 state: RecvState::default(),
27 assembler: Assembler::new(),
28 sent_max_stream_data: initial_max_data,
29 end: 0,
30 stopped: false,
31 })
32 }
33
34 pub(super) fn reinit(&mut self, initial_max_data: u64) {
36 self.state = RecvState::default();
37 self.assembler.reinit();
38 self.sent_max_stream_data = initial_max_data;
39 self.end = 0;
40 self.stopped = false;
41 }
42
43 pub(super) fn ingest(
47 &mut self,
48 frame: frame::Stream,
49 payload_len: usize,
50 received: u64,
51 max_data: u64,
52 ) -> Result<(u64, bool), TransportError> {
53 let end = frame.offset + frame.data.len() as u64;
54 if end >= 2u64.pow(62) {
55 return Err(TransportError::FLOW_CONTROL_ERROR(
56 "maximum stream offset too large",
57 ));
58 }
59
60 if let Some(final_offset) = self.final_offset() {
61 if end > final_offset || (frame.fin && end != final_offset) {
62 debug!(end, final_offset, "final size error");
63 return Err(TransportError::FINAL_SIZE_ERROR(""));
64 }
65 }
66
67 let new_bytes = self.credit_consumed_by(end, received, max_data)?;
68
69 if frame.fin && !self.stopped {
72 if let RecvState::Recv { ref mut size } = self.state {
73 *size = Some(end);
74 }
75 }
76
77 self.end = self.end.max(end);
78 if !self.stopped {
81 self.assembler
82 .insert(frame.offset, frame.data, payload_len)
83 .map_err(|_| TransportError::INTERNAL_ERROR("too many gaps in stream buffer"))?;
84 }
85
86 Ok((new_bytes, frame.fin && self.stopped))
87 }
88
89 pub(super) fn stop(&mut self) -> Result<(u64, ShouldTransmit), ClosedStream> {
90 if self.stopped {
91 return Err(ClosedStream { _private: () });
92 }
93
94 self.stopped = true;
95 self.assembler.clear();
96 let read_credits = self.end - self.assembler.bytes_read();
98 Ok((read_credits, ShouldTransmit(self.is_receiving())))
103 }
104
105 pub(super) fn max_stream_data(&mut self, stream_receive_window: u64) -> (u64, ShouldTransmit) {
113 let max_stream_data = self.assembler.bytes_read() + stream_receive_window;
114
115 let diff = max_stream_data - self.sent_max_stream_data;
123 let transmit = self.can_send_flow_control() && diff >= (stream_receive_window / 8);
124 (max_stream_data, ShouldTransmit(transmit))
125 }
126
127 pub(super) fn record_sent_max_stream_data(&mut self, sent_value: u64) {
133 if sent_value > self.sent_max_stream_data {
134 self.sent_max_stream_data = sent_value;
135 }
136 }
137
138 pub(super) fn final_offset_unknown(&self) -> bool {
146 matches!(self.state, RecvState::Recv { size: None })
147 }
148
149 pub(super) fn can_send_flow_control(&self) -> bool {
151 self.final_offset_unknown() && !self.stopped
154 }
155
156 pub(super) fn is_receiving(&self) -> bool {
158 matches!(self.state, RecvState::Recv { .. })
159 }
160
161 fn final_offset(&self) -> Option<u64> {
162 match self.state {
163 RecvState::Recv { size } => size,
164 RecvState::ResetRecvd { size, .. } => Some(size),
165 }
166 }
167
168 pub(super) fn reset(
170 &mut self,
171 error_code: VarInt,
172 final_offset: VarInt,
173 received: u64,
174 max_data: u64,
175 ) -> Result<bool, TransportError> {
176 if let Some(offset) = self.final_offset() {
178 if offset != final_offset.into_inner() {
179 return Err(TransportError::FINAL_SIZE_ERROR("inconsistent value"));
180 }
181 } else if self.end > u64::from(final_offset) {
182 return Err(TransportError::FINAL_SIZE_ERROR(
183 "lower than high water mark",
184 ));
185 }
186 self.credit_consumed_by(final_offset.into(), received, max_data)?;
187
188 if matches!(self.state, RecvState::ResetRecvd { .. }) {
189 return Ok(false);
190 }
191 self.state = RecvState::ResetRecvd {
192 size: final_offset.into(),
193 error_code,
194 };
195 self.assembler.clear();
200 Ok(true)
201 }
202
203 pub(super) fn reset_code(&self) -> Option<VarInt> {
204 match self.state {
205 RecvState::ResetRecvd { error_code, .. } => Some(error_code),
206 _ => None,
207 }
208 }
209
210 fn credit_consumed_by(
213 &self,
214 offset: u64,
215 received: u64,
216 max_data: u64,
217 ) -> Result<u64, TransportError> {
218 let prev_end = self.end;
219 let new_bytes = offset.saturating_sub(prev_end);
220 if offset > self.sent_max_stream_data || received + new_bytes > max_data {
221 debug!(
222 received,
223 new_bytes,
224 max_data,
225 offset,
226 stream_max_data = self.sent_max_stream_data,
227 "flow control error"
228 );
229 return Err(TransportError::FLOW_CONTROL_ERROR(""));
230 }
231
232 Ok(new_bytes)
233 }
234}
235
236pub struct Chunks<'a> {
248 id: StreamId,
249 ordered: bool,
250 streams: &'a mut StreamsState,
251 pending: &'a mut Retransmits,
252 state: ChunksState,
253 read: u64,
254}
255
256impl<'a> Chunks<'a> {
257 pub(super) fn new(
258 id: StreamId,
259 ordered: bool,
260 streams: &'a mut StreamsState,
261 pending: &'a mut Retransmits,
262 ) -> Result<Self, ReadableError> {
263 let mut entry = match streams.recv.entry(id) {
264 Entry::Occupied(entry) => entry,
265 Entry::Vacant(_) => return Err(ReadableError::ClosedStream),
266 };
267
268 let mut recv =
269 match get_or_insert_recv(streams.stream_receive_window)(entry.get_mut()).stopped {
270 true => return Err(ReadableError::ClosedStream),
271 false => entry.remove().unwrap().into_inner(), };
273
274 recv.assembler.ensure_ordering(ordered)?;
275 Ok(Self {
276 id,
277 ordered,
278 streams,
279 pending,
280 state: ChunksState::Readable(recv),
281 read: 0,
282 })
283 }
284
285 pub fn next(&mut self, max_length: usize) -> Result<Option<Chunk>, ReadError> {
289 let rs = match self.state {
290 ChunksState::Readable(ref mut rs) => rs,
291 ChunksState::Reset(error_code) => {
292 return Err(ReadError::Reset(error_code));
293 }
294 ChunksState::Finished => {
295 return Ok(None);
296 }
297 ChunksState::Finalized => panic!("must not call next() after finalize()"),
298 };
299
300 if let Some(chunk) = rs.assembler.read(max_length, self.ordered) {
301 self.read += chunk.bytes.len() as u64;
302 return Ok(Some(chunk));
303 }
304
305 match rs.state {
306 RecvState::ResetRecvd { error_code, .. } => {
307 debug_assert_eq!(self.read, 0, "reset streams have empty buffers");
308 let state = mem::replace(&mut self.state, ChunksState::Reset(error_code));
309 let recv = match state {
311 ChunksState::Readable(recv) => StreamRecv::Open(recv),
312 _ => unreachable!("state must be ChunkState::Readable"),
313 };
314 self.streams.stream_recv_freed(self.id, recv);
315 Err(ReadError::Reset(error_code))
316 }
317 RecvState::Recv { size } => {
318 if size == Some(rs.end) && rs.assembler.bytes_read() == rs.end {
319 let state = mem::replace(&mut self.state, ChunksState::Finished);
320 let recv = match state {
322 ChunksState::Readable(recv) => StreamRecv::Open(recv),
323 _ => unreachable!("state must be ChunkState::Readable"),
324 };
325 self.streams.stream_recv_freed(self.id, recv);
326 Ok(None)
327 } else {
328 Err(ReadError::Blocked)
333 }
334 }
335 }
336 }
337
338 pub fn finalize(mut self) -> ShouldTransmit {
348 self.finalize_inner()
349 }
350
351 fn finalize_inner(&mut self) -> ShouldTransmit {
352 let state = mem::replace(&mut self.state, ChunksState::Finalized);
353 if let ChunksState::Finalized = state {
354 return ShouldTransmit(false);
356 }
357
358 let mut should_transmit = self.streams.queue_max_stream_id(self.pending);
362
363 if let ChunksState::Readable(mut rs) = state {
365 let (_, max_stream_data) = rs.max_stream_data(self.streams.stream_receive_window);
366 should_transmit |= max_stream_data.0;
367 if max_stream_data.0 {
368 self.pending.max_stream_data.insert(self.id);
369 }
370 self.streams
372 .recv
373 .insert(self.id, Some(StreamRecv::Open(rs)));
374 }
375
376 let max_data = self.streams.add_read_credits(self.read);
378 self.pending.max_data |= max_data.0;
379 should_transmit |= max_data.0;
380 ShouldTransmit(should_transmit)
381 }
382}
383
384impl Drop for Chunks<'_> {
385 fn drop(&mut self) {
386 let _ = self.finalize_inner();
387 }
388}
389
390enum ChunksState {
391 Readable(Box<Recv>),
392 Reset(VarInt),
393 Finished,
394 Finalized,
395}
396
397#[derive(Debug, Error, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
399pub enum ReadError {
400 #[error("blocked")]
405 Blocked,
406 #[error("reset by peer: code {0}")]
410 Reset(VarInt),
411}
412
413#[derive(Debug, Error, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
415pub enum ReadableError {
416 #[error("closed stream")]
418 ClosedStream,
419 #[error("ordered read after unordered read")]
424 IllegalOrderedRead,
425}
426
427impl From<IllegalOrderedRead> for ReadableError {
428 fn from(_: IllegalOrderedRead) -> Self {
429 Self::IllegalOrderedRead
430 }
431}
432
433#[derive(Debug, Copy, Clone, Eq, PartialEq)]
434enum RecvState {
435 Recv { size: Option<u64> },
436 ResetRecvd { size: u64, error_code: VarInt },
437}
438
439impl Default for RecvState {
440 fn default() -> Self {
441 Self::Recv { size: None }
442 }
443}
444
445#[cfg(test)]
446mod tests {
447 use bytes::Bytes;
448
449 use crate::{Dir, Side};
450
451 use super::*;
452
453 #[test]
454 fn reordered_frames_while_stopped() {
455 const INITIAL_BYTES: u64 = 3;
456 const INITIAL_OFFSET: u64 = 3;
457 const RECV_WINDOW: u64 = 8;
458 let mut s = Recv::new(RECV_WINDOW);
459 let mut data_recvd = 0;
460 let (new_bytes, is_closed) = s
462 .ingest(
463 frame::Stream {
464 id: StreamId::new(Side::Client, Dir::Uni, 0),
465 offset: INITIAL_OFFSET,
466 fin: false,
467 data: Bytes::from_static(&[0; INITIAL_BYTES as usize]),
468 },
469 123,
470 data_recvd,
471 data_recvd + 1024,
472 )
473 .unwrap();
474 data_recvd += new_bytes;
475 assert_eq!(new_bytes, INITIAL_OFFSET + INITIAL_BYTES);
476 assert!(!is_closed);
477
478 let (credits, transmit) = s.stop().unwrap();
479 assert!(transmit.should_transmit());
480 assert_eq!(
481 credits,
482 INITIAL_OFFSET + INITIAL_BYTES,
483 "full connection flow control credit is issued by stop"
484 );
485
486 let (max_stream_data, transmit) = s.max_stream_data(RECV_WINDOW);
487 assert!(!transmit.should_transmit());
488 assert_eq!(
489 max_stream_data, RECV_WINDOW,
490 "stream flow control credit isn't issued by stop"
491 );
492
493 let (new_bytes, is_closed) = s
495 .ingest(
496 frame::Stream {
497 id: StreamId::new(Side::Client, Dir::Uni, 0),
498 offset: RECV_WINDOW - 1,
499 fin: false,
500 data: Bytes::from_static(&[0; 1]),
501 },
502 123,
503 data_recvd,
504 data_recvd + 1024,
505 )
506 .unwrap();
507 data_recvd += new_bytes;
508 assert_eq!(new_bytes, RECV_WINDOW - (INITIAL_OFFSET + INITIAL_BYTES));
509 assert!(!is_closed);
510
511 let (max_stream_data, transmit) = s.max_stream_data(RECV_WINDOW);
512 assert!(!transmit.should_transmit());
513 assert_eq!(
514 max_stream_data, RECV_WINDOW,
515 "stream flow control credit isn't issued after stop"
516 );
517
518 let (new_bytes, is_closed) = s
520 .ingest(
521 frame::Stream {
522 id: StreamId::new(Side::Client, Dir::Uni, 0),
523 offset: 0,
524 fin: false,
525 data: Bytes::from_static(&[0; INITIAL_OFFSET as usize]),
526 },
527 123,
528 data_recvd,
529 data_recvd + 1024,
530 )
531 .unwrap();
532 assert_eq!(
533 new_bytes, 0,
534 "reordered frames don't issue connection-level flow control for stopped streams"
535 );
536 assert!(!is_closed);
537
538 let (max_stream_data, transmit) = s.max_stream_data(RECV_WINDOW);
539 assert!(!transmit.should_transmit());
540 assert_eq!(
541 max_stream_data, RECV_WINDOW,
542 "stream flow control credit isn't issued after stop"
543 );
544 }
545}