blob: 630e67ad1a4428eaf29d4fb1f97e8dbf94131153 [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// Copyright (c) 2013 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/third_party/quiche/src/quic/core/quic_config.h"
6
vasilvv872e7a32019-03-12 16:42:44 -07007#include <string>
8
QUICHE teama6ef0a62019-03-07 20:34:33 -05009#include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message.h"
10#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
11#include "net/third_party/quiche/src/quic/core/quic_packets.h"
12#include "net/third_party/quiche/src/quic/core/quic_time.h"
13#include "net/third_party/quiche/src/quic/core/quic_utils.h"
14#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050015#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
16#include "net/third_party/quiche/src/quic/platform/api/quic_uint128.h"
17#include "net/third_party/quiche/src/quic/test_tools/quic_config_peer.h"
18#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
19
20namespace quic {
21namespace test {
22namespace {
23
fkastenholzd3a1de92019-05-15 07:00:07 -070024class QuicConfigTest : public QuicTestWithParam<QuicTransportVersion> {
QUICHE teama6ef0a62019-03-07 20:34:33 -050025 protected:
26 QuicConfig config_;
27};
28
fkastenholzd3a1de92019-05-15 07:00:07 -070029// Run all tests with all versions of QUIC.
30INSTANTIATE_TEST_SUITE_P(QuicConfigTests,
31 QuicConfigTest,
32 ::testing::ValuesIn(AllSupportedTransportVersions()));
33
34TEST_P(QuicConfigTest, ToHandshakeMessage) {
QUICHE teama6ef0a62019-03-07 20:34:33 -050035 config_.SetInitialStreamFlowControlWindowToSend(
36 kInitialStreamFlowControlWindowForTest);
37 config_.SetInitialSessionFlowControlWindowToSend(
38 kInitialSessionFlowControlWindowForTest);
39 config_.SetIdleNetworkTimeout(QuicTime::Delta::FromSeconds(5),
40 QuicTime::Delta::FromSeconds(2));
41 CryptoHandshakeMessage msg;
fkastenholzd3a1de92019-05-15 07:00:07 -070042 config_.ToHandshakeMessage(&msg, GetParam());
QUICHE teama6ef0a62019-03-07 20:34:33 -050043
44 uint32_t value;
45 QuicErrorCode error = msg.GetUint32(kICSL, &value);
46 EXPECT_EQ(QUIC_NO_ERROR, error);
47 EXPECT_EQ(5u, value);
48
49 error = msg.GetUint32(kSFCW, &value);
50 EXPECT_EQ(QUIC_NO_ERROR, error);
51 EXPECT_EQ(kInitialStreamFlowControlWindowForTest, value);
52
53 error = msg.GetUint32(kCFCW, &value);
54 EXPECT_EQ(QUIC_NO_ERROR, error);
55 EXPECT_EQ(kInitialSessionFlowControlWindowForTest, value);
56}
57
fkastenholzd3a1de92019-05-15 07:00:07 -070058TEST_P(QuicConfigTest, ProcessClientHello) {
fkastenholz4c7303c2019-07-29 08:17:07 -070059 const uint32_t kTestMaxAckDelayMs =
60 static_cast<uint32_t>(kDefaultDelayedAckTimeMs + 1);
QUICHE teama6ef0a62019-03-07 20:34:33 -050061 QuicConfig client_config;
62 QuicTagVector cgst;
63 cgst.push_back(kQBIC);
64 client_config.SetIdleNetworkTimeout(
65 QuicTime::Delta::FromSeconds(2 * kMaximumIdleTimeoutSecs),
66 QuicTime::Delta::FromSeconds(kMaximumIdleTimeoutSecs));
67 client_config.SetInitialRoundTripTimeUsToSend(10 * kNumMicrosPerMilli);
68 client_config.SetInitialStreamFlowControlWindowToSend(
69 2 * kInitialStreamFlowControlWindowForTest);
70 client_config.SetInitialSessionFlowControlWindowToSend(
71 2 * kInitialSessionFlowControlWindowForTest);
72 QuicTagVector copt;
73 copt.push_back(kTBBR);
74 client_config.SetConnectionOptionsToSend(copt);
fkastenholz4c7303c2019-07-29 08:17:07 -070075 client_config.SetMaxAckDelayToSendMs(kTestMaxAckDelayMs);
QUICHE teama6ef0a62019-03-07 20:34:33 -050076 CryptoHandshakeMessage msg;
fkastenholzd3a1de92019-05-15 07:00:07 -070077 client_config.ToHandshakeMessage(&msg, GetParam());
QUICHE teama6ef0a62019-03-07 20:34:33 -050078
vasilvvc48c8712019-03-11 13:38:16 -070079 std::string error_details;
QUICHE teama6ef0a62019-03-07 20:34:33 -050080 QuicTagVector initial_received_options;
81 initial_received_options.push_back(kIW50);
82 EXPECT_TRUE(
83 config_.SetInitialReceivedConnectionOptions(initial_received_options));
84 EXPECT_FALSE(
85 config_.SetInitialReceivedConnectionOptions(initial_received_options))
86 << "You can only set initial options once.";
87 const QuicErrorCode error =
88 config_.ProcessPeerHello(msg, CLIENT, &error_details);
89 EXPECT_FALSE(
90 config_.SetInitialReceivedConnectionOptions(initial_received_options))
91 << "You cannot set initial options after the hello.";
92 EXPECT_EQ(QUIC_NO_ERROR, error);
93 EXPECT_TRUE(config_.negotiated());
94 EXPECT_EQ(QuicTime::Delta::FromSeconds(kMaximumIdleTimeoutSecs),
95 config_.IdleNetworkTimeout());
96 EXPECT_EQ(10 * kNumMicrosPerMilli, config_.ReceivedInitialRoundTripTimeUs());
97 EXPECT_TRUE(config_.HasReceivedConnectionOptions());
98 EXPECT_EQ(2u, config_.ReceivedConnectionOptions().size());
99 EXPECT_EQ(config_.ReceivedConnectionOptions()[0], kIW50);
100 EXPECT_EQ(config_.ReceivedConnectionOptions()[1], kTBBR);
101 EXPECT_EQ(config_.ReceivedInitialStreamFlowControlWindowBytes(),
102 2 * kInitialStreamFlowControlWindowForTest);
103 EXPECT_EQ(config_.ReceivedInitialSessionFlowControlWindowBytes(),
104 2 * kInitialSessionFlowControlWindowForTest);
fkastenholz4c7303c2019-07-29 08:17:07 -0700105 if (GetQuicReloadableFlag(quic_negotiate_ack_delay_time)) {
106 EXPECT_TRUE(config_.HasReceivedMaxAckDelayMs());
107 EXPECT_EQ(kTestMaxAckDelayMs, config_.ReceivedMaxAckDelayMs());
108 } else {
109 EXPECT_FALSE(config_.HasReceivedMaxAckDelayMs());
110 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500111}
112
fkastenholzd3a1de92019-05-15 07:00:07 -0700113TEST_P(QuicConfigTest, ProcessServerHello) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500114 QuicIpAddress host;
115 host.FromString("127.0.3.1");
116 const QuicSocketAddress kTestServerAddress = QuicSocketAddress(host, 1234);
117 const QuicUint128 kTestResetToken = MakeQuicUint128(0, 10111100001);
fkastenholz4c7303c2019-07-29 08:17:07 -0700118 const uint32_t kTestMaxAckDelayMs =
119 static_cast<uint32_t>(kDefaultDelayedAckTimeMs + 1);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500120 QuicConfig server_config;
121 QuicTagVector cgst;
122 cgst.push_back(kQBIC);
123 server_config.SetIdleNetworkTimeout(
124 QuicTime::Delta::FromSeconds(kMaximumIdleTimeoutSecs / 2),
125 QuicTime::Delta::FromSeconds(kMaximumIdleTimeoutSecs / 2));
126 server_config.SetInitialRoundTripTimeUsToSend(10 * kNumMicrosPerMilli);
127 server_config.SetInitialStreamFlowControlWindowToSend(
128 2 * kInitialStreamFlowControlWindowForTest);
129 server_config.SetInitialSessionFlowControlWindowToSend(
130 2 * kInitialSessionFlowControlWindowForTest);
131 server_config.SetAlternateServerAddressToSend(kTestServerAddress);
132 server_config.SetStatelessResetTokenToSend(kTestResetToken);
fkastenholz4c7303c2019-07-29 08:17:07 -0700133 server_config.SetMaxAckDelayToSendMs(kTestMaxAckDelayMs);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500134 CryptoHandshakeMessage msg;
fkastenholzd3a1de92019-05-15 07:00:07 -0700135 server_config.ToHandshakeMessage(&msg, GetParam());
vasilvvc48c8712019-03-11 13:38:16 -0700136 std::string error_details;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500137 const QuicErrorCode error =
138 config_.ProcessPeerHello(msg, SERVER, &error_details);
139 EXPECT_EQ(QUIC_NO_ERROR, error);
140 EXPECT_TRUE(config_.negotiated());
141 EXPECT_EQ(QuicTime::Delta::FromSeconds(kMaximumIdleTimeoutSecs / 2),
142 config_.IdleNetworkTimeout());
143 EXPECT_EQ(10 * kNumMicrosPerMilli, config_.ReceivedInitialRoundTripTimeUs());
144 EXPECT_EQ(config_.ReceivedInitialStreamFlowControlWindowBytes(),
145 2 * kInitialStreamFlowControlWindowForTest);
146 EXPECT_EQ(config_.ReceivedInitialSessionFlowControlWindowBytes(),
147 2 * kInitialSessionFlowControlWindowForTest);
148 EXPECT_TRUE(config_.HasReceivedAlternateServerAddress());
149 EXPECT_EQ(kTestServerAddress, config_.ReceivedAlternateServerAddress());
150 EXPECT_TRUE(config_.HasReceivedStatelessResetToken());
151 EXPECT_EQ(kTestResetToken, config_.ReceivedStatelessResetToken());
fkastenholz4c7303c2019-07-29 08:17:07 -0700152 if (GetQuicReloadableFlag(quic_negotiate_ack_delay_time)) {
153 EXPECT_TRUE(config_.HasReceivedMaxAckDelayMs());
154 EXPECT_EQ(kTestMaxAckDelayMs, config_.ReceivedMaxAckDelayMs());
155 } else {
156 EXPECT_FALSE(config_.HasReceivedMaxAckDelayMs());
157 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500158}
159
fkastenholzd3a1de92019-05-15 07:00:07 -0700160TEST_P(QuicConfigTest, MissingOptionalValuesInCHLO) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500161 CryptoHandshakeMessage msg;
162 msg.SetValue(kICSL, 1);
163
164 // Set all REQUIRED tags.
165 msg.SetValue(kICSL, 1);
fkastenholzd3a1de92019-05-15 07:00:07 -0700166 msg.SetValue(kMIBS, 1);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500167
168 // No error, as rest are optional.
vasilvvc48c8712019-03-11 13:38:16 -0700169 std::string error_details;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500170 const QuicErrorCode error =
171 config_.ProcessPeerHello(msg, CLIENT, &error_details);
172 EXPECT_EQ(QUIC_NO_ERROR, error);
173 EXPECT_TRUE(config_.negotiated());
174}
175
fkastenholzd3a1de92019-05-15 07:00:07 -0700176TEST_P(QuicConfigTest, MissingOptionalValuesInSHLO) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500177 CryptoHandshakeMessage msg;
178
179 // Set all REQUIRED tags.
180 msg.SetValue(kICSL, 1);
fkastenholzd3a1de92019-05-15 07:00:07 -0700181 msg.SetValue(kMIBS, 1);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500182
183 // No error, as rest are optional.
vasilvvc48c8712019-03-11 13:38:16 -0700184 std::string error_details;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500185 const QuicErrorCode error =
186 config_.ProcessPeerHello(msg, SERVER, &error_details);
187 EXPECT_EQ(QUIC_NO_ERROR, error);
188 EXPECT_TRUE(config_.negotiated());
189}
190
fkastenholzd3a1de92019-05-15 07:00:07 -0700191TEST_P(QuicConfigTest, MissingValueInCHLO) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500192 // Server receives CHLO with missing kICSL.
193 CryptoHandshakeMessage msg;
vasilvvc48c8712019-03-11 13:38:16 -0700194 std::string error_details;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500195 const QuicErrorCode error =
196 config_.ProcessPeerHello(msg, CLIENT, &error_details);
197 EXPECT_EQ(QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND, error);
198}
199
fkastenholzd3a1de92019-05-15 07:00:07 -0700200TEST_P(QuicConfigTest, MissingValueInSHLO) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500201 // Client receives SHLO with missing kICSL.
202 CryptoHandshakeMessage msg;
vasilvvc48c8712019-03-11 13:38:16 -0700203 std::string error_details;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500204 const QuicErrorCode error =
205 config_.ProcessPeerHello(msg, SERVER, &error_details);
206 EXPECT_EQ(QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND, error);
207}
208
fkastenholzd3a1de92019-05-15 07:00:07 -0700209TEST_P(QuicConfigTest, OutOfBoundSHLO) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500210 QuicConfig server_config;
211 server_config.SetIdleNetworkTimeout(
212 QuicTime::Delta::FromSeconds(2 * kMaximumIdleTimeoutSecs),
213 QuicTime::Delta::FromSeconds(2 * kMaximumIdleTimeoutSecs));
214
215 CryptoHandshakeMessage msg;
fkastenholzd3a1de92019-05-15 07:00:07 -0700216 server_config.ToHandshakeMessage(&msg, GetParam());
vasilvvc48c8712019-03-11 13:38:16 -0700217 std::string error_details;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500218 const QuicErrorCode error =
219 config_.ProcessPeerHello(msg, SERVER, &error_details);
220 EXPECT_EQ(QUIC_INVALID_NEGOTIATED_VALUE, error);
221}
222
fkastenholzd3a1de92019-05-15 07:00:07 -0700223TEST_P(QuicConfigTest, InvalidFlowControlWindow) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500224 // QuicConfig should not accept an invalid flow control window to send to the
225 // peer: the receive window must be at least the default of 16 Kb.
226 QuicConfig config;
227 const uint64_t kInvalidWindow = kMinimumFlowControlSendWindow - 1;
228 EXPECT_QUIC_BUG(
229 config.SetInitialStreamFlowControlWindowToSend(kInvalidWindow),
230 "Initial stream flow control receive window");
231
232 EXPECT_EQ(kMinimumFlowControlSendWindow,
233 config.GetInitialStreamFlowControlWindowToSend());
234}
235
fkastenholzd3a1de92019-05-15 07:00:07 -0700236TEST_P(QuicConfigTest, HasClientSentConnectionOption) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500237 QuicConfig client_config;
238 QuicTagVector copt;
239 copt.push_back(kTBBR);
240 client_config.SetConnectionOptionsToSend(copt);
241 EXPECT_TRUE(client_config.HasClientSentConnectionOption(
242 kTBBR, Perspective::IS_CLIENT));
243
244 CryptoHandshakeMessage msg;
fkastenholzd3a1de92019-05-15 07:00:07 -0700245 client_config.ToHandshakeMessage(&msg, GetParam());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500246
vasilvvc48c8712019-03-11 13:38:16 -0700247 std::string error_details;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500248 const QuicErrorCode error =
249 config_.ProcessPeerHello(msg, CLIENT, &error_details);
250 EXPECT_EQ(QUIC_NO_ERROR, error);
251 EXPECT_TRUE(config_.negotiated());
252
253 EXPECT_TRUE(config_.HasReceivedConnectionOptions());
254 EXPECT_EQ(1u, config_.ReceivedConnectionOptions().size());
255 EXPECT_TRUE(
256 config_.HasClientSentConnectionOption(kTBBR, Perspective::IS_SERVER));
257}
258
fkastenholzd3a1de92019-05-15 07:00:07 -0700259TEST_P(QuicConfigTest, DontSendClientConnectionOptions) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500260 QuicConfig client_config;
261 QuicTagVector copt;
262 copt.push_back(kTBBR);
263 client_config.SetClientConnectionOptions(copt);
264
265 CryptoHandshakeMessage msg;
fkastenholzd3a1de92019-05-15 07:00:07 -0700266 client_config.ToHandshakeMessage(&msg, GetParam());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500267
vasilvvc48c8712019-03-11 13:38:16 -0700268 std::string error_details;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500269 const QuicErrorCode error =
270 config_.ProcessPeerHello(msg, CLIENT, &error_details);
271 EXPECT_EQ(QUIC_NO_ERROR, error);
272 EXPECT_TRUE(config_.negotiated());
273
274 EXPECT_FALSE(config_.HasReceivedConnectionOptions());
275}
276
fkastenholzd3a1de92019-05-15 07:00:07 -0700277TEST_P(QuicConfigTest, HasClientRequestedIndependentOption) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500278 QuicConfig client_config;
279 QuicTagVector client_opt;
280 client_opt.push_back(kRENO);
281 QuicTagVector copt;
282 copt.push_back(kTBBR);
283 client_config.SetClientConnectionOptions(client_opt);
284 client_config.SetConnectionOptionsToSend(copt);
285 EXPECT_TRUE(client_config.HasClientSentConnectionOption(
286 kTBBR, Perspective::IS_CLIENT));
287 EXPECT_TRUE(client_config.HasClientRequestedIndependentOption(
288 kRENO, Perspective::IS_CLIENT));
289 EXPECT_FALSE(client_config.HasClientRequestedIndependentOption(
290 kTBBR, Perspective::IS_CLIENT));
291
292 CryptoHandshakeMessage msg;
fkastenholzd3a1de92019-05-15 07:00:07 -0700293 client_config.ToHandshakeMessage(&msg, GetParam());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500294
vasilvvc48c8712019-03-11 13:38:16 -0700295 std::string error_details;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500296 const QuicErrorCode error =
297 config_.ProcessPeerHello(msg, CLIENT, &error_details);
298 EXPECT_EQ(QUIC_NO_ERROR, error);
299 EXPECT_TRUE(config_.negotiated());
300
301 EXPECT_TRUE(config_.HasReceivedConnectionOptions());
302 EXPECT_EQ(1u, config_.ReceivedConnectionOptions().size());
303 EXPECT_FALSE(config_.HasClientRequestedIndependentOption(
304 kRENO, Perspective::IS_SERVER));
305 EXPECT_TRUE(config_.HasClientRequestedIndependentOption(
306 kTBBR, Perspective::IS_SERVER));
307}
308
309} // namespace
310} // namespace test
311} // namespace quic