Index: net/http/http_pipelined_connection_impl.cc |
diff --git a/net/http/http_pipelined_connection_impl.cc b/net/http/http_pipelined_connection_impl.cc |
index 82c788f903edbaf88a8861f94bb81e3ea8dcd06d..1287355f7f9fc436d23e53470d153dc1e8b78325 100644 |
--- a/net/http/http_pipelined_connection_impl.cc |
+++ b/net/http/http_pipelined_connection_impl.cc |
@@ -9,7 +9,9 @@ |
#include "net/base/io_buffer.h" |
#include "net/http/http_pipelined_stream.h" |
#include "net/http/http_request_info.h" |
+#include "net/http/http_response_headers.h" |
#include "net/http/http_stream_parser.h" |
+#include "net/http/http_version.h" |
#include "net/socket/client_socket_handle.h" |
namespace net { |
@@ -165,7 +167,7 @@ int HttpPipelinedConnectionImpl::DoSendRequestLoop(int result) { |
rv = DoEvictPendingSendRequests(rv); |
break; |
default: |
- NOTREACHED() << "bad send state: " << state; |
+ CHECK(false) << "bad send state: " << state; |
rv = ERR_FAILED; |
break; |
} |
@@ -335,7 +337,7 @@ int HttpPipelinedConnectionImpl::DoReadHeadersLoop(int result) { |
case READ_STATE_NONE: |
break; |
default: |
- NOTREACHED() << "bad read state"; |
+ CHECK(false) << "bad read state"; |
rv = ERR_FAILED; |
break; |
} |
@@ -392,7 +394,7 @@ int HttpPipelinedConnectionImpl::DoStartNextDeferredRead(int result) { |
break; |
default: |
- NOTREACHED() << "Unexpected read state: " |
+ CHECK(false) << "Unexpected read state: " |
<< stream_info_map_[next_id].state; |
} |
@@ -423,6 +425,8 @@ int HttpPipelinedConnectionImpl::DoReadHeadersComplete(int result) { |
usable_ = false; |
} |
+ CheckHeadersForPipelineCompatibility(result, active_read_id_); |
+ |
if (!read_still_on_call_stack_) { |
QueueUserCallback(active_read_id_, |
stream_info_map_[active_read_id_].read_headers_callback, |
@@ -443,6 +447,7 @@ int HttpPipelinedConnectionImpl::DoReadStreamClosed() { |
CHECK_EQ(stream_info_map_[active_read_id_].state, STREAM_CLOSED); |
active_read_id_ = 0; |
if (!usable_) { |
+ // TODO(simonjam): Don't wait this long to evict. |
read_next_state_ = READ_STATE_EVICT_PENDING_READS; |
return OK; |
} |
@@ -525,7 +530,7 @@ void HttpPipelinedConnectionImpl::Close(int pipeline_id, |
break; |
default: |
- NOTREACHED(); |
+ CHECK(false); |
break; |
} |
} |
@@ -606,6 +611,38 @@ void HttpPipelinedConnectionImpl::GetSSLCertRequestInfo( |
cert_request_info); |
} |
+void HttpPipelinedConnectionImpl::CheckHeadersForPipelineCompatibility( |
+ int result, |
+ int pipeline_id) { |
+ if (result < OK) { |
+ switch (result) { |
+ // TODO(simonjam): Ignoring specific errors like this may not work. |
+ // Collect metrics to see if this code is useful. |
+ case ERR_ABORTED: |
+ case ERR_INTERNET_DISCONNECTED: |
+ // These errors are no fault of the server. |
+ break; |
+ |
+ default: |
+ delegate_->OnPipelineFeedback(this, PIPELINE_SOCKET_ERROR); |
+ return; |
+ } |
+ } |
+ HttpResponseInfo* info = GetResponseInfo(pipeline_id); |
+ const HttpVersion required_version(1, 1); |
+ if (info->headers->GetParsedHttpVersion() < required_version) { |
+ delegate_->OnPipelineFeedback(this, OLD_HTTP_VERSION); |
+ return; |
+ } |
+ if (!info->headers->IsKeepAlive() || !CanFindEndOfResponse(pipeline_id)) { |
+ usable_ = false; |
+ delegate_->OnPipelineFeedback(this, MUST_CLOSE_CONNECTION); |
+ return; |
+ } |
+ // TODO(simonjam): We should also check for, and work around, authentication. |
+ delegate_->OnPipelineFeedback(this, OK); |
+} |
+ |
void HttpPipelinedConnectionImpl::QueueUserCallback( |
int pipeline_id, |
OldCompletionCallback* callback, |