summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorwillchan@chromium.org <willchan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-10-13 02:41:00 +0000
committerwillchan@chromium.org <willchan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-10-13 02:41:00 +0000
commit721c0ceae9fef3230bd36b0d1b742f231f37ad19 (patch)
tree0116ac0a7f43a0f41f39336a90d659c42b4ce4a0 /net
parent8210022eadf1cd0f53b3df8610be03c702353fd3 (diff)
downloadchromium_src-721c0ceae9fef3230bd36b0d1b742f231f37ad19.zip
chromium_src-721c0ceae9fef3230bd36b0d1b742f231f37ad19.tar.gz
chromium_src-721c0ceae9fef3230bd36b0d1b742f231f37ad19.tar.bz2
Support SPDY RST_STREAM with REFUSED_STREAM status properly.
Retry the HTTP request in this case. Did the quick dirty implementation which will redo the proxy resolution which is unnecessary, since we already have the SPDY session and should just requeue the SpdyStream, but whatever. Fix that later. BUG=100115 TEST=new unittest Review URL: http://codereview.chromium.org/8246008 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@105246 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r--net/base/net_error_list.h4
-rw-r--r--net/http/http_network_transaction.cc4
-rw-r--r--net/spdy/spdy_network_transaction_unittest.cc54
-rw-r--r--net/spdy/spdy_session.cc2
4 files changed, 64 insertions, 0 deletions
diff --git a/net/base/net_error_list.h b/net/base/net_error_list.h
index 4d1008a..d0dae4d 100644
--- a/net/base/net_error_list.h
+++ b/net/base/net_error_list.h
@@ -501,6 +501,10 @@ NET_ERROR(RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION, -349)
// The HTTP response contained multiple Location headers.
NET_ERROR(RESPONSE_HEADERS_MULTIPLE_LOCATION, -350)
+// SPDY server refused the stream. Client should retry. This should never be a
+// user-visible error.
+NET_ERROR(SPDY_SERVER_REFUSED_STREAM, -351)
+
// The cache does not have the requested entry.
NET_ERROR(CACHE_MISS, -400)
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc
index 2e6a46c..c994051 100644
--- a/net/http/http_network_transaction.cc
+++ b/net/http/http_network_transaction.cc
@@ -1202,6 +1202,10 @@ int HttpNetworkTransaction::HandleIOError(int error) {
error = OK;
}
break;
+ case ERR_SPDY_SERVER_REFUSED_STREAM:
+ ResetConnectionAndRequestForResend();
+ error = OK;
+ break;
}
return error;
}
diff --git a/net/spdy/spdy_network_transaction_unittest.cc b/net/spdy/spdy_network_transaction_unittest.cc
index 32b5b7c..b7ee325 100644
--- a/net/spdy/spdy_network_transaction_unittest.cc
+++ b/net/spdy/spdy_network_transaction_unittest.cc
@@ -5607,4 +5607,58 @@ TEST_P(SpdyNetworkTransactionTest, ServerPushCrossOriginCorrectness) {
}
}
+TEST_P(SpdyNetworkTransactionTest, RetryAfterRefused) {
+ // Construct the request.
+ scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
+ scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
+ MockWrite writes[] = {
+ CreateMockWrite(*req, 1),
+ CreateMockWrite(*req2, 3),
+ };
+
+ scoped_ptr<spdy::SpdyFrame> refused(
+ ConstructSpdyRstStream(1, spdy::REFUSED_STREAM));
+ scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 3));
+ scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(3, true));
+ MockRead reads[] = {
+ CreateMockRead(*refused, 2),
+ CreateMockRead(*resp, 4),
+ CreateMockRead(*body, 5),
+ MockRead(true, 0, 6) // EOF
+ };
+
+ scoped_refptr<OrderedSocketData> data(
+ new OrderedSocketData(reads, arraysize(reads),
+ writes, arraysize(writes)));
+ NormalSpdyTransactionHelper helper(CreateGetRequest(),
+ BoundNetLog(), GetParam());
+
+ helper.RunPreTestSetup();
+ helper.AddData(data.get());
+
+ HttpNetworkTransaction* trans = helper.trans();
+
+ // Start the transaction with basic parameters.
+ TestOldCompletionCallback callback;
+ int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+ rv = callback.WaitForResult();
+ EXPECT_EQ(OK, rv);
+
+ // Verify that we consumed all test data.
+ EXPECT_TRUE(data->at_read_eof()) << "Read count: "
+ << data->read_count()
+ << " Read index: "
+ << data->read_index();
+ EXPECT_TRUE(data->at_write_eof()) << "Write count: "
+ << data->write_count()
+ << " Write index: "
+ << data->write_index();
+
+ // Verify the SYN_REPLY.
+ HttpResponseInfo response = *trans->GetResponseInfo();
+ EXPECT_TRUE(response.headers != NULL);
+ EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
+}
+
} // namespace net
diff --git a/net/spdy/spdy_session.cc b/net/spdy/spdy_session.cc
index d4fcda5..fd19edc 100644
--- a/net/spdy/spdy_session.cc
+++ b/net/spdy/spdy_session.cc
@@ -1286,6 +1286,8 @@ void SpdySession::OnRst(const spdy::SpdyRstStreamControlFrame& frame) {
if (frame.status() == 0) {
stream->OnDataReceived(NULL, 0);
+ } else if (frame.status() == spdy::REFUSED_STREAM) {
+ DeleteStream(stream_id, ERR_SPDY_SERVER_REFUSED_STREAM);
} else {
LOG(ERROR) << "Spdy stream closed: " << frame.status();
// TODO(mbelshe): Map from Spdy-protocol errors to something sensical.