diff options
author | satish@chromium.org <satish@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-04 08:58:37 +0000 |
---|---|---|
committer | satish@chromium.org <satish@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-04 08:58:37 +0000 |
commit | 66ca8387165faa63b999b3d3080626cb4d8388b5 (patch) | |
tree | f3f33773a2c2a7814e54297eb30bb62e9fc65355 | |
parent | 02c89fbf01c7c7decffcb109220a400863798f0f (diff) | |
download | chromium_src-66ca8387165faa63b999b3d3080626cb4d8388b5.zip chromium_src-66ca8387165faa63b999b3d3080626cb4d8388b5.tar.gz chromium_src-66ca8387165faa63b999b3d3080626cb4d8388b5.tar.bz2 |
Revert "Add chunked uploads support to SPDY"
This reverts commit 8431a6e7be70b1b50b0d5b851bbe728b7fef220f.
TBR=satish
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@76896 0039d316-1c4b-4281-b951-d872f2087c98
24 files changed, 89 insertions, 371 deletions
diff --git a/chrome/common/net/url_fetcher.cc b/chrome/common/net/url_fetcher.cc index 5e5e910..30c18fb 100644 --- a/chrome/common/net/url_fetcher.cc +++ b/chrome/common/net/url_fetcher.cc @@ -101,12 +101,11 @@ class URLFetcher::Core // |original_url_| and |url_|. base::TimeTicks GetBackoffReleaseTime(); - void CompleteAddingUploadDataChunk(const std::string& data, - bool is_last_chunk); + void CompleteAddingUploadDataChunk(const std::string& data); // Adds a block of data to be uploaded in a POST body. This can only be called // after Start(). - void AppendChunkToUpload(const std::string& data, bool is_last_chunk); + void AppendChunkToUpload(const std::string& data); URLFetcher* fetcher_; // Corresponding fetcher object GURL original_url_; // The URL we were asked to fetch @@ -292,23 +291,23 @@ void URLFetcher::Core::OnResponseStarted(net::URLRequest* request) { } void URLFetcher::Core::CompleteAddingUploadDataChunk( - const std::string& content, bool is_last_chunk) { + const std::string& content) { DCHECK(is_chunked_upload_); DCHECK(request_.get()); - DCHECK(!content.empty()); - request_->AppendChunkToUpload(content.data(), - static_cast<int>(content.length()), - is_last_chunk); + if (content.length()) { + request_->AppendChunkToUpload(content.data(), + static_cast<int>(content.length())); + } else { + request_->MarkEndOfChunks(); + } } -void URLFetcher::Core::AppendChunkToUpload(const std::string& content, - bool is_last_chunk) { +void URLFetcher::Core::AppendChunkToUpload(const std::string& content) { DCHECK(delegate_loop_proxy_); CHECK(io_message_loop_proxy_.get()); io_message_loop_proxy_->PostTask( FROM_HERE, - NewRunnableMethod(this, &Core::CompleteAddingUploadDataChunk, content, - is_last_chunk)); + NewRunnableMethod(this, &Core::CompleteAddingUploadDataChunk, content)); } void URLFetcher::Core::OnReadCompleted(net::URLRequest* request, @@ -521,10 +520,13 @@ void URLFetcher::set_chunked_upload(const std::string& content_type) { core_->is_chunked_upload_ = true; } -void URLFetcher::AppendChunkToUpload(const std::string& data, - bool is_last_chunk) { +void URLFetcher::AppendChunkToUpload(const std::string& data) { DCHECK(data.length()); - core_->AppendChunkToUpload(data, is_last_chunk); + core_->AppendChunkToUpload(data); +} + +void URLFetcher::MarkEndOfChunks() { + core_->AppendChunkToUpload(std::string()); } const std::string& URLFetcher::upload_data() const { diff --git a/chrome/common/net/url_fetcher.h b/chrome/common/net/url_fetcher.h index e3e7eff..20f6ea7 100644 --- a/chrome/common/net/url_fetcher.h +++ b/chrome/common/net/url_fetcher.h @@ -140,7 +140,12 @@ class URLFetcher { // Adds the given bytes to a request's POST data transmitted using chunked // transfer encoding. // This method should be called ONLY after calling Start(). - void AppendChunkToUpload(const std::string& data, bool is_last_chunk); + void AppendChunkToUpload(const std::string& data); + + // Signals the end of a chunked transfer encoded data stream. This method + // should be called ONLY after calling Start(), set_chunked_upload() and + // typically one or more calls to AppendChunkToUpload. + void MarkEndOfChunks(); // Set one or more load flags as defined in net/base/load_flags.h. Must be // called before the request is started. diff --git a/net/base/upload_data.cc b/net/base/upload_data.cc index 4af308e..490029c 100644 --- a/net/base/upload_data.cc +++ b/net/base/upload_data.cc @@ -28,13 +28,16 @@ UploadData::Element::~Element() { delete file_stream_; } -void UploadData::Element::SetToChunk(const char* bytes, - int bytes_len, - bool is_last_chunk) { +void UploadData::Element::SetToChunk(const char* bytes, int bytes_len) { + std::string chunk_length = StringPrintf("%X\r\n", bytes_len); bytes_.clear(); + bytes_.insert(bytes_.end(), chunk_length.data(), + chunk_length.data() + chunk_length.length()); bytes_.insert(bytes_.end(), bytes, bytes + bytes_len); + const char* crlf = "\r\n"; + bytes_.insert(bytes_.end(), crlf, crlf + 2); type_ = TYPE_CHUNK; - is_last_chunk_ = is_last_chunk; + is_last_chunk_ = (bytes_len == 0); } uint64 UploadData::Element::GetContentLength() { @@ -143,12 +146,10 @@ void UploadData::AppendBlob(const GURL& blob_url) { elements_.back().SetToBlobUrl(blob_url); } -void UploadData::AppendChunk(const char* bytes, - int bytes_len, - bool is_last_chunk) { +void UploadData::AppendChunk(const char* bytes, int bytes_len) { DCHECK(is_chunked_); elements_.push_back(Element()); - elements_.back().SetToChunk(bytes, bytes_len, is_last_chunk); + elements_.back().SetToChunk(bytes, bytes_len); if (chunk_callback_) chunk_callback_->OnChunkAvailable(); } diff --git a/net/base/upload_data.h b/net/base/upload_data.h index b9cc864..e746f65 100644 --- a/net/base/upload_data.h +++ b/net/base/upload_data.h @@ -96,7 +96,7 @@ class UploadData : public base::RefCounted<UploadData> { // Though similar to bytes, a chunk indicates that the element is sent via // chunked transfer encoding and not buffered until the full upload data // is available. - void SetToChunk(const char* bytes, int bytes_len, bool is_last_chunk); + void SetToChunk(const char* bytes, int bytes_len); bool is_last_chunk() const { return is_last_chunk_; } // Sets whether this is the last chunk. Used during IPC marshalling. @@ -153,8 +153,8 @@ class UploadData : public base::RefCounted<UploadData> { void AppendBlob(const GURL& blob_url); // Adds the given chunk of bytes to be sent immediately with chunked transfer - // encoding. - void AppendChunk(const char* bytes, int bytes_len, bool is_last_chunk); + // encoding. Set bytes_len to zero for the last chunk. + void AppendChunk(const char* bytes, int bytes_len); // Sets the callback to be invoked when a new chunk is available to upload. void set_chunk_callback(ChunkCallback* callback); diff --git a/net/base/upload_data_stream.cc b/net/base/upload_data_stream.cc index 4a056f4..9f7bdbb 100644 --- a/net/base/upload_data_stream.cc +++ b/net/base/upload_data_stream.cc @@ -12,8 +12,6 @@ namespace net { -bool UploadDataStream::merge_chunks_ = true; - UploadDataStream::~UploadDataStream() { } @@ -71,13 +69,8 @@ int UploadDataStream::FillBuf() { size_t bytes_copied = std::min(count, size_remaining); - // Check if we have anything to copy first, because we are getting the - // address of an element in |d| and that will throw an exception if |d| - // is an empty vector. - if (bytes_copied) { - memcpy(buf_->data() + buf_len_, &d[next_element_offset_], bytes_copied); - buf_len_ += bytes_copied; - } + memcpy(buf_->data() + buf_len_, &d[next_element_offset_], bytes_copied); + buf_len_ += bytes_copied; if (bytes_copied == count) { advance_to_next_element = true; @@ -133,9 +126,6 @@ int UploadDataStream::FillBuf() { next_element_remaining_ = 0; next_element_stream_.reset(); } - - if (is_chunked() && !merge_chunks_) - break; } if (next_element_ == elements.size() && !buf_len_) { @@ -148,13 +138,4 @@ int UploadDataStream::FillBuf() { return OK; } -bool UploadDataStream::IsOnLastChunk() const { - const std::vector<UploadData::Element>& elements = *data_->elements(); - DCHECK(data_->is_chunked()); - return (eof_ || - (!elements.empty() && - next_element_ == elements.size() && - elements.back().is_last_chunk())); -} - } // namespace net diff --git a/net/base/upload_data_stream.h b/net/base/upload_data_stream.h index decc3f6..f291140 100644 --- a/net/base/upload_data_stream.h +++ b/net/base/upload_data_stream.h @@ -27,12 +27,6 @@ class UploadDataStream { IOBuffer* buf() const { return buf_; } size_t buf_len() const { return buf_len_; } - // TODO(satish): We should ideally have UploadDataStream expose a Read() - // method which returns data in a caller provided IOBuffer. That would do away - // with this method and make the interface cleaner as well with less memmove - // calls. - size_t GetMaxBufferSize() const { return kBufSize; } - // Call to indicate that a portion of the stream's buffer was consumed. This // call modifies the stream's buffer so that it contains the next segment of // the upload data to be consumed. @@ -56,16 +50,6 @@ class UploadDataStream { // position < size. bool eof() const { return eof_; } - // Returns whether the data available in buf() includes the last chunk in a - // chunked data stream. This method returns true once the final chunk has been - // placed in the IOBuffer returned by buf(), in contrast to eof() which - // returns true only after the data in buf() has been consumed. - bool IsOnLastChunk() const; - -#if defined(UNIT_TEST) - static void set_merge_chunks(bool merge) { merge_chunks_ = merge; } -#endif - private: enum { kBufSize = 16384 }; @@ -109,10 +93,6 @@ class UploadDataStream { // Whether there is no data left to read. bool eof_; - // TODO(satish): Remove this once we have a better way to unit test POST - // requests with chunked uploads. - static bool merge_chunks_; - DISALLOW_COPY_AND_ASSIGN(UploadDataStream); }; diff --git a/net/http/http_stream_parser.cc b/net/http/http_stream_parser.cc index eb1ed35..6621f0b 100644 --- a/net/http/http_stream_parser.cc +++ b/net/http/http_stream_parser.cc @@ -6,7 +6,6 @@ #include "base/compiler_specific.h" #include "base/metrics/histogram.h" -#include "base/string_util.h" #include "net/base/address_list.h" #include "net/base/auth.h" #include "net/base/io_buffer.h" @@ -41,10 +40,7 @@ HttpStreamParser::HttpStreamParser(ClientSocketHandle* connection, connection_(connection), net_log_(net_log), ALLOW_THIS_IN_INITIALIZER_LIST( - io_callback_(this, &HttpStreamParser::OnIOComplete)), - chunk_length_(0), - chunk_length_without_encoding_(0), - sent_last_chunk_(false) { + io_callback_(this, &HttpStreamParser::OnIOComplete)) { DCHECK_EQ(0, read_buffer->offset()); } @@ -83,12 +79,8 @@ int HttpStreamParser::SendRequest(const std::string& request_line, request_headers_ = new DrainableIOBuffer(headers_io_buf, headers_io_buf->size()); request_body_.reset(request_body); - if (request_body_ != NULL && request_body_->is_chunked()) { + if (request_body_ != NULL && request_body_->is_chunked()) request_body_->set_chunk_callback(this); - const int kChunkHeaderFooterSize = 12; // 2 CRLFs + max of 8 hex chars. - chunk_buf_ = new IOBuffer(request_body_->GetMaxBufferSize() + - kChunkHeaderFooterSize); - } io_state_ = STATE_SENDING_HEADERS; result = DoLoop(OK); @@ -284,56 +276,17 @@ int HttpStreamParser::DoSendHeaders(int result) { } int HttpStreamParser::DoSendBody(int result) { - if (request_body_->is_chunked()) { - chunk_length_ -= result; - if (chunk_length_) { - memmove(chunk_buf_->data(), chunk_buf_->data() + result, chunk_length_); - return connection_->socket()->Write(chunk_buf_, chunk_length_, - &io_callback_); - } - - if (sent_last_chunk_) { - io_state_ = STATE_REQUEST_SENT; - return OK; - } - - request_body_->MarkConsumedAndFillBuffer(chunk_length_without_encoding_); - chunk_length_without_encoding_ = 0; - chunk_length_ = 0; - - int buf_len = static_cast<int>(request_body_->buf_len()); - if (request_body_->eof()) { - static const char kLastChunk[] = "0\r\n\r\n"; - chunk_length_ = strlen(kLastChunk); - memcpy(chunk_buf_->data(), kLastChunk, chunk_length_); - sent_last_chunk_ = true; - } else if (buf_len) { - // Encode and send the buffer as 1 chunk. - std::string chunk_header = StringPrintf("%X\r\n", buf_len); - char* chunk_ptr = chunk_buf_->data(); - memcpy(chunk_ptr, chunk_header.data(), chunk_header.length()); - chunk_ptr += chunk_header.length(); - memcpy(chunk_ptr, request_body_->buf()->data(), buf_len); - chunk_ptr += buf_len; - memcpy(chunk_ptr, "\r\n", 2); - chunk_length_without_encoding_ = buf_len; - chunk_length_ = chunk_header.length() + buf_len + 2; - } - - if (!chunk_length_) // More POST data is yet to come? - return ERR_IO_PENDING; - - return connection_->socket()->Write(chunk_buf_, chunk_length_, - &io_callback_); - } - - // Non-chunked request body. request_body_->MarkConsumedAndFillBuffer(result); if (!request_body_->eof()) { int buf_len = static_cast<int>(request_body_->buf_len()); - result = connection_->socket()->Write(request_body_->buf(), buf_len, - &io_callback_); + if (buf_len) { + result = connection_->socket()->Write(request_body_->buf(), buf_len, + &io_callback_); + } else { + // More POST data is to come hence wait for the callback. + result = ERR_IO_PENDING; + } } else { io_state_ = STATE_REQUEST_SENT; } diff --git a/net/http/http_stream_parser.h b/net/http/http_stream_parser.h index d9241a6..5f7e943 100644 --- a/net/http/http_stream_parser.h +++ b/net/http/http_stream_parser.h @@ -189,13 +189,6 @@ class HttpStreamParser : public ChunkCallback { // Callback to be used when doing IO. CompletionCallbackImpl<HttpStreamParser> io_callback_; - // Stores an encoded chunk for chunked uploads. - // Note: This should perhaps be improved to not create copies of the data. - scoped_refptr<IOBuffer> chunk_buf_; - size_t chunk_length_; - size_t chunk_length_without_encoding_; - bool sent_last_chunk_; - DISALLOW_COPY_AND_ASSIGN(HttpStreamParser); }; diff --git a/net/spdy/spdy_http_stream.cc b/net/spdy/spdy_http_stream.cc index 51a2efd..e07578e 100644 --- a/net/spdy/spdy_http_stream.cc +++ b/net/spdy/spdy_http_stream.cc @@ -177,11 +177,6 @@ void SpdyHttpStream::SetConnectionReused() { // SPDY doesn't need an indicator here. } -void SpdyHttpStream::set_chunk_callback(ChunkCallback* callback) { - if (request_body_stream_ != NULL) - request_body_stream_->set_chunk_callback(callback); -} - int SpdyHttpStream::SendRequest(const HttpRequestHeaders& request_headers, UploadDataStream* request_body, HttpResponseInfo* response, @@ -205,7 +200,7 @@ int SpdyHttpStream::SendRequest(const HttpRequestHeaders& request_headers, CHECK(!request_body_stream_.get()); if (request_body) { - if (request_body->size() || request_body->is_chunked()) + if (request_body->size()) request_body_stream_.reset(request_body); else delete request_body; @@ -269,33 +264,17 @@ bool SpdyHttpStream::OnSendHeadersComplete(int status) { int SpdyHttpStream::OnSendBody() { CHECK(request_body_stream_.get()); - int buf_len = static_cast<int>(request_body_stream_->buf_len()); if (!buf_len) return OK; - bool is_chunked = request_body_stream_->is_chunked(); - // TODO(satish): For non-chunked POST data, we set DATA_FLAG_FIN for all - // blocks of data written out. This is wrong if the POST data was larger than - // UploadDataStream::kBufSize as that is the largest buffer that - // UploadDataStream returns at a time and we'll be setting the FIN flag for - // each block of data written out. - bool eof = !is_chunked || request_body_stream_->IsOnLastChunk(); - return stream_->WriteStreamData( - request_body_stream_->buf(), buf_len, - eof ? spdy::DATA_FLAG_FIN : spdy::DATA_FLAG_NONE); + return stream_->WriteStreamData(request_body_stream_->buf(), buf_len, + spdy::DATA_FLAG_FIN); } -int SpdyHttpStream::OnSendBodyComplete(int status, bool* eof) { +bool SpdyHttpStream::OnSendBodyComplete(int status) { CHECK(request_body_stream_.get()); - request_body_stream_->MarkConsumedAndFillBuffer(status); - *eof = request_body_stream_->eof(); - if (!*eof && - request_body_stream_->is_chunked() && - !request_body_stream_->buf_len()) - return ERR_IO_PENDING; - - return OK; + return request_body_stream_->eof(); } int SpdyHttpStream::OnResponseReceived(const spdy::SpdyHeaderBlock& response, diff --git a/net/spdy/spdy_http_stream.h b/net/spdy/spdy_http_stream.h index bdae342..6e78379 100644 --- a/net/spdy/spdy_http_stream.h +++ b/net/spdy/spdy_http_stream.h @@ -69,14 +69,13 @@ class SpdyHttpStream : public SpdyStream::Delegate, public HttpStream { // SpdyStream::Delegate methods: virtual bool OnSendHeadersComplete(int status); virtual int OnSendBody(); - virtual int OnSendBodyComplete(int status, bool* eof); + virtual bool OnSendBodyComplete(int status); virtual int OnResponseReceived(const spdy::SpdyHeaderBlock& response, base::Time response_time, int status); virtual void OnDataReceived(const char* buffer, int bytes); virtual void OnDataSent(int length); virtual void OnClose(int status); - virtual void set_chunk_callback(ChunkCallback* callback); private: FRIEND_TEST_ALL_PREFIXES(SpdyNetworkTransactionTest, FlowControlStallResume); @@ -128,8 +127,6 @@ class SpdyHttpStream : public SpdyStream::Delegate, public HttpStream { // Is this spdy stream direct to the origin server (or to a proxy). bool direct_; - bool send_last_chunk_; - DISALLOW_COPY_AND_ASSIGN(SpdyHttpStream); }; diff --git a/net/spdy/spdy_http_stream_unittest.cc b/net/spdy/spdy_http_stream_unittest.cc index bee345a..1688871 100644 --- a/net/spdy/spdy_http_stream_unittest.cc +++ b/net/spdy/spdy_http_stream_unittest.cc @@ -93,69 +93,7 @@ TEST_F(SpdyHttpStreamTest, SendRequest) { // Because we abandoned the stream, we don't expect to find a session in the // pool anymore. - EXPECT_FALSE(http_session_->spdy_session_pool()->HasSession(pair)); - EXPECT_TRUE(data()->at_read_eof()); - EXPECT_TRUE(data()->at_write_eof()); -} - -TEST_F(SpdyHttpStreamTest, SendChunkedPost) { - EnableCompression(false); - SpdySession::SetSSLMode(false); - UploadDataStream::set_merge_chunks(false); - - scoped_ptr<spdy::SpdyFrame> req(ConstructChunkedSpdyPost(NULL, 0)); - scoped_ptr<spdy::SpdyFrame> chunk1(ConstructSpdyBodyFrame(1, false)); - scoped_ptr<spdy::SpdyFrame> chunk2(ConstructSpdyBodyFrame(1, true)); - MockWrite writes[] = { - CreateMockWrite(*req.get(), 1), - CreateMockWrite(*chunk1, 2), // POST upload frames - CreateMockWrite(*chunk2, 3), - }; - scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0)); - MockRead reads[] = { - CreateMockRead(*resp, 4), - CreateMockRead(*chunk1, 5), - CreateMockRead(*chunk2, 5), - MockRead(false, 0, 6) // EOF - }; - - HostPortPair host_port_pair("www.google.com", 80); - HostPortProxyPair pair(host_port_pair, ProxyServer::Direct()); - EXPECT_EQ(OK, InitSession(reads, arraysize(reads), writes, arraysize(writes), - host_port_pair)); - - HttpRequestInfo request; - request.method = "POST"; - request.url = GURL("http://www.google.com/"); - request.upload_data = new UploadData(); - request.upload_data->set_is_chunked(true); - request.upload_data->AppendChunk(kUploadData, kUploadDataSize, false); - request.upload_data->AppendChunk(kUploadData, kUploadDataSize, true); - TestCompletionCallback callback; - HttpResponseInfo response; - HttpRequestHeaders headers; - BoundNetLog net_log; - SpdyHttpStream http_stream(session_.get(), true); - ASSERT_EQ( - OK, - http_stream.InitializeStream(&request, net_log, NULL)); - - UploadDataStream* upload_stream = - UploadDataStream::Create(request.upload_data, NULL); - EXPECT_EQ(ERR_IO_PENDING, http_stream.SendRequest( - headers, upload_stream, &response, &callback)); - EXPECT_TRUE(http_session_->spdy_session_pool()->HasSession(pair)); - - // This triggers the MockWrite and read 2 - callback.WaitForResult(); - - // This triggers read 3. The empty read causes the session to shut down. - data()->CompleteRead(); - MessageLoop::current()->RunAllPending(); - - // Because we abandoned the stream, we don't expect to find a session in the - // pool anymore. - EXPECT_FALSE(http_session_->spdy_session_pool()->HasSession(pair)); + EXPECT_TRUE(!http_session_->spdy_session_pool()->HasSession(pair)); EXPECT_TRUE(data()->at_read_eof()); EXPECT_TRUE(data()->at_write_eof()); } @@ -213,7 +151,7 @@ TEST_F(SpdyHttpStreamTest, SpdyURLTest) { // Because we abandoned the stream, we don't expect to find a session in the // pool anymore. - EXPECT_FALSE(http_session_->spdy_session_pool()->HasSession(pair)); + EXPECT_TRUE(!http_session_->spdy_session_pool()->HasSession(pair)); EXPECT_TRUE(data()->at_read_eof()); EXPECT_TRUE(data()->at_write_eof()); } diff --git a/net/spdy/spdy_http_utils.cc b/net/spdy/spdy_http_utils.cc index a3b7e54..bf7376a 100644 --- a/net/spdy/spdy_http_utils.cc +++ b/net/spdy/spdy_http_utils.cc @@ -83,10 +83,8 @@ void CreateSpdyHeadersFromHttpRequest(const HttpRequestInfo& info, HttpRequestHeaders::Iterator it(request_headers); while (it.GetNext()) { std::string name = StringToLowerASCII(it.name()); - if (name == "connection" || name == "proxy-connection" || - name == "transfer-encoding") { + if (name == "connection" || name == "proxy-connection") continue; - } if (headers->find(name) == headers->end()) { (*headers)[name] = it.value(); } else { diff --git a/net/spdy/spdy_network_transaction_unittest.cc b/net/spdy/spdy_network_transaction_unittest.cc index 94ef61d..84e19d6 100644 --- a/net/spdy/spdy_network_transaction_unittest.cc +++ b/net/spdy/spdy_network_transaction_unittest.cc @@ -40,7 +40,6 @@ class SpdyNetworkTransactionTest EnableCompression(false); google_get_request_initialized_ = false; google_post_request_initialized_ = false; - google_chunked_post_request_initialized_ = false; } virtual void TearDown() { @@ -351,21 +350,6 @@ class SpdyNetworkTransactionTest return google_post_request_; } - const HttpRequestInfo& CreateChunkedPostRequest() { - if (!google_chunked_post_request_initialized_) { - google_chunked_post_request_.method = "POST"; - google_chunked_post_request_.url = GURL(kDefaultURL); - google_chunked_post_request_.upload_data = new UploadData(); - google_chunked_post_request_.upload_data->set_is_chunked(true); - google_chunked_post_request_.upload_data->AppendChunk( - kUploadData, kUploadDataSize, false); - google_chunked_post_request_.upload_data->AppendChunk( - kUploadData, kUploadDataSize, true); - google_chunked_post_request_initialized_ = true; - } - return google_chunked_post_request_; - } - // Read the result of a particular transaction, knowing that we've got // multiple transactions in the read pipeline; so as we read, we may have // to skip over data destined for other transactions while we consume @@ -470,10 +454,8 @@ class SpdyNetworkTransactionTest private: bool google_get_request_initialized_; bool google_post_request_initialized_; - bool google_chunked_post_request_initialized_; HttpRequestInfo google_get_request_; HttpRequestInfo google_post_request_; - HttpRequestInfo google_chunked_post_request_; HttpRequestInfo google_get_push_request_; }; @@ -1543,38 +1525,6 @@ TEST_P(SpdyNetworkTransactionTest, Post) { EXPECT_EQ("hello!", out.response_data); } -// Test that a chunked POST works. -TEST_P(SpdyNetworkTransactionTest, ChunkedPost) { - UploadDataStream::set_merge_chunks(false); - scoped_ptr<spdy::SpdyFrame> req(ConstructChunkedSpdyPost(NULL, 0)); - scoped_ptr<spdy::SpdyFrame> chunk1(ConstructSpdyBodyFrame(1, false)); - scoped_ptr<spdy::SpdyFrame> chunk2(ConstructSpdyBodyFrame(1, true)); - MockWrite writes[] = { - CreateMockWrite(*req), - CreateMockWrite(*chunk1), - CreateMockWrite(*chunk2), - }; - - scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0)); - MockRead reads[] = { - CreateMockRead(*resp), - CreateMockRead(*chunk1), - CreateMockRead(*chunk2), - MockRead(true, 0, 0) // EOF - }; - - scoped_refptr<DelayedSocketData> data( - new DelayedSocketData(2, reads, arraysize(reads), - writes, arraysize(writes))); - NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(), - BoundNetLog(), GetParam()); - helper.RunToCompletion(data.get()); - TransactionHelperResult out = helper.output(); - EXPECT_EQ(OK, out.rv); - EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); - EXPECT_EQ("hello!hello!", out.response_data); -} - // Test that a POST without any post data works. TEST_P(SpdyNetworkTransactionTest, NullPost) { // Setup the request diff --git a/net/spdy/spdy_proxy_client_socket.cc b/net/spdy/spdy_proxy_client_socket.cc index f451868..452ee3b 100644 --- a/net/spdy/spdy_proxy_client_socket.cc +++ b/net/spdy/spdy_proxy_client_socket.cc @@ -404,11 +404,11 @@ int SpdyProxyClientSocket::OnSendBody() { return ERR_UNEXPECTED; } -int SpdyProxyClientSocket::OnSendBodyComplete(int /*status*/, bool* /*eof*/) { +bool SpdyProxyClientSocket::OnSendBodyComplete(int status) { // Because we use |spdy_stream_| via STATE_OPEN (ala WebSockets) // OnSendBodyComplete() should never be called. NOTREACHED(); - return ERR_UNEXPECTED; + return false; } int SpdyProxyClientSocket::OnResponseReceived( @@ -498,7 +498,4 @@ void SpdyProxyClientSocket::OnClose(int status) { write_callback->Run(ERR_CONNECTION_CLOSED); } -void SpdyProxyClientSocket::set_chunk_callback(ChunkCallback* /*callback*/) { -} - } // namespace net diff --git a/net/spdy/spdy_proxy_client_socket.h b/net/spdy/spdy_proxy_client_socket.h index 69261d3..f66283e1 100644 --- a/net/spdy/spdy_proxy_client_socket.h +++ b/net/spdy/spdy_proxy_client_socket.h @@ -88,14 +88,13 @@ class SpdyProxyClientSocket : public ProxyClientSocket, // SpdyStream::Delegate methods: virtual bool OnSendHeadersComplete(int status); virtual int OnSendBody(); - virtual int OnSendBodyComplete(int status, bool* eof); + virtual bool OnSendBodyComplete(int status); virtual int OnResponseReceived(const spdy::SpdyHeaderBlock& response, base::Time response_time, int status); virtual void OnDataReceived(const char* data, int length); virtual void OnDataSent(int length); virtual void OnClose(int status); - virtual void set_chunk_callback(ChunkCallback* /*callback*/); private: enum State { diff --git a/net/spdy/spdy_session.cc b/net/spdy/spdy_session.cc index 9776aff..c268ee4 100644 --- a/net/spdy/spdy_session.cc +++ b/net/spdy/spdy_session.cc @@ -636,7 +636,7 @@ void SpdySession::OnWriteComplete(int result) { // size. if (result > 0) { result = in_flight_write_.buffer()->size(); - DCHECK_GE(result, static_cast<int>(spdy::SpdyFrame::size())); + DCHECK_GT(result, static_cast<int>(spdy::SpdyFrame::size())); result -= static_cast<int>(spdy::SpdyFrame::size()); } diff --git a/net/spdy/spdy_stream.cc b/net/spdy/spdy_stream.cc index e948b33..3900993 100644 --- a/net/spdy/spdy_stream.cc +++ b/net/spdy/spdy_stream.cc @@ -112,8 +112,6 @@ void SpdyStream::PushedStreamReplayData() { } void SpdyStream::DetachDelegate() { - if (delegate_) - delegate_->set_chunk_callback(NULL); delegate_ = NULL; if (!closed()) Cancel(); @@ -350,22 +348,13 @@ void SpdyStream::OnWriteComplete(int bytes) { DoLoop(bytes); } -void SpdyStream::OnChunkAvailable() { - DCHECK(io_state_ == STATE_SEND_HEADERS || io_state_ == STATE_SEND_BODY || - io_state_ == STATE_SEND_BODY_COMPLETE); - if (io_state_ == STATE_SEND_BODY) - OnWriteComplete(0); -} - void SpdyStream::OnClose(int status) { io_state_ = STATE_DONE; response_status_ = status; Delegate* delegate = delegate_; delegate_ = NULL; - if (delegate) { - delegate->set_chunk_callback(NULL); + if (delegate) delegate->OnClose(status); - } } void SpdyStream::Cancel() { @@ -378,9 +367,6 @@ void SpdyStream::Cancel() { } int SpdyStream::SendRequest(bool has_upload_data) { - if (delegate_) - delegate_->set_chunk_callback(this); - // Pushed streams do not send any data, and should always be in STATE_OPEN or // STATE_DONE. However, we still want to return IO_PENDING to mimic non-push // behavior. @@ -559,17 +545,17 @@ int SpdyStream::DoSendBodyComplete(int result) { if (result < 0) return result; + CHECK_NE(result, 0); + if (!delegate_) return ERR_UNEXPECTED; - bool eof = false; - result = delegate_->OnSendBodyComplete(result, &eof); - if (!eof) + if (!delegate_->OnSendBodyComplete(result)) io_state_ = STATE_SEND_BODY; else io_state_ = STATE_WAITING_FOR_RESPONSE; - return result; + return OK; } int SpdyStream::DoOpen(int result) { diff --git a/net/spdy/spdy_stream.h b/net/spdy/spdy_stream.h index 6d6b09c..9a055c2 100644 --- a/net/spdy/spdy_stream.h +++ b/net/spdy/spdy_stream.h @@ -16,7 +16,6 @@ #include "googleurl/src/gurl.h" #include "net/base/bandwidth_metrics.h" #include "net/base/io_buffer.h" -#include "net/base/upload_data.h" #include "net/base/net_log.h" #include "net/spdy/spdy_framer.h" #include "net/spdy/spdy_protocol.h" @@ -35,9 +34,7 @@ class SSLInfo; // a SpdyNetworkTransaction) will maintain a reference to the stream. When // initiated by the server, only the SpdySession will maintain any reference, // until such a time as a client object requests a stream for the path. -class SpdyStream - : public base::RefCounted<SpdyStream>, - public ChunkCallback { +class SpdyStream : public base::RefCounted<SpdyStream> { public: // Delegate handles protocol specific behavior of spdy stream. class Delegate { @@ -53,10 +50,9 @@ class SpdyStream virtual int OnSendBody() = 0; // Called when data has been sent. |status| indicates network error - // or number of bytes that has been sent. On return, |eof| is set to true - // if no more data is available to send in the request body. - // Returns network error code. OK when it successfully sent data. - virtual int OnSendBodyComplete(int status, bool* eof) = 0; + // or number of bytes has been sent. + // Returns true if no more data to be sent. + virtual bool OnSendBodyComplete(int status) = 0; // Called when the SYN_STREAM, SYN_REPLY, or HEADERS frames are received. // Normal streams will receive a SYN_REPLY and optional HEADERS frames. @@ -77,9 +73,6 @@ class SpdyStream // Called when SpdyStream is closed. virtual void OnClose(int status) = 0; - // Sets the callback to be invoked when a new chunk is available to upload. - virtual void set_chunk_callback(ChunkCallback* callback) = 0; - protected: friend class base::RefCounted<Delegate>; virtual ~Delegate() {} @@ -229,9 +222,6 @@ class SpdyStream // true. GURL GetUrl() const; - // ChunkCallback methods. - virtual void OnChunkAvailable(); - private: enum State { STATE_NONE, diff --git a/net/spdy/spdy_stream_unittest.cc b/net/spdy/spdy_stream_unittest.cc index a7b4fac..532c79f 100644 --- a/net/spdy/spdy_stream_unittest.cc +++ b/net/spdy/spdy_stream_unittest.cc @@ -51,9 +51,9 @@ class TestSpdyStreamDelegate : public SpdyStream::Delegate { ADD_FAILURE() << "OnSendBody should not be called"; return ERR_UNEXPECTED; } - virtual int OnSendBodyComplete(int /*status*/, bool* /*eof*/) { + virtual bool OnSendBodyComplete(int status) { ADD_FAILURE() << "OnSendBodyComplete should not be called"; - return ERR_UNEXPECTED; + return true; } virtual int OnResponseReceived(const spdy::SpdyHeaderBlock& response, @@ -80,7 +80,6 @@ class TestSpdyStreamDelegate : public SpdyStream::Delegate { callback_ = NULL; callback->Run(OK); } - virtual void set_chunk_callback(net::ChunkCallback *) {} bool send_headers_completed() const { return send_headers_completed_; } const linked_ptr<spdy::SpdyHeaderBlock>& response() const { diff --git a/net/spdy/spdy_test_util.cc b/net/spdy/spdy_test_util.cc index 7e1711a..6342b16 100644 --- a/net/spdy/spdy_test_util.cc +++ b/net/spdy/spdy_test_util.cc @@ -672,35 +672,6 @@ spdy::SpdyFrame* ConstructSpdyPost(int64 content_length, arraysize(post_headers)); } -// Constructs a chunked transfer SPDY POST SYN packet. -// |extra_headers| are the extra header-value pairs, which typically -// will vary the most between calls. -// Returns a SpdyFrame. -spdy::SpdyFrame* ConstructChunkedSpdyPost(const char* const extra_headers[], - int extra_header_count) { - const char* post_headers[] = { - "method", - "POST", - "url", - "/", - "host", - "www.google.com", - "scheme", - "http", - "version", - "HTTP/1.1" - }; - return ConstructSpdyControlFrame(extra_headers, - extra_header_count, - false, - 1, - LOWEST, - spdy::SYN_STREAM, - spdy::CONTROL_FLAG_NONE, - post_headers, - arraysize(post_headers)); -} - // Constructs a standard SPDY SYN_REPLY packet to match the SPDY POST. // |extra_headers| are the extra header-value pairs, which typically // will vary the most between calls. diff --git a/net/spdy/spdy_test_util.h b/net/spdy/spdy_test_util.h index 4cfed13..7bd78b6 100644 --- a/net/spdy/spdy_test_util.h +++ b/net/spdy/spdy_test_util.h @@ -280,13 +280,6 @@ spdy::SpdyFrame* ConstructSpdyPost(int64 content_length, const char* const extra_headers[], int extra_header_count); -// Constructs a chunked transfer SPDY POST SYN packet. -// |extra_headers| are the extra header-value pairs, which typically -// will vary the most between calls. -// Returns a SpdyFrame. -spdy::SpdyFrame* ConstructChunkedSpdyPost(const char* const extra_headers[], - int extra_header_count); - // Constructs a standard SPDY SYN_REPLY packet to match the SPDY POST. // |extra_headers| are the extra header-value pairs, which typically // will vary the most between calls. diff --git a/net/url_request/url_request.cc b/net/url_request/url_request.cc index 5af99ea..e25bac6 100644 --- a/net/url_request/url_request.cc +++ b/net/url_request/url_request.cc @@ -184,13 +184,17 @@ void URLRequest::EnableChunkedUpload() { } } -void URLRequest::AppendChunkToUpload(const char* bytes, - int bytes_len, - bool is_last_chunk) { +void URLRequest::AppendChunkToUpload(const char* bytes, int bytes_len) { DCHECK(upload_); DCHECK(upload_->is_chunked()); DCHECK_GT(bytes_len, 0); - upload_->AppendChunk(bytes, bytes_len, is_last_chunk); + upload_->AppendChunk(bytes, bytes_len); +} + +void URLRequest::MarkEndOfChunks() { + DCHECK(upload_); + DCHECK(upload_->is_chunked()); + upload_->AppendChunk(NULL, 0); } void URLRequest::set_upload(net::UploadData* upload) { diff --git a/net/url_request/url_request.h b/net/url_request/url_request.h index 849a03b..a2ad24b 100644 --- a/net/url_request/url_request.h +++ b/net/url_request/url_request.h @@ -330,9 +330,10 @@ class URLRequest : public base::NonThreadSafe { // call MarkEndOfChunks() to indicate the end of upload data. // // This method may be called only after calling EnableChunkedUpload(). - void AppendChunkToUpload(const char* bytes, - int bytes_len, - bool is_last_chunk); + void AppendChunkToUpload(const char* bytes, int bytes_len); + + // Indicates the end of a chunked transfer encoded request body. + void MarkEndOfChunks(); // Set the upload data directly. void set_upload(net::UploadData* upload); diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc index d0b8f58..5e03f9b 100644 --- a/net/url_request/url_request_unittest.cc +++ b/net/url_request/url_request_unittest.cc @@ -178,12 +178,13 @@ class URLRequestTestHTTP : public URLRequestTest { } void AddChunksToUpload(TestURLRequest* r) { - r->AppendChunkToUpload("a", 1, false); - r->AppendChunkToUpload("bcd", 3, false); - r->AppendChunkToUpload("this is a longer chunk than before.", 35, false); - r->AppendChunkToUpload("\r\n\r\n", 4, false); - r->AppendChunkToUpload("0", 1, false); - r->AppendChunkToUpload("2323", 4, true); + r->AppendChunkToUpload("a", 1); + r->AppendChunkToUpload("bcd", 3); + r->AppendChunkToUpload("this is a longer chunk than before.", 35); + r->AppendChunkToUpload("\r\n\r\n", 4); + r->AppendChunkToUpload("0", 1); + r->AppendChunkToUpload("2323", 4); + r->MarkEndOfChunks(); } void VerifyReceivedDataMatchesChunks(TestURLRequest* r, TestDelegate* d) { |