blob: 029cd4d87a041444f3502b720fcb7ea326fb9564 [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
rch675757b2016-07-29 16:40:115#include "net/quic/chromium/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"
rch675757b2016-07-29 16:40:1116#include "net/quic/chromium/quic_chromium_client_session.h"
rch223465c2016-12-08 21:17:2917#include "net/quic/chromium/quic_http_utils.h"
rchd4db7c152016-07-29 21:58:1218#include "net/quic/core/quic_spdy_session.h"
19#include "net/quic/core/quic_write_blocked_list.h"
20#include "net/quic/core/spdy_utils.h"
[email protected]dd3fd0e2012-11-04 05:14:4021
22namespace net {
rch1bcfddf22017-06-03 00:26:2923namespace {
24// Sets a boolean to a value, and restores it to the previous value once
25// the saver goes out of scope.
26class ScopedBoolSaver {
27 public:
28 ScopedBoolSaver(bool* var, bool new_val) : var_(var), old_val_(*var) {
29 *var_ = new_val;
30 }
[email protected]dd3fd0e2012-11-04 05:14:4031
rch1bcfddf22017-06-03 00:26:2932 ~ScopedBoolSaver() { *var_ = old_val_; }
33
34 private:
35 bool* var_;
36 bool old_val_;
37};
38} // namespace
39
40QuicChromiumClientStream::Handle::Handle(QuicChromiumClientStream* stream)
rch27da0452017-05-26 22:54:5441 : stream_(stream),
rch1bcfddf22017-06-03 00:26:2942 may_invoke_callbacks_(true),
rch27da0452017-05-26 22:54:5443 read_headers_buffer_(nullptr),
rch1bcfddf22017-06-03 00:26:2944 read_body_buffer_len_(0),
45 net_error_(ERR_UNEXPECTED),
46 weak_factory_(this) {
rch08e198572017-05-09 16:56:5547 SaveState();
48}
49
50QuicChromiumClientStream::Handle::~Handle() {
51 if (stream_) {
52 stream_->ClearHandle();
53 // TODO(rch): If stream_ is still valid, it should probably be Reset()
54 // so that it does not leak.
55 // stream_->Reset(QUIC_STREAM_CANCELLED);
56 }
57}
58
rchfb47f712017-05-21 03:24:0059void QuicChromiumClientStream::Handle::OnInitialHeadersAvailable() {
60 if (!read_headers_callback_)
61 return; // Wait for ReadInitialHeaders to be called.
62
63 int rv = ERR_QUIC_PROTOCOL_ERROR;
64 if (!stream_->DeliverInitialHeaders(read_headers_buffer_, &rv))
65 rv = ERR_QUIC_PROTOCOL_ERROR;
66
rch1bcfddf22017-06-03 00:26:2967 ResetAndRun(&read_headers_callback_, rv);
rch08e198572017-05-09 16:56:5568}
69
rchce246412017-05-30 13:51:5070void QuicChromiumClientStream::Handle::OnTrailingHeadersAvailable() {
71 if (!read_headers_callback_)
72 return; // Wait for ReadInitialHeaders to be called.
73
74 int rv = ERR_QUIC_PROTOCOL_ERROR;
75 if (!stream_->DeliverTrailingHeaders(read_headers_buffer_, &rv))
76 rv = ERR_QUIC_PROTOCOL_ERROR;
77
rch1bcfddf22017-06-03 00:26:2978 ResetAndRun(&read_headers_callback_, rv);
rch08e198572017-05-09 16:56:5579}
80
81void QuicChromiumClientStream::Handle::OnDataAvailable() {
rch27da0452017-05-26 22:54:5482 if (!read_body_callback_)
83 return; // Wait for ReadBody to be called.
84
85 int rv = stream_->Read(read_body_buffer_, read_body_buffer_len_);
86 if (rv == ERR_IO_PENDING)
87 return; // Spurrious, likely because of trailers?
88
89 read_body_buffer_ = nullptr;
90 read_body_buffer_len_ = 0;
rch1bcfddf22017-06-03 00:26:2991 ResetAndRun(&read_body_callback_, rv);
rch08e198572017-05-09 16:56:5592}
93
rch2ab4d872017-05-28 15:15:4094void QuicChromiumClientStream::Handle::OnCanWrite() {
95 if (!write_callback_)
96 return;
97
rch1bcfddf22017-06-03 00:26:2998 ResetAndRun(&write_callback_, OK);
rch2ab4d872017-05-28 15:15:4099}
100
rch08e198572017-05-09 16:56:55101void QuicChromiumClientStream::Handle::OnClose() {
rch1bcfddf22017-06-03 00:26:29102 if (net_error_ == ERR_UNEXPECTED) {
103 if (stream_error() == QUIC_STREAM_NO_ERROR &&
104 connection_error() == QUIC_NO_ERROR && fin_sent() && fin_received()) {
105 net_error_ = ERR_CONNECTION_CLOSED;
106 } else {
107 net_error_ = ERR_QUIC_PROTOCOL_ERROR;
108 }
rch08e198572017-05-09 16:56:55109 }
rch1bcfddf22017-06-03 00:26:29110 OnError(net_error_);
rch08e198572017-05-09 16:56:55111}
112
113void QuicChromiumClientStream::Handle::OnError(int error) {
rch1bcfddf22017-06-03 00:26:29114 net_error_ = error;
rch08e198572017-05-09 16:56:55115 if (stream_)
116 SaveState();
117 stream_ = nullptr;
rch1bcfddf22017-06-03 00:26:29118
119 // Post a task to invoke the callbacks to ensure that there is no reentrancy.
120 // A ScopedPacketBundler might cause an error which closes the stream under
121 // the call stack of the owner of the handle.
122 base::ThreadTaskRunnerHandle::Get()->PostTask(
123 FROM_HERE,
124 base::Bind(&QuicChromiumClientStream::Handle::InvokeCallbacksOnClose,
125 weak_factory_.GetWeakPtr(), error));
126}
127
128void QuicChromiumClientStream::Handle::InvokeCallbacksOnClose(int error) {
129 // Invoking a callback may cause |this| to be deleted. If this happens, no
130 // more callbacks should be invoked. Guard against this by holding a WeakPtr
131 // to |this| and ensuring it's still valid.
132 auto guard(weak_factory_.GetWeakPtr());
133 for (auto* callback :
134 {&read_headers_callback_, &read_body_callback_, &write_callback_}) {
135 if (*callback)
136 ResetAndRun(callback, error);
137 if (!guard.get())
138 return;
rch08e198572017-05-09 16:56:55139 }
140}
141
rchfb47f712017-05-21 03:24:00142int QuicChromiumClientStream::Handle::ReadInitialHeaders(
143 SpdyHeaderBlock* header_block,
144 const CompletionCallback& callback) {
rch1bcfddf22017-06-03 00:26:29145 ScopedBoolSaver saver(&may_invoke_callbacks_, false);
rchfb47f712017-05-21 03:24:00146 if (!stream_)
rch1bcfddf22017-06-03 00:26:29147 return net_error_;
rchfb47f712017-05-21 03:24:00148
149 int frame_len = 0;
150 if (stream_->DeliverInitialHeaders(header_block, &frame_len))
151 return frame_len;
152
153 read_headers_buffer_ = header_block;
rch1bcfddf22017-06-03 00:26:29154 SetCallback(callback, &read_headers_callback_);
rchfb47f712017-05-21 03:24:00155 return ERR_IO_PENDING;
156}
157
rch27da0452017-05-26 22:54:54158int QuicChromiumClientStream::Handle::ReadBody(
159 IOBuffer* buffer,
160 int buffer_len,
161 const CompletionCallback& callback) {
rch1bcfddf22017-06-03 00:26:29162 ScopedBoolSaver saver(&may_invoke_callbacks_, false);
163 if (IsDoneReading())
164 return OK;
165
rch27da0452017-05-26 22:54:54166 if (!stream_)
rch1bcfddf22017-06-03 00:26:29167 return net_error_;
rch27da0452017-05-26 22:54:54168
169 int rv = stream_->Read(buffer, buffer_len);
170 if (rv != ERR_IO_PENDING)
171 return rv;
172
rch1bcfddf22017-06-03 00:26:29173 SetCallback(callback, &read_body_callback_);
rch27da0452017-05-26 22:54:54174 read_body_buffer_ = buffer;
175 read_body_buffer_len_ = buffer_len;
176 return ERR_IO_PENDING;
177}
178
rchce246412017-05-30 13:51:50179int QuicChromiumClientStream::Handle::ReadTrailingHeaders(
180 SpdyHeaderBlock* header_block,
181 const CompletionCallback& callback) {
rch1bcfddf22017-06-03 00:26:29182 ScopedBoolSaver saver(&may_invoke_callbacks_, false);
rchce246412017-05-30 13:51:50183 if (!stream_)
rch1bcfddf22017-06-03 00:26:29184 return net_error_;
rchce246412017-05-30 13:51:50185
186 int frame_len = 0;
187 if (stream_->DeliverTrailingHeaders(header_block, &frame_len))
188 return frame_len;
189
190 read_headers_buffer_ = header_block;
rch1bcfddf22017-06-03 00:26:29191 SetCallback(callback, &read_headers_callback_);
rchce246412017-05-30 13:51:50192 return ERR_IO_PENDING;
193}
194
rch1bcfddf22017-06-03 00:26:29195int QuicChromiumClientStream::Handle::WriteHeaders(
rch08e198572017-05-09 16:56:55196 SpdyHeaderBlock header_block,
197 bool fin,
198 QuicReferenceCountedPointer<QuicAckListenerInterface>
199 ack_notifier_delegate) {
200 if (!stream_)
201 return 0;
rch1bcfddf22017-06-03 00:26:29202 return HandleIOComplete(stream_->WriteHeaders(std::move(header_block), fin,
203 ack_notifier_delegate));
rch08e198572017-05-09 16:56:55204}
205
206int QuicChromiumClientStream::Handle::WriteStreamData(
207 base::StringPiece data,
208 bool fin,
209 const CompletionCallback& callback) {
rch1bcfddf22017-06-03 00:26:29210 ScopedBoolSaver saver(&may_invoke_callbacks_, false);
rch08e198572017-05-09 16:56:55211 if (!stream_)
rch1bcfddf22017-06-03 00:26:29212 return net_error_;
rch2ab4d872017-05-28 15:15:40213
214 if (stream_->WriteStreamData(data, fin))
rch1bcfddf22017-06-03 00:26:29215 return HandleIOComplete(OK);
rch2ab4d872017-05-28 15:15:40216
rch1bcfddf22017-06-03 00:26:29217 SetCallback(callback, &write_callback_);
rch2ab4d872017-05-28 15:15:40218 return ERR_IO_PENDING;
rch08e198572017-05-09 16:56:55219}
220
221int QuicChromiumClientStream::Handle::WritevStreamData(
222 const std::vector<scoped_refptr<IOBuffer>>& buffers,
223 const std::vector<int>& lengths,
224 bool fin,
225 const CompletionCallback& callback) {
rch1bcfddf22017-06-03 00:26:29226 ScopedBoolSaver saver(&may_invoke_callbacks_, false);
rch08e198572017-05-09 16:56:55227 if (!stream_)
rch1bcfddf22017-06-03 00:26:29228 return net_error_;
rch2ab4d872017-05-28 15:15:40229
230 if (stream_->WritevStreamData(buffers, lengths, fin))
rch1bcfddf22017-06-03 00:26:29231 return HandleIOComplete(OK);
rch2ab4d872017-05-28 15:15:40232
rch1bcfddf22017-06-03 00:26:29233 SetCallback(callback, &write_callback_);
rch2ab4d872017-05-28 15:15:40234 return ERR_IO_PENDING;
rch08e198572017-05-09 16:56:55235}
236
237int QuicChromiumClientStream::Handle::Read(IOBuffer* buf, int buf_len) {
238 if (!stream_)
rch1bcfddf22017-06-03 00:26:29239 return net_error_;
rch08e198572017-05-09 16:56:55240 return stream_->Read(buf, buf_len);
241}
242
243void QuicChromiumClientStream::Handle::OnFinRead() {
rch1bcfddf22017-06-03 00:26:29244 read_headers_callback_.Reset();
rch08e198572017-05-09 16:56:55245 if (stream_)
246 stream_->OnFinRead();
247}
248
249void QuicChromiumClientStream::Handle::DisableConnectionMigration() {
250 if (stream_)
251 stream_->DisableConnectionMigration();
252}
253
254void QuicChromiumClientStream::Handle::SetPriority(SpdyPriority priority) {
255 if (stream_)
256 stream_->SetPriority(priority);
257}
258
259void QuicChromiumClientStream::Handle::Reset(
260 QuicRstStreamErrorCode error_code) {
261 if (stream_)
262 stream_->Reset(error_code);
263}
264
265QuicStreamId QuicChromiumClientStream::Handle::id() const {
266 if (!stream_)
267 return id_;
268 return stream_->id();
269}
270
271QuicErrorCode QuicChromiumClientStream::Handle::connection_error() const {
272 if (!stream_)
273 return connection_error_;
274 return stream_->connection_error();
275}
276
277QuicRstStreamErrorCode QuicChromiumClientStream::Handle::stream_error() const {
278 if (!stream_)
279 return stream_error_;
280 return stream_->stream_error();
281}
282
283bool QuicChromiumClientStream::Handle::fin_sent() const {
284 if (!stream_)
285 return fin_sent_;
286 return stream_->fin_sent();
287}
288
289bool QuicChromiumClientStream::Handle::fin_received() const {
290 if (!stream_)
291 return fin_received_;
292 return stream_->fin_received();
293}
294
295uint64_t QuicChromiumClientStream::Handle::stream_bytes_read() const {
296 if (!stream_)
297 return stream_bytes_read_;
298 return stream_->stream_bytes_read();
299}
300
301uint64_t QuicChromiumClientStream::Handle::stream_bytes_written() const {
302 if (!stream_)
303 return stream_bytes_written_;
304 return stream_->stream_bytes_written();
305}
306
307size_t QuicChromiumClientStream::Handle::NumBytesConsumed() const {
308 if (!stream_)
309 return num_bytes_consumed_;
310 return stream_->sequencer()->NumBytesConsumed();
311}
312
313bool QuicChromiumClientStream::Handle::IsDoneReading() const {
314 if (!stream_)
315 return is_done_reading_;
316 return stream_->IsDoneReading();
317}
318
319bool QuicChromiumClientStream::Handle::IsFirstStream() const {
320 if (!stream_)
321 return is_first_stream_;
322 return stream_->IsFirstStream();
323}
324
325void QuicChromiumClientStream::Handle::OnPromiseHeaderList(
326 QuicStreamId promised_id,
327 size_t frame_len,
328 const QuicHeaderList& header_list) {
329 stream_->OnPromiseHeaderList(promised_id, frame_len, header_list);
330}
331
332SpdyPriority QuicChromiumClientStream::Handle::priority() const {
333 if (!stream_)
334 return priority_;
335 return stream_->priority();
336}
337
338bool QuicChromiumClientStream::Handle::can_migrate() {
339 if (!stream_)
340 return false;
341 return stream_->can_migrate();
342}
343
rch08e198572017-05-09 16:56:55344void QuicChromiumClientStream::Handle::SaveState() {
345 DCHECK(stream_);
346 fin_sent_ = stream_->fin_sent();
347 fin_received_ = stream_->fin_received();
348 num_bytes_consumed_ = stream_->sequencer()->NumBytesConsumed();
349 id_ = stream_->id();
350 connection_error_ = stream_->connection_error();
351 stream_error_ = stream_->stream_error();
352 is_done_reading_ = stream_->IsDoneReading();
353 is_first_stream_ = stream_->IsFirstStream();
354 stream_bytes_read_ = stream_->stream_bytes_read();
355 stream_bytes_written_ = stream_->stream_bytes_written();
356 priority_ = stream_->priority();
357}
358
rch1bcfddf22017-06-03 00:26:29359void QuicChromiumClientStream::Handle::SetCallback(
360 const CompletionCallback& new_callback,
361 CompletionCallback* callback) {
362 // TODO(rch): Convert this to a DCHECK once we ensure the API is stable and
363 // bug free.
364 CHECK(!may_invoke_callbacks_);
365 *callback = new_callback;
366}
367
368void QuicChromiumClientStream::Handle::ResetAndRun(CompletionCallback* callback,
369 int rv) {
370 // TODO(rch): Convert this to a DCHECK once we ensure the API is stable and
371 // bug free.
372 CHECK(may_invoke_callbacks_);
373 ResetAndReturn(callback).Run(rv);
374}
375
376int QuicChromiumClientStream::Handle::HandleIOComplete(int rv) {
377 // If |stream_| is still valid the stream has not been closed. If the stream
378 // has not been closed, then just return |rv|.
379 if (rv < 0 || stream_)
380 return rv;
381
382 if (stream_error_ == QUIC_STREAM_NO_ERROR &&
383 connection_error_ == QUIC_NO_ERROR && fin_sent_ && fin_received_) {
384 return rv;
385 }
386
387 return net_error_;
388}
389
ckrasic244375a32016-02-04 21:21:22390QuicChromiumClientStream::QuicChromiumClientStream(
391 QuicStreamId id,
392 QuicClientSessionBase* session,
tfarina42834112016-09-22 13:38:20393 const NetLogWithSource& net_log)
alyssarc39b80f2015-10-22 17:13:58394 : QuicSpdyStream(id, session),
rchb27683c2015-07-29 23:53:50395 net_log_(net_log),
rch08e198572017-05-09 16:56:55396 handle_(nullptr),
rchb27683c2015-07-29 23:53:50397 headers_delivered_(false),
rchd4651b92017-05-04 00:41:17398 initial_headers_sent_(false),
ckrasic244375a32016-02-04 21:21:22399 session_(session),
jri231c2972016-03-08 19:50:11400 can_migrate_(true),
rch6788ad52017-05-09 04:49:04401 initial_headers_frame_len_(0),
rchce246412017-05-30 13:51:50402 trailing_headers_frame_len_(0),
rchb27683c2015-07-29 23:53:50403 weak_factory_(this) {}
[email protected]dd3fd0e2012-11-04 05:14:40404
rch12fef552016-01-15 16:26:31405QuicChromiumClientStream::~QuicChromiumClientStream() {
rch08e198572017-05-09 16:56:55406 if (handle_)
407 handle_->OnClose();
[email protected]dd3fd0e2012-11-04 05:14:40408}
409
dahollingsaf3796492016-05-25 19:21:35410void QuicChromiumClientStream::OnInitialHeadersComplete(
411 bool fin,
412 size_t frame_len,
413 const QuicHeaderList& header_list) {
414 QuicSpdyStream::OnInitialHeadersComplete(fin, frame_len, header_list);
415
416 SpdyHeaderBlock header_block;
417 int64_t length = -1;
418 if (!SpdyUtils::CopyAndValidateHeaders(header_list, &length, &header_block)) {
419 DLOG(ERROR) << "Failed to parse header list: " << header_list.DebugString();
420 ConsumeHeaderList();
421 Reset(QUIC_BAD_APPLICATION_PAYLOAD);
422 return;
423 }
424
425 ConsumeHeaderList();
426 session_->OnInitialHeadersComplete(id(), header_block);
427
rch08e198572017-05-09 16:56:55428 // Buffer the headers and deliver them when the handle arrives.
rch6788ad52017-05-09 04:49:04429 initial_headers_ = std::move(header_block);
430 initial_headers_frame_len_ = frame_len;
rchfb47f712017-05-21 03:24:00431
432 if (handle_) {
433 // The handle will be notified of the headers via a posted task.
434 NotifyHandleOfInitialHeadersAvailableLater();
435 }
dahollingsaf3796492016-05-25 19:21:35436}
437
438void QuicChromiumClientStream::OnTrailingHeadersComplete(
439 bool fin,
440 size_t frame_len,
441 const QuicHeaderList& header_list) {
442 QuicSpdyStream::OnTrailingHeadersComplete(fin, frame_len, header_list);
rchce246412017-05-30 13:51:50443 trailing_headers_frame_len_ = frame_len;
444 if (handle_) {
445 // The handle will be notified of the headers via a posted task.
446 NotifyHandleOfTrailingHeadersAvailableLater();
447 }
dahollingsaf3796492016-05-25 19:21:35448}
449
ckrasic769733c2016-06-30 00:42:13450void QuicChromiumClientStream::OnPromiseHeaderList(
451 QuicStreamId promised_id,
452 size_t frame_len,
453 const QuicHeaderList& header_list) {
454 SpdyHeaderBlock promise_headers;
455 int64_t content_length = -1;
456 if (!SpdyUtils::CopyAndValidateHeaders(header_list, &content_length,
457 &promise_headers)) {
458 DLOG(ERROR) << "Failed to parse header list: " << header_list.DebugString();
459 ConsumeHeaderList();
460 Reset(QUIC_BAD_APPLICATION_PAYLOAD);
461 return;
462 }
463 ConsumeHeaderList();
464
465 session_->HandlePromised(id(), promised_id, promise_headers);
466}
467
rch12fef552016-01-15 16:26:31468void QuicChromiumClientStream::OnDataAvailable() {
rchb27683c2015-07-29 23:53:50469 if (!FinishedReadingHeaders() || !headers_delivered_) {
rch7dd15702015-07-01 18:57:57470 // Buffer the data in the sequencer until the headers have been read.
rchb27683c2015-07-29 23:53:50471 return;
rch7dd15702015-07-01 18:57:57472 }
473
xunjieli7640faa2016-10-06 00:45:42474 if (!sequencer()->HasBytesToRead() && !FinishedReadingTrailers()) {
475 // If there is no data to read, wait until either FIN is received or
476 // trailers are delivered.
477 return;
478 }
479
rch08e198572017-05-09 16:56:55480 // The handle will read the data via a posted task, and
rchb27683c2015-07-29 23:53:50481 // will be able to, potentially, read all data which has queued up.
rch08e198572017-05-09 16:56:55482 if (handle_)
483 NotifyHandleOfDataAvailableLater();
[email protected]dd3fd0e2012-11-04 05:14:40484}
485
rch12fef552016-01-15 16:26:31486void QuicChromiumClientStream::OnClose() {
rch08e198572017-05-09 16:56:55487 if (handle_) {
488 handle_->OnClose();
489 handle_ = nullptr;
[email protected]f702d572012-12-04 15:56:20490 }
fayangf66f9f12016-11-08 15:25:41491 QuicStream::OnClose();
[email protected]dd3fd0e2012-11-04 05:14:40492}
493
rch12fef552016-01-15 16:26:31494void QuicChromiumClientStream::OnCanWrite() {
fayangf66f9f12016-11-08 15:25:41495 QuicStream::OnCanWrite();
[email protected]6adeb922013-09-01 22:43:25496
rch2ab4d872017-05-28 15:15:40497 if (!HasBufferedData() && handle_)
498 handle_->OnCanWrite();
[email protected]6adeb922013-09-01 22:43:25499}
500
xunjieli5fafe142016-03-23 23:32:54501size_t QuicChromiumClientStream::WriteHeaders(
bnc2dc1cc42016-06-23 23:08:34502 SpdyHeaderBlock header_block,
xunjieli5fafe142016-03-23 23:32:54503 bool fin,
fayangc26bcdb2016-12-21 15:33:12504 QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
rchcb1d6bde2016-06-18 00:33:07505 if (!session()->IsCryptoHandshakeConfirmed()) {
506 auto entry = header_block.find(":method");
507 DCHECK(entry != header_block.end());
508 DCHECK_NE("POST", entry->second);
509 }
xunjieli5fafe142016-03-23 23:32:54510 net_log_.AddEvent(
mikecirone8b85c432016-09-08 19:11:00511 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
xunjieli5fafe142016-03-23 23:32:54512 base::Bind(&QuicRequestNetLogCallback, id(), &header_block,
513 QuicSpdyStream::priority()));
rchd4651b92017-05-04 00:41:17514 size_t len = QuicSpdyStream::WriteHeaders(std::move(header_block), fin,
515 std::move(ack_listener));
516 initial_headers_sent_ = true;
517 return len;
xunjieli5fafe142016-03-23 23:32:54518}
519
fayanga64c1a92016-02-13 01:55:58520SpdyPriority QuicChromiumClientStream::priority() const {
rchd4651b92017-05-04 00:41:17521 return initial_headers_sent_ ? QuicSpdyStream::priority()
522 : kV3HighestPriority;
[email protected]24e5bc52013-09-18 15:36:58523}
524
rch2ab4d872017-05-28 15:15:40525bool QuicChromiumClientStream::WriteStreamData(QuicStringPiece data, bool fin) {
526 // Must not be called when data is buffered.
[email protected]6adeb922013-09-01 22:43:25527 DCHECK(!HasBufferedData());
528 // Writes the data, or buffers it.
rtennetibe635732014-10-02 22:51:42529 WriteOrBufferData(data, fin, nullptr);
rch2ab4d872017-05-28 15:15:40530 return !HasBufferedData(); // Was all data written?
[email protected]6adeb922013-09-01 22:43:25531}
532
rch2ab4d872017-05-28 15:15:40533bool QuicChromiumClientStream::WritevStreamData(
xunjieli2328a2682016-05-16 19:38:25534 const std::vector<scoped_refptr<IOBuffer>>& buffers,
xunjieli07a42ce2016-04-26 20:05:31535 const std::vector<int>& lengths,
rch2ab4d872017-05-28 15:15:40536 bool fin) {
xunjieli07a42ce2016-04-26 20:05:31537 // Must not be called when data is buffered.
538 DCHECK(!HasBufferedData());
539 // Writes the data, or buffers it.
540 for (size_t i = 0; i < buffers.size(); ++i) {
541 bool is_fin = fin && (i == buffers.size() - 1);
fayang19c30772017-03-09 15:06:17542 QuicStringPiece string_data(buffers[i]->data(), lengths[i]);
xunjieli07a42ce2016-04-26 20:05:31543 WriteOrBufferData(string_data, is_fin, nullptr);
544 }
rch2ab4d872017-05-28 15:15:40545 return !HasBufferedData(); // Was all data written?
xunjieli07a42ce2016-04-26 20:05:31546}
547
rch08e198572017-05-09 16:56:55548std::unique_ptr<QuicChromiumClientStream::Handle>
rch1bcfddf22017-06-03 00:26:29549QuicChromiumClientStream::CreateHandle() {
rch08e198572017-05-09 16:56:55550 DCHECK(!handle_);
551 auto handle = std::unique_ptr<QuicChromiumClientStream::Handle>(
rch1bcfddf22017-06-03 00:26:29552 new QuicChromiumClientStream::Handle(this));
rch08e198572017-05-09 16:56:55553 handle_ = handle.get();
rch6788ad52017-05-09 04:49:04554
555 // Should this perhaps be via PostTask to make reasoning simpler?
rchfb47f712017-05-21 03:24:00556 if (!initial_headers_.empty())
557 handle_->OnInitialHeadersAvailable();
rch08e198572017-05-09 16:56:55558
559 return handle;
560}
561
562void QuicChromiumClientStream::ClearHandle() {
563 handle_ = nullptr;
[email protected]dd3fd0e2012-11-04 05:14:40564}
565
rch12fef552016-01-15 16:26:31566void QuicChromiumClientStream::OnError(int error) {
rch08e198572017-05-09 16:56:55567 if (handle_) {
568 QuicChromiumClientStream::Handle* handle = handle_;
569 handle_ = nullptr;
570 handle->OnError(error);
[email protected]56dfb902013-01-03 23:17:55571 }
572}
573
rch12fef552016-01-15 16:26:31574int QuicChromiumClientStream::Read(IOBuffer* buf, int buf_len) {
xunjieliec0ed02a2016-10-10 18:05:06575 if (IsDoneReading())
rchb27683c2015-07-29 23:53:50576 return 0; // EOF
577
578 if (!HasBytesToRead())
579 return ERR_IO_PENDING;
580
581 iovec iov;
582 iov.iov_base = buf->data();
583 iov.iov_len = buf_len;
xunjieliec0ed02a2016-10-10 18:05:06584 size_t bytes_read = Readv(&iov, 1);
rch03499252017-05-03 17:44:37585 // Since HasBytesToRead is true, Readv() must of read some data.
586 DCHECK_NE(0u, bytes_read);
xunjieliec0ed02a2016-10-10 18:05:06587 return bytes_read;
rchb27683c2015-07-29 23:53:50588}
589
rchfb47f712017-05-21 03:24:00590void QuicChromiumClientStream::NotifyHandleOfInitialHeadersAvailableLater() {
rch08e198572017-05-09 16:56:55591 DCHECK(handle_);
rch6788ad52017-05-09 04:49:04592 base::ThreadTaskRunnerHandle::Get()->PostTask(
593 FROM_HERE,
rchec5b74ac2017-05-09 13:31:40594 base::Bind(
rch08e198572017-05-09 16:56:55595 &QuicChromiumClientStream::NotifyHandleOfInitialHeadersAvailable,
rchfb47f712017-05-21 03:24:00596 weak_factory_.GetWeakPtr()));
rchb27683c2015-07-29 23:53:50597}
598
rchfb47f712017-05-21 03:24:00599void QuicChromiumClientStream::NotifyHandleOfInitialHeadersAvailable() {
rch08e198572017-05-09 16:56:55600 if (!handle_)
rchb27683c2015-07-29 23:53:50601 return;
602
rchfb47f712017-05-21 03:24:00603 if (!headers_delivered_)
604 handle_->OnInitialHeadersAvailable();
rchec5b74ac2017-05-09 13:31:40605}
606
rchce246412017-05-30 13:51:50607void QuicChromiumClientStream::NotifyHandleOfTrailingHeadersAvailableLater() {
rch08e198572017-05-09 16:56:55608 DCHECK(handle_);
rchec5b74ac2017-05-09 13:31:40609 base::ThreadTaskRunnerHandle::Get()->PostTask(
610 FROM_HERE,
611 base::Bind(
rch08e198572017-05-09 16:56:55612 &QuicChromiumClientStream::NotifyHandleOfTrailingHeadersAvailable,
rchce246412017-05-30 13:51:50613 weak_factory_.GetWeakPtr()));
rchec5b74ac2017-05-09 13:31:40614}
615
rchce246412017-05-30 13:51:50616void QuicChromiumClientStream::NotifyHandleOfTrailingHeadersAvailable() {
rch08e198572017-05-09 16:56:55617 if (!handle_)
rchec5b74ac2017-05-09 13:31:40618 return;
619
620 DCHECK(headers_delivered_);
rch1bcfddf22017-06-03 00:26:29621 // Post an async task to notify handle of the FIN flag.
rch08e198572017-05-09 16:56:55622 NotifyHandleOfDataAvailableLater();
rchce246412017-05-30 13:51:50623 handle_->OnTrailingHeadersAvailable();
rchb27683c2015-07-29 23:53:50624}
625
rchfb47f712017-05-21 03:24:00626bool QuicChromiumClientStream::DeliverInitialHeaders(SpdyHeaderBlock* headers,
627 int* frame_len) {
628 if (initial_headers_.empty())
629 return false;
630
631 headers_delivered_ = true;
632 net_log_.AddEvent(
633 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_READ_RESPONSE_HEADERS,
634 base::Bind(&SpdyHeaderBlockNetLogCallback, &initial_headers_));
635
636 *headers = std::move(initial_headers_);
637 *frame_len = initial_headers_frame_len_;
638 return true;
639}
640
rchce246412017-05-30 13:51:50641bool QuicChromiumClientStream::DeliverTrailingHeaders(SpdyHeaderBlock* headers,
642 int* frame_len) {
643 if (received_trailers().empty())
644 return false;
645
646 net_log_.AddEvent(
647 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_READ_RESPONSE_TRAILERS,
648 base::Bind(&SpdyHeaderBlockNetLogCallback, &received_trailers()));
649
650 *headers = received_trailers().Clone();
651 *frame_len = trailing_headers_frame_len_;
652
653 MarkTrailersConsumed();
654 return true;
655}
656
rch08e198572017-05-09 16:56:55657void QuicChromiumClientStream::NotifyHandleOfDataAvailableLater() {
658 DCHECK(handle_);
rch6788ad52017-05-09 04:49:04659 base::ThreadTaskRunnerHandle::Get()->PostTask(
660 FROM_HERE,
rch08e198572017-05-09 16:56:55661 base::Bind(&QuicChromiumClientStream::NotifyHandleOfDataAvailable,
rchb27683c2015-07-29 23:53:50662 weak_factory_.GetWeakPtr()));
663}
664
rch08e198572017-05-09 16:56:55665void QuicChromiumClientStream::NotifyHandleOfDataAvailable() {
666 if (handle_)
667 handle_->OnDataAvailable();
rchb27683c2015-07-29 23:53:50668}
669
jri231c2972016-03-08 19:50:11670void QuicChromiumClientStream::DisableConnectionMigration() {
671 can_migrate_ = false;
672}
673
xunjieli100937eb52016-09-15 20:09:37674bool QuicChromiumClientStream::IsFirstStream() {
675 return id() == kHeadersStreamId + 2;
676}
677
[email protected]dd3fd0e2012-11-04 05:14:40678} // namespace net