1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/quic/quic_client_session.h"
9 #include "base/files/file_path.h"
10 #include "base/rand_util.h"
11 #include "net/base/capturing_net_log.h"
12 #include "net/base/test_completion_callback.h"
13 #include "net/base/test_data_directory.h"
14 #include "net/cert/cert_verify_result.h"
15 #include "net/quic/crypto/aes_128_gcm_12_encrypter.h"
16 #include "net/quic/crypto/crypto_protocol.h"
17 #include "net/quic/crypto/proof_verifier_chromium.h"
18 #include "net/quic/crypto/quic_decrypter.h"
19 #include "net/quic/crypto/quic_encrypter.h"
20 #include "net/quic/crypto/quic_server_info.h"
21 #include "net/quic/quic_default_packet_writer.h"
22 #include "net/quic/test_tools/crypto_test_utils.h"
23 #include "net/quic/test_tools/quic_client_session_peer.h"
24 #include "net/quic/test_tools/quic_test_utils.h"
25 #include "net/quic/test_tools/simple_quic_framer.h"
26 #include "net/socket/socket_test_util.h"
27 #include "net/test/cert_test_util.h"
28 #include "net/udp/datagram_client_socket.h"
36 const char kServerHostname
[] = "www.example.org";
37 const uint16 kServerPort
= 80;
39 class TestPacketWriter
: public QuicDefaultPacketWriter
{
41 TestPacketWriter(QuicVersion version
) : version_(version
) {}
44 virtual WriteResult
WritePacket(
45 const char* buffer
, size_t buf_len
,
46 const IPAddressNumber
& self_address
,
47 const IPEndPoint
& peer_address
) OVERRIDE
{
48 SimpleQuicFramer
framer(SupportedVersions(version_
));
49 QuicEncryptedPacket
packet(buffer
, buf_len
);
50 EXPECT_TRUE(framer
.ProcessPacket(packet
));
51 header_
= framer
.header();
52 return WriteResult(WRITE_STATUS_OK
, packet
.length());
55 virtual bool IsWriteBlockedDataBuffered() const OVERRIDE
{
56 // Chrome sockets' Write() methods buffer the data until the Write is
61 // Returns the header from the last packet written.
62 const QuicPacketHeader
& header() { return header_
; }
66 QuicPacketHeader header_
;
69 class FakeChannelIDKey
: public ChannelIDKey
{
71 // ChannelIDKey implementation
72 virtual bool Sign(base::StringPiece signed_data
,
73 std::string
* out_signature
) const OVERRIDE
{
78 virtual std::string
SerializeKey() const OVERRIDE
{
83 class QuicClientSessionTest
: public ::testing::TestWithParam
<QuicVersion
> {
85 QuicClientSessionTest()
86 : writer_(new TestPacketWriter(GetParam())),
88 new PacketSavingConnection(false, SupportedVersions(GetParam()))),
89 session_(connection_
, GetSocket().Pass(), writer_
.Pass(), NULL
, NULL
,
90 make_scoped_ptr((QuicServerInfo
*)NULL
),
91 QuicServerId(kServerHostname
, kServerPort
, false,
92 PRIVACY_MODE_DISABLED
),
93 DefaultQuicConfig(), &crypto_config_
,
94 base::MessageLoop::current()->message_loop_proxy().get(),
96 session_
.config()->SetDefaults();
97 crypto_config_
.SetDefaults();
100 virtual void TearDown() OVERRIDE
{
101 session_
.CloseSessionOnError(ERR_ABORTED
);
104 scoped_ptr
<DatagramClientSocket
> GetSocket() {
105 socket_factory_
.AddSocketDataProvider(&socket_data_
);
106 return socket_factory_
.CreateDatagramClientSocket(
107 DatagramSocket::DEFAULT_BIND
, base::Bind(&base::RandInt
),
108 &net_log_
, NetLog::Source());
111 void CompleteCryptoHandshake() {
112 ASSERT_EQ(ERR_IO_PENDING
,
113 session_
.CryptoConnect(false, callback_
.callback()));
114 CryptoTestUtils::HandshakeWithFakeServer(
115 connection_
, session_
.GetCryptoStream());
116 ASSERT_EQ(OK
, callback_
.WaitForResult());
119 scoped_ptr
<QuicDefaultPacketWriter
> writer_
;
120 PacketSavingConnection
* connection_
;
121 CapturingNetLog net_log_
;
122 MockClientSocketFactory socket_factory_
;
123 StaticSocketDataProvider socket_data_
;
124 QuicClientSession session_
;
127 QuicConnectionVisitorInterface
* visitor_
;
128 TestCompletionCallback callback_
;
129 QuicCryptoClientConfig crypto_config_
;
132 INSTANTIATE_TEST_CASE_P(Tests
, QuicClientSessionTest
,
133 ::testing::ValuesIn(QuicSupportedVersions()));
135 TEST_P(QuicClientSessionTest
, CryptoConnect
) {
136 CompleteCryptoHandshake();
139 TEST_P(QuicClientSessionTest
, MaxNumStreams
) {
140 CompleteCryptoHandshake();
142 std::vector
<QuicReliableClientStream
*> streams
;
143 for (size_t i
= 0; i
< kDefaultMaxStreamsPerConnection
; i
++) {
144 QuicReliableClientStream
* stream
= session_
.CreateOutgoingDataStream();
146 streams
.push_back(stream
);
148 EXPECT_FALSE(session_
.CreateOutgoingDataStream());
150 // Close a stream and ensure I can now open a new one.
151 session_
.CloseStream(streams
[0]->id());
152 EXPECT_TRUE(session_
.CreateOutgoingDataStream());
155 TEST_P(QuicClientSessionTest
, MaxNumStreamsViaRequest
) {
156 CompleteCryptoHandshake();
158 std::vector
<QuicReliableClientStream
*> streams
;
159 for (size_t i
= 0; i
< kDefaultMaxStreamsPerConnection
; i
++) {
160 QuicReliableClientStream
* stream
= session_
.CreateOutgoingDataStream();
162 streams
.push_back(stream
);
165 QuicReliableClientStream
* stream
;
166 QuicClientSession::StreamRequest stream_request
;
167 TestCompletionCallback callback
;
168 ASSERT_EQ(ERR_IO_PENDING
,
169 stream_request
.StartRequest(session_
.GetWeakPtr(), &stream
,
170 callback
.callback()));
172 // Close a stream and ensure I can now open a new one.
173 session_
.CloseStream(streams
[0]->id());
174 ASSERT_TRUE(callback
.have_result());
175 EXPECT_EQ(OK
, callback
.WaitForResult());
176 EXPECT_TRUE(stream
!= NULL
);
179 TEST_P(QuicClientSessionTest
, GoAwayReceived
) {
180 CompleteCryptoHandshake();
182 // After receiving a GoAway, I should no longer be able to create outgoing
184 session_
.OnGoAway(QuicGoAwayFrame(QUIC_PEER_GOING_AWAY
, 1u, "Going away."));
185 EXPECT_EQ(NULL
, session_
.CreateOutgoingDataStream());
188 TEST_P(QuicClientSessionTest
, CanPool
) {
189 // Load a cert that is valid for:
193 base::FilePath certs_dir
= GetTestCertsDirectory();
195 CertVerifyResult result
;
196 ProofVerifyDetailsChromium details
;
197 details
.cert_verify_result
.verified_cert
=
198 ImportCertFromFile(certs_dir
, "spdy_pooling.pem");
199 ASSERT_TRUE(details
.cert_verify_result
.verified_cert
);
201 session_
.OnProofVerifyDetailsAvailable(details
);
202 CompleteCryptoHandshake();
205 EXPECT_TRUE(session_
.CanPool("www.example.org"));
206 EXPECT_TRUE(session_
.CanPool("mail.example.org"));
207 EXPECT_TRUE(session_
.CanPool("mail.example.com"));
208 EXPECT_FALSE(session_
.CanPool("mail.google.com"));
211 TEST_P(QuicClientSessionTest
, ConnectionPooledWithTlsChannelId
) {
212 // Load a cert that is valid for:
216 base::FilePath certs_dir
= GetTestCertsDirectory();
218 CertVerifyResult result
;
219 ProofVerifyDetailsChromium details
;
220 details
.cert_verify_result
.verified_cert
=
221 ImportCertFromFile(certs_dir
, "spdy_pooling.pem");
222 ASSERT_TRUE(details
.cert_verify_result
.verified_cert
);
224 session_
.OnProofVerifyDetailsAvailable(details
);
225 CompleteCryptoHandshake();
226 QuicClientSessionPeer::SetChannelIDKey(&session_
, new FakeChannelIDKey
);
228 EXPECT_TRUE(session_
.CanPool("www.example.org"));
229 EXPECT_TRUE(session_
.CanPool("mail.example.org"));
230 EXPECT_FALSE(session_
.CanPool("mail.example.com"));
231 EXPECT_FALSE(session_
.CanPool("mail.google.com"));