Index: net/http/http_network_transaction.cc |
=================================================================== |
--- net/http/http_network_transaction.cc (revision 14682) |
+++ net/http/http_network_transaction.cc (working copy) |
@@ -31,6 +31,10 @@ |
namespace net { |
+void HttpNetworkTransaction::ResponseHeaders::Realloc(size_t new_size) { |
+ headers_.reset(static_cast<char*>(realloc(headers_.release(), new_size))); |
+} |
+ |
//----------------------------------------------------------------------------- |
HttpNetworkTransaction::HttpNetworkTransaction(HttpNetworkSession* session, |
@@ -50,7 +54,9 @@ |
using_tunnel_(false), |
establishing_tunnel_(false), |
reading_body_from_socket_(false), |
+ request_headers_(new RequestHeaders()), |
request_headers_bytes_sent_(0), |
+ header_buf_(new ResponseHeaders()), |
header_buf_capacity_(0), |
header_buf_len_(0), |
header_buf_body_offset_(-1), |
@@ -298,29 +304,31 @@ |
HttpUtil::SpecForRequest(request_->url) : |
HttpUtil::PathForRequest(request_->url); |
- request_headers_ = request_->method + " " + path + |
+ request_headers_->headers_ = request_->method + " " + path + |
" HTTP/1.1\r\nHost: " + request_->url.host(); |
if (request_->url.IntPort() != -1) |
- request_headers_ += ":" + request_->url.port(); |
- request_headers_ += "\r\n"; |
+ request_headers_->headers_ += ":" + request_->url.port(); |
+ request_headers_->headers_ += "\r\n"; |
// For compat with HTTP/1.0 servers and proxies: |
if (using_proxy_) |
- request_headers_ += "Proxy-"; |
- request_headers_ += "Connection: keep-alive\r\n"; |
+ request_headers_->headers_ += "Proxy-"; |
+ request_headers_->headers_ += "Connection: keep-alive\r\n"; |
if (!request_->user_agent.empty()) |
- request_headers_ += "User-Agent: " + request_->user_agent + "\r\n"; |
+ request_headers_->headers_ += "User-Agent: " + request_->user_agent + |
+ "\r\n"; |
// Our consumer should have made sure that this is a safe referrer. See for |
// instance WebCore::FrameLoader::HideReferrer. |
if (request_->referrer.is_valid()) |
- request_headers_ += "Referer: " + request_->referrer.spec() + "\r\n"; |
+ request_headers_->headers_ += "Referer: " + request_->referrer.spec() + |
+ "\r\n"; |
// Add a content length header? |
if (request_->upload_data) { |
request_body_stream_.reset(new UploadDataStream(request_->upload_data)); |
- request_headers_ += |
+ request_headers_->headers_ += |
"Content-Length: " + Uint64ToString(request_body_stream_->size()) + |
"\r\n"; |
} else if (request_->method == "POST" || request_->method == "PUT" || |
@@ -329,22 +337,23 @@ |
// IE and Safari also add a content length header. Presumably it is to |
// support sending a HEAD request to an URL that only expects to be sent a |
// POST or some other method that normally would have a message body. |
- request_headers_ += "Content-Length: 0\r\n"; |
+ request_headers_->headers_ += "Content-Length: 0\r\n"; |
} |
// Honor load flags that impact proxy caches. |
if (request_->load_flags & LOAD_BYPASS_CACHE) { |
- request_headers_ += "Pragma: no-cache\r\nCache-Control: no-cache\r\n"; |
+ request_headers_->headers_ += |
+ "Pragma: no-cache\r\nCache-Control: no-cache\r\n"; |
} else if (request_->load_flags & LOAD_VALIDATE_CACHE) { |
- request_headers_ += "Cache-Control: max-age=0\r\n"; |
+ request_headers_->headers_ += "Cache-Control: max-age=0\r\n"; |
} |
ApplyAuth(); |
// TODO(darin): Need to prune out duplicate headers. |
- request_headers_ += request_->extra_headers; |
- request_headers_ += "\r\n"; |
+ request_headers_->headers_ += request_->extra_headers; |
+ request_headers_->headers_ += "\r\n"; |
} |
// The HTTP CONNECT method for establishing a tunnel connection is documented |
@@ -353,19 +362,20 @@ |
void HttpNetworkTransaction::BuildTunnelRequest() { |
// RFC 2616 Section 9 says the Host request-header field MUST accompany all |
// HTTP/1.1 requests. |
- request_headers_ = StringPrintf("CONNECT %s:%d HTTP/1.1\r\n", |
+ request_headers_->headers_ = StringPrintf("CONNECT %s:%d HTTP/1.1\r\n", |
request_->url.host().c_str(), request_->url.EffectiveIntPort()); |
- request_headers_ += "Host: " + request_->url.host(); |
+ request_headers_->headers_ += "Host: " + request_->url.host(); |
if (request_->url.has_port()) |
- request_headers_ += ":" + request_->url.port(); |
- request_headers_ += "\r\n"; |
+ request_headers_->headers_ += ":" + request_->url.port(); |
+ request_headers_->headers_ += "\r\n"; |
if (!request_->user_agent.empty()) |
- request_headers_ += "User-Agent: " + request_->user_agent + "\r\n"; |
+ request_headers_->headers_ += "User-Agent: " + request_->user_agent + |
+ "\r\n"; |
ApplyAuth(); |
- request_headers_ += "\r\n"; |
+ request_headers_->headers_ += "\r\n"; |
} |
void HttpNetworkTransaction::DoCallback(int rv) { |
@@ -654,7 +664,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_->headers_.empty()) { |
if (establishing_tunnel_) { |
BuildTunnelRequest(); |
} else { |
@@ -668,12 +678,12 @@ |
response_.request_time = Time::Now(); |
} |
- const char* buf = request_headers_.data() + request_headers_bytes_sent_; |
- int buf_len = static_cast<int>(request_headers_.size() - |
+ request_headers_->SetDataOffset(request_headers_bytes_sent_); |
+ int buf_len = static_cast<int>(request_headers_->headers_.size() - |
request_headers_bytes_sent_); |
DCHECK(buf_len > 0); |
- return connection_.socket()->Write(buf, buf_len, &io_callback_); |
+ return connection_.socket()->Write(request_headers_, buf_len, &io_callback_); |
} |
int HttpNetworkTransaction::DoWriteHeadersComplete(int result) { |
@@ -681,7 +691,7 @@ |
return HandleIOError(result); |
request_headers_bytes_sent_ += result; |
- if (request_headers_bytes_sent_ < request_headers_.size()) { |
+ if (request_headers_bytes_sent_ < request_headers_->headers_.size()) { |
next_state_ = STATE_WRITE_HEADERS; |
} else if (!establishing_tunnel_ && request_body_stream_.get() && |
request_body_stream_->size()) { |
@@ -700,11 +710,17 @@ |
const char* buf = request_body_stream_->buf(); |
int buf_len = static_cast<int>(request_body_stream_->buf_len()); |
+ DCHECK(!write_buffer_); |
+ write_buffer_ = new IOBuffer(buf_len); |
+ memcpy(write_buffer_->data(), buf, buf_len); |
- return connection_.socket()->Write(buf, buf_len, &io_callback_); |
+ return connection_.socket()->Write(write_buffer_, buf_len, &io_callback_); |
} |
int HttpNetworkTransaction::DoWriteBodyComplete(int result) { |
+ DCHECK(write_buffer_); |
+ write_buffer_ = NULL; |
+ |
if (result < 0) |
return HandleIOError(result); |
@@ -724,14 +740,13 @@ |
// Grow the read buffer if necessary. |
if (header_buf_len_ == header_buf_capacity_) { |
header_buf_capacity_ += kHeaderBufInitialSize; |
- header_buf_.reset(static_cast<char*>( |
- realloc(header_buf_.release(), header_buf_capacity_))); |
+ header_buf_->Realloc(header_buf_capacity_); |
} |
- char* buf = header_buf_.get() + header_buf_len_; |
int buf_len = header_buf_capacity_ - header_buf_len_; |
+ header_buf_->set_data(header_buf_len_); |
- return connection_.socket()->Read(buf, buf_len, &io_callback_); |
+ return connection_.socket()->Read(header_buf_, buf_len, &io_callback_); |
} |
int HttpNetworkTransaction::HandleConnectionClosedBeforeEndOfHeaders() { |
@@ -792,12 +807,12 @@ |
// Look for the start of the status line, if it hasn't been found yet. |
if (!has_found_status_line_start()) { |
header_buf_http_offset_ = HttpUtil::LocateStartOfStatusLine( |
- header_buf_.get(), header_buf_len_); |
+ header_buf_->headers(), header_buf_len_); |
} |
if (has_found_status_line_start()) { |
int eoh = HttpUtil::LocateEndOfHeaders( |
- header_buf_.get(), header_buf_len_, header_buf_http_offset_); |
+ header_buf_->headers(), header_buf_len_, header_buf_http_offset_); |
if (eoh == -1) { |
// Prevent growing the headers buffer indefinitely. |
if (header_buf_len_ >= kMaxHeaderBufSize) |
@@ -836,12 +851,13 @@ |
return 0; |
// We may have some data remaining in the header buffer. |
- if (header_buf_.get() && header_buf_body_offset_ < header_buf_len_) { |
+ if (header_buf_->headers() && header_buf_body_offset_ < header_buf_len_) { |
int n = std::min(read_buf_len_, header_buf_len_ - header_buf_body_offset_); |
- memcpy(read_buf_->data(), header_buf_.get() + header_buf_body_offset_, n); |
+ memcpy(read_buf_->data(), header_buf_->headers() + header_buf_body_offset_, |
+ n); |
header_buf_body_offset_ += n; |
if (header_buf_body_offset_ == header_buf_len_) { |
- header_buf_.reset(); |
+ header_buf_->Reset(); |
header_buf_capacity_ = 0; |
header_buf_len_ = 0; |
header_buf_body_offset_ = -1; |
@@ -850,8 +866,7 @@ |
} |
reading_body_from_socket_ = true; |
- return connection_.socket()->Read(read_buf_->data(), read_buf_len_, |
- &io_callback_); |
+ return connection_.socket()->Read(read_buf_, read_buf_len_, &io_callback_); |
} |
int HttpNetworkTransaction::DoReadBodyComplete(int result) { |
@@ -1059,7 +1074,7 @@ |
if (has_found_status_line_start()) { |
headers = new HttpResponseHeaders( |
HttpUtil::AssembleRawHeaders( |
- header_buf_.get(), header_buf_body_offset_)); |
+ header_buf_->headers(), header_buf_body_offset_)); |
} else { |
// Fabricate a status line to to preserve the HTTP/0.9 version. |
// (otherwise HttpResponseHeaders will default it to HTTP/1.0). |
@@ -1087,7 +1102,7 @@ |
} |
next_state_ = STATE_SSL_CONNECT; |
// Reset for the real request and response headers. |
- request_headers_.clear(); |
+ request_headers_->headers_.clear(); |
request_headers_bytes_sent_ = 0; |
header_buf_len_ = 0; |
header_buf_body_offset_ = 0; |
@@ -1127,7 +1142,8 @@ |
// If we've already received some bytes after the 1xx response, |
// move them to the beginning of header_buf_. |
if (header_buf_len_) { |
- memmove(header_buf_.get(), header_buf_.get() + header_buf_body_offset_, |
+ memmove(header_buf_->headers(), |
+ header_buf_->headers() + header_buf_body_offset_, |
header_buf_len_); |
} |
header_buf_body_offset_ = -1; |
@@ -1266,7 +1282,7 @@ |
void HttpNetworkTransaction::ResetStateForRestart() { |
pending_auth_target_ = HttpAuth::AUTH_NONE; |
- header_buf_.reset(); |
+ header_buf_->Reset(); |
header_buf_capacity_ = 0; |
header_buf_len_ = 0; |
header_buf_body_offset_ = -1; |
@@ -1275,7 +1291,7 @@ |
response_body_read_ = 0; |
read_buf_ = NULL; |
read_buf_len_ = 0; |
- request_headers_.clear(); |
+ request_headers_->headers_.clear(); |
request_headers_bytes_sent_ = 0; |
chunked_decoder_.reset(); |
// Reset all the members of response_. |
@@ -1298,7 +1314,7 @@ |
// first to recreate the SSL tunnel. 2) An empty request_headers_ causes |
// BuildRequestHeaders to be called, which rewinds request_body_stream_ to |
// the beginning of request_->upload_data. |
- request_headers_.clear(); |
+ request_headers_->headers_.clear(); |
request_headers_bytes_sent_ = 0; |
next_state_ = STATE_INIT_CONNECTION; // Resend the request. |
return true; |
@@ -1362,7 +1378,7 @@ |
auth_identity_[target].password, |
request_, |
&proxy_info_); |
- request_headers_ += HttpAuth::GetAuthorizationHeaderName(target) + |
+ request_headers_->headers_ += HttpAuth::GetAuthorizationHeaderName(target) + |
": " + credentials + "\r\n"; |
} |