Chromium Code Reviews| OLD | NEW |
|---|---|
| 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_http_stream.h" | 5 #include "net/quic/chromium/quic_http_stream.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/auto_reset.h" | 9 #include "base/auto_reset.h" |
| 10 #include "base/callback_helpers.h" | 10 #include "base/callback_helpers.h" |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 58 response_headers_received_(false), | 58 response_headers_received_(false), |
| 59 trailing_headers_received_(false), | 59 trailing_headers_received_(false), |
| 60 headers_bytes_received_(0), | 60 headers_bytes_received_(0), |
| 61 headers_bytes_sent_(0), | 61 headers_bytes_sent_(0), |
| 62 closed_stream_received_bytes_(0), | 62 closed_stream_received_bytes_(0), |
| 63 closed_stream_sent_bytes_(0), | 63 closed_stream_sent_bytes_(0), |
| 64 closed_is_first_stream_(false), | 64 closed_is_first_stream_(false), |
| 65 user_buffer_len_(0), | 65 user_buffer_len_(0), |
| 66 session_error_(ERR_UNEXPECTED), | 66 session_error_(ERR_UNEXPECTED), |
| 67 found_promise_(false), | 67 found_promise_(false), |
| 68 push_handle_(nullptr), | |
| 69 in_loop_(false), | 68 in_loop_(false), |
| 70 weak_factory_(this) {} | 69 weak_factory_(this) {} |
| 71 | 70 |
| 72 QuicHttpStream::~QuicHttpStream() { | 71 QuicHttpStream::~QuicHttpStream() { |
| 73 CHECK(!in_loop_); | 72 CHECK(!in_loop_); |
| 74 Close(false); | 73 Close(false); |
| 75 } | 74 } |
| 76 | 75 |
| 77 bool QuicHttpStream::CheckVary(const SpdyHeaderBlock& client_request, | |
| 78 const SpdyHeaderBlock& promise_request, | |
| 79 const SpdyHeaderBlock& promise_response) { | |
| 80 HttpResponseInfo promise_response_info; | |
| 81 | |
| 82 HttpRequestInfo promise_request_info; | |
| 83 ConvertHeaderBlockToHttpRequestHeaders(promise_request, | |
| 84 &promise_request_info.extra_headers); | |
| 85 HttpRequestInfo client_request_info; | |
| 86 ConvertHeaderBlockToHttpRequestHeaders(client_request, | |
| 87 &client_request_info.extra_headers); | |
| 88 | |
| 89 if (!SpdyHeadersToHttpResponse(promise_response, &promise_response_info)) { | |
| 90 DLOG(WARNING) << "Invalid headers"; | |
| 91 return false; | |
| 92 } | |
| 93 | |
| 94 HttpVaryData vary_data; | |
| 95 if (!vary_data.Init(promise_request_info, | |
| 96 *promise_response_info.headers.get())) { | |
| 97 // Promise didn't contain valid vary info, so URL match was sufficient. | |
| 98 return true; | |
| 99 } | |
| 100 // Now compare the client request for matching. | |
| 101 return vary_data.MatchesRequest(client_request_info, | |
| 102 *promise_response_info.headers.get()); | |
| 103 } | |
| 104 | |
| 105 void QuicHttpStream::OnRendezvousResult(QuicSpdyStream* stream) { | |
| 106 push_handle_ = nullptr; | |
| 107 if (stream) { | |
| 108 stream_ = static_cast<QuicChromiumClientStream*>(stream)->CreateHandle(); | |
| 109 } | |
| 110 | |
| 111 // callback_ should only be non-null in the case of asynchronous | |
| 112 // rendezvous; i.e. |Try()| returned QUIC_PENDING. | |
| 113 if (callback_.is_null()) | |
| 114 return; | |
| 115 | |
| 116 DCHECK_EQ(STATE_HANDLE_PROMISE_COMPLETE, next_state_); | |
| 117 if (!stream) { | |
| 118 // rendezvous has failed so proceed as with a non-push request. | |
| 119 next_state_ = STATE_REQUEST_STREAM; | |
| 120 } | |
| 121 | |
| 122 OnIOComplete(OK); | |
| 123 } | |
| 124 | |
| 125 HttpResponseInfo::ConnectionInfo QuicHttpStream::ConnectionInfoFromQuicVersion( | 76 HttpResponseInfo::ConnectionInfo QuicHttpStream::ConnectionInfoFromQuicVersion( |
| 126 QuicVersion quic_version) { | 77 QuicVersion quic_version) { |
| 127 switch (quic_version) { | 78 switch (quic_version) { |
| 128 case QUIC_VERSION_UNSUPPORTED: | 79 case QUIC_VERSION_UNSUPPORTED: |
| 129 return HttpResponseInfo::CONNECTION_INFO_QUIC_UNKNOWN_VERSION; | 80 return HttpResponseInfo::CONNECTION_INFO_QUIC_UNKNOWN_VERSION; |
| 130 case QUIC_VERSION_35: | 81 case QUIC_VERSION_35: |
| 131 return HttpResponseInfo::CONNECTION_INFO_QUIC_35; | 82 return HttpResponseInfo::CONNECTION_INFO_QUIC_35; |
| 132 case QUIC_VERSION_36: | 83 case QUIC_VERSION_36: |
| 133 return HttpResponseInfo::CONNECTION_INFO_QUIC_36; | 84 return HttpResponseInfo::CONNECTION_INFO_QUIC_36; |
| 134 case QUIC_VERSION_37: | 85 case QUIC_VERSION_37: |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 187 | 138 |
| 188 next_state_ = STATE_REQUEST_STREAM; | 139 next_state_ = STATE_REQUEST_STREAM; |
| 189 int rv = DoLoop(OK); | 140 int rv = DoLoop(OK); |
| 190 if (rv == ERR_IO_PENDING) | 141 if (rv == ERR_IO_PENDING) |
| 191 callback_ = callback; | 142 callback_ = callback; |
| 192 | 143 |
| 193 return MapStreamError(rv); | 144 return MapStreamError(rv); |
| 194 } | 145 } |
| 195 | 146 |
| 196 int QuicHttpStream::DoHandlePromise() { | 147 int QuicHttpStream::DoHandlePromise() { |
| 197 QuicAsyncStatus push_status = quic_session()->GetPushPromiseIndex()->Try( | 148 int rv = quic_session()->RendezvousWithPromised( |
| 198 request_headers_, this, &this->push_handle_); | 149 request_headers_, |
| 150 base::Bind(&QuicHttpStream::OnIOComplete, weak_factory_.GetWeakPtr())); | |
|
xunjieli
2017/06/21 20:55:28
Should this be "base::Unretained(this)" given that
Ryan Hamilton
2017/06/21 22:24:51
Hm! Interesting. I think that's possible! But sinc
xunjieli
2017/06/22 14:43:30
Acknowledged. Let's do it as a follow-up. If the H
| |
| 199 | 151 |
| 200 switch (push_status) { | 152 if (rv == ERR_IO_PENDING) { |
| 201 case QUIC_FAILURE: | 153 next_state_ = STATE_HANDLE_PROMISE_COMPLETE; |
| 202 // Push rendezvous failed. | 154 return ERR_IO_PENDING; |
| 203 next_state_ = STATE_REQUEST_STREAM; | |
| 204 break; | |
| 205 case QUIC_SUCCESS: | |
| 206 next_state_ = STATE_HANDLE_PROMISE_COMPLETE; | |
| 207 break; | |
| 208 case QUIC_PENDING: | |
| 209 next_state_ = STATE_HANDLE_PROMISE_COMPLETE; | |
| 210 return ERR_IO_PENDING; | |
| 211 } | 155 } |
| 212 return OK; | 156 |
| 157 if (rv < 0) { | |
|
xunjieli
2017/06/21 20:55:28
nit: This branch is not needed. We can go directly
Ryan Hamilton
2017/06/21 22:24:51
Hah! Clever! In fact, we don't need any of these b
| |
| 158 // Push rendezvous failed. | |
| 159 next_state_ = STATE_REQUEST_STREAM; | |
| 160 return OK; | |
| 161 } | |
| 162 | |
| 163 next_state_ = STATE_HANDLE_PROMISE_COMPLETE; | |
| 164 return rv; | |
| 213 } | 165 } |
| 214 | 166 |
| 215 int QuicHttpStream::DoHandlePromiseComplete(int rv) { | 167 int QuicHttpStream::DoHandlePromiseComplete(int rv) { |
|
xunjieli
2017/06/21 20:55:28
optional nit: add a
DCHECK_NE(ERR_IO_PENDING, rv)
Ryan Hamilton
2017/06/21 22:24:51
Done.
| |
| 216 if (rv != OK) | 168 if (rv != OK) { |
| 217 return rv; | 169 // rendezvous has failed so proceed as with a non-push request. |
| 170 next_state_ = STATE_REQUEST_STREAM; | |
| 171 return OK; | |
| 172 } | |
| 173 | |
| 174 stream_ = quic_session()->ReleasePromisedStream(); | |
| 218 | 175 |
| 219 next_state_ = STATE_OPEN; | 176 next_state_ = STATE_OPEN; |
| 220 stream_net_log_.AddEvent( | 177 stream_net_log_.AddEvent( |
| 221 NetLogEventType::QUIC_HTTP_STREAM_ADOPTED_PUSH_STREAM, | 178 NetLogEventType::QUIC_HTTP_STREAM_ADOPTED_PUSH_STREAM, |
| 222 base::Bind(&NetLogQuicPushStreamCallback, stream_->id(), | 179 base::Bind(&NetLogQuicPushStreamCallback, stream_->id(), |
| 223 &request_info_->url)); | 180 &request_info_->url)); |
| 224 quic_session()->net_log().AddEvent( | 181 quic_session()->net_log().AddEvent( |
| 225 NetLogEventType::QUIC_HTTP_STREAM_ADOPTED_PUSH_STREAM, | 182 NetLogEventType::QUIC_HTTP_STREAM_ADOPTED_PUSH_STREAM, |
| 226 base::Bind(&NetLogQuicPushStreamCallback, stream_->id(), | 183 base::Bind(&NetLogQuicPushStreamCallback, stream_->id(), |
| 227 &request_info_->url)); | 184 &request_info_->url)); |
| (...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 504 base::AutoReset<bool> auto_reset_in_loop(&in_loop_, true); | 461 base::AutoReset<bool> auto_reset_in_loop(&in_loop_, true); |
| 505 do { | 462 do { |
| 506 State state = next_state_; | 463 State state = next_state_; |
| 507 next_state_ = STATE_NONE; | 464 next_state_ = STATE_NONE; |
| 508 switch (state) { | 465 switch (state) { |
| 509 case STATE_HANDLE_PROMISE: | 466 case STATE_HANDLE_PROMISE: |
| 510 CHECK_EQ(OK, rv); | 467 CHECK_EQ(OK, rv); |
| 511 rv = DoHandlePromise(); | 468 rv = DoHandlePromise(); |
| 512 break; | 469 break; |
| 513 case STATE_HANDLE_PROMISE_COMPLETE: | 470 case STATE_HANDLE_PROMISE_COMPLETE: |
| 514 CHECK_EQ(OK, rv); | |
| 515 rv = DoHandlePromiseComplete(rv); | 471 rv = DoHandlePromiseComplete(rv); |
| 516 break; | 472 break; |
| 517 case STATE_REQUEST_STREAM: | 473 case STATE_REQUEST_STREAM: |
| 518 CHECK_EQ(OK, rv); | 474 CHECK_EQ(OK, rv); |
| 519 rv = DoRequestStream(); | 475 rv = DoRequestStream(); |
| 520 break; | 476 break; |
| 521 case STATE_REQUEST_STREAM_COMPLETE: | 477 case STATE_REQUEST_STREAM_COMPLETE: |
| 522 rv = DoRequestStreamComplete(rv); | 478 rv = DoRequestStreamComplete(rv); |
| 523 break; | 479 break; |
| 524 case STATE_SET_REQUEST_PRIORITY: | 480 case STATE_SET_REQUEST_PRIORITY: |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 734 int QuicHttpStream::HandleReadComplete(int rv) { | 690 int QuicHttpStream::HandleReadComplete(int rv) { |
| 735 if (stream_->IsDoneReading()) { | 691 if (stream_->IsDoneReading()) { |
| 736 stream_->OnFinRead(); | 692 stream_->OnFinRead(); |
| 737 SetResponseStatus(OK); | 693 SetResponseStatus(OK); |
| 738 ResetStream(); | 694 ResetStream(); |
| 739 } | 695 } |
| 740 return rv; | 696 return rv; |
| 741 } | 697 } |
| 742 | 698 |
| 743 void QuicHttpStream::ResetStream() { | 699 void QuicHttpStream::ResetStream() { |
| 744 if (push_handle_) { | |
| 745 push_handle_->Cancel(); | |
| 746 push_handle_ = nullptr; | |
| 747 } | |
| 748 | |
| 749 // If |request_body_stream_| is non-NULL, Reset it, to abort any in progress | 700 // If |request_body_stream_| is non-NULL, Reset it, to abort any in progress |
| 750 // read. | 701 // read. |
| 751 if (request_body_stream_) | 702 if (request_body_stream_) |
| 752 request_body_stream_->Reset(); | 703 request_body_stream_->Reset(); |
| 753 | 704 |
| 754 if (!stream_) | 705 if (!stream_) |
| 755 return; | 706 return; |
| 756 | 707 |
| 757 DCHECK_LE(stream_->NumBytesConsumed(), stream_->stream_bytes_read()); | 708 DCHECK_LE(stream_->NumBytesConsumed(), stream_->stream_bytes_read()); |
| 758 // Only count the uniquely received bytes. | 709 // Only count the uniquely received bytes. |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 805 // Explicit stream error are always fatal. | 756 // Explicit stream error are always fatal. |
| 806 if (stream_->stream_error() != QUIC_STREAM_NO_ERROR && | 757 if (stream_->stream_error() != QUIC_STREAM_NO_ERROR && |
| 807 stream_->stream_error() != QUIC_STREAM_CONNECTION_ERROR) { | 758 stream_->stream_error() != QUIC_STREAM_CONNECTION_ERROR) { |
| 808 return ERR_QUIC_PROTOCOL_ERROR; | 759 return ERR_QUIC_PROTOCOL_ERROR; |
| 809 } | 760 } |
| 810 | 761 |
| 811 return ERR_QUIC_PROTOCOL_ERROR; | 762 return ERR_QUIC_PROTOCOL_ERROR; |
| 812 } | 763 } |
| 813 | 764 |
| 814 } // namespace net | 765 } // namespace net |
| OLD | NEW |