diff options
author | agl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-11 19:55:24 +0000 |
---|---|---|
committer | agl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-11 19:55:24 +0000 |
commit | 73b8dd223e73499e269deeccf8caaa81ebd75cd0 (patch) | |
tree | 439fdb1120940b666080b49ad7c575e94f907248 /net | |
parent | 76d8b628a14b4958646c9ea9c22232fe80de8ca1 (diff) | |
download | chromium_src-73b8dd223e73499e269deeccf8caaa81ebd75cd0.zip chromium_src-73b8dd223e73499e269deeccf8caaa81ebd75cd0.tar.gz chromium_src-73b8dd223e73499e269deeccf8caaa81ebd75cd0.tar.bz2 |
net: restart on NPN misprediction and add tests for Snap Start errors.
Restart an HTTP load when we mispredict the NPN protocol in a Snap Start connection.
Also, test the behaviour of the HTTP layer when SSL errors result
from the first Write() call. When we are doing Snap Start, we need to
merge the first application data record into the ClientHello. Thus the
SSL socket will report that it has connected immedately in order to get
a Write() call. This means that some errors, which would typically
result from the Connect(), are now returned on the first Write().
BUG=none
TEST=net_unittests
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@65837 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r-- | net/http/http_network_layer_unittest.cc | 2 | ||||
-rw-r--r-- | net/http/http_network_transaction.cc | 10 | ||||
-rw-r--r-- | net/http/http_network_transaction_unittest.cc | 92 |
3 files changed, 103 insertions, 1 deletions
diff --git a/net/http/http_network_layer_unittest.cc b/net/http/http_network_layer_unittest.cc index dadda13..2850404 100644 --- a/net/http/http_network_layer_unittest.cc +++ b/net/http/http_network_layer_unittest.cc @@ -84,7 +84,7 @@ TEST_F(HttpNetworkLayerTest, GET) { "User-Agent: Foo/1.0\r\n\r\n"), }; net::StaticSocketDataProvider data(data_reads, arraysize(data_reads), - data_writes, arraysize(data_reads)); + data_writes, arraysize(data_writes)); mock_socket_factory.AddSocketDataProvider(&data); MockHostResolver host_resolver; diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc index 7cbbc9bf..c671751 100644 --- a/net/http/http_network_transaction.cc +++ b/net/http/http_network_transaction.cc @@ -1014,6 +1014,16 @@ int HttpNetworkTransaction::HandleIOError(int error) { error = OK; } break; + case ERR_SSL_SNAP_START_NPN_MISPREDICTION: + // This means that we tried to Snap Start a connection, but we + // mispredicted the NPN result. This isn't a problem from the point of + // view of the SSL layer because the server will ignore the application + // data in the Snap Start extension. However, at the HTTP layer, we have + // already decided that it's a HTTP or SPDY connection and it's easier to + // abort and start again. + ResetConnectionAndRequestForResend(); + error = OK; + break; } return error; } diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc index e328031..32656bf 100644 --- a/net/http/http_network_transaction_unittest.cc +++ b/net/http/http_network_transaction_unittest.cc @@ -7746,4 +7746,96 @@ TEST_F(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) { EXPECT_EQ(OK, callback.WaitForResult()); } +// Given a net error, cause that error to be returned from the first Write() +// call and verify that the HttpTransaction fails with that error. +static void CheckErrorIsPassedBack(int error, bool async) { + SessionDependencies session_deps; + + SSLSocketDataProvider ssl_data(async, OK); + net::MockWrite data_writes[] = { + net::MockWrite(async, error), + }; + net::StaticSocketDataProvider data(NULL, 0, + data_writes, arraysize(data_writes)); + session_deps.socket_factory.AddSocketDataProvider(&data); + session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data); + + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); + scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session)); + + net::HttpRequestInfo request_info; + request_info.url = GURL("https://www.example.com/"); + request_info.method = "GET"; + request_info.load_flags = net::LOAD_NORMAL; + + TestCompletionCallback callback; + int rv = trans->Start(&request_info, &callback, net::BoundNetLog()); + if (rv == net::ERR_IO_PENDING) + rv = callback.WaitForResult(); + ASSERT_EQ(error, rv); +} + +TEST_F(HttpNetworkTransactionTest, SSLWriteCertError) { + // Just check a grab bag of cert errors. + static const int kErrors[] = { + ERR_CERT_COMMON_NAME_INVALID, + ERR_CERT_AUTHORITY_INVALID, + ERR_CERT_DATE_INVALID, + }; + for (size_t i = 0; i < arraysize(kErrors); i++) { + CheckErrorIsPassedBack(kErrors[i], false /* not async */); + CheckErrorIsPassedBack(kErrors[i], true /* async */); + } +} + +// Test that the transaction is restarted in the event of an NPN misprediction. +TEST_F(HttpNetworkTransactionTest, NPNMispredict) { + SessionDependencies session_deps; + + SSLSocketDataProvider ssl_data1(true /* async */, OK); + SSLSocketDataProvider ssl_data2(true /* async */, OK); + + net::MockWrite data1_writes[] = { + net::MockWrite(true /* async */, ERR_SSL_SNAP_START_NPN_MISPREDICTION), + }; + net::MockRead data2_reads[] = { + net::MockRead("HTTP/1.0 200 OK\r\n\r\n"), + net::MockRead("hello world"), + net::MockRead(false, net::OK), + }; + net::MockWrite data2_writes[] = { + net::MockWrite("GET / HTTP/1.1\r\n" + "Host: www.example.com\r\n" + "Connection: keep-alive\r\n\r\n"), + }; + net::StaticSocketDataProvider data1( + NULL, 0, data1_writes, arraysize(data1_writes)); + net::StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), + data2_writes, arraysize(data2_writes)); + + session_deps.socket_factory.AddSocketDataProvider(&data1); + session_deps.socket_factory.AddSocketDataProvider(&data2); + session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1); + session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2); + + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); + scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session)); + + net::HttpRequestInfo request_info; + request_info.url = GURL("https://www.example.com/"); + request_info.method = "GET"; + request_info.load_flags = net::LOAD_NORMAL; + + TestCompletionCallback callback; + int rv = trans->Start(&request_info, &callback, net::BoundNetLog()); + if (rv == net::ERR_IO_PENDING) + rv = callback.WaitForResult(); + ASSERT_EQ(OK, rv); + + std::string contents; + rv = ReadTransaction(trans.get(), &contents); + EXPECT_EQ(net::OK, rv); + EXPECT_EQ("hello world", contents); +} + } // namespace net |