blob: 49f09176c657f7091b3a52251b9b805d472b92c7 [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/third_party/quiche/src/quic/core/quic_stream_sequencer.h"
6
7#include <algorithm>
renjietang8be8b742020-01-14 12:41:09 -08008#include <cstddef>
QUICHE teama6ef0a62019-03-07 20:34:33 -05009#include <limits>
vasilvv872e7a32019-03-12 16:42:44 -070010#include <string>
QUICHE teama6ef0a62019-03-07 20:34:33 -050011#include <utility>
12
renjietang03987852019-10-22 12:06:37 -070013#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050014#include "net/third_party/quiche/src/quic/core/quic_packets.h"
15#include "net/third_party/quiche/src/quic/core/quic_stream.h"
16#include "net/third_party/quiche/src/quic/core/quic_stream_sequencer_buffer.h"
renjietang8be8b742020-01-14 12:41:09 -080017#include "net/third_party/quiche/src/quic/core/quic_types.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050018#include "net/third_party/quiche/src/quic/core/quic_utils.h"
19#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
20#include "net/third_party/quiche/src/quic/platform/api/quic_clock.h"
21#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
renjietangc152cc52019-08-13 11:54:57 -070022#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050023#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
dmcardlecf0bfcf2019-12-13 08:08:21 -080024#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
25#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050026
27namespace quic {
28
29QuicStreamSequencer::QuicStreamSequencer(StreamInterface* quic_stream)
30 : stream_(quic_stream),
31 buffered_frames_(kStreamReceiveWindowLimit),
renjietang03987852019-10-22 12:06:37 -070032 highest_offset_(0),
QUICHE teama6ef0a62019-03-07 20:34:33 -050033 close_offset_(std::numeric_limits<QuicStreamOffset>::max()),
34 blocked_(false),
35 num_frames_received_(0),
36 num_duplicate_frames_received_(0),
37 ignore_read_data_(false),
renjietang7eb51a72020-01-06 10:45:43 -080038 level_triggered_(false) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -050039
40QuicStreamSequencer::~QuicStreamSequencer() {}
41
42void QuicStreamSequencer::OnStreamFrame(const QuicStreamFrame& frame) {
renjietang963c2ec2019-09-12 11:46:50 -070043 DCHECK_LE(frame.offset + frame.data_length, close_offset_);
QUICHE teama6ef0a62019-03-07 20:34:33 -050044 ++num_frames_received_;
45 const QuicStreamOffset byte_offset = frame.offset;
46 const size_t data_len = frame.data_length;
47
renjietang8be8b742020-01-14 12:41:09 -080048 if (frame.fin &&
49 (!CloseStreamAtOffset(frame.offset + data_len) || data_len == 0)) {
50 return;
QUICHE teama6ef0a62019-03-07 20:34:33 -050051 }
52 OnFrameData(byte_offset, data_len, frame.data_buffer);
53}
54
55void QuicStreamSequencer::OnCryptoFrame(const QuicCryptoFrame& frame) {
56 ++num_frames_received_;
57 OnFrameData(frame.offset, frame.data_length, frame.data_buffer);
58}
59
60void QuicStreamSequencer::OnFrameData(QuicStreamOffset byte_offset,
61 size_t data_len,
62 const char* data_buffer) {
renjietang03987852019-10-22 12:06:37 -070063 highest_offset_ = std::max(highest_offset_, byte_offset + data_len);
QUICHE teama6ef0a62019-03-07 20:34:33 -050064 const size_t previous_readable_bytes = buffered_frames_.ReadableBytes();
65 size_t bytes_written;
vasilvvc48c8712019-03-11 13:38:16 -070066 std::string error_details;
QUICHE teama6ef0a62019-03-07 20:34:33 -050067 QuicErrorCode result = buffered_frames_.OnStreamData(
dmcardlecf0bfcf2019-12-13 08:08:21 -080068 byte_offset, quiche::QuicheStringPiece(data_buffer, data_len),
69 &bytes_written, &error_details);
QUICHE teama6ef0a62019-03-07 20:34:33 -050070 if (result != QUIC_NO_ERROR) {
dmcardlecf0bfcf2019-12-13 08:08:21 -080071 std::string details = quiche::QuicheStrCat(
QUICHE teama6ef0a62019-03-07 20:34:33 -050072 "Stream ", stream_->id(), ": ", QuicErrorCodeToString(result), ": ",
73 error_details,
74 "\nPeer Address: ", stream_->PeerAddressOfLatestPacket().ToString());
75 QUIC_LOG_FIRST_N(WARNING, 50) << QuicErrorCodeToString(result);
76 QUIC_LOG_FIRST_N(WARNING, 50) << details;
77 stream_->CloseConnectionWithDetails(result, details);
78 return;
79 }
80
81 if (bytes_written == 0) {
82 ++num_duplicate_frames_received_;
83 // Silently ignore duplicates.
84 return;
85 }
86
87 if (blocked_) {
88 return;
89 }
90
91 if (level_triggered_) {
92 if (buffered_frames_.ReadableBytes() > previous_readable_bytes) {
93 // Readable bytes has changed, let stream decide if to inform application
94 // or not.
ianswettef3d9cd2019-12-23 07:16:43 -080095 if (ignore_read_data_) {
QUICHE teama6ef0a62019-03-07 20:34:33 -050096 FlushBufferedFrames();
97 } else {
98 stream_->OnDataAvailable();
99 }
100 }
101 return;
102 }
103 const bool stream_unblocked =
104 previous_readable_bytes == 0 && buffered_frames_.ReadableBytes() > 0;
105 if (stream_unblocked) {
106 if (ignore_read_data_) {
107 FlushBufferedFrames();
108 } else {
109 stream_->OnDataAvailable();
110 }
111 }
112}
113
renjietangc152cc52019-08-13 11:54:57 -0700114bool QuicStreamSequencer::CloseStreamAtOffset(QuicStreamOffset offset) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500115 const QuicStreamOffset kMaxOffset =
116 std::numeric_limits<QuicStreamOffset>::max();
117
118 // If there is a scheduled close, the new offset should match it.
119 if (close_offset_ != kMaxOffset && offset != close_offset_) {
renjietang03987852019-10-22 12:06:37 -0700120 stream_->CloseConnectionWithDetails(
121 QUIC_STREAM_SEQUENCER_INVALID_STATE,
dmcardlecf0bfcf2019-12-13 08:08:21 -0800122 quiche::QuicheStrCat(
123 "Stream ", stream_->id(), " received new final offset: ", offset,
124 ", which is different from close offset: ", close_offset_));
renjietangc152cc52019-08-13 11:54:57 -0700125 return false;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500126 }
127
renjietang03987852019-10-22 12:06:37 -0700128 // The final offset should be no less than the highest offset that is
129 // received.
renjietang7eb51a72020-01-06 10:45:43 -0800130 if (offset < highest_offset_) {
renjietange2a64de2019-11-15 12:16:56 -0800131 stream_->CloseConnectionWithDetails(
132 QUIC_STREAM_SEQUENCER_INVALID_STATE,
dmcardlecf0bfcf2019-12-13 08:08:21 -0800133 quiche::QuicheStrCat(
renjietange2a64de2019-11-15 12:16:56 -0800134 "Stream ", stream_->id(), " received fin with offset: ", offset,
135 ", which reduces current highest offset: ", highest_offset_));
136 return false;
renjietang03987852019-10-22 12:06:37 -0700137 }
138
QUICHE teama6ef0a62019-03-07 20:34:33 -0500139 close_offset_ = offset;
140
141 MaybeCloseStream();
renjietangc152cc52019-08-13 11:54:57 -0700142 return true;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500143}
144
bncf152d8c2019-08-06 06:03:08 -0700145void QuicStreamSequencer::MaybeCloseStream() {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500146 if (blocked_ || !IsClosed()) {
bncf152d8c2019-08-06 06:03:08 -0700147 return;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500148 }
149
150 QUIC_DVLOG(1) << "Passing up termination, as we've processed "
151 << buffered_frames_.BytesConsumed() << " of " << close_offset_
152 << " bytes.";
153 // This will cause the stream to consume the FIN.
154 // Technically it's an error if |num_bytes_consumed| isn't exactly
155 // equal to |close_offset|, but error handling seems silly at this point.
156 if (ignore_read_data_) {
157 // The sequencer is discarding stream data and must notify the stream on
158 // receipt of a FIN because the consumer won't.
159 stream_->OnFinRead();
160 } else {
161 stream_->OnDataAvailable();
162 }
163 buffered_frames_.Clear();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500164}
165
166int QuicStreamSequencer::GetReadableRegions(iovec* iov, size_t iov_len) const {
167 DCHECK(!blocked_);
168 return buffered_frames_.GetReadableRegions(iov, iov_len);
169}
170
171bool QuicStreamSequencer::GetReadableRegion(iovec* iov) const {
172 DCHECK(!blocked_);
173 return buffered_frames_.GetReadableRegion(iov);
174}
175
bnc7b3e0a92019-06-24 16:06:45 -0700176bool QuicStreamSequencer::PeekRegion(QuicStreamOffset offset,
177 iovec* iov) const {
178 DCHECK(!blocked_);
179 return buffered_frames_.PeekRegion(offset, iov);
180}
181
vasilvvc48c8712019-03-11 13:38:16 -0700182void QuicStreamSequencer::Read(std::string* buffer) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500183 DCHECK(!blocked_);
184 buffer->resize(buffer->size() + ReadableBytes());
185 iovec iov;
186 iov.iov_len = ReadableBytes();
187 iov.iov_base = &(*buffer)[buffer->size() - iov.iov_len];
188 Readv(&iov, 1);
189}
190
renjietang8be8b742020-01-14 12:41:09 -0800191size_t QuicStreamSequencer::Readv(const struct iovec* iov, size_t iov_len) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500192 DCHECK(!blocked_);
vasilvvc48c8712019-03-11 13:38:16 -0700193 std::string error_details;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500194 size_t bytes_read;
195 QuicErrorCode read_error =
196 buffered_frames_.Readv(iov, iov_len, &bytes_read, &error_details);
197 if (read_error != QUIC_NO_ERROR) {
vasilvvc48c8712019-03-11 13:38:16 -0700198 std::string details =
dmcardlecf0bfcf2019-12-13 08:08:21 -0800199 quiche::QuicheStrCat("Stream ", stream_->id(), ": ", error_details);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500200 stream_->CloseConnectionWithDetails(read_error, details);
renjietang8be8b742020-01-14 12:41:09 -0800201 return bytes_read;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500202 }
203
204 stream_->AddBytesConsumed(bytes_read);
renjietang8be8b742020-01-14 12:41:09 -0800205 return bytes_read;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500206}
207
208bool QuicStreamSequencer::HasBytesToRead() const {
209 return buffered_frames_.HasBytesToRead();
210}
211
212size_t QuicStreamSequencer::ReadableBytes() const {
213 return buffered_frames_.ReadableBytes();
214}
215
216bool QuicStreamSequencer::IsClosed() const {
217 return buffered_frames_.BytesConsumed() >= close_offset_;
218}
219
220void QuicStreamSequencer::MarkConsumed(size_t num_bytes_consumed) {
221 DCHECK(!blocked_);
222 bool result = buffered_frames_.MarkConsumed(num_bytes_consumed);
223 if (!result) {
224 QUIC_BUG << "Invalid argument to MarkConsumed."
225 << " expect to consume: " << num_bytes_consumed
226 << ", but not enough bytes available. " << DebugString();
227 stream_->Reset(QUIC_ERROR_PROCESSING_STREAM);
228 return;
229 }
230 stream_->AddBytesConsumed(num_bytes_consumed);
231}
232
233void QuicStreamSequencer::SetBlockedUntilFlush() {
234 blocked_ = true;
235}
236
237void QuicStreamSequencer::SetUnblocked() {
238 blocked_ = false;
239 if (IsClosed() || HasBytesToRead()) {
240 stream_->OnDataAvailable();
241 }
242}
243
244void QuicStreamSequencer::StopReading() {
245 if (ignore_read_data_) {
246 return;
247 }
248 ignore_read_data_ = true;
249 FlushBufferedFrames();
250}
251
252void QuicStreamSequencer::ReleaseBuffer() {
253 buffered_frames_.ReleaseWholeBuffer();
254}
255
256void QuicStreamSequencer::ReleaseBufferIfEmpty() {
257 if (buffered_frames_.Empty()) {
258 buffered_frames_.ReleaseWholeBuffer();
259 }
260}
261
262void QuicStreamSequencer::FlushBufferedFrames() {
263 DCHECK(ignore_read_data_);
264 size_t bytes_flushed = buffered_frames_.FlushBufferedFrames();
265 QUIC_DVLOG(1) << "Flushing buffered data at offset "
266 << buffered_frames_.BytesConsumed() << " length "
267 << bytes_flushed << " for stream " << stream_->id();
268 stream_->AddBytesConsumed(bytes_flushed);
269 MaybeCloseStream();
270}
271
272size_t QuicStreamSequencer::NumBytesBuffered() const {
273 return buffered_frames_.BytesBuffered();
274}
275
276QuicStreamOffset QuicStreamSequencer::NumBytesConsumed() const {
277 return buffered_frames_.BytesConsumed();
278}
279
vasilvvc48c8712019-03-11 13:38:16 -0700280const std::string QuicStreamSequencer::DebugString() const {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500281 // clang-format off
dmcardlecf0bfcf2019-12-13 08:08:21 -0800282 return quiche::QuicheStrCat("QuicStreamSequencer:",
QUICHE teama6ef0a62019-03-07 20:34:33 -0500283 "\n bytes buffered: ", NumBytesBuffered(),
284 "\n bytes consumed: ", NumBytesConsumed(),
285 "\n has bytes to read: ", HasBytesToRead() ? "true" : "false",
286 "\n frames received: ", num_frames_received(),
287 "\n close offset bytes: ", close_offset_,
288 "\n is closed: ", IsClosed() ? "true" : "false");
289 // clang-format on
290}
291
292} // namespace quic