summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/quic/quic_http_stream.cc41
-rw-r--r--net/quic/quic_http_stream.h2
-rw-r--r--net/quic/quic_http_stream_test.cc60
3 files changed, 80 insertions, 23 deletions
diff --git a/net/quic/quic_http_stream.cc b/net/quic/quic_http_stream.cc
index 8df900e..3ddccac 100644
--- a/net/quic/quic_http_stream.cc
+++ b/net/quic/quic_http_stream.cc
@@ -23,7 +23,7 @@ namespace net {
static const size_t kHeaderBufInitialSize = 4096;
QuicHttpStream::QuicHttpStream(QuicReliableClientStream* stream)
- : io_state_(STATE_NONE),
+ : next_state_(STATE_NONE),
stream_(stream),
request_info_(NULL),
request_body_stream_(NULL),
@@ -95,7 +95,7 @@ int QuicHttpStream::SendRequest(const HttpRequestHeaders& request_headers,
// Store the response info.
response_info_ = response;
- io_state_ = STATE_SEND_HEADERS;
+ next_state_ = STATE_SEND_HEADERS;
int rv = DoLoop(OK);
if (rv == ERR_IO_PENDING)
callback_ = callback;
@@ -189,7 +189,7 @@ HttpStream* QuicHttpStream::RenewStreamForAuth() {
}
bool QuicHttpStream::IsResponseBodyComplete() const {
- return io_state_ == STATE_OPEN && !stream_;
+ return next_state_ == STATE_OPEN && !stream_;
}
bool QuicHttpStream::CanFindEndOfResponse() const {
@@ -323,7 +323,9 @@ void QuicHttpStream::DoCallback(int rv) {
int QuicHttpStream::DoLoop(int rv) {
do {
- switch (io_state_) {
+ State state = next_state_;
+ next_state_ = STATE_NONE;
+ switch (state) {
case STATE_SEND_HEADERS:
CHECK_EQ(OK, rv);
rv = DoSendHeaders();
@@ -349,10 +351,10 @@ int QuicHttpStream::DoLoop(int rv) {
CHECK_EQ(OK, rv);
break;
default:
- NOTREACHED() << "io_state_: " << io_state_;
+ NOTREACHED() << "next_state_: " << next_state_;
break;
}
- } while (io_state_ != STATE_NONE && io_state_ != STATE_OPEN &&
+ } while (next_state_ != STATE_NONE && next_state_ != STATE_OPEN &&
rv != ERR_IO_PENDING);
return rv;
@@ -364,25 +366,23 @@ int QuicHttpStream::DoSendHeaders() {
bool has_upload_data = request_body_stream_ != NULL;
- io_state_ = STATE_SEND_HEADERS_COMPLETE;
+ next_state_ = STATE_SEND_HEADERS_COMPLETE;
QuicConsumedData rv = stream_->WriteData(request_, !has_upload_data);
return rv.bytes_consumed;
}
int QuicHttpStream::DoSendHeadersComplete(int rv) {
- if (rv < 0) {
- io_state_ = STATE_NONE;
+ if (rv < 0)
return rv;
- }
- io_state_ = request_body_stream_ ?
+ next_state_ = request_body_stream_ ?
STATE_READ_REQUEST_BODY : STATE_OPEN;
return OK;
}
int QuicHttpStream::DoReadRequestBody() {
- io_state_ = STATE_READ_REQUEST_BODY_COMPLETE;
+ next_state_ = STATE_READ_REQUEST_BODY_COMPLETE;
return request_body_stream_->Read(raw_request_body_buf_,
raw_request_body_buf_->size(),
base::Bind(&QuicHttpStream::OnIOComplete,
@@ -392,17 +392,15 @@ int QuicHttpStream::DoReadRequestBody() {
int QuicHttpStream::DoReadRequestBodyComplete(int rv) {
// |rv| is the result of read from the request body from the last call to
// DoSendBody().
- if (rv < 0) {
- io_state_ = STATE_NONE;
+ if (rv < 0)
return rv;
- }
request_body_buf_ = new DrainableIOBuffer(raw_request_body_buf_, rv);
if (rv == 0) { // Reached the end.
DCHECK(request_body_stream_->IsEOF());
}
- io_state_ = STATE_SEND_BODY;
+ next_state_ = STATE_SEND_BODY;
return OK;
}
@@ -419,23 +417,22 @@ int QuicHttpStream::DoSendBody() {
QuicConsumedData rv = stream_->WriteData(data, eof);
request_body_buf_->DidConsume(rv.bytes_consumed);
if (eof) {
- io_state_ = STATE_OPEN;
+ next_state_ = STATE_OPEN;
return OK;
}
+ next_state_ = STATE_SEND_BODY_COMPLETE;
return rv.bytes_consumed;
}
- io_state_ = STATE_SEND_BODY_COMPLETE;
+ next_state_ = STATE_SEND_BODY_COMPLETE;
return OK;
}
int QuicHttpStream::DoSendBodyComplete(int rv) {
- if (rv < 0) {
- io_state_ = STATE_NONE;
+ if (rv < 0)
return rv;
- }
- io_state_ = STATE_READ_REQUEST_BODY;
+ next_state_ = STATE_READ_REQUEST_BODY;
return OK;
}
diff --git a/net/quic/quic_http_stream.h b/net/quic/quic_http_stream.h
index 6716dd5..f6dd5bb 100644
--- a/net/quic/quic_http_stream.h
+++ b/net/quic/quic_http_stream.h
@@ -91,7 +91,7 @@ class NET_EXPORT_PRIVATE QuicHttpStream :
void BufferResponseBody(const char* data, int length);
- State io_state_;
+ State next_state_;
QuicReliableClientStream* stream_; // Non-owning.
diff --git a/net/quic/quic_http_stream_test.cc b/net/quic/quic_http_stream_test.cc
index 2b43b2ef..5b4efaa 100644
--- a/net/quic/quic_http_stream_test.cc
+++ b/net/quic/quic_http_stream_test.cc
@@ -458,6 +458,66 @@ TEST_F(QuicHttpStreamTest, SendPostRequest) {
EXPECT_TRUE(AtEof());
}
+TEST_F(QuicHttpStreamTest, SendChunkedPostRequest) {
+ SetRequestString("POST", "/");
+ size_t chunk_size = strlen(kUploadData);
+ AddWrite(SYNCHRONOUS, ConstructDataPacket(1, !kFin, 0, request_data_));
+ AddWrite(SYNCHRONOUS, ConstructDataPacket(2, !kFin, request_data_.length(),
+ kUploadData));
+ AddWrite(SYNCHRONOUS, ConstructDataPacket(3, kFin,
+ request_data_.length() + chunk_size,
+ kUploadData));
+ AddWrite(SYNCHRONOUS, ConstructAckPacket(4, 2, 3));
+
+ Initialize();
+
+ UploadDataStream upload_data_stream(UploadDataStream::CHUNKED, 0);
+ upload_data_stream.AppendChunk(kUploadData, chunk_size, false);
+
+ request_.method = "POST";
+ request_.url = GURL("http://www.google.com/");
+ request_.upload_data_stream = &upload_data_stream;
+ ASSERT_EQ(OK, request_.upload_data_stream->Init(CompletionCallback()));
+
+ ASSERT_EQ(OK, stream_->InitializeStream(&request_, net_log_,
+ callback_.callback()));
+ ASSERT_EQ(ERR_IO_PENDING, stream_->SendRequest(headers_, &response_,
+ callback_.callback()));
+ EXPECT_EQ(&response_, stream_->GetResponseInfo());
+
+ upload_data_stream.AppendChunk(kUploadData, chunk_size, true);
+
+ // Ack both packets in the request.
+ scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 2, 1));
+ ProcessPacket(*ack);
+
+ // Send the response headers (but not the body).
+ SetResponseString("200 OK", "");
+ scoped_ptr<QuicEncryptedPacket> resp(
+ ConstructDataPacket(2, !kFin, 0, response_data_));
+ ProcessPacket(*resp);
+
+ // Since the headers have already arrived, this should return immediately.
+ ASSERT_EQ(OK, stream_->ReadResponseHeaders(callback_.callback()));
+ ASSERT_TRUE(response_.headers != NULL);
+ EXPECT_EQ(200, response_.headers->response_code());
+ EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
+
+ // Send the response body.
+ const char kResponseBody[] = "Hello world!";
+ scoped_ptr<QuicEncryptedPacket> resp_body(
+ ConstructDataPacket(3, kFin, response_data_.length(), kResponseBody));
+ ProcessPacket(*resp_body);
+
+ // Since the body has already arrived, this should return immediately.
+ ASSERT_EQ(static_cast<int>(strlen(kResponseBody)),
+ stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
+ callback_.callback()));
+
+ EXPECT_TRUE(stream_->IsResponseBodyComplete());
+ EXPECT_TRUE(AtEof());
+}
+
TEST_F(QuicHttpStreamTest, DestroyedEarly) {
SetRequestString("GET", "/");
AddWrite(SYNCHRONOUS, ConstructDataPacket(1, kFin, 0, request_data_));