Index: net/http/http_network_transaction.cc |
=================================================================== |
--- net/http/http_network_transaction.cc (revision 54789) |
+++ net/http/http_network_transaction.cc (working copy) |
@@ -298,7 +298,7 @@ |
// update in DoSSLConnectComplete if |result| is OK? |
if (using_spdy_) { |
// TODO(cbentzel): Add auth support to spdy. See http://crbug.com/46620 |
- next_state_ = STATE_SPDY_GET_STREAM; |
+ next_state_ = STATE_INIT_STREAM; |
} else { |
next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN; |
} |
@@ -370,10 +370,10 @@ |
// Even if the server says the connection is keep-alive, we have to be |
// able to find the end of each response in order to reuse the connection. |
if (GetResponseHeaders()->IsKeepAlive() && |
- http_stream_->CanFindEndOfResponse()) { |
+ stream_->CanFindEndOfResponse()) { |
// If the response body hasn't been completely read, we need to drain |
// it first. |
- if (!http_stream_->IsResponseBodyComplete()) { |
+ if (!stream_->IsResponseBodyComplete()) { |
next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART; |
read_buf_ = new IOBuffer(kDrainBodyBufferSize); // A bit bucket. |
read_buf_len_ = kDrainBodyBufferSize; |
@@ -430,16 +430,10 @@ |
} |
// Are we using SPDY or HTTP? |
- if (using_spdy_) { |
- DCHECK(!http_stream_.get()); |
- DCHECK(spdy_http_stream_->GetResponseInfo()->headers); |
- next_state = STATE_SPDY_READ_BODY; |
- } else { |
- DCHECK(!spdy_http_stream_.get()); |
- next_state = STATE_READ_BODY; |
- |
- if (!connection_->is_initialized()) |
- return 0; // |*connection_| has been reset. Treat like EOF. |
+ next_state = STATE_READ_BODY; |
+ DCHECK(stream_->GetResponseInfo()->headers); |
+ if (!using_spdy_ && !connection_->is_initialized()) { |
+ return 0; // |*connection_| has been reset. Treat like EOF. |
} |
read_buf_ = buf; |
@@ -468,14 +462,11 @@ |
case STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE: |
case STATE_GENERATE_SERVER_AUTH_TOKEN_COMPLETE: |
case STATE_SEND_REQUEST_COMPLETE: |
- case STATE_SPDY_GET_STREAM: |
- case STATE_SPDY_SEND_REQUEST_COMPLETE: |
+ case STATE_INIT_STREAM_COMPLETE: |
return LOAD_STATE_SENDING_REQUEST; |
case STATE_READ_HEADERS_COMPLETE: |
- case STATE_SPDY_READ_HEADERS_COMPLETE: |
return LOAD_STATE_WAITING_FOR_RESPONSE; |
case STATE_READ_BODY_COMPLETE: |
- case STATE_SPDY_READ_BODY_COMPLETE: |
return LOAD_STATE_READING_RESPONSE; |
default: |
return LOAD_STATE_IDLE; |
@@ -483,10 +474,10 @@ |
} |
uint64 HttpNetworkTransaction::GetUploadProgress() const { |
- if (!http_stream_.get()) |
+ if (!stream_.get()) |
return 0; |
- return http_stream_->GetUploadProgress(); |
+ return stream_->GetUploadProgress(); |
} |
HttpNetworkTransaction::~HttpNetworkTransaction() { |
@@ -497,9 +488,10 @@ |
// The STATE_NONE check guarantees there are no pending socket IOs that |
// could try to call this object back after it is deleted. |
bool keep_alive = next_state_ == STATE_NONE && |
- http_stream_.get() && |
- http_stream_->IsResponseBodyComplete() && |
- http_stream_->CanFindEndOfResponse() && |
+ !using_spdy_ && |
+ stream_.get() && |
+ stream_->IsResponseBodyComplete() && |
+ stream_->CanFindEndOfResponse() && |
GetResponseHeaders()->IsKeepAlive(); |
if (!keep_alive) |
connection_->socket()->Disconnect(); |
@@ -508,8 +500,8 @@ |
if (pac_request_) |
session_->proxy_service()->CancelPacRequest(pac_request_); |
- if (spdy_http_stream_.get()) |
- spdy_http_stream_->Cancel(); |
+ if (using_spdy_ && stream_.get()) |
+ static_cast<SpdyHttpStream*>(stream_.get())->Cancel(); |
} |
void HttpNetworkTransaction::DoCallback(int rv) { |
@@ -550,6 +542,13 @@ |
case STATE_INIT_CONNECTION_COMPLETE: |
rv = DoInitConnectionComplete(rv); |
break; |
+ case STATE_INIT_STREAM: |
+ DCHECK_EQ(OK, rv); |
+ rv = DoInitStream(); |
+ break; |
+ case STATE_INIT_STREAM_COMPLETE: |
+ rv = DoInitStreamComplete(rv); |
+ break; |
case STATE_RESTART_TUNNEL_AUTH: |
DCHECK_EQ(OK, rv); |
rv = DoRestartTunnelAuth(); |
@@ -609,40 +608,6 @@ |
net_log_.EndEvent( |
NetLog::TYPE_HTTP_TRANSACTION_DRAIN_BODY_FOR_AUTH_RESTART, NULL); |
break; |
- case STATE_SPDY_GET_STREAM: |
- DCHECK_EQ(OK, rv); |
- rv = DoSpdyGetStream(); |
- break; |
- case STATE_SPDY_GET_STREAM_COMPLETE: |
- rv = DoSpdyGetStreamComplete(rv); |
- break; |
- case STATE_SPDY_SEND_REQUEST: |
- DCHECK_EQ(OK, rv); |
- net_log_.BeginEvent(NetLog::TYPE_SPDY_TRANSACTION_SEND_REQUEST, NULL); |
- rv = DoSpdySendRequest(); |
- break; |
- case STATE_SPDY_SEND_REQUEST_COMPLETE: |
- rv = DoSpdySendRequestComplete(rv); |
- net_log_.EndEvent(NetLog::TYPE_SPDY_TRANSACTION_SEND_REQUEST, NULL); |
- break; |
- case STATE_SPDY_READ_HEADERS: |
- DCHECK_EQ(OK, rv); |
- net_log_.BeginEvent(NetLog::TYPE_SPDY_TRANSACTION_READ_HEADERS, NULL); |
- rv = DoSpdyReadHeaders(); |
- break; |
- case STATE_SPDY_READ_HEADERS_COMPLETE: |
- rv = DoSpdyReadHeadersComplete(rv); |
- net_log_.EndEvent(NetLog::TYPE_SPDY_TRANSACTION_READ_HEADERS, NULL); |
- break; |
- case STATE_SPDY_READ_BODY: |
- DCHECK_EQ(OK, rv); |
- net_log_.BeginEvent(NetLog::TYPE_SPDY_TRANSACTION_READ_BODY, NULL); |
- rv = DoSpdyReadBody(); |
- break; |
- case STATE_SPDY_READ_BODY_COMPLETE: |
- rv = DoSpdyReadBodyComplete(rv); |
- net_log_.EndEvent(NetLog::TYPE_SPDY_TRANSACTION_READ_BODY, NULL); |
- break; |
default: |
NOTREACHED() << "bad state"; |
rv = ERR_FAILED; |
@@ -748,7 +713,9 @@ |
if (session_->spdy_session_pool()->HasSession(pair)) { |
using_spdy_ = true; |
reused_socket_ = true; |
- next_state_ = STATE_SPDY_GET_STREAM; |
+ next_state_ = STATE_INIT_STREAM; |
+ spdy_session_ = |
+ session_->spdy_session_pool()->Get(pair, session_, net_log_); |
return OK; |
} |
@@ -950,7 +917,7 @@ |
if (!using_ssl_) { |
DCHECK_EQ(OK, result); |
if (using_spdy_) |
- next_state_ = STATE_SPDY_GET_STREAM; |
+ next_state_ = STATE_INIT_STREAM; |
else |
next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN; |
return result; |
@@ -987,13 +954,56 @@ |
if (using_spdy_) { |
UpdateConnectionTypeHistograms(CONNECTION_SPDY); |
// TODO(cbentzel): Add auth support to spdy. See http://crbug.com/46620 |
- next_state_ = STATE_SPDY_GET_STREAM; |
+ next_state_ = STATE_INIT_STREAM; |
} else { |
next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN; |
} |
return OK; |
} |
+int HttpNetworkTransaction::DoInitStream() { |
+ next_state_ = STATE_INIT_STREAM_COMPLETE; |
+ |
+ if (!using_spdy_) { |
+ stream_.reset(new HttpBasicStream(connection_.get())); |
+ return stream_->InitializeStream(request_, net_log_, &io_callback_); |
+ } |
+ |
+ CHECK(!stream_.get()); |
+ |
+ const scoped_refptr<SpdySessionPool> spdy_pool = |
+ session_->spdy_session_pool(); |
+ |
+ HostPortProxyPair pair(endpoint_, proxy_info_.ToPacString()); |
+ if (!spdy_session_.get()) { |
+ // SPDY can be negotiated using the TLS next protocol negotiation (NPN) |
+ // extension, or just directly using SSL. Either way, |connection_| must |
+ // contain an SSLClientSocket. |
+ CHECK(connection_->socket()); |
+ int error = spdy_pool->GetSpdySessionFromSocket( |
+ pair, session_, connection_.release(), net_log_, |
+ spdy_certificate_error_, &spdy_session_, using_ssl_); |
+ if (error != OK) |
+ return error; |
+ } |
+ CHECK(spdy_session_.get()); |
+ if (spdy_session_->IsClosed()) |
+ return ERR_CONNECTION_CLOSED; |
+ |
+ headers_valid_ = false; |
+ |
+ stream_.reset(new SpdyHttpStream(spdy_session_.release())); |
+ return stream_->InitializeStream(request_, net_log_, &io_callback_); |
+} |
+ |
+int HttpNetworkTransaction::DoInitStreamComplete(int result) { |
+ if (result < 0) |
+ return result; |
+ |
+ next_state_ = STATE_SEND_REQUEST; |
+ return OK; |
+} |
+ |
int HttpNetworkTransaction::DoRestartTunnelAuth() { |
next_state_ = STATE_RESTART_TUNNEL_AUTH_COMPLETE; |
HttpProxyClientSocket* http_proxy_socket = |
@@ -1057,7 +1067,7 @@ |
int HttpNetworkTransaction::DoGenerateServerAuthTokenComplete(int rv) { |
DCHECK_NE(ERR_IO_PENDING, rv); |
if (rv == OK) |
- next_state_ = STATE_SEND_REQUEST; |
+ next_state_ = STATE_INIT_STREAM; |
return rv; |
} |
@@ -1074,7 +1084,7 @@ |
// This is constructed lazily (instead of within our Start method), so that |
// we have proxy info available. |
- if (request_headers_.empty()) { |
+ if (request_headers_.empty() && !using_spdy_) { |
// Figure out if we can/should add Proxy-Authentication & Authentication |
// headers. |
HttpRequestHeaders authorization_headers; |
@@ -1107,10 +1117,8 @@ |
} |
headers_valid_ = false; |
- http_stream_.reset(new HttpBasicStream(connection_.get())); |
- http_stream_->InitializeStream(request_, net_log_, NULL); |
- return http_stream_->SendRequest(request_headers_, request_body, &response_, |
- &io_callback_); |
+ return stream_->SendRequest(request_headers_, request_body, &response_, |
+ &io_callback_); |
} |
int HttpNetworkTransaction::DoSendRequestComplete(int result) { |
@@ -1122,7 +1130,7 @@ |
int HttpNetworkTransaction::DoReadHeaders() { |
next_state_ = STATE_READ_HEADERS_COMPLETE; |
- return http_stream_->ReadResponseHeaders(&io_callback_); |
+ return stream_->ReadResponseHeaders(&io_callback_); |
} |
int HttpNetworkTransaction::HandleConnectionClosedBeforeEndOfHeaders() { |
@@ -1136,6 +1144,18 @@ |
} |
int HttpNetworkTransaction::DoReadHeadersComplete(int result) { |
+ if (using_spdy_) { |
+ // TODO(willchan): Flesh out the support for HTTP authentication here. |
+ if (result < 0) |
+ return HandleIOError(result); |
+ |
+ if (result == OK) |
+ headers_valid_ = true; |
+ |
+ LogTransactionConnectedMetrics(); |
+ return result; |
+ } |
+ |
// We can get a certificate error or ERR_SSL_CLIENT_AUTH_CERT_NEEDED here |
// due to SSL renegotiation. |
if (using_ssl_) { |
@@ -1241,32 +1261,37 @@ |
int HttpNetworkTransaction::DoReadBody() { |
DCHECK(read_buf_); |
DCHECK_GT(read_buf_len_, 0); |
- DCHECK(connection_->is_initialized()); |
+ if (!using_spdy_) |
+ DCHECK(connection_->is_initialized()); |
next_state_ = STATE_READ_BODY_COMPLETE; |
- return http_stream_->ReadResponseBody(read_buf_, read_buf_len_, |
- &io_callback_); |
+ return stream_->ReadResponseBody(read_buf_, read_buf_len_, &io_callback_); |
} |
int HttpNetworkTransaction::DoReadBodyComplete(int result) { |
- // We are done with the Read call. |
- bool done = false, keep_alive = false; |
- if (result <= 0) |
- done = true; |
+ if (!using_spdy_) { |
+ // We are done with the Read call. |
+ bool done = false, keep_alive = false; |
+ if (result <= 0) |
+ done = true; |
- if (http_stream_->IsResponseBodyComplete()) { |
- done = true; |
- if (http_stream_->CanFindEndOfResponse()) |
- keep_alive = GetResponseHeaders()->IsKeepAlive(); |
- } |
+ if (stream_->IsResponseBodyComplete()) { |
+ done = true; |
+ if (stream_->CanFindEndOfResponse()) |
+ keep_alive = GetResponseHeaders()->IsKeepAlive(); |
+ } |
- // Clean up connection_->if we are done. |
- if (done) { |
- LogTransactionMetrics(); |
- if (!keep_alive) |
- connection_->socket()->Disconnect(); |
- connection_->Reset(); |
- // The next Read call will return 0 (EOF). |
+ // Clean up connection_->if we are done. |
+ if (done) { |
+ LogTransactionMetrics(); |
+ if (!keep_alive) |
+ connection_->socket()->Disconnect(); |
+ connection_->Reset(); |
+ // The next Read call will return 0 (EOF). |
+ } |
+ } else { |
+ if (result <= 0) |
+ stream_.reset(); |
} |
// Clear these to avoid leaving around old state. |
@@ -1296,7 +1321,7 @@ |
// Error or closed connection while reading the socket. |
done = true; |
keep_alive = false; |
- } else if (http_stream_->IsResponseBodyComplete()) { |
+ } else if (stream_->IsResponseBodyComplete()) { |
done = true; |
} |
@@ -1310,118 +1335,6 @@ |
return OK; |
} |
-int HttpNetworkTransaction::DoSpdyGetStream() { |
- next_state_ = STATE_SPDY_GET_STREAM_COMPLETE; |
- CHECK(!spdy_http_stream_.get()); |
- |
- // First we get a SPDY session. Theoretically, we've just negotiated one, but |
- // if one already exists, then screw it, use the existing one! Otherwise, |
- // use the existing TCP socket. |
- |
- const scoped_refptr<SpdySessionPool> spdy_pool = |
- session_->spdy_session_pool(); |
- scoped_refptr<SpdySession> spdy_session; |
- |
- HostPortProxyPair pair(endpoint_, proxy_info_.ToPacString()); |
- if (spdy_pool->HasSession(pair)) { |
- spdy_session = spdy_pool->Get(pair, session_, net_log_); |
- } else { |
- if(using_ssl_) { |
- // SPDY can be negotiated using the TLS next protocol negotiation (NPN) |
- // extension, or just directly using SSL. Either way, |connection_| must |
- // contain an SSLClientSocket. |
- CHECK(connection_->socket()); |
- int error = spdy_pool->GetSpdySessionFromSocket( |
- pair, session_, connection_.release(), net_log_, |
- spdy_certificate_error_, &spdy_session, true); |
- if (error != OK) |
- return error; |
- } |
- else { |
- // We may want SPDY without SSL |
- int error = spdy_pool->GetSpdySessionFromSocket( |
- pair, session_, connection_.release(), net_log_, |
- spdy_certificate_error_, &spdy_session, false); |
- if (error != OK) |
- return error; |
- } |
- } |
- |
- CHECK(spdy_session.get()); |
- if (spdy_session->IsClosed()) |
- return ERR_CONNECTION_CLOSED; |
- |
- headers_valid_ = false; |
- |
- spdy_http_stream_.reset(new SpdyHttpStream(spdy_session)); |
- return spdy_http_stream_->InitializeStream(request_, net_log_, &io_callback_); |
-} |
- |
-int HttpNetworkTransaction::DoSpdyGetStreamComplete(int result) { |
- if (result < 0) |
- return result; |
- |
- next_state_ = STATE_SPDY_SEND_REQUEST; |
- return OK; |
-} |
- |
-int HttpNetworkTransaction::DoSpdySendRequest() { |
- next_state_ = STATE_SPDY_SEND_REQUEST_COMPLETE; |
- |
- UploadDataStream* upload_data_stream = NULL; |
- if (request_->upload_data) { |
- int error_code = OK; |
- upload_data_stream = UploadDataStream::Create(request_->upload_data, |
- &error_code); |
- if (!upload_data_stream) |
- return error_code; |
- } |
- return spdy_http_stream_->SendRequest(request_headers_, upload_data_stream, |
- &response_, &io_callback_); |
-} |
- |
-int HttpNetworkTransaction::DoSpdySendRequestComplete(int result) { |
- if (result < 0) |
- return HandleIOError(result); |
- |
- next_state_ = STATE_SPDY_READ_HEADERS; |
- return OK; |
-} |
- |
-int HttpNetworkTransaction::DoSpdyReadHeaders() { |
- next_state_ = STATE_SPDY_READ_HEADERS_COMPLETE; |
- return spdy_http_stream_->ReadResponseHeaders(&io_callback_); |
-} |
- |
-int HttpNetworkTransaction::DoSpdyReadHeadersComplete(int result) { |
- // TODO(willchan): Flesh out the support for HTTP authentication here. |
- if (result < 0) |
- return HandleIOError(result); |
- |
- if (result == OK) |
- headers_valid_ = true; |
- |
- LogTransactionConnectedMetrics(); |
- return result; |
-} |
- |
-int HttpNetworkTransaction::DoSpdyReadBody() { |
- next_state_ = STATE_SPDY_READ_BODY_COMPLETE; |
- |
- return spdy_http_stream_->ReadResponseBody( |
- read_buf_, read_buf_len_, &io_callback_); |
-} |
- |
-int HttpNetworkTransaction::DoSpdyReadBodyComplete(int result) { |
- read_buf_ = NULL; |
- read_buf_len_ = 0; |
- |
- if (result <= 0) |
- spdy_http_stream_.reset(); |
- |
- return result; |
-} |
- |
void HttpNetworkTransaction::LogHttpConnectedMetrics( |
const ClientSocketHandle& handle) { |
UMA_HISTOGRAM_ENUMERATION("Net.HttpSocketType", handle.reuse_type(), |
@@ -1700,7 +1613,7 @@ |
pending_auth_target_ = HttpAuth::AUTH_NONE; |
read_buf_ = NULL; |
read_buf_len_ = 0; |
- http_stream_.reset(); |
+ stream_.reset(); |
headers_valid_ = false; |
request_headers_.clear(); |
response_ = HttpResponseInfo(); |
@@ -1711,8 +1624,9 @@ |
} |
bool HttpNetworkTransaction::ShouldResendRequest(int error) const { |
- if (using_spdy_ && spdy_http_stream_ != NULL) |
- return spdy_http_stream_->ShouldResendFailedRequest(error); |
+ if (using_spdy_ && stream_ != NULL) |
+ return static_cast<SpdyHttpStream *>(stream_.get())-> |
+ ShouldResendFailedRequest(error); |
// NOTE: we resend a request only if we reused a keep-alive connection. |
// This automatically prevents an infinite resend loop because we'll run |
@@ -1739,7 +1653,7 @@ |
// headers, but we may need to resend the CONNECT request first to recreate |
// the SSL tunnel. |
- spdy_http_stream_.reset(NULL); |
+ stream_.reset(NULL); |
request_headers_.clear(); |
next_state_ = STATE_INIT_CONNECTION; // Resend the request. |
@@ -1888,6 +1802,8 @@ |
STATE_CASE(STATE_RESOLVE_PROXY_COMPLETE); |
STATE_CASE(STATE_INIT_CONNECTION); |
STATE_CASE(STATE_INIT_CONNECTION_COMPLETE); |
+ STATE_CASE(STATE_INIT_STREAM); |
+ STATE_CASE(STATE_INIT_STREAM_COMPLETE); |
STATE_CASE(STATE_GENERATE_PROXY_AUTH_TOKEN); |
STATE_CASE(STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE); |
STATE_CASE(STATE_GENERATE_SERVER_AUTH_TOKEN); |
@@ -1900,14 +1816,6 @@ |
STATE_CASE(STATE_READ_BODY_COMPLETE); |
STATE_CASE(STATE_DRAIN_BODY_FOR_AUTH_RESTART); |
STATE_CASE(STATE_DRAIN_BODY_FOR_AUTH_RESTART_COMPLETE); |
- STATE_CASE(STATE_SPDY_GET_STREAM); |
- STATE_CASE(STATE_SPDY_GET_STREAM_COMPLETE); |
- STATE_CASE(STATE_SPDY_SEND_REQUEST); |
- STATE_CASE(STATE_SPDY_SEND_REQUEST_COMPLETE); |
- STATE_CASE(STATE_SPDY_READ_HEADERS); |
- STATE_CASE(STATE_SPDY_READ_HEADERS_COMPLETE); |
- STATE_CASE(STATE_SPDY_READ_BODY); |
- STATE_CASE(STATE_SPDY_READ_BODY_COMPLETE); |
STATE_CASE(STATE_NONE); |
default: |
description = StringPrintf("Unknown state 0x%08X (%u)", state, state); |