| 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 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 104 return vary_data.MatchesRequest(client_request_info, | 104 return vary_data.MatchesRequest(client_request_info, |
| 105 *promise_response_info.headers.get()); | 105 *promise_response_info.headers.get()); |
| 106 } | 106 } |
| 107 | 107 |
| 108 void QuicHttpStream::OnRendezvousResult(QuicSpdyStream* stream) { | 108 void QuicHttpStream::OnRendezvousResult(QuicSpdyStream* stream) { |
| 109 push_handle_ = nullptr; | 109 push_handle_ = nullptr; |
| 110 if (stream) { | 110 if (stream) { |
| 111 stream_ = static_cast<QuicChromiumClientStream*>(stream); | 111 stream_ = static_cast<QuicChromiumClientStream*>(stream); |
| 112 stream_->SetDelegate(this); | 112 stream_->SetDelegate(this); |
| 113 } | 113 } |
| 114 // callback_ should be non-null in the case of asynchronous | 114 |
| 115 // callback_ should only be non-null in the case of asynchronous |
| 115 // rendezvous; i.e. |Try()| returned QUIC_PENDING. | 116 // rendezvous; i.e. |Try()| returned QUIC_PENDING. |
| 116 if (!callback_.is_null()) { | 117 if (callback_.is_null()) |
| 117 if (stream) { | 118 return; |
| 118 next_state_ = STATE_OPEN; | 119 |
| 119 stream_net_log_.AddEvent( | 120 if (stream) { |
| 120 NetLogEventType::QUIC_HTTP_STREAM_ADOPTED_PUSH_STREAM, | 121 next_state_ = STATE_HANDLE_PROMISE_COMPLETE; |
| 121 base::Bind(&NetLogQuicPushStreamCallback, stream_->id(), | 122 } else { |
| 122 &request_info_->url)); | |
| 123 session_->net_log().AddEvent( | |
| 124 NetLogEventType::QUIC_HTTP_STREAM_ADOPTED_PUSH_STREAM, | |
| 125 base::Bind(&NetLogQuicPushStreamCallback, stream_->id(), | |
| 126 &request_info_->url)); | |
| 127 DoCallback(OK); | |
| 128 return; | |
| 129 } | |
| 130 // rendezvous has failed so proceed as with a non-push request. | 123 // rendezvous has failed so proceed as with a non-push request. |
| 131 next_state_ = STATE_REQUEST_STREAM; | 124 next_state_ = STATE_REQUEST_STREAM; |
| 132 OnIOComplete(OK); | |
| 133 } | 125 } |
| 126 |
| 127 OnIOComplete(OK); |
| 134 } | 128 } |
| 135 | 129 |
| 136 int QuicHttpStream::InitializeStream(const HttpRequestInfo* request_info, | 130 int QuicHttpStream::InitializeStream(const HttpRequestInfo* request_info, |
| 137 RequestPriority priority, | 131 RequestPriority priority, |
| 138 const BoundNetLog& stream_net_log, | 132 const BoundNetLog& stream_net_log, |
| 139 const CompletionCallback& callback) { | 133 const CompletionCallback& callback) { |
| 140 CHECK(callback_.is_null()); | 134 CHECK(callback_.is_null()); |
| 141 DCHECK(!stream_); | 135 DCHECK(!stream_); |
| 142 if (!session_) | 136 if (!session_) |
| 143 return was_handshake_confirmed_ ? ERR_CONNECTION_CLOSED | 137 return was_handshake_confirmed_ ? ERR_CONNECTION_CLOSED |
| (...skipping 29 matching lines...) Expand all Loading... |
| 173 } | 167 } |
| 174 | 168 |
| 175 next_state_ = STATE_REQUEST_STREAM; | 169 next_state_ = STATE_REQUEST_STREAM; |
| 176 int rv = DoLoop(OK); | 170 int rv = DoLoop(OK); |
| 177 if (rv == ERR_IO_PENDING) | 171 if (rv == ERR_IO_PENDING) |
| 178 callback_ = callback; | 172 callback_ = callback; |
| 179 | 173 |
| 180 return rv; | 174 return rv; |
| 181 } | 175 } |
| 182 | 176 |
| 183 void QuicHttpStream::OnStreamReady(int rv) { | |
| 184 DCHECK(rv == OK || !stream_); | |
| 185 if (rv == OK) { | |
| 186 stream_->SetDelegate(this); | |
| 187 if (request_info_->load_flags & LOAD_DISABLE_CONNECTION_MIGRATION) { | |
| 188 stream_->DisableConnectionMigration(); | |
| 189 } | |
| 190 if (response_info_) { | |
| 191 // This happens in the case of a asynchronous push rendezvous | |
| 192 // that ultimately fails (e.g. vary failure). |response_info_| | |
| 193 // non-null implies that |DoStreamRequest()| was called via | |
| 194 // |SendRequest()|. | |
| 195 next_state_ = STATE_SET_REQUEST_PRIORITY; | |
| 196 rv = DoLoop(OK); | |
| 197 } | |
| 198 } else if (!was_handshake_confirmed_) { | |
| 199 rv = ERR_QUIC_HANDSHAKE_FAILED; | |
| 200 } | |
| 201 if (rv != ERR_IO_PENDING) { | |
| 202 DoCallback(rv); | |
| 203 } | |
| 204 } | |
| 205 | |
| 206 bool QuicHttpStream::CancelPromiseIfHasBody() { | 177 bool QuicHttpStream::CancelPromiseIfHasBody() { |
| 207 if (!request_body_stream_) | 178 if (!request_body_stream_) |
| 208 return false; | 179 return false; |
| 209 // Method type or request with body ineligble for push. | 180 |
| 181 // A request with a body is ineligble for push. |
| 210 this->push_handle_->Cancel(); | 182 this->push_handle_->Cancel(); |
| 211 this->push_handle_ = nullptr; | 183 this->push_handle_ = nullptr; |
| 212 next_state_ = STATE_REQUEST_STREAM; | |
| 213 return true; | 184 return true; |
| 214 } | 185 } |
| 215 | 186 |
| 216 int QuicHttpStream::HandlePromise() { | 187 int QuicHttpStream::DoHandlePromise() { |
| 217 QuicAsyncStatus push_status = session_->push_promise_index()->Try( | 188 QuicAsyncStatus push_status = session_->push_promise_index()->Try( |
| 218 request_headers_, this, &this->push_handle_); | 189 request_headers_, this, &this->push_handle_); |
| 219 | 190 |
| 220 switch (push_status) { | 191 switch (push_status) { |
| 221 case QUIC_FAILURE: | 192 case QUIC_FAILURE: |
| 222 // Push rendezvous failed. | 193 // Push rendezvous failed. |
| 223 next_state_ = STATE_REQUEST_STREAM; | 194 next_state_ = STATE_REQUEST_STREAM; |
| 224 break; | 195 break; |
| 225 case QUIC_SUCCESS: | 196 case QUIC_SUCCESS: |
| 226 next_state_ = STATE_OPEN; | 197 next_state_ = STATE_HANDLE_PROMISE_COMPLETE; |
| 227 if (!CancelPromiseIfHasBody()) { | |
| 228 stream_net_log_.AddEvent( | |
| 229 NetLogEventType::QUIC_HTTP_STREAM_ADOPTED_PUSH_STREAM, | |
| 230 base::Bind(&NetLogQuicPushStreamCallback, stream_->id(), | |
| 231 &request_info_->url)); | |
| 232 session_->net_log().AddEvent( | |
| 233 NetLogEventType::QUIC_HTTP_STREAM_ADOPTED_PUSH_STREAM, | |
| 234 base::Bind(&NetLogQuicPushStreamCallback, stream_->id(), | |
| 235 &request_info_->url)); | |
| 236 // Avoid the call to |DoLoop()| below, which would reset | |
| 237 // next_state_ to STATE_NONE. | |
| 238 return OK; | |
| 239 } | |
| 240 | |
| 241 break; | 198 break; |
| 242 case QUIC_PENDING: | 199 case QUIC_PENDING: |
| 243 if (!CancelPromiseIfHasBody()) { | 200 if (!CancelPromiseIfHasBody()) { |
| 201 next_state_ = STATE_HANDLE_PROMISE_COMPLETE; |
| 244 // Have a promise but the promised stream doesn't exist yet. | 202 // Have a promise but the promised stream doesn't exist yet. |
| 245 // Still have to do validation before accepting the promised | 203 // Still have to do validation before accepting the promised |
| 246 // stream for sure. | 204 // stream for sure. |
| 247 return ERR_IO_PENDING; | 205 return ERR_IO_PENDING; |
| 248 } | 206 } |
| 249 break; | 207 next_state_ = STATE_REQUEST_STREAM; |
| 250 } | 208 } |
| 251 return DoLoop(OK); | 209 return OK; |
| 210 } |
| 211 |
| 212 int QuicHttpStream::DoHandlePromiseComplete(int rv) { |
| 213 if (rv != OK) |
| 214 return rv; |
| 215 |
| 216 if (CancelPromiseIfHasBody()) { |
| 217 next_state_ = STATE_REQUEST_STREAM; |
| 218 return OK; |
| 219 } |
| 220 |
| 221 next_state_ = STATE_OPEN; |
| 222 stream_net_log_.AddEvent( |
| 223 NetLogEventType::QUIC_HTTP_STREAM_ADOPTED_PUSH_STREAM, |
| 224 base::Bind(&NetLogQuicPushStreamCallback, stream_->id(), |
| 225 &request_info_->url)); |
| 226 session_->net_log().AddEvent( |
| 227 NetLogEventType::QUIC_HTTP_STREAM_ADOPTED_PUSH_STREAM, |
| 228 base::Bind(&NetLogQuicPushStreamCallback, stream_->id(), |
| 229 &request_info_->url)); |
| 230 return OK; |
| 252 } | 231 } |
| 253 | 232 |
| 254 int QuicHttpStream::SendRequest(const HttpRequestHeaders& request_headers, | 233 int QuicHttpStream::SendRequest(const HttpRequestHeaders& request_headers, |
| 255 HttpResponseInfo* response, | 234 HttpResponseInfo* response, |
| 256 const CompletionCallback& callback) { | 235 const CompletionCallback& callback) { |
| 257 CHECK(!request_body_stream_); | 236 CHECK(!request_body_stream_); |
| 258 CHECK(!response_info_); | 237 CHECK(!response_info_); |
| 259 CHECK(callback_.is_null()); | 238 CHECK(callback_.is_null()); |
| 260 CHECK(!callback.is_null()); | 239 CHECK(!callback.is_null()); |
| 261 CHECK(response); | 240 CHECK(response); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 292 // The request body buffer is empty at first. | 271 // The request body buffer is empty at first. |
| 293 request_body_buf_ = new DrainableIOBuffer(raw_request_body_buf_.get(), 0); | 272 request_body_buf_ = new DrainableIOBuffer(raw_request_body_buf_.get(), 0); |
| 294 } | 273 } |
| 295 | 274 |
| 296 // Store the response info. | 275 // Store the response info. |
| 297 response_info_ = response; | 276 response_info_ = response; |
| 298 | 277 |
| 299 int rv; | 278 int rv; |
| 300 | 279 |
| 301 if (found_promise_) { | 280 if (found_promise_) { |
| 302 rv = HandlePromise(); | 281 // TODO(rch): If this request has a body, instead of waiting for the pushed |
| 282 // headers to arrive before canceling the push we could cancel the pushed |
| 283 // stream now and go straight to STATE_REQUEST_STREAM. |
| 284 next_state_ = STATE_HANDLE_PROMISE; |
| 303 } else { | 285 } else { |
| 304 next_state_ = STATE_SET_REQUEST_PRIORITY; | 286 next_state_ = STATE_SET_REQUEST_PRIORITY; |
| 305 rv = DoLoop(OK); | |
| 306 } | 287 } |
| 288 rv = DoLoop(OK); |
| 307 | 289 |
| 308 if (rv == ERR_IO_PENDING) | 290 if (rv == ERR_IO_PENDING) |
| 309 callback_ = callback; | 291 callback_ = callback; |
| 310 | 292 |
| 311 return rv > 0 ? OK : rv; | 293 return rv > 0 ? OK : rv; |
| 312 } | 294 } |
| 313 | 295 |
| 314 UploadProgress QuicHttpStream::GetUploadProgress() const { | 296 UploadProgress QuicHttpStream::GetUploadProgress() const { |
| 315 if (!request_body_stream_) | 297 if (!request_body_stream_) |
| 316 return UploadProgress(); | 298 return UploadProgress(); |
| (...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 585 base::ResetAndReturn(&callback_).Run(rv); | 567 base::ResetAndReturn(&callback_).Run(rv); |
| 586 } | 568 } |
| 587 | 569 |
| 588 int QuicHttpStream::DoLoop(int rv) { | 570 int QuicHttpStream::DoLoop(int rv) { |
| 589 CHECK(!in_loop_); | 571 CHECK(!in_loop_); |
| 590 base::AutoReset<bool> auto_reset_in_loop(&in_loop_, true); | 572 base::AutoReset<bool> auto_reset_in_loop(&in_loop_, true); |
| 591 do { | 573 do { |
| 592 State state = next_state_; | 574 State state = next_state_; |
| 593 next_state_ = STATE_NONE; | 575 next_state_ = STATE_NONE; |
| 594 switch (state) { | 576 switch (state) { |
| 577 case STATE_HANDLE_PROMISE: |
| 578 CHECK_EQ(OK, rv); |
| 579 rv = DoHandlePromise(); |
| 580 break; |
| 581 case STATE_HANDLE_PROMISE_COMPLETE: |
| 582 CHECK_EQ(OK, rv); |
| 583 rv = DoHandlePromiseComplete(rv); |
| 584 break; |
| 595 case STATE_REQUEST_STREAM: | 585 case STATE_REQUEST_STREAM: |
| 596 rv = DoStreamRequest(); | 586 CHECK_EQ(OK, rv); |
| 587 rv = DoRequestStream(); |
| 588 break; |
| 589 case STATE_REQUEST_STREAM_COMPLETE: |
| 590 rv = DoRequestStreamComplete(rv); |
| 597 break; | 591 break; |
| 598 case STATE_SET_REQUEST_PRIORITY: | 592 case STATE_SET_REQUEST_PRIORITY: |
| 593 CHECK_EQ(OK, rv); |
| 599 rv = DoSetRequestPriority(); | 594 rv = DoSetRequestPriority(); |
| 600 break; | 595 break; |
| 601 case STATE_WAIT_FOR_CONFIRMATION: | 596 case STATE_WAIT_FOR_CONFIRMATION: |
| 602 CHECK_EQ(OK, rv); | 597 CHECK_EQ(OK, rv); |
| 603 rv = DoWaitForConfirmation(); | 598 rv = DoWaitForConfirmation(); |
| 604 break; | 599 break; |
| 605 case STATE_WAIT_FOR_CONFIRMATION_COMPLETE: | 600 case STATE_WAIT_FOR_CONFIRMATION_COMPLETE: |
| 606 rv = DoWaitForConfirmationComplete(rv); | 601 rv = DoWaitForConfirmationComplete(rv); |
| 607 break; | 602 break; |
| 608 case STATE_SEND_HEADERS: | 603 case STATE_SEND_HEADERS: |
| (...skipping 23 matching lines...) Expand all Loading... |
| 632 default: | 627 default: |
| 633 NOTREACHED() << "next_state_: " << next_state_; | 628 NOTREACHED() << "next_state_: " << next_state_; |
| 634 break; | 629 break; |
| 635 } | 630 } |
| 636 } while (next_state_ != STATE_NONE && next_state_ != STATE_OPEN && | 631 } while (next_state_ != STATE_NONE && next_state_ != STATE_OPEN && |
| 637 rv != ERR_IO_PENDING); | 632 rv != ERR_IO_PENDING); |
| 638 | 633 |
| 639 return rv; | 634 return rv; |
| 640 } | 635 } |
| 641 | 636 |
| 642 int QuicHttpStream::DoStreamRequest() { | 637 int QuicHttpStream::DoRequestStream() { |
| 643 int rv = stream_request_.StartRequest( | 638 next_state_ = STATE_REQUEST_STREAM_COMPLETE; |
| 639 return stream_request_.StartRequest( |
| 644 session_, &stream_, | 640 session_, &stream_, |
| 645 base::Bind(&QuicHttpStream::OnStreamReady, weak_factory_.GetWeakPtr())); | 641 base::Bind(&QuicHttpStream::OnIOComplete, weak_factory_.GetWeakPtr())); |
| 646 if (rv == OK) { | 642 } |
| 647 stream_->SetDelegate(this); | 643 |
| 648 if (request_info_->load_flags & LOAD_DISABLE_CONNECTION_MIGRATION) { | 644 int QuicHttpStream::DoRequestStreamComplete(int rv) { |
| 649 stream_->DisableConnectionMigration(); | 645 DCHECK(rv == OK || !stream_); |
| 650 } | 646 if (rv != OK) |
| 651 if (response_info_) { | 647 return was_handshake_confirmed_ ? rv : ERR_QUIC_HANDSHAKE_FAILED; |
| 652 next_state_ = STATE_SET_REQUEST_PRIORITY; | 648 |
| 653 } | 649 stream_->SetDelegate(this); |
| 654 } else if (rv != ERR_IO_PENDING && !was_handshake_confirmed_) { | 650 if (request_info_->load_flags & LOAD_DISABLE_CONNECTION_MIGRATION) { |
| 655 rv = ERR_QUIC_HANDSHAKE_FAILED; | 651 stream_->DisableConnectionMigration(); |
| 656 } | 652 } |
| 657 return rv; | 653 |
| 654 if (response_info_) { |
| 655 // This happens in the case of a asynchronous push rendezvous |
| 656 // that ultimately fails (e.g. vary failure). |response_info_| |
| 657 // non-null implies that |DoRequestStream()| was called via |
| 658 // |SendRequest()|. |
| 659 next_state_ = STATE_SET_REQUEST_PRIORITY; |
| 660 } |
| 661 |
| 662 return OK; |
| 658 } | 663 } |
| 659 | 664 |
| 660 int QuicHttpStream::DoSetRequestPriority() { | 665 int QuicHttpStream::DoSetRequestPriority() { |
| 661 // Set priority according to request | 666 // Set priority according to request |
| 662 DCHECK(stream_); | 667 DCHECK(stream_); |
| 663 DCHECK(response_info_); | 668 DCHECK(response_info_); |
| 664 SpdyPriority priority = ConvertRequestPriorityToQuicPriority(priority_); | 669 SpdyPriority priority = ConvertRequestPriorityToQuicPriority(priority_); |
| 665 stream_->SetPriority(priority); | 670 stream_->SetPriority(priority); |
| 666 next_state_ = STATE_WAIT_FOR_CONFIRMATION; | 671 next_state_ = STATE_WAIT_FOR_CONFIRMATION; |
| 667 return OK; | 672 return OK; |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 839 closed_is_first_stream_ = stream_->IsFirstStream(); | 844 closed_is_first_stream_ = stream_->IsFirstStream(); |
| 840 stream_ = nullptr; | 845 stream_ = nullptr; |
| 841 | 846 |
| 842 // If |request_body_stream_| is non-NULL, Reset it, to abort any in progress | 847 // If |request_body_stream_| is non-NULL, Reset it, to abort any in progress |
| 843 // read. | 848 // read. |
| 844 if (request_body_stream_) | 849 if (request_body_stream_) |
| 845 request_body_stream_->Reset(); | 850 request_body_stream_->Reset(); |
| 846 } | 851 } |
| 847 | 852 |
| 848 } // namespace net | 853 } // namespace net |
| OLD | NEW |