Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/http/http_pipelined_connection_impl.h" | 5 #include "net/http/http_pipelined_connection_impl.h" |
| 6 | 6 |
| 7 #include "base/message_loop.h" | 7 #include "base/message_loop.h" |
| 8 #include "base/stl_util.h" | 8 #include "base/stl_util.h" |
| 9 #include "net/base/io_buffer.h" | 9 #include "net/base/io_buffer.h" |
| 10 #include "net/http/http_pipelined_stream.h" | 10 #include "net/http/http_pipelined_stream.h" |
| 11 #include "net/http/http_request_info.h" | 11 #include "net/http/http_request_info.h" |
| 12 #include "net/http/http_response_headers.h" | |
| 12 #include "net/http/http_stream_parser.h" | 13 #include "net/http/http_stream_parser.h" |
| 14 #include "net/http/http_version.h" | |
| 13 #include "net/socket/client_socket_handle.h" | 15 #include "net/socket/client_socket_handle.h" |
| 14 | 16 |
| 15 namespace net { | 17 namespace net { |
| 16 | 18 |
| 17 HttpPipelinedConnectionImpl::HttpPipelinedConnectionImpl( | 19 HttpPipelinedConnectionImpl::HttpPipelinedConnectionImpl( |
| 18 ClientSocketHandle* connection, | 20 ClientSocketHandle* connection, |
| 19 HttpPipelinedConnection::Delegate* delegate, | 21 HttpPipelinedConnection::Delegate* delegate, |
| 20 const SSLConfig& used_ssl_config, | 22 const SSLConfig& used_ssl_config, |
| 21 const ProxyInfo& used_proxy_info, | 23 const ProxyInfo& used_proxy_info, |
| 22 const BoundNetLog& net_log, | 24 const BoundNetLog& net_log, |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 158 case SEND_STATE_SEND_ACTIVE_REQUEST: | 160 case SEND_STATE_SEND_ACTIVE_REQUEST: |
| 159 rv = DoSendActiveRequest(rv); | 161 rv = DoSendActiveRequest(rv); |
| 160 break; | 162 break; |
| 161 case SEND_STATE_COMPLETE: | 163 case SEND_STATE_COMPLETE: |
| 162 rv = DoSendComplete(rv); | 164 rv = DoSendComplete(rv); |
| 163 break; | 165 break; |
| 164 case SEND_STATE_EVICT_PENDING_REQUESTS: | 166 case SEND_STATE_EVICT_PENDING_REQUESTS: |
| 165 rv = DoEvictPendingSendRequests(rv); | 167 rv = DoEvictPendingSendRequests(rv); |
| 166 break; | 168 break; |
| 167 default: | 169 default: |
| 168 NOTREACHED() << "bad send state: " << state; | 170 CHECK(false) << "bad send state: " << state; |
| 169 rv = ERR_FAILED; | 171 rv = ERR_FAILED; |
| 170 break; | 172 break; |
| 171 } | 173 } |
| 172 } while (rv != ERR_IO_PENDING && send_next_state_ != SEND_STATE_NONE); | 174 } while (rv != ERR_IO_PENDING && send_next_state_ != SEND_STATE_NONE); |
| 173 send_still_on_call_stack_ = false; | 175 send_still_on_call_stack_ = false; |
| 174 return rv; | 176 return rv; |
| 175 } | 177 } |
| 176 | 178 |
| 177 void HttpPipelinedConnectionImpl::OnSendIOCallback(int result) { | 179 void HttpPipelinedConnectionImpl::OnSendIOCallback(int result) { |
| 178 CHECK(active_send_request_.get()); | 180 CHECK(active_send_request_.get()); |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 328 return rv; | 330 return rv; |
| 329 case READ_STATE_STREAM_CLOSED: | 331 case READ_STATE_STREAM_CLOSED: |
| 330 rv = DoReadStreamClosed(); | 332 rv = DoReadStreamClosed(); |
| 331 break; | 333 break; |
| 332 case READ_STATE_EVICT_PENDING_READS: | 334 case READ_STATE_EVICT_PENDING_READS: |
| 333 rv = DoEvictPendingReadHeaders(rv); | 335 rv = DoEvictPendingReadHeaders(rv); |
| 334 break; | 336 break; |
| 335 case READ_STATE_NONE: | 337 case READ_STATE_NONE: |
| 336 break; | 338 break; |
| 337 default: | 339 default: |
| 338 NOTREACHED() << "bad read state"; | 340 CHECK(false) << "bad read state"; |
| 339 rv = ERR_FAILED; | 341 rv = ERR_FAILED; |
| 340 break; | 342 break; |
| 341 } | 343 } |
| 342 } while (rv != ERR_IO_PENDING && read_next_state_ != READ_STATE_NONE); | 344 } while (rv != ERR_IO_PENDING && read_next_state_ != READ_STATE_NONE); |
| 343 read_still_on_call_stack_ = false; | 345 read_still_on_call_stack_ = false; |
| 344 return rv; | 346 return rv; |
| 345 } | 347 } |
| 346 | 348 |
| 347 void HttpPipelinedConnectionImpl::OnReadIOCallback(int result) { | 349 void HttpPipelinedConnectionImpl::OnReadIOCallback(int result) { |
| 348 DoReadHeadersLoop(result); | 350 DoReadHeadersLoop(result); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 385 // Since nobody will read whatever data is on the pipeline associated with | 387 // Since nobody will read whatever data is on the pipeline associated with |
| 386 // this closed request, we must shut down the rest of the pipeline. | 388 // this closed request, we must shut down the rest of the pipeline. |
| 387 read_next_state_ = READ_STATE_EVICT_PENDING_READS; | 389 read_next_state_ = READ_STATE_EVICT_PENDING_READS; |
| 388 break; | 390 break; |
| 389 | 391 |
| 390 case STREAM_SENT: | 392 case STREAM_SENT: |
| 391 read_next_state_ = READ_STATE_NONE; | 393 read_next_state_ = READ_STATE_NONE; |
| 392 break; | 394 break; |
| 393 | 395 |
| 394 default: | 396 default: |
| 395 NOTREACHED() << "Unexpected read state: " | 397 CHECK(false) << "Unexpected read state: " |
| 396 << stream_info_map_[next_id].state; | 398 << stream_info_map_[next_id].state; |
| 397 } | 399 } |
| 398 | 400 |
| 399 return OK; | 401 return OK; |
| 400 } | 402 } |
| 401 | 403 |
| 402 int HttpPipelinedConnectionImpl::DoReadHeaders(int result) { | 404 int HttpPipelinedConnectionImpl::DoReadHeaders(int result) { |
| 403 CHECK(active_read_id_); | 405 CHECK(active_read_id_); |
| 404 CHECK(ContainsKey(stream_info_map_, active_read_id_)); | 406 CHECK(ContainsKey(stream_info_map_, active_read_id_)); |
| 405 CHECK_EQ(STREAM_READ_PENDING, stream_info_map_[active_read_id_].state); | 407 CHECK_EQ(STREAM_READ_PENDING, stream_info_map_[active_read_id_].state); |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 416 CHECK_EQ(STREAM_ACTIVE, stream_info_map_[active_read_id_].state); | 418 CHECK_EQ(STREAM_ACTIVE, stream_info_map_[active_read_id_].state); |
| 417 | 419 |
| 418 read_next_state_ = READ_STATE_WAITING_FOR_CLOSE; | 420 read_next_state_ = READ_STATE_WAITING_FOR_CLOSE; |
| 419 if (result < OK) { | 421 if (result < OK) { |
| 420 if (result == ERR_SOCKET_NOT_CONNECTED && completed_one_request_) { | 422 if (result == ERR_SOCKET_NOT_CONNECTED && completed_one_request_) { |
| 421 result = ERR_PIPELINE_EVICTION; | 423 result = ERR_PIPELINE_EVICTION; |
| 422 } | 424 } |
| 423 usable_ = false; | 425 usable_ = false; |
| 424 } | 426 } |
| 425 | 427 |
| 428 CheckHeadersForPipelineCompatibility(result, active_read_id_); | |
| 429 | |
| 426 if (!read_still_on_call_stack_) { | 430 if (!read_still_on_call_stack_) { |
| 427 QueueUserCallback(active_read_id_, | 431 QueueUserCallback(active_read_id_, |
| 428 stream_info_map_[active_read_id_].read_headers_callback, | 432 stream_info_map_[active_read_id_].read_headers_callback, |
| 429 result, FROM_HERE); | 433 result, FROM_HERE); |
| 430 } | 434 } |
| 431 | 435 |
| 432 return result; | 436 return result; |
| 433 } | 437 } |
| 434 | 438 |
| 435 int HttpPipelinedConnectionImpl::DoReadWaitForClose(int result) { | 439 int HttpPipelinedConnectionImpl::DoReadWaitForClose(int result) { |
| 436 read_next_state_ = READ_STATE_WAITING_FOR_CLOSE; | 440 read_next_state_ = READ_STATE_WAITING_FOR_CLOSE; |
| 437 return result; | 441 return result; |
| 438 } | 442 } |
| 439 | 443 |
| 440 int HttpPipelinedConnectionImpl::DoReadStreamClosed() { | 444 int HttpPipelinedConnectionImpl::DoReadStreamClosed() { |
| 441 CHECK(active_read_id_); | 445 CHECK(active_read_id_); |
| 442 CHECK(ContainsKey(stream_info_map_, active_read_id_)); | 446 CHECK(ContainsKey(stream_info_map_, active_read_id_)); |
| 443 CHECK_EQ(stream_info_map_[active_read_id_].state, STREAM_CLOSED); | 447 CHECK_EQ(stream_info_map_[active_read_id_].state, STREAM_CLOSED); |
| 444 active_read_id_ = 0; | 448 active_read_id_ = 0; |
| 445 if (!usable_) { | 449 if (!usable_) { |
| 450 // TODO(simonjam): Don't wait this long to evict. | |
| 446 read_next_state_ = READ_STATE_EVICT_PENDING_READS; | 451 read_next_state_ = READ_STATE_EVICT_PENDING_READS; |
| 447 return OK; | 452 return OK; |
| 448 } | 453 } |
| 449 completed_one_request_ = true; | 454 completed_one_request_ = true; |
| 450 MessageLoop::current()->PostTask( | 455 MessageLoop::current()->PostTask( |
| 451 FROM_HERE, | 456 FROM_HERE, |
| 452 method_factory_.NewRunnableMethod( | 457 method_factory_.NewRunnableMethod( |
| 453 &HttpPipelinedConnectionImpl::StartNextDeferredRead)); | 458 &HttpPipelinedConnectionImpl::StartNextDeferredRead)); |
| 454 read_next_state_ = READ_STATE_NONE; | 459 read_next_state_ = READ_STATE_NONE; |
| 455 return OK; | 460 return OK; |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 518 case STREAM_READ_EVICTED: | 523 case STREAM_READ_EVICTED: |
| 519 stream_info_map_[pipeline_id].state = STREAM_CLOSED; | 524 stream_info_map_[pipeline_id].state = STREAM_CLOSED; |
| 520 break; | 525 break; |
| 521 | 526 |
| 522 case STREAM_CLOSED: | 527 case STREAM_CLOSED: |
| 523 case STREAM_UNUSED: | 528 case STREAM_UNUSED: |
| 524 // TODO(simonjam): Why is Close() sometimes called twice? | 529 // TODO(simonjam): Why is Close() sometimes called twice? |
| 525 break; | 530 break; |
| 526 | 531 |
| 527 default: | 532 default: |
| 528 NOTREACHED(); | 533 CHECK(false); |
| 529 break; | 534 break; |
| 530 } | 535 } |
| 531 } | 536 } |
| 532 | 537 |
| 533 int HttpPipelinedConnectionImpl::ReadResponseBody( | 538 int HttpPipelinedConnectionImpl::ReadResponseBody( |
| 534 int pipeline_id, | 539 int pipeline_id, |
| 535 IOBuffer* buf, | 540 IOBuffer* buf, |
| 536 int buf_len, | 541 int buf_len, |
| 537 OldCompletionCallback* callback) { | 542 OldCompletionCallback* callback) { |
| 538 CHECK(ContainsKey(stream_info_map_, pipeline_id)); | 543 CHECK(ContainsKey(stream_info_map_, pipeline_id)); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 599 | 604 |
| 600 void HttpPipelinedConnectionImpl::GetSSLCertRequestInfo( | 605 void HttpPipelinedConnectionImpl::GetSSLCertRequestInfo( |
| 601 int pipeline_id, | 606 int pipeline_id, |
| 602 SSLCertRequestInfo* cert_request_info) { | 607 SSLCertRequestInfo* cert_request_info) { |
| 603 CHECK(ContainsKey(stream_info_map_, pipeline_id)); | 608 CHECK(ContainsKey(stream_info_map_, pipeline_id)); |
| 604 CHECK(stream_info_map_[pipeline_id].parser.get()); | 609 CHECK(stream_info_map_[pipeline_id].parser.get()); |
| 605 return stream_info_map_[pipeline_id].parser->GetSSLCertRequestInfo( | 610 return stream_info_map_[pipeline_id].parser->GetSSLCertRequestInfo( |
| 606 cert_request_info); | 611 cert_request_info); |
| 607 } | 612 } |
| 608 | 613 |
| 614 void HttpPipelinedConnectionImpl::CheckHeadersForPipelineCompatibility( | |
| 615 int result, | |
| 616 int pipeline_id) { | |
| 617 if (result < OK) { | |
|
mmenke
2011/11/21 14:51:39
When things go wrong, we won't necessarily get the
James Simonsen
2011/12/01 01:17:10
Okay, I've added a TODO. Eventually, I want to cir
| |
| 618 switch (result) { | |
| 619 case ERR_ABORTED: | |
| 620 case ERR_INTERNET_DISCONNECTED: | |
| 621 // These errors are no fault of the server. | |
| 622 break; | |
| 623 | |
| 624 default: | |
| 625 delegate_->OnPipelineFeedback(this, SOCKET_ERROR); | |
| 626 return; | |
| 627 } | |
| 628 } | |
| 629 HttpResponseInfo* info = GetResponseInfo(pipeline_id); | |
| 630 const HttpVersion required_version(1, 1); | |
| 631 if (info->headers->GetParsedHttpVersion() < required_version) { | |
| 632 delegate_->OnPipelineFeedback(this, OLD_HTTP_VERSION); | |
| 633 return; | |
| 634 } | |
| 635 if (!info->headers->IsKeepAlive() || !CanFindEndOfResponse(pipeline_id)) { | |
| 636 usable_ = false; | |
| 637 delegate_->OnPipelineFeedback(this, MUST_CLOSE_CONNECTION); | |
| 638 return; | |
| 639 } | |
|
mmenke
2011/11/21 14:51:39
We should also be doing something about NTLM AUTH
James Simonsen
2011/12/01 01:17:10
Yeah, that was next on my list. I'm going to do it
| |
| 640 delegate_->OnPipelineFeedback(this, OK); | |
| 641 } | |
| 642 | |
| 609 void HttpPipelinedConnectionImpl::QueueUserCallback( | 643 void HttpPipelinedConnectionImpl::QueueUserCallback( |
| 610 int pipeline_id, | 644 int pipeline_id, |
| 611 OldCompletionCallback* callback, | 645 OldCompletionCallback* callback, |
| 612 int rv, | 646 int rv, |
| 613 const tracked_objects::Location& from_here) { | 647 const tracked_objects::Location& from_here) { |
| 614 CHECK(!stream_info_map_[pipeline_id].pending_user_callback); | 648 CHECK(!stream_info_map_[pipeline_id].pending_user_callback); |
| 615 stream_info_map_[pipeline_id].pending_user_callback = callback; | 649 stream_info_map_[pipeline_id].pending_user_callback = callback; |
| 616 MessageLoop::current()->PostTask( | 650 MessageLoop::current()->PostTask( |
| 617 from_here, | 651 from_here, |
| 618 method_factory_.NewRunnableMethod( | 652 method_factory_.NewRunnableMethod( |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 669 HttpPipelinedConnectionImpl::StreamInfo::StreamInfo() | 703 HttpPipelinedConnectionImpl::StreamInfo::StreamInfo() |
| 670 : read_headers_callback(NULL), | 704 : read_headers_callback(NULL), |
| 671 pending_user_callback(NULL), | 705 pending_user_callback(NULL), |
| 672 state(STREAM_CREATED) { | 706 state(STREAM_CREATED) { |
| 673 } | 707 } |
| 674 | 708 |
| 675 HttpPipelinedConnectionImpl::StreamInfo::~StreamInfo() { | 709 HttpPipelinedConnectionImpl::StreamInfo::~StreamInfo() { |
| 676 } | 710 } |
| 677 | 711 |
| 678 } // namespace net | 712 } // namespace net |
| OLD | NEW |