summaryrefslogtreecommitdiffstats
path: root/net/http
diff options
context:
space:
mode:
authorrvargas@google.com <rvargas@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-04-30 21:51:25 +0000
committerrvargas@google.com <rvargas@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-04-30 21:51:25 +0000
commitffeb088e92325536ac1c371df3c4bd857ccb1221 (patch)
treeaf34055a796ac8181e3d90b838a02fcaf960ce26 /net/http
parentb57d5cc9dd98fc4fb284878ecc73e2eb95f6d1bd (diff)
downloadchromium_src-ffeb088e92325536ac1c371df3c4bd857ccb1221.zip
chromium_src-ffeb088e92325536ac1c371df3c4bd857ccb1221.tar.gz
chromium_src-ffeb088e92325536ac1c371df3c4bd857ccb1221.tar.bz2
Extend the use of IOBuffers to the code underneath
HttpNetworkTransaction (to the Socket class). This is the first step to remove the blocking call on the destructor of the network transaction, from IO thread. BUG=9258 R=wtc Review URL: http://codereview.chromium.org/87073 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@14998 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/http')
-rw-r--r--net/http/http_network_transaction.cc69
-rw-r--r--net/http/http_network_transaction.h37
-rw-r--r--net/http/http_network_transaction_unittest.cc24
3 files changed, 87 insertions, 43 deletions
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc
index f4fefcc4..e059d97 100644
--- a/net/http/http_network_transaction.cc
+++ b/net/http/http_network_transaction.cc
@@ -31,6 +31,10 @@ using base::Time;
namespace net {
+void HttpNetworkTransaction::ResponseHeaders::Realloc(size_t new_size) {
+ headers_.reset(static_cast<char*>(realloc(headers_.release(), new_size)));
+}
+
namespace {
void BuildRequestHeaders(const HttpRequestInfo* request_info,
@@ -142,7 +146,9 @@ HttpNetworkTransaction::HttpNetworkTransaction(HttpNetworkSession* session,
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),
@@ -671,7 +677,7 @@ int HttpNetworkTransaction::DoWriteHeaders() {
// 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()) {
// Figure out if we can/should add Proxy-Authentication & Authentication
// headers.
bool have_proxy_auth =
@@ -693,15 +699,14 @@ int HttpNetworkTransaction::DoWriteHeaders() {
BuildAuthorizationHeader(HttpAuth::AUTH_SERVER));
if (establishing_tunnel_) {
- BuildTunnelRequest(request_, authorization_headers, &request_headers_);
+ BuildTunnelRequest(request_, authorization_headers,
+ &request_headers_->headers_);
} else {
if (request_->upload_data)
request_body_stream_.reset(new UploadDataStream(request_->upload_data));
- BuildRequestHeaders(request_,
- authorization_headers,
- request_body_stream_.get(),
- using_proxy_,
- &request_headers_);
+ BuildRequestHeaders(request_, authorization_headers,
+ request_body_stream_.get(), using_proxy_,
+ &request_headers_->headers_);
}
}
@@ -711,12 +716,12 @@ int HttpNetworkTransaction::DoWriteHeaders() {
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_GT(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) {
@@ -724,7 +729,7 @@ int HttpNetworkTransaction::DoWriteHeadersComplete(int result) {
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()) {
@@ -743,11 +748,17 @@ int HttpNetworkTransaction::DoWriteBody() {
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);
@@ -767,14 +778,13 @@ int HttpNetworkTransaction::DoReadHeaders() {
// 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() {
@@ -837,12 +847,12 @@ int HttpNetworkTransaction::DoReadHeadersComplete(int result) {
// 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)
@@ -881,12 +891,13 @@ int HttpNetworkTransaction::DoReadBody() {
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;
@@ -895,8 +906,7 @@ int HttpNetworkTransaction::DoReadBody() {
}
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) {
@@ -1120,7 +1130,7 @@ int HttpNetworkTransaction::DidReadResponseHeaders() {
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).
@@ -1148,7 +1158,7 @@ int HttpNetworkTransaction::DidReadResponseHeaders() {
}
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;
@@ -1188,7 +1198,8 @@ int HttpNetworkTransaction::DidReadResponseHeaders() {
// 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;
@@ -1329,7 +1340,7 @@ int HttpNetworkTransaction::HandleIOError(int error) {
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;
@@ -1338,7 +1349,7 @@ void HttpNetworkTransaction::ResetStateForRestart() {
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_.
@@ -1365,7 +1376,7 @@ void HttpNetworkTransaction::ResetConnectionAndRequestForResend() {
// 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.
}
diff --git a/net/http/http_network_transaction.h b/net/http/http_network_transaction.h
index d3a6f49..9ba9cc0 100644
--- a/net/http/http_network_transaction.h
+++ b/net/http/http_network_transaction.h
@@ -55,6 +55,38 @@ class HttpNetworkTransaction : public HttpTransaction {
private:
FRIEND_TEST(HttpNetworkTransactionTest, ResetStateForRestart);
+ // This version of IOBuffer lets us use a string as the real storage and
+ // "move" the data pointer inside the string before using it to do actual IO.
+ class RequestHeaders : public net::IOBuffer {
+ public:
+ RequestHeaders() : net::IOBuffer() {}
+ ~RequestHeaders() { data_ = NULL; }
+
+ void SetDataOffset(size_t offset) {
+ data_ = const_cast<char*>(headers_.data()) + offset;
+ }
+
+ // This is intentionally a public member.
+ std::string headers_;
+ };
+
+ // This version of IOBuffer lets us use a malloc'ed buffer as the real storage
+ // and "move" the data pointer inside the buffer before using it to do actual
+ // IO.
+ class ResponseHeaders : public net::IOBuffer {
+ public:
+ ResponseHeaders() : net::IOBuffer() {}
+ ~ResponseHeaders() { data_ = NULL; }
+
+ void set_data(size_t offset) { data_ = headers_.get() + offset; }
+ char* headers() { return headers_.get(); }
+ void Reset() { headers_.reset(); }
+ void Realloc(size_t new_size);
+
+ private:
+ scoped_ptr_malloc<char> headers_;
+ };
+
void DoCallback(int result);
void OnIOComplete(int result);
@@ -276,15 +308,16 @@ class HttpNetworkTransaction : public HttpTransaction {
SSLConfig ssl_config_;
- std::string request_headers_;
+ scoped_refptr<RequestHeaders> request_headers_;
size_t request_headers_bytes_sent_;
scoped_ptr<UploadDataStream> request_body_stream_;
+ scoped_refptr<IOBuffer> write_buffer_;
// The read buffer may be larger than it is full. The 'capacity' indicates
// the allocation size of the buffer, and the 'len' indicates how much data
// is in the buffer already. The 'body offset' indicates the offset of the
// start of the response body within the read buffer.
- scoped_ptr_malloc<char> header_buf_;
+ scoped_refptr<ResponseHeaders> header_buf_;
int header_buf_capacity_;
int header_buf_len_;
int header_buf_body_offset_;
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc
index f6c3fa2..514ee38 100644
--- a/net/http/http_network_transaction_unittest.cc
+++ b/net/http/http_network_transaction_unittest.cc
@@ -118,9 +118,9 @@ class MockClientSocket : public SSLClientSocket {
return connected_;
}
// Socket methods:
- virtual int Read(char* buf, int buf_len,
+ virtual int Read(IOBuffer* buf, int buf_len,
CompletionCallback* callback) = 0;
- virtual int Write(const char* buf, int buf_len,
+ virtual int Write(IOBuffer* buf, int buf_len,
CompletionCallback* callback) = 0;
#if defined(OS_LINUX)
@@ -175,14 +175,14 @@ class MockTCPClientSocket : public MockClientSocket {
}
// Socket methods:
- virtual int Read(char* buf, int buf_len, CompletionCallback* callback) {
+ virtual int Read(IOBuffer* buf, int buf_len, CompletionCallback* callback) {
DCHECK(!callback_);
MockRead& r = data_->reads[read_index_];
int result = r.result;
if (r.data) {
if (r.data_len - read_offset_ > 0) {
result = std::min(buf_len, r.data_len - read_offset_);
- memcpy(buf, r.data + read_offset_, result);
+ memcpy(buf->data(), r.data + read_offset_, result);
read_offset_ += result;
if (read_offset_ == r.data_len) {
read_index_++;
@@ -199,7 +199,7 @@ class MockTCPClientSocket : public MockClientSocket {
return result;
}
- virtual int Write(const char* buf, int buf_len,
+ virtual int Write(IOBuffer* buf, int buf_len,
CompletionCallback* callback) {
DCHECK(buf);
DCHECK(buf_len > 0);
@@ -214,7 +214,7 @@ class MockTCPClientSocket : public MockClientSocket {
int result = w.result;
if (w.data) {
std::string expected_data(w.data, w.data_len);
- std::string actual_data(buf, buf_len);
+ std::string actual_data(buf->data(), buf_len);
EXPECT_EQ(expected_data, actual_data);
if (expected_data != actual_data)
return ERR_UNEXPECTED;
@@ -307,12 +307,12 @@ class MockSSLClientSocket : public MockClientSocket {
}
// Socket methods:
- virtual int Read(char* buf, int buf_len, CompletionCallback* callback) {
+ virtual int Read(IOBuffer* buf, int buf_len, CompletionCallback* callback) {
DCHECK(!callback_);
return transport_->Read(buf, buf_len, callback);
}
- virtual int Write(const char* buf, int buf_len,
+ virtual int Write(IOBuffer* buf, int buf_len,
CompletionCallback* callback) {
DCHECK(!callback_);
return transport_->Write(buf, buf_len, callback);
@@ -2912,7 +2912,7 @@ TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
CreateSession(proxy_service.get()), &mock_socket_factory));
// Setup some state (which we expect ResetStateForRestart() will clear).
- trans->header_buf_.reset(static_cast<char*>(malloc(10)));
+ trans->header_buf_->Realloc(10);
trans->header_buf_capacity_ = 10;
trans->header_buf_len_ = 3;
trans->header_buf_body_offset_ = 11;
@@ -2921,7 +2921,7 @@ TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
trans->response_body_read_ = 1;
trans->read_buf_ = new IOBuffer(15);
trans->read_buf_len_ = 15;
- trans->request_headers_ = "Authorization: NTLM";
+ trans->request_headers_->headers_ = "Authorization: NTLM";
trans->request_headers_bytes_sent_ = 3;
// Setup state in response_
@@ -2943,7 +2943,7 @@ TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
trans->ResetStateForRestart();
// Verify that the state that needed to be reset, has been reset.
- EXPECT_EQ(NULL, trans->header_buf_.get());
+ EXPECT_EQ(NULL, trans->header_buf_->headers());
EXPECT_EQ(0, trans->header_buf_capacity_);
EXPECT_EQ(0, trans->header_buf_len_);
EXPECT_EQ(-1, trans->header_buf_body_offset_);
@@ -2952,7 +2952,7 @@ TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
EXPECT_EQ(0, trans->response_body_read_);
EXPECT_EQ(NULL, trans->read_buf_.get());
EXPECT_EQ(0, trans->read_buf_len_);
- EXPECT_EQ("", trans->request_headers_);
+ EXPECT_EQ("", trans->request_headers_->headers_);
EXPECT_EQ(0U, trans->request_headers_bytes_sent_);
EXPECT_EQ(NULL, trans->response_.auth_challenge.get());
EXPECT_EQ(NULL, trans->response_.headers.get());