blob: d79766893311484988d8de0bf598caf4ce352ccb [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>
8#include <limits>
vasilvv872e7a32019-03-12 16:42:44 -07009#include <string>
QUICHE teama6ef0a62019-03-07 20:34:33 -050010#include <utility>
11
renjietang03987852019-10-22 12:06:37 -070012#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050013#include "net/third_party/quiche/src/quic/core/quic_packets.h"
14#include "net/third_party/quiche/src/quic/core/quic_stream.h"
15#include "net/third_party/quiche/src/quic/core/quic_stream_sequencer_buffer.h"
16#include "net/third_party/quiche/src/quic/core/quic_utils.h"
17#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
18#include "net/third_party/quiche/src/quic/platform/api/quic_clock.h"
19#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
renjietangc152cc52019-08-13 11:54:57 -070020#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050021#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
22#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050023#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
24
25namespace quic {
26
27QuicStreamSequencer::QuicStreamSequencer(StreamInterface* quic_stream)
28 : stream_(quic_stream),
29 buffered_frames_(kStreamReceiveWindowLimit),
renjietang03987852019-10-22 12:06:37 -070030 highest_offset_(0),
QUICHE teama6ef0a62019-03-07 20:34:33 -050031 close_offset_(std::numeric_limits<QuicStreamOffset>::max()),
32 blocked_(false),
33 num_frames_received_(0),
34 num_duplicate_frames_received_(0),
35 ignore_read_data_(false),
36 level_triggered_(false),
37 stop_reading_when_level_triggered_(
renjietange2a64de2019-11-15 12:16:56 -080038 GetQuicReloadableFlag(quic_stop_reading_when_level_triggered)),
39 close_connection_and_discard_data_on_wrong_offset_(GetQuicReloadableFlag(
40 quic_close_connection_and_discard_data_on_wrong_offset)) {
ianswett3ccd7702019-10-24 04:03:48 -070041 if (stop_reading_when_level_triggered_) {
42 QUIC_RELOADABLE_FLAG_COUNT(quic_stop_reading_when_level_triggered);
43 }
44}
QUICHE teama6ef0a62019-03-07 20:34:33 -050045
46QuicStreamSequencer::~QuicStreamSequencer() {}
47
48void QuicStreamSequencer::OnStreamFrame(const QuicStreamFrame& frame) {
renjietang963c2ec2019-09-12 11:46:50 -070049 DCHECK_LE(frame.offset + frame.data_length, close_offset_);
QUICHE teama6ef0a62019-03-07 20:34:33 -050050 ++num_frames_received_;
51 const QuicStreamOffset byte_offset = frame.offset;
52 const size_t data_len = frame.data_length;
53
54 if (frame.fin) {
renjietangc152cc52019-08-13 11:54:57 -070055 bool should_process_data = CloseStreamAtOffset(frame.offset + data_len);
QUICHE teama6ef0a62019-03-07 20:34:33 -050056 if (data_len == 0) {
57 return;
58 }
renjietange2a64de2019-11-15 12:16:56 -080059 if (close_connection_and_discard_data_on_wrong_offset_) {
60 QUIC_RELOADABLE_FLAG_COUNT_N(
61 quic_close_connection_and_discard_data_on_wrong_offset, 1, 3);
renjietangc152cc52019-08-13 11:54:57 -070062 if (!should_process_data) {
63 return;
64 }
65 }
QUICHE teama6ef0a62019-03-07 20:34:33 -050066 }
67 OnFrameData(byte_offset, data_len, frame.data_buffer);
68}
69
70void QuicStreamSequencer::OnCryptoFrame(const QuicCryptoFrame& frame) {
71 ++num_frames_received_;
72 OnFrameData(frame.offset, frame.data_length, frame.data_buffer);
73}
74
75void QuicStreamSequencer::OnFrameData(QuicStreamOffset byte_offset,
76 size_t data_len,
77 const char* data_buffer) {
renjietang03987852019-10-22 12:06:37 -070078 highest_offset_ = std::max(highest_offset_, byte_offset + data_len);
QUICHE teama6ef0a62019-03-07 20:34:33 -050079 const size_t previous_readable_bytes = buffered_frames_.ReadableBytes();
80 size_t bytes_written;
vasilvvc48c8712019-03-11 13:38:16 -070081 std::string error_details;
QUICHE teama6ef0a62019-03-07 20:34:33 -050082 QuicErrorCode result = buffered_frames_.OnStreamData(
83 byte_offset, QuicStringPiece(data_buffer, data_len), &bytes_written,
84 &error_details);
85 if (result != QUIC_NO_ERROR) {
vasilvvc48c8712019-03-11 13:38:16 -070086 std::string details = QuicStrCat(
QUICHE teama6ef0a62019-03-07 20:34:33 -050087 "Stream ", stream_->id(), ": ", QuicErrorCodeToString(result), ": ",
88 error_details,
89 "\nPeer Address: ", stream_->PeerAddressOfLatestPacket().ToString());
90 QUIC_LOG_FIRST_N(WARNING, 50) << QuicErrorCodeToString(result);
91 QUIC_LOG_FIRST_N(WARNING, 50) << details;
92 stream_->CloseConnectionWithDetails(result, details);
93 return;
94 }
95
96 if (bytes_written == 0) {
97 ++num_duplicate_frames_received_;
98 // Silently ignore duplicates.
99 return;
100 }
101
102 if (blocked_) {
103 return;
104 }
105
106 if (level_triggered_) {
107 if (buffered_frames_.ReadableBytes() > previous_readable_bytes) {
108 // Readable bytes has changed, let stream decide if to inform application
109 // or not.
110 if (stop_reading_when_level_triggered_ && ignore_read_data_) {
111 QUIC_RELOADABLE_FLAG_COUNT(quic_stop_reading_when_level_triggered);
112 FlushBufferedFrames();
113 } else {
114 stream_->OnDataAvailable();
115 }
116 }
117 return;
118 }
119 const bool stream_unblocked =
120 previous_readable_bytes == 0 && buffered_frames_.ReadableBytes() > 0;
121 if (stream_unblocked) {
122 if (ignore_read_data_) {
123 FlushBufferedFrames();
124 } else {
125 stream_->OnDataAvailable();
126 }
127 }
128}
129
renjietangc152cc52019-08-13 11:54:57 -0700130bool QuicStreamSequencer::CloseStreamAtOffset(QuicStreamOffset offset) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500131 const QuicStreamOffset kMaxOffset =
132 std::numeric_limits<QuicStreamOffset>::max();
133
134 // If there is a scheduled close, the new offset should match it.
135 if (close_offset_ != kMaxOffset && offset != close_offset_) {
renjietange2a64de2019-11-15 12:16:56 -0800136 if (!close_connection_and_discard_data_on_wrong_offset_) {
renjietang03987852019-10-22 12:06:37 -0700137 stream_->Reset(QUIC_MULTIPLE_TERMINATION_OFFSETS);
138 return false;
139 }
renjietange2a64de2019-11-15 12:16:56 -0800140 QUIC_RELOADABLE_FLAG_COUNT_N(
141 quic_close_connection_and_discard_data_on_wrong_offset, 2, 3);
renjietang03987852019-10-22 12:06:37 -0700142 stream_->CloseConnectionWithDetails(
143 QUIC_STREAM_SEQUENCER_INVALID_STATE,
144 QuicStrCat("Stream ", stream_->id(),
145 " received new final offset: ", offset,
146 ", which is different from close offset: ", close_offset_));
renjietangc152cc52019-08-13 11:54:57 -0700147 return false;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500148 }
149
renjietang03987852019-10-22 12:06:37 -0700150 // The final offset should be no less than the highest offset that is
151 // received.
renjietange2a64de2019-11-15 12:16:56 -0800152 if (close_connection_and_discard_data_on_wrong_offset_ &&
153 offset < highest_offset_) {
154 QUIC_RELOADABLE_FLAG_COUNT_N(
155 quic_close_connection_and_discard_data_on_wrong_offset, 3, 3);
156 stream_->CloseConnectionWithDetails(
157 QUIC_STREAM_SEQUENCER_INVALID_STATE,
158 QuicStrCat(
159 "Stream ", stream_->id(), " received fin with offset: ", offset,
160 ", which reduces current highest offset: ", highest_offset_));
161 return false;
renjietang03987852019-10-22 12:06:37 -0700162 }
163
QUICHE teama6ef0a62019-03-07 20:34:33 -0500164 close_offset_ = offset;
165
166 MaybeCloseStream();
renjietangc152cc52019-08-13 11:54:57 -0700167 return true;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500168}
169
bncf152d8c2019-08-06 06:03:08 -0700170void QuicStreamSequencer::MaybeCloseStream() {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500171 if (blocked_ || !IsClosed()) {
bncf152d8c2019-08-06 06:03:08 -0700172 return;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500173 }
174
175 QUIC_DVLOG(1) << "Passing up termination, as we've processed "
176 << buffered_frames_.BytesConsumed() << " of " << close_offset_
177 << " bytes.";
178 // This will cause the stream to consume the FIN.
179 // Technically it's an error if |num_bytes_consumed| isn't exactly
180 // equal to |close_offset|, but error handling seems silly at this point.
181 if (ignore_read_data_) {
182 // The sequencer is discarding stream data and must notify the stream on
183 // receipt of a FIN because the consumer won't.
184 stream_->OnFinRead();
185 } else {
186 stream_->OnDataAvailable();
187 }
188 buffered_frames_.Clear();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500189}
190
191int QuicStreamSequencer::GetReadableRegions(iovec* iov, size_t iov_len) const {
192 DCHECK(!blocked_);
193 return buffered_frames_.GetReadableRegions(iov, iov_len);
194}
195
196bool QuicStreamSequencer::GetReadableRegion(iovec* iov) const {
197 DCHECK(!blocked_);
198 return buffered_frames_.GetReadableRegion(iov);
199}
200
bnc7b3e0a92019-06-24 16:06:45 -0700201bool QuicStreamSequencer::PeekRegion(QuicStreamOffset offset,
202 iovec* iov) const {
203 DCHECK(!blocked_);
204 return buffered_frames_.PeekRegion(offset, iov);
205}
206
vasilvvc48c8712019-03-11 13:38:16 -0700207void QuicStreamSequencer::Read(std::string* buffer) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500208 DCHECK(!blocked_);
209 buffer->resize(buffer->size() + ReadableBytes());
210 iovec iov;
211 iov.iov_len = ReadableBytes();
212 iov.iov_base = &(*buffer)[buffer->size() - iov.iov_len];
213 Readv(&iov, 1);
214}
215
216int QuicStreamSequencer::Readv(const struct iovec* iov, size_t iov_len) {
217 DCHECK(!blocked_);
vasilvvc48c8712019-03-11 13:38:16 -0700218 std::string error_details;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500219 size_t bytes_read;
220 QuicErrorCode read_error =
221 buffered_frames_.Readv(iov, iov_len, &bytes_read, &error_details);
222 if (read_error != QUIC_NO_ERROR) {
vasilvvc48c8712019-03-11 13:38:16 -0700223 std::string details =
QUICHE teama6ef0a62019-03-07 20:34:33 -0500224 QuicStrCat("Stream ", stream_->id(), ": ", error_details);
225 stream_->CloseConnectionWithDetails(read_error, details);
226 return static_cast<int>(bytes_read);
227 }
228
229 stream_->AddBytesConsumed(bytes_read);
230 return static_cast<int>(bytes_read);
231}
232
233bool QuicStreamSequencer::HasBytesToRead() const {
234 return buffered_frames_.HasBytesToRead();
235}
236
237size_t QuicStreamSequencer::ReadableBytes() const {
238 return buffered_frames_.ReadableBytes();
239}
240
241bool QuicStreamSequencer::IsClosed() const {
242 return buffered_frames_.BytesConsumed() >= close_offset_;
243}
244
245void QuicStreamSequencer::MarkConsumed(size_t num_bytes_consumed) {
246 DCHECK(!blocked_);
247 bool result = buffered_frames_.MarkConsumed(num_bytes_consumed);
248 if (!result) {
249 QUIC_BUG << "Invalid argument to MarkConsumed."
250 << " expect to consume: " << num_bytes_consumed
251 << ", but not enough bytes available. " << DebugString();
252 stream_->Reset(QUIC_ERROR_PROCESSING_STREAM);
253 return;
254 }
255 stream_->AddBytesConsumed(num_bytes_consumed);
256}
257
258void QuicStreamSequencer::SetBlockedUntilFlush() {
259 blocked_ = true;
260}
261
262void QuicStreamSequencer::SetUnblocked() {
263 blocked_ = false;
264 if (IsClosed() || HasBytesToRead()) {
265 stream_->OnDataAvailable();
266 }
267}
268
269void QuicStreamSequencer::StopReading() {
270 if (ignore_read_data_) {
271 return;
272 }
273 ignore_read_data_ = true;
274 FlushBufferedFrames();
275}
276
277void QuicStreamSequencer::ReleaseBuffer() {
278 buffered_frames_.ReleaseWholeBuffer();
279}
280
281void QuicStreamSequencer::ReleaseBufferIfEmpty() {
282 if (buffered_frames_.Empty()) {
283 buffered_frames_.ReleaseWholeBuffer();
284 }
285}
286
287void QuicStreamSequencer::FlushBufferedFrames() {
288 DCHECK(ignore_read_data_);
289 size_t bytes_flushed = buffered_frames_.FlushBufferedFrames();
290 QUIC_DVLOG(1) << "Flushing buffered data at offset "
291 << buffered_frames_.BytesConsumed() << " length "
292 << bytes_flushed << " for stream " << stream_->id();
293 stream_->AddBytesConsumed(bytes_flushed);
294 MaybeCloseStream();
295}
296
297size_t QuicStreamSequencer::NumBytesBuffered() const {
298 return buffered_frames_.BytesBuffered();
299}
300
301QuicStreamOffset QuicStreamSequencer::NumBytesConsumed() const {
302 return buffered_frames_.BytesConsumed();
303}
304
vasilvvc48c8712019-03-11 13:38:16 -0700305const std::string QuicStreamSequencer::DebugString() const {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500306 // clang-format off
307 return QuicStrCat("QuicStreamSequencer:",
308 "\n bytes buffered: ", NumBytesBuffered(),
309 "\n bytes consumed: ", NumBytesConsumed(),
310 "\n has bytes to read: ", HasBytesToRead() ? "true" : "false",
311 "\n frames received: ", num_frames_received(),
312 "\n close offset bytes: ", close_offset_,
313 "\n is closed: ", IsClosed() ? "true" : "false");
314 // clang-format on
315}
316
317} // namespace quic