Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(253)

Side by Side Diff: net/quic/chromium/quic_chromium_client_stream.cc

Issue 2873963003: Add an async ReadInitialHeaders method to QuicChromiumClientStream::Handle (Closed)
Patch Set: Cleanup Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/quic/chromium/quic_chromium_client_stream.h" 5 #include "net/quic/chromium/quic_chromium_client_stream.h"
6 6
7 #include <utility> 7 #include <utility>
8 8
9 #include "base/bind_helpers.h" 9 #include "base/bind_helpers.h"
10 #include "base/callback_helpers.h" 10 #include "base/callback_helpers.h"
11 #include "base/location.h" 11 #include "base/location.h"
12 #include "base/threading/thread_task_runner_handle.h" 12 #include "base/threading/thread_task_runner_handle.h"
13 #include "net/base/io_buffer.h" 13 #include "net/base/io_buffer.h"
14 #include "net/base/net_errors.h" 14 #include "net/base/net_errors.h"
15 #include "net/log/net_log_event_type.h" 15 #include "net/log/net_log_event_type.h"
16 #include "net/quic/chromium/quic_chromium_client_session.h" 16 #include "net/quic/chromium/quic_chromium_client_session.h"
17 #include "net/quic/chromium/quic_http_utils.h" 17 #include "net/quic/chromium/quic_http_utils.h"
18 #include "net/quic/core/quic_spdy_session.h" 18 #include "net/quic/core/quic_spdy_session.h"
19 #include "net/quic/core/quic_write_blocked_list.h" 19 #include "net/quic/core/quic_write_blocked_list.h"
20 #include "net/quic/core/spdy_utils.h" 20 #include "net/quic/core/spdy_utils.h"
21 21
22 namespace net { 22 namespace net {
23 23
24 namespace {
25
26 // Sets a boolean to a value, and restores it to the previous value once
27 // the saver goes out of scope.
28 class ScopedBoolSaver {
29 public:
30 ScopedBoolSaver(bool* var, bool new_val) : var_(var), old_val_(*var) {
31 *var_ = new_val;
32 }
33
34 ~ScopedBoolSaver() { *var_ = old_val_; }
35
36 private:
37 bool* var_;
38 bool old_val_;
39 };
40
41 } // namespace
42
24 QuicChromiumClientStream::Handle::Handle(QuicChromiumClientStream* stream, 43 QuicChromiumClientStream::Handle::Handle(QuicChromiumClientStream* stream,
25 Delegate* delegate) 44 Delegate* delegate)
26 : stream_(stream), delegate_(delegate) { 45 : stream_(stream),
46 delegate_(delegate),
47 can_invoke_callbacks_(true),
48 read_headers_buffer_(nullptr) {
27 SaveState(); 49 SaveState();
28 } 50 }
29 51
30 QuicChromiumClientStream::Handle::~Handle() { 52 QuicChromiumClientStream::Handle::~Handle() {
31 if (stream_) { 53 if (stream_) {
32 stream_->ClearHandle(); 54 stream_->ClearHandle();
33 // TODO(rch): If stream_ is still valid, it should probably be Reset() 55 // TODO(rch): If stream_ is still valid, it should probably be Reset()
34 // so that it does not leak. 56 // so that it does not leak.
35 // stream_->Reset(QUIC_STREAM_CANCELLED); 57 // stream_->Reset(QUIC_STREAM_CANCELLED);
36 } 58 }
37 } 59 }
38 60
39 void QuicChromiumClientStream::Handle::ClearDelegate() { 61 void QuicChromiumClientStream::Handle::ClearDelegate() {
40 delegate_ = nullptr; 62 delegate_ = nullptr;
41 } 63 }
42 64
43 void QuicChromiumClientStream::Handle::OnInitialHeadersAvailable( 65 void QuicChromiumClientStream::Handle::OnInitialHeadersAvailable() {
44 const SpdyHeaderBlock& headers, 66 if (!read_headers_callback_ || !can_invoke_callbacks_)
45 size_t frame_len) { 67 return; // Wait for ReadInitialHeaders to be called.
46 delegate_->OnInitialHeadersAvailable(headers, frame_len); 68
69 int rv;
xunjieli 2017/05/10 17:54:27 Looks like DeliverInitialiHeaders() can fail to in
Ryan Hamilton 2017/05/10 18:26:40 I think that should only happen when Deliver retur
70 if (!stream_->DeliverInitialHeaders(read_headers_buffer_, &rv))
xunjieli 2017/05/10 17:54:27 If BidiStream or QuicHttpStream is gone but Handle
Ryan Hamilton 2017/05/10 18:26:40 The Handle is by definition owned by "the caller"
xunjieli 2017/05/10 18:58:08 Acknowledged. The ownership model takes a while to
Ryan Hamilton 2017/05/10 19:33:46 *fingers crossed*!
71 rv = ERR_QUIC_PROTOCOL_ERROR;
72
73 ResetAndReturn(&read_headers_callback_).Run(rv);
47 } 74 }
48 75
49 void QuicChromiumClientStream::Handle::OnTrailingHeadersAvailable( 76 void QuicChromiumClientStream::Handle::OnTrailingHeadersAvailable(
50 const SpdyHeaderBlock& headers, 77 const SpdyHeaderBlock& headers,
51 size_t frame_len) { 78 size_t frame_len) {
52 delegate_->OnTrailingHeadersAvailable(headers, frame_len); 79 delegate_->OnTrailingHeadersAvailable(headers, frame_len);
53 } 80 }
54 81
55 void QuicChromiumClientStream::Handle::OnDataAvailable() { 82 void QuicChromiumClientStream::Handle::OnDataAvailable() {
56 delegate_->OnDataAvailable(); 83 delegate_->OnDataAvailable();
(...skipping 14 matching lines...) Expand all
71 if (stream_) 98 if (stream_)
72 SaveState(); 99 SaveState();
73 stream_ = nullptr; 100 stream_ = nullptr;
74 if (delegate_) { 101 if (delegate_) {
75 auto* delegate = delegate_; 102 auto* delegate = delegate_;
76 delegate_ = nullptr; 103 delegate_ = nullptr;
77 delegate->OnError(error); 104 delegate->OnError(error);
78 } 105 }
79 } 106 }
80 107
108 int QuicChromiumClientStream::Handle::ReadInitialHeaders(
109 SpdyHeaderBlock* header_block,
110 const CompletionCallback& callback) {
111 ScopedBoolSaver saver(&can_invoke_callbacks_, false);
xunjieli 2017/05/10 17:54:27 Why do we need to have this bool? I don't see any
Ryan Hamilton 2017/05/10 18:26:40 AH! Sorry, I meant to mention this in the CL descr
xunjieli 2017/05/10 18:58:08 I see. That makes sense. Let's omit this in this C
Ryan Hamilton 2017/05/10 19:33:46 SGTM. Done.
112 if (!stream_)
113 return ERR_CONNECTION_CLOSED;
114
115 int frame_len;
xunjieli 2017/05/10 17:54:27 same here. |frame_len| might not be initialized.
Ryan Hamilton 2017/05/10 18:26:40 Done.
116 if (stream_->DeliverInitialHeaders(header_block, &frame_len))
117 return frame_len;
118
119 read_headers_buffer_ = header_block;
120 SetCallback(callback, &read_headers_callback_);
121 return ERR_IO_PENDING;
122 }
123
81 size_t QuicChromiumClientStream::Handle::WriteHeaders( 124 size_t QuicChromiumClientStream::Handle::WriteHeaders(
82 SpdyHeaderBlock header_block, 125 SpdyHeaderBlock header_block,
83 bool fin, 126 bool fin,
84 QuicReferenceCountedPointer<QuicAckListenerInterface> 127 QuicReferenceCountedPointer<QuicAckListenerInterface>
85 ack_notifier_delegate) { 128 ack_notifier_delegate) {
86 if (!stream_) 129 if (!stream_)
87 return 0; 130 return 0;
88 return stream_->WriteHeaders(std::move(header_block), fin, 131 return stream_->WriteHeaders(std::move(header_block), fin,
89 ack_notifier_delegate); 132 ack_notifier_delegate);
90 } 133 }
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
227 id_ = stream_->id(); 270 id_ = stream_->id();
228 connection_error_ = stream_->connection_error(); 271 connection_error_ = stream_->connection_error();
229 stream_error_ = stream_->stream_error(); 272 stream_error_ = stream_->stream_error();
230 is_done_reading_ = stream_->IsDoneReading(); 273 is_done_reading_ = stream_->IsDoneReading();
231 is_first_stream_ = stream_->IsFirstStream(); 274 is_first_stream_ = stream_->IsFirstStream();
232 stream_bytes_read_ = stream_->stream_bytes_read(); 275 stream_bytes_read_ = stream_->stream_bytes_read();
233 stream_bytes_written_ = stream_->stream_bytes_written(); 276 stream_bytes_written_ = stream_->stream_bytes_written();
234 priority_ = stream_->priority(); 277 priority_ = stream_->priority();
235 } 278 }
236 279
280 void QuicChromiumClientStream::Handle::SetCallback(
281 CompletionCallback new_callback,
282 CompletionCallback* callback) {
283 DCHECK(!can_invoke_callbacks_);
284 *callback = new_callback;
285 }
286
237 QuicChromiumClientStream::QuicChromiumClientStream( 287 QuicChromiumClientStream::QuicChromiumClientStream(
238 QuicStreamId id, 288 QuicStreamId id,
239 QuicClientSessionBase* session, 289 QuicClientSessionBase* session,
240 const NetLogWithSource& net_log) 290 const NetLogWithSource& net_log)
241 : QuicSpdyStream(id, session), 291 : QuicSpdyStream(id, session),
242 net_log_(net_log), 292 net_log_(net_log),
243 handle_(nullptr), 293 handle_(nullptr),
244 headers_delivered_(false), 294 headers_delivered_(false),
245 initial_headers_sent_(false), 295 initial_headers_sent_(false),
246 session_(session), 296 session_(session),
(...skipping 17 matching lines...) Expand all
264 if (!SpdyUtils::CopyAndValidateHeaders(header_list, &length, &header_block)) { 314 if (!SpdyUtils::CopyAndValidateHeaders(header_list, &length, &header_block)) {
265 DLOG(ERROR) << "Failed to parse header list: " << header_list.DebugString(); 315 DLOG(ERROR) << "Failed to parse header list: " << header_list.DebugString();
266 ConsumeHeaderList(); 316 ConsumeHeaderList();
267 Reset(QUIC_BAD_APPLICATION_PAYLOAD); 317 Reset(QUIC_BAD_APPLICATION_PAYLOAD);
268 return; 318 return;
269 } 319 }
270 320
271 ConsumeHeaderList(); 321 ConsumeHeaderList();
272 session_->OnInitialHeadersComplete(id(), header_block); 322 session_->OnInitialHeadersComplete(id(), header_block);
273 323
274 if (handle_) {
275 // The handle will receive the headers via a posted task.
276 NotifyHandleOfInitialHeadersAvailableLater(std::move(header_block),
277 frame_len);
278 return;
279 }
280
281 // Buffer the headers and deliver them when the handle arrives. 324 // Buffer the headers and deliver them when the handle arrives.
282 initial_headers_ = std::move(header_block); 325 initial_headers_ = std::move(header_block);
283 initial_headers_frame_len_ = frame_len; 326 initial_headers_frame_len_ = frame_len;
327
328 if (handle_) {
329 // The handle will be notified of the headers via a posted task.
330 NotifyHandleOfInitialHeadersAvailableLater();
331 }
284 } 332 }
285 333
286 void QuicChromiumClientStream::OnTrailingHeadersComplete( 334 void QuicChromiumClientStream::OnTrailingHeadersComplete(
287 bool fin, 335 bool fin,
288 size_t frame_len, 336 size_t frame_len,
289 const QuicHeaderList& header_list) { 337 const QuicHeaderList& header_list) {
290 QuicSpdyStream::OnTrailingHeadersComplete(fin, frame_len, header_list); 338 QuicSpdyStream::OnTrailingHeadersComplete(fin, frame_len, header_list);
291 NotifyHandleOfTrailingHeadersAvailableLater(received_trailers().Clone(), 339 NotifyHandleOfTrailingHeadersAvailableLater(received_trailers().Clone(),
292 frame_len); 340 frame_len);
293 } 341 }
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
407 455
408 std::unique_ptr<QuicChromiumClientStream::Handle> 456 std::unique_ptr<QuicChromiumClientStream::Handle>
409 QuicChromiumClientStream::CreateHandle( 457 QuicChromiumClientStream::CreateHandle(
410 QuicChromiumClientStream::Delegate* delegate) { 458 QuicChromiumClientStream::Delegate* delegate) {
411 DCHECK(!handle_); 459 DCHECK(!handle_);
412 auto handle = std::unique_ptr<QuicChromiumClientStream::Handle>( 460 auto handle = std::unique_ptr<QuicChromiumClientStream::Handle>(
413 new QuicChromiumClientStream::Handle(this, delegate)); 461 new QuicChromiumClientStream::Handle(this, delegate));
414 handle_ = handle.get(); 462 handle_ = handle.get();
415 463
416 // Should this perhaps be via PostTask to make reasoning simpler? 464 // Should this perhaps be via PostTask to make reasoning simpler?
417 if (!initial_headers_.empty()) { 465 if (!initial_headers_.empty())
418 handle_->OnInitialHeadersAvailable(std::move(initial_headers_), 466 handle_->OnInitialHeadersAvailable();
419 initial_headers_frame_len_);
420 }
421 467
422 return handle; 468 return handle;
423 } 469 }
424 470
425 void QuicChromiumClientStream::ClearHandle() { 471 void QuicChromiumClientStream::ClearHandle() {
426 handle_ = nullptr; 472 handle_ = nullptr;
427 } 473 }
428 474
429 void QuicChromiumClientStream::OnError(int error) { 475 void QuicChromiumClientStream::OnError(int error) {
430 if (handle_) { 476 if (handle_) {
(...skipping 12 matching lines...) Expand all
443 489
444 iovec iov; 490 iovec iov;
445 iov.iov_base = buf->data(); 491 iov.iov_base = buf->data();
446 iov.iov_len = buf_len; 492 iov.iov_len = buf_len;
447 size_t bytes_read = Readv(&iov, 1); 493 size_t bytes_read = Readv(&iov, 1);
448 // Since HasBytesToRead is true, Readv() must of read some data. 494 // Since HasBytesToRead is true, Readv() must of read some data.
449 DCHECK_NE(0u, bytes_read); 495 DCHECK_NE(0u, bytes_read);
450 return bytes_read; 496 return bytes_read;
451 } 497 }
452 498
453 void QuicChromiumClientStream::NotifyHandleOfInitialHeadersAvailableLater( 499 void QuicChromiumClientStream::NotifyHandleOfInitialHeadersAvailableLater() {
454 SpdyHeaderBlock headers,
455 size_t frame_len) {
456 DCHECK(handle_); 500 DCHECK(handle_);
457 base::ThreadTaskRunnerHandle::Get()->PostTask( 501 base::ThreadTaskRunnerHandle::Get()->PostTask(
458 FROM_HERE, 502 FROM_HERE,
459 base::Bind( 503 base::Bind(
460 &QuicChromiumClientStream::NotifyHandleOfInitialHeadersAvailable, 504 &QuicChromiumClientStream::NotifyHandleOfInitialHeadersAvailable,
461 weak_factory_.GetWeakPtr(), base::Passed(std::move(headers)), 505 weak_factory_.GetWeakPtr()));
462 frame_len));
463 } 506 }
464 507
465 void QuicChromiumClientStream::NotifyHandleOfInitialHeadersAvailable( 508 void QuicChromiumClientStream::NotifyHandleOfInitialHeadersAvailable() {
466 SpdyHeaderBlock headers,
467 size_t frame_len) {
468 if (!handle_) 509 if (!handle_)
469 return; 510 return;
470 511
471 DCHECK(!headers_delivered_); 512 if (!headers_delivered_)
472 headers_delivered_ = true; 513 handle_->OnInitialHeadersAvailable();
473 net_log_.AddEvent(
474 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_READ_RESPONSE_HEADERS,
475 base::Bind(&SpdyHeaderBlockNetLogCallback, &headers));
476
477 handle_->OnInitialHeadersAvailable(headers, frame_len);
478 } 514 }
479 515
480 void QuicChromiumClientStream::NotifyHandleOfTrailingHeadersAvailableLater( 516 void QuicChromiumClientStream::NotifyHandleOfTrailingHeadersAvailableLater(
481 SpdyHeaderBlock headers, 517 SpdyHeaderBlock headers,
482 size_t frame_len) { 518 size_t frame_len) {
483 DCHECK(handle_); 519 DCHECK(handle_);
484 base::ThreadTaskRunnerHandle::Get()->PostTask( 520 base::ThreadTaskRunnerHandle::Get()->PostTask(
485 FROM_HERE, 521 FROM_HERE,
486 base::Bind( 522 base::Bind(
487 &QuicChromiumClientStream::NotifyHandleOfTrailingHeadersAvailable, 523 &QuicChromiumClientStream::NotifyHandleOfTrailingHeadersAvailable,
488 weak_factory_.GetWeakPtr(), base::Passed(std::move(headers)), 524 weak_factory_.GetWeakPtr(), base::Passed(std::move(headers)),
489 frame_len)); 525 frame_len));
490 } 526 }
491 527
492 void QuicChromiumClientStream::NotifyHandleOfTrailingHeadersAvailable( 528 void QuicChromiumClientStream::NotifyHandleOfTrailingHeadersAvailable(
493 SpdyHeaderBlock headers, 529 SpdyHeaderBlock headers,
494 size_t frame_len) { 530 size_t frame_len) {
495 if (!handle_) 531 if (!handle_)
496 return; 532 return;
497 533
498 DCHECK(headers_delivered_); 534 DCHECK(headers_delivered_);
499 // Only mark trailers consumed when we are about to notify delegate. 535 // Only mark trailers consumed when we are about to notify delegate.
500 MarkTrailersConsumed(); 536 MarkTrailersConsumed();
501 // Post an async task to notify delegate of the FIN flag. 537 // Post an async task to notify delegate of the FIN flag.
502 NotifyHandleOfDataAvailableLater(); 538 NotifyHandleOfDataAvailableLater();
503 net_log_.AddEvent( 539 net_log_.AddEvent(
504 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_READ_RESPONSE_TRAILERS, 540 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_READ_RESPONSE_TRAILERS,
505 base::Bind(&SpdyHeaderBlockNetLogCallback, &headers)); 541 base::Bind(&SpdyHeaderBlockNetLogCallback, &headers));
542 handle_->OnTrailingHeadersAvailable(headers, frame_len);
543 }
506 544
507 handle_->OnTrailingHeadersAvailable(headers, frame_len); 545 bool QuicChromiumClientStream::DeliverInitialHeaders(SpdyHeaderBlock* headers,
546 int* frame_len) {
547 if (initial_headers_.empty())
548 return false;
549
550 headers_delivered_ = true;
551 net_log_.AddEvent(
552 NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_READ_RESPONSE_HEADERS,
553 base::Bind(&SpdyHeaderBlockNetLogCallback, &initial_headers_));
554
555 *headers = std::move(initial_headers_);
556 *frame_len = initial_headers_frame_len_;
557 return true;
508 } 558 }
509 559
510 void QuicChromiumClientStream::NotifyHandleOfDataAvailableLater() { 560 void QuicChromiumClientStream::NotifyHandleOfDataAvailableLater() {
511 DCHECK(handle_); 561 DCHECK(handle_);
512 base::ThreadTaskRunnerHandle::Get()->PostTask( 562 base::ThreadTaskRunnerHandle::Get()->PostTask(
513 FROM_HERE, 563 FROM_HERE,
514 base::Bind(&QuicChromiumClientStream::NotifyHandleOfDataAvailable, 564 base::Bind(&QuicChromiumClientStream::NotifyHandleOfDataAvailable,
515 weak_factory_.GetWeakPtr())); 565 weak_factory_.GetWeakPtr()));
516 } 566 }
517 567
518 void QuicChromiumClientStream::NotifyHandleOfDataAvailable() { 568 void QuicChromiumClientStream::NotifyHandleOfDataAvailable() {
519 if (handle_) 569 if (handle_)
520 handle_->OnDataAvailable(); 570 handle_->OnDataAvailable();
521 } 571 }
522 572
523 void QuicChromiumClientStream::DisableConnectionMigration() { 573 void QuicChromiumClientStream::DisableConnectionMigration() {
524 can_migrate_ = false; 574 can_migrate_ = false;
525 } 575 }
526 576
527 bool QuicChromiumClientStream::IsFirstStream() { 577 bool QuicChromiumClientStream::IsFirstStream() {
528 return id() == kHeadersStreamId + 2; 578 return id() == kHeadersStreamId + 2;
529 } 579 }
530 580
531 } // namespace net 581 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698