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 && (end > final_offset || (frame.fin && end != final_offset))
62 {
63 debug!(end, final_offset, "final size error");
64 return Err(TransportError::FINAL_SIZE_ERROR(""));
65 }
66
67 let new_bytes = self.credit_consumed_by(end, received, max_data)?;
68
69 if frame.fin
72 && !self.stopped
73 && let RecvState::Recv { ref mut size } = self.state
74 {
75 *size = Some(end);
76 }
77
78 self.end = self.end.max(end);
79 if !self.stopped {
82 self.assembler.insert(frame.offset, frame.data, payload_len);
83 }
84
85 Ok((new_bytes, frame.fin && self.stopped))
86 }
87
88 pub(super) fn stop(&mut self) -> Result<(u64, ShouldTransmit), ClosedStream> {
89 if self.stopped {
90 return Err(ClosedStream { _private: () });
91 }
92
93 self.stopped = true;
94 self.assembler.clear();
95 let read_credits = self.end - self.assembler.bytes_read();
97 Ok((read_credits, ShouldTransmit(self.is_receiving())))
102 }
103
104 pub(super) fn max_stream_data(&mut self, stream_receive_window: u64) -> (u64, ShouldTransmit) {
112 let max_stream_data = self.assembler.bytes_read() + stream_receive_window;
113
114 let diff = max_stream_data - self.sent_max_stream_data;
122 let transmit = self.can_send_flow_control() && diff >= (stream_receive_window / 8);
123 (max_stream_data, ShouldTransmit(transmit))
124 }
125
126 pub(super) fn record_sent_max_stream_data(&mut self, sent_value: u64) {
132 if sent_value > self.sent_max_stream_data {
133 self.sent_max_stream_data = sent_value;
134 }
135 }
136
137 pub(super) fn final_offset_unknown(&self) -> bool {
145 matches!(self.state, RecvState::Recv { size: None })
146 }
147
148 pub(super) fn can_send_flow_control(&self) -> bool {
150 self.final_offset_unknown() && !self.stopped
153 }
154
155 pub(super) fn is_receiving(&self) -> bool {
157 matches!(self.state, RecvState::Recv { .. })
158 }
159
160 fn final_offset(&self) -> Option<u64> {
161 match self.state {
162 RecvState::Recv { size } => size,
163 RecvState::ResetRecvd { size, .. } => Some(size),
164 }
165 }
166
167 pub(super) fn reset(
169 &mut self,
170 error_code: VarInt,
171 final_offset: VarInt,
172 received: u64,
173 max_data: u64,
174 ) -> Result<bool, TransportError> {
175 if let Some(offset) = self.final_offset() {
177 if offset != final_offset.into_inner() {
178 return Err(TransportError::FINAL_SIZE_ERROR("inconsistent value"));
179 }
180 } else if self.end > u64::from(final_offset) {
181 return Err(TransportError::FINAL_SIZE_ERROR(
182 "lower than high water mark",
183 ));
184 }
185 self.credit_consumed_by(final_offset.into(), received, max_data)?;
186
187 if matches!(self.state, RecvState::ResetRecvd { .. }) {
188 return Ok(false);
189 }
190 self.state = RecvState::ResetRecvd {
191 size: final_offset.into(),
192 error_code,
193 };
194 self.assembler.clear();
199 Ok(true)
200 }
201
202 pub(super) fn reset_code(&self) -> Option<VarInt> {
203 match self.state {
204 RecvState::ResetRecvd { error_code, .. } => Some(error_code),
205 _ => None,
206 }
207 }
208
209 fn credit_consumed_by(
212 &self,
213 offset: u64,
214 received: u64,
215 max_data: u64,
216 ) -> Result<u64, TransportError> {
217 let prev_end = self.end;
218 let new_bytes = offset.saturating_sub(prev_end);
219 if offset > self.sent_max_stream_data || received + new_bytes > max_data {
220 debug!(
221 received,
222 new_bytes,
223 max_data,
224 offset,
225 stream_max_data = self.sent_max_stream_data,
226 "flow control error"
227 );
228 return Err(TransportError::FLOW_CONTROL_ERROR(""));
229 }
230
231 Ok(new_bytes)
232 }
233}
234
235pub struct Chunks<'a> {
247 id: StreamId,
248 ordered: bool,
249 streams: &'a mut StreamsState,
250 pending: &'a mut Retransmits,
251 state: ChunksState,
252 read: u64,
253}
254
255impl<'a> Chunks<'a> {
256 pub(super) fn new(
257 id: StreamId,
258 ordered: bool,
259 streams: &'a mut StreamsState,
260 pending: &'a mut Retransmits,
261 ) -> Result<Self, ReadableError> {
262 let mut entry = match streams.recv.entry(id) {
263 Entry::Occupied(entry) => entry,
264 Entry::Vacant(_) => return Err(ReadableError::ClosedStream),
265 };
266
267 let mut recv =
268 match get_or_insert_recv(streams.stream_receive_window)(entry.get_mut()).stopped {
269 true => return Err(ReadableError::ClosedStream),
270 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 {
349 self.finalize_inner()
350 }
351
352 fn finalize_inner(&mut self) -> ShouldTransmit {
353 let state = mem::replace(&mut self.state, ChunksState::Finalized);
354 if let ChunksState::Finalized = state {
355 return ShouldTransmit(false);
357 }
358
359 let mut should_transmit = self.streams.queue_max_stream_id(self.pending);
363
364 if let ChunksState::Readable(mut rs) = state {
366 let (_, max_stream_data) = rs.max_stream_data(self.streams.stream_receive_window);
367 should_transmit |= max_stream_data.0;
368 if max_stream_data.0 {
369 self.pending.max_stream_data.insert(self.id);
370 }
371 self.streams
373 .recv
374 .insert(self.id, Some(StreamRecv::Open(rs)));
375 }
376
377 let max_data = self.streams.add_read_credits(self.read);
379 self.pending.max_data |= max_data.0;
380 should_transmit |= max_data.0;
381 ShouldTransmit(should_transmit)
382 }
383}
384
385impl Drop for Chunks<'_> {
386 fn drop(&mut self) {
387 let _ = self.finalize_inner();
388 }
389}
390
391enum ChunksState {
392 Readable(Box<Recv>),
393 Reset(VarInt),
394 Finished,
395 Finalized,
396}
397
398#[derive(Debug, Error, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
400pub enum ReadError {
401 #[error("blocked")]
406 Blocked,
407 #[error("reset by peer: code {0}")]
411 Reset(VarInt),
412}
413
414#[derive(Debug, Error, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
416pub enum ReadableError {
417 #[error("closed stream")]
419 ClosedStream,
420 #[error("ordered read after unordered read")]
425 IllegalOrderedRead,
426}
427
428impl From<IllegalOrderedRead> for ReadableError {
429 fn from(_: IllegalOrderedRead) -> Self {
430 Self::IllegalOrderedRead
431 }
432}
433
434#[derive(Debug, Copy, Clone, Eq, PartialEq)]
435enum RecvState {
436 Recv { size: Option<u64> },
437 ResetRecvd { size: u64, error_code: VarInt },
438}
439
440impl Default for RecvState {
441 fn default() -> Self {
442 Self::Recv { size: None }
443 }
444}
445
446#[cfg(test)]
447mod tests {
448 use bytes::Bytes;
449
450 use crate::{Dir, Side};
451
452 use super::*;
453
454 #[test]
455 fn reordered_frames_while_stopped() {
456 const INITIAL_BYTES: u64 = 3;
457 const INITIAL_OFFSET: u64 = 3;
458 const RECV_WINDOW: u64 = 8;
459 let mut s = Recv::new(RECV_WINDOW);
460 let mut data_recvd = 0;
461 let (new_bytes, is_closed) = s
463 .ingest(
464 frame::Stream {
465 id: StreamId::new(Side::Client, Dir::Uni, 0),
466 offset: INITIAL_OFFSET,
467 fin: false,
468 data: Bytes::from_static(&[0; INITIAL_BYTES as usize]),
469 },
470 123,
471 data_recvd,
472 data_recvd + 1024,
473 )
474 .unwrap();
475 data_recvd += new_bytes;
476 assert_eq!(new_bytes, INITIAL_OFFSET + INITIAL_BYTES);
477 assert!(!is_closed);
478
479 let (credits, transmit) = s.stop().unwrap();
480 assert!(transmit.should_transmit());
481 assert_eq!(
482 credits,
483 INITIAL_OFFSET + INITIAL_BYTES,
484 "full connection flow control credit is issued by stop"
485 );
486
487 let (max_stream_data, transmit) = s.max_stream_data(RECV_WINDOW);
488 assert!(!transmit.should_transmit());
489 assert_eq!(
490 max_stream_data, RECV_WINDOW,
491 "stream flow control credit isn't issued by stop"
492 );
493
494 let (new_bytes, is_closed) = s
496 .ingest(
497 frame::Stream {
498 id: StreamId::new(Side::Client, Dir::Uni, 0),
499 offset: RECV_WINDOW - 1,
500 fin: false,
501 data: Bytes::from_static(&[0; 1]),
502 },
503 123,
504 data_recvd,
505 data_recvd + 1024,
506 )
507 .unwrap();
508 data_recvd += new_bytes;
509 assert_eq!(new_bytes, RECV_WINDOW - (INITIAL_OFFSET + INITIAL_BYTES));
510 assert!(!is_closed);
511
512 let (max_stream_data, transmit) = s.max_stream_data(RECV_WINDOW);
513 assert!(!transmit.should_transmit());
514 assert_eq!(
515 max_stream_data, RECV_WINDOW,
516 "stream flow control credit isn't issued after stop"
517 );
518
519 let (new_bytes, is_closed) = s
521 .ingest(
522 frame::Stream {
523 id: StreamId::new(Side::Client, Dir::Uni, 0),
524 offset: 0,
525 fin: false,
526 data: Bytes::from_static(&[0; INITIAL_OFFSET as usize]),
527 },
528 123,
529 data_recvd,
530 data_recvd + 1024,
531 )
532 .unwrap();
533 assert_eq!(
534 new_bytes, 0,
535 "reordered frames don't issue connection-level flow control for stopped streams"
536 );
537 assert!(!is_closed);
538
539 let (max_stream_data, transmit) = s.max_stream_data(RECV_WINDOW);
540 assert!(!transmit.should_transmit());
541 assert_eq!(
542 max_stream_data, RECV_WINDOW,
543 "stream flow control credit isn't issued after stop"
544 );
545 }
546}