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 |