summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoragl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-09-21 15:15:01 +0000
committeragl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-09-21 15:15:01 +0000
commitb3e12d4a13e468036a2f59c11a820adb4c36aeac (patch)
tree10d9f36880cf6aebf48894c10a62d721565e2f0f
parent486f3378bfef5343691f23296b60265b08ea9213 (diff)
downloadchromium_src-b3e12d4a13e468036a2f59c11a820adb4c36aeac.zip
chromium_src-b3e12d4a13e468036a2f59c11a820adb4c36aeac.tar.gz
chromium_src-b3e12d4a13e468036a2f59c11a820adb4c36aeac.tar.bz2
net: add test for False Start corking.
See r58838 for details of why we do False Start corking. BUG=none TEST=net_unittests http://codereview.chromium.org/3427014 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@60056 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--net/socket/ssl_client_socket_unittest.cc38
-rw-r--r--net/tools/testserver/testserver.py24
-rw-r--r--third_party/tlslite/README.chromium4
-rw-r--r--third_party/tlslite/patches/false_start_corking.patch27
-rw-r--r--third_party/tlslite/tlslite/TLSRecordLayer.py9
5 files changed, 96 insertions, 6 deletions
diff --git a/net/socket/ssl_client_socket_unittest.cc b/net/socket/ssl_client_socket_unittest.cc
index 70540f9..cc69721 100644
--- a/net/socket/ssl_client_socket_unittest.cc
+++ b/net/socket/ssl_client_socket_unittest.cc
@@ -32,6 +32,11 @@ class SSLClientSocketTest : public PlatformTest {
socket_factory_(net::ClientSocketFactory::GetDefaultFactory()) {
}
+ // PerformHTTPSRequest makes an HTTPS request to the testserver by requesting
+ // the given path (i.e. "/"). If |response| is non-NULL then any resulting
+ // bytes (including any HTTP headers etc) are appended to |response|.
+ void PerformHTTPSRequest(const std::string& path, std::string* response);
+
protected:
scoped_refptr<net::HostResolver> resolver_;
net::ClientSocketFactory* socket_factory_;
@@ -276,7 +281,8 @@ TEST_F(SSLClientSocketTest, ConnectClientAuthSendNullCert) {
// - Server closes the underlying TCP connection directly.
// - Server sends data unexpectedly.
-TEST_F(SSLClientSocketTest, Read) {
+void SSLClientSocketTest::PerformHTTPSRequest(const std::string& path,
+ std::string* response) {
net::TestServer test_server(net::TestServer::TYPE_HTTPS, FilePath());
ASSERT_TRUE(test_server.Start());
@@ -305,17 +311,17 @@ TEST_F(SSLClientSocketTest, Read) {
}
EXPECT_TRUE(sock->IsConnected());
- const char request_text[] = "GET / HTTP/1.0\r\n\r\n";
+ const std::string request_text = "GET " + path + " HTTP/1.0\r\n\r\n";
scoped_refptr<net::IOBuffer> request_buffer =
- new net::IOBuffer(arraysize(request_text) - 1);
- memcpy(request_buffer->data(), request_text, arraysize(request_text) - 1);
+ new net::IOBuffer(request_text.size());
+ memcpy(request_buffer->data(), request_text.data(), request_text.size());
- rv = sock->Write(request_buffer, arraysize(request_text) - 1, &callback);
+ rv = sock->Write(request_buffer, request_text.size(), &callback);
EXPECT_TRUE(rv >= 0 || rv == net::ERR_IO_PENDING);
if (rv == net::ERR_IO_PENDING)
rv = callback.WaitForResult();
- EXPECT_EQ(static_cast<int>(arraysize(request_text) - 1), rv);
+ EXPECT_EQ(static_cast<int>(request_text.size()), rv);
scoped_refptr<net::IOBuffer> buf = new net::IOBuffer(4096);
for (;;) {
@@ -328,9 +334,15 @@ TEST_F(SSLClientSocketTest, Read) {
EXPECT_GE(rv, 0);
if (rv <= 0)
break;
+ if (response)
+ *response += std::string(buf->data(), rv);
}
}
+TEST_F(SSLClientSocketTest, Read) {
+ PerformHTTPSRequest("/", NULL /* don't care about reply contents */);
+}
+
// Test the full duplex mode, with Read and Write pending at the same time.
// This test also serves as a regression test for http://crbug.com/29815.
TEST_F(SSLClientSocketTest, Read_FullDuplex) {
@@ -541,3 +553,17 @@ TEST_F(SSLClientSocketTest, PrematureApplicationData) {
rv = sock->Connect(&callback);
EXPECT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
}
+
+// CorkedFalseStart tries to test that, in a full handshake, an application
+// data record is contained in the same packet as the Finished handshake
+// message. This test is inheriently false-negative-flaky: if everything is
+// good it'll always pass but, if things break, it'll non-deterministicly fail.
+//
+// WARNING: do not mark this test as flaky. See above.
+TEST_F(SSLClientSocketTest, CorkedFalseStart) {
+ std::string response;
+ PerformHTTPSRequest("/corked-false-start", &response);
+ // "979bdf01cb3c" is a random string which is included in the response to
+ // make it easy to grep for.
+ ASSERT_TRUE(std::string::npos != response.find("979bdf01cb3c"));
+}
diff --git a/net/tools/testserver/testserver.py b/net/tools/testserver/testserver.py
index 8a864a8..081517e 100644
--- a/net/tools/testserver/testserver.py
+++ b/net/tools/testserver/testserver.py
@@ -88,6 +88,7 @@ class HTTPSServer(tlslite.api.TLSSocketServerMixIn, StoppableHTTPServer):
sessionCache=self.session_cache,
reqCert=self.ssl_client_auth,
reqCAs=self.ssl_client_cas)
+ self.corkedFalseStart = tlsConnection.corkedFalseStart
tlsConnection.ignoreAbruptClose = True
return True
except tlslite.api.TLSAbruptCloseError:
@@ -124,6 +125,7 @@ class TestPageHandler(BaseHTTPServer.BaseHTTPRequestHandler):
self.EchoHeader,
self.EchoHeaderOverride,
self.EchoAllHandler,
+ self.FalseStartHandler,
self.FileHandler,
self.RealFileWithCommonHeaderHandler,
self.RealBZ2FileWithCommonHeaderHandler,
@@ -587,6 +589,28 @@ class TestPageHandler(BaseHTTPServer.BaseHTTPRequestHandler):
self.end_headers()
return True
+ def FalseStartHandler(self):
+ """This handler returns kMagic1 if the request was made over a corked False
+ Start connection and kMagic2 otherwise."""
+
+ # These are easy to grep for in the reply.
+ kMagic1 = "979bdf01cb3c\n"
+ kMagic2 = "71733287b84e\n"
+
+ if not self._ShouldHandleRequest("/corked-false-start"):
+ return False
+
+ self.send_response(200)
+ self.send_header('Content-type', 'text/plain')
+ self.end_headers()
+ if self.server.corkedFalseStart:
+ self.wfile.write("Client did corked False Start correctly\n")
+ self.wfile.write(kMagic1)
+ else:
+ self.wfile.write("Client didn't do corked False Start\n")
+ self.wfile.write(kMagic2)
+ return True
+
def FileHandler(self):
"""This handler sends the contents of the requested file. Wow, it's like
a real webserver!"""
diff --git a/third_party/tlslite/README.chromium b/third_party/tlslite/README.chromium
index 3fc9665..c9b8845 100644
--- a/third_party/tlslite/README.chromium
+++ b/third_party/tlslite/README.chromium
@@ -25,3 +25,7 @@ Local Modifications:
default to a certificate_types of [rsa_sign] in CertificateRequest. Apple's
Secure Transport library rejects an empty list and raises an SSL protocol
error.
+- patches/false_start_corking.patch: tlslite/TLSRecordLayer.py was changed to
+ report if data was pending on the socket when a Finished handshake message is
+ processed. This allows us to test that our SSL client sockets are corking
+ False Start application data correctly.
diff --git a/third_party/tlslite/patches/false_start_corking.patch b/third_party/tlslite/patches/false_start_corking.patch
new file mode 100644
index 0000000..feebe34
--- /dev/null
+++ b/third_party/tlslite/patches/false_start_corking.patch
@@ -0,0 +1,27 @@
+diff --git a/tlslite/TLSRecordLayer.py b/tlslite/TLSRecordLayer.py
+index 1bbd09d..44cd33e 100644
+--- a/tlslite/TLSRecordLayer.py
++++ b/tlslite/TLSRecordLayer.py
+@@ -161,6 +161,10 @@ class TLSRecordLayer:
+ #Fault we will induce, for testing purposes
+ self.fault = None
+
++ # Set to true if we observe a corked False Start (i.e., there's a
++ # record pending when we read the Finished.)
++ self.corkedFalseStart = False
++
+ #*********************************************************
+ # Public Functions START
+ #*********************************************************
+@@ -713,6 +717,11 @@ class TLSRecordLayer:
+ yield ClientKeyExchange(constructorType, \
+ self.version).parse(p)
+ elif subType == HandshakeType.finished:
++ try:
++ m = self.sock.recv(1, socket.MSG_PEEK | socket.MSG_DONTWAIT)
++ self.corkedFalseStart = len(m) == 1
++ except:
++ pass
+ yield Finished(self.version).parse(p)
+ else:
+ raise AssertionError()
diff --git a/third_party/tlslite/tlslite/TLSRecordLayer.py b/third_party/tlslite/tlslite/TLSRecordLayer.py
index 1bbd09d..44cd33e 100644
--- a/third_party/tlslite/tlslite/TLSRecordLayer.py
+++ b/third_party/tlslite/tlslite/TLSRecordLayer.py
@@ -161,6 +161,10 @@ class TLSRecordLayer:
#Fault we will induce, for testing purposes
self.fault = None
+ # Set to true if we observe a corked False Start (i.e., there's a
+ # record pending when we read the Finished.)
+ self.corkedFalseStart = False
+
#*********************************************************
# Public Functions START
#*********************************************************
@@ -713,6 +717,11 @@ class TLSRecordLayer:
yield ClientKeyExchange(constructorType, \
self.version).parse(p)
elif subType == HandshakeType.finished:
+ try:
+ m = self.sock.recv(1, socket.MSG_PEEK | socket.MSG_DONTWAIT)
+ self.corkedFalseStart = len(m) == 1
+ except:
+ pass
yield Finished(self.version).parse(p)
else:
raise AssertionError()