1 // Copyright 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 "quiche/quic/core/quic_connection_id_manager.h"
6
7 #include <cstddef>
8
9 #include "quiche/quic/core/frames/quic_retire_connection_id_frame.h"
10 #include "quiche/quic/core/quic_connection_id.h"
11 #include "quiche/quic/core/quic_error_codes.h"
12 #include "quiche/quic/platform/api/quic_flags.h"
13 #include "quiche/quic/platform/api/quic_test.h"
14 #include "quiche/quic/test_tools/mock_clock.h"
15 #include "quiche/quic/test_tools/mock_connection_id_generator.h"
16 #include "quiche/quic/test_tools/quic_connection_id_manager_peer.h"
17 #include "quiche/quic/test_tools/quic_test_utils.h"
18
19 namespace quic::test {
20 namespace {
21
22 using ::quic::test::IsError;
23 using ::quic::test::IsQuicNoError;
24 using ::quic::test::QuicConnectionIdManagerPeer;
25 using ::quic::test::TestConnectionId;
26 using ::testing::_;
27 using ::testing::ElementsAre;
28 using ::testing::IsNull;
29 using ::testing::Return;
30 using ::testing::StrictMock;
31
32 class TestPeerIssuedConnectionIdManagerVisitor
33 : public QuicConnectionIdManagerVisitorInterface {
34 public:
SetPeerIssuedConnectionIdManager(QuicPeerIssuedConnectionIdManager * peer_issued_connection_id_manager)35 void SetPeerIssuedConnectionIdManager(
36 QuicPeerIssuedConnectionIdManager* peer_issued_connection_id_manager) {
37 peer_issued_connection_id_manager_ = peer_issued_connection_id_manager;
38 }
39
OnPeerIssuedConnectionIdRetired()40 void OnPeerIssuedConnectionIdRetired() override {
41 // Replace current connection Id if it has been retired.
42 if (!peer_issued_connection_id_manager_->IsConnectionIdActive(
43 current_peer_issued_connection_id_)) {
44 current_peer_issued_connection_id_ =
45 peer_issued_connection_id_manager_->ConsumeOneUnusedConnectionId()
46 ->connection_id;
47 }
48 // Retire all the to-be-retired connection Ids.
49 most_recent_retired_connection_id_sequence_numbers_ =
50 peer_issued_connection_id_manager_
51 ->ConsumeToBeRetiredConnectionIdSequenceNumbers();
52 }
53
54 const std::vector<uint64_t>&
most_recent_retired_connection_id_sequence_numbers()55 most_recent_retired_connection_id_sequence_numbers() {
56 return most_recent_retired_connection_id_sequence_numbers_;
57 }
58
SetCurrentPeerConnectionId(QuicConnectionId cid)59 void SetCurrentPeerConnectionId(QuicConnectionId cid) {
60 current_peer_issued_connection_id_ = cid;
61 }
62
GetCurrentPeerConnectionId()63 const QuicConnectionId& GetCurrentPeerConnectionId() {
64 return current_peer_issued_connection_id_;
65 }
66
SendNewConnectionId(const QuicNewConnectionIdFrame &)67 bool SendNewConnectionId(const QuicNewConnectionIdFrame& /*frame*/) override {
68 return false;
69 }
MaybeReserveConnectionId(const QuicConnectionId &)70 bool MaybeReserveConnectionId(const QuicConnectionId&) override {
71 return false;
72 }
73
OnSelfIssuedConnectionIdRetired(const QuicConnectionId &)74 void OnSelfIssuedConnectionIdRetired(
75 const QuicConnectionId& /*connection_id*/) override {}
76
77 private:
78 QuicPeerIssuedConnectionIdManager* peer_issued_connection_id_manager_ =
79 nullptr;
80 QuicConnectionId current_peer_issued_connection_id_;
81 std::vector<uint64_t> most_recent_retired_connection_id_sequence_numbers_;
82 };
83
84 class QuicPeerIssuedConnectionIdManagerTest : public QuicTest {
85 public:
QuicPeerIssuedConnectionIdManagerTest()86 QuicPeerIssuedConnectionIdManagerTest()
87 : peer_issued_cid_manager_(
88 /*active_connection_id_limit=*/2, initial_connection_id_, &clock_,
89 &alarm_factory_, &cid_manager_visitor_, /*context=*/nullptr) {
90 clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10));
91 cid_manager_visitor_.SetPeerIssuedConnectionIdManager(
92 &peer_issued_cid_manager_);
93 cid_manager_visitor_.SetCurrentPeerConnectionId(initial_connection_id_);
94 retire_peer_issued_cid_alarm_ =
95 QuicConnectionIdManagerPeer::GetRetirePeerIssuedConnectionIdAlarm(
96 &peer_issued_cid_manager_);
97 }
98
99 protected:
100 MockClock clock_;
101 test::MockAlarmFactory alarm_factory_;
102 TestPeerIssuedConnectionIdManagerVisitor cid_manager_visitor_;
103 QuicConnectionId initial_connection_id_ = TestConnectionId(0);
104 QuicPeerIssuedConnectionIdManager peer_issued_cid_manager_;
105 QuicAlarm* retire_peer_issued_cid_alarm_ = nullptr;
106 std::string error_details_;
107 bool duplicate_frame_ = false;
108 };
109
TEST_F(QuicPeerIssuedConnectionIdManagerTest,ConnectionIdSequenceWhenMigrationSucceed)110 TEST_F(QuicPeerIssuedConnectionIdManagerTest,
111 ConnectionIdSequenceWhenMigrationSucceed) {
112 {
113 // Receives CID #1 from peer.
114 QuicNewConnectionIdFrame frame;
115 frame.connection_id = TestConnectionId(1);
116 frame.sequence_number = 1u;
117 frame.retire_prior_to = 0u;
118 frame.stateless_reset_token =
119 QuicUtils::GenerateStatelessResetToken(frame.connection_id);
120 ASSERT_THAT(peer_issued_cid_manager_.OnNewConnectionIdFrame(
121 frame, &error_details_, &duplicate_frame_),
122 IsQuicNoError());
123
124 // Start to use CID #1 for alternative path.
125 const QuicConnectionIdData* aternative_connection_id_data =
126 peer_issued_cid_manager_.ConsumeOneUnusedConnectionId();
127 ASSERT_THAT(aternative_connection_id_data, testing::NotNull());
128 EXPECT_EQ(aternative_connection_id_data->connection_id,
129 TestConnectionId(1));
130 EXPECT_EQ(aternative_connection_id_data->stateless_reset_token,
131 frame.stateless_reset_token);
132
133 // Connection migration succeed. Prepares to retire CID #0.
134 peer_issued_cid_manager_.MaybeRetireUnusedConnectionIds(
135 {TestConnectionId(1)});
136 cid_manager_visitor_.SetCurrentPeerConnectionId(TestConnectionId(1));
137 ASSERT_TRUE(retire_peer_issued_cid_alarm_->IsSet());
138 alarm_factory_.FireAlarm(retire_peer_issued_cid_alarm_);
139 EXPECT_THAT(cid_manager_visitor_
140 .most_recent_retired_connection_id_sequence_numbers(),
141 ElementsAre(0u));
142 }
143
144 {
145 // Receives CID #2 from peer since CID #0 is retired.
146 QuicNewConnectionIdFrame frame;
147 frame.connection_id = TestConnectionId(2);
148 frame.sequence_number = 2u;
149 frame.retire_prior_to = 1u;
150 frame.stateless_reset_token =
151 QuicUtils::GenerateStatelessResetToken(frame.connection_id);
152 ASSERT_THAT(peer_issued_cid_manager_.OnNewConnectionIdFrame(
153 frame, &error_details_, &duplicate_frame_),
154 IsQuicNoError());
155 // Start to use CID #2 for alternative path.
156 peer_issued_cid_manager_.ConsumeOneUnusedConnectionId();
157 // Connection migration succeed. Prepares to retire CID #1.
158 peer_issued_cid_manager_.MaybeRetireUnusedConnectionIds(
159 {TestConnectionId(2)});
160 cid_manager_visitor_.SetCurrentPeerConnectionId(TestConnectionId(2));
161 ASSERT_TRUE(retire_peer_issued_cid_alarm_->IsSet());
162 alarm_factory_.FireAlarm(retire_peer_issued_cid_alarm_);
163 EXPECT_THAT(cid_manager_visitor_
164 .most_recent_retired_connection_id_sequence_numbers(),
165 ElementsAre(1u));
166 }
167
168 {
169 // Receives CID #3 from peer since CID #1 is retired.
170 QuicNewConnectionIdFrame frame;
171 frame.connection_id = TestConnectionId(3);
172 frame.sequence_number = 3u;
173 frame.retire_prior_to = 2u;
174 frame.stateless_reset_token =
175 QuicUtils::GenerateStatelessResetToken(frame.connection_id);
176 ASSERT_THAT(peer_issued_cid_manager_.OnNewConnectionIdFrame(
177 frame, &error_details_, &duplicate_frame_),
178 IsQuicNoError());
179 // Start to use CID #3 for alternative path.
180 peer_issued_cid_manager_.ConsumeOneUnusedConnectionId();
181 // Connection migration succeed. Prepares to retire CID #2.
182 peer_issued_cid_manager_.MaybeRetireUnusedConnectionIds(
183 {TestConnectionId(3)});
184 cid_manager_visitor_.SetCurrentPeerConnectionId(TestConnectionId(3));
185 ASSERT_TRUE(retire_peer_issued_cid_alarm_->IsSet());
186 alarm_factory_.FireAlarm(retire_peer_issued_cid_alarm_);
187 EXPECT_THAT(cid_manager_visitor_
188 .most_recent_retired_connection_id_sequence_numbers(),
189 ElementsAre(2u));
190 }
191
192 {
193 // Receives CID #4 from peer since CID #2 is retired.
194 QuicNewConnectionIdFrame frame;
195 frame.connection_id = TestConnectionId(4);
196 frame.sequence_number = 4u;
197 frame.retire_prior_to = 3u;
198 frame.stateless_reset_token =
199 QuicUtils::GenerateStatelessResetToken(frame.connection_id);
200 ASSERT_THAT(peer_issued_cid_manager_.OnNewConnectionIdFrame(
201 frame, &error_details_, &duplicate_frame_),
202 IsQuicNoError());
203 }
204 }
205
TEST_F(QuicPeerIssuedConnectionIdManagerTest,ConnectionIdSequenceWhenMigrationFail)206 TEST_F(QuicPeerIssuedConnectionIdManagerTest,
207 ConnectionIdSequenceWhenMigrationFail) {
208 {
209 // Receives CID #1 from peer.
210 QuicNewConnectionIdFrame frame;
211 frame.connection_id = TestConnectionId(1);
212 frame.sequence_number = 1u;
213 frame.retire_prior_to = 0u;
214 frame.stateless_reset_token =
215 QuicUtils::GenerateStatelessResetToken(frame.connection_id);
216 ASSERT_THAT(peer_issued_cid_manager_.OnNewConnectionIdFrame(
217 frame, &error_details_, &duplicate_frame_),
218 IsQuicNoError());
219 // Start to use CID #1 for alternative path.
220 peer_issued_cid_manager_.ConsumeOneUnusedConnectionId();
221 // Connection migration fails. Prepares to retire CID #1.
222 peer_issued_cid_manager_.MaybeRetireUnusedConnectionIds(
223 {initial_connection_id_});
224 // Actually retires CID #1.
225 ASSERT_TRUE(retire_peer_issued_cid_alarm_->IsSet());
226 alarm_factory_.FireAlarm(retire_peer_issued_cid_alarm_);
227 EXPECT_THAT(cid_manager_visitor_
228 .most_recent_retired_connection_id_sequence_numbers(),
229 ElementsAre(1u));
230 }
231
232 {
233 // Receives CID #2 from peer since CID #1 is retired.
234 QuicNewConnectionIdFrame frame;
235 frame.connection_id = TestConnectionId(2);
236 frame.sequence_number = 2u;
237 frame.retire_prior_to = 0u;
238 frame.stateless_reset_token =
239 QuicUtils::GenerateStatelessResetToken(frame.connection_id);
240 ASSERT_THAT(peer_issued_cid_manager_.OnNewConnectionIdFrame(
241 frame, &error_details_, &duplicate_frame_),
242 IsQuicNoError());
243 // Start to use CID #2 for alternative path.
244 peer_issued_cid_manager_.ConsumeOneUnusedConnectionId();
245 // Connection migration fails again. Prepares to retire CID #2.
246 peer_issued_cid_manager_.MaybeRetireUnusedConnectionIds(
247 {initial_connection_id_});
248 // Actually retires CID #2.
249 ASSERT_TRUE(retire_peer_issued_cid_alarm_->IsSet());
250 alarm_factory_.FireAlarm(retire_peer_issued_cid_alarm_);
251 EXPECT_THAT(cid_manager_visitor_
252 .most_recent_retired_connection_id_sequence_numbers(),
253 ElementsAre(2u));
254 }
255
256 {
257 // Receives CID #3 from peer since CID #2 is retired.
258 QuicNewConnectionIdFrame frame;
259 frame.connection_id = TestConnectionId(3);
260 frame.sequence_number = 3u;
261 frame.retire_prior_to = 0u;
262 frame.stateless_reset_token =
263 QuicUtils::GenerateStatelessResetToken(frame.connection_id);
264 ASSERT_THAT(peer_issued_cid_manager_.OnNewConnectionIdFrame(
265 frame, &error_details_, &duplicate_frame_),
266 IsQuicNoError());
267 // Start to use CID #3 for alternative path.
268 peer_issued_cid_manager_.ConsumeOneUnusedConnectionId();
269 // Connection migration succeed. Prepares to retire CID #0.
270 peer_issued_cid_manager_.MaybeRetireUnusedConnectionIds(
271 {TestConnectionId(3)});
272 // After CID #3 is default (i.e., when there is no pending frame to write
273 // associated with CID #0), #0 can actually be retired.
274 cid_manager_visitor_.SetCurrentPeerConnectionId(TestConnectionId(3));
275 ASSERT_TRUE(retire_peer_issued_cid_alarm_->IsSet());
276 alarm_factory_.FireAlarm(retire_peer_issued_cid_alarm_);
277 EXPECT_THAT(cid_manager_visitor_
278 .most_recent_retired_connection_id_sequence_numbers(),
279 ElementsAre(0u));
280 }
281
282 {
283 // Receives CID #4 from peer since CID #0 is retired.
284 QuicNewConnectionIdFrame frame;
285 frame.connection_id = TestConnectionId(4);
286 frame.sequence_number = 4u;
287 frame.retire_prior_to = 3u;
288 frame.stateless_reset_token =
289 QuicUtils::GenerateStatelessResetToken(frame.connection_id);
290 EXPECT_THAT(peer_issued_cid_manager_.OnNewConnectionIdFrame(
291 frame, &error_details_, &duplicate_frame_),
292 IsQuicNoError());
293 EXPECT_FALSE(retire_peer_issued_cid_alarm_->IsSet());
294 }
295 }
296
TEST_F(QuicPeerIssuedConnectionIdManagerTest,ReceivesNewConnectionIdOutOfOrder)297 TEST_F(QuicPeerIssuedConnectionIdManagerTest,
298 ReceivesNewConnectionIdOutOfOrder) {
299 {
300 // Receives new CID #1 that retires prior to #0.
301 // Outcome: (active: #0 unused: #1)
302 QuicNewConnectionIdFrame frame;
303 frame.connection_id = TestConnectionId(1);
304 frame.sequence_number = 1u;
305 frame.retire_prior_to = 0u;
306 frame.stateless_reset_token =
307 QuicUtils::GenerateStatelessResetToken(frame.connection_id);
308 ASSERT_THAT(peer_issued_cid_manager_.OnNewConnectionIdFrame(
309 frame, &error_details_, &duplicate_frame_),
310 IsQuicNoError());
311 // Start to use CID #1 for alternative path.
312 // Outcome: (active: #0 #1 unused: None)
313 peer_issued_cid_manager_.ConsumeOneUnusedConnectionId();
314 }
315
316 {
317 // Receives new CID #3 that retires prior to #2.
318 // Outcome: (active: None unused: #3)
319 QuicNewConnectionIdFrame frame;
320 frame.connection_id = TestConnectionId(3);
321 frame.sequence_number = 3u;
322 frame.retire_prior_to = 2u;
323 frame.stateless_reset_token =
324 QuicUtils::GenerateStatelessResetToken(frame.connection_id);
325 ASSERT_THAT(peer_issued_cid_manager_.OnNewConnectionIdFrame(
326 frame, &error_details_, &duplicate_frame_),
327 IsQuicNoError());
328 }
329
330 {
331 // Receives new CID #2 that retires prior to #1.
332 // Outcome: (active: None unused: #3, #2)
333 QuicNewConnectionIdFrame frame;
334 frame.connection_id = TestConnectionId(2);
335 frame.sequence_number = 2u;
336 frame.retire_prior_to = 1u;
337 frame.stateless_reset_token =
338 QuicUtils::GenerateStatelessResetToken(frame.connection_id);
339 ASSERT_THAT(peer_issued_cid_manager_.OnNewConnectionIdFrame(
340 frame, &error_details_, &duplicate_frame_),
341 IsQuicNoError());
342 }
343
344 {
345 EXPECT_FALSE(
346 peer_issued_cid_manager_.IsConnectionIdActive(TestConnectionId(0)));
347 EXPECT_FALSE(
348 peer_issued_cid_manager_.IsConnectionIdActive(TestConnectionId(1)));
349 // When there is no frame associated with #0 and #1 to write, replace the
350 // in-use CID with an unused CID (#2) and retires #0 & #1.
351 ASSERT_TRUE(retire_peer_issued_cid_alarm_->IsSet());
352 alarm_factory_.FireAlarm(retire_peer_issued_cid_alarm_);
353 EXPECT_THAT(cid_manager_visitor_
354 .most_recent_retired_connection_id_sequence_numbers(),
355 ElementsAre(0u, 1u));
356 EXPECT_EQ(cid_manager_visitor_.GetCurrentPeerConnectionId(),
357 TestConnectionId(2));
358 // Get another unused CID for path validation.
359 EXPECT_EQ(
360 peer_issued_cid_manager_.ConsumeOneUnusedConnectionId()->connection_id,
361 TestConnectionId(3));
362 }
363 }
364
TEST_F(QuicPeerIssuedConnectionIdManagerTest,VisitedNewConnectionIdFrameIsIgnored)365 TEST_F(QuicPeerIssuedConnectionIdManagerTest,
366 VisitedNewConnectionIdFrameIsIgnored) {
367 // Receives new CID #1 that retires prior to #0.
368 // Outcome: (active: #0 unused: #1)
369 QuicNewConnectionIdFrame frame;
370 frame.connection_id = TestConnectionId(1);
371 frame.sequence_number = 1u;
372 frame.retire_prior_to = 0u;
373 frame.stateless_reset_token =
374 QuicUtils::GenerateStatelessResetToken(frame.connection_id);
375 ASSERT_THAT(peer_issued_cid_manager_.OnNewConnectionIdFrame(
376 frame, &error_details_, &duplicate_frame_),
377 IsQuicNoError());
378 // Start to use CID #1 for alternative path.
379 // Outcome: (active: #0 #1 unused: None)
380 peer_issued_cid_manager_.ConsumeOneUnusedConnectionId();
381 // Prepare to retire CID #1 as path validation fails.
382 peer_issued_cid_manager_.MaybeRetireUnusedConnectionIds(
383 {initial_connection_id_});
384 // Actually retires CID #1.
385 ASSERT_TRUE(retire_peer_issued_cid_alarm_->IsSet());
386 alarm_factory_.FireAlarm(retire_peer_issued_cid_alarm_);
387 EXPECT_THAT(
388 cid_manager_visitor_.most_recent_retired_connection_id_sequence_numbers(),
389 ElementsAre(1u));
390 // Receives the same frame again. Should be a no-op.
391 ASSERT_THAT(peer_issued_cid_manager_.OnNewConnectionIdFrame(
392 frame, &error_details_, &duplicate_frame_),
393 IsQuicNoError());
394 EXPECT_EQ(true, duplicate_frame_);
395 EXPECT_THAT(peer_issued_cid_manager_.ConsumeOneUnusedConnectionId(),
396 testing::IsNull());
397 }
398
TEST_F(QuicPeerIssuedConnectionIdManagerTest,ErrorWhenActiveConnectionIdLimitExceeded)399 TEST_F(QuicPeerIssuedConnectionIdManagerTest,
400 ErrorWhenActiveConnectionIdLimitExceeded) {
401 {
402 // Receives new CID #1 that retires prior to #0.
403 // Outcome: (active: #0 unused: #1)
404 QuicNewConnectionIdFrame frame;
405 frame.connection_id = TestConnectionId(1);
406 frame.sequence_number = 1u;
407 frame.retire_prior_to = 0u;
408 frame.stateless_reset_token =
409 QuicUtils::GenerateStatelessResetToken(frame.connection_id);
410 ASSERT_THAT(peer_issued_cid_manager_.OnNewConnectionIdFrame(
411 frame, &error_details_, &duplicate_frame_),
412 IsQuicNoError());
413 }
414
415 {
416 QuicNewConnectionIdFrame frame;
417 frame.connection_id = TestConnectionId(2);
418 frame.sequence_number = 2u;
419 frame.retire_prior_to = 0u;
420 frame.stateless_reset_token =
421 QuicUtils::GenerateStatelessResetToken(frame.connection_id);
422 ASSERT_THAT(peer_issued_cid_manager_.OnNewConnectionIdFrame(
423 frame, &error_details_, &duplicate_frame_),
424 IsError(QUIC_CONNECTION_ID_LIMIT_ERROR));
425 }
426 }
427
TEST_F(QuicPeerIssuedConnectionIdManagerTest,ErrorWhenTheSameConnectionIdIsSeenWithDifferentSequenceNumbers)428 TEST_F(QuicPeerIssuedConnectionIdManagerTest,
429 ErrorWhenTheSameConnectionIdIsSeenWithDifferentSequenceNumbers) {
430 {
431 QuicNewConnectionIdFrame frame;
432 frame.connection_id = TestConnectionId(1);
433 frame.sequence_number = 1u;
434 frame.retire_prior_to = 0u;
435 frame.stateless_reset_token =
436 QuicUtils::GenerateStatelessResetToken(frame.connection_id);
437 ASSERT_THAT(peer_issued_cid_manager_.OnNewConnectionIdFrame(
438 frame, &error_details_, &duplicate_frame_),
439 IsQuicNoError());
440 }
441
442 {
443 QuicNewConnectionIdFrame frame;
444 frame.connection_id = TestConnectionId(1);
445 frame.sequence_number = 2u;
446 frame.retire_prior_to = 1u;
447 frame.stateless_reset_token =
448 QuicUtils::GenerateStatelessResetToken(TestConnectionId(2));
449 ASSERT_THAT(peer_issued_cid_manager_.OnNewConnectionIdFrame(
450 frame, &error_details_, &duplicate_frame_),
451 IsError(IETF_QUIC_PROTOCOL_VIOLATION));
452 }
453 }
454
TEST_F(QuicPeerIssuedConnectionIdManagerTest,NewConnectionIdFrameWithTheSameSequenceNumberIsIgnored)455 TEST_F(QuicPeerIssuedConnectionIdManagerTest,
456 NewConnectionIdFrameWithTheSameSequenceNumberIsIgnored) {
457 {
458 QuicNewConnectionIdFrame frame;
459 frame.connection_id = TestConnectionId(1);
460 frame.sequence_number = 1u;
461 frame.retire_prior_to = 0u;
462 frame.stateless_reset_token =
463 QuicUtils::GenerateStatelessResetToken(frame.connection_id);
464 ASSERT_THAT(peer_issued_cid_manager_.OnNewConnectionIdFrame(
465 frame, &error_details_, &duplicate_frame_),
466 IsQuicNoError());
467 }
468
469 {
470 QuicNewConnectionIdFrame frame;
471 frame.connection_id = TestConnectionId(2);
472 frame.sequence_number = 1u;
473 frame.retire_prior_to = 0u;
474 frame.stateless_reset_token =
475 QuicUtils::GenerateStatelessResetToken(TestConnectionId(2));
476 EXPECT_THAT(peer_issued_cid_manager_.OnNewConnectionIdFrame(
477 frame, &error_details_, &duplicate_frame_),
478 IsQuicNoError());
479 EXPECT_EQ(true, duplicate_frame_);
480 EXPECT_EQ(
481 peer_issued_cid_manager_.ConsumeOneUnusedConnectionId()->connection_id,
482 TestConnectionId(1));
483 EXPECT_THAT(peer_issued_cid_manager_.ConsumeOneUnusedConnectionId(),
484 IsNull());
485 }
486 }
487
TEST_F(QuicPeerIssuedConnectionIdManagerTest,ErrorWhenThereAreTooManyGapsInIssuedConnectionIdSequenceNumbers)488 TEST_F(QuicPeerIssuedConnectionIdManagerTest,
489 ErrorWhenThereAreTooManyGapsInIssuedConnectionIdSequenceNumbers) {
490 // Add 20 intervals: [0, 1), [2, 3), ..., [38,39)
491 for (int i = 2; i <= 38; i += 2) {
492 QuicNewConnectionIdFrame frame;
493 frame.connection_id = TestConnectionId(i);
494 frame.sequence_number = i;
495 frame.retire_prior_to = i;
496 frame.stateless_reset_token =
497 QuicUtils::GenerateStatelessResetToken(frame.connection_id);
498 ASSERT_THAT(peer_issued_cid_manager_.OnNewConnectionIdFrame(
499 frame, &error_details_, &duplicate_frame_),
500 IsQuicNoError());
501 }
502
503 // Interval [40, 41) goes over the limit.
504 QuicNewConnectionIdFrame frame;
505 frame.connection_id = TestConnectionId(40);
506 frame.sequence_number = 40u;
507 frame.retire_prior_to = 40u;
508 frame.stateless_reset_token =
509 QuicUtils::GenerateStatelessResetToken(frame.connection_id);
510 ASSERT_THAT(peer_issued_cid_manager_.OnNewConnectionIdFrame(
511 frame, &error_details_, &duplicate_frame_),
512 IsError(IETF_QUIC_PROTOCOL_VIOLATION));
513 }
514
TEST_F(QuicPeerIssuedConnectionIdManagerTest,ReplaceConnectionId)515 TEST_F(QuicPeerIssuedConnectionIdManagerTest, ReplaceConnectionId) {
516 ASSERT_TRUE(
517 peer_issued_cid_manager_.IsConnectionIdActive(initial_connection_id_));
518 peer_issued_cid_manager_.ReplaceConnectionId(initial_connection_id_,
519 TestConnectionId(1));
520 EXPECT_FALSE(
521 peer_issued_cid_manager_.IsConnectionIdActive(initial_connection_id_));
522 EXPECT_TRUE(
523 peer_issued_cid_manager_.IsConnectionIdActive(TestConnectionId(1)));
524 }
525
526 class TestSelfIssuedConnectionIdManagerVisitor
527 : public QuicConnectionIdManagerVisitorInterface {
528 public:
OnPeerIssuedConnectionIdRetired()529 void OnPeerIssuedConnectionIdRetired() override {}
530
531 MOCK_METHOD(bool, SendNewConnectionId,
532 (const QuicNewConnectionIdFrame& frame), (override));
533 MOCK_METHOD(bool, MaybeReserveConnectionId,
534 (const QuicConnectionId& connection_id), (override));
535 MOCK_METHOD(void, OnSelfIssuedConnectionIdRetired,
536 (const QuicConnectionId& connection_id), (override));
537 };
538
539 class QuicSelfIssuedConnectionIdManagerTest : public QuicTest {
540 public:
QuicSelfIssuedConnectionIdManagerTest()541 QuicSelfIssuedConnectionIdManagerTest()
542 : cid_manager_(/*active_connection_id_limit*/ 2, initial_connection_id_,
543 &clock_, &alarm_factory_, &cid_manager_visitor_,
544 /*context=*/nullptr, connection_id_generator_) {
545 clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10));
546 retire_self_issued_cid_alarm_ =
547 QuicConnectionIdManagerPeer::GetRetireSelfIssuedConnectionIdAlarm(
548 &cid_manager_);
549 }
550
551 protected:
552 // Verify that a call to GenerateNewConnectionId() does the right thing.
CheckGenerate(QuicConnectionId old_cid)553 QuicConnectionId CheckGenerate(QuicConnectionId old_cid) {
554 QuicConnectionId new_cid = old_cid;
555 (*new_cid.mutable_data())++;
556 // Ready for the actual call.
557 EXPECT_CALL(connection_id_generator_, GenerateNextConnectionId(old_cid))
558 .WillOnce(Return(new_cid));
559 return new_cid;
560 }
561
562 MockClock clock_;
563 test::MockAlarmFactory alarm_factory_;
564 TestSelfIssuedConnectionIdManagerVisitor cid_manager_visitor_;
565 QuicConnectionId initial_connection_id_ = TestConnectionId(0);
566 StrictMock<QuicSelfIssuedConnectionIdManager> cid_manager_;
567 QuicAlarm* retire_self_issued_cid_alarm_ = nullptr;
568 std::string error_details_;
569 QuicTime::Delta pto_delay_ = QuicTime::Delta::FromMilliseconds(10);
570 MockConnectionIdGenerator connection_id_generator_;
571 };
572
573 MATCHER_P3(ExpectedNewConnectionIdFrame, connection_id, sequence_number,
574 retire_prior_to, "") {
575 return (arg.connection_id == connection_id) &&
576 (arg.sequence_number == sequence_number) &&
577 (arg.retire_prior_to == retire_prior_to);
578 }
579
TEST_F(QuicSelfIssuedConnectionIdManagerTest,RetireSelfIssuedConnectionIdInOrder)580 TEST_F(QuicSelfIssuedConnectionIdManagerTest,
581 RetireSelfIssuedConnectionIdInOrder) {
582 QuicConnectionId cid0 = initial_connection_id_;
583 QuicConnectionId cid1 = CheckGenerate(cid0);
584 QuicConnectionId cid2 = CheckGenerate(cid1);
585 QuicConnectionId cid3 = CheckGenerate(cid2);
586 QuicConnectionId cid4 = CheckGenerate(cid3);
587 QuicConnectionId cid5 = CheckGenerate(cid4);
588
589 // Sends CID #1 to peer.
590 EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(cid1))
591 .WillOnce(Return(true));
592 EXPECT_CALL(cid_manager_visitor_,
593 SendNewConnectionId(ExpectedNewConnectionIdFrame(cid1, 1u, 0u)))
594 .WillOnce(Return(true));
595 cid_manager_.MaybeSendNewConnectionIds();
596
597 {
598 // Peer retires CID #0;
599 // Sends CID #2 and asks peer to retire CIDs prior to #1.
600 // Outcome: (#1, #2) are active.
601 EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(cid2))
602 .WillOnce(Return(true));
603 EXPECT_CALL(cid_manager_visitor_,
604 SendNewConnectionId(ExpectedNewConnectionIdFrame(cid2, 2u, 1u)))
605 .WillOnce(Return(true));
606 QuicRetireConnectionIdFrame retire_cid_frame;
607 retire_cid_frame.sequence_number = 0u;
608 ASSERT_THAT(cid_manager_.OnRetireConnectionIdFrame(
609 retire_cid_frame, pto_delay_, &error_details_),
610 IsQuicNoError());
611 }
612
613 {
614 // Peer retires CID #1;
615 // Sends CID #3 and asks peer to retire CIDs prior to #2.
616 // Outcome: (#2, #3) are active.
617 EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(cid3))
618 .WillOnce(Return(true));
619 EXPECT_CALL(cid_manager_visitor_,
620 SendNewConnectionId(ExpectedNewConnectionIdFrame(cid3, 3u, 2u)))
621 .WillOnce(Return(true));
622 QuicRetireConnectionIdFrame retire_cid_frame;
623 retire_cid_frame.sequence_number = 1u;
624 ASSERT_THAT(cid_manager_.OnRetireConnectionIdFrame(
625 retire_cid_frame, pto_delay_, &error_details_),
626 IsQuicNoError());
627 }
628
629 {
630 // Peer retires CID #2;
631 // Sends CID #4 and asks peer to retire CIDs prior to #3.
632 // Outcome: (#3, #4) are active.
633 EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(cid4))
634 .WillOnce(Return(true));
635 EXPECT_CALL(cid_manager_visitor_,
636 SendNewConnectionId(ExpectedNewConnectionIdFrame(cid4, 4u, 3u)))
637 .WillOnce(Return(true));
638 QuicRetireConnectionIdFrame retire_cid_frame;
639 retire_cid_frame.sequence_number = 2u;
640 ASSERT_THAT(cid_manager_.OnRetireConnectionIdFrame(
641 retire_cid_frame, pto_delay_, &error_details_),
642 IsQuicNoError());
643 }
644
645 {
646 // Peer retires CID #3;
647 // Sends CID #5 and asks peer to retire CIDs prior to #4.
648 // Outcome: (#4, #5) are active.
649 EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(cid5))
650 .WillOnce(Return(true));
651 EXPECT_CALL(cid_manager_visitor_,
652 SendNewConnectionId(ExpectedNewConnectionIdFrame(cid5, 5u, 4u)))
653 .WillOnce(Return(true));
654 QuicRetireConnectionIdFrame retire_cid_frame;
655 retire_cid_frame.sequence_number = 3u;
656 ASSERT_THAT(cid_manager_.OnRetireConnectionIdFrame(
657 retire_cid_frame, pto_delay_, &error_details_),
658 IsQuicNoError());
659 }
660 }
661
TEST_F(QuicSelfIssuedConnectionIdManagerTest,RetireSelfIssuedConnectionIdOutOfOrder)662 TEST_F(QuicSelfIssuedConnectionIdManagerTest,
663 RetireSelfIssuedConnectionIdOutOfOrder) {
664 QuicConnectionId cid0 = initial_connection_id_;
665 QuicConnectionId cid1 = CheckGenerate(cid0);
666 QuicConnectionId cid2 = CheckGenerate(cid1);
667 QuicConnectionId cid3 = CheckGenerate(cid2);
668 QuicConnectionId cid4 = CheckGenerate(cid3);
669
670 // Sends CID #1 to peer.
671 EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(cid1))
672 .WillOnce(Return(true));
673 EXPECT_CALL(cid_manager_visitor_,
674 SendNewConnectionId(ExpectedNewConnectionIdFrame(cid1, 1u, 0u)))
675 .WillOnce(Return(true));
676 cid_manager_.MaybeSendNewConnectionIds();
677
678 {
679 // Peer retires CID #1;
680 // Sends CID #2 and asks peer to retire CIDs prior to #0.
681 // Outcome: (#0, #2) are active.
682 EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(cid2))
683 .WillOnce(Return(true));
684 EXPECT_CALL(cid_manager_visitor_,
685 SendNewConnectionId(ExpectedNewConnectionIdFrame(cid2, 2u, 0u)))
686 .WillOnce(Return(true));
687 QuicRetireConnectionIdFrame retire_cid_frame;
688 retire_cid_frame.sequence_number = 1u;
689 ASSERT_THAT(cid_manager_.OnRetireConnectionIdFrame(
690 retire_cid_frame, pto_delay_, &error_details_),
691 IsQuicNoError());
692 }
693
694 {
695 // Peer retires CID #1 again. This is a no-op.
696 QuicRetireConnectionIdFrame retire_cid_frame;
697 retire_cid_frame.sequence_number = 1u;
698 ASSERT_THAT(cid_manager_.OnRetireConnectionIdFrame(
699 retire_cid_frame, pto_delay_, &error_details_),
700 IsQuicNoError());
701 }
702
703 {
704 // Peer retires CID #0;
705 // Sends CID #3 and asks peer to retire CIDs prior to #2.
706 // Outcome: (#2, #3) are active.
707 EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(cid3))
708 .WillOnce(Return(true));
709 EXPECT_CALL(cid_manager_visitor_,
710 SendNewConnectionId(ExpectedNewConnectionIdFrame(cid3, 3u, 2u)))
711 .WillOnce(Return(true));
712 QuicRetireConnectionIdFrame retire_cid_frame;
713 retire_cid_frame.sequence_number = 0u;
714 ASSERT_THAT(cid_manager_.OnRetireConnectionIdFrame(
715 retire_cid_frame, pto_delay_, &error_details_),
716 IsQuicNoError());
717 }
718
719 {
720 // Peer retires CID #3;
721 // Sends CID #4 and asks peer to retire CIDs prior to #2.
722 // Outcome: (#2, #4) are active.
723 EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(cid4))
724 .WillOnce(Return(true));
725 EXPECT_CALL(cid_manager_visitor_,
726 SendNewConnectionId(ExpectedNewConnectionIdFrame(cid4, 4u, 2u)))
727 .WillOnce(Return(true));
728 QuicRetireConnectionIdFrame retire_cid_frame;
729 retire_cid_frame.sequence_number = 3u;
730 ASSERT_THAT(cid_manager_.OnRetireConnectionIdFrame(
731 retire_cid_frame, pto_delay_, &error_details_),
732 IsQuicNoError());
733 }
734
735 {
736 // Peer retires CID #0 again. This is a no-op.
737 QuicRetireConnectionIdFrame retire_cid_frame;
738 retire_cid_frame.sequence_number = 0u;
739 ASSERT_THAT(cid_manager_.OnRetireConnectionIdFrame(
740 retire_cid_frame, pto_delay_, &error_details_),
741 IsQuicNoError());
742 }
743 }
744
TEST_F(QuicSelfIssuedConnectionIdManagerTest,ScheduleConnectionIdRetirementOneAtATime)745 TEST_F(QuicSelfIssuedConnectionIdManagerTest,
746 ScheduleConnectionIdRetirementOneAtATime) {
747 QuicConnectionId cid0 = initial_connection_id_;
748 QuicConnectionId cid1 = CheckGenerate(cid0);
749 QuicConnectionId cid2 = CheckGenerate(cid1);
750 QuicConnectionId cid3 = CheckGenerate(cid2);
751 EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(_))
752 .Times(3)
753 .WillRepeatedly(Return(true));
754 EXPECT_CALL(cid_manager_visitor_, SendNewConnectionId(_))
755 .Times(3)
756 .WillRepeatedly(Return(true));
757 QuicTime::Delta connection_id_expire_timeout = 3 * pto_delay_;
758 QuicRetireConnectionIdFrame retire_cid_frame;
759
760 // CID #1 is sent to peer.
761 cid_manager_.MaybeSendNewConnectionIds();
762
763 // CID #0's retirement is scheduled and CID #2 is sent to peer.
764 retire_cid_frame.sequence_number = 0u;
765 ASSERT_THAT(cid_manager_.OnRetireConnectionIdFrame(
766 retire_cid_frame, pto_delay_, &error_details_),
767 IsQuicNoError());
768 // While CID #0's retirement is scheduled, it is not retired yet.
769 EXPECT_THAT(cid_manager_.GetUnretiredConnectionIds(),
770 ElementsAre(cid0, cid1, cid2));
771 EXPECT_TRUE(retire_self_issued_cid_alarm_->IsSet());
772 EXPECT_EQ(retire_self_issued_cid_alarm_->deadline(),
773 clock_.ApproximateNow() + connection_id_expire_timeout);
774
775 // CID #0 is actually retired.
776 EXPECT_CALL(cid_manager_visitor_, OnSelfIssuedConnectionIdRetired(cid0));
777 clock_.AdvanceTime(connection_id_expire_timeout);
778 alarm_factory_.FireAlarm(retire_self_issued_cid_alarm_);
779 EXPECT_THAT(cid_manager_.GetUnretiredConnectionIds(),
780 ElementsAre(cid1, cid2));
781 EXPECT_FALSE(retire_self_issued_cid_alarm_->IsSet());
782
783 // CID #1's retirement is scheduled and CID #3 is sent to peer.
784 retire_cid_frame.sequence_number = 1u;
785 ASSERT_THAT(cid_manager_.OnRetireConnectionIdFrame(
786 retire_cid_frame, pto_delay_, &error_details_),
787 IsQuicNoError());
788 // While CID #1's retirement is scheduled, it is not retired yet.
789 EXPECT_THAT(cid_manager_.GetUnretiredConnectionIds(),
790 ElementsAre(cid1, cid2, cid3));
791 EXPECT_TRUE(retire_self_issued_cid_alarm_->IsSet());
792 EXPECT_EQ(retire_self_issued_cid_alarm_->deadline(),
793 clock_.ApproximateNow() + connection_id_expire_timeout);
794
795 // CID #1 is actually retired.
796 EXPECT_CALL(cid_manager_visitor_, OnSelfIssuedConnectionIdRetired(cid1));
797 clock_.AdvanceTime(connection_id_expire_timeout);
798 alarm_factory_.FireAlarm(retire_self_issued_cid_alarm_);
799 EXPECT_THAT(cid_manager_.GetUnretiredConnectionIds(),
800 ElementsAre(cid2, cid3));
801 EXPECT_FALSE(retire_self_issued_cid_alarm_->IsSet());
802 }
803
TEST_F(QuicSelfIssuedConnectionIdManagerTest,ScheduleMultipleConnectionIdRetirement)804 TEST_F(QuicSelfIssuedConnectionIdManagerTest,
805 ScheduleMultipleConnectionIdRetirement) {
806 QuicConnectionId cid0 = initial_connection_id_;
807 QuicConnectionId cid1 = CheckGenerate(cid0);
808 QuicConnectionId cid2 = CheckGenerate(cid1);
809 QuicConnectionId cid3 = CheckGenerate(cid2);
810 EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(_))
811 .Times(3)
812 .WillRepeatedly(Return(true));
813 EXPECT_CALL(cid_manager_visitor_, SendNewConnectionId(_))
814 .Times(3)
815 .WillRepeatedly(Return(true));
816 QuicTime::Delta connection_id_expire_timeout = 3 * pto_delay_;
817 QuicRetireConnectionIdFrame retire_cid_frame;
818
819 // CID #1 is sent to peer.
820 cid_manager_.MaybeSendNewConnectionIds();
821
822 // CID #0's retirement is scheduled and CID #2 is sent to peer.
823 retire_cid_frame.sequence_number = 0u;
824 ASSERT_THAT(cid_manager_.OnRetireConnectionIdFrame(
825 retire_cid_frame, pto_delay_, &error_details_),
826 IsQuicNoError());
827
828 clock_.AdvanceTime(connection_id_expire_timeout * 0.25);
829
830 // CID #1's retirement is scheduled and CID #3 is sent to peer.
831 retire_cid_frame.sequence_number = 1u;
832 ASSERT_THAT(cid_manager_.OnRetireConnectionIdFrame(
833 retire_cid_frame, pto_delay_, &error_details_),
834 IsQuicNoError());
835
836 // While CID #0, #1s retirement is scheduled, they are not retired yet.
837 EXPECT_THAT(cid_manager_.GetUnretiredConnectionIds(),
838 ElementsAre(cid0, cid1, cid2, cid3));
839 EXPECT_TRUE(retire_self_issued_cid_alarm_->IsSet());
840 EXPECT_EQ(retire_self_issued_cid_alarm_->deadline(),
841 clock_.ApproximateNow() + connection_id_expire_timeout * 0.75);
842
843 // CID #0 is actually retired.
844 EXPECT_CALL(cid_manager_visitor_, OnSelfIssuedConnectionIdRetired(cid0));
845 clock_.AdvanceTime(connection_id_expire_timeout * 0.75);
846 alarm_factory_.FireAlarm(retire_self_issued_cid_alarm_);
847 EXPECT_THAT(cid_manager_.GetUnretiredConnectionIds(),
848 ElementsAre(cid1, cid2, cid3));
849 EXPECT_TRUE(retire_self_issued_cid_alarm_->IsSet());
850 EXPECT_EQ(retire_self_issued_cid_alarm_->deadline(),
851 clock_.ApproximateNow() + connection_id_expire_timeout * 0.25);
852
853 // CID #1 is actually retired.
854 EXPECT_CALL(cid_manager_visitor_, OnSelfIssuedConnectionIdRetired(cid1));
855 clock_.AdvanceTime(connection_id_expire_timeout * 0.25);
856 alarm_factory_.FireAlarm(retire_self_issued_cid_alarm_);
857 EXPECT_THAT(cid_manager_.GetUnretiredConnectionIds(),
858 ElementsAre(cid2, cid3));
859 EXPECT_FALSE(retire_self_issued_cid_alarm_->IsSet());
860 }
861
TEST_F(QuicSelfIssuedConnectionIdManagerTest,AllExpiredConnectionIdsAreRetiredInOneBatch)862 TEST_F(QuicSelfIssuedConnectionIdManagerTest,
863 AllExpiredConnectionIdsAreRetiredInOneBatch) {
864 QuicConnectionId cid0 = initial_connection_id_;
865 QuicConnectionId cid1 = CheckGenerate(cid0);
866 QuicConnectionId cid2 = CheckGenerate(cid1);
867 QuicConnectionId cid3 = CheckGenerate(cid2);
868 QuicConnectionId cid;
869 EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(_))
870 .Times(3)
871 .WillRepeatedly(Return(true));
872 EXPECT_CALL(cid_manager_visitor_, SendNewConnectionId(_))
873 .Times(3)
874 .WillRepeatedly(Return(true));
875 QuicTime::Delta connection_id_expire_timeout = 3 * pto_delay_;
876 QuicRetireConnectionIdFrame retire_cid_frame;
877 EXPECT_TRUE(cid_manager_.IsConnectionIdInUse(cid0));
878 EXPECT_FALSE(cid_manager_.HasConnectionIdToConsume());
879 EXPECT_FALSE(cid_manager_.ConsumeOneConnectionId().has_value());
880
881 // CID #1 is sent to peer.
882 cid_manager_.MaybeSendNewConnectionIds();
883 EXPECT_TRUE(cid_manager_.IsConnectionIdInUse(cid1));
884 EXPECT_TRUE(cid_manager_.HasConnectionIdToConsume());
885 cid = *cid_manager_.ConsumeOneConnectionId();
886 EXPECT_EQ(cid1, cid);
887 EXPECT_FALSE(cid_manager_.HasConnectionIdToConsume());
888
889 // CID #0's retirement is scheduled and CID #2 is sent to peer.
890 retire_cid_frame.sequence_number = 0u;
891 cid_manager_.OnRetireConnectionIdFrame(retire_cid_frame, pto_delay_,
892 &error_details_);
893 EXPECT_TRUE(cid_manager_.IsConnectionIdInUse(cid0));
894 EXPECT_TRUE(cid_manager_.IsConnectionIdInUse(cid1));
895 EXPECT_TRUE(cid_manager_.IsConnectionIdInUse(cid2));
896 EXPECT_TRUE(cid_manager_.HasConnectionIdToConsume());
897 cid = *cid_manager_.ConsumeOneConnectionId();
898 EXPECT_EQ(cid2, cid);
899 EXPECT_FALSE(cid_manager_.HasConnectionIdToConsume());
900
901 clock_.AdvanceTime(connection_id_expire_timeout * 0.1);
902
903 // CID #1's retirement is scheduled and CID #3 is sent to peer.
904 retire_cid_frame.sequence_number = 1u;
905 cid_manager_.OnRetireConnectionIdFrame(retire_cid_frame, pto_delay_,
906 &error_details_);
907
908 {
909 // CID #0 & #1 are retired in a single alarm fire.
910 clock_.AdvanceTime(connection_id_expire_timeout);
911 testing::InSequence s;
912 EXPECT_CALL(cid_manager_visitor_, OnSelfIssuedConnectionIdRetired(cid0));
913 EXPECT_CALL(cid_manager_visitor_, OnSelfIssuedConnectionIdRetired(cid1));
914 alarm_factory_.FireAlarm(retire_self_issued_cid_alarm_);
915 EXPECT_FALSE(cid_manager_.IsConnectionIdInUse(cid0));
916 EXPECT_FALSE(cid_manager_.IsConnectionIdInUse(cid1));
917 EXPECT_TRUE(cid_manager_.IsConnectionIdInUse(cid2));
918 EXPECT_THAT(cid_manager_.GetUnretiredConnectionIds(),
919 ElementsAre(cid2, cid3));
920 EXPECT_FALSE(retire_self_issued_cid_alarm_->IsSet());
921 }
922 }
923
TEST_F(QuicSelfIssuedConnectionIdManagerTest,ErrorWhenRetireConnectionIdNeverIssued)924 TEST_F(QuicSelfIssuedConnectionIdManagerTest,
925 ErrorWhenRetireConnectionIdNeverIssued) {
926 QuicConnectionId cid0 = initial_connection_id_;
927 QuicConnectionId cid1 = CheckGenerate(cid0);
928
929 // CID #1 is sent to peer.
930 EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(_))
931 .WillOnce(Return(true));
932 EXPECT_CALL(cid_manager_visitor_, SendNewConnectionId(_))
933 .WillOnce(Return(true));
934 cid_manager_.MaybeSendNewConnectionIds();
935
936 // CID #2 is never issued.
937 QuicRetireConnectionIdFrame retire_cid_frame;
938 retire_cid_frame.sequence_number = 2u;
939 ASSERT_THAT(cid_manager_.OnRetireConnectionIdFrame(
940 retire_cid_frame, pto_delay_, &error_details_),
941 IsError(IETF_QUIC_PROTOCOL_VIOLATION));
942 }
943
TEST_F(QuicSelfIssuedConnectionIdManagerTest,ErrorWhenTooManyConnectionIdWaitingToBeRetired)944 TEST_F(QuicSelfIssuedConnectionIdManagerTest,
945 ErrorWhenTooManyConnectionIdWaitingToBeRetired) {
946 // CID #0 & #1 are issued.
947 QuicConnectionId last_connection_id = CheckGenerate(initial_connection_id_);
948 EXPECT_CALL(cid_manager_visitor_,
949 MaybeReserveConnectionId(last_connection_id))
950 .WillOnce(Return(true));
951 EXPECT_CALL(cid_manager_visitor_, SendNewConnectionId(_))
952 .WillOnce(Return(true));
953 cid_manager_.MaybeSendNewConnectionIds();
954
955 // Add 8 connection IDs to the to-be-retired list.
956
957 for (int i = 0; i < 8; ++i) {
958 last_connection_id = CheckGenerate(last_connection_id);
959 EXPECT_CALL(cid_manager_visitor_,
960 MaybeReserveConnectionId(last_connection_id))
961 .WillOnce(Return(true));
962 EXPECT_CALL(cid_manager_visitor_, SendNewConnectionId(_));
963 QuicRetireConnectionIdFrame retire_cid_frame;
964 retire_cid_frame.sequence_number = i;
965 ASSERT_THAT(cid_manager_.OnRetireConnectionIdFrame(
966 retire_cid_frame, pto_delay_, &error_details_),
967 IsQuicNoError());
968 }
969 QuicRetireConnectionIdFrame retire_cid_frame;
970 retire_cid_frame.sequence_number = 8u;
971 // This would have push the number of to-be-retired connection IDs over its
972 // limit.
973 ASSERT_THAT(cid_manager_.OnRetireConnectionIdFrame(
974 retire_cid_frame, pto_delay_, &error_details_),
975 IsError(QUIC_TOO_MANY_CONNECTION_ID_WAITING_TO_RETIRE));
976 }
977
TEST_F(QuicSelfIssuedConnectionIdManagerTest,CannotIssueNewCidDueToVisitor)978 TEST_F(QuicSelfIssuedConnectionIdManagerTest, CannotIssueNewCidDueToVisitor) {
979 QuicConnectionId cid0 = initial_connection_id_;
980 QuicConnectionId cid1 = CheckGenerate(cid0);
981 EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(cid1))
982 .WillOnce(Return(false));
983 EXPECT_CALL(cid_manager_visitor_, SendNewConnectionId(_)).Times(0);
984 cid_manager_.MaybeSendNewConnectionIds();
985 }
986
TEST_F(QuicSelfIssuedConnectionIdManagerTest,CannotIssueNewCidUponRetireConnectionIdDueToVisitor)987 TEST_F(QuicSelfIssuedConnectionIdManagerTest,
988 CannotIssueNewCidUponRetireConnectionIdDueToVisitor) {
989 QuicConnectionId cid0 = initial_connection_id_;
990 QuicConnectionId cid1 = CheckGenerate(cid0);
991 QuicConnectionId cid2 = CheckGenerate(cid1);
992 // CID #0 & #1 are issued.
993 EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(cid1))
994 .WillOnce(Return(true));
995 EXPECT_CALL(cid_manager_visitor_, SendNewConnectionId(_))
996 .WillOnce(Return(true));
997 cid_manager_.MaybeSendNewConnectionIds();
998
999 // CID #2 is not issued.
1000 EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(cid2))
1001 .WillOnce(Return(false));
1002 EXPECT_CALL(cid_manager_visitor_, SendNewConnectionId(_)).Times(0);
1003 QuicRetireConnectionIdFrame retire_cid_frame;
1004 retire_cid_frame.sequence_number = 1;
1005 ASSERT_THAT(cid_manager_.OnRetireConnectionIdFrame(
1006 retire_cid_frame, pto_delay_, &error_details_),
1007 IsQuicNoError());
1008 }
1009
TEST_F(QuicSelfIssuedConnectionIdManagerTest,DoNotIssueConnectionIdVoluntarilyIfOneHasIssuedForPerferredAddress)1010 TEST_F(QuicSelfIssuedConnectionIdManagerTest,
1011 DoNotIssueConnectionIdVoluntarilyIfOneHasIssuedForPerferredAddress) {
1012 QuicConnectionId cid0 = initial_connection_id_;
1013 QuicConnectionId cid1 = CheckGenerate(cid0);
1014 EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(cid1))
1015 .WillOnce(Return(true));
1016 std::optional<QuicNewConnectionIdFrame> new_cid_frame =
1017 cid_manager_.MaybeIssueNewConnectionIdForPreferredAddress();
1018 ASSERT_TRUE(new_cid_frame.has_value());
1019 ASSERT_THAT(*new_cid_frame, ExpectedNewConnectionIdFrame(cid1, 1u, 0u));
1020 EXPECT_THAT(cid_manager_.GetUnretiredConnectionIds(),
1021 ElementsAre(cid0, cid1));
1022
1023 EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(_)).Times(0);
1024 EXPECT_CALL(cid_manager_visitor_, SendNewConnectionId(_)).Times(0);
1025 cid_manager_.MaybeSendNewConnectionIds();
1026 }
1027
1028 // Regression test for b/258450534
TEST_F(QuicSelfIssuedConnectionIdManagerTest,RetireConnectionIdAfterConnectionIdCollisionIsFine)1029 TEST_F(QuicSelfIssuedConnectionIdManagerTest,
1030 RetireConnectionIdAfterConnectionIdCollisionIsFine) {
1031 QuicConnectionId cid0 = initial_connection_id_;
1032 QuicConnectionId cid1 = CheckGenerate(cid0);
1033 EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(cid1))
1034 .WillOnce(Return(true));
1035 EXPECT_CALL(cid_manager_visitor_, SendNewConnectionId(_))
1036 .WillOnce(Return(true));
1037 cid_manager_.MaybeSendNewConnectionIds();
1038
1039 QuicRetireConnectionIdFrame retire_cid_frame(/*control_frame_id=*/0,
1040 /*sequence_number=*/1);
1041 QuicConnectionId cid2 = CheckGenerate(cid1);
1042 // This happens when cid2 is aleady present in the dispatcher map.
1043 EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(cid2))
1044 .WillOnce(Return(false));
1045 std::string error_details;
1046 EXPECT_EQ(
1047 cid_manager_.OnRetireConnectionIdFrame(
1048 retire_cid_frame, QuicTime::Delta::FromSeconds(1), &error_details),
1049 QUIC_NO_ERROR)
1050 << error_details;
1051
1052 EXPECT_EQ(
1053 cid_manager_.OnRetireConnectionIdFrame(
1054 retire_cid_frame, QuicTime::Delta::FromSeconds(1), &error_details),
1055 QUIC_NO_ERROR)
1056 << error_details;
1057 }
1058
1059 } // namespace
1060 } // namespace quic::test
1061