blob: cd5e352381827b9f6d347f13aac5b3aeb5f0248c [file] [log] [blame]
[email protected]dd3fd0e2012-11-04 05:14:401// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Ryan Hamiltona3ee93a72018-08-01 22:03:085#include "net/quic/quic_chromium_client_stream.h"
[email protected]dd3fd0e2012-11-04 05:14:406
bnc2dc1cc42016-06-23 23:08:347#include <utility>
8
Sebastien Marchand6d0558fd2019-01-25 16:49:379#include "base/bind.h"
bnc94893a72016-06-30 13:45:2510#include "base/bind_helpers.h"
[email protected]6adeb922013-09-01 22:43:2511#include "base/callback_helpers.h"
rchb27683c2015-07-29 23:53:5012#include "base/location.h"
Gabriel Charette9f60dd12020-03-06 20:48:0413#include "base/memory/ptr_util.h"
Victor Vasiliev502ba582020-09-15 23:16:1514#include "base/strings/abseil_string_conversions.h"
gabf767595f2016-05-11 18:50:3515#include "base/threading/thread_task_runner_handle.h"
rchb27683c2015-07-29 23:53:5016#include "net/base/io_buffer.h"
[email protected]dd3fd0e2012-11-04 05:14:4017#include "net/base/net_errors.h"
mikecirone8b85c432016-09-08 19:11:0018#include "net/log/net_log_event_type.h"
Ryan Hamiltona3ee93a72018-08-01 22:03:0819#include "net/quic/quic_chromium_client_session.h"
20#include "net/quic/quic_http_utils.h"
Bence Béky94658bf2018-05-11 19:22:5821#include "net/spdy/spdy_log_util.h"
Victor Vasiliev6bb59d22019-03-08 21:34:5122#include "net/third_party/quiche/src/quic/core/http/quic_spdy_session.h"
23#include "net/third_party/quiche/src/quic/core/http/spdy_utils.h"
24#include "net/third_party/quiche/src/quic/core/quic_utils.h"
25#include "net/third_party/quiche/src/quic/core/quic_write_blocked_list.h"
[email protected]dd3fd0e2012-11-04 05:14:4026
27namespace net {
rch1bcfddf22017-06-03 00:26:2928namespace {
29// Sets a boolean to a value, and restores it to the previous value once
30// the saver goes out of scope.
31class ScopedBoolSaver {
32 public:
33 ScopedBoolSaver(bool* var, bool new_val) : var_(var), old_val_(*var) {
34 *var_ = new_val;
35 }
[email protected]dd3fd0e2012-11-04 05:14:4036
rch1bcfddf22017-06-03 00:26:2937 ~ScopedBoolSaver() { *var_ = old_val_; }
38
39 private:
40 bool* var_;
41 bool old_val_;
42};
43} // namespace
44
45QuicChromiumClientStream::Handle::Handle(QuicChromiumClientStream* stream)
rch27da0452017-05-26 22:54:5446 : stream_(stream),
rch1bcfddf22017-06-03 00:26:2947 may_invoke_callbacks_(true),
rch27da0452017-05-26 22:54:5448 read_headers_buffer_(nullptr),
rch1bcfddf22017-06-03 00:26:2949 read_body_buffer_len_(0),
50 net_error_(ERR_UNEXPECTED),
Jeremy Romand54000b22019-07-08 18:40:1651 net_log_(stream->net_log()) {
rch08e198572017-05-09 16:56:5552 SaveState();
53}
54
55QuicChromiumClientStream::Handle::~Handle() {
56 if (stream_) {
57 stream_->ClearHandle();
58 // TODO(rch): If stream_ is still valid, it should probably be Reset()
59 // so that it does not leak.
Ryan Hamilton8d9ee76e2018-05-29 23:52:5260 // stream_->Reset(quic::QUIC_STREAM_CANCELLED);
rch08e198572017-05-09 16:56:5561 }
62}
63
rchfb47f712017-05-21 03:24:0064void QuicChromiumClientStream::Handle::OnInitialHeadersAvailable() {
65 if (!read_headers_callback_)
66 return; // Wait for ReadInitialHeaders to be called.
67
Bence Békyb6300042020-01-28 21:18:2068 int rv = stream_->DeliverInitialHeaders(read_headers_buffer_);
69 DCHECK_NE(ERR_IO_PENDING, rv);
rchfb47f712017-05-21 03:24:0070
Bence Békyd8a21fc32018-06-27 18:29:5871 ResetAndRun(std::move(read_headers_callback_), rv);
rch08e198572017-05-09 16:56:5572}
73
rchce246412017-05-30 13:51:5074void QuicChromiumClientStream::Handle::OnTrailingHeadersAvailable() {
75 if (!read_headers_callback_)
76 return; // Wait for ReadInitialHeaders to be called.
77
78 int rv = ERR_QUIC_PROTOCOL_ERROR;
79 if (!stream_->DeliverTrailingHeaders(read_headers_buffer_, &rv))
80 rv = ERR_QUIC_PROTOCOL_ERROR;
81
Bence Békyd8a21fc32018-06-27 18:29:5882 ResetAndRun(std::move(read_headers_callback_), rv);
rch08e198572017-05-09 16:56:5583}
84
85void QuicChromiumClientStream::Handle::OnDataAvailable() {
rch27da0452017-05-26 22:54:5486 if (!read_body_callback_)
87 return; // Wait for ReadBody to be called.
88
89 int rv = stream_->Read(read_body_buffer_, read_body_buffer_len_);
90 if (rv == ERR_IO_PENDING)
91 return; // Spurrious, likely because of trailers?
92
93 read_body_buffer_ = nullptr;
94 read_body_buffer_len_ = 0;
Bence Békyd8a21fc32018-06-27 18:29:5895 ResetAndRun(std::move(read_body_callback_), rv);
rch08e198572017-05-09 16:56:5596}
97
rch2ab4d872017-05-28 15:15:4098void QuicChromiumClientStream::Handle::OnCanWrite() {
99 if (!write_callback_)
100 return;
101
Bence Békyd8a21fc32018-06-27 18:29:58102 ResetAndRun(std::move(write_callback_), OK);
rch2ab4d872017-05-28 15:15:40103}
104
rch08e198572017-05-09 16:56:55105void QuicChromiumClientStream::Handle::OnClose() {
rch1bcfddf22017-06-03 00:26:29106 if (net_error_ == ERR_UNEXPECTED) {
Ryan Hamilton8d9ee76e2018-05-29 23:52:52107 if (stream_error() == quic::QUIC_STREAM_NO_ERROR &&
108 connection_error() == quic::QUIC_NO_ERROR && fin_sent() &&
109 fin_received()) {
rch1bcfddf22017-06-03 00:26:29110 net_error_ = ERR_CONNECTION_CLOSED;
111 } else {
112 net_error_ = ERR_QUIC_PROTOCOL_ERROR;
113 }
rch08e198572017-05-09 16:56:55114 }
rch1bcfddf22017-06-03 00:26:29115 OnError(net_error_);
rch08e198572017-05-09 16:56:55116}
117
118void QuicChromiumClientStream::Handle::OnError(int error) {
rch1bcfddf22017-06-03 00:26:29119 net_error_ = error;
rch08e198572017-05-09 16:56:55120 if (stream_)
121 SaveState();
122 stream_ = nullptr;
rch1bcfddf22017-06-03 00:26:29123
124 // Post a task to invoke the callbacks to ensure that there is no reentrancy.
Ryan Hamilton8df4adab2017-11-14 00:13:27125 // A ScopedPacketFlusher might cause an error which closes the stream under
rch1bcfddf22017-06-03 00:26:29126 // the call stack of the owner of the handle.
127 base::ThreadTaskRunnerHandle::Get()->PostTask(
128 FROM_HERE,
kylecharf4fe5172019-02-15 18:53:49129 base::BindOnce(&QuicChromiumClientStream::Handle::InvokeCallbacksOnClose,
130 weak_factory_.GetWeakPtr(), error));
rch1bcfddf22017-06-03 00:26:29131}
132
133void QuicChromiumClientStream::Handle::InvokeCallbacksOnClose(int error) {
134 // Invoking a callback may cause |this| to be deleted. If this happens, no
135 // more callbacks should be invoked. Guard against this by holding a WeakPtr
136 // to |this| and ensuring it's still valid.
137 auto guard(weak_factory_.GetWeakPtr());
138 for (auto* callback :
139 {&read_headers_callback_, &read_body_callback_, &write_callback_}) {
140 if (*callback)
Bence Békyd8a21fc32018-06-27 18:29:58141 ResetAndRun(std::move(*callback), error);
rch1bcfddf22017-06-03 00:26:29142 if (!guard.get())
143 return;
rch08e198572017-05-09 16:56:55144 }
145}
146
rchfb47f712017-05-21 03:24:00147int QuicChromiumClientStream::Handle::ReadInitialHeaders(
Ryan Hamilton0239aac2018-05-19 00:03:13148 spdy::SpdyHeaderBlock* header_block,
Bence Békyd8a21fc32018-06-27 18:29:58149 CompletionOnceCallback callback) {
rch1bcfddf22017-06-03 00:26:29150 ScopedBoolSaver saver(&may_invoke_callbacks_, false);
rchfb47f712017-05-21 03:24:00151 if (!stream_)
rch1bcfddf22017-06-03 00:26:29152 return net_error_;
rchfb47f712017-05-21 03:24:00153
Bence Békyb6300042020-01-28 21:18:20154 int rv = stream_->DeliverInitialHeaders(header_block);
155 if (rv != ERR_IO_PENDING) {
156 return rv;
157 }
rchfb47f712017-05-21 03:24:00158
159 read_headers_buffer_ = header_block;
Bence Békyd8a21fc32018-06-27 18:29:58160 SetCallback(std::move(callback), &read_headers_callback_);
rchfb47f712017-05-21 03:24:00161 return ERR_IO_PENDING;
162}
163
rch27da0452017-05-26 22:54:54164int QuicChromiumClientStream::Handle::ReadBody(
165 IOBuffer* buffer,
166 int buffer_len,
Bence Békyd8a21fc32018-06-27 18:29:58167 CompletionOnceCallback callback) {
rch1bcfddf22017-06-03 00:26:29168 ScopedBoolSaver saver(&may_invoke_callbacks_, false);
169 if (IsDoneReading())
170 return OK;
171
rch27da0452017-05-26 22:54:54172 if (!stream_)
rch1bcfddf22017-06-03 00:26:29173 return net_error_;
rch27da0452017-05-26 22:54:54174
175 int rv = stream_->Read(buffer, buffer_len);
176 if (rv != ERR_IO_PENDING)
177 return rv;
178
Bence Békyd8a21fc32018-06-27 18:29:58179 SetCallback(std::move(callback), &read_body_callback_);
rch27da0452017-05-26 22:54:54180 read_body_buffer_ = buffer;
181 read_body_buffer_len_ = buffer_len;
182 return ERR_IO_PENDING;
183}
184
rchce246412017-05-30 13:51:50185int QuicChromiumClientStream::Handle::ReadTrailingHeaders(
Ryan Hamilton0239aac2018-05-19 00:03:13186 spdy::SpdyHeaderBlock* header_block,
Bence Békyd8a21fc32018-06-27 18:29:58187 CompletionOnceCallback callback) {
rch1bcfddf22017-06-03 00:26:29188 ScopedBoolSaver saver(&may_invoke_callbacks_, false);
rchce246412017-05-30 13:51:50189 if (!stream_)
rch1bcfddf22017-06-03 00:26:29190 return net_error_;
rchce246412017-05-30 13:51:50191
192 int frame_len = 0;
193 if (stream_->DeliverTrailingHeaders(header_block, &frame_len))
194 return frame_len;
195
196 read_headers_buffer_ = header_block;
Bence Békyd8a21fc32018-06-27 18:29:58197 SetCallback(std::move(callback), &read_headers_callback_);
rchce246412017-05-30 13:51:50198 return ERR_IO_PENDING;
199}
200
rch1bcfddf22017-06-03 00:26:29201int QuicChromiumClientStream::Handle::WriteHeaders(
Ryan Hamilton0239aac2018-05-19 00:03:13202 spdy::SpdyHeaderBlock header_block,
rch08e198572017-05-09 16:56:55203 bool fin,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52204 quic::QuicReferenceCountedPointer<quic::QuicAckListenerInterface>
rch08e198572017-05-09 16:56:55205 ack_notifier_delegate) {
206 if (!stream_)
207 return 0;
rch1bcfddf22017-06-03 00:26:29208 return HandleIOComplete(stream_->WriteHeaders(std::move(header_block), fin,
209 ack_notifier_delegate));
rch08e198572017-05-09 16:56:55210}
211
212int QuicChromiumClientStream::Handle::WriteStreamData(
213 base::StringPiece data,
214 bool fin,
Bence Békyd8a21fc32018-06-27 18:29:58215 CompletionOnceCallback callback) {
rch1bcfddf22017-06-03 00:26:29216 ScopedBoolSaver saver(&may_invoke_callbacks_, false);
rch08e198572017-05-09 16:56:55217 if (!stream_)
rch1bcfddf22017-06-03 00:26:29218 return net_error_;
rch2ab4d872017-05-28 15:15:40219
Victor Vasiliev502ba582020-09-15 23:16:15220 if (stream_->WriteStreamData(base::StringPieceToStringView(data), fin))
rch1bcfddf22017-06-03 00:26:29221 return HandleIOComplete(OK);
rch2ab4d872017-05-28 15:15:40222
Bence Békyd8a21fc32018-06-27 18:29:58223 SetCallback(std::move(callback), &write_callback_);
rch2ab4d872017-05-28 15:15:40224 return ERR_IO_PENDING;
rch08e198572017-05-09 16:56:55225}
226
227int QuicChromiumClientStream::Handle::WritevStreamData(
228 const std::vector<scoped_refptr<IOBuffer>>& buffers,
229 const std::vector<int>& lengths,
230 bool fin,
Bence Békyd8a21fc32018-06-27 18:29:58231 CompletionOnceCallback callback) {
rch1bcfddf22017-06-03 00:26:29232 ScopedBoolSaver saver(&may_invoke_callbacks_, false);
rch08e198572017-05-09 16:56:55233 if (!stream_)
rch1bcfddf22017-06-03 00:26:29234 return net_error_;
rch2ab4d872017-05-28 15:15:40235
236 if (stream_->WritevStreamData(buffers, lengths, fin))
rch1bcfddf22017-06-03 00:26:29237 return HandleIOComplete(OK);
rch2ab4d872017-05-28 15:15:40238
Bence Békyd8a21fc32018-06-27 18:29:58239 SetCallback(std::move(callback), &write_callback_);
rch2ab4d872017-05-28 15:15:40240 return ERR_IO_PENDING;
rch08e198572017-05-09 16:56:55241}
242
243int QuicChromiumClientStream::Handle::Read(IOBuffer* buf, int buf_len) {
244 if (!stream_)
rch1bcfddf22017-06-03 00:26:29245 return net_error_;
rch08e198572017-05-09 16:56:55246 return stream_->Read(buf, buf_len);
247}
248
249void QuicChromiumClientStream::Handle::OnFinRead() {
rch1bcfddf22017-06-03 00:26:29250 read_headers_callback_.Reset();
rch08e198572017-05-09 16:56:55251 if (stream_)
252 stream_->OnFinRead();
253}
254
Zhongyi Shibb28b1f2018-07-18 02:41:26255void QuicChromiumClientStream::Handle::
256 DisableConnectionMigrationToCellularNetwork() {
rch08e198572017-05-09 16:56:55257 if (stream_)
Zhongyi Shibb28b1f2018-07-18 02:41:26258 stream_->DisableConnectionMigrationToCellularNetwork();
rch08e198572017-05-09 16:56:55259}
260
Ryan Hamilton0239aac2018-05-19 00:03:13261void QuicChromiumClientStream::Handle::SetPriority(
Dan Zhang98f8c7062019-07-30 14:32:00262 const spdy::SpdyStreamPrecedence& precedence) {
rch08e198572017-05-09 16:56:55263 if (stream_)
Dan Zhang98f8c7062019-07-30 14:32:00264 stream_->SetPriority(precedence);
rch08e198572017-05-09 16:56:55265}
266
267void QuicChromiumClientStream::Handle::Reset(
Ryan Hamilton8d9ee76e2018-05-29 23:52:52268 quic::QuicRstStreamErrorCode error_code) {
rch08e198572017-05-09 16:56:55269 if (stream_)
270 stream_->Reset(error_code);
271}
272
Ryan Hamilton8d9ee76e2018-05-29 23:52:52273quic::QuicStreamId QuicChromiumClientStream::Handle::id() const {
rch08e198572017-05-09 16:56:55274 if (!stream_)
275 return id_;
276 return stream_->id();
277}
278
Ryan Hamilton8d9ee76e2018-05-29 23:52:52279quic::QuicErrorCode QuicChromiumClientStream::Handle::connection_error() const {
rch08e198572017-05-09 16:56:55280 if (!stream_)
281 return connection_error_;
282 return stream_->connection_error();
283}
284
Ryan Hamilton8d9ee76e2018-05-29 23:52:52285quic::QuicRstStreamErrorCode QuicChromiumClientStream::Handle::stream_error()
286 const {
rch08e198572017-05-09 16:56:55287 if (!stream_)
288 return stream_error_;
289 return stream_->stream_error();
290}
291
292bool QuicChromiumClientStream::Handle::fin_sent() const {
293 if (!stream_)
294 return fin_sent_;
295 return stream_->fin_sent();
296}
297
298bool QuicChromiumClientStream::Handle::fin_received() const {
299 if (!stream_)
300 return fin_received_;
301 return stream_->fin_received();
302}
303
304uint64_t QuicChromiumClientStream::Handle::stream_bytes_read() const {
305 if (!stream_)
306 return stream_bytes_read_;
307 return stream_->stream_bytes_read();
308}
309
310uint64_t QuicChromiumClientStream::Handle::stream_bytes_written() const {
311 if (!stream_)
312 return stream_bytes_written_;
313 return stream_->stream_bytes_written();
314}
315
316size_t QuicChromiumClientStream::Handle::NumBytesConsumed() const {
317 if (!stream_)
318 return num_bytes_consumed_;
319 return stream_->sequencer()->NumBytesConsumed();
320}
321
Yixin Wang0d2c6b7e12017-08-16 21:12:55322bool QuicChromiumClientStream::Handle::HasBytesToRead() const {
323 if (!stream_)
324 return false;
Renjief49758b2019-01-11 23:32:41325 return stream_->HasBytesToRead();
Yixin Wang0d2c6b7e12017-08-16 21:12:55326}
327
rch08e198572017-05-09 16:56:55328bool QuicChromiumClientStream::Handle::IsDoneReading() const {
329 if (!stream_)
330 return is_done_reading_;
331 return stream_->IsDoneReading();
332}
333
334bool QuicChromiumClientStream::Handle::IsFirstStream() const {
335 if (!stream_)
336 return is_first_stream_;
337 return stream_->IsFirstStream();
338}
339
340void QuicChromiumClientStream::Handle::OnPromiseHeaderList(
Ryan Hamilton8d9ee76e2018-05-29 23:52:52341 quic::QuicStreamId promised_id,
rch08e198572017-05-09 16:56:55342 size_t frame_len,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52343 const quic::QuicHeaderList& header_list) {
rch08e198572017-05-09 16:56:55344 stream_->OnPromiseHeaderList(promised_id, frame_len, header_list);
345}
346
Zhongyi Shibb28b1f2018-07-18 02:41:26347bool QuicChromiumClientStream::Handle::can_migrate_to_cellular_network() {
rch08e198572017-05-09 16:56:55348 if (!stream_)
349 return false;
Zhongyi Shibb28b1f2018-07-18 02:41:26350 return stream_->can_migrate_to_cellular_network();
rch08e198572017-05-09 16:56:55351}
352
Yixin Wang0d2c6b7e12017-08-16 21:12:55353const NetLogWithSource& QuicChromiumClientStream::Handle::net_log() const {
354 return net_log_;
355}
356
rch08e198572017-05-09 16:56:55357void QuicChromiumClientStream::Handle::SaveState() {
358 DCHECK(stream_);
359 fin_sent_ = stream_->fin_sent();
360 fin_received_ = stream_->fin_received();
361 num_bytes_consumed_ = stream_->sequencer()->NumBytesConsumed();
362 id_ = stream_->id();
363 connection_error_ = stream_->connection_error();
364 stream_error_ = stream_->stream_error();
365 is_done_reading_ = stream_->IsDoneReading();
366 is_first_stream_ = stream_->IsFirstStream();
367 stream_bytes_read_ = stream_->stream_bytes_read();
368 stream_bytes_written_ = stream_->stream_bytes_written();
rch08e198572017-05-09 16:56:55369}
370
rch1bcfddf22017-06-03 00:26:29371void QuicChromiumClientStream::Handle::SetCallback(
Bence Békyd8a21fc32018-06-27 18:29:58372 CompletionOnceCallback new_callback,
373 CompletionOnceCallback* callback) {
rch1bcfddf22017-06-03 00:26:29374 // TODO(rch): Convert this to a DCHECK once we ensure the API is stable and
375 // bug free.
376 CHECK(!may_invoke_callbacks_);
Bence Békyd8a21fc32018-06-27 18:29:58377 *callback = std::move(new_callback);
rch1bcfddf22017-06-03 00:26:29378}
379
Bence Békyd8a21fc32018-06-27 18:29:58380void QuicChromiumClientStream::Handle::ResetAndRun(
381 CompletionOnceCallback callback,
382 int rv) {
rch1bcfddf22017-06-03 00:26:29383 // TODO(rch): Convert this to a DCHECK once we ensure the API is stable and
384 // bug free.
385 CHECK(may_invoke_callbacks_);
Bence Békyd8a21fc32018-06-27 18:29:58386 std::move(callback).Run(rv);
rch1bcfddf22017-06-03 00:26:29387}
388
389int QuicChromiumClientStream::Handle::HandleIOComplete(int rv) {
390 // If |stream_| is still valid the stream has not been closed. If the stream
391 // has not been closed, then just return |rv|.
392 if (rv < 0 || stream_)
393 return rv;
394
Ryan Hamilton8d9ee76e2018-05-29 23:52:52395 if (stream_error_ == quic::QUIC_STREAM_NO_ERROR &&
396 connection_error_ == quic::QUIC_NO_ERROR && fin_sent_ && fin_received_) {
rch1bcfddf22017-06-03 00:26:29397 return rv;
398 }
399
400 return net_error_;
401}
402
ckrasic244375a32016-02-04 21:21:22403QuicChromiumClientStream::QuicChromiumClientStream(
Ryan Hamilton8d9ee76e2018-05-29 23:52:52404 quic::QuicStreamId id,
405 quic::QuicSpdyClientSessionBase* session,
Fan Yang70c2dd22018-10-10 17:12:15406 quic::StreamType type,
Ramin Halavati683bcaa92018-02-14 08:42:39407 const NetLogWithSource& net_log,
408 const NetworkTrafficAnnotationTag& traffic_annotation)
Fan Yang70c2dd22018-10-10 17:12:15409 : quic::QuicSpdyStream(id, session, type),
rchb27683c2015-07-29 23:53:50410 net_log_(net_log),
rch08e198572017-05-09 16:56:55411 handle_(nullptr),
rchd4651b92017-05-04 00:41:17412 initial_headers_sent_(false),
ckrasic244375a32016-02-04 21:21:22413 session_(session),
Ryan Hamilton47cf9d12018-10-17 04:33:09414 quic_version_(session->connection()->transport_version()),
Zhongyi Shibb28b1f2018-07-18 02:41:26415 can_migrate_to_cellular_network_(true),
Bence Békyb6300042020-01-28 21:18:20416 initial_headers_arrived_(false),
417 headers_delivered_(false),
rch6788ad52017-05-09 04:49:04418 initial_headers_frame_len_(0),
Jeremy Romand54000b22019-07-08 18:40:16419 trailing_headers_frame_len_(0) {}
[email protected]dd3fd0e2012-11-04 05:14:40420
Fan Yang32c5a112018-12-10 20:06:33421QuicChromiumClientStream::QuicChromiumClientStream(
Ryan Hamilton8380c652019-06-04 02:25:06422 quic::PendingStream* pending,
Fan Yang32c5a112018-12-10 20:06:33423 quic::QuicSpdyClientSessionBase* session,
424 quic::StreamType type,
425 const NetLogWithSource& net_log,
426 const NetworkTrafficAnnotationTag& traffic_annotation)
Ryan Hamilton8380c652019-06-04 02:25:06427 : quic::QuicSpdyStream(pending, session, type),
Fan Yang32c5a112018-12-10 20:06:33428 net_log_(net_log),
429 handle_(nullptr),
Fan Yang32c5a112018-12-10 20:06:33430 initial_headers_sent_(false),
431 session_(session),
432 quic_version_(session->connection()->transport_version()),
433 can_migrate_to_cellular_network_(true),
Bence Békyb6300042020-01-28 21:18:20434 initial_headers_arrived_(false),
435 headers_delivered_(false),
Fan Yang32c5a112018-12-10 20:06:33436 initial_headers_frame_len_(0),
Jeremy Romand54000b22019-07-08 18:40:16437 trailing_headers_frame_len_(0) {}
Fan Yang32c5a112018-12-10 20:06:33438
rch12fef552016-01-15 16:26:31439QuicChromiumClientStream::~QuicChromiumClientStream() {
rch08e198572017-05-09 16:56:55440 if (handle_)
441 handle_->OnClose();
[email protected]dd3fd0e2012-11-04 05:14:40442}
443
dahollingsaf3796492016-05-25 19:21:35444void QuicChromiumClientStream::OnInitialHeadersComplete(
445 bool fin,
446 size_t frame_len,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52447 const quic::QuicHeaderList& header_list) {
448 quic::QuicSpdyStream::OnInitialHeadersComplete(fin, frame_len, header_list);
dahollingsaf3796492016-05-25 19:21:35449
Ryan Hamilton0239aac2018-05-19 00:03:13450 spdy::SpdyHeaderBlock header_block;
dahollingsaf3796492016-05-25 19:21:35451 int64_t length = -1;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52452 if (!quic::SpdyUtils::CopyAndValidateHeaders(header_list, &length,
453 &header_block)) {
dahollingsaf3796492016-05-25 19:21:35454 DLOG(ERROR) << "Failed to parse header list: " << header_list.DebugString();
455 ConsumeHeaderList();
Ryan Hamilton8d9ee76e2018-05-29 23:52:52456 Reset(quic::QUIC_BAD_APPLICATION_PAYLOAD);
dahollingsaf3796492016-05-25 19:21:35457 return;
458 }
459
460 ConsumeHeaderList();
461 session_->OnInitialHeadersComplete(id(), header_block);
462
rch08e198572017-05-09 16:56:55463 // Buffer the headers and deliver them when the handle arrives.
Bence Békyb6300042020-01-28 21:18:20464 initial_headers_arrived_ = true;
rch6788ad52017-05-09 04:49:04465 initial_headers_ = std::move(header_block);
466 initial_headers_frame_len_ = frame_len;
rchfb47f712017-05-21 03:24:00467
468 if (handle_) {
469 // The handle will be notified of the headers via a posted task.
470 NotifyHandleOfInitialHeadersAvailableLater();
471 }
dahollingsaf3796492016-05-25 19:21:35472}
473
474void QuicChromiumClientStream::OnTrailingHeadersComplete(
475 bool fin,
476 size_t frame_len,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52477 const quic::QuicHeaderList& header_list) {
478 quic::QuicSpdyStream::OnTrailingHeadersComplete(fin, frame_len, header_list);
rchce246412017-05-30 13:51:50479 trailing_headers_frame_len_ = frame_len;
480 if (handle_) {
481 // The handle will be notified of the headers via a posted task.
482 NotifyHandleOfTrailingHeadersAvailableLater();
483 }
dahollingsaf3796492016-05-25 19:21:35484}
485
ckrasic769733c2016-06-30 00:42:13486void QuicChromiumClientStream::OnPromiseHeaderList(
Ryan Hamilton8d9ee76e2018-05-29 23:52:52487 quic::QuicStreamId promised_id,
ckrasic769733c2016-06-30 00:42:13488 size_t frame_len,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52489 const quic::QuicHeaderList& header_list) {
Ryan Hamilton0239aac2018-05-19 00:03:13490 spdy::SpdyHeaderBlock promise_headers;
ckrasic769733c2016-06-30 00:42:13491 int64_t content_length = -1;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52492 if (!quic::SpdyUtils::CopyAndValidateHeaders(header_list, &content_length,
493 &promise_headers)) {
ckrasic769733c2016-06-30 00:42:13494 DLOG(ERROR) << "Failed to parse header list: " << header_list.DebugString();
495 ConsumeHeaderList();
Ryan Hamilton8d9ee76e2018-05-29 23:52:52496 Reset(quic::QUIC_BAD_APPLICATION_PAYLOAD);
ckrasic769733c2016-06-30 00:42:13497 return;
498 }
499 ConsumeHeaderList();
500
501 session_->HandlePromised(id(), promised_id, promise_headers);
502}
503
Frank Kastenholz1dac18b62018-11-29 18:50:36504void QuicChromiumClientStream::OnBodyAvailable() {
rchb27683c2015-07-29 23:53:50505 if (!FinishedReadingHeaders() || !headers_delivered_) {
rch7dd15702015-07-01 18:57:57506 // Buffer the data in the sequencer until the headers have been read.
rchb27683c2015-07-29 23:53:50507 return;
rch7dd15702015-07-01 18:57:57508 }
509
Renjief49758b2019-01-11 23:32:41510 if (!HasBytesToRead() && !FinishedReadingTrailers()) {
xunjieli7640faa2016-10-06 00:45:42511 // If there is no data to read, wait until either FIN is received or
512 // trailers are delivered.
513 return;
514 }
515
rch08e198572017-05-09 16:56:55516 // The handle will read the data via a posted task, and
rchb27683c2015-07-29 23:53:50517 // will be able to, potentially, read all data which has queued up.
rch08e198572017-05-09 16:56:55518 if (handle_)
519 NotifyHandleOfDataAvailableLater();
[email protected]dd3fd0e2012-11-04 05:14:40520}
521
rch12fef552016-01-15 16:26:31522void QuicChromiumClientStream::OnClose() {
rch08e198572017-05-09 16:56:55523 if (handle_) {
524 handle_->OnClose();
525 handle_ = nullptr;
[email protected]f702d572012-12-04 15:56:20526 }
Ryan Hamilton8d9ee76e2018-05-29 23:52:52527 quic::QuicStream::OnClose();
[email protected]dd3fd0e2012-11-04 05:14:40528}
529
rch12fef552016-01-15 16:26:31530void QuicChromiumClientStream::OnCanWrite() {
Ryan Hamilton8d9ee76e2018-05-29 23:52:52531 quic::QuicStream::OnCanWrite();
[email protected]6adeb922013-09-01 22:43:25532
rch2ab4d872017-05-28 15:15:40533 if (!HasBufferedData() && handle_)
534 handle_->OnCanWrite();
[email protected]6adeb922013-09-01 22:43:25535}
536
xunjieli5fafe142016-03-23 23:32:54537size_t QuicChromiumClientStream::WriteHeaders(
Ryan Hamilton0239aac2018-05-19 00:03:13538 spdy::SpdyHeaderBlock header_block,
xunjieli5fafe142016-03-23 23:32:54539 bool fin,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52540 quic::QuicReferenceCountedPointer<quic::QuicAckListenerInterface>
541 ack_listener) {
Victor Vasiliev29197e22020-01-16 20:48:32542 if (!session()->OneRttKeysAvailable()) {
rchcb1d6bde2016-06-18 00:33:07543 auto entry = header_block.find(":method");
544 DCHECK(entry != header_block.end());
545 DCHECK_NE("POST", entry->second);
546 }
xunjieli5fafe142016-03-23 23:32:54547 net_log_.AddEvent(
mikecirone8b85c432016-09-08 19:11:00548 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
Eric Roman06bd9742019-07-13 15:19:13549 [&](NetLogCaptureMode capture_mode) {
Dan Zhang98f8c7062019-07-30 14:32:00550 return QuicRequestNetLogParams(
551 id(), &header_block, precedence().spdy3_priority(), capture_mode);
Eric Roman06bd9742019-07-13 15:19:13552 });
Ryan Hamilton8d9ee76e2018-05-29 23:52:52553 size_t len = quic::QuicSpdyStream::WriteHeaders(std::move(header_block), fin,
554 std::move(ack_listener));
rchd4651b92017-05-04 00:41:17555 initial_headers_sent_ = true;
556 return len;
xunjieli5fafe142016-03-23 23:32:54557}
558
Zhongyi Shid1c00fc42019-12-14 06:05:09559bool QuicChromiumClientStream::WriteStreamData(quiche::QuicheStringPiece data,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52560 bool fin) {
rch2ab4d872017-05-28 15:15:40561 // Must not be called when data is buffered.
[email protected]6adeb922013-09-01 22:43:25562 DCHECK(!HasBufferedData());
563 // Writes the data, or buffers it.
Dan Zhang5ae7041a22019-02-13 23:58:18564 WriteOrBufferBody(data, fin);
rch2ab4d872017-05-28 15:15:40565 return !HasBufferedData(); // Was all data written?
[email protected]6adeb922013-09-01 22:43:25566}
567
rch2ab4d872017-05-28 15:15:40568bool QuicChromiumClientStream::WritevStreamData(
xunjieli2328a2682016-05-16 19:38:25569 const std::vector<scoped_refptr<IOBuffer>>& buffers,
xunjieli07a42ce2016-04-26 20:05:31570 const std::vector<int>& lengths,
rch2ab4d872017-05-28 15:15:40571 bool fin) {
xunjieli07a42ce2016-04-26 20:05:31572 // Must not be called when data is buffered.
573 DCHECK(!HasBufferedData());
574 // Writes the data, or buffers it.
Ryan Hamiltona3ee93a72018-08-01 22:03:08575 for (size_t i = 0; i < buffers.size(); ++i) {
576 bool is_fin = fin && (i == buffers.size() - 1);
Zhongyi Shid1c00fc42019-12-14 06:05:09577 quiche::QuicheStringPiece string_data(buffers[i]->data(), lengths[i]);
Dan Zhang5ae7041a22019-02-13 23:58:18578 WriteOrBufferBody(string_data, is_fin);
Ryan Hamiltona3ee93a72018-08-01 22:03:08579 }
rch2ab4d872017-05-28 15:15:40580 return !HasBufferedData(); // Was all data written?
xunjieli07a42ce2016-04-26 20:05:31581}
582
rch08e198572017-05-09 16:56:55583std::unique_ptr<QuicChromiumClientStream::Handle>
rch1bcfddf22017-06-03 00:26:29584QuicChromiumClientStream::CreateHandle() {
rch08e198572017-05-09 16:56:55585 DCHECK(!handle_);
Ryan Hamiltona3ee93a72018-08-01 22:03:08586 auto handle = base::WrapUnique(new QuicChromiumClientStream::Handle(this));
rch08e198572017-05-09 16:56:55587 handle_ = handle.get();
rch6788ad52017-05-09 04:49:04588
589 // Should this perhaps be via PostTask to make reasoning simpler?
Bence Békyb6300042020-01-28 21:18:20590 if (initial_headers_arrived_) {
rchfb47f712017-05-21 03:24:00591 handle_->OnInitialHeadersAvailable();
Bence Békyb6300042020-01-28 21:18:20592 }
rch08e198572017-05-09 16:56:55593
594 return handle;
595}
596
597void QuicChromiumClientStream::ClearHandle() {
598 handle_ = nullptr;
[email protected]dd3fd0e2012-11-04 05:14:40599}
600
rch12fef552016-01-15 16:26:31601void QuicChromiumClientStream::OnError(int error) {
rch08e198572017-05-09 16:56:55602 if (handle_) {
603 QuicChromiumClientStream::Handle* handle = handle_;
604 handle_ = nullptr;
605 handle->OnError(error);
[email protected]56dfb902013-01-03 23:17:55606 }
607}
608
rch12fef552016-01-15 16:26:31609int QuicChromiumClientStream::Read(IOBuffer* buf, int buf_len) {
xunjieliec0ed02a2016-10-10 18:05:06610 if (IsDoneReading())
rchb27683c2015-07-29 23:53:50611 return 0; // EOF
612
613 if (!HasBytesToRead())
614 return ERR_IO_PENDING;
615
616 iovec iov;
617 iov.iov_base = buf->data();
618 iov.iov_len = buf_len;
xunjieliec0ed02a2016-10-10 18:05:06619 size_t bytes_read = Readv(&iov, 1);
rch03499252017-05-03 17:44:37620 // Since HasBytesToRead is true, Readv() must of read some data.
621 DCHECK_NE(0u, bytes_read);
xunjieliec0ed02a2016-10-10 18:05:06622 return bytes_read;
rchb27683c2015-07-29 23:53:50623}
624
rchfb47f712017-05-21 03:24:00625void QuicChromiumClientStream::NotifyHandleOfInitialHeadersAvailableLater() {
rch08e198572017-05-09 16:56:55626 DCHECK(handle_);
rch6788ad52017-05-09 04:49:04627 base::ThreadTaskRunnerHandle::Get()->PostTask(
628 FROM_HERE,
kylecharf4fe5172019-02-15 18:53:49629 base::BindOnce(
rch08e198572017-05-09 16:56:55630 &QuicChromiumClientStream::NotifyHandleOfInitialHeadersAvailable,
rchfb47f712017-05-21 03:24:00631 weak_factory_.GetWeakPtr()));
rchb27683c2015-07-29 23:53:50632}
633
rchfb47f712017-05-21 03:24:00634void QuicChromiumClientStream::NotifyHandleOfInitialHeadersAvailable() {
rch08e198572017-05-09 16:56:55635 if (!handle_)
rchb27683c2015-07-29 23:53:50636 return;
637
rchfb47f712017-05-21 03:24:00638 if (!headers_delivered_)
639 handle_->OnInitialHeadersAvailable();
rchec5b74ac2017-05-09 13:31:40640}
641
rchce246412017-05-30 13:51:50642void QuicChromiumClientStream::NotifyHandleOfTrailingHeadersAvailableLater() {
rch08e198572017-05-09 16:56:55643 DCHECK(handle_);
rchec5b74ac2017-05-09 13:31:40644 base::ThreadTaskRunnerHandle::Get()->PostTask(
645 FROM_HERE,
kylecharf4fe5172019-02-15 18:53:49646 base::BindOnce(
rch08e198572017-05-09 16:56:55647 &QuicChromiumClientStream::NotifyHandleOfTrailingHeadersAvailable,
rchce246412017-05-30 13:51:50648 weak_factory_.GetWeakPtr()));
rchec5b74ac2017-05-09 13:31:40649}
650
rchce246412017-05-30 13:51:50651void QuicChromiumClientStream::NotifyHandleOfTrailingHeadersAvailable() {
rch08e198572017-05-09 16:56:55652 if (!handle_)
rchec5b74ac2017-05-09 13:31:40653 return;
654
655 DCHECK(headers_delivered_);
rch1bcfddf22017-06-03 00:26:29656 // Post an async task to notify handle of the FIN flag.
rch08e198572017-05-09 16:56:55657 NotifyHandleOfDataAvailableLater();
rchce246412017-05-30 13:51:50658 handle_->OnTrailingHeadersAvailable();
rchb27683c2015-07-29 23:53:50659}
660
Bence Békyb6300042020-01-28 21:18:20661int QuicChromiumClientStream::DeliverInitialHeaders(
662 spdy::SpdyHeaderBlock* headers) {
663 if (!initial_headers_arrived_) {
664 return ERR_IO_PENDING;
665 }
rchfb47f712017-05-21 03:24:00666
667 headers_delivered_ = true;
Bence Békyb6300042020-01-28 21:18:20668
669 if (initial_headers_.empty()) {
670 return ERR_INVALID_RESPONSE;
671 }
672
rchfb47f712017-05-21 03:24:00673 net_log_.AddEvent(
674 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_READ_RESPONSE_HEADERS,
Eric Roman06bd9742019-07-13 15:19:13675 [&](NetLogCaptureMode capture_mode) {
676 return QuicResponseNetLogParams(id(), fin_received(), &initial_headers_,
677 capture_mode);
678 });
rchfb47f712017-05-21 03:24:00679
680 *headers = std::move(initial_headers_);
Bence Békyb6300042020-01-28 21:18:20681 return initial_headers_frame_len_;
rchfb47f712017-05-21 03:24:00682}
683
Ryan Hamilton0239aac2018-05-19 00:03:13684bool QuicChromiumClientStream::DeliverTrailingHeaders(
685 spdy::SpdyHeaderBlock* headers,
686 int* frame_len) {
rchce246412017-05-30 13:51:50687 if (received_trailers().empty())
688 return false;
689
690 net_log_.AddEvent(
691 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_READ_RESPONSE_TRAILERS,
Eric Roman06bd9742019-07-13 15:19:13692 [&](NetLogCaptureMode capture_mode) {
693 return QuicResponseNetLogParams(id(), fin_received(),
694 &received_trailers(), capture_mode);
695 });
rchce246412017-05-30 13:51:50696
697 *headers = received_trailers().Clone();
698 *frame_len = trailing_headers_frame_len_;
699
700 MarkTrailersConsumed();
701 return true;
702}
703
rch08e198572017-05-09 16:56:55704void QuicChromiumClientStream::NotifyHandleOfDataAvailableLater() {
705 DCHECK(handle_);
rch6788ad52017-05-09 04:49:04706 base::ThreadTaskRunnerHandle::Get()->PostTask(
707 FROM_HERE,
kylecharf4fe5172019-02-15 18:53:49708 base::BindOnce(&QuicChromiumClientStream::NotifyHandleOfDataAvailable,
709 weak_factory_.GetWeakPtr()));
rchb27683c2015-07-29 23:53:50710}
711
rch08e198572017-05-09 16:56:55712void QuicChromiumClientStream::NotifyHandleOfDataAvailable() {
713 if (handle_)
714 handle_->OnDataAvailable();
rchb27683c2015-07-29 23:53:50715}
716
Zhongyi Shibb28b1f2018-07-18 02:41:26717void QuicChromiumClientStream::DisableConnectionMigrationToCellularNetwork() {
718 can_migrate_to_cellular_network_ = false;
jri231c2972016-03-08 19:50:11719}
720
xunjieli100937eb52016-09-15 20:09:37721bool QuicChromiumClientStream::IsFirstStream() {
Victor Vasiliev7da08172019-10-14 06:04:25722 if (VersionUsesHttp3(quic_version_)) {
Fan Yang2330d182019-08-05 14:50:50723 return id() == quic::QuicUtils::GetFirstBidirectionalStreamId(
724 quic_version_, quic::Perspective::IS_CLIENT);
725 }
Fan Yang32c5a112018-12-10 20:06:33726 return id() == quic::QuicUtils::GetHeadersStreamId(quic_version_) +
727 quic::QuicUtils::StreamIdDelta(quic_version_);
xunjieli100937eb52016-09-15 20:09:37728}
729
[email protected]dd3fd0e2012-11-04 05:14:40730} // namespace net