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 QuicClientSessionTest
: public ::testing::TestWithParam
<QuicVersion
> {
71 QuicClientSessionTest()
72 : writer_(new TestPacketWriter(GetParam())),
74 new PacketSavingConnection(false, SupportedVersions(GetParam()))),
75 session_(connection_
, GetSocket().Pass(), writer_
.Pass(), NULL
, NULL
,
76 make_scoped_ptr((QuicServerInfo
*)NULL
),
77 QuicServerId(kServerHostname
, kServerPort
, false,
78 PRIVACY_MODE_DISABLED
),
79 DefaultQuicConfig(), &crypto_config_
,
80 base::MessageLoop::current()->message_loop_proxy().get(),
82 session_
.InitializeSession();
83 session_
.config()->SetDefaults();
84 crypto_config_
.SetDefaults();
87 virtual void TearDown() OVERRIDE
{
88 session_
.CloseSessionOnError(ERR_ABORTED
);
91 scoped_ptr
<DatagramClientSocket
> GetSocket() {
92 socket_factory_
.AddSocketDataProvider(&socket_data_
);
93 return socket_factory_
.CreateDatagramClientSocket(
94 DatagramSocket::DEFAULT_BIND
, base::Bind(&base::RandInt
),
95 &net_log_
, NetLog::Source());
98 void CompleteCryptoHandshake() {
99 ASSERT_EQ(ERR_IO_PENDING
,
100 session_
.CryptoConnect(false, callback_
.callback()));
101 CryptoTestUtils::HandshakeWithFakeServer(
102 connection_
, session_
.GetCryptoStream());
103 ASSERT_EQ(OK
, callback_
.WaitForResult());
106 scoped_ptr
<QuicDefaultPacketWriter
> writer_
;
107 PacketSavingConnection
* connection_
;
108 CapturingNetLog net_log_
;
109 MockClientSocketFactory socket_factory_
;
110 StaticSocketDataProvider socket_data_
;
111 QuicClientSession session_
;
114 QuicConnectionVisitorInterface
* visitor_
;
115 TestCompletionCallback callback_
;
116 QuicCryptoClientConfig crypto_config_
;
119 INSTANTIATE_TEST_CASE_P(Tests
, QuicClientSessionTest
,
120 ::testing::ValuesIn(QuicSupportedVersions()));
122 TEST_P(QuicClientSessionTest
, CryptoConnect
) {
123 CompleteCryptoHandshake();
126 TEST_P(QuicClientSessionTest
, MaxNumStreams
) {
127 CompleteCryptoHandshake();
129 std::vector
<QuicReliableClientStream
*> streams
;
130 for (size_t i
= 0; i
< kDefaultMaxStreamsPerConnection
; i
++) {
131 QuicReliableClientStream
* stream
= session_
.CreateOutgoingDataStream();
133 streams
.push_back(stream
);
135 EXPECT_FALSE(session_
.CreateOutgoingDataStream());
137 // Close a stream and ensure I can now open a new one.
138 session_
.CloseStream(streams
[0]->id());
139 EXPECT_TRUE(session_
.CreateOutgoingDataStream());
142 TEST_P(QuicClientSessionTest
, MaxNumStreamsViaRequest
) {
143 CompleteCryptoHandshake();
145 std::vector
<QuicReliableClientStream
*> streams
;
146 for (size_t i
= 0; i
< kDefaultMaxStreamsPerConnection
; i
++) {
147 QuicReliableClientStream
* stream
= session_
.CreateOutgoingDataStream();
149 streams
.push_back(stream
);
152 QuicReliableClientStream
* stream
;
153 QuicClientSession::StreamRequest stream_request
;
154 TestCompletionCallback callback
;
155 ASSERT_EQ(ERR_IO_PENDING
,
156 stream_request
.StartRequest(session_
.GetWeakPtr(), &stream
,
157 callback
.callback()));
159 // Close a stream and ensure I can now open a new one.
160 session_
.CloseStream(streams
[0]->id());
161 ASSERT_TRUE(callback
.have_result());
162 EXPECT_EQ(OK
, callback
.WaitForResult());
163 EXPECT_TRUE(stream
!= NULL
);
166 TEST_P(QuicClientSessionTest
, GoAwayReceived
) {
167 CompleteCryptoHandshake();
169 // After receiving a GoAway, I should no longer be able to create outgoing
171 session_
.OnGoAway(QuicGoAwayFrame(QUIC_PEER_GOING_AWAY
, 1u, "Going away."));
172 EXPECT_EQ(NULL
, session_
.CreateOutgoingDataStream());
175 TEST_P(QuicClientSessionTest
, CanPool
) {
176 // Load a cert that is valid for:
180 base::FilePath certs_dir
= GetTestCertsDirectory();
182 CertVerifyResult result
;
183 ProofVerifyDetailsChromium details
;
184 details
.cert_verify_result
.verified_cert
=
185 ImportCertFromFile(certs_dir
, "spdy_pooling.pem");
186 ASSERT_TRUE(details
.cert_verify_result
.verified_cert
);
188 session_
.OnProofVerifyDetailsAvailable(details
);
189 CompleteCryptoHandshake();
192 EXPECT_TRUE(session_
.CanPool("www.example.org"));
193 EXPECT_TRUE(session_
.CanPool("mail.example.org"));
194 EXPECT_TRUE(session_
.CanPool("mail.example.com"));
195 EXPECT_FALSE(session_
.CanPool("mail.google.com"));
198 TEST_P(QuicClientSessionTest
, ConnectionPooledWithTlsChannelId
) {
199 // Load a cert that is valid for:
203 base::FilePath certs_dir
= GetTestCertsDirectory();
205 CertVerifyResult result
;
206 ProofVerifyDetailsChromium details
;
207 details
.cert_verify_result
.verified_cert
=
208 ImportCertFromFile(certs_dir
, "spdy_pooling.pem");
209 ASSERT_TRUE(details
.cert_verify_result
.verified_cert
);
211 session_
.OnProofVerifyDetailsAvailable(details
);
212 CompleteCryptoHandshake();
213 QuicClientSessionPeer::SetChannelIDSent(&session_
, true);
215 EXPECT_TRUE(session_
.CanPool("www.example.org"));
216 EXPECT_TRUE(session_
.CanPool("mail.example.org"));
217 EXPECT_FALSE(session_
.CanPool("mail.example.com"));
218 EXPECT_FALSE(session_
.CanPool("mail.google.com"));