blob: 5d5c176ed8895daf91a713a11a33683692677b32 [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// Copyright 2013 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/http/quic_spdy_stream.h"
6
renjietang2abedac2019-05-20 14:04:50 -07007#include <limits>
vasilvv872e7a32019-03-12 16:42:44 -07008#include <string>
QUICHE teama6ef0a62019-03-07 20:34:33 -05009#include <utility>
10
bnc3fc60df2019-07-17 11:55:10 -070011#include "net/third_party/quiche/src/quic/core/http/http_constants.h"
renjietang7d4f9132019-06-20 15:04:34 -070012#include "net/third_party/quiche/src/quic/core/http/http_decoder.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050013#include "net/third_party/quiche/src/quic/core/http/quic_spdy_session.h"
14#include "net/third_party/quiche/src/quic/core/http/spdy_utils.h"
renjietang2abedac2019-05-20 14:04:50 -070015#include "net/third_party/quiche/src/quic/core/qpack/qpack_decoder.h"
16#include "net/third_party/quiche/src/quic/core/qpack/qpack_encoder.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050017#include "net/third_party/quiche/src/quic/core/quic_utils.h"
renjietang2abedac2019-05-20 14:04:50 -070018#include "net/third_party/quiche/src/quic/core/quic_versions.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050019#include "net/third_party/quiche/src/quic/core/quic_write_blocked_list.h"
20#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
21#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
22#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
23#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
24#include "net/third_party/quiche/src/quic/platform/api/quic_mem_slice_storage.h"
bnc4e9283d2019-12-17 07:08:57 -080025#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
dmcardleba2fb7e2019-12-13 07:44:34 -080026#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
27#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050028#include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"
29
30using spdy::SpdyHeaderBlock;
31using spdy::SpdyPriority;
32
33namespace quic {
34
35// Visitor of HttpDecoder that passes data frame to QuicSpdyStream and closes
36// the connection on unexpected frames.
37class QuicSpdyStream::HttpDecoderVisitor : public HttpDecoder::Visitor {
38 public:
39 explicit HttpDecoderVisitor(QuicSpdyStream* stream) : stream_(stream) {}
40 HttpDecoderVisitor(const HttpDecoderVisitor&) = delete;
41 HttpDecoderVisitor& operator=(const HttpDecoderVisitor&) = delete;
42
bncdfabdfb2020-01-17 17:46:40 -080043 void OnError(HttpDecoder* decoder) override {
QUICHE teama6ef0a62019-03-07 20:34:33 -050044 stream_->session()->connection()->CloseConnection(
bncdfabdfb2020-01-17 17:46:40 -080045 decoder->error(), decoder->error_detail(),
QUICHE teama6ef0a62019-03-07 20:34:33 -050046 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
47 }
48
dschinazi17d42422019-06-18 16:35:07 -070049 bool OnCancelPushFrame(const CancelPushFrame& /*frame*/) override {
QUICHE teama6ef0a62019-03-07 20:34:33 -050050 CloseConnectionOnWrongFrame("Cancel Push");
renjietang546a6282019-06-03 10:21:21 -070051 return false;
QUICHE teama6ef0a62019-03-07 20:34:33 -050052 }
53
dschinazi17d42422019-06-18 16:35:07 -070054 bool OnMaxPushIdFrame(const MaxPushIdFrame& /*frame*/) override {
QUICHE teama6ef0a62019-03-07 20:34:33 -050055 CloseConnectionOnWrongFrame("Max Push Id");
renjietang546a6282019-06-03 10:21:21 -070056 return false;
QUICHE teama6ef0a62019-03-07 20:34:33 -050057 }
58
dschinazi17d42422019-06-18 16:35:07 -070059 bool OnGoAwayFrame(const GoAwayFrame& /*frame*/) override {
QUICHE teama6ef0a62019-03-07 20:34:33 -050060 CloseConnectionOnWrongFrame("Goaway");
renjietang546a6282019-06-03 10:21:21 -070061 return false;
QUICHE teama6ef0a62019-03-07 20:34:33 -050062 }
63
bnca2b13be2019-07-31 12:04:20 -070064 bool OnSettingsFrameStart(QuicByteCount /*header_length*/) override {
renjietangf41bf642019-04-02 11:45:34 -070065 CloseConnectionOnWrongFrame("Settings");
renjietang546a6282019-06-03 10:21:21 -070066 return false;
renjietangf41bf642019-04-02 11:45:34 -070067 }
68
dschinazi17d42422019-06-18 16:35:07 -070069 bool OnSettingsFrame(const SettingsFrame& /*frame*/) override {
QUICHE teama6ef0a62019-03-07 20:34:33 -050070 CloseConnectionOnWrongFrame("Settings");
renjietang546a6282019-06-03 10:21:21 -070071 return false;
QUICHE teama6ef0a62019-03-07 20:34:33 -050072 }
73
dschinazi17d42422019-06-18 16:35:07 -070074 bool OnDuplicatePushFrame(const DuplicatePushFrame& /*frame*/) override {
bncbf3dbe52019-07-17 05:17:41 -070075 // TODO(b/137554973): Consume frame.
QUICHE teama6ef0a62019-03-07 20:34:33 -050076 CloseConnectionOnWrongFrame("Duplicate Push");
renjietang546a6282019-06-03 10:21:21 -070077 return false;
QUICHE teama6ef0a62019-03-07 20:34:33 -050078 }
79
bnca2b13be2019-07-31 12:04:20 -070080 bool OnDataFrameStart(QuicByteCount header_length) override {
81 return stream_->OnDataFrameStart(header_length);
QUICHE teama6ef0a62019-03-07 20:34:33 -050082 }
83
dmcardleba2fb7e2019-12-13 07:44:34 -080084 bool OnDataFramePayload(quiche::QuicheStringPiece payload) override {
bnc70914262019-03-16 12:49:50 -070085 DCHECK(!payload.empty());
renjietang546a6282019-06-03 10:21:21 -070086 return stream_->OnDataFramePayload(payload);
QUICHE teama6ef0a62019-03-07 20:34:33 -050087 }
88
renjietang546a6282019-06-03 10:21:21 -070089 bool OnDataFrameEnd() override { return stream_->OnDataFrameEnd(); }
QUICHE teama6ef0a62019-03-07 20:34:33 -050090
bnca2b13be2019-07-31 12:04:20 -070091 bool OnHeadersFrameStart(QuicByteCount header_length) override {
renjietanga29a96a2019-10-10 12:47:50 -070092 if (!VersionUsesHttp3(stream_->transport_version())) {
bnc62446bc2019-03-14 06:11:25 -070093 CloseConnectionOnWrongFrame("Headers");
renjietang546a6282019-06-03 10:21:21 -070094 return false;
bnc62446bc2019-03-14 06:11:25 -070095 }
bnca2b13be2019-07-31 12:04:20 -070096 return stream_->OnHeadersFrameStart(header_length);
QUICHE teama6ef0a62019-03-07 20:34:33 -050097 }
98
dmcardleba2fb7e2019-12-13 07:44:34 -080099 bool OnHeadersFramePayload(quiche::QuicheStringPiece payload) override {
bnc70914262019-03-16 12:49:50 -0700100 DCHECK(!payload.empty());
renjietanga29a96a2019-10-10 12:47:50 -0700101 if (!VersionUsesHttp3(stream_->transport_version())) {
bnc62446bc2019-03-14 06:11:25 -0700102 CloseConnectionOnWrongFrame("Headers");
renjietang546a6282019-06-03 10:21:21 -0700103 return false;
bnc62446bc2019-03-14 06:11:25 -0700104 }
renjietang546a6282019-06-03 10:21:21 -0700105 return stream_->OnHeadersFramePayload(payload);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500106 }
107
renjietang546a6282019-06-03 10:21:21 -0700108 bool OnHeadersFrameEnd() override {
renjietanga29a96a2019-10-10 12:47:50 -0700109 if (!VersionUsesHttp3(stream_->transport_version())) {
bnc62446bc2019-03-14 06:11:25 -0700110 CloseConnectionOnWrongFrame("Headers");
renjietang546a6282019-06-03 10:21:21 -0700111 return false;
bnc62446bc2019-03-14 06:11:25 -0700112 }
renjietang546a6282019-06-03 10:21:21 -0700113 return stream_->OnHeadersFrameEnd();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500114 }
115
bncf0db6542019-09-23 11:18:28 -0700116 bool OnPushPromiseFrameStart(QuicByteCount header_length) override {
renjietanga29a96a2019-10-10 12:47:50 -0700117 if (!VersionUsesHttp3(stream_->transport_version())) {
renjietang3c3dfb72019-07-26 11:55:52 -0700118 CloseConnectionOnWrongFrame("Push Promise");
119 return false;
120 }
bncf0db6542019-09-23 11:18:28 -0700121 return stream_->OnPushPromiseFrameStart(header_length);
122 }
123
124 bool OnPushPromiseFramePushId(PushId push_id,
125 QuicByteCount push_id_length) override {
renjietanga29a96a2019-10-10 12:47:50 -0700126 if (!VersionUsesHttp3(stream_->transport_version())) {
bncf0db6542019-09-23 11:18:28 -0700127 CloseConnectionOnWrongFrame("Push Promise");
128 return false;
129 }
130 return stream_->OnPushPromiseFramePushId(push_id, push_id_length);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500131 }
132
dmcardleba2fb7e2019-12-13 07:44:34 -0800133 bool OnPushPromiseFramePayload(quiche::QuicheStringPiece payload) override {
bnc70914262019-03-16 12:49:50 -0700134 DCHECK(!payload.empty());
renjietanga29a96a2019-10-10 12:47:50 -0700135 if (!VersionUsesHttp3(stream_->transport_version())) {
renjietang3c3dfb72019-07-26 11:55:52 -0700136 CloseConnectionOnWrongFrame("Push Promise");
137 return false;
138 }
139 return stream_->OnPushPromiseFramePayload(payload);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500140 }
141
renjietang546a6282019-06-03 10:21:21 -0700142 bool OnPushPromiseFrameEnd() override {
renjietanga29a96a2019-10-10 12:47:50 -0700143 if (!VersionUsesHttp3(stream_->transport_version())) {
renjietang3c3dfb72019-07-26 11:55:52 -0700144 CloseConnectionOnWrongFrame("Push Promise");
145 return false;
146 }
147 return stream_->OnPushPromiseFrameEnd();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500148 }
149
bnc51e89622020-01-10 10:40:32 -0800150 bool OnPriorityUpdateFrameStart(QuicByteCount /*header_length*/) override {
151 CloseConnectionOnWrongFrame("Priority update");
152 return false;
153 }
154
155 bool OnPriorityUpdateFrame(const PriorityUpdateFrame& /*frame*/) override {
156 CloseConnectionOnWrongFrame("Priority update");
157 return false;
158 }
159
bnc25827c42019-07-29 08:57:24 -0700160 bool OnUnknownFrameStart(uint64_t frame_type,
bnca2b13be2019-07-31 12:04:20 -0700161 QuicByteCount header_length) override {
162 return stream_->OnUnknownFrameStart(frame_type, header_length);
bncbf3dbe52019-07-17 05:17:41 -0700163 }
164
dmcardleba2fb7e2019-12-13 07:44:34 -0800165 bool OnUnknownFramePayload(quiche::QuicheStringPiece payload) override {
bnc25827c42019-07-29 08:57:24 -0700166 return stream_->OnUnknownFramePayload(payload);
bncbf3dbe52019-07-17 05:17:41 -0700167 }
168
bnc25827c42019-07-29 08:57:24 -0700169 bool OnUnknownFrameEnd() override { return stream_->OnUnknownFrameEnd(); }
bncbf3dbe52019-07-17 05:17:41 -0700170
QUICHE teama6ef0a62019-03-07 20:34:33 -0500171 private:
dmcardleba2fb7e2019-12-13 07:44:34 -0800172 void CloseConnectionOnWrongFrame(quiche::QuicheStringPiece frame_type) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500173 stream_->session()->connection()->CloseConnection(
bncdfabdfb2020-01-17 17:46:40 -0800174 QUIC_HTTP_FRAME_UNEXPECTED_ON_SPDY_STREAM,
dmcardleba2fb7e2019-12-13 07:44:34 -0800175 quiche::QuicheStrCat(frame_type, " frame received on data stream"),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500176 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
177 }
178
179 QuicSpdyStream* stream_;
180};
181
182#define ENDPOINT \
183 (session()->perspective() == Perspective::IS_SERVER ? "Server: " \
184 : "Client:" \
185 " ")
186
187QuicSpdyStream::QuicSpdyStream(QuicStreamId id,
188 QuicSpdySession* spdy_session,
189 StreamType type)
190 : QuicStream(id, spdy_session, /*is_static=*/false, type),
191 spdy_session_(spdy_session),
renjietang2abedac2019-05-20 14:04:50 -0700192 on_body_available_called_because_sequencer_is_closed_(false),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500193 visitor_(nullptr),
bncc057c012019-07-02 11:13:22 -0700194 blocked_on_decoding_headers_(false),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500195 headers_decompressed_(false),
bnc446887e2019-11-27 13:08:28 -0800196 header_list_size_limit_exceeded_(false),
renjietang6f572a82019-07-23 16:33:13 -0700197 headers_payload_length_(0),
198 trailers_payload_length_(0),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500199 trailers_decompressed_(false),
200 trailers_consumed_(false),
renjietang7498c8c2019-07-02 19:28:42 -0700201 priority_sent_(false),
vasilvv0fc587f2019-09-06 13:33:08 -0700202 http_decoder_visitor_(std::make_unique<HttpDecoderVisitor>(this)),
bnca9bb4692019-07-09 17:29:48 -0700203 decoder_(http_decoder_visitor_.get()),
bnc8aadca72019-06-28 11:09:39 -0700204 sequencer_offset_(0),
205 is_decoder_processing_input_(false),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500206 ack_listener_(nullptr) {
bncfa1de5f2019-07-09 17:53:56 -0700207 DCHECK_EQ(session()->connection(), spdy_session->connection());
renjietangd1d00852019-09-06 10:43:12 -0700208 DCHECK_EQ(transport_version(), spdy_session->transport_version());
bncfa1de5f2019-07-09 17:53:56 -0700209 DCHECK(!QuicUtils::IsCryptoStreamId(transport_version(), id));
bnc8aadca72019-06-28 11:09:39 -0700210 DCHECK_EQ(0u, sequencer()->NumBytesConsumed());
renjietang2abedac2019-05-20 14:04:50 -0700211 // If headers are sent on the headers stream, then do not receive any
212 // callbacks from the sequencer until headers are complete.
renjietanga29a96a2019-10-10 12:47:50 -0700213 if (!VersionUsesHttp3(transport_version())) {
renjietang2abedac2019-05-20 14:04:50 -0700214 sequencer()->SetBlockedUntilFlush();
215 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500216
renjietanga29a96a2019-10-10 12:47:50 -0700217 if (VersionUsesHttp3(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500218 sequencer()->set_level_triggered(true);
219 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500220}
221
renjietangbaea59c2019-05-29 15:08:14 -0700222QuicSpdyStream::QuicSpdyStream(PendingStream* pending,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500223 QuicSpdySession* spdy_session,
224 StreamType type)
renjietangbaea59c2019-05-29 15:08:14 -0700225 : QuicStream(pending, type, /*is_static=*/false),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500226 spdy_session_(spdy_session),
renjietang2abedac2019-05-20 14:04:50 -0700227 on_body_available_called_because_sequencer_is_closed_(false),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500228 visitor_(nullptr),
bncc057c012019-07-02 11:13:22 -0700229 blocked_on_decoding_headers_(false),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500230 headers_decompressed_(false),
bnc446887e2019-11-27 13:08:28 -0800231 header_list_size_limit_exceeded_(false),
renjietang6f572a82019-07-23 16:33:13 -0700232 headers_payload_length_(0),
233 trailers_payload_length_(0),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500234 trailers_decompressed_(false),
235 trailers_consumed_(false),
renjietang7498c8c2019-07-02 19:28:42 -0700236 priority_sent_(false),
vasilvv0fc587f2019-09-06 13:33:08 -0700237 http_decoder_visitor_(std::make_unique<HttpDecoderVisitor>(this)),
bnca9bb4692019-07-09 17:29:48 -0700238 decoder_(http_decoder_visitor_.get()),
bnc8aadca72019-06-28 11:09:39 -0700239 sequencer_offset_(sequencer()->NumBytesConsumed()),
240 is_decoder_processing_input_(false),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500241 ack_listener_(nullptr) {
bncfa1de5f2019-07-09 17:53:56 -0700242 DCHECK_EQ(session()->connection(), spdy_session->connection());
renjietangd1d00852019-09-06 10:43:12 -0700243 DCHECK_EQ(transport_version(), spdy_session->transport_version());
bncfa1de5f2019-07-09 17:53:56 -0700244 DCHECK(!QuicUtils::IsCryptoStreamId(transport_version(), id()));
renjietang2abedac2019-05-20 14:04:50 -0700245 // If headers are sent on the headers stream, then do not receive any
246 // callbacks from the sequencer until headers are complete.
renjietanga29a96a2019-10-10 12:47:50 -0700247 if (!VersionUsesHttp3(transport_version())) {
renjietang2abedac2019-05-20 14:04:50 -0700248 sequencer()->SetBlockedUntilFlush();
249 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500250
renjietanga29a96a2019-10-10 12:47:50 -0700251 if (VersionUsesHttp3(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500252 sequencer()->set_level_triggered(true);
253 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500254}
255
256QuicSpdyStream::~QuicSpdyStream() {}
257
258size_t QuicSpdyStream::WriteHeaders(
259 SpdyHeaderBlock header_block,
260 bool fin,
261 QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
fayanga4b37b22019-06-18 13:37:47 -0700262 QuicConnection::ScopedPacketFlusher flusher(spdy_session_->connection());
renjietangbb1c4892019-05-24 15:58:44 -0700263 // Send stream type for server push stream
renjietanga29a96a2019-10-10 12:47:50 -0700264 if (VersionUsesHttp3(transport_version()) && type() == WRITE_UNIDIRECTIONAL &&
265 send_buffer().stream_offset() == 0) {
renjietangbb1c4892019-05-24 15:58:44 -0700266 char data[sizeof(kServerPushStream)];
bnc4e9283d2019-12-17 07:08:57 -0800267 QuicDataWriter writer(QUICHE_ARRAYSIZE(data), data);
renjietangbb1c4892019-05-24 15:58:44 -0700268 writer.WriteVarInt62(kServerPushStream);
269
270 // Similar to frame headers, stream type byte shouldn't be exposed to upper
271 // layer applications.
272 unacked_frame_headers_offsets_.Add(0, writer.length());
273
dschinazi88bd5b02019-10-10 00:52:20 -0700274 QUIC_LOG(INFO) << ENDPOINT << "Stream " << id()
275 << " is writing type as server push";
dmcardleba2fb7e2019-12-13 07:44:34 -0800276 WriteOrBufferData(quiche::QuicheStringPiece(writer.data(), writer.length()),
277 false, nullptr);
renjietangbb1c4892019-05-24 15:58:44 -0700278 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500279 size_t bytes_written =
280 WriteHeadersImpl(std::move(header_block), fin, std::move(ack_listener));
renjietanga29a96a2019-10-10 12:47:50 -0700281 if (!VersionUsesHttp3(transport_version()) && fin) {
renjietang2abedac2019-05-20 14:04:50 -0700282 // If HEADERS are sent on the headers stream, then |fin_sent_| needs to be
283 // set and write side needs to be closed without actually sending a FIN on
284 // this stream.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500285 // TODO(rch): Add test to ensure fin_sent_ is set whenever a fin is sent.
286 set_fin_sent(true);
287 CloseWriteSide();
288 }
289 return bytes_written;
290}
291
dmcardleba2fb7e2019-12-13 07:44:34 -0800292void QuicSpdyStream::WriteOrBufferBody(quiche::QuicheStringPiece data,
293 bool fin) {
renjietanga29a96a2019-10-10 12:47:50 -0700294 if (!VersionUsesHttp3(transport_version()) || data.length() == 0) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500295 WriteOrBufferData(data, fin, nullptr);
296 return;
297 }
fayanga4b37b22019-06-18 13:37:47 -0700298 QuicConnection::ScopedPacketFlusher flusher(spdy_session_->connection());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500299
300 // Write frame header.
301 std::unique_ptr<char[]> buffer;
302 QuicByteCount header_length =
bnc46942722019-10-29 11:56:21 -0700303 HttpEncoder::SerializeDataFrameHeader(data.length(), &buffer);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500304 unacked_frame_headers_offsets_.Add(
305 send_buffer().stream_offset(),
306 send_buffer().stream_offset() + header_length);
dschinazi88bd5b02019-10-10 00:52:20 -0700307 QUIC_DLOG(INFO) << ENDPOINT << "Stream " << id()
renjietang2abedac2019-05-20 14:04:50 -0700308 << " is writing DATA frame header of length "
QUICHE teama6ef0a62019-03-07 20:34:33 -0500309 << header_length;
dmcardleba2fb7e2019-12-13 07:44:34 -0800310 WriteOrBufferData(quiche::QuicheStringPiece(buffer.get(), header_length),
311 false, nullptr);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500312
313 // Write body.
dschinazi88bd5b02019-10-10 00:52:20 -0700314 QUIC_DLOG(INFO) << ENDPOINT << "Stream " << id()
renjietang2abedac2019-05-20 14:04:50 -0700315 << " is writing DATA frame payload of length "
renjietangdbe98342019-10-18 11:00:57 -0700316 << data.length() << " with fin " << fin;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500317 WriteOrBufferData(data, fin, nullptr);
318}
319
320size_t QuicSpdyStream::WriteTrailers(
321 SpdyHeaderBlock trailer_block,
322 QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
323 if (fin_sent()) {
324 QUIC_BUG << "Trailers cannot be sent after a FIN, on stream " << id();
325 return 0;
326 }
327
renjietanga29a96a2019-10-10 12:47:50 -0700328 if (!VersionUsesHttp3(transport_version())) {
renjietang2abedac2019-05-20 14:04:50 -0700329 // The header block must contain the final offset for this stream, as the
330 // trailers may be processed out of order at the peer.
331 const QuicStreamOffset final_offset =
332 stream_bytes_written() + BufferedDataBytes();
dschinazi88bd5b02019-10-10 00:52:20 -0700333 QUIC_DLOG(INFO) << ENDPOINT << "Inserting trailer: ("
334 << kFinalOffsetHeaderKey << ", " << final_offset << ")";
dmcardleba2fb7e2019-12-13 07:44:34 -0800335 trailer_block.insert(
336 std::make_pair(kFinalOffsetHeaderKey,
337 quiche::QuicheTextUtils::Uint64ToString(final_offset)));
renjietang2abedac2019-05-20 14:04:50 -0700338 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500339
340 // Write the trailing headers with a FIN, and close stream for writing:
341 // trailers are the last thing to be sent on a stream.
342 const bool kFin = true;
343 size_t bytes_written =
344 WriteHeadersImpl(std::move(trailer_block), kFin, std::move(ack_listener));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500345
renjietang2abedac2019-05-20 14:04:50 -0700346 // If trailers are sent on the headers stream, then |fin_sent_| needs to be
347 // set without actually sending a FIN on this stream.
renjietanga29a96a2019-10-10 12:47:50 -0700348 if (!VersionUsesHttp3(transport_version())) {
renjietang2abedac2019-05-20 14:04:50 -0700349 set_fin_sent(kFin);
350
351 // Also, write side of this stream needs to be closed. However, only do
352 // this if there is no more buffered data, otherwise it will never be sent.
353 if (BufferedDataBytes() == 0) {
354 CloseWriteSide();
355 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500356 }
357
358 return bytes_written;
359}
360
renjietang3c3dfb72019-07-26 11:55:52 -0700361void QuicSpdyStream::WritePushPromise(const PushPromiseFrame& frame) {
renjietanga29a96a2019-10-10 12:47:50 -0700362 DCHECK(VersionUsesHttp3(transport_version()));
renjietang3c3dfb72019-07-26 11:55:52 -0700363 std::unique_ptr<char[]> push_promise_frame_with_id;
364 const size_t push_promise_frame_length =
bnc46942722019-10-29 11:56:21 -0700365 HttpEncoder::SerializePushPromiseFrameWithOnlyPushId(
renjietang3c3dfb72019-07-26 11:55:52 -0700366 frame, &push_promise_frame_with_id);
367
368 unacked_frame_headers_offsets_.Add(send_buffer().stream_offset(),
369 send_buffer().stream_offset() +
370 push_promise_frame_length +
371 frame.headers.length());
372
373 // Write Push Promise frame header and push id.
dschinazi88bd5b02019-10-10 00:52:20 -0700374 QUIC_DLOG(INFO) << ENDPOINT << "Stream " << id()
renjietang3c3dfb72019-07-26 11:55:52 -0700375 << " is writing Push Promise frame header of length "
376 << push_promise_frame_length << " , with promised id "
377 << frame.push_id;
dmcardleba2fb7e2019-12-13 07:44:34 -0800378 WriteOrBufferData(quiche::QuicheStringPiece(push_promise_frame_with_id.get(),
379 push_promise_frame_length),
renjietang3c3dfb72019-07-26 11:55:52 -0700380 /* fin = */ false, /* ack_listener = */ nullptr);
381
382 // Write response headers.
dschinazi88bd5b02019-10-10 00:52:20 -0700383 QUIC_DLOG(INFO) << ENDPOINT << "Stream " << id()
renjietang3c3dfb72019-07-26 11:55:52 -0700384 << " is writing Push Promise request header of length "
385 << frame.headers.length();
386 WriteOrBufferData(frame.headers, /* fin = */ false,
387 /* ack_listener = */ nullptr);
388}
389
QUICHE teama6ef0a62019-03-07 20:34:33 -0500390QuicConsumedData QuicSpdyStream::WritevBody(const struct iovec* iov,
391 int count,
392 bool fin) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500393 QuicMemSliceStorage storage(
394 iov, count,
395 session()->connection()->helper()->GetStreamSendBufferAllocator(),
396 GetQuicFlag(FLAGS_quic_send_buffer_max_data_slice_size));
397 return WriteBodySlices(storage.ToSpan(), fin);
398}
399
400QuicConsumedData QuicSpdyStream::WriteBodySlices(QuicMemSliceSpan slices,
401 bool fin) {
renjietanga29a96a2019-10-10 12:47:50 -0700402 if (!VersionUsesHttp3(transport_version()) || slices.empty()) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500403 return WriteMemSlices(slices, fin);
404 }
405
406 std::unique_ptr<char[]> buffer;
407 QuicByteCount header_length =
bnc46942722019-10-29 11:56:21 -0700408 HttpEncoder::SerializeDataFrameHeader(slices.total_length(), &buffer);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500409 if (!CanWriteNewDataAfterData(header_length)) {
410 return {0, false};
411 }
412
fayanga4b37b22019-06-18 13:37:47 -0700413 QuicConnection::ScopedPacketFlusher flusher(spdy_session_->connection());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500414
415 // Write frame header.
416 struct iovec header_iov = {static_cast<void*>(buffer.get()), header_length};
417 QuicMemSliceStorage storage(
418 &header_iov, 1,
419 spdy_session_->connection()->helper()->GetStreamSendBufferAllocator(),
420 GetQuicFlag(FLAGS_quic_send_buffer_max_data_slice_size));
421 unacked_frame_headers_offsets_.Add(
422 send_buffer().stream_offset(),
423 send_buffer().stream_offset() + header_length);
dschinazi88bd5b02019-10-10 00:52:20 -0700424 QUIC_DLOG(INFO) << ENDPOINT << "Stream " << id()
renjietang2abedac2019-05-20 14:04:50 -0700425 << " is writing DATA frame header of length "
QUICHE teama6ef0a62019-03-07 20:34:33 -0500426 << header_length;
427 WriteMemSlices(storage.ToSpan(), false);
428
429 // Write body.
dschinazi88bd5b02019-10-10 00:52:20 -0700430 QUIC_DLOG(INFO) << ENDPOINT << "Stream " << id()
renjietang2abedac2019-05-20 14:04:50 -0700431 << " is writing DATA frame payload of length "
QUICHE teama6ef0a62019-03-07 20:34:33 -0500432 << slices.total_length();
433 return WriteMemSlices(slices, fin);
434}
435
436size_t QuicSpdyStream::Readv(const struct iovec* iov, size_t iov_len) {
437 DCHECK(FinishedReadingHeaders());
renjietanga29a96a2019-10-10 12:47:50 -0700438 if (!VersionUsesHttp3(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500439 return sequencer()->Readv(iov, iov_len);
440 }
bncc9019492019-07-23 06:44:39 -0700441 size_t bytes_read = 0;
bnc0b83e0c2019-08-16 15:56:32 -0700442 sequencer()->MarkConsumed(body_manager_.ReadBody(iov, iov_len, &bytes_read));
bnc8d041302019-06-10 10:19:04 -0700443
renjietangbd1a0392019-05-31 11:36:24 -0700444 return bytes_read;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500445}
446
447int QuicSpdyStream::GetReadableRegions(iovec* iov, size_t iov_len) const {
448 DCHECK(FinishedReadingHeaders());
renjietanga29a96a2019-10-10 12:47:50 -0700449 if (!VersionUsesHttp3(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500450 return sequencer()->GetReadableRegions(iov, iov_len);
451 }
bnc0b83e0c2019-08-16 15:56:32 -0700452 return body_manager_.PeekBody(iov, iov_len);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500453}
454
455void QuicSpdyStream::MarkConsumed(size_t num_bytes) {
456 DCHECK(FinishedReadingHeaders());
renjietanga29a96a2019-10-10 12:47:50 -0700457 if (!VersionUsesHttp3(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500458 sequencer()->MarkConsumed(num_bytes);
459 return;
460 }
bnc8d041302019-06-10 10:19:04 -0700461
bnc0b83e0c2019-08-16 15:56:32 -0700462 sequencer()->MarkConsumed(body_manager_.OnBodyConsumed(num_bytes));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500463}
464
465bool QuicSpdyStream::IsDoneReading() const {
466 bool done_reading_headers = FinishedReadingHeaders();
467 bool done_reading_body = sequencer()->IsClosed();
468 bool done_reading_trailers = FinishedReadingTrailers();
469 return done_reading_headers && done_reading_body && done_reading_trailers;
470}
471
472bool QuicSpdyStream::HasBytesToRead() const {
renjietanga29a96a2019-10-10 12:47:50 -0700473 if (!VersionUsesHttp3(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500474 return sequencer()->HasBytesToRead();
475 }
bnc0b83e0c2019-08-16 15:56:32 -0700476 return body_manager_.HasBytesToRead();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500477}
478
479void QuicSpdyStream::MarkTrailersConsumed() {
480 trailers_consumed_ = true;
481}
482
483uint64_t QuicSpdyStream::total_body_bytes_read() const {
renjietanga29a96a2019-10-10 12:47:50 -0700484 if (VersionUsesHttp3(transport_version())) {
bnc0b83e0c2019-08-16 15:56:32 -0700485 return body_manager_.total_body_bytes_received();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500486 }
487 return sequencer()->NumBytesConsumed();
488}
489
490void QuicSpdyStream::ConsumeHeaderList() {
491 header_list_.Clear();
renjietang2abedac2019-05-20 14:04:50 -0700492
bnc8d041302019-06-10 10:19:04 -0700493 if (!FinishedReadingHeaders()) {
renjietang2abedac2019-05-20 14:04:50 -0700494 return;
495 }
496
renjietanga29a96a2019-10-10 12:47:50 -0700497 if (!VersionUsesHttp3(transport_version())) {
bnc8d041302019-06-10 10:19:04 -0700498 sequencer()->SetUnblocked();
renjietang2abedac2019-05-20 14:04:50 -0700499 return;
500 }
501
bnc0b83e0c2019-08-16 15:56:32 -0700502 if (body_manager_.HasBytesToRead()) {
renjietang2abedac2019-05-20 14:04:50 -0700503 OnBodyAvailable();
504 return;
505 }
506
507 if (sequencer()->IsClosed() &&
508 !on_body_available_called_because_sequencer_is_closed_) {
509 on_body_available_called_because_sequencer_is_closed_ = true;
510 OnBodyAvailable();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500511 }
512}
513
fayang476683a2019-07-25 12:42:16 -0700514void QuicSpdyStream::OnStreamHeadersPriority(
515 const spdy::SpdyStreamPrecedence& precedence) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500516 DCHECK_EQ(Perspective::IS_SERVER, session()->connection()->perspective());
fayang476683a2019-07-25 12:42:16 -0700517 SetPriority(precedence);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500518}
519
bnc62706802019-06-26 12:37:46 -0700520void QuicSpdyStream::OnStreamHeaderList(bool fin,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500521 size_t frame_len,
522 const QuicHeaderList& header_list) {
bnc8d041302019-06-10 10:19:04 -0700523 // TODO(b/134706391): remove |fin| argument.
bnc446887e2019-11-27 13:08:28 -0800524 // When using Google QUIC, an empty header list indicates that the size limit
525 // has been exceeded.
526 // When using IETF QUIC, there is an explicit signal from
527 // QpackDecodedHeadersAccumulator.
528 if ((VersionUsesHttp3(transport_version()) &&
529 header_list_size_limit_exceeded_) ||
530 (!VersionUsesHttp3(transport_version()) && header_list.empty())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500531 OnHeadersTooLarge();
532 if (IsDoneReading()) {
bnc62706802019-06-26 12:37:46 -0700533 return;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500534 }
535 }
536 if (!headers_decompressed_) {
537 OnInitialHeadersComplete(fin, frame_len, header_list);
538 } else {
539 OnTrailingHeadersComplete(fin, frame_len, header_list);
540 }
541}
542
bncb7ac1042019-12-06 10:32:23 -0800543void QuicSpdyStream::OnHeadersDecoded(QuicHeaderList headers,
544 bool header_list_size_limit_exceeded) {
545 header_list_size_limit_exceeded_ = header_list_size_limit_exceeded;
bnc232ff9b2019-11-13 18:38:22 -0800546 qpack_decoded_headers_accumulator_.reset();
547
548 QuicSpdySession::LogHeaderCompressionRatioHistogram(
549 /* using_qpack = */ true,
550 /* is_sent = */ false, headers.compressed_header_bytes(),
551 headers.uncompressed_header_bytes());
552
553 if (spdy_session_->promised_stream_id() ==
554 QuicUtils::GetInvalidStreamId(session()->transport_version())) {
555 const QuicByteCount frame_length = headers_decompressed_
556 ? trailers_payload_length_
557 : headers_payload_length_;
558 OnStreamHeaderList(/* fin = */ false, frame_length, headers);
559 } else {
560 spdy_session_->OnHeaderList(headers);
561 }
562
563 if (blocked_on_decoding_headers_) {
564 blocked_on_decoding_headers_ = false;
565 // Continue decoding HTTP/3 frames.
566 OnDataAvailable();
567 }
bncc057c012019-07-02 11:13:22 -0700568}
569
dmcardleba2fb7e2019-12-13 07:44:34 -0800570void QuicSpdyStream::OnHeaderDecodingError(
571 quiche::QuicheStringPiece error_message) {
bnc232ff9b2019-11-13 18:38:22 -0800572 qpack_decoded_headers_accumulator_.reset();
573
dmcardleba2fb7e2019-12-13 07:44:34 -0800574 std::string connection_close_error_message = quiche::QuicheStrCat(
bnc232ff9b2019-11-13 18:38:22 -0800575 "Error decoding ", headers_decompressed_ ? "trailers" : "headers",
576 " on stream ", id(), ": ", error_message);
577 CloseConnectionWithDetails(QUIC_QPACK_DECOMPRESSION_FAILED,
578 connection_close_error_message);
bncc057c012019-07-02 11:13:22 -0700579}
580
QUICHE teama6ef0a62019-03-07 20:34:33 -0500581void QuicSpdyStream::OnHeadersTooLarge() {
renjietanga29a96a2019-10-10 12:47:50 -0700582 if (VersionUsesHttp3(transport_version())) {
bnc446887e2019-11-27 13:08:28 -0800583 // TODO(b/124216424): Reset stream with H3_REQUEST_CANCELLED (if client)
584 // or with H3_REQUEST_REJECTED (if server).
renjietang2abedac2019-05-20 14:04:50 -0700585 std::string error_message =
dmcardleba2fb7e2019-12-13 07:44:34 -0800586 quiche::QuicheStrCat("Too large headers received on stream ", id());
renjietang2abedac2019-05-20 14:04:50 -0700587 CloseConnectionWithDetails(QUIC_HEADERS_STREAM_DATA_DECOMPRESS_FAILURE,
588 error_message);
589 } else {
590 Reset(QUIC_HEADERS_TOO_LARGE);
591 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500592}
593
594void QuicSpdyStream::OnInitialHeadersComplete(
595 bool fin,
596 size_t /*frame_len*/,
597 const QuicHeaderList& header_list) {
bnc8d041302019-06-10 10:19:04 -0700598 // TODO(b/134706391): remove |fin| argument.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500599 headers_decompressed_ = true;
600 header_list_ = header_list;
renjietang2abedac2019-05-20 14:04:50 -0700601
renjietanga29a96a2019-10-10 12:47:50 -0700602 if (VersionUsesHttp3(transport_version())) {
renjietang2abedac2019-05-20 14:04:50 -0700603 if (fin) {
604 OnStreamFrame(
605 QuicStreamFrame(id(), /* fin = */ true,
606 flow_controller()->highest_received_byte_offset(),
dmcardleba2fb7e2019-12-13 07:44:34 -0800607 quiche::QuicheStringPiece()));
renjietang2abedac2019-05-20 14:04:50 -0700608 }
609 return;
610 }
611
bnc70f78fc2019-08-26 10:12:31 -0700612 if (fin && !rst_sent()) {
dmcardleba2fb7e2019-12-13 07:44:34 -0800613 OnStreamFrame(QuicStreamFrame(id(), fin, /* offset = */ 0,
614 quiche::QuicheStringPiece()));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500615 }
616 if (FinishedReadingHeaders()) {
617 sequencer()->SetUnblocked();
618 }
619}
620
621void QuicSpdyStream::OnPromiseHeaderList(
622 QuicStreamId /* promised_id */,
623 size_t /* frame_len */,
624 const QuicHeaderList& /*header_list */) {
625 // To be overridden in QuicSpdyClientStream. Not supported on
626 // server side.
627 session()->connection()->CloseConnection(
628 QUIC_INVALID_HEADERS_STREAM_DATA, "Promise headers received by server",
629 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
630}
631
632void QuicSpdyStream::OnTrailingHeadersComplete(
633 bool fin,
634 size_t /*frame_len*/,
635 const QuicHeaderList& header_list) {
bnc8d041302019-06-10 10:19:04 -0700636 // TODO(b/134706391): remove |fin| argument.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500637 DCHECK(!trailers_decompressed_);
renjietanga29a96a2019-10-10 12:47:50 -0700638 if (!VersionUsesHttp3(transport_version()) && fin_received()) {
dschinazi88bd5b02019-10-10 00:52:20 -0700639 QUIC_DLOG(INFO) << ENDPOINT
640 << "Received Trailers after FIN, on stream: " << id();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500641 session()->connection()->CloseConnection(
642 QUIC_INVALID_HEADERS_STREAM_DATA, "Trailers after fin",
643 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
644 return;
645 }
renjietang2abedac2019-05-20 14:04:50 -0700646
renjietanga29a96a2019-10-10 12:47:50 -0700647 if (!VersionUsesHttp3(transport_version()) && !fin) {
dschinazi88bd5b02019-10-10 00:52:20 -0700648 QUIC_DLOG(INFO) << ENDPOINT
649 << "Trailers must have FIN set, on stream: " << id();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500650 session()->connection()->CloseConnection(
651 QUIC_INVALID_HEADERS_STREAM_DATA, "Fin missing from trailers",
652 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
653 return;
654 }
655
656 size_t final_byte_offset = 0;
renjietanga29a96a2019-10-10 12:47:50 -0700657 const bool expect_final_byte_offset = !VersionUsesHttp3(transport_version());
renjietang2abedac2019-05-20 14:04:50 -0700658 if (!SpdyUtils::CopyAndValidateTrailers(header_list, expect_final_byte_offset,
bnc5231ee22019-04-15 19:02:13 -0700659 &final_byte_offset,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500660 &received_trailers_)) {
dschinazi88bd5b02019-10-10 00:52:20 -0700661 QUIC_DLOG(ERROR) << ENDPOINT << "Trailers for stream " << id()
662 << " are malformed.";
QUICHE teama6ef0a62019-03-07 20:34:33 -0500663 session()->connection()->CloseConnection(
664 QUIC_INVALID_HEADERS_STREAM_DATA, "Trailers are malformed",
665 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
666 return;
667 }
668 trailers_decompressed_ = true;
bncab33c712019-06-28 15:42:15 -0700669 if (fin) {
670 const QuicStreamOffset offset =
renjietanga29a96a2019-10-10 12:47:50 -0700671 VersionUsesHttp3(transport_version())
bncab33c712019-06-28 15:42:15 -0700672 ? flow_controller()->highest_received_byte_offset()
673 : final_byte_offset;
dmcardleba2fb7e2019-12-13 07:44:34 -0800674 OnStreamFrame(
675 QuicStreamFrame(id(), fin, offset, quiche::QuicheStringPiece()));
bncab33c712019-06-28 15:42:15 -0700676 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500677}
678
fayang476683a2019-07-25 12:42:16 -0700679void QuicSpdyStream::OnPriorityFrame(
680 const spdy::SpdyStreamPrecedence& precedence) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500681 DCHECK_EQ(Perspective::IS_SERVER, session()->connection()->perspective());
fayang476683a2019-07-25 12:42:16 -0700682 SetPriority(precedence);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500683}
684
685void QuicSpdyStream::OnStreamReset(const QuicRstStreamFrame& frame) {
686 if (frame.error_code != QUIC_STREAM_NO_ERROR) {
bnc84aa7e52019-12-13 05:25:21 -0800687 if (VersionUsesHttp3(transport_version()) && !fin_received() &&
688 spdy_session_->qpack_decoder()) {
689 spdy_session_->qpack_decoder()->OnStreamReset(id());
690 }
bnc6f18a822019-11-27 17:50:38 -0800691
QUICHE teama6ef0a62019-03-07 20:34:33 -0500692 QuicStream::OnStreamReset(frame);
693 return;
694 }
bnc6f18a822019-11-27 17:50:38 -0800695
dschinazi88bd5b02019-10-10 00:52:20 -0700696 QUIC_DVLOG(1) << ENDPOINT
697 << "Received QUIC_STREAM_NO_ERROR, not discarding response";
QUICHE teama6ef0a62019-03-07 20:34:33 -0500698 set_rst_received(true);
699 MaybeIncreaseHighestReceivedOffset(frame.byte_offset);
700 set_stream_error(frame.error_code);
701 CloseWriteSide();
702}
703
bnc6f18a822019-11-27 17:50:38 -0800704void QuicSpdyStream::Reset(QuicRstStreamErrorCode error) {
bnc84aa7e52019-12-13 05:25:21 -0800705 if (VersionUsesHttp3(transport_version()) && !fin_received() &&
706 spdy_session_->qpack_decoder()) {
707 spdy_session_->qpack_decoder()->OnStreamReset(id());
708 }
bnc6f18a822019-11-27 17:50:38 -0800709
710 QuicStream::Reset(error);
711}
712
QUICHE teama6ef0a62019-03-07 20:34:33 -0500713void QuicSpdyStream::OnDataAvailable() {
renjietanga29a96a2019-10-10 12:47:50 -0700714 if (!VersionUsesHttp3(transport_version())) {
renjietang2abedac2019-05-20 14:04:50 -0700715 // Sequencer must be blocked until headers are consumed.
716 DCHECK(FinishedReadingHeaders());
717 }
bncfa0c90c2019-03-13 14:14:28 -0700718
renjietanga29a96a2019-10-10 12:47:50 -0700719 if (!VersionUsesHttp3(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500720 OnBodyAvailable();
721 return;
722 }
723
bnc8aadca72019-06-28 11:09:39 -0700724 if (is_decoder_processing_input_) {
725 // Let the outermost nested OnDataAvailable() call do the work.
726 return;
727 }
728
bncc057c012019-07-02 11:13:22 -0700729 if (blocked_on_decoding_headers_) {
730 return;
731 }
732
QUICHE teama6ef0a62019-03-07 20:34:33 -0500733 iovec iov;
bncef518152019-07-18 05:36:44 -0700734 while (session()->connection()->connected() && !reading_stopped() &&
735 decoder_.error() == QUIC_NO_ERROR) {
bnc8aadca72019-06-28 11:09:39 -0700736 DCHECK_GE(sequencer_offset_, sequencer()->NumBytesConsumed());
737 if (!sequencer()->PeekRegion(sequencer_offset_, &iov)) {
738 break;
739 }
740
bncd48a92e2019-06-18 19:24:58 -0700741 DCHECK(!sequencer()->IsClosed());
bnc8aadca72019-06-28 11:09:39 -0700742 is_decoder_processing_input_ = true;
743 QuicByteCount processed_bytes = decoder_.ProcessInput(
744 reinterpret_cast<const char*>(iov.iov_base), iov.iov_len);
745 is_decoder_processing_input_ = false;
746 sequencer_offset_ += processed_bytes;
bncc057c012019-07-02 11:13:22 -0700747 if (blocked_on_decoding_headers_) {
748 return;
749 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500750 }
751
renjietang2abedac2019-05-20 14:04:50 -0700752 // Do not call OnBodyAvailable() until headers are consumed.
753 if (!FinishedReadingHeaders()) {
754 return;
755 }
756
bnc0b83e0c2019-08-16 15:56:32 -0700757 if (body_manager_.HasBytesToRead()) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500758 OnBodyAvailable();
759 return;
760 }
761
renjietang2abedac2019-05-20 14:04:50 -0700762 if (sequencer()->IsClosed() &&
763 !on_body_available_called_because_sequencer_is_closed_) {
764 on_body_available_called_because_sequencer_is_closed_ = true;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500765 OnBodyAvailable();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500766 }
767}
768
769void QuicSpdyStream::OnClose() {
770 QuicStream::OnClose();
771
772 if (visitor_) {
773 Visitor* visitor = visitor_;
774 // Calling Visitor::OnClose() may result the destruction of the visitor,
775 // so we need to ensure we don't call it again.
776 visitor_ = nullptr;
777 visitor->OnClose(this);
778 }
779}
780
781void QuicSpdyStream::OnCanWrite() {
782 QuicStream::OnCanWrite();
783
784 // Trailers (and hence a FIN) may have been sent ahead of queued body bytes.
785 if (!HasBufferedData() && fin_sent()) {
786 CloseWriteSide();
787 }
788}
789
790bool QuicSpdyStream::FinishedReadingHeaders() const {
791 return headers_decompressed_ && header_list_.empty();
792}
793
bncd0119902019-06-26 12:12:33 -0700794// static
QUICHE teama6ef0a62019-03-07 20:34:33 -0500795bool QuicSpdyStream::ParseHeaderStatusCode(const SpdyHeaderBlock& header,
bncd0119902019-06-26 12:12:33 -0700796 int* status_code) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500797 SpdyHeaderBlock::const_iterator it = header.find(spdy::kHttp2StatusHeader);
798 if (it == header.end()) {
799 return false;
800 }
dmcardleba2fb7e2019-12-13 07:44:34 -0800801 const quiche::QuicheStringPiece status(it->second);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500802 if (status.size() != 3) {
803 return false;
804 }
805 // First character must be an integer in range [1,5].
806 if (status[0] < '1' || status[0] > '5') {
807 return false;
808 }
809 // The remaining two characters must be integers.
810 if (!isdigit(status[1]) || !isdigit(status[2])) {
811 return false;
812 }
dmcardleba2fb7e2019-12-13 07:44:34 -0800813 return quiche::QuicheTextUtils::StringToInt(status, status_code);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500814}
815
816bool QuicSpdyStream::FinishedReadingTrailers() const {
817 // If no further trailing headers are expected, and the decompressed trailers
818 // (if any) have been consumed, then reading of trailers is finished.
819 if (!fin_received()) {
820 return false;
821 } else if (!trailers_decompressed_) {
822 return true;
823 } else {
824 return trailers_consumed_;
825 }
826}
827
828void QuicSpdyStream::ClearSession() {
829 spdy_session_ = nullptr;
830}
831
bnca2b13be2019-07-31 12:04:20 -0700832bool QuicSpdyStream::OnDataFrameStart(QuicByteCount header_length) {
renjietanga29a96a2019-10-10 12:47:50 -0700833 DCHECK(VersionUsesHttp3(transport_version()));
bnc519216c2019-07-09 05:03:48 -0700834 if (!headers_decompressed_ || trailers_decompressed_) {
835 // TODO(b/124216424): Change error code to HTTP_UNEXPECTED_FRAME.
836 session()->connection()->CloseConnection(
837 QUIC_INVALID_HEADERS_STREAM_DATA, "Unexpected DATA frame received.",
838 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
839 return false;
840 }
841
bnc0b83e0c2019-08-16 15:56:32 -0700842 sequencer()->MarkConsumed(body_manager_.OnNonBody(header_length));
bnce5f9c032019-07-25 11:30:40 -0700843
renjietang546a6282019-06-03 10:21:21 -0700844 return true;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500845}
846
dmcardleba2fb7e2019-12-13 07:44:34 -0800847bool QuicSpdyStream::OnDataFramePayload(quiche::QuicheStringPiece payload) {
renjietanga29a96a2019-10-10 12:47:50 -0700848 DCHECK(VersionUsesHttp3(transport_version()));
bncfa0c90c2019-03-13 14:14:28 -0700849
bnc0b83e0c2019-08-16 15:56:32 -0700850 body_manager_.OnBody(payload);
bnce5f9c032019-07-25 11:30:40 -0700851
renjietang546a6282019-06-03 10:21:21 -0700852 return true;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500853}
854
renjietang546a6282019-06-03 10:21:21 -0700855bool QuicSpdyStream::OnDataFrameEnd() {
renjietanga29a96a2019-10-10 12:47:50 -0700856 DCHECK(VersionUsesHttp3(transport_version()));
dschinazi88bd5b02019-10-10 00:52:20 -0700857 QUIC_DVLOG(1) << ENDPOINT
858 << "Reaches the end of a data frame. Total bytes received are "
bnc0b83e0c2019-08-16 15:56:32 -0700859 << body_manager_.total_body_bytes_received();
renjietang546a6282019-06-03 10:21:21 -0700860 return true;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500861}
862
863bool QuicSpdyStream::OnStreamFrameAcked(QuicStreamOffset offset,
864 QuicByteCount data_length,
865 bool fin_acked,
866 QuicTime::Delta ack_delay_time,
867 QuicByteCount* newly_acked_length) {
868 const bool new_data_acked = QuicStream::OnStreamFrameAcked(
869 offset, data_length, fin_acked, ack_delay_time, newly_acked_length);
870
871 const QuicByteCount newly_acked_header_length =
872 GetNumFrameHeadersInInterval(offset, data_length);
873 DCHECK_LE(newly_acked_header_length, *newly_acked_length);
874 unacked_frame_headers_offsets_.Difference(offset, offset + data_length);
875 if (ack_listener_ != nullptr && new_data_acked) {
876 ack_listener_->OnPacketAcked(
877 *newly_acked_length - newly_acked_header_length, ack_delay_time);
878 }
879 return new_data_acked;
880}
881
882void QuicSpdyStream::OnStreamFrameRetransmitted(QuicStreamOffset offset,
883 QuicByteCount data_length,
884 bool fin_retransmitted) {
885 QuicStream::OnStreamFrameRetransmitted(offset, data_length,
886 fin_retransmitted);
887
888 const QuicByteCount retransmitted_header_length =
889 GetNumFrameHeadersInInterval(offset, data_length);
890 DCHECK_LE(retransmitted_header_length, data_length);
891
892 if (ack_listener_ != nullptr) {
893 ack_listener_->OnPacketRetransmitted(data_length -
894 retransmitted_header_length);
895 }
896}
897
898QuicByteCount QuicSpdyStream::GetNumFrameHeadersInInterval(
899 QuicStreamOffset offset,
900 QuicByteCount data_length) const {
901 QuicByteCount header_acked_length = 0;
902 QuicIntervalSet<QuicStreamOffset> newly_acked(offset, offset + data_length);
903 newly_acked.Intersection(unacked_frame_headers_offsets_);
904 for (const auto& interval : newly_acked) {
905 header_acked_length += interval.Length();
906 }
907 return header_acked_length;
908}
909
bnca2b13be2019-07-31 12:04:20 -0700910bool QuicSpdyStream::OnHeadersFrameStart(QuicByteCount header_length) {
renjietanga29a96a2019-10-10 12:47:50 -0700911 DCHECK(VersionUsesHttp3(transport_version()));
renjietang2abedac2019-05-20 14:04:50 -0700912 DCHECK(!qpack_decoded_headers_accumulator_);
913
bnc519216c2019-07-09 05:03:48 -0700914 if (trailers_decompressed_) {
915 // TODO(b/124216424): Change error code to HTTP_UNEXPECTED_FRAME.
916 session()->connection()->CloseConnection(
917 QUIC_INVALID_HEADERS_STREAM_DATA,
918 "HEADERS frame received after trailing HEADERS.",
919 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
920 return false;
921 }
922
bnc0b83e0c2019-08-16 15:56:32 -0700923 sequencer()->MarkConsumed(body_manager_.OnNonBody(header_length));
renjietang2abedac2019-05-20 14:04:50 -0700924
925 qpack_decoded_headers_accumulator_ =
vasilvv0fc587f2019-09-06 13:33:08 -0700926 std::make_unique<QpackDecodedHeadersAccumulator>(
bncc057c012019-07-02 11:13:22 -0700927 id(), spdy_session_->qpack_decoder(), this,
bncbdd303e2019-07-09 05:33:17 -0700928 spdy_session_->max_inbound_header_list_size());
bnc8d041302019-06-10 10:19:04 -0700929
renjietang546a6282019-06-03 10:21:21 -0700930 return true;
bnc62446bc2019-03-14 06:11:25 -0700931}
932
dmcardleba2fb7e2019-12-13 07:44:34 -0800933bool QuicSpdyStream::OnHeadersFramePayload(quiche::QuicheStringPiece payload) {
renjietanga29a96a2019-10-10 12:47:50 -0700934 DCHECK(VersionUsesHttp3(transport_version()));
bncfcd42352019-09-20 17:55:47 -0700935 DCHECK(qpack_decoded_headers_accumulator_);
renjietang2abedac2019-05-20 14:04:50 -0700936
bnca2b13be2019-07-31 12:04:20 -0700937 if (headers_decompressed_) {
938 trailers_payload_length_ += payload.length();
939 } else {
940 headers_payload_length_ += payload.length();
941 }
942
bnc232ff9b2019-11-13 18:38:22 -0800943 qpack_decoded_headers_accumulator_->Decode(payload);
bnc8d041302019-06-10 10:19:04 -0700944
bnc232ff9b2019-11-13 18:38:22 -0800945 // |qpack_decoded_headers_accumulator_| is reset if an error is detected.
bncf9ff46b2019-11-26 10:32:09 -0800946 if (!qpack_decoded_headers_accumulator_) {
947 return false;
948 }
949
950 sequencer()->MarkConsumed(body_manager_.OnNonBody(payload.size()));
951 return true;
bnc62446bc2019-03-14 06:11:25 -0700952}
953
renjietang546a6282019-06-03 10:21:21 -0700954bool QuicSpdyStream::OnHeadersFrameEnd() {
renjietanga29a96a2019-10-10 12:47:50 -0700955 DCHECK(VersionUsesHttp3(transport_version()));
bncfcd42352019-09-20 17:55:47 -0700956 DCHECK(qpack_decoded_headers_accumulator_);
renjietang2abedac2019-05-20 14:04:50 -0700957
bnc232ff9b2019-11-13 18:38:22 -0800958 qpack_decoded_headers_accumulator_->EndHeaderBlock();
bncc057c012019-07-02 11:13:22 -0700959
bnc232ff9b2019-11-13 18:38:22 -0800960 // If decoding is complete or an error is detected, then
961 // |qpack_decoded_headers_accumulator_| is already reset.
962 if (qpack_decoded_headers_accumulator_) {
bncc057c012019-07-02 11:13:22 -0700963 blocked_on_decoding_headers_ = true;
964 return false;
965 }
966
bncc057c012019-07-02 11:13:22 -0700967 return !sequencer()->IsClosed() && !reading_stopped();
968}
969
bncf0db6542019-09-23 11:18:28 -0700970bool QuicSpdyStream::OnPushPromiseFrameStart(QuicByteCount header_length) {
renjietanga29a96a2019-10-10 12:47:50 -0700971 DCHECK(VersionUsesHttp3(transport_version()));
bncf0db6542019-09-23 11:18:28 -0700972 DCHECK(!qpack_decoded_headers_accumulator_);
973
974 sequencer()->MarkConsumed(body_manager_.OnNonBody(header_length));
975
976 return true;
977}
978
979bool QuicSpdyStream::OnPushPromiseFramePushId(PushId push_id,
980 QuicByteCount push_id_length) {
renjietanga29a96a2019-10-10 12:47:50 -0700981 DCHECK(VersionUsesHttp3(transport_version()));
renjietang3c3dfb72019-07-26 11:55:52 -0700982 DCHECK(!qpack_decoded_headers_accumulator_);
983
984 // TODO(renjietang): Check max push id and handle errors.
985 spdy_session_->OnPushPromise(id(), push_id);
bncf0db6542019-09-23 11:18:28 -0700986 sequencer()->MarkConsumed(body_manager_.OnNonBody(push_id_length));
renjietang3c3dfb72019-07-26 11:55:52 -0700987
988 qpack_decoded_headers_accumulator_ =
vasilvv0fc587f2019-09-06 13:33:08 -0700989 std::make_unique<QpackDecodedHeadersAccumulator>(
renjietang3c3dfb72019-07-26 11:55:52 -0700990 id(), spdy_session_->qpack_decoder(), this,
991 spdy_session_->max_inbound_header_list_size());
992
993 return true;
994}
995
dmcardleba2fb7e2019-12-13 07:44:34 -0800996bool QuicSpdyStream::OnPushPromiseFramePayload(
997 quiche::QuicheStringPiece payload) {
renjietang3c3dfb72019-07-26 11:55:52 -0700998 spdy_session_->OnCompressedFrameSize(payload.length());
999 return OnHeadersFramePayload(payload);
1000}
1001
1002bool QuicSpdyStream::OnPushPromiseFrameEnd() {
renjietanga29a96a2019-10-10 12:47:50 -07001003 DCHECK(VersionUsesHttp3(transport_version()));
renjietang3c3dfb72019-07-26 11:55:52 -07001004
renjietang6fbdaf42019-07-29 10:50:54 -07001005 return OnHeadersFrameEnd();
renjietang3c3dfb72019-07-26 11:55:52 -07001006}
1007
bnc25827c42019-07-29 08:57:24 -07001008bool QuicSpdyStream::OnUnknownFrameStart(uint64_t frame_type,
bnca2b13be2019-07-31 12:04:20 -07001009 QuicByteCount header_length) {
bnc25827c42019-07-29 08:57:24 -07001010 // Ignore unknown frames, but consume frame header.
dschinazi88bd5b02019-10-10 00:52:20 -07001011 QUIC_DVLOG(1) << ENDPOINT << "Discarding " << header_length
bnc25827c42019-07-29 08:57:24 -07001012 << " byte long frame header of frame of unknown type "
1013 << frame_type << ".";
bnc0b83e0c2019-08-16 15:56:32 -07001014 sequencer()->MarkConsumed(body_manager_.OnNonBody(header_length));
bnc25827c42019-07-29 08:57:24 -07001015 return true;
1016}
1017
dmcardleba2fb7e2019-12-13 07:44:34 -08001018bool QuicSpdyStream::OnUnknownFramePayload(quiche::QuicheStringPiece payload) {
bnc25827c42019-07-29 08:57:24 -07001019 // Ignore unknown frames, but consume frame payload.
dschinazi88bd5b02019-10-10 00:52:20 -07001020 QUIC_DVLOG(1) << ENDPOINT << "Discarding " << payload.size()
bnc25827c42019-07-29 08:57:24 -07001021 << " bytes of payload of frame of unknown type.";
bnc0b83e0c2019-08-16 15:56:32 -07001022 sequencer()->MarkConsumed(body_manager_.OnNonBody(payload.size()));
bnc25827c42019-07-29 08:57:24 -07001023 return true;
1024}
1025
1026bool QuicSpdyStream::OnUnknownFrameEnd() {
1027 return true;
1028}
1029
renjietang2abedac2019-05-20 14:04:50 -07001030size_t QuicSpdyStream::WriteHeadersImpl(
1031 spdy::SpdyHeaderBlock header_block,
1032 bool fin,
1033 QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
renjietanga29a96a2019-10-10 12:47:50 -07001034 if (!VersionUsesHttp3(transport_version())) {
renjietang2abedac2019-05-20 14:04:50 -07001035 return spdy_session_->WriteHeadersOnHeadersStream(
fayang476683a2019-07-25 12:42:16 -07001036 id(), std::move(header_block), fin, precedence(),
renjietang2abedac2019-05-20 14:04:50 -07001037 std::move(ack_listener));
1038 }
1039
bnccd3c4b52020-01-10 11:13:18 -08001040 if (!priority_sent_) {
1041 PriorityUpdateFrame priority_update;
1042 priority_update.prioritized_element_type = REQUEST_STREAM;
1043 priority_update.prioritized_element_id = id();
1044 // Value between 0 and 7, inclusive. Lower value means higher priority.
1045 int urgency = precedence().spdy3_priority();
1046 priority_update.priority_field_value = quiche::QuicheStrCat("u=", urgency);
1047 spdy_session_->WriteHttp3PriorityUpdate(priority_update);
1048 priority_sent_ = true;
1049 }
renjietang7498c8c2019-07-02 19:28:42 -07001050
renjietang2abedac2019-05-20 14:04:50 -07001051 // Encode header list.
bnc609c24e2019-09-10 05:24:32 -07001052 QuicByteCount encoder_stream_sent_byte_count;
bncf21c1ad2019-06-20 20:09:50 -07001053 std::string encoded_headers =
bnc609c24e2019-09-10 05:24:32 -07001054 spdy_session_->qpack_encoder()->EncodeHeaderList(
1055 id(), header_block, &encoder_stream_sent_byte_count);
renjietang2abedac2019-05-20 14:04:50 -07001056
1057 // Write HEADERS frame.
1058 std::unique_ptr<char[]> headers_frame_header;
1059 const size_t headers_frame_header_length =
bnc46942722019-10-29 11:56:21 -07001060 HttpEncoder::SerializeHeadersFrameHeader(encoded_headers.size(),
1061 &headers_frame_header);
renjietang2abedac2019-05-20 14:04:50 -07001062 unacked_frame_headers_offsets_.Add(
1063 send_buffer().stream_offset(),
1064 send_buffer().stream_offset() + headers_frame_header_length);
1065
dschinazi88bd5b02019-10-10 00:52:20 -07001066 QUIC_DLOG(INFO) << ENDPOINT << "Stream " << id()
renjietang2abedac2019-05-20 14:04:50 -07001067 << " is writing HEADERS frame header of length "
1068 << headers_frame_header_length;
dmcardleba2fb7e2019-12-13 07:44:34 -08001069 WriteOrBufferData(quiche::QuicheStringPiece(headers_frame_header.get(),
1070 headers_frame_header_length),
1071 /* fin = */ false, /* ack_listener = */ nullptr);
renjietang2abedac2019-05-20 14:04:50 -07001072
dschinazi88bd5b02019-10-10 00:52:20 -07001073 QUIC_DLOG(INFO) << ENDPOINT << "Stream " << id()
renjietang2abedac2019-05-20 14:04:50 -07001074 << " is writing HEADERS frame payload of length "
renjietangdbe98342019-10-18 11:00:57 -07001075 << encoded_headers.length() << " with fin " << fin;
renjietang2abedac2019-05-20 14:04:50 -07001076 WriteOrBufferData(encoded_headers, fin, nullptr);
1077
bnc20a9ad92019-10-01 10:29:14 -07001078 QuicSpdySession::LogHeaderCompressionRatioHistogram(
1079 /* using_qpack = */ true,
1080 /* is_sent = */ true,
1081 encoded_headers.size() + encoder_stream_sent_byte_count,
1082 header_block.TotalBytesUsed());
1083
bnc609c24e2019-09-10 05:24:32 -07001084 return encoded_headers.size() + encoder_stream_sent_byte_count;
bnc62446bc2019-03-14 06:11:25 -07001085}
1086
QUICHE teama6ef0a62019-03-07 20:34:33 -05001087#undef ENDPOINT // undef for jumbo builds
1088} // namespace quic