blob: 2274ef374790504d8ebf4135e1d34670f6edf10a [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
bnc94893a72016-06-30 13:45:259#include "base/bind_helpers.h"
[email protected]6adeb922013-09-01 22:43:2510#include "base/callback_helpers.h"
rchb27683c2015-07-29 23:53:5011#include "base/location.h"
gabf767595f2016-05-11 18:50:3512#include "base/threading/thread_task_runner_handle.h"
rchb27683c2015-07-29 23:53:5013#include "net/base/io_buffer.h"
[email protected]dd3fd0e2012-11-04 05:14:4014#include "net/base/net_errors.h"
mikecirone8b85c432016-09-08 19:11:0015#include "net/log/net_log_event_type.h"
Ryan Hamiltona3ee93a72018-08-01 22:03:0816#include "net/quic/quic_chromium_client_session.h"
17#include "net/quic/quic_http_utils.h"
Bence Béky94658bf2018-05-11 19:22:5818#include "net/spdy/spdy_log_util.h"
Victor Vasilievc5b409c22018-07-24 12:23:4619#include "net/third_party/quic/core/http/quic_spdy_session.h"
20#include "net/third_party/quic/core/http/spdy_utils.h"
Ryan Hamilton47cf9d12018-10-17 04:33:0921#include "net/third_party/quic/core/quic_utils.h"
Ryan Hamilton56b10c5d2018-05-11 13:40:1622#include "net/third_party/quic/core/quic_write_blocked_list.h"
[email protected]dd3fd0e2012-11-04 05:14:4023
24namespace net {
rch1bcfddf22017-06-03 00:26:2925namespace {
26// Sets a boolean to a value, and restores it to the previous value once
27// the saver goes out of scope.
28class ScopedBoolSaver {
29 public:
30 ScopedBoolSaver(bool* var, bool new_val) : var_(var), old_val_(*var) {
31 *var_ = new_val;
32 }
[email protected]dd3fd0e2012-11-04 05:14:4033
rch1bcfddf22017-06-03 00:26:2934 ~ScopedBoolSaver() { *var_ = old_val_; }
35
36 private:
37 bool* var_;
38 bool old_val_;
39};
40} // namespace
41
42QuicChromiumClientStream::Handle::Handle(QuicChromiumClientStream* stream)
rch27da0452017-05-26 22:54:5443 : stream_(stream),
rch1bcfddf22017-06-03 00:26:2944 may_invoke_callbacks_(true),
rch27da0452017-05-26 22:54:5445 read_headers_buffer_(nullptr),
rch1bcfddf22017-06-03 00:26:2946 read_body_buffer_len_(0),
47 net_error_(ERR_UNEXPECTED),
Yixin Wang0d2c6b7e12017-08-16 21:12:5548 net_log_(stream->net_log()),
rch1bcfddf22017-06-03 00:26:2949 weak_factory_(this) {
rch08e198572017-05-09 16:56:5550 SaveState();
51}
52
53QuicChromiumClientStream::Handle::~Handle() {
54 if (stream_) {
55 stream_->ClearHandle();
56 // TODO(rch): If stream_ is still valid, it should probably be Reset()
57 // so that it does not leak.
Ryan Hamilton8d9ee76e2018-05-29 23:52:5258 // stream_->Reset(quic::QUIC_STREAM_CANCELLED);
rch08e198572017-05-09 16:56:5559 }
60}
61
rchfb47f712017-05-21 03:24:0062void QuicChromiumClientStream::Handle::OnInitialHeadersAvailable() {
63 if (!read_headers_callback_)
64 return; // Wait for ReadInitialHeaders to be called.
65
66 int rv = ERR_QUIC_PROTOCOL_ERROR;
67 if (!stream_->DeliverInitialHeaders(read_headers_buffer_, &rv))
68 rv = ERR_QUIC_PROTOCOL_ERROR;
69
Bence Békyd8a21fc32018-06-27 18:29:5870 ResetAndRun(std::move(read_headers_callback_), rv);
rch08e198572017-05-09 16:56:5571}
72
rchce246412017-05-30 13:51:5073void QuicChromiumClientStream::Handle::OnTrailingHeadersAvailable() {
74 if (!read_headers_callback_)
75 return; // Wait for ReadInitialHeaders to be called.
76
77 int rv = ERR_QUIC_PROTOCOL_ERROR;
78 if (!stream_->DeliverTrailingHeaders(read_headers_buffer_, &rv))
79 rv = ERR_QUIC_PROTOCOL_ERROR;
80
Bence Békyd8a21fc32018-06-27 18:29:5881 ResetAndRun(std::move(read_headers_callback_), rv);
rch08e198572017-05-09 16:56:5582}
83
84void QuicChromiumClientStream::Handle::OnDataAvailable() {
rch27da0452017-05-26 22:54:5485 if (!read_body_callback_)
86 return; // Wait for ReadBody to be called.
87
88 int rv = stream_->Read(read_body_buffer_, read_body_buffer_len_);
89 if (rv == ERR_IO_PENDING)
90 return; // Spurrious, likely because of trailers?
91
92 read_body_buffer_ = nullptr;
93 read_body_buffer_len_ = 0;
Bence Békyd8a21fc32018-06-27 18:29:5894 ResetAndRun(std::move(read_body_callback_), rv);
rch08e198572017-05-09 16:56:5595}
96
rch2ab4d872017-05-28 15:15:4097void QuicChromiumClientStream::Handle::OnCanWrite() {
98 if (!write_callback_)
99 return;
100
Bence Békyd8a21fc32018-06-27 18:29:58101 ResetAndRun(std::move(write_callback_), OK);
rch2ab4d872017-05-28 15:15:40102}
103
rch08e198572017-05-09 16:56:55104void QuicChromiumClientStream::Handle::OnClose() {
rch1bcfddf22017-06-03 00:26:29105 if (net_error_ == ERR_UNEXPECTED) {
Ryan Hamilton8d9ee76e2018-05-29 23:52:52106 if (stream_error() == quic::QUIC_STREAM_NO_ERROR &&
107 connection_error() == quic::QUIC_NO_ERROR && fin_sent() &&
108 fin_received()) {
rch1bcfddf22017-06-03 00:26:29109 net_error_ = ERR_CONNECTION_CLOSED;
110 } else {
111 net_error_ = ERR_QUIC_PROTOCOL_ERROR;
112 }
rch08e198572017-05-09 16:56:55113 }
rch1bcfddf22017-06-03 00:26:29114 OnError(net_error_);
rch08e198572017-05-09 16:56:55115}
116
117void QuicChromiumClientStream::Handle::OnError(int error) {
rch1bcfddf22017-06-03 00:26:29118 net_error_ = error;
rch08e198572017-05-09 16:56:55119 if (stream_)
120 SaveState();
121 stream_ = nullptr;
rch1bcfddf22017-06-03 00:26:29122
123 // Post a task to invoke the callbacks to ensure that there is no reentrancy.
Ryan Hamilton8df4adab2017-11-14 00:13:27124 // A ScopedPacketFlusher might cause an error which closes the stream under
rch1bcfddf22017-06-03 00:26:29125 // the call stack of the owner of the handle.
126 base::ThreadTaskRunnerHandle::Get()->PostTask(
127 FROM_HERE,
128 base::Bind(&QuicChromiumClientStream::Handle::InvokeCallbacksOnClose,
129 weak_factory_.GetWeakPtr(), error));
130}
131
132void QuicChromiumClientStream::Handle::InvokeCallbacksOnClose(int error) {
133 // Invoking a callback may cause |this| to be deleted. If this happens, no
134 // more callbacks should be invoked. Guard against this by holding a WeakPtr
135 // to |this| and ensuring it's still valid.
136 auto guard(weak_factory_.GetWeakPtr());
137 for (auto* callback :
138 {&read_headers_callback_, &read_body_callback_, &write_callback_}) {
139 if (*callback)
Bence Békyd8a21fc32018-06-27 18:29:58140 ResetAndRun(std::move(*callback), error);
rch1bcfddf22017-06-03 00:26:29141 if (!guard.get())
142 return;
rch08e198572017-05-09 16:56:55143 }
144}
145
rchfb47f712017-05-21 03:24:00146int QuicChromiumClientStream::Handle::ReadInitialHeaders(
Ryan Hamilton0239aac2018-05-19 00:03:13147 spdy::SpdyHeaderBlock* header_block,
Bence Békyd8a21fc32018-06-27 18:29:58148 CompletionOnceCallback callback) {
rch1bcfddf22017-06-03 00:26:29149 ScopedBoolSaver saver(&may_invoke_callbacks_, false);
rchfb47f712017-05-21 03:24:00150 if (!stream_)
rch1bcfddf22017-06-03 00:26:29151 return net_error_;
rchfb47f712017-05-21 03:24:00152
153 int frame_len = 0;
154 if (stream_->DeliverInitialHeaders(header_block, &frame_len))
155 return frame_len;
156
157 read_headers_buffer_ = header_block;
Bence Békyd8a21fc32018-06-27 18:29:58158 SetCallback(std::move(callback), &read_headers_callback_);
rchfb47f712017-05-21 03:24:00159 return ERR_IO_PENDING;
160}
161
rch27da0452017-05-26 22:54:54162int QuicChromiumClientStream::Handle::ReadBody(
163 IOBuffer* buffer,
164 int buffer_len,
Bence Békyd8a21fc32018-06-27 18:29:58165 CompletionOnceCallback callback) {
rch1bcfddf22017-06-03 00:26:29166 ScopedBoolSaver saver(&may_invoke_callbacks_, false);
167 if (IsDoneReading())
168 return OK;
169
rch27da0452017-05-26 22:54:54170 if (!stream_)
rch1bcfddf22017-06-03 00:26:29171 return net_error_;
rch27da0452017-05-26 22:54:54172
173 int rv = stream_->Read(buffer, buffer_len);
174 if (rv != ERR_IO_PENDING)
175 return rv;
176
Bence Békyd8a21fc32018-06-27 18:29:58177 SetCallback(std::move(callback), &read_body_callback_);
rch27da0452017-05-26 22:54:54178 read_body_buffer_ = buffer;
179 read_body_buffer_len_ = buffer_len;
180 return ERR_IO_PENDING;
181}
182
rchce246412017-05-30 13:51:50183int QuicChromiumClientStream::Handle::ReadTrailingHeaders(
Ryan Hamilton0239aac2018-05-19 00:03:13184 spdy::SpdyHeaderBlock* header_block,
Bence Békyd8a21fc32018-06-27 18:29:58185 CompletionOnceCallback callback) {
rch1bcfddf22017-06-03 00:26:29186 ScopedBoolSaver saver(&may_invoke_callbacks_, false);
rchce246412017-05-30 13:51:50187 if (!stream_)
rch1bcfddf22017-06-03 00:26:29188 return net_error_;
rchce246412017-05-30 13:51:50189
190 int frame_len = 0;
191 if (stream_->DeliverTrailingHeaders(header_block, &frame_len))
192 return frame_len;
193
194 read_headers_buffer_ = header_block;
Bence Békyd8a21fc32018-06-27 18:29:58195 SetCallback(std::move(callback), &read_headers_callback_);
rchce246412017-05-30 13:51:50196 return ERR_IO_PENDING;
197}
198
rch1bcfddf22017-06-03 00:26:29199int QuicChromiumClientStream::Handle::WriteHeaders(
Ryan Hamilton0239aac2018-05-19 00:03:13200 spdy::SpdyHeaderBlock header_block,
rch08e198572017-05-09 16:56:55201 bool fin,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52202 quic::QuicReferenceCountedPointer<quic::QuicAckListenerInterface>
rch08e198572017-05-09 16:56:55203 ack_notifier_delegate) {
204 if (!stream_)
205 return 0;
rch1bcfddf22017-06-03 00:26:29206 return HandleIOComplete(stream_->WriteHeaders(std::move(header_block), fin,
207 ack_notifier_delegate));
rch08e198572017-05-09 16:56:55208}
209
210int QuicChromiumClientStream::Handle::WriteStreamData(
211 base::StringPiece data,
212 bool fin,
Bence Békyd8a21fc32018-06-27 18:29:58213 CompletionOnceCallback callback) {
rch1bcfddf22017-06-03 00:26:29214 ScopedBoolSaver saver(&may_invoke_callbacks_, false);
rch08e198572017-05-09 16:56:55215 if (!stream_)
rch1bcfddf22017-06-03 00:26:29216 return net_error_;
rch2ab4d872017-05-28 15:15:40217
218 if (stream_->WriteStreamData(data, fin))
rch1bcfddf22017-06-03 00:26:29219 return HandleIOComplete(OK);
rch2ab4d872017-05-28 15:15:40220
Bence Békyd8a21fc32018-06-27 18:29:58221 SetCallback(std::move(callback), &write_callback_);
rch2ab4d872017-05-28 15:15:40222 return ERR_IO_PENDING;
rch08e198572017-05-09 16:56:55223}
224
225int QuicChromiumClientStream::Handle::WritevStreamData(
226 const std::vector<scoped_refptr<IOBuffer>>& buffers,
227 const std::vector<int>& lengths,
228 bool fin,
Bence Békyd8a21fc32018-06-27 18:29:58229 CompletionOnceCallback callback) {
rch1bcfddf22017-06-03 00:26:29230 ScopedBoolSaver saver(&may_invoke_callbacks_, false);
rch08e198572017-05-09 16:56:55231 if (!stream_)
rch1bcfddf22017-06-03 00:26:29232 return net_error_;
rch2ab4d872017-05-28 15:15:40233
234 if (stream_->WritevStreamData(buffers, lengths, fin))
rch1bcfddf22017-06-03 00:26:29235 return HandleIOComplete(OK);
rch2ab4d872017-05-28 15:15:40236
Bence Békyd8a21fc32018-06-27 18:29:58237 SetCallback(std::move(callback), &write_callback_);
rch2ab4d872017-05-28 15:15:40238 return ERR_IO_PENDING;
rch08e198572017-05-09 16:56:55239}
240
241int QuicChromiumClientStream::Handle::Read(IOBuffer* buf, int buf_len) {
242 if (!stream_)
rch1bcfddf22017-06-03 00:26:29243 return net_error_;
rch08e198572017-05-09 16:56:55244 return stream_->Read(buf, buf_len);
245}
246
247void QuicChromiumClientStream::Handle::OnFinRead() {
rch1bcfddf22017-06-03 00:26:29248 read_headers_callback_.Reset();
rch08e198572017-05-09 16:56:55249 if (stream_)
250 stream_->OnFinRead();
251}
252
Zhongyi Shibb28b1f2018-07-18 02:41:26253void QuicChromiumClientStream::Handle::
254 DisableConnectionMigrationToCellularNetwork() {
rch08e198572017-05-09 16:56:55255 if (stream_)
Zhongyi Shibb28b1f2018-07-18 02:41:26256 stream_->DisableConnectionMigrationToCellularNetwork();
rch08e198572017-05-09 16:56:55257}
258
Ryan Hamilton0239aac2018-05-19 00:03:13259void QuicChromiumClientStream::Handle::SetPriority(
260 spdy::SpdyPriority priority) {
rch08e198572017-05-09 16:56:55261 if (stream_)
262 stream_->SetPriority(priority);
263}
264
265void QuicChromiumClientStream::Handle::Reset(
Ryan Hamilton8d9ee76e2018-05-29 23:52:52266 quic::QuicRstStreamErrorCode error_code) {
rch08e198572017-05-09 16:56:55267 if (stream_)
268 stream_->Reset(error_code);
269}
270
Ryan Hamilton8d9ee76e2018-05-29 23:52:52271quic::QuicStreamId QuicChromiumClientStream::Handle::id() const {
rch08e198572017-05-09 16:56:55272 if (!stream_)
273 return id_;
274 return stream_->id();
275}
276
Ryan Hamilton8d9ee76e2018-05-29 23:52:52277quic::QuicErrorCode QuicChromiumClientStream::Handle::connection_error() const {
rch08e198572017-05-09 16:56:55278 if (!stream_)
279 return connection_error_;
280 return stream_->connection_error();
281}
282
Ryan Hamilton8d9ee76e2018-05-29 23:52:52283quic::QuicRstStreamErrorCode QuicChromiumClientStream::Handle::stream_error()
284 const {
rch08e198572017-05-09 16:56:55285 if (!stream_)
286 return stream_error_;
287 return stream_->stream_error();
288}
289
290bool QuicChromiumClientStream::Handle::fin_sent() const {
291 if (!stream_)
292 return fin_sent_;
293 return stream_->fin_sent();
294}
295
296bool QuicChromiumClientStream::Handle::fin_received() const {
297 if (!stream_)
298 return fin_received_;
299 return stream_->fin_received();
300}
301
302uint64_t QuicChromiumClientStream::Handle::stream_bytes_read() const {
303 if (!stream_)
304 return stream_bytes_read_;
305 return stream_->stream_bytes_read();
306}
307
308uint64_t QuicChromiumClientStream::Handle::stream_bytes_written() const {
309 if (!stream_)
310 return stream_bytes_written_;
311 return stream_->stream_bytes_written();
312}
313
314size_t QuicChromiumClientStream::Handle::NumBytesConsumed() const {
315 if (!stream_)
316 return num_bytes_consumed_;
317 return stream_->sequencer()->NumBytesConsumed();
318}
319
Yixin Wang0d2c6b7e12017-08-16 21:12:55320bool QuicChromiumClientStream::Handle::HasBytesToRead() const {
321 if (!stream_)
322 return false;
323 return stream_->sequencer()->HasBytesToRead();
324}
325
rch08e198572017-05-09 16:56:55326bool QuicChromiumClientStream::Handle::IsDoneReading() const {
327 if (!stream_)
328 return is_done_reading_;
329 return stream_->IsDoneReading();
330}
331
332bool QuicChromiumClientStream::Handle::IsFirstStream() const {
333 if (!stream_)
334 return is_first_stream_;
335 return stream_->IsFirstStream();
336}
337
338void QuicChromiumClientStream::Handle::OnPromiseHeaderList(
Ryan Hamilton8d9ee76e2018-05-29 23:52:52339 quic::QuicStreamId promised_id,
rch08e198572017-05-09 16:56:55340 size_t frame_len,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52341 const quic::QuicHeaderList& header_list) {
rch08e198572017-05-09 16:56:55342 stream_->OnPromiseHeaderList(promised_id, frame_len, header_list);
343}
344
Zhongyi Shibb28b1f2018-07-18 02:41:26345bool QuicChromiumClientStream::Handle::can_migrate_to_cellular_network() {
rch08e198572017-05-09 16:56:55346 if (!stream_)
347 return false;
Zhongyi Shibb28b1f2018-07-18 02:41:26348 return stream_->can_migrate_to_cellular_network();
rch08e198572017-05-09 16:56:55349}
350
Yixin Wang0d2c6b7e12017-08-16 21:12:55351const NetLogWithSource& QuicChromiumClientStream::Handle::net_log() const {
352 return net_log_;
353}
354
rch08e198572017-05-09 16:56:55355void QuicChromiumClientStream::Handle::SaveState() {
356 DCHECK(stream_);
357 fin_sent_ = stream_->fin_sent();
358 fin_received_ = stream_->fin_received();
359 num_bytes_consumed_ = stream_->sequencer()->NumBytesConsumed();
360 id_ = stream_->id();
361 connection_error_ = stream_->connection_error();
362 stream_error_ = stream_->stream_error();
363 is_done_reading_ = stream_->IsDoneReading();
364 is_first_stream_ = stream_->IsFirstStream();
365 stream_bytes_read_ = stream_->stream_bytes_read();
366 stream_bytes_written_ = stream_->stream_bytes_written();
rch08e198572017-05-09 16:56:55367}
368
rch1bcfddf22017-06-03 00:26:29369void QuicChromiumClientStream::Handle::SetCallback(
Bence Békyd8a21fc32018-06-27 18:29:58370 CompletionOnceCallback new_callback,
371 CompletionOnceCallback* callback) {
rch1bcfddf22017-06-03 00:26:29372 // TODO(rch): Convert this to a DCHECK once we ensure the API is stable and
373 // bug free.
374 CHECK(!may_invoke_callbacks_);
Bence Békyd8a21fc32018-06-27 18:29:58375 *callback = std::move(new_callback);
rch1bcfddf22017-06-03 00:26:29376}
377
Bence Békyd8a21fc32018-06-27 18:29:58378void QuicChromiumClientStream::Handle::ResetAndRun(
379 CompletionOnceCallback callback,
380 int rv) {
rch1bcfddf22017-06-03 00:26:29381 // TODO(rch): Convert this to a DCHECK once we ensure the API is stable and
382 // bug free.
383 CHECK(may_invoke_callbacks_);
Bence Békyd8a21fc32018-06-27 18:29:58384 std::move(callback).Run(rv);
rch1bcfddf22017-06-03 00:26:29385}
386
387int QuicChromiumClientStream::Handle::HandleIOComplete(int rv) {
388 // If |stream_| is still valid the stream has not been closed. If the stream
389 // has not been closed, then just return |rv|.
390 if (rv < 0 || stream_)
391 return rv;
392
Ryan Hamilton8d9ee76e2018-05-29 23:52:52393 if (stream_error_ == quic::QUIC_STREAM_NO_ERROR &&
394 connection_error_ == quic::QUIC_NO_ERROR && fin_sent_ && fin_received_) {
rch1bcfddf22017-06-03 00:26:29395 return rv;
396 }
397
398 return net_error_;
399}
400
ckrasic244375a32016-02-04 21:21:22401QuicChromiumClientStream::QuicChromiumClientStream(
Ryan Hamilton8d9ee76e2018-05-29 23:52:52402 quic::QuicStreamId id,
403 quic::QuicSpdyClientSessionBase* session,
Fan Yang70c2dd22018-10-10 17:12:15404 quic::StreamType type,
Ramin Halavati683bcaa92018-02-14 08:42:39405 const NetLogWithSource& net_log,
406 const NetworkTrafficAnnotationTag& traffic_annotation)
Fan Yang70c2dd22018-10-10 17:12:15407 : quic::QuicSpdyStream(id, session, type),
rchb27683c2015-07-29 23:53:50408 net_log_(net_log),
rch08e198572017-05-09 16:56:55409 handle_(nullptr),
rchb27683c2015-07-29 23:53:50410 headers_delivered_(false),
rchd4651b92017-05-04 00:41:17411 initial_headers_sent_(false),
ckrasic244375a32016-02-04 21:21:22412 session_(session),
Ryan Hamilton47cf9d12018-10-17 04:33:09413 quic_version_(session->connection()->transport_version()),
Zhongyi Shibb28b1f2018-07-18 02:41:26414 can_migrate_to_cellular_network_(true),
rch6788ad52017-05-09 04:49:04415 initial_headers_frame_len_(0),
rchce246412017-05-30 13:51:50416 trailing_headers_frame_len_(0),
rchb27683c2015-07-29 23:53:50417 weak_factory_(this) {}
[email protected]dd3fd0e2012-11-04 05:14:40418
Fan Yang32c5a112018-12-10 20:06:33419QuicChromiumClientStream::QuicChromiumClientStream(
420 quic::PendingStream pending,
421 quic::QuicSpdyClientSessionBase* session,
422 quic::StreamType type,
423 const NetLogWithSource& net_log,
424 const NetworkTrafficAnnotationTag& traffic_annotation)
425 : quic::QuicSpdyStream(std::move(pending), session, type),
426 net_log_(net_log),
427 handle_(nullptr),
428 headers_delivered_(false),
429 initial_headers_sent_(false),
430 session_(session),
431 quic_version_(session->connection()->transport_version()),
432 can_migrate_to_cellular_network_(true),
433 initial_headers_frame_len_(0),
434 trailing_headers_frame_len_(0),
435 weak_factory_(this) {}
436
rch12fef552016-01-15 16:26:31437QuicChromiumClientStream::~QuicChromiumClientStream() {
rch08e198572017-05-09 16:56:55438 if (handle_)
439 handle_->OnClose();
[email protected]dd3fd0e2012-11-04 05:14:40440}
441
dahollingsaf3796492016-05-25 19:21:35442void QuicChromiumClientStream::OnInitialHeadersComplete(
443 bool fin,
444 size_t frame_len,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52445 const quic::QuicHeaderList& header_list) {
446 quic::QuicSpdyStream::OnInitialHeadersComplete(fin, frame_len, header_list);
dahollingsaf3796492016-05-25 19:21:35447
Ryan Hamilton0239aac2018-05-19 00:03:13448 spdy::SpdyHeaderBlock header_block;
dahollingsaf3796492016-05-25 19:21:35449 int64_t length = -1;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52450 if (!quic::SpdyUtils::CopyAndValidateHeaders(header_list, &length,
451 &header_block)) {
dahollingsaf3796492016-05-25 19:21:35452 DLOG(ERROR) << "Failed to parse header list: " << header_list.DebugString();
453 ConsumeHeaderList();
Ryan Hamilton8d9ee76e2018-05-29 23:52:52454 Reset(quic::QUIC_BAD_APPLICATION_PAYLOAD);
dahollingsaf3796492016-05-25 19:21:35455 return;
456 }
457
458 ConsumeHeaderList();
459 session_->OnInitialHeadersComplete(id(), header_block);
460
rch08e198572017-05-09 16:56:55461 // Buffer the headers and deliver them when the handle arrives.
rch6788ad52017-05-09 04:49:04462 initial_headers_ = std::move(header_block);
463 initial_headers_frame_len_ = frame_len;
rchfb47f712017-05-21 03:24:00464
465 if (handle_) {
466 // The handle will be notified of the headers via a posted task.
467 NotifyHandleOfInitialHeadersAvailableLater();
468 }
dahollingsaf3796492016-05-25 19:21:35469}
470
471void QuicChromiumClientStream::OnTrailingHeadersComplete(
472 bool fin,
473 size_t frame_len,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52474 const quic::QuicHeaderList& header_list) {
475 quic::QuicSpdyStream::OnTrailingHeadersComplete(fin, frame_len, header_list);
rchce246412017-05-30 13:51:50476 trailing_headers_frame_len_ = frame_len;
477 if (handle_) {
478 // The handle will be notified of the headers via a posted task.
479 NotifyHandleOfTrailingHeadersAvailableLater();
480 }
dahollingsaf3796492016-05-25 19:21:35481}
482
ckrasic769733c2016-06-30 00:42:13483void QuicChromiumClientStream::OnPromiseHeaderList(
Ryan Hamilton8d9ee76e2018-05-29 23:52:52484 quic::QuicStreamId promised_id,
ckrasic769733c2016-06-30 00:42:13485 size_t frame_len,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52486 const quic::QuicHeaderList& header_list) {
Ryan Hamilton0239aac2018-05-19 00:03:13487 spdy::SpdyHeaderBlock promise_headers;
ckrasic769733c2016-06-30 00:42:13488 int64_t content_length = -1;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52489 if (!quic::SpdyUtils::CopyAndValidateHeaders(header_list, &content_length,
490 &promise_headers)) {
ckrasic769733c2016-06-30 00:42:13491 DLOG(ERROR) << "Failed to parse header list: " << header_list.DebugString();
492 ConsumeHeaderList();
Ryan Hamilton8d9ee76e2018-05-29 23:52:52493 Reset(quic::QUIC_BAD_APPLICATION_PAYLOAD);
ckrasic769733c2016-06-30 00:42:13494 return;
495 }
496 ConsumeHeaderList();
497
498 session_->HandlePromised(id(), promised_id, promise_headers);
499}
500
Frank Kastenholz1dac18b62018-11-29 18:50:36501void QuicChromiumClientStream::OnBodyAvailable() {
rchb27683c2015-07-29 23:53:50502 if (!FinishedReadingHeaders() || !headers_delivered_) {
rch7dd15702015-07-01 18:57:57503 // Buffer the data in the sequencer until the headers have been read.
rchb27683c2015-07-29 23:53:50504 return;
rch7dd15702015-07-01 18:57:57505 }
506
xunjieli7640faa2016-10-06 00:45:42507 if (!sequencer()->HasBytesToRead() && !FinishedReadingTrailers()) {
508 // If there is no data to read, wait until either FIN is received or
509 // trailers are delivered.
510 return;
511 }
512
rch08e198572017-05-09 16:56:55513 // The handle will read the data via a posted task, and
rchb27683c2015-07-29 23:53:50514 // will be able to, potentially, read all data which has queued up.
rch08e198572017-05-09 16:56:55515 if (handle_)
516 NotifyHandleOfDataAvailableLater();
[email protected]dd3fd0e2012-11-04 05:14:40517}
518
rch12fef552016-01-15 16:26:31519void QuicChromiumClientStream::OnClose() {
rch08e198572017-05-09 16:56:55520 if (handle_) {
521 handle_->OnClose();
522 handle_ = nullptr;
[email protected]f702d572012-12-04 15:56:20523 }
Ryan Hamilton8d9ee76e2018-05-29 23:52:52524 quic::QuicStream::OnClose();
[email protected]dd3fd0e2012-11-04 05:14:40525}
526
rch12fef552016-01-15 16:26:31527void QuicChromiumClientStream::OnCanWrite() {
Ryan Hamilton8d9ee76e2018-05-29 23:52:52528 quic::QuicStream::OnCanWrite();
[email protected]6adeb922013-09-01 22:43:25529
rch2ab4d872017-05-28 15:15:40530 if (!HasBufferedData() && handle_)
531 handle_->OnCanWrite();
[email protected]6adeb922013-09-01 22:43:25532}
533
xunjieli5fafe142016-03-23 23:32:54534size_t QuicChromiumClientStream::WriteHeaders(
Ryan Hamilton0239aac2018-05-19 00:03:13535 spdy::SpdyHeaderBlock header_block,
xunjieli5fafe142016-03-23 23:32:54536 bool fin,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52537 quic::QuicReferenceCountedPointer<quic::QuicAckListenerInterface>
538 ack_listener) {
rchcb1d6bde2016-06-18 00:33:07539 if (!session()->IsCryptoHandshakeConfirmed()) {
540 auto entry = header_block.find(":method");
541 DCHECK(entry != header_block.end());
542 DCHECK_NE("POST", entry->second);
543 }
xunjieli5fafe142016-03-23 23:32:54544 net_log_.AddEvent(
mikecirone8b85c432016-09-08 19:11:00545 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
Ryan Hamiltond4ecca12018-02-20 21:36:22546 base::Bind(&QuicRequestNetLogCallback, id(), &header_block, priority()));
Ryan Hamilton8d9ee76e2018-05-29 23:52:52547 size_t len = quic::QuicSpdyStream::WriteHeaders(std::move(header_block), fin,
548 std::move(ack_listener));
rchd4651b92017-05-04 00:41:17549 initial_headers_sent_ = true;
550 return len;
xunjieli5fafe142016-03-23 23:32:54551}
552
Ryan Hamilton8d9ee76e2018-05-29 23:52:52553bool QuicChromiumClientStream::WriteStreamData(quic::QuicStringPiece data,
554 bool fin) {
rch2ab4d872017-05-28 15:15:40555 // Must not be called when data is buffered.
[email protected]6adeb922013-09-01 22:43:25556 DCHECK(!HasBufferedData());
557 // Writes the data, or buffers it.
rtennetibe635732014-10-02 22:51:42558 WriteOrBufferData(data, fin, nullptr);
rch2ab4d872017-05-28 15:15:40559 return !HasBufferedData(); // Was all data written?
[email protected]6adeb922013-09-01 22:43:25560}
561
rch2ab4d872017-05-28 15:15:40562bool QuicChromiumClientStream::WritevStreamData(
xunjieli2328a2682016-05-16 19:38:25563 const std::vector<scoped_refptr<IOBuffer>>& buffers,
xunjieli07a42ce2016-04-26 20:05:31564 const std::vector<int>& lengths,
rch2ab4d872017-05-28 15:15:40565 bool fin) {
xunjieli07a42ce2016-04-26 20:05:31566 // Must not be called when data is buffered.
567 DCHECK(!HasBufferedData());
568 // Writes the data, or buffers it.
Ryan Hamiltona3ee93a72018-08-01 22:03:08569 for (size_t i = 0; i < buffers.size(); ++i) {
570 bool is_fin = fin && (i == buffers.size() - 1);
571 quic::QuicStringPiece string_data(buffers[i]->data(), lengths[i]);
572 WriteOrBufferData(string_data, is_fin, nullptr);
573 }
rch2ab4d872017-05-28 15:15:40574 return !HasBufferedData(); // Was all data written?
xunjieli07a42ce2016-04-26 20:05:31575}
576
rch08e198572017-05-09 16:56:55577std::unique_ptr<QuicChromiumClientStream::Handle>
rch1bcfddf22017-06-03 00:26:29578QuicChromiumClientStream::CreateHandle() {
rch08e198572017-05-09 16:56:55579 DCHECK(!handle_);
Ryan Hamiltona3ee93a72018-08-01 22:03:08580 auto handle = base::WrapUnique(new QuicChromiumClientStream::Handle(this));
rch08e198572017-05-09 16:56:55581 handle_ = handle.get();
rch6788ad52017-05-09 04:49:04582
583 // Should this perhaps be via PostTask to make reasoning simpler?
rchfb47f712017-05-21 03:24:00584 if (!initial_headers_.empty())
585 handle_->OnInitialHeadersAvailable();
rch08e198572017-05-09 16:56:55586
587 return handle;
588}
589
590void QuicChromiumClientStream::ClearHandle() {
591 handle_ = nullptr;
[email protected]dd3fd0e2012-11-04 05:14:40592}
593
rch12fef552016-01-15 16:26:31594void QuicChromiumClientStream::OnError(int error) {
rch08e198572017-05-09 16:56:55595 if (handle_) {
596 QuicChromiumClientStream::Handle* handle = handle_;
597 handle_ = nullptr;
598 handle->OnError(error);
[email protected]56dfb902013-01-03 23:17:55599 }
600}
601
rch12fef552016-01-15 16:26:31602int QuicChromiumClientStream::Read(IOBuffer* buf, int buf_len) {
xunjieliec0ed02a2016-10-10 18:05:06603 if (IsDoneReading())
rchb27683c2015-07-29 23:53:50604 return 0; // EOF
605
606 if (!HasBytesToRead())
607 return ERR_IO_PENDING;
608
609 iovec iov;
610 iov.iov_base = buf->data();
611 iov.iov_len = buf_len;
xunjieliec0ed02a2016-10-10 18:05:06612 size_t bytes_read = Readv(&iov, 1);
rch03499252017-05-03 17:44:37613 // Since HasBytesToRead is true, Readv() must of read some data.
614 DCHECK_NE(0u, bytes_read);
xunjieliec0ed02a2016-10-10 18:05:06615 return bytes_read;
rchb27683c2015-07-29 23:53:50616}
617
rchfb47f712017-05-21 03:24:00618void QuicChromiumClientStream::NotifyHandleOfInitialHeadersAvailableLater() {
rch08e198572017-05-09 16:56:55619 DCHECK(handle_);
rch6788ad52017-05-09 04:49:04620 base::ThreadTaskRunnerHandle::Get()->PostTask(
621 FROM_HERE,
rchec5b74ac2017-05-09 13:31:40622 base::Bind(
rch08e198572017-05-09 16:56:55623 &QuicChromiumClientStream::NotifyHandleOfInitialHeadersAvailable,
rchfb47f712017-05-21 03:24:00624 weak_factory_.GetWeakPtr()));
rchb27683c2015-07-29 23:53:50625}
626
rchfb47f712017-05-21 03:24:00627void QuicChromiumClientStream::NotifyHandleOfInitialHeadersAvailable() {
rch08e198572017-05-09 16:56:55628 if (!handle_)
rchb27683c2015-07-29 23:53:50629 return;
630
rchfb47f712017-05-21 03:24:00631 if (!headers_delivered_)
632 handle_->OnInitialHeadersAvailable();
rchec5b74ac2017-05-09 13:31:40633}
634
rchce246412017-05-30 13:51:50635void QuicChromiumClientStream::NotifyHandleOfTrailingHeadersAvailableLater() {
rch08e198572017-05-09 16:56:55636 DCHECK(handle_);
rchec5b74ac2017-05-09 13:31:40637 base::ThreadTaskRunnerHandle::Get()->PostTask(
638 FROM_HERE,
639 base::Bind(
rch08e198572017-05-09 16:56:55640 &QuicChromiumClientStream::NotifyHandleOfTrailingHeadersAvailable,
rchce246412017-05-30 13:51:50641 weak_factory_.GetWeakPtr()));
rchec5b74ac2017-05-09 13:31:40642}
643
rchce246412017-05-30 13:51:50644void QuicChromiumClientStream::NotifyHandleOfTrailingHeadersAvailable() {
rch08e198572017-05-09 16:56:55645 if (!handle_)
rchec5b74ac2017-05-09 13:31:40646 return;
647
648 DCHECK(headers_delivered_);
rch1bcfddf22017-06-03 00:26:29649 // Post an async task to notify handle of the FIN flag.
rch08e198572017-05-09 16:56:55650 NotifyHandleOfDataAvailableLater();
rchce246412017-05-30 13:51:50651 handle_->OnTrailingHeadersAvailable();
rchb27683c2015-07-29 23:53:50652}
653
Ryan Hamilton0239aac2018-05-19 00:03:13654bool QuicChromiumClientStream::DeliverInitialHeaders(
655 spdy::SpdyHeaderBlock* headers,
656 int* frame_len) {
rchfb47f712017-05-21 03:24:00657 if (initial_headers_.empty())
658 return false;
659
660 headers_delivered_ = true;
661 net_log_.AddEvent(
662 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_READ_RESPONSE_HEADERS,
663 base::Bind(&SpdyHeaderBlockNetLogCallback, &initial_headers_));
664
665 *headers = std::move(initial_headers_);
666 *frame_len = initial_headers_frame_len_;
667 return true;
668}
669
Ryan Hamilton0239aac2018-05-19 00:03:13670bool QuicChromiumClientStream::DeliverTrailingHeaders(
671 spdy::SpdyHeaderBlock* headers,
672 int* frame_len) {
rchce246412017-05-30 13:51:50673 if (received_trailers().empty())
674 return false;
675
676 net_log_.AddEvent(
677 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_READ_RESPONSE_TRAILERS,
678 base::Bind(&SpdyHeaderBlockNetLogCallback, &received_trailers()));
679
680 *headers = received_trailers().Clone();
681 *frame_len = trailing_headers_frame_len_;
682
683 MarkTrailersConsumed();
684 return true;
685}
686
rch08e198572017-05-09 16:56:55687void QuicChromiumClientStream::NotifyHandleOfDataAvailableLater() {
688 DCHECK(handle_);
rch6788ad52017-05-09 04:49:04689 base::ThreadTaskRunnerHandle::Get()->PostTask(
690 FROM_HERE,
rch08e198572017-05-09 16:56:55691 base::Bind(&QuicChromiumClientStream::NotifyHandleOfDataAvailable,
rchb27683c2015-07-29 23:53:50692 weak_factory_.GetWeakPtr()));
693}
694
rch08e198572017-05-09 16:56:55695void QuicChromiumClientStream::NotifyHandleOfDataAvailable() {
696 if (handle_)
697 handle_->OnDataAvailable();
rchb27683c2015-07-29 23:53:50698}
699
Zhongyi Shibb28b1f2018-07-18 02:41:26700void QuicChromiumClientStream::DisableConnectionMigrationToCellularNetwork() {
701 can_migrate_to_cellular_network_ = false;
jri231c2972016-03-08 19:50:11702}
703
xunjieli100937eb52016-09-15 20:09:37704bool QuicChromiumClientStream::IsFirstStream() {
Fan Yang32c5a112018-12-10 20:06:33705 return id() == quic::QuicUtils::GetHeadersStreamId(quic_version_) +
706 quic::QuicUtils::StreamIdDelta(quic_version_);
xunjieli100937eb52016-09-15 20:09:37707}
708
[email protected]dd3fd0e2012-11-04 05:14:40709} // namespace net