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/base64.h"
10 #include "base/files/file_path.h"
11 #include "base/rand_util.h"
12 #include "net/base/capturing_net_log.h"
13 #include "net/base/test_completion_callback.h"
14 #include "net/base/test_data_directory.h"
15 #include "net/cert/cert_verify_result.h"
16 #include "net/http/transport_security_state.h"
17 #include "net/quic/crypto/aes_128_gcm_12_encrypter.h"
18 #include "net/quic/crypto/crypto_protocol.h"
19 #include "net/quic/crypto/proof_verifier_chromium.h"
20 #include "net/quic/crypto/quic_decrypter.h"
21 #include "net/quic/crypto/quic_encrypter.h"
22 #include "net/quic/crypto/quic_server_info.h"
23 #include "net/quic/test_tools/crypto_test_utils.h"
24 #include "net/quic/test_tools/quic_client_session_peer.h"
25 #include "net/quic/test_tools/quic_test_utils.h"
26 #include "net/quic/test_tools/simple_quic_framer.h"
27 #include "net/socket/socket_test_util.h"
28 #include "net/spdy/spdy_test_utils.h"
29 #include "net/test/cert_test_util.h"
30 #include "net/udp/datagram_client_socket.h"
38 const char kServerHostname
[] = "www.example.org";
39 const uint16 kServerPort
= 80;
41 class QuicClientSessionTest
: public ::testing::TestWithParam
<QuicVersion
> {
43 QuicClientSessionTest()
45 new PacketSavingConnection(false, SupportedVersions(GetParam()))),
46 session_(connection_
, GetSocket().Pass(), NULL
,
47 &transport_security_state_
,
48 make_scoped_ptr((QuicServerInfo
*)NULL
), DefaultQuicConfig(),
49 base::MessageLoop::current()->message_loop_proxy().get(),
51 session_
.InitializeSession(QuicServerId(kServerHostname
, kServerPort
, false,
52 PRIVACY_MODE_DISABLED
),
53 &crypto_config_
, NULL
);
54 session_
.config()->SetDefaults();
55 crypto_config_
.SetDefaults();
58 virtual void TearDown() OVERRIDE
{
59 session_
.CloseSessionOnError(ERR_ABORTED
);
62 scoped_ptr
<DatagramClientSocket
> GetSocket() {
63 socket_factory_
.AddSocketDataProvider(&socket_data_
);
64 return socket_factory_
.CreateDatagramClientSocket(
65 DatagramSocket::DEFAULT_BIND
, base::Bind(&base::RandInt
),
66 &net_log_
, NetLog::Source());
69 void CompleteCryptoHandshake() {
70 ASSERT_EQ(ERR_IO_PENDING
,
71 session_
.CryptoConnect(false, callback_
.callback()));
72 CryptoTestUtils::HandshakeWithFakeServer(
73 connection_
, session_
.GetCryptoStream());
74 ASSERT_EQ(OK
, callback_
.WaitForResult());
77 PacketSavingConnection
* connection_
;
78 CapturingNetLog net_log_
;
79 MockClientSocketFactory socket_factory_
;
80 StaticSocketDataProvider socket_data_
;
81 TransportSecurityState transport_security_state_
;
82 QuicClientSession session_
;
85 QuicConnectionVisitorInterface
* visitor_
;
86 TestCompletionCallback callback_
;
87 QuicCryptoClientConfig crypto_config_
;
90 INSTANTIATE_TEST_CASE_P(Tests
, QuicClientSessionTest
,
91 ::testing::ValuesIn(QuicSupportedVersions()));
93 TEST_P(QuicClientSessionTest
, CryptoConnect
) {
94 CompleteCryptoHandshake();
97 TEST_P(QuicClientSessionTest
, MaxNumStreams
) {
98 CompleteCryptoHandshake();
100 std::vector
<QuicReliableClientStream
*> streams
;
101 for (size_t i
= 0; i
< kDefaultMaxStreamsPerConnection
; i
++) {
102 QuicReliableClientStream
* stream
= session_
.CreateOutgoingDataStream();
104 streams
.push_back(stream
);
106 EXPECT_FALSE(session_
.CreateOutgoingDataStream());
108 // Close a stream and ensure I can now open a new one.
109 session_
.CloseStream(streams
[0]->id());
110 EXPECT_TRUE(session_
.CreateOutgoingDataStream());
113 TEST_P(QuicClientSessionTest
, MaxNumStreamsViaRequest
) {
114 CompleteCryptoHandshake();
116 std::vector
<QuicReliableClientStream
*> streams
;
117 for (size_t i
= 0; i
< kDefaultMaxStreamsPerConnection
; i
++) {
118 QuicReliableClientStream
* stream
= session_
.CreateOutgoingDataStream();
120 streams
.push_back(stream
);
123 QuicReliableClientStream
* stream
;
124 QuicClientSession::StreamRequest stream_request
;
125 TestCompletionCallback callback
;
126 ASSERT_EQ(ERR_IO_PENDING
,
127 stream_request
.StartRequest(session_
.GetWeakPtr(), &stream
,
128 callback
.callback()));
130 // Close a stream and ensure I can now open a new one.
131 session_
.CloseStream(streams
[0]->id());
132 ASSERT_TRUE(callback
.have_result());
133 EXPECT_EQ(OK
, callback
.WaitForResult());
134 EXPECT_TRUE(stream
!= NULL
);
137 TEST_P(QuicClientSessionTest
, GoAwayReceived
) {
138 CompleteCryptoHandshake();
140 // After receiving a GoAway, I should no longer be able to create outgoing
142 session_
.OnGoAway(QuicGoAwayFrame(QUIC_PEER_GOING_AWAY
, 1u, "Going away."));
143 EXPECT_EQ(NULL
, session_
.CreateOutgoingDataStream());
146 TEST_P(QuicClientSessionTest
, CanPool
) {
147 // Load a cert that is valid for:
152 ProofVerifyDetailsChromium details
;
153 details
.cert_verify_result
.verified_cert
=
154 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
155 ASSERT_TRUE(details
.cert_verify_result
.verified_cert
.get());
157 session_
.OnProofVerifyDetailsAvailable(details
);
158 CompleteCryptoHandshake();
161 EXPECT_TRUE(session_
.CanPool("www.example.org"));
162 EXPECT_TRUE(session_
.CanPool("mail.example.org"));
163 EXPECT_TRUE(session_
.CanPool("mail.example.com"));
164 EXPECT_FALSE(session_
.CanPool("mail.google.com"));
167 TEST_P(QuicClientSessionTest
, ConnectionPooledWithTlsChannelId
) {
168 // Load a cert that is valid for:
173 ProofVerifyDetailsChromium details
;
174 details
.cert_verify_result
.verified_cert
=
175 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
176 ASSERT_TRUE(details
.cert_verify_result
.verified_cert
.get());
178 session_
.OnProofVerifyDetailsAvailable(details
);
179 CompleteCryptoHandshake();
180 QuicClientSessionPeer::SetChannelIDSent(&session_
, true);
182 EXPECT_TRUE(session_
.CanPool("www.example.org"));
183 EXPECT_TRUE(session_
.CanPool("mail.example.org"));
184 EXPECT_FALSE(session_
.CanPool("mail.example.com"));
185 EXPECT_FALSE(session_
.CanPool("mail.google.com"));
188 TEST_P(QuicClientSessionTest
, ConnectionNotPooledWithDifferentPin
) {
189 uint8 primary_pin
= 1;
190 uint8 backup_pin
= 2;
192 AddPin(&transport_security_state_
, "mail.example.org", primary_pin
,
195 ProofVerifyDetailsChromium details
;
196 details
.cert_verify_result
.verified_cert
=
197 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
198 details
.cert_verify_result
.is_issued_by_known_root
= true;
199 details
.cert_verify_result
.public_key_hashes
.push_back(
200 GetTestHashValue(bad_pin
));
202 ASSERT_TRUE(details
.cert_verify_result
.verified_cert
.get());
204 session_
.OnProofVerifyDetailsAvailable(details
);
205 CompleteCryptoHandshake();
206 QuicClientSessionPeer::SetChannelIDSent(&session_
, true);
208 EXPECT_FALSE(session_
.CanPool("mail.example.org"));
211 TEST_P(QuicClientSessionTest
, ConnectionPooledWithMatchingPin
) {
212 uint8 primary_pin
= 1;
213 uint8 backup_pin
= 2;
214 AddPin(&transport_security_state_
, "mail.example.org", primary_pin
,
217 ProofVerifyDetailsChromium details
;
218 details
.cert_verify_result
.verified_cert
=
219 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
220 details
.cert_verify_result
.is_issued_by_known_root
= true;
221 details
.cert_verify_result
.public_key_hashes
.push_back(
222 GetTestHashValue(primary_pin
));
224 ASSERT_TRUE(details
.cert_verify_result
.verified_cert
.get());
226 session_
.OnProofVerifyDetailsAvailable(details
);
227 CompleteCryptoHandshake();
228 QuicClientSessionPeer::SetChannelIDSent(&session_
, true);
230 EXPECT_TRUE(session_
.CanPool("mail.example.org"));