blob: 67c24e48f4c3e36470fb193fdb6948321e960bba [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 {
renjietang87df0d02020-02-13 11:53:52 -080044 stream_->OnUnrecoverableError(decoder->error(), decoder->error_detail());
QUICHE teama6ef0a62019-03-07 20:34:33 -050045 }
46
dschinazi17d42422019-06-18 16:35:07 -070047 bool OnCancelPushFrame(const CancelPushFrame& /*frame*/) override {
QUICHE teama6ef0a62019-03-07 20:34:33 -050048 CloseConnectionOnWrongFrame("Cancel Push");
renjietang546a6282019-06-03 10:21:21 -070049 return false;
QUICHE teama6ef0a62019-03-07 20:34:33 -050050 }
51
dschinazi17d42422019-06-18 16:35:07 -070052 bool OnMaxPushIdFrame(const MaxPushIdFrame& /*frame*/) override {
QUICHE teama6ef0a62019-03-07 20:34:33 -050053 CloseConnectionOnWrongFrame("Max Push Id");
renjietang546a6282019-06-03 10:21:21 -070054 return false;
QUICHE teama6ef0a62019-03-07 20:34:33 -050055 }
56
dschinazi17d42422019-06-18 16:35:07 -070057 bool OnGoAwayFrame(const GoAwayFrame& /*frame*/) override {
QUICHE teama6ef0a62019-03-07 20:34:33 -050058 CloseConnectionOnWrongFrame("Goaway");
renjietang546a6282019-06-03 10:21:21 -070059 return false;
QUICHE teama6ef0a62019-03-07 20:34:33 -050060 }
61
bnca2b13be2019-07-31 12:04:20 -070062 bool OnSettingsFrameStart(QuicByteCount /*header_length*/) override {
renjietangf41bf642019-04-02 11:45:34 -070063 CloseConnectionOnWrongFrame("Settings");
renjietang546a6282019-06-03 10:21:21 -070064 return false;
renjietangf41bf642019-04-02 11:45:34 -070065 }
66
dschinazi17d42422019-06-18 16:35:07 -070067 bool OnSettingsFrame(const SettingsFrame& /*frame*/) override {
QUICHE teama6ef0a62019-03-07 20:34:33 -050068 CloseConnectionOnWrongFrame("Settings");
renjietang546a6282019-06-03 10:21:21 -070069 return false;
QUICHE teama6ef0a62019-03-07 20:34:33 -050070 }
71
bnc32f36f92020-03-27 15:48:45 -070072 bool OnDataFrameStart(QuicByteCount header_length,
73 QuicByteCount payload_length) override {
74 return stream_->OnDataFrameStart(header_length, payload_length);
QUICHE teama6ef0a62019-03-07 20:34:33 -050075 }
76
dmcardleba2fb7e2019-12-13 07:44:34 -080077 bool OnDataFramePayload(quiche::QuicheStringPiece payload) override {
bnc70914262019-03-16 12:49:50 -070078 DCHECK(!payload.empty());
renjietang546a6282019-06-03 10:21:21 -070079 return stream_->OnDataFramePayload(payload);
QUICHE teama6ef0a62019-03-07 20:34:33 -050080 }
81
renjietang546a6282019-06-03 10:21:21 -070082 bool OnDataFrameEnd() override { return stream_->OnDataFrameEnd(); }
QUICHE teama6ef0a62019-03-07 20:34:33 -050083
bnc32f36f92020-03-27 15:48:45 -070084 bool OnHeadersFrameStart(QuicByteCount header_length,
85 QuicByteCount payload_length) override {
renjietanga29a96a2019-10-10 12:47:50 -070086 if (!VersionUsesHttp3(stream_->transport_version())) {
bnc62446bc2019-03-14 06:11:25 -070087 CloseConnectionOnWrongFrame("Headers");
renjietang546a6282019-06-03 10:21:21 -070088 return false;
bnc62446bc2019-03-14 06:11:25 -070089 }
bnc32f36f92020-03-27 15:48:45 -070090 return stream_->OnHeadersFrameStart(header_length, payload_length);
QUICHE teama6ef0a62019-03-07 20:34:33 -050091 }
92
dmcardleba2fb7e2019-12-13 07:44:34 -080093 bool OnHeadersFramePayload(quiche::QuicheStringPiece payload) override {
bnc70914262019-03-16 12:49:50 -070094 DCHECK(!payload.empty());
renjietanga29a96a2019-10-10 12:47:50 -070095 if (!VersionUsesHttp3(stream_->transport_version())) {
bnc62446bc2019-03-14 06:11:25 -070096 CloseConnectionOnWrongFrame("Headers");
renjietang546a6282019-06-03 10:21:21 -070097 return false;
bnc62446bc2019-03-14 06:11:25 -070098 }
renjietang546a6282019-06-03 10:21:21 -070099 return stream_->OnHeadersFramePayload(payload);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500100 }
101
renjietang546a6282019-06-03 10:21:21 -0700102 bool OnHeadersFrameEnd() override {
renjietanga29a96a2019-10-10 12:47:50 -0700103 if (!VersionUsesHttp3(stream_->transport_version())) {
bnc62446bc2019-03-14 06:11:25 -0700104 CloseConnectionOnWrongFrame("Headers");
renjietang546a6282019-06-03 10:21:21 -0700105 return false;
bnc62446bc2019-03-14 06:11:25 -0700106 }
renjietang546a6282019-06-03 10:21:21 -0700107 return stream_->OnHeadersFrameEnd();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500108 }
109
bncf0db6542019-09-23 11:18:28 -0700110 bool OnPushPromiseFrameStart(QuicByteCount header_length) override {
renjietanga29a96a2019-10-10 12:47:50 -0700111 if (!VersionUsesHttp3(stream_->transport_version())) {
renjietang3c3dfb72019-07-26 11:55:52 -0700112 CloseConnectionOnWrongFrame("Push Promise");
113 return false;
114 }
bncf0db6542019-09-23 11:18:28 -0700115 return stream_->OnPushPromiseFrameStart(header_length);
116 }
117
118 bool OnPushPromiseFramePushId(PushId push_id,
bnc32f36f92020-03-27 15:48:45 -0700119 QuicByteCount push_id_length,
120 QuicByteCount header_block_length) override {
renjietanga29a96a2019-10-10 12:47:50 -0700121 if (!VersionUsesHttp3(stream_->transport_version())) {
bncf0db6542019-09-23 11:18:28 -0700122 CloseConnectionOnWrongFrame("Push Promise");
123 return false;
124 }
bnc32f36f92020-03-27 15:48:45 -0700125 return stream_->OnPushPromiseFramePushId(push_id, push_id_length,
126 header_block_length);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500127 }
128
dmcardleba2fb7e2019-12-13 07:44:34 -0800129 bool OnPushPromiseFramePayload(quiche::QuicheStringPiece payload) override {
bnc70914262019-03-16 12:49:50 -0700130 DCHECK(!payload.empty());
renjietanga29a96a2019-10-10 12:47:50 -0700131 if (!VersionUsesHttp3(stream_->transport_version())) {
renjietang3c3dfb72019-07-26 11:55:52 -0700132 CloseConnectionOnWrongFrame("Push Promise");
133 return false;
134 }
135 return stream_->OnPushPromiseFramePayload(payload);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500136 }
137
renjietang546a6282019-06-03 10:21:21 -0700138 bool OnPushPromiseFrameEnd() override {
renjietanga29a96a2019-10-10 12:47:50 -0700139 if (!VersionUsesHttp3(stream_->transport_version())) {
renjietang3c3dfb72019-07-26 11:55:52 -0700140 CloseConnectionOnWrongFrame("Push Promise");
141 return false;
142 }
143 return stream_->OnPushPromiseFrameEnd();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500144 }
145
bnc51e89622020-01-10 10:40:32 -0800146 bool OnPriorityUpdateFrameStart(QuicByteCount /*header_length*/) override {
147 CloseConnectionOnWrongFrame("Priority update");
148 return false;
149 }
150
151 bool OnPriorityUpdateFrame(const PriorityUpdateFrame& /*frame*/) override {
152 CloseConnectionOnWrongFrame("Priority update");
153 return false;
154 }
155
bnc25827c42019-07-29 08:57:24 -0700156 bool OnUnknownFrameStart(uint64_t frame_type,
bnc32f36f92020-03-27 15:48:45 -0700157 QuicByteCount header_length,
158 QuicByteCount payload_length) override {
159 return stream_->OnUnknownFrameStart(frame_type, header_length,
160 payload_length);
bncbf3dbe52019-07-17 05:17:41 -0700161 }
162
dmcardleba2fb7e2019-12-13 07:44:34 -0800163 bool OnUnknownFramePayload(quiche::QuicheStringPiece payload) override {
bnc25827c42019-07-29 08:57:24 -0700164 return stream_->OnUnknownFramePayload(payload);
bncbf3dbe52019-07-17 05:17:41 -0700165 }
166
bnc25827c42019-07-29 08:57:24 -0700167 bool OnUnknownFrameEnd() override { return stream_->OnUnknownFrameEnd(); }
bncbf3dbe52019-07-17 05:17:41 -0700168
QUICHE teama6ef0a62019-03-07 20:34:33 -0500169 private:
dmcardleba2fb7e2019-12-13 07:44:34 -0800170 void CloseConnectionOnWrongFrame(quiche::QuicheStringPiece frame_type) {
renjietang87df0d02020-02-13 11:53:52 -0800171 stream_->OnUnrecoverableError(
bncdfabdfb2020-01-17 17:46:40 -0800172 QUIC_HTTP_FRAME_UNEXPECTED_ON_SPDY_STREAM,
renjietangf196f6a2020-02-12 12:34:23 -0800173 quiche::QuicheStrCat(frame_type, " frame received on data stream"));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500174 }
175
176 QuicSpdyStream* stream_;
177};
178
179#define ENDPOINT \
180 (session()->perspective() == Perspective::IS_SERVER ? "Server: " \
181 : "Client:" \
182 " ")
183
184QuicSpdyStream::QuicSpdyStream(QuicStreamId id,
185 QuicSpdySession* spdy_session,
186 StreamType type)
187 : QuicStream(id, spdy_session, /*is_static=*/false, type),
188 spdy_session_(spdy_session),
renjietang2abedac2019-05-20 14:04:50 -0700189 on_body_available_called_because_sequencer_is_closed_(false),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500190 visitor_(nullptr),
bncc057c012019-07-02 11:13:22 -0700191 blocked_on_decoding_headers_(false),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500192 headers_decompressed_(false),
bnc446887e2019-11-27 13:08:28 -0800193 header_list_size_limit_exceeded_(false),
renjietang6f572a82019-07-23 16:33:13 -0700194 headers_payload_length_(0),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500195 trailers_decompressed_(false),
196 trailers_consumed_(false),
vasilvv0fc587f2019-09-06 13:33:08 -0700197 http_decoder_visitor_(std::make_unique<HttpDecoderVisitor>(this)),
bnca9bb4692019-07-09 17:29:48 -0700198 decoder_(http_decoder_visitor_.get()),
bnc8aadca72019-06-28 11:09:39 -0700199 sequencer_offset_(0),
200 is_decoder_processing_input_(false),
bncb8abf382020-01-30 11:26:12 -0800201 ack_listener_(nullptr),
bnc3e004e92020-08-31 07:03:13 -0700202 last_sent_urgency_(DefaultUrgency()) {
bncfa1de5f2019-07-09 17:53:56 -0700203 DCHECK_EQ(session()->connection(), spdy_session->connection());
renjietangd1d00852019-09-06 10:43:12 -0700204 DCHECK_EQ(transport_version(), spdy_session->transport_version());
bncfa1de5f2019-07-09 17:53:56 -0700205 DCHECK(!QuicUtils::IsCryptoStreamId(transport_version(), id));
bnc8aadca72019-06-28 11:09:39 -0700206 DCHECK_EQ(0u, sequencer()->NumBytesConsumed());
renjietang2abedac2019-05-20 14:04:50 -0700207 // If headers are sent on the headers stream, then do not receive any
208 // callbacks from the sequencer until headers are complete.
renjietanga29a96a2019-10-10 12:47:50 -0700209 if (!VersionUsesHttp3(transport_version())) {
renjietang2abedac2019-05-20 14:04:50 -0700210 sequencer()->SetBlockedUntilFlush();
211 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500212
renjietanga29a96a2019-10-10 12:47:50 -0700213 if (VersionUsesHttp3(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500214 sequencer()->set_level_triggered(true);
215 }
bncf6b86b22020-01-26 11:08:46 -0800216
217 spdy_session_->OnStreamCreated(this);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500218}
219
renjietangbaea59c2019-05-29 15:08:14 -0700220QuicSpdyStream::QuicSpdyStream(PendingStream* pending,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500221 QuicSpdySession* spdy_session,
222 StreamType type)
renjietang49aec632020-08-31 10:56:28 -0700223 : QuicStream(pending, spdy_session, type, /*is_static=*/false),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500224 spdy_session_(spdy_session),
renjietang2abedac2019-05-20 14:04:50 -0700225 on_body_available_called_because_sequencer_is_closed_(false),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500226 visitor_(nullptr),
bncc057c012019-07-02 11:13:22 -0700227 blocked_on_decoding_headers_(false),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500228 headers_decompressed_(false),
bnc446887e2019-11-27 13:08:28 -0800229 header_list_size_limit_exceeded_(false),
renjietang6f572a82019-07-23 16:33:13 -0700230 headers_payload_length_(0),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500231 trailers_decompressed_(false),
232 trailers_consumed_(false),
vasilvv0fc587f2019-09-06 13:33:08 -0700233 http_decoder_visitor_(std::make_unique<HttpDecoderVisitor>(this)),
bnca9bb4692019-07-09 17:29:48 -0700234 decoder_(http_decoder_visitor_.get()),
bnc8aadca72019-06-28 11:09:39 -0700235 sequencer_offset_(sequencer()->NumBytesConsumed()),
236 is_decoder_processing_input_(false),
bncb8abf382020-01-30 11:26:12 -0800237 ack_listener_(nullptr),
bnc3e004e92020-08-31 07:03:13 -0700238 last_sent_urgency_(DefaultUrgency()) {
bncfa1de5f2019-07-09 17:53:56 -0700239 DCHECK_EQ(session()->connection(), spdy_session->connection());
renjietangd1d00852019-09-06 10:43:12 -0700240 DCHECK_EQ(transport_version(), spdy_session->transport_version());
bncfa1de5f2019-07-09 17:53:56 -0700241 DCHECK(!QuicUtils::IsCryptoStreamId(transport_version(), id()));
renjietang2abedac2019-05-20 14:04:50 -0700242 // If headers are sent on the headers stream, then do not receive any
243 // callbacks from the sequencer until headers are complete.
renjietanga29a96a2019-10-10 12:47:50 -0700244 if (!VersionUsesHttp3(transport_version())) {
renjietang2abedac2019-05-20 14:04:50 -0700245 sequencer()->SetBlockedUntilFlush();
246 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500247
renjietanga29a96a2019-10-10 12:47:50 -0700248 if (VersionUsesHttp3(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500249 sequencer()->set_level_triggered(true);
250 }
bncf6b86b22020-01-26 11:08:46 -0800251
252 spdy_session_->OnStreamCreated(this);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500253}
254
255QuicSpdyStream::~QuicSpdyStream() {}
256
257size_t QuicSpdyStream::WriteHeaders(
258 SpdyHeaderBlock header_block,
259 bool fin,
260 QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
fayanga4b37b22019-06-18 13:37:47 -0700261 QuicConnection::ScopedPacketFlusher flusher(spdy_session_->connection());
renjietangbb1c4892019-05-24 15:58:44 -0700262 // Send stream type for server push stream
renjietanga29a96a2019-10-10 12:47:50 -0700263 if (VersionUsesHttp3(transport_version()) && type() == WRITE_UNIDIRECTIONAL &&
264 send_buffer().stream_offset() == 0) {
renjietangbb1c4892019-05-24 15:58:44 -0700265 char data[sizeof(kServerPushStream)];
bnc4e9283d2019-12-17 07:08:57 -0800266 QuicDataWriter writer(QUICHE_ARRAYSIZE(data), data);
renjietangbb1c4892019-05-24 15:58:44 -0700267 writer.WriteVarInt62(kServerPushStream);
268
269 // Similar to frame headers, stream type byte shouldn't be exposed to upper
270 // layer applications.
271 unacked_frame_headers_offsets_.Add(0, writer.length());
272
dschinazi88bd5b02019-10-10 00:52:20 -0700273 QUIC_LOG(INFO) << ENDPOINT << "Stream " << id()
274 << " is writing type as server push";
dmcardleba2fb7e2019-12-13 07:44:34 -0800275 WriteOrBufferData(quiche::QuicheStringPiece(writer.data(), writer.length()),
276 false, nullptr);
renjietangbb1c4892019-05-24 15:58:44 -0700277 }
bnc80abd362020-01-30 10:46:30 -0800278
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.
fayang3a51d1a2020-04-16 13:42:08 -0700286 SetFinSent();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500287 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
bncb9d5e792020-03-20 17:43:41 -0700300 if (spdy_session_->debug_visitor()) {
301 spdy_session_->debug_visitor()->OnDataFrameSent(id(), data.length());
302 }
303
QUICHE teama6ef0a62019-03-07 20:34:33 -0500304 // Write frame header.
305 std::unique_ptr<char[]> buffer;
306 QuicByteCount header_length =
bnc46942722019-10-29 11:56:21 -0700307 HttpEncoder::SerializeDataFrameHeader(data.length(), &buffer);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500308 unacked_frame_headers_offsets_.Add(
309 send_buffer().stream_offset(),
310 send_buffer().stream_offset() + header_length);
dschinazi88bd5b02019-10-10 00:52:20 -0700311 QUIC_DLOG(INFO) << ENDPOINT << "Stream " << id()
renjietang2abedac2019-05-20 14:04:50 -0700312 << " is writing DATA frame header of length "
QUICHE teama6ef0a62019-03-07 20:34:33 -0500313 << header_length;
dmcardleba2fb7e2019-12-13 07:44:34 -0800314 WriteOrBufferData(quiche::QuicheStringPiece(buffer.get(), header_length),
315 false, nullptr);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500316
317 // Write body.
dschinazi88bd5b02019-10-10 00:52:20 -0700318 QUIC_DLOG(INFO) << ENDPOINT << "Stream " << id()
renjietang2abedac2019-05-20 14:04:50 -0700319 << " is writing DATA frame payload of length "
renjietangdbe98342019-10-18 11:00:57 -0700320 << data.length() << " with fin " << fin;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500321 WriteOrBufferData(data, fin, nullptr);
322}
323
324size_t QuicSpdyStream::WriteTrailers(
325 SpdyHeaderBlock trailer_block,
326 QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
327 if (fin_sent()) {
328 QUIC_BUG << "Trailers cannot be sent after a FIN, on stream " << id();
329 return 0;
330 }
331
renjietanga29a96a2019-10-10 12:47:50 -0700332 if (!VersionUsesHttp3(transport_version())) {
renjietang2abedac2019-05-20 14:04:50 -0700333 // The header block must contain the final offset for this stream, as the
334 // trailers may be processed out of order at the peer.
335 const QuicStreamOffset final_offset =
336 stream_bytes_written() + BufferedDataBytes();
dschinazi88bd5b02019-10-10 00:52:20 -0700337 QUIC_DLOG(INFO) << ENDPOINT << "Inserting trailer: ("
338 << kFinalOffsetHeaderKey << ", " << final_offset << ")";
dmcardleba2fb7e2019-12-13 07:44:34 -0800339 trailer_block.insert(
340 std::make_pair(kFinalOffsetHeaderKey,
341 quiche::QuicheTextUtils::Uint64ToString(final_offset)));
renjietang2abedac2019-05-20 14:04:50 -0700342 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500343
344 // Write the trailing headers with a FIN, and close stream for writing:
345 // trailers are the last thing to be sent on a stream.
346 const bool kFin = true;
347 size_t bytes_written =
348 WriteHeadersImpl(std::move(trailer_block), kFin, std::move(ack_listener));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500349
renjietang2abedac2019-05-20 14:04:50 -0700350 // If trailers are sent on the headers stream, then |fin_sent_| needs to be
351 // set without actually sending a FIN on this stream.
renjietanga29a96a2019-10-10 12:47:50 -0700352 if (!VersionUsesHttp3(transport_version())) {
fayang3a51d1a2020-04-16 13:42:08 -0700353 SetFinSent();
renjietang2abedac2019-05-20 14:04:50 -0700354
355 // Also, write side of this stream needs to be closed. However, only do
356 // this if there is no more buffered data, otherwise it will never be sent.
357 if (BufferedDataBytes() == 0) {
358 CloseWriteSide();
359 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500360 }
361
362 return bytes_written;
363}
364
renjietang3c3dfb72019-07-26 11:55:52 -0700365void QuicSpdyStream::WritePushPromise(const PushPromiseFrame& frame) {
renjietanga29a96a2019-10-10 12:47:50 -0700366 DCHECK(VersionUsesHttp3(transport_version()));
renjietang3c3dfb72019-07-26 11:55:52 -0700367 std::unique_ptr<char[]> push_promise_frame_with_id;
368 const size_t push_promise_frame_length =
bnc46942722019-10-29 11:56:21 -0700369 HttpEncoder::SerializePushPromiseFrameWithOnlyPushId(
renjietang3c3dfb72019-07-26 11:55:52 -0700370 frame, &push_promise_frame_with_id);
371
372 unacked_frame_headers_offsets_.Add(send_buffer().stream_offset(),
373 send_buffer().stream_offset() +
374 push_promise_frame_length +
375 frame.headers.length());
376
377 // Write Push Promise frame header and push id.
dschinazi88bd5b02019-10-10 00:52:20 -0700378 QUIC_DLOG(INFO) << ENDPOINT << "Stream " << id()
renjietang3c3dfb72019-07-26 11:55:52 -0700379 << " is writing Push Promise frame header of length "
380 << push_promise_frame_length << " , with promised id "
381 << frame.push_id;
dmcardleba2fb7e2019-12-13 07:44:34 -0800382 WriteOrBufferData(quiche::QuicheStringPiece(push_promise_frame_with_id.get(),
383 push_promise_frame_length),
renjietang3c3dfb72019-07-26 11:55:52 -0700384 /* fin = */ false, /* ack_listener = */ nullptr);
385
386 // Write response headers.
dschinazi88bd5b02019-10-10 00:52:20 -0700387 QUIC_DLOG(INFO) << ENDPOINT << "Stream " << id()
renjietang3c3dfb72019-07-26 11:55:52 -0700388 << " is writing Push Promise request header of length "
389 << frame.headers.length();
390 WriteOrBufferData(frame.headers, /* fin = */ false,
391 /* ack_listener = */ nullptr);
392}
393
QUICHE teama6ef0a62019-03-07 20:34:33 -0500394QuicConsumedData QuicSpdyStream::WritevBody(const struct iovec* iov,
395 int count,
396 bool fin) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500397 QuicMemSliceStorage storage(
398 iov, count,
399 session()->connection()->helper()->GetStreamSendBufferAllocator(),
400 GetQuicFlag(FLAGS_quic_send_buffer_max_data_slice_size));
401 return WriteBodySlices(storage.ToSpan(), fin);
402}
403
404QuicConsumedData QuicSpdyStream::WriteBodySlices(QuicMemSliceSpan slices,
405 bool fin) {
renjietanga29a96a2019-10-10 12:47:50 -0700406 if (!VersionUsesHttp3(transport_version()) || slices.empty()) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500407 return WriteMemSlices(slices, fin);
408 }
409
410 std::unique_ptr<char[]> buffer;
411 QuicByteCount header_length =
bnc46942722019-10-29 11:56:21 -0700412 HttpEncoder::SerializeDataFrameHeader(slices.total_length(), &buffer);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500413 if (!CanWriteNewDataAfterData(header_length)) {
414 return {0, false};
415 }
416
bncb9d5e792020-03-20 17:43:41 -0700417 if (spdy_session_->debug_visitor()) {
418 spdy_session_->debug_visitor()->OnDataFrameSent(id(),
419 slices.total_length());
420 }
421
fayanga4b37b22019-06-18 13:37:47 -0700422 QuicConnection::ScopedPacketFlusher flusher(spdy_session_->connection());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500423
424 // Write frame header.
425 struct iovec header_iov = {static_cast<void*>(buffer.get()), header_length};
426 QuicMemSliceStorage storage(
427 &header_iov, 1,
428 spdy_session_->connection()->helper()->GetStreamSendBufferAllocator(),
429 GetQuicFlag(FLAGS_quic_send_buffer_max_data_slice_size));
430 unacked_frame_headers_offsets_.Add(
431 send_buffer().stream_offset(),
432 send_buffer().stream_offset() + header_length);
dschinazi88bd5b02019-10-10 00:52:20 -0700433 QUIC_DLOG(INFO) << ENDPOINT << "Stream " << id()
renjietang2abedac2019-05-20 14:04:50 -0700434 << " is writing DATA frame header of length "
QUICHE teama6ef0a62019-03-07 20:34:33 -0500435 << header_length;
436 WriteMemSlices(storage.ToSpan(), false);
437
438 // Write body.
dschinazi88bd5b02019-10-10 00:52:20 -0700439 QUIC_DLOG(INFO) << ENDPOINT << "Stream " << id()
renjietang2abedac2019-05-20 14:04:50 -0700440 << " is writing DATA frame payload of length "
QUICHE teama6ef0a62019-03-07 20:34:33 -0500441 << slices.total_length();
442 return WriteMemSlices(slices, fin);
443}
444
445size_t QuicSpdyStream::Readv(const struct iovec* iov, size_t iov_len) {
446 DCHECK(FinishedReadingHeaders());
renjietanga29a96a2019-10-10 12:47:50 -0700447 if (!VersionUsesHttp3(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500448 return sequencer()->Readv(iov, iov_len);
449 }
bncc9019492019-07-23 06:44:39 -0700450 size_t bytes_read = 0;
bnc0b83e0c2019-08-16 15:56:32 -0700451 sequencer()->MarkConsumed(body_manager_.ReadBody(iov, iov_len, &bytes_read));
bnc8d041302019-06-10 10:19:04 -0700452
renjietangbd1a0392019-05-31 11:36:24 -0700453 return bytes_read;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500454}
455
456int QuicSpdyStream::GetReadableRegions(iovec* iov, size_t iov_len) const {
457 DCHECK(FinishedReadingHeaders());
renjietanga29a96a2019-10-10 12:47:50 -0700458 if (!VersionUsesHttp3(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500459 return sequencer()->GetReadableRegions(iov, iov_len);
460 }
bnc0b83e0c2019-08-16 15:56:32 -0700461 return body_manager_.PeekBody(iov, iov_len);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500462}
463
464void QuicSpdyStream::MarkConsumed(size_t num_bytes) {
465 DCHECK(FinishedReadingHeaders());
renjietanga29a96a2019-10-10 12:47:50 -0700466 if (!VersionUsesHttp3(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500467 sequencer()->MarkConsumed(num_bytes);
468 return;
469 }
bnc8d041302019-06-10 10:19:04 -0700470
bnc0b83e0c2019-08-16 15:56:32 -0700471 sequencer()->MarkConsumed(body_manager_.OnBodyConsumed(num_bytes));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500472}
473
474bool QuicSpdyStream::IsDoneReading() const {
475 bool done_reading_headers = FinishedReadingHeaders();
476 bool done_reading_body = sequencer()->IsClosed();
477 bool done_reading_trailers = FinishedReadingTrailers();
478 return done_reading_headers && done_reading_body && done_reading_trailers;
479}
480
481bool QuicSpdyStream::HasBytesToRead() const {
renjietanga29a96a2019-10-10 12:47:50 -0700482 if (!VersionUsesHttp3(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500483 return sequencer()->HasBytesToRead();
484 }
bnc0b83e0c2019-08-16 15:56:32 -0700485 return body_manager_.HasBytesToRead();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500486}
487
488void QuicSpdyStream::MarkTrailersConsumed() {
489 trailers_consumed_ = true;
490}
491
492uint64_t QuicSpdyStream::total_body_bytes_read() const {
renjietanga29a96a2019-10-10 12:47:50 -0700493 if (VersionUsesHttp3(transport_version())) {
bnc0b83e0c2019-08-16 15:56:32 -0700494 return body_manager_.total_body_bytes_received();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500495 }
496 return sequencer()->NumBytesConsumed();
497}
498
499void QuicSpdyStream::ConsumeHeaderList() {
500 header_list_.Clear();
renjietang2abedac2019-05-20 14:04:50 -0700501
bnc8d041302019-06-10 10:19:04 -0700502 if (!FinishedReadingHeaders()) {
renjietang2abedac2019-05-20 14:04:50 -0700503 return;
504 }
505
renjietanga29a96a2019-10-10 12:47:50 -0700506 if (!VersionUsesHttp3(transport_version())) {
bnc8d041302019-06-10 10:19:04 -0700507 sequencer()->SetUnblocked();
renjietang2abedac2019-05-20 14:04:50 -0700508 return;
509 }
510
bnc0b83e0c2019-08-16 15:56:32 -0700511 if (body_manager_.HasBytesToRead()) {
renjietang2abedac2019-05-20 14:04:50 -0700512 OnBodyAvailable();
513 return;
514 }
515
516 if (sequencer()->IsClosed() &&
517 !on_body_available_called_because_sequencer_is_closed_) {
518 on_body_available_called_because_sequencer_is_closed_ = true;
519 OnBodyAvailable();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500520 }
521}
522
fayang476683a2019-07-25 12:42:16 -0700523void QuicSpdyStream::OnStreamHeadersPriority(
524 const spdy::SpdyStreamPrecedence& precedence) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500525 DCHECK_EQ(Perspective::IS_SERVER, session()->connection()->perspective());
fayang476683a2019-07-25 12:42:16 -0700526 SetPriority(precedence);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500527}
528
bnc62706802019-06-26 12:37:46 -0700529void QuicSpdyStream::OnStreamHeaderList(bool fin,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500530 size_t frame_len,
531 const QuicHeaderList& header_list) {
wub13ebfa62020-08-10 07:48:24 -0700532 if (!spdy_session()->user_agent_id().has_value()) {
533 std::string uaid;
534 for (const auto& kv : header_list) {
535 if (quiche::QuicheTextUtils::ToLower(kv.first) == kUserAgentHeaderName) {
536 uaid = kv.second;
537 break;
wubbe634b72020-06-16 08:41:26 -0700538 }
wubbe634b72020-06-16 08:41:26 -0700539 }
wub13ebfa62020-08-10 07:48:24 -0700540 spdy_session()->SetUserAgentId(std::move(uaid));
wubbe634b72020-06-16 08:41:26 -0700541 }
542
bnc8d041302019-06-10 10:19:04 -0700543 // TODO(b/134706391): remove |fin| argument.
bnc446887e2019-11-27 13:08:28 -0800544 // When using Google QUIC, an empty header list indicates that the size limit
545 // has been exceeded.
546 // When using IETF QUIC, there is an explicit signal from
547 // QpackDecodedHeadersAccumulator.
548 if ((VersionUsesHttp3(transport_version()) &&
549 header_list_size_limit_exceeded_) ||
550 (!VersionUsesHttp3(transport_version()) && header_list.empty())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500551 OnHeadersTooLarge();
552 if (IsDoneReading()) {
bnc62706802019-06-26 12:37:46 -0700553 return;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500554 }
555 }
556 if (!headers_decompressed_) {
557 OnInitialHeadersComplete(fin, frame_len, header_list);
558 } else {
559 OnTrailingHeadersComplete(fin, frame_len, header_list);
560 }
561}
562
bncb7ac1042019-12-06 10:32:23 -0800563void QuicSpdyStream::OnHeadersDecoded(QuicHeaderList headers,
564 bool header_list_size_limit_exceeded) {
565 header_list_size_limit_exceeded_ = header_list_size_limit_exceeded;
bnc232ff9b2019-11-13 18:38:22 -0800566 qpack_decoded_headers_accumulator_.reset();
567
568 QuicSpdySession::LogHeaderCompressionRatioHistogram(
569 /* using_qpack = */ true,
570 /* is_sent = */ false, headers.compressed_header_bytes(),
571 headers.uncompressed_header_bytes());
572
bncb9d5e792020-03-20 17:43:41 -0700573 const QuicStreamId promised_stream_id = spdy_session()->promised_stream_id();
574 Http3DebugVisitor* const debug_visitor = spdy_session()->debug_visitor();
575 if (promised_stream_id ==
576 QuicUtils::GetInvalidStreamId(transport_version())) {
577 if (debug_visitor) {
578 debug_visitor->OnHeadersDecoded(id(), headers);
579 }
580
bnc7ffadb82020-04-07 10:01:30 -0700581 OnStreamHeaderList(/* fin = */ false, headers_payload_length_, headers);
bnc232ff9b2019-11-13 18:38:22 -0800582 } else {
bncb9d5e792020-03-20 17:43:41 -0700583 if (debug_visitor) {
584 debug_visitor->OnPushPromiseDecoded(id(), promised_stream_id, headers);
585 }
586
bnc232ff9b2019-11-13 18:38:22 -0800587 spdy_session_->OnHeaderList(headers);
588 }
589
590 if (blocked_on_decoding_headers_) {
591 blocked_on_decoding_headers_ = false;
592 // Continue decoding HTTP/3 frames.
593 OnDataAvailable();
594 }
bncc057c012019-07-02 11:13:22 -0700595}
596
dmcardleba2fb7e2019-12-13 07:44:34 -0800597void QuicSpdyStream::OnHeaderDecodingError(
598 quiche::QuicheStringPiece error_message) {
bnc232ff9b2019-11-13 18:38:22 -0800599 qpack_decoded_headers_accumulator_.reset();
600
dmcardleba2fb7e2019-12-13 07:44:34 -0800601 std::string connection_close_error_message = quiche::QuicheStrCat(
bnc232ff9b2019-11-13 18:38:22 -0800602 "Error decoding ", headers_decompressed_ ? "trailers" : "headers",
603 " on stream ", id(), ": ", error_message);
renjietang87df0d02020-02-13 11:53:52 -0800604 OnUnrecoverableError(QUIC_QPACK_DECOMPRESSION_FAILED,
605 connection_close_error_message);
bncc057c012019-07-02 11:13:22 -0700606}
607
bnc80abd362020-01-30 10:46:30 -0800608void QuicSpdyStream::MaybeSendPriorityUpdateFrame() {
609 if (!VersionUsesHttp3(transport_version()) ||
610 session()->perspective() != Perspective::IS_CLIENT) {
611 return;
612 }
613
614 // Value between 0 and 7, inclusive. Lower value means higher priority.
615 int urgency = precedence().spdy3_priority();
bncb8abf382020-01-30 11:26:12 -0800616 if (last_sent_urgency_ == urgency) {
617 return;
618 }
619 last_sent_urgency_ = urgency;
bnc80abd362020-01-30 10:46:30 -0800620
621 PriorityUpdateFrame priority_update;
622 priority_update.prioritized_element_type = REQUEST_STREAM;
623 priority_update.prioritized_element_id = id();
624 priority_update.priority_field_value = quiche::QuicheStrCat("u=", urgency);
625 spdy_session_->WriteHttp3PriorityUpdate(priority_update);
626}
627
QUICHE teama6ef0a62019-03-07 20:34:33 -0500628void QuicSpdyStream::OnHeadersTooLarge() {
bnc52ffb982020-05-01 11:31:28 -0700629 Reset(QUIC_HEADERS_TOO_LARGE);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500630}
631
632void QuicSpdyStream::OnInitialHeadersComplete(
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 headers_decompressed_ = true;
638 header_list_ = header_list;
renjietang2abedac2019-05-20 14:04:50 -0700639
renjietanga29a96a2019-10-10 12:47:50 -0700640 if (VersionUsesHttp3(transport_version())) {
renjietang2abedac2019-05-20 14:04:50 -0700641 if (fin) {
renjietang07b2e8d2020-08-10 15:18:24 -0700642 OnStreamFrame(QuicStreamFrame(id(), /* fin = */ true,
643 highest_received_byte_offset(),
644 quiche::QuicheStringPiece()));
renjietang2abedac2019-05-20 14:04:50 -0700645 }
646 return;
647 }
648
bnc70f78fc2019-08-26 10:12:31 -0700649 if (fin && !rst_sent()) {
dmcardleba2fb7e2019-12-13 07:44:34 -0800650 OnStreamFrame(QuicStreamFrame(id(), fin, /* offset = */ 0,
651 quiche::QuicheStringPiece()));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500652 }
653 if (FinishedReadingHeaders()) {
654 sequencer()->SetUnblocked();
655 }
656}
657
658void QuicSpdyStream::OnPromiseHeaderList(
659 QuicStreamId /* promised_id */,
660 size_t /* frame_len */,
661 const QuicHeaderList& /*header_list */) {
662 // To be overridden in QuicSpdyClientStream. Not supported on
663 // server side.
renjietangf196f6a2020-02-12 12:34:23 -0800664 stream_delegate()->OnStreamError(QUIC_INVALID_HEADERS_STREAM_DATA,
665 "Promise headers received by server");
QUICHE teama6ef0a62019-03-07 20:34:33 -0500666}
667
668void QuicSpdyStream::OnTrailingHeadersComplete(
669 bool fin,
670 size_t /*frame_len*/,
671 const QuicHeaderList& header_list) {
bnc8d041302019-06-10 10:19:04 -0700672 // TODO(b/134706391): remove |fin| argument.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500673 DCHECK(!trailers_decompressed_);
renjietanga29a96a2019-10-10 12:47:50 -0700674 if (!VersionUsesHttp3(transport_version()) && fin_received()) {
dschinazi88bd5b02019-10-10 00:52:20 -0700675 QUIC_DLOG(INFO) << ENDPOINT
676 << "Received Trailers after FIN, on stream: " << id();
renjietangf196f6a2020-02-12 12:34:23 -0800677 stream_delegate()->OnStreamError(QUIC_INVALID_HEADERS_STREAM_DATA,
678 "Trailers after fin");
QUICHE teama6ef0a62019-03-07 20:34:33 -0500679 return;
680 }
renjietang2abedac2019-05-20 14:04:50 -0700681
renjietanga29a96a2019-10-10 12:47:50 -0700682 if (!VersionUsesHttp3(transport_version()) && !fin) {
dschinazi88bd5b02019-10-10 00:52:20 -0700683 QUIC_DLOG(INFO) << ENDPOINT
684 << "Trailers must have FIN set, on stream: " << id();
renjietangf196f6a2020-02-12 12:34:23 -0800685 stream_delegate()->OnStreamError(QUIC_INVALID_HEADERS_STREAM_DATA,
686 "Fin missing from trailers");
QUICHE teama6ef0a62019-03-07 20:34:33 -0500687 return;
688 }
689
690 size_t final_byte_offset = 0;
renjietanga29a96a2019-10-10 12:47:50 -0700691 const bool expect_final_byte_offset = !VersionUsesHttp3(transport_version());
renjietang2abedac2019-05-20 14:04:50 -0700692 if (!SpdyUtils::CopyAndValidateTrailers(header_list, expect_final_byte_offset,
bnc5231ee22019-04-15 19:02:13 -0700693 &final_byte_offset,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500694 &received_trailers_)) {
dschinazi88bd5b02019-10-10 00:52:20 -0700695 QUIC_DLOG(ERROR) << ENDPOINT << "Trailers for stream " << id()
696 << " are malformed.";
renjietangf196f6a2020-02-12 12:34:23 -0800697 stream_delegate()->OnStreamError(QUIC_INVALID_HEADERS_STREAM_DATA,
698 "Trailers are malformed");
QUICHE teama6ef0a62019-03-07 20:34:33 -0500699 return;
700 }
701 trailers_decompressed_ = true;
bncab33c712019-06-28 15:42:15 -0700702 if (fin) {
renjietang07b2e8d2020-08-10 15:18:24 -0700703 const QuicStreamOffset offset = VersionUsesHttp3(transport_version())
704 ? highest_received_byte_offset()
705 : final_byte_offset;
dmcardleba2fb7e2019-12-13 07:44:34 -0800706 OnStreamFrame(
707 QuicStreamFrame(id(), fin, offset, quiche::QuicheStringPiece()));
bncab33c712019-06-28 15:42:15 -0700708 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500709}
710
fayang476683a2019-07-25 12:42:16 -0700711void QuicSpdyStream::OnPriorityFrame(
712 const spdy::SpdyStreamPrecedence& precedence) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500713 DCHECK_EQ(Perspective::IS_SERVER, session()->connection()->perspective());
fayang476683a2019-07-25 12:42:16 -0700714 SetPriority(precedence);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500715}
716
717void QuicSpdyStream::OnStreamReset(const QuicRstStreamFrame& frame) {
718 if (frame.error_code != QUIC_STREAM_NO_ERROR) {
bnc84aa7e52019-12-13 05:25:21 -0800719 if (VersionUsesHttp3(transport_version()) && !fin_received() &&
720 spdy_session_->qpack_decoder()) {
721 spdy_session_->qpack_decoder()->OnStreamReset(id());
722 }
bnc6f18a822019-11-27 17:50:38 -0800723
QUICHE teama6ef0a62019-03-07 20:34:33 -0500724 QuicStream::OnStreamReset(frame);
725 return;
726 }
bnc6f18a822019-11-27 17:50:38 -0800727
dschinazi88bd5b02019-10-10 00:52:20 -0700728 QUIC_DVLOG(1) << ENDPOINT
729 << "Received QUIC_STREAM_NO_ERROR, not discarding response";
QUICHE teama6ef0a62019-03-07 20:34:33 -0500730 set_rst_received(true);
731 MaybeIncreaseHighestReceivedOffset(frame.byte_offset);
732 set_stream_error(frame.error_code);
733 CloseWriteSide();
734}
735
bnc6f18a822019-11-27 17:50:38 -0800736void QuicSpdyStream::Reset(QuicRstStreamErrorCode error) {
bnc84aa7e52019-12-13 05:25:21 -0800737 if (VersionUsesHttp3(transport_version()) && !fin_received() &&
738 spdy_session_->qpack_decoder()) {
739 spdy_session_->qpack_decoder()->OnStreamReset(id());
740 }
bnc6f18a822019-11-27 17:50:38 -0800741
742 QuicStream::Reset(error);
743}
744
QUICHE teama6ef0a62019-03-07 20:34:33 -0500745void QuicSpdyStream::OnDataAvailable() {
renjietanga29a96a2019-10-10 12:47:50 -0700746 if (!VersionUsesHttp3(transport_version())) {
renjietang2abedac2019-05-20 14:04:50 -0700747 // Sequencer must be blocked until headers are consumed.
748 DCHECK(FinishedReadingHeaders());
749 }
bncfa0c90c2019-03-13 14:14:28 -0700750
renjietanga29a96a2019-10-10 12:47:50 -0700751 if (!VersionUsesHttp3(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500752 OnBodyAvailable();
753 return;
754 }
755
bnc8aadca72019-06-28 11:09:39 -0700756 if (is_decoder_processing_input_) {
757 // Let the outermost nested OnDataAvailable() call do the work.
758 return;
759 }
760
bncc057c012019-07-02 11:13:22 -0700761 if (blocked_on_decoding_headers_) {
762 return;
763 }
764
QUICHE teama6ef0a62019-03-07 20:34:33 -0500765 iovec iov;
bncef518152019-07-18 05:36:44 -0700766 while (session()->connection()->connected() && !reading_stopped() &&
767 decoder_.error() == QUIC_NO_ERROR) {
bnc8aadca72019-06-28 11:09:39 -0700768 DCHECK_GE(sequencer_offset_, sequencer()->NumBytesConsumed());
769 if (!sequencer()->PeekRegion(sequencer_offset_, &iov)) {
770 break;
771 }
772
bncd48a92e2019-06-18 19:24:58 -0700773 DCHECK(!sequencer()->IsClosed());
bnc8aadca72019-06-28 11:09:39 -0700774 is_decoder_processing_input_ = true;
775 QuicByteCount processed_bytes = decoder_.ProcessInput(
776 reinterpret_cast<const char*>(iov.iov_base), iov.iov_len);
777 is_decoder_processing_input_ = false;
778 sequencer_offset_ += processed_bytes;
bncc057c012019-07-02 11:13:22 -0700779 if (blocked_on_decoding_headers_) {
780 return;
781 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500782 }
783
renjietang2abedac2019-05-20 14:04:50 -0700784 // Do not call OnBodyAvailable() until headers are consumed.
785 if (!FinishedReadingHeaders()) {
786 return;
787 }
788
bnc0b83e0c2019-08-16 15:56:32 -0700789 if (body_manager_.HasBytesToRead()) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500790 OnBodyAvailable();
791 return;
792 }
793
renjietang2abedac2019-05-20 14:04:50 -0700794 if (sequencer()->IsClosed() &&
795 !on_body_available_called_because_sequencer_is_closed_) {
796 on_body_available_called_because_sequencer_is_closed_ = true;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500797 OnBodyAvailable();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500798 }
799}
800
801void QuicSpdyStream::OnClose() {
802 QuicStream::OnClose();
803
804 if (visitor_) {
805 Visitor* visitor = visitor_;
806 // Calling Visitor::OnClose() may result the destruction of the visitor,
807 // so we need to ensure we don't call it again.
808 visitor_ = nullptr;
809 visitor->OnClose(this);
810 }
811}
812
813void QuicSpdyStream::OnCanWrite() {
814 QuicStream::OnCanWrite();
815
816 // Trailers (and hence a FIN) may have been sent ahead of queued body bytes.
817 if (!HasBufferedData() && fin_sent()) {
818 CloseWriteSide();
819 }
820}
821
822bool QuicSpdyStream::FinishedReadingHeaders() const {
823 return headers_decompressed_ && header_list_.empty();
824}
825
bncd0119902019-06-26 12:12:33 -0700826// static
QUICHE teama6ef0a62019-03-07 20:34:33 -0500827bool QuicSpdyStream::ParseHeaderStatusCode(const SpdyHeaderBlock& header,
bncd0119902019-06-26 12:12:33 -0700828 int* status_code) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500829 SpdyHeaderBlock::const_iterator it = header.find(spdy::kHttp2StatusHeader);
830 if (it == header.end()) {
831 return false;
832 }
dmcardleba2fb7e2019-12-13 07:44:34 -0800833 const quiche::QuicheStringPiece status(it->second);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500834 if (status.size() != 3) {
835 return false;
836 }
837 // First character must be an integer in range [1,5].
838 if (status[0] < '1' || status[0] > '5') {
839 return false;
840 }
841 // The remaining two characters must be integers.
842 if (!isdigit(status[1]) || !isdigit(status[2])) {
843 return false;
844 }
dmcardleba2fb7e2019-12-13 07:44:34 -0800845 return quiche::QuicheTextUtils::StringToInt(status, status_code);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500846}
847
848bool QuicSpdyStream::FinishedReadingTrailers() const {
849 // If no further trailing headers are expected, and the decompressed trailers
850 // (if any) have been consumed, then reading of trailers is finished.
851 if (!fin_received()) {
852 return false;
853 } else if (!trailers_decompressed_) {
854 return true;
855 } else {
856 return trailers_consumed_;
857 }
858}
859
860void QuicSpdyStream::ClearSession() {
861 spdy_session_ = nullptr;
862}
863
bnc32f36f92020-03-27 15:48:45 -0700864bool QuicSpdyStream::OnDataFrameStart(QuicByteCount header_length,
bnc6ab8c792020-03-27 16:15:03 -0700865 QuicByteCount payload_length) {
renjietanga29a96a2019-10-10 12:47:50 -0700866 DCHECK(VersionUsesHttp3(transport_version()));
bnc6ab8c792020-03-27 16:15:03 -0700867
868 if (spdy_session_->debug_visitor()) {
869 spdy_session_->debug_visitor()->OnDataFrameReceived(id(), payload_length);
870 }
871
bnc519216c2019-07-09 05:03:48 -0700872 if (!headers_decompressed_ || trailers_decompressed_) {
bnc3e8fe7c2020-03-10 17:44:58 -0700873 stream_delegate()->OnStreamError(
874 QUIC_HTTP_INVALID_FRAME_SEQUENCE_ON_SPDY_STREAM,
875 "Unexpected DATA frame received.");
bnc519216c2019-07-09 05:03:48 -0700876 return false;
877 }
878
bnc0b83e0c2019-08-16 15:56:32 -0700879 sequencer()->MarkConsumed(body_manager_.OnNonBody(header_length));
bnce5f9c032019-07-25 11:30:40 -0700880
renjietang546a6282019-06-03 10:21:21 -0700881 return true;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500882}
883
dmcardleba2fb7e2019-12-13 07:44:34 -0800884bool QuicSpdyStream::OnDataFramePayload(quiche::QuicheStringPiece payload) {
renjietanga29a96a2019-10-10 12:47:50 -0700885 DCHECK(VersionUsesHttp3(transport_version()));
bncfa0c90c2019-03-13 14:14:28 -0700886
bnc0b83e0c2019-08-16 15:56:32 -0700887 body_manager_.OnBody(payload);
bnce5f9c032019-07-25 11:30:40 -0700888
renjietang546a6282019-06-03 10:21:21 -0700889 return true;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500890}
891
renjietang546a6282019-06-03 10:21:21 -0700892bool QuicSpdyStream::OnDataFrameEnd() {
renjietanga29a96a2019-10-10 12:47:50 -0700893 DCHECK(VersionUsesHttp3(transport_version()));
bncb9d5e792020-03-20 17:43:41 -0700894
dschinazi88bd5b02019-10-10 00:52:20 -0700895 QUIC_DVLOG(1) << ENDPOINT
896 << "Reaches the end of a data frame. Total bytes received are "
bnc0b83e0c2019-08-16 15:56:32 -0700897 << body_manager_.total_body_bytes_received();
renjietang546a6282019-06-03 10:21:21 -0700898 return true;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500899}
900
901bool QuicSpdyStream::OnStreamFrameAcked(QuicStreamOffset offset,
902 QuicByteCount data_length,
903 bool fin_acked,
904 QuicTime::Delta ack_delay_time,
QUICHE team2f5f30b2020-02-18 08:52:28 -0800905 QuicTime receive_timestamp,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500906 QuicByteCount* newly_acked_length) {
907 const bool new_data_acked = QuicStream::OnStreamFrameAcked(
QUICHE team2f5f30b2020-02-18 08:52:28 -0800908 offset, data_length, fin_acked, ack_delay_time, receive_timestamp,
909 newly_acked_length);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500910
911 const QuicByteCount newly_acked_header_length =
912 GetNumFrameHeadersInInterval(offset, data_length);
913 DCHECK_LE(newly_acked_header_length, *newly_acked_length);
914 unacked_frame_headers_offsets_.Difference(offset, offset + data_length);
915 if (ack_listener_ != nullptr && new_data_acked) {
wub2146ce82020-07-30 13:17:52 -0700916 ack_listener_->OnPacketAcked(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500917 *newly_acked_length - newly_acked_header_length, ack_delay_time);
918 }
919 return new_data_acked;
920}
921
922void QuicSpdyStream::OnStreamFrameRetransmitted(QuicStreamOffset offset,
923 QuicByteCount data_length,
924 bool fin_retransmitted) {
925 QuicStream::OnStreamFrameRetransmitted(offset, data_length,
926 fin_retransmitted);
927
928 const QuicByteCount retransmitted_header_length =
929 GetNumFrameHeadersInInterval(offset, data_length);
930 DCHECK_LE(retransmitted_header_length, data_length);
931
932 if (ack_listener_ != nullptr) {
933 ack_listener_->OnPacketRetransmitted(data_length -
934 retransmitted_header_length);
935 }
936}
937
938QuicByteCount QuicSpdyStream::GetNumFrameHeadersInInterval(
939 QuicStreamOffset offset,
940 QuicByteCount data_length) const {
941 QuicByteCount header_acked_length = 0;
942 QuicIntervalSet<QuicStreamOffset> newly_acked(offset, offset + data_length);
943 newly_acked.Intersection(unacked_frame_headers_offsets_);
944 for (const auto& interval : newly_acked) {
945 header_acked_length += interval.Length();
946 }
947 return header_acked_length;
948}
949
bnc32f36f92020-03-27 15:48:45 -0700950bool QuicSpdyStream::OnHeadersFrameStart(QuicByteCount header_length,
bnc6ab8c792020-03-27 16:15:03 -0700951 QuicByteCount payload_length) {
renjietanga29a96a2019-10-10 12:47:50 -0700952 DCHECK(VersionUsesHttp3(transport_version()));
renjietang2abedac2019-05-20 14:04:50 -0700953 DCHECK(!qpack_decoded_headers_accumulator_);
954
bnc6ab8c792020-03-27 16:15:03 -0700955 if (spdy_session_->debug_visitor()) {
956 spdy_session_->debug_visitor()->OnHeadersFrameReceived(id(),
957 payload_length);
958 }
959
bnc7ffadb82020-04-07 10:01:30 -0700960 headers_payload_length_ = payload_length;
961
bnc519216c2019-07-09 05:03:48 -0700962 if (trailers_decompressed_) {
renjietangf196f6a2020-02-12 12:34:23 -0800963 stream_delegate()->OnStreamError(
bnc3e8fe7c2020-03-10 17:44:58 -0700964 QUIC_HTTP_INVALID_FRAME_SEQUENCE_ON_SPDY_STREAM,
renjietangf196f6a2020-02-12 12:34:23 -0800965 "HEADERS frame received after trailing HEADERS.");
bnc519216c2019-07-09 05:03:48 -0700966 return false;
967 }
968
bnc0b83e0c2019-08-16 15:56:32 -0700969 sequencer()->MarkConsumed(body_manager_.OnNonBody(header_length));
renjietang2abedac2019-05-20 14:04:50 -0700970
971 qpack_decoded_headers_accumulator_ =
vasilvv0fc587f2019-09-06 13:33:08 -0700972 std::make_unique<QpackDecodedHeadersAccumulator>(
bncc057c012019-07-02 11:13:22 -0700973 id(), spdy_session_->qpack_decoder(), this,
bncbdd303e2019-07-09 05:33:17 -0700974 spdy_session_->max_inbound_header_list_size());
bnc8d041302019-06-10 10:19:04 -0700975
renjietang546a6282019-06-03 10:21:21 -0700976 return true;
bnc62446bc2019-03-14 06:11:25 -0700977}
978
dmcardleba2fb7e2019-12-13 07:44:34 -0800979bool QuicSpdyStream::OnHeadersFramePayload(quiche::QuicheStringPiece payload) {
renjietanga29a96a2019-10-10 12:47:50 -0700980 DCHECK(VersionUsesHttp3(transport_version()));
bncfcd42352019-09-20 17:55:47 -0700981 DCHECK(qpack_decoded_headers_accumulator_);
renjietang2abedac2019-05-20 14:04:50 -0700982
bnc232ff9b2019-11-13 18:38:22 -0800983 qpack_decoded_headers_accumulator_->Decode(payload);
bnc8d041302019-06-10 10:19:04 -0700984
bnc232ff9b2019-11-13 18:38:22 -0800985 // |qpack_decoded_headers_accumulator_| is reset if an error is detected.
bncf9ff46b2019-11-26 10:32:09 -0800986 if (!qpack_decoded_headers_accumulator_) {
987 return false;
988 }
989
990 sequencer()->MarkConsumed(body_manager_.OnNonBody(payload.size()));
991 return true;
bnc62446bc2019-03-14 06:11:25 -0700992}
993
renjietang546a6282019-06-03 10:21:21 -0700994bool QuicSpdyStream::OnHeadersFrameEnd() {
renjietanga29a96a2019-10-10 12:47:50 -0700995 DCHECK(VersionUsesHttp3(transport_version()));
bncfcd42352019-09-20 17:55:47 -0700996 DCHECK(qpack_decoded_headers_accumulator_);
renjietang2abedac2019-05-20 14:04:50 -0700997
bnc232ff9b2019-11-13 18:38:22 -0800998 qpack_decoded_headers_accumulator_->EndHeaderBlock();
bncc057c012019-07-02 11:13:22 -0700999
bnc232ff9b2019-11-13 18:38:22 -08001000 // If decoding is complete or an error is detected, then
1001 // |qpack_decoded_headers_accumulator_| is already reset.
1002 if (qpack_decoded_headers_accumulator_) {
bncc057c012019-07-02 11:13:22 -07001003 blocked_on_decoding_headers_ = true;
1004 return false;
1005 }
1006
bncc057c012019-07-02 11:13:22 -07001007 return !sequencer()->IsClosed() && !reading_stopped();
1008}
1009
bncf0db6542019-09-23 11:18:28 -07001010bool QuicSpdyStream::OnPushPromiseFrameStart(QuicByteCount header_length) {
renjietanga29a96a2019-10-10 12:47:50 -07001011 DCHECK(VersionUsesHttp3(transport_version()));
bncf0db6542019-09-23 11:18:28 -07001012 DCHECK(!qpack_decoded_headers_accumulator_);
1013
1014 sequencer()->MarkConsumed(body_manager_.OnNonBody(header_length));
1015
1016 return true;
1017}
1018
bnc32f36f92020-03-27 15:48:45 -07001019bool QuicSpdyStream::OnPushPromiseFramePushId(
1020 PushId push_id,
1021 QuicByteCount push_id_length,
bnc6ab8c792020-03-27 16:15:03 -07001022 QuicByteCount header_block_length) {
renjietanga29a96a2019-10-10 12:47:50 -07001023 DCHECK(VersionUsesHttp3(transport_version()));
renjietang3c3dfb72019-07-26 11:55:52 -07001024 DCHECK(!qpack_decoded_headers_accumulator_);
1025
bnc6ab8c792020-03-27 16:15:03 -07001026 if (spdy_session_->debug_visitor()) {
1027 spdy_session_->debug_visitor()->OnPushPromiseFrameReceived(
1028 id(), push_id, header_block_length);
1029 }
1030
bnc7ffadb82020-04-07 10:01:30 -07001031 // TODO(b/151749109): Check max push id and handle errors.
renjietang3c3dfb72019-07-26 11:55:52 -07001032 spdy_session_->OnPushPromise(id(), push_id);
bncf0db6542019-09-23 11:18:28 -07001033 sequencer()->MarkConsumed(body_manager_.OnNonBody(push_id_length));
renjietang3c3dfb72019-07-26 11:55:52 -07001034
1035 qpack_decoded_headers_accumulator_ =
vasilvv0fc587f2019-09-06 13:33:08 -07001036 std::make_unique<QpackDecodedHeadersAccumulator>(
renjietang3c3dfb72019-07-26 11:55:52 -07001037 id(), spdy_session_->qpack_decoder(), this,
1038 spdy_session_->max_inbound_header_list_size());
1039
1040 return true;
1041}
1042
dmcardleba2fb7e2019-12-13 07:44:34 -08001043bool QuicSpdyStream::OnPushPromiseFramePayload(
1044 quiche::QuicheStringPiece payload) {
renjietang3c3dfb72019-07-26 11:55:52 -07001045 spdy_session_->OnCompressedFrameSize(payload.length());
1046 return OnHeadersFramePayload(payload);
1047}
1048
1049bool QuicSpdyStream::OnPushPromiseFrameEnd() {
renjietanga29a96a2019-10-10 12:47:50 -07001050 DCHECK(VersionUsesHttp3(transport_version()));
renjietang3c3dfb72019-07-26 11:55:52 -07001051
renjietang6fbdaf42019-07-29 10:50:54 -07001052 return OnHeadersFrameEnd();
renjietang3c3dfb72019-07-26 11:55:52 -07001053}
1054
bnc25827c42019-07-29 08:57:24 -07001055bool QuicSpdyStream::OnUnknownFrameStart(uint64_t frame_type,
bnc32f36f92020-03-27 15:48:45 -07001056 QuicByteCount header_length,
bnc6ab8c792020-03-27 16:15:03 -07001057 QuicByteCount payload_length) {
bncb9d5e792020-03-20 17:43:41 -07001058 if (spdy_session_->debug_visitor()) {
bnc6ab8c792020-03-27 16:15:03 -07001059 spdy_session_->debug_visitor()->OnUnknownFrameReceived(id(), frame_type,
1060 payload_length);
bncb9d5e792020-03-20 17:43:41 -07001061 }
1062
bnc25827c42019-07-29 08:57:24 -07001063 // Ignore unknown frames, but consume frame header.
dschinazi88bd5b02019-10-10 00:52:20 -07001064 QUIC_DVLOG(1) << ENDPOINT << "Discarding " << header_length
bnc25827c42019-07-29 08:57:24 -07001065 << " byte long frame header of frame of unknown type "
1066 << frame_type << ".";
bnc0b83e0c2019-08-16 15:56:32 -07001067 sequencer()->MarkConsumed(body_manager_.OnNonBody(header_length));
bnc25827c42019-07-29 08:57:24 -07001068 return true;
1069}
1070
dmcardleba2fb7e2019-12-13 07:44:34 -08001071bool QuicSpdyStream::OnUnknownFramePayload(quiche::QuicheStringPiece payload) {
bnc25827c42019-07-29 08:57:24 -07001072 // Ignore unknown frames, but consume frame payload.
dschinazi88bd5b02019-10-10 00:52:20 -07001073 QUIC_DVLOG(1) << ENDPOINT << "Discarding " << payload.size()
bnc25827c42019-07-29 08:57:24 -07001074 << " bytes of payload of frame of unknown type.";
bnc0b83e0c2019-08-16 15:56:32 -07001075 sequencer()->MarkConsumed(body_manager_.OnNonBody(payload.size()));
bnc25827c42019-07-29 08:57:24 -07001076 return true;
1077}
1078
1079bool QuicSpdyStream::OnUnknownFrameEnd() {
1080 return true;
1081}
1082
renjietang2abedac2019-05-20 14:04:50 -07001083size_t QuicSpdyStream::WriteHeadersImpl(
1084 spdy::SpdyHeaderBlock header_block,
1085 bool fin,
1086 QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
renjietanga29a96a2019-10-10 12:47:50 -07001087 if (!VersionUsesHttp3(transport_version())) {
renjietang2abedac2019-05-20 14:04:50 -07001088 return spdy_session_->WriteHeadersOnHeadersStream(
fayang476683a2019-07-25 12:42:16 -07001089 id(), std::move(header_block), fin, precedence(),
renjietang2abedac2019-05-20 14:04:50 -07001090 std::move(ack_listener));
1091 }
1092
1093 // Encode header list.
bnc609c24e2019-09-10 05:24:32 -07001094 QuicByteCount encoder_stream_sent_byte_count;
bncf21c1ad2019-06-20 20:09:50 -07001095 std::string encoded_headers =
bnc609c24e2019-09-10 05:24:32 -07001096 spdy_session_->qpack_encoder()->EncodeHeaderList(
1097 id(), header_block, &encoder_stream_sent_byte_count);
renjietang2abedac2019-05-20 14:04:50 -07001098
bncb9d5e792020-03-20 17:43:41 -07001099 if (spdy_session_->debug_visitor()) {
1100 spdy_session_->debug_visitor()->OnHeadersFrameSent(id(), header_block);
1101 }
1102
renjietang2abedac2019-05-20 14:04:50 -07001103 // Write HEADERS frame.
1104 std::unique_ptr<char[]> headers_frame_header;
1105 const size_t headers_frame_header_length =
bnc46942722019-10-29 11:56:21 -07001106 HttpEncoder::SerializeHeadersFrameHeader(encoded_headers.size(),
1107 &headers_frame_header);
renjietang2abedac2019-05-20 14:04:50 -07001108 unacked_frame_headers_offsets_.Add(
1109 send_buffer().stream_offset(),
1110 send_buffer().stream_offset() + headers_frame_header_length);
1111
dschinazi88bd5b02019-10-10 00:52:20 -07001112 QUIC_DLOG(INFO) << ENDPOINT << "Stream " << id()
renjietang2abedac2019-05-20 14:04:50 -07001113 << " is writing HEADERS frame header of length "
1114 << headers_frame_header_length;
dmcardleba2fb7e2019-12-13 07:44:34 -08001115 WriteOrBufferData(quiche::QuicheStringPiece(headers_frame_header.get(),
1116 headers_frame_header_length),
1117 /* fin = */ false, /* ack_listener = */ nullptr);
renjietang2abedac2019-05-20 14:04:50 -07001118
dschinazi88bd5b02019-10-10 00:52:20 -07001119 QUIC_DLOG(INFO) << ENDPOINT << "Stream " << id()
renjietang2abedac2019-05-20 14:04:50 -07001120 << " is writing HEADERS frame payload of length "
renjietangdbe98342019-10-18 11:00:57 -07001121 << encoded_headers.length() << " with fin " << fin;
renjietang2abedac2019-05-20 14:04:50 -07001122 WriteOrBufferData(encoded_headers, fin, nullptr);
1123
bnc20a9ad92019-10-01 10:29:14 -07001124 QuicSpdySession::LogHeaderCompressionRatioHistogram(
1125 /* using_qpack = */ true,
1126 /* is_sent = */ true,
1127 encoded_headers.size() + encoder_stream_sent_byte_count,
1128 header_block.TotalBytesUsed());
1129
bnc7a6f00f2020-04-27 13:10:18 -07001130 return encoded_headers.size();
bnc62446bc2019-03-14 06:11:25 -07001131}
1132
QUICHE teama6ef0a62019-03-07 20:34:33 -05001133#undef ENDPOINT // undef for jumbo builds
1134} // namespace quic