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.
4
5 #include "net/quic/quic_client_session.h"
6
7 #include <vector>
8
9 #include "base/rand_util.h"
10 #include "net/base/capturing_net_log.h"
11 #include "net/base/test_completion_callback.h"
12 #include "net/quic/crypto/aes_128_gcm_12_encrypter.h"
13 #include "net/quic/crypto/crypto_protocol.h"
14 #include "net/quic/crypto/quic_decrypter.h"
15 #include "net/quic/crypto/quic_encrypter.h"
16 #include "net/quic/crypto/quic_server_info.h"
17 #include "net/quic/quic_default_packet_writer.h"
18 #include "net/quic/test_tools/crypto_test_utils.h"
19 #include "net/quic/test_tools/quic_client_session_peer.h"
20 #include "net/quic/test_tools/quic_test_utils.h"
21 #include "net/quic/test_tools/simple_quic_framer.h"
22 #include "net/socket/socket_test_util.h"
23 #include "net/udp/datagram_client_socket.h"
24
25 using testing::_;
26
27 namespace net {
28 namespace test {
29 namespace {
30
31 const char kServerHostname[] = "www.example.com";
32 const uint16 kServerPort = 80;
33
34 class TestPacketWriter : public QuicDefaultPacketWriter {
35 public:
TestPacketWriter(QuicVersion version)36 TestPacketWriter(QuicVersion version) : version_(version) {}
37
38 // QuicPacketWriter
WritePacket(const char * buffer,size_t buf_len,const IPAddressNumber & self_address,const IPEndPoint & peer_address)39 virtual WriteResult WritePacket(
40 const char* buffer, size_t buf_len,
41 const IPAddressNumber& self_address,
42 const IPEndPoint& peer_address) OVERRIDE {
43 SimpleQuicFramer framer(SupportedVersions(version_));
44 QuicEncryptedPacket packet(buffer, buf_len);
45 EXPECT_TRUE(framer.ProcessPacket(packet));
46 header_ = framer.header();
47 return WriteResult(WRITE_STATUS_OK, packet.length());
48 }
49
IsWriteBlockedDataBuffered() const50 virtual bool IsWriteBlockedDataBuffered() const OVERRIDE {
51 // Chrome sockets' Write() methods buffer the data until the Write is
52 // permitted.
53 return true;
54 }
55
56 // Returns the header from the last packet written.
header()57 const QuicPacketHeader& header() { return header_; }
58
59 private:
60 QuicVersion version_;
61 QuicPacketHeader header_;
62 };
63
64 class QuicClientSessionTest : public ::testing::TestWithParam<QuicVersion> {
65 protected:
QuicClientSessionTest()66 QuicClientSessionTest()
67 : writer_(new TestPacketWriter(GetParam())),
68 connection_(
69 new PacketSavingConnection(false, SupportedVersions(GetParam()))),
70 session_(connection_, GetSocket().Pass(), writer_.Pass(), NULL, NULL,
71 make_scoped_ptr((QuicServerInfo*)NULL),
72 QuicServerId(kServerHostname, kServerPort, false,
73 PRIVACY_MODE_DISABLED),
74 DefaultQuicConfig(), &crypto_config_,
75 base::MessageLoop::current()->message_loop_proxy().get(),
76 &net_log_) {
77 session_.config()->SetDefaults();
78 crypto_config_.SetDefaults();
79 }
80
TearDown()81 virtual void TearDown() OVERRIDE {
82 session_.CloseSessionOnError(ERR_ABORTED);
83 }
84
GetSocket()85 scoped_ptr<DatagramClientSocket> GetSocket() {
86 socket_factory_.AddSocketDataProvider(&socket_data_);
87 return socket_factory_.CreateDatagramClientSocket(
88 DatagramSocket::DEFAULT_BIND, base::Bind(&base::RandInt),
89 &net_log_, NetLog::Source());
90 }
91
CompleteCryptoHandshake()92 void CompleteCryptoHandshake() {
93 ASSERT_EQ(ERR_IO_PENDING,
94 session_.CryptoConnect(false, callback_.callback()));
95 CryptoTestUtils::HandshakeWithFakeServer(
96 connection_, session_.GetCryptoStream());
97 ASSERT_EQ(OK, callback_.WaitForResult());
98 }
99
100 scoped_ptr<QuicDefaultPacketWriter> writer_;
101 PacketSavingConnection* connection_;
102 CapturingNetLog net_log_;
103 MockClientSocketFactory socket_factory_;
104 StaticSocketDataProvider socket_data_;
105 QuicClientSession session_;
106 MockClock clock_;
107 MockRandom random_;
108 QuicConnectionVisitorInterface* visitor_;
109 TestCompletionCallback callback_;
110 QuicCryptoClientConfig crypto_config_;
111 };
112
113 INSTANTIATE_TEST_CASE_P(Tests, QuicClientSessionTest,
114 ::testing::ValuesIn(QuicSupportedVersions()));
115
TEST_P(QuicClientSessionTest,CryptoConnect)116 TEST_P(QuicClientSessionTest, CryptoConnect) {
117 CompleteCryptoHandshake();
118 }
119
TEST_P(QuicClientSessionTest,MaxNumStreams)120 TEST_P(QuicClientSessionTest, MaxNumStreams) {
121 CompleteCryptoHandshake();
122
123 std::vector<QuicReliableClientStream*> streams;
124 for (size_t i = 0; i < kDefaultMaxStreamsPerConnection; i++) {
125 QuicReliableClientStream* stream = session_.CreateOutgoingDataStream();
126 EXPECT_TRUE(stream);
127 streams.push_back(stream);
128 }
129 EXPECT_FALSE(session_.CreateOutgoingDataStream());
130
131 // Close a stream and ensure I can now open a new one.
132 session_.CloseStream(streams[0]->id());
133 EXPECT_TRUE(session_.CreateOutgoingDataStream());
134 }
135
TEST_P(QuicClientSessionTest,MaxNumStreamsViaRequest)136 TEST_P(QuicClientSessionTest, MaxNumStreamsViaRequest) {
137 CompleteCryptoHandshake();
138
139 std::vector<QuicReliableClientStream*> streams;
140 for (size_t i = 0; i < kDefaultMaxStreamsPerConnection; i++) {
141 QuicReliableClientStream* stream = session_.CreateOutgoingDataStream();
142 EXPECT_TRUE(stream);
143 streams.push_back(stream);
144 }
145
146 QuicReliableClientStream* stream;
147 QuicClientSession::StreamRequest stream_request;
148 TestCompletionCallback callback;
149 ASSERT_EQ(ERR_IO_PENDING,
150 stream_request.StartRequest(session_.GetWeakPtr(), &stream,
151 callback.callback()));
152
153 // Close a stream and ensure I can now open a new one.
154 session_.CloseStream(streams[0]->id());
155 ASSERT_TRUE(callback.have_result());
156 EXPECT_EQ(OK, callback.WaitForResult());
157 EXPECT_TRUE(stream != NULL);
158 }
159
TEST_P(QuicClientSessionTest,GoAwayReceived)160 TEST_P(QuicClientSessionTest, GoAwayReceived) {
161 CompleteCryptoHandshake();
162
163 // After receiving a GoAway, I should no longer be able to create outgoing
164 // streams.
165 session_.OnGoAway(QuicGoAwayFrame(QUIC_PEER_GOING_AWAY, 1u, "Going away."));
166 EXPECT_EQ(NULL, session_.CreateOutgoingDataStream());
167 }
168
169 } // namespace
170 } // namespace test
171 } // namespace net
172