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
, NULL
,
47 &transport_security_state_
,
48 make_scoped_ptr((QuicServerInfo
*)NULL
),
49 QuicServerId(kServerHostname
, kServerPort
, false,
50 PRIVACY_MODE_DISABLED
),
51 DefaultQuicConfig(), &crypto_config_
,
52 base::MessageLoop::current()->message_loop_proxy().get(),
54 session_
.InitializeSession();
55 session_
.config()->SetDefaults();
56 crypto_config_
.SetDefaults();
59 virtual void TearDown() OVERRIDE
{
60 session_
.CloseSessionOnError(ERR_ABORTED
);
63 scoped_ptr
<DatagramClientSocket
> GetSocket() {
64 socket_factory_
.AddSocketDataProvider(&socket_data_
);
65 return socket_factory_
.CreateDatagramClientSocket(
66 DatagramSocket::DEFAULT_BIND
, base::Bind(&base::RandInt
),
67 &net_log_
, NetLog::Source());
70 void CompleteCryptoHandshake() {
71 ASSERT_EQ(ERR_IO_PENDING
,
72 session_
.CryptoConnect(false, callback_
.callback()));
73 CryptoTestUtils::HandshakeWithFakeServer(
74 connection_
, session_
.GetCryptoStream());
75 ASSERT_EQ(OK
, callback_
.WaitForResult());
78 PacketSavingConnection
* connection_
;
79 CapturingNetLog net_log_
;
80 MockClientSocketFactory socket_factory_
;
81 StaticSocketDataProvider socket_data_
;
82 TransportSecurityState transport_security_state_
;
83 QuicClientSession session_
;
86 QuicConnectionVisitorInterface
* visitor_
;
87 TestCompletionCallback callback_
;
88 QuicCryptoClientConfig crypto_config_
;
91 INSTANTIATE_TEST_CASE_P(Tests
, QuicClientSessionTest
,
92 ::testing::ValuesIn(QuicSupportedVersions()));
94 TEST_P(QuicClientSessionTest
, CryptoConnect
) {
95 CompleteCryptoHandshake();
98 TEST_P(QuicClientSessionTest
, MaxNumStreams
) {
99 CompleteCryptoHandshake();
101 std::vector
<QuicReliableClientStream
*> streams
;
102 for (size_t i
= 0; i
< kDefaultMaxStreamsPerConnection
; i
++) {
103 QuicReliableClientStream
* stream
= session_
.CreateOutgoingDataStream();
105 streams
.push_back(stream
);
107 EXPECT_FALSE(session_
.CreateOutgoingDataStream());
109 // Close a stream and ensure I can now open a new one.
110 session_
.CloseStream(streams
[0]->id());
111 EXPECT_TRUE(session_
.CreateOutgoingDataStream());
114 TEST_P(QuicClientSessionTest
, MaxNumStreamsViaRequest
) {
115 CompleteCryptoHandshake();
117 std::vector
<QuicReliableClientStream
*> streams
;
118 for (size_t i
= 0; i
< kDefaultMaxStreamsPerConnection
; i
++) {
119 QuicReliableClientStream
* stream
= session_
.CreateOutgoingDataStream();
121 streams
.push_back(stream
);
124 QuicReliableClientStream
* stream
;
125 QuicClientSession::StreamRequest stream_request
;
126 TestCompletionCallback callback
;
127 ASSERT_EQ(ERR_IO_PENDING
,
128 stream_request
.StartRequest(session_
.GetWeakPtr(), &stream
,
129 callback
.callback()));
131 // Close a stream and ensure I can now open a new one.
132 session_
.CloseStream(streams
[0]->id());
133 ASSERT_TRUE(callback
.have_result());
134 EXPECT_EQ(OK
, callback
.WaitForResult());
135 EXPECT_TRUE(stream
!= NULL
);
138 TEST_P(QuicClientSessionTest
, GoAwayReceived
) {
139 CompleteCryptoHandshake();
141 // After receiving a GoAway, I should no longer be able to create outgoing
143 session_
.OnGoAway(QuicGoAwayFrame(QUIC_PEER_GOING_AWAY
, 1u, "Going away."));
144 EXPECT_EQ(NULL
, session_
.CreateOutgoingDataStream());
147 TEST_P(QuicClientSessionTest
, CanPool
) {
148 // Load a cert that is valid for:
153 ProofVerifyDetailsChromium details
;
154 details
.cert_verify_result
.verified_cert
=
155 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
156 ASSERT_TRUE(details
.cert_verify_result
.verified_cert
);
158 session_
.OnProofVerifyDetailsAvailable(details
);
159 CompleteCryptoHandshake();
162 EXPECT_TRUE(session_
.CanPool("www.example.org"));
163 EXPECT_TRUE(session_
.CanPool("mail.example.org"));
164 EXPECT_TRUE(session_
.CanPool("mail.example.com"));
165 EXPECT_FALSE(session_
.CanPool("mail.google.com"));
168 TEST_P(QuicClientSessionTest
, ConnectionPooledWithTlsChannelId
) {
169 // Load a cert that is valid for:
174 ProofVerifyDetailsChromium details
;
175 details
.cert_verify_result
.verified_cert
=
176 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
177 ASSERT_TRUE(details
.cert_verify_result
.verified_cert
);
179 session_
.OnProofVerifyDetailsAvailable(details
);
180 CompleteCryptoHandshake();
181 QuicClientSessionPeer::SetChannelIDSent(&session_
, true);
183 EXPECT_TRUE(session_
.CanPool("www.example.org"));
184 EXPECT_TRUE(session_
.CanPool("mail.example.org"));
185 EXPECT_FALSE(session_
.CanPool("mail.example.com"));
186 EXPECT_FALSE(session_
.CanPool("mail.google.com"));
189 TEST_P(QuicClientSessionTest
, ConnectionNotPooledWithDifferentPin
) {
190 uint8 primary_pin
= 1;
191 uint8 backup_pin
= 2;
193 AddPin(&transport_security_state_
, "mail.example.org", primary_pin
,
196 ProofVerifyDetailsChromium details
;
197 details
.cert_verify_result
.verified_cert
=
198 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
199 details
.cert_verify_result
.is_issued_by_known_root
= true;
200 details
.cert_verify_result
.public_key_hashes
.push_back(
201 GetTestHashValue(bad_pin
));
203 ASSERT_TRUE(details
.cert_verify_result
.verified_cert
);
205 session_
.OnProofVerifyDetailsAvailable(details
);
206 CompleteCryptoHandshake();
207 QuicClientSessionPeer::SetChannelIDSent(&session_
, true);
209 EXPECT_FALSE(session_
.CanPool("mail.example.org"));
212 TEST_P(QuicClientSessionTest
, ConnectionPooledWithMatchingPin
) {
213 uint8 primary_pin
= 1;
214 uint8 backup_pin
= 2;
215 AddPin(&transport_security_state_
, "mail.example.org", primary_pin
,
218 ProofVerifyDetailsChromium details
;
219 details
.cert_verify_result
.verified_cert
=
220 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
221 details
.cert_verify_result
.is_issued_by_known_root
= true;
222 details
.cert_verify_result
.public_key_hashes
.push_back(
223 GetTestHashValue(primary_pin
));
225 ASSERT_TRUE(details
.cert_verify_result
.verified_cert
);
227 session_
.OnProofVerifyDetailsAvailable(details
);
228 CompleteCryptoHandshake();
229 QuicClientSessionPeer::SetChannelIDSent(&session_
, true);
231 EXPECT_TRUE(session_
.CanPool("mail.example.org"));