| OLD | NEW |
| (Empty) |
| 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 "net/tools/quic/quic_time_wait_list_manager.h" | |
| 6 | |
| 7 #include <errno.h> | |
| 8 | |
| 9 #include "net/quic/crypto/crypto_protocol.h" | |
| 10 #include "net/quic/crypto/null_encrypter.h" | |
| 11 #include "net/quic/crypto/quic_decrypter.h" | |
| 12 #include "net/quic/crypto/quic_encrypter.h" | |
| 13 #include "net/quic/quic_data_reader.h" | |
| 14 #include "net/quic/quic_flags.h" | |
| 15 #include "net/quic/quic_framer.h" | |
| 16 #include "net/quic/quic_packet_writer.h" | |
| 17 #include "net/quic/quic_protocol.h" | |
| 18 #include "net/quic/quic_utils.h" | |
| 19 #include "net/quic/test_tools/quic_test_utils.h" | |
| 20 #include "net/tools/quic/test_tools/mock_epoll_server.h" | |
| 21 #include "net/tools/quic/test_tools/quic_test_utils.h" | |
| 22 #include "testing/gmock/include/gmock/gmock.h" | |
| 23 #include "testing/gtest/include/gtest/gtest.h" | |
| 24 | |
| 25 using net::test::BuildUnsizedDataPacket; | |
| 26 using net::test::NoOpFramerVisitor; | |
| 27 using net::test::QuicVersionMax; | |
| 28 using net::test::QuicVersionMin; | |
| 29 using net::test::ValueRestore; | |
| 30 using testing::Args; | |
| 31 using testing::Assign; | |
| 32 using testing::DoAll; | |
| 33 using testing::Matcher; | |
| 34 using testing::MatcherInterface; | |
| 35 using testing::NiceMock; | |
| 36 using testing::Return; | |
| 37 using testing::ReturnPointee; | |
| 38 using testing::SetArgPointee; | |
| 39 using testing::StrictMock; | |
| 40 using testing::Truly; | |
| 41 using testing::_; | |
| 42 | |
| 43 namespace net { | |
| 44 namespace tools { | |
| 45 namespace test { | |
| 46 | |
| 47 class FramerVisitorCapturingPublicReset : public NoOpFramerVisitor { | |
| 48 public: | |
| 49 FramerVisitorCapturingPublicReset() {} | |
| 50 ~FramerVisitorCapturingPublicReset() override {} | |
| 51 | |
| 52 void OnPublicResetPacket(const QuicPublicResetPacket& public_reset) override { | |
| 53 public_reset_packet_ = public_reset; | |
| 54 } | |
| 55 | |
| 56 const QuicPublicResetPacket public_reset_packet() { | |
| 57 return public_reset_packet_; | |
| 58 } | |
| 59 | |
| 60 private: | |
| 61 QuicPublicResetPacket public_reset_packet_; | |
| 62 }; | |
| 63 | |
| 64 class QuicTimeWaitListManagerPeer { | |
| 65 public: | |
| 66 static bool ShouldSendResponse(QuicTimeWaitListManager* manager, | |
| 67 int received_packet_count) { | |
| 68 return manager->ShouldSendResponse(received_packet_count); | |
| 69 } | |
| 70 | |
| 71 static QuicTime::Delta time_wait_period(QuicTimeWaitListManager* manager) { | |
| 72 return manager->kTimeWaitPeriod_; | |
| 73 } | |
| 74 | |
| 75 static QuicVersion GetQuicVersionFromConnectionId( | |
| 76 QuicTimeWaitListManager* manager, | |
| 77 QuicConnectionId connection_id) { | |
| 78 return manager->GetQuicVersionFromConnectionId(connection_id); | |
| 79 } | |
| 80 }; | |
| 81 | |
| 82 namespace { | |
| 83 | |
| 84 class MockFakeTimeEpollServer : public FakeTimeEpollServer { | |
| 85 public: | |
| 86 MOCK_METHOD2(RegisterAlarm, void(int64 timeout_in_us, | |
| 87 EpollAlarmCallbackInterface* alarm)); | |
| 88 }; | |
| 89 | |
| 90 class QuicTimeWaitListManagerTest : public ::testing::Test { | |
| 91 protected: | |
| 92 QuicTimeWaitListManagerTest() | |
| 93 : time_wait_list_manager_(&writer_, &visitor_, | |
| 94 &epoll_server_, QuicSupportedVersions()), | |
| 95 framer_(QuicSupportedVersions(), QuicTime::Zero(), true), | |
| 96 connection_id_(45), | |
| 97 client_address_(net::test::TestPeerIPAddress(), kTestPort), | |
| 98 writer_is_blocked_(false) {} | |
| 99 | |
| 100 ~QuicTimeWaitListManagerTest() override {} | |
| 101 | |
| 102 void SetUp() override { | |
| 103 EXPECT_CALL(writer_, IsWriteBlocked()) | |
| 104 .WillRepeatedly(ReturnPointee(&writer_is_blocked_)); | |
| 105 EXPECT_CALL(writer_, IsWriteBlockedDataBuffered()) | |
| 106 .WillRepeatedly(Return(false)); | |
| 107 } | |
| 108 | |
| 109 void AddConnectionId(QuicConnectionId connection_id) { | |
| 110 AddConnectionId(connection_id, QuicVersionMax(), nullptr); | |
| 111 } | |
| 112 | |
| 113 void AddConnectionId(QuicConnectionId connection_id, | |
| 114 QuicVersion version, | |
| 115 QuicEncryptedPacket* packet) { | |
| 116 time_wait_list_manager_.AddConnectionIdToTimeWait( | |
| 117 connection_id, version, packet); | |
| 118 } | |
| 119 | |
| 120 bool IsConnectionIdInTimeWait(QuicConnectionId connection_id) { | |
| 121 return time_wait_list_manager_.IsConnectionIdInTimeWait(connection_id); | |
| 122 } | |
| 123 | |
| 124 void ProcessPacket(QuicConnectionId connection_id, | |
| 125 QuicPacketSequenceNumber sequence_number) { | |
| 126 QuicEncryptedPacket packet(nullptr, 0); | |
| 127 time_wait_list_manager_.ProcessPacket(server_address_, | |
| 128 client_address_, | |
| 129 connection_id, | |
| 130 sequence_number, | |
| 131 packet); | |
| 132 } | |
| 133 | |
| 134 QuicEncryptedPacket* ConstructEncryptedPacket( | |
| 135 EncryptionLevel level, | |
| 136 QuicConnectionId connection_id, | |
| 137 QuicPacketSequenceNumber sequence_number) { | |
| 138 QuicPacketHeader header; | |
| 139 header.public_header.connection_id = connection_id; | |
| 140 header.public_header.connection_id_length = PACKET_8BYTE_CONNECTION_ID; | |
| 141 header.public_header.version_flag = false; | |
| 142 header.public_header.reset_flag = false; | |
| 143 header.public_header.sequence_number_length = PACKET_6BYTE_SEQUENCE_NUMBER; | |
| 144 header.packet_sequence_number = sequence_number; | |
| 145 header.entropy_flag = false; | |
| 146 header.entropy_hash = 0; | |
| 147 header.fec_flag = false; | |
| 148 header.is_in_fec_group = NOT_IN_FEC_GROUP; | |
| 149 header.fec_group = 0; | |
| 150 QuicStreamFrame stream_frame(1, false, 0, MakeIOVector("data")); | |
| 151 QuicFrame frame(&stream_frame); | |
| 152 QuicFrames frames; | |
| 153 frames.push_back(frame); | |
| 154 scoped_ptr<QuicPacket> packet( | |
| 155 BuildUnsizedDataPacket(&framer_, header, frames)); | |
| 156 EXPECT_TRUE(packet != nullptr); | |
| 157 QuicEncryptedPacket* encrypted = framer_.EncryptPacket(ENCRYPTION_NONE, | |
| 158 sequence_number, | |
| 159 *packet); | |
| 160 EXPECT_TRUE(encrypted != nullptr); | |
| 161 return encrypted; | |
| 162 } | |
| 163 | |
| 164 NiceMock<MockFakeTimeEpollServer> epoll_server_; | |
| 165 StrictMock<MockPacketWriter> writer_; | |
| 166 StrictMock<MockQuicServerSessionVisitor> visitor_; | |
| 167 QuicTimeWaitListManager time_wait_list_manager_; | |
| 168 QuicFramer framer_; | |
| 169 QuicConnectionId connection_id_; | |
| 170 IPEndPoint server_address_; | |
| 171 IPEndPoint client_address_; | |
| 172 bool writer_is_blocked_; | |
| 173 }; | |
| 174 | |
| 175 class ValidatePublicResetPacketPredicate | |
| 176 : public MatcherInterface<const std::tr1::tuple<const char*, int> > { | |
| 177 public: | |
| 178 explicit ValidatePublicResetPacketPredicate(QuicConnectionId connection_id, | |
| 179 QuicPacketSequenceNumber number) | |
| 180 : connection_id_(connection_id), sequence_number_(number) { | |
| 181 } | |
| 182 | |
| 183 virtual bool MatchAndExplain( | |
| 184 const std::tr1::tuple<const char*, int> packet_buffer, | |
| 185 testing::MatchResultListener* /* listener */) const override { | |
| 186 FramerVisitorCapturingPublicReset visitor; | |
| 187 QuicFramer framer(QuicSupportedVersions(), | |
| 188 QuicTime::Zero(), | |
| 189 false); | |
| 190 framer.set_visitor(&visitor); | |
| 191 QuicEncryptedPacket encrypted(std::tr1::get<0>(packet_buffer), | |
| 192 std::tr1::get<1>(packet_buffer)); | |
| 193 framer.ProcessPacket(encrypted); | |
| 194 QuicPublicResetPacket packet = visitor.public_reset_packet(); | |
| 195 return connection_id_ == packet.public_header.connection_id && | |
| 196 packet.public_header.reset_flag && !packet.public_header.version_flag && | |
| 197 sequence_number_ == packet.rejected_sequence_number && | |
| 198 net::test::TestPeerIPAddress() == packet.client_address.address() && | |
| 199 kTestPort == packet.client_address.port(); | |
| 200 } | |
| 201 | |
| 202 virtual void DescribeTo(::std::ostream* os) const override {} | |
| 203 | |
| 204 virtual void DescribeNegationTo(::std::ostream* os) const override {} | |
| 205 | |
| 206 private: | |
| 207 QuicConnectionId connection_id_; | |
| 208 QuicPacketSequenceNumber sequence_number_; | |
| 209 }; | |
| 210 | |
| 211 | |
| 212 Matcher<const std::tr1::tuple<const char*, int> > PublicResetPacketEq( | |
| 213 QuicConnectionId connection_id, | |
| 214 QuicPacketSequenceNumber sequence_number) { | |
| 215 return MakeMatcher(new ValidatePublicResetPacketPredicate(connection_id, | |
| 216 sequence_number)); | |
| 217 } | |
| 218 | |
| 219 TEST_F(QuicTimeWaitListManagerTest, CheckConnectionIdInTimeWait) { | |
| 220 EXPECT_FALSE(IsConnectionIdInTimeWait(connection_id_)); | |
| 221 EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id_)); | |
| 222 AddConnectionId(connection_id_); | |
| 223 EXPECT_EQ(1u, time_wait_list_manager_.num_connections()); | |
| 224 EXPECT_TRUE(IsConnectionIdInTimeWait(connection_id_)); | |
| 225 } | |
| 226 | |
| 227 TEST_F(QuicTimeWaitListManagerTest, SendConnectionClose) { | |
| 228 size_t kConnectionCloseLength = 100; | |
| 229 EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id_)); | |
| 230 AddConnectionId( | |
| 231 connection_id_, | |
| 232 QuicVersionMax(), | |
| 233 new QuicEncryptedPacket( | |
| 234 new char[kConnectionCloseLength], kConnectionCloseLength, true)); | |
| 235 const int kRandomSequenceNumber = 1; | |
| 236 EXPECT_CALL(writer_, WritePacket(_, kConnectionCloseLength, | |
| 237 server_address_.address(), | |
| 238 client_address_)) | |
| 239 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 1))); | |
| 240 | |
| 241 ProcessPacket(connection_id_, kRandomSequenceNumber); | |
| 242 } | |
| 243 | |
| 244 TEST_F(QuicTimeWaitListManagerTest, SendPublicReset) { | |
| 245 EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id_)); | |
| 246 AddConnectionId(connection_id_); | |
| 247 const int kRandomSequenceNumber = 1; | |
| 248 EXPECT_CALL(writer_, WritePacket(_, _, | |
| 249 server_address_.address(), | |
| 250 client_address_)) | |
| 251 .With(Args<0, 1>(PublicResetPacketEq(connection_id_, | |
| 252 kRandomSequenceNumber))) | |
| 253 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0))); | |
| 254 | |
| 255 ProcessPacket(connection_id_, kRandomSequenceNumber); | |
| 256 } | |
| 257 | |
| 258 TEST_F(QuicTimeWaitListManagerTest, SendPublicResetWithExponentialBackOff) { | |
| 259 EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id_)); | |
| 260 AddConnectionId(connection_id_); | |
| 261 EXPECT_EQ(1u, time_wait_list_manager_.num_connections()); | |
| 262 for (int sequence_number = 1; sequence_number < 101; ++sequence_number) { | |
| 263 if ((sequence_number & (sequence_number - 1)) == 0) { | |
| 264 EXPECT_CALL(writer_, WritePacket(_, _, _, _)) | |
| 265 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 1))); | |
| 266 } | |
| 267 ProcessPacket(connection_id_, sequence_number); | |
| 268 // Send public reset with exponential back off. | |
| 269 if ((sequence_number & (sequence_number - 1)) == 0) { | |
| 270 EXPECT_TRUE(QuicTimeWaitListManagerPeer::ShouldSendResponse( | |
| 271 &time_wait_list_manager_, sequence_number)); | |
| 272 } else { | |
| 273 EXPECT_FALSE(QuicTimeWaitListManagerPeer::ShouldSendResponse( | |
| 274 &time_wait_list_manager_, sequence_number)); | |
| 275 } | |
| 276 } | |
| 277 } | |
| 278 | |
| 279 TEST_F(QuicTimeWaitListManagerTest, CleanUpOldConnectionIds) { | |
| 280 const size_t kConnectionIdCount = 100; | |
| 281 const size_t kOldConnectionIdCount = 31; | |
| 282 | |
| 283 // Add connection_ids such that their expiry time is kTimeWaitPeriod_. | |
| 284 epoll_server_.set_now_in_usec(0); | |
| 285 for (size_t connection_id = 1; connection_id <= kOldConnectionIdCount; | |
| 286 ++connection_id) { | |
| 287 EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id)); | |
| 288 AddConnectionId(connection_id); | |
| 289 } | |
| 290 EXPECT_EQ(kOldConnectionIdCount, time_wait_list_manager_.num_connections()); | |
| 291 | |
| 292 // Add remaining connection_ids such that their add time is | |
| 293 // 2 * kTimeWaitPeriod. | |
| 294 const QuicTime::Delta time_wait_period = | |
| 295 QuicTimeWaitListManagerPeer::time_wait_period(&time_wait_list_manager_); | |
| 296 epoll_server_.set_now_in_usec(time_wait_period.ToMicroseconds()); | |
| 297 for (size_t connection_id = kOldConnectionIdCount + 1; | |
| 298 connection_id <= kConnectionIdCount; ++connection_id) { | |
| 299 EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id)); | |
| 300 AddConnectionId(connection_id); | |
| 301 } | |
| 302 EXPECT_EQ(kConnectionIdCount, time_wait_list_manager_.num_connections()); | |
| 303 | |
| 304 QuicTime::Delta offset = QuicTime::Delta::FromMicroseconds(39); | |
| 305 // Now set the current time as time_wait_period + offset usecs. | |
| 306 epoll_server_.set_now_in_usec(time_wait_period.Add(offset).ToMicroseconds()); | |
| 307 // After all the old connection_ids are cleaned up, check the next alarm | |
| 308 // interval. | |
| 309 int64 next_alarm_time = epoll_server_.ApproximateNowInUsec() + | |
| 310 time_wait_period.Subtract(offset).ToMicroseconds(); | |
| 311 EXPECT_CALL(epoll_server_, RegisterAlarm(next_alarm_time, _)); | |
| 312 | |
| 313 for (size_t connection_id = 1; connection_id <= kConnectionIdCount; | |
| 314 ++connection_id) { | |
| 315 if (connection_id <= kOldConnectionIdCount) { | |
| 316 EXPECT_CALL(visitor_, OnConnectionRemovedFromTimeWaitList(connection_id)); | |
| 317 } | |
| 318 } | |
| 319 time_wait_list_manager_.CleanUpOldConnectionIds(); | |
| 320 for (size_t connection_id = 1; connection_id <= kConnectionIdCount; | |
| 321 ++connection_id) { | |
| 322 EXPECT_EQ(connection_id > kOldConnectionIdCount, | |
| 323 IsConnectionIdInTimeWait(connection_id)) | |
| 324 << "kOldConnectionIdCount: " << kOldConnectionIdCount | |
| 325 << " connection_id: " << connection_id; | |
| 326 } | |
| 327 EXPECT_EQ(kConnectionIdCount - kOldConnectionIdCount, | |
| 328 time_wait_list_manager_.num_connections()); | |
| 329 } | |
| 330 | |
| 331 TEST_F(QuicTimeWaitListManagerTest, SendQueuedPackets) { | |
| 332 QuicConnectionId connection_id = 1; | |
| 333 EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id)); | |
| 334 AddConnectionId(connection_id); | |
| 335 QuicPacketSequenceNumber sequence_number = 234; | |
| 336 scoped_ptr<QuicEncryptedPacket> packet(ConstructEncryptedPacket( | |
| 337 ENCRYPTION_NONE, connection_id, sequence_number)); | |
| 338 // Let first write through. | |
| 339 EXPECT_CALL(writer_, WritePacket(_, _, | |
| 340 server_address_.address(), | |
| 341 client_address_)) | |
| 342 .With(Args<0, 1>(PublicResetPacketEq(connection_id, | |
| 343 sequence_number))) | |
| 344 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, packet->length()))); | |
| 345 ProcessPacket(connection_id, sequence_number); | |
| 346 | |
| 347 // write block for the next packet. | |
| 348 EXPECT_CALL(writer_, WritePacket(_, _, | |
| 349 server_address_.address(), | |
| 350 client_address_)) | |
| 351 .With(Args<0, 1>(PublicResetPacketEq(connection_id, | |
| 352 sequence_number))) | |
| 353 .WillOnce(DoAll( | |
| 354 Assign(&writer_is_blocked_, true), | |
| 355 Return(WriteResult(WRITE_STATUS_BLOCKED, EAGAIN)))); | |
| 356 EXPECT_CALL(visitor_, OnWriteBlocked(&time_wait_list_manager_)); | |
| 357 ProcessPacket(connection_id, sequence_number); | |
| 358 // 3rd packet. No public reset should be sent; | |
| 359 ProcessPacket(connection_id, sequence_number); | |
| 360 | |
| 361 // write packet should not be called since we are write blocked but the | |
| 362 // should be queued. | |
| 363 QuicConnectionId other_connection_id = 2; | |
| 364 EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(other_connection_id)); | |
| 365 AddConnectionId(other_connection_id); | |
| 366 QuicPacketSequenceNumber other_sequence_number = 23423; | |
| 367 scoped_ptr<QuicEncryptedPacket> other_packet( | |
| 368 ConstructEncryptedPacket( | |
| 369 ENCRYPTION_NONE, other_connection_id, other_sequence_number)); | |
| 370 EXPECT_CALL(writer_, WritePacket(_, _, _, _)) | |
| 371 .Times(0); | |
| 372 EXPECT_CALL(visitor_, OnWriteBlocked(&time_wait_list_manager_)); | |
| 373 ProcessPacket(other_connection_id, other_sequence_number); | |
| 374 EXPECT_EQ(2u, time_wait_list_manager_.num_connections()); | |
| 375 | |
| 376 // Now expect all the write blocked public reset packets to be sent again. | |
| 377 writer_is_blocked_ = false; | |
| 378 EXPECT_CALL(writer_, WritePacket(_, _, | |
| 379 server_address_.address(), | |
| 380 client_address_)) | |
| 381 .With(Args<0, 1>(PublicResetPacketEq(connection_id, | |
| 382 sequence_number))) | |
| 383 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, packet->length()))); | |
| 384 EXPECT_CALL(writer_, WritePacket(_, _, | |
| 385 server_address_.address(), | |
| 386 client_address_)) | |
| 387 .With(Args<0, 1>(PublicResetPacketEq(other_connection_id, | |
| 388 other_sequence_number))) | |
| 389 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, | |
| 390 other_packet->length()))); | |
| 391 time_wait_list_manager_.OnCanWrite(); | |
| 392 } | |
| 393 | |
| 394 TEST_F(QuicTimeWaitListManagerTest, GetQuicVersionFromMap) { | |
| 395 const int kConnectionId1 = 123; | |
| 396 const int kConnectionId2 = 456; | |
| 397 const int kConnectionId3 = 789; | |
| 398 | |
| 399 EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(kConnectionId1)); | |
| 400 EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(kConnectionId2)); | |
| 401 EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(kConnectionId3)); | |
| 402 AddConnectionId(kConnectionId1, QuicVersionMin(), nullptr); | |
| 403 AddConnectionId(kConnectionId2, QuicVersionMax(), nullptr); | |
| 404 AddConnectionId(kConnectionId3, QuicVersionMax(), nullptr); | |
| 405 | |
| 406 EXPECT_EQ(QuicVersionMin(), | |
| 407 QuicTimeWaitListManagerPeer::GetQuicVersionFromConnectionId( | |
| 408 &time_wait_list_manager_, kConnectionId1)); | |
| 409 EXPECT_EQ(QuicVersionMax(), | |
| 410 QuicTimeWaitListManagerPeer::GetQuicVersionFromConnectionId( | |
| 411 &time_wait_list_manager_, kConnectionId2)); | |
| 412 EXPECT_EQ(QuicVersionMax(), | |
| 413 QuicTimeWaitListManagerPeer::GetQuicVersionFromConnectionId( | |
| 414 &time_wait_list_manager_, kConnectionId3)); | |
| 415 } | |
| 416 | |
| 417 TEST_F(QuicTimeWaitListManagerTest, AddConnectionIdTwice) { | |
| 418 // Add connection_ids such that their expiry time is kTimeWaitPeriod_. | |
| 419 epoll_server_.set_now_in_usec(0); | |
| 420 EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id_)); | |
| 421 AddConnectionId(connection_id_); | |
| 422 EXPECT_TRUE(IsConnectionIdInTimeWait(connection_id_)); | |
| 423 size_t kConnectionCloseLength = 100; | |
| 424 AddConnectionId( | |
| 425 connection_id_, | |
| 426 QuicVersionMax(), | |
| 427 new QuicEncryptedPacket( | |
| 428 new char[kConnectionCloseLength], kConnectionCloseLength, true)); | |
| 429 EXPECT_TRUE(IsConnectionIdInTimeWait(connection_id_)); | |
| 430 EXPECT_EQ(1u, time_wait_list_manager_.num_connections()); | |
| 431 | |
| 432 EXPECT_CALL(writer_, WritePacket(_, | |
| 433 kConnectionCloseLength, | |
| 434 server_address_.address(), | |
| 435 client_address_)) | |
| 436 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 1))); | |
| 437 | |
| 438 const int kRandomSequenceNumber = 1; | |
| 439 ProcessPacket(connection_id_, kRandomSequenceNumber); | |
| 440 | |
| 441 const QuicTime::Delta time_wait_period = | |
| 442 QuicTimeWaitListManagerPeer::time_wait_period(&time_wait_list_manager_); | |
| 443 | |
| 444 QuicTime::Delta offset = QuicTime::Delta::FromMicroseconds(39); | |
| 445 // Now set the current time as time_wait_period + offset usecs. | |
| 446 epoll_server_.set_now_in_usec(time_wait_period.Add(offset).ToMicroseconds()); | |
| 447 // After the connection_ids are cleaned up, check the next alarm interval. | |
| 448 int64 next_alarm_time = epoll_server_.ApproximateNowInUsec() + | |
| 449 time_wait_period.ToMicroseconds(); | |
| 450 | |
| 451 EXPECT_CALL(epoll_server_, RegisterAlarm(next_alarm_time, _)); | |
| 452 EXPECT_CALL(visitor_, OnConnectionRemovedFromTimeWaitList(connection_id_)); | |
| 453 time_wait_list_manager_.CleanUpOldConnectionIds(); | |
| 454 EXPECT_FALSE(IsConnectionIdInTimeWait(connection_id_)); | |
| 455 EXPECT_EQ(0u, time_wait_list_manager_.num_connections()); | |
| 456 } | |
| 457 | |
| 458 TEST_F(QuicTimeWaitListManagerTest, ConnectionIdsOrderedByTime) { | |
| 459 // Simple randomization: the values of connection_ids are swapped based on the | |
| 460 // current seconds on the clock. If the container is broken, the test will be | |
| 461 // 50% flaky. | |
| 462 int odd_second = static_cast<int>(epoll_server_.ApproximateNowInUsec()) % 2; | |
| 463 EXPECT_TRUE(odd_second == 0 || odd_second == 1); | |
| 464 const QuicConnectionId kConnectionId1 = odd_second; | |
| 465 const QuicConnectionId kConnectionId2 = 1 - odd_second; | |
| 466 | |
| 467 // 1 will hash lower than 2, but we add it later. They should come out in the | |
| 468 // add order, not hash order. | |
| 469 epoll_server_.set_now_in_usec(0); | |
| 470 EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(kConnectionId1)); | |
| 471 AddConnectionId(kConnectionId1); | |
| 472 epoll_server_.set_now_in_usec(10); | |
| 473 EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(kConnectionId2)); | |
| 474 AddConnectionId(kConnectionId2); | |
| 475 EXPECT_EQ(2u, time_wait_list_manager_.num_connections()); | |
| 476 | |
| 477 const QuicTime::Delta time_wait_period = | |
| 478 QuicTimeWaitListManagerPeer::time_wait_period(&time_wait_list_manager_); | |
| 479 epoll_server_.set_now_in_usec(time_wait_period.ToMicroseconds() + 1); | |
| 480 | |
| 481 EXPECT_CALL(epoll_server_, RegisterAlarm(_, _)); | |
| 482 | |
| 483 EXPECT_CALL(visitor_, OnConnectionRemovedFromTimeWaitList(kConnectionId1)); | |
| 484 time_wait_list_manager_.CleanUpOldConnectionIds(); | |
| 485 EXPECT_FALSE(IsConnectionIdInTimeWait(kConnectionId1)); | |
| 486 EXPECT_TRUE(IsConnectionIdInTimeWait(kConnectionId2)); | |
| 487 EXPECT_EQ(1u, time_wait_list_manager_.num_connections()); | |
| 488 } | |
| 489 | |
| 490 TEST_F(QuicTimeWaitListManagerTest, MaxConnectionsTest) { | |
| 491 ValueRestore<bool> old_flag(&FLAGS_quic_limit_time_wait_list_size, true); | |
| 492 // Basically, shut off time-based eviction. | |
| 493 FLAGS_quic_time_wait_list_seconds = 10000000000; | |
| 494 FLAGS_quic_time_wait_list_max_connections = 5; | |
| 495 | |
| 496 QuicConnectionId current_connection_id = 0; | |
| 497 // Add exactly the maximum number of connections | |
| 498 for (int64 i = 0; i < FLAGS_quic_time_wait_list_max_connections; ++i) { | |
| 499 ++current_connection_id; | |
| 500 EXPECT_FALSE(IsConnectionIdInTimeWait(current_connection_id)); | |
| 501 EXPECT_CALL(visitor_, | |
| 502 OnConnectionAddedToTimeWaitList(current_connection_id)); | |
| 503 AddConnectionId(current_connection_id); | |
| 504 EXPECT_EQ(current_connection_id, time_wait_list_manager_.num_connections()); | |
| 505 EXPECT_TRUE(IsConnectionIdInTimeWait(current_connection_id)); | |
| 506 } | |
| 507 | |
| 508 // Now keep adding. Since we're already at the max, every new connection-id | |
| 509 // will evict the oldest one. | |
| 510 for (int64 i = 0; i < FLAGS_quic_time_wait_list_max_connections; ++i) { | |
| 511 ++current_connection_id; | |
| 512 const QuicConnectionId id_to_evict = | |
| 513 current_connection_id - FLAGS_quic_time_wait_list_max_connections; | |
| 514 EXPECT_TRUE(IsConnectionIdInTimeWait(id_to_evict)); | |
| 515 EXPECT_FALSE(IsConnectionIdInTimeWait(current_connection_id)); | |
| 516 EXPECT_CALL(visitor_, OnConnectionRemovedFromTimeWaitList(id_to_evict)); | |
| 517 EXPECT_CALL(visitor_, | |
| 518 OnConnectionAddedToTimeWaitList(current_connection_id)); | |
| 519 AddConnectionId(current_connection_id); | |
| 520 EXPECT_EQ(static_cast<size_t>(FLAGS_quic_time_wait_list_max_connections), | |
| 521 time_wait_list_manager_.num_connections()); | |
| 522 EXPECT_FALSE(IsConnectionIdInTimeWait(id_to_evict)); | |
| 523 EXPECT_TRUE(IsConnectionIdInTimeWait(current_connection_id)); | |
| 524 } | |
| 525 } | |
| 526 | |
| 527 } // namespace | |
| 528 } // namespace test | |
| 529 } // namespace tools | |
| 530 } // namespace net | |
| OLD | NEW |