quic_time_wait_list_manager_test.cc revision f2477e01787aa58f445919b809d89e252beef54f
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_framer.h" 15#include "net/quic/quic_packet_writer.h" 16#include "net/quic/quic_protocol.h" 17#include "net/quic/test_tools/quic_test_utils.h" 18#include "net/tools/quic/test_tools/mock_epoll_server.h" 19#include "net/tools/quic/test_tools/quic_test_utils.h" 20#include "testing/gmock/include/gmock/gmock.h" 21#include "testing/gtest/include/gtest/gtest.h" 22 23using net::test::FramerVisitorCapturingPublicReset; 24using testing::_; 25using testing::Args; 26using testing::Matcher; 27using testing::MatcherInterface; 28using testing::Return; 29using testing::SetArgPointee; 30using testing::Truly; 31 32namespace net { 33namespace tools { 34namespace test { 35 36class QuicTimeWaitListManagerPeer { 37 public: 38 static QuicVersion version(QuicTimeWaitListManager* manager) { 39 return manager->framer_.version(); 40 } 41 42 static bool is_write_blocked(QuicTimeWaitListManager* manager) { 43 return manager->is_write_blocked_; 44 } 45 46 static bool ShouldSendResponse(QuicTimeWaitListManager* manager, 47 int received_packet_count) { 48 return manager->ShouldSendResponse(received_packet_count); 49 } 50 51 static QuicTime::Delta time_wait_period(QuicTimeWaitListManager* manager) { 52 return manager->kTimeWaitPeriod_; 53 } 54 55 static QuicVersion GetQuicVersionFromGuid(QuicTimeWaitListManager* manager, 56 QuicGuid guid) { 57 return manager->GetQuicVersionFromGuid(guid); 58 } 59}; 60 61namespace { 62 63class TestTimeWaitListManager : public QuicTimeWaitListManager { 64 public: 65 TestTimeWaitListManager(QuicPacketWriter* writer, 66 EpollServer* epoll_server) 67 : QuicTimeWaitListManager(writer, epoll_server, QuicSupportedVersions()) { 68 } 69}; 70 71class MockFakeTimeEpollServer : public FakeTimeEpollServer { 72 public: 73 MOCK_METHOD2(RegisterAlarm, void(int64 timeout_in_us, 74 EpollAlarmCallbackInterface* alarm)); 75}; 76 77class QuicTimeWaitListManagerTest : public testing::Test { 78 protected: 79 QuicTimeWaitListManagerTest() 80 : time_wait_list_manager_( 81 &writer_, &epoll_server_, QuicSupportedVersions()), 82 framer_(QuicSupportedVersions(), QuicTime::Zero(), true), 83 guid_(45) { 84 } 85 86 virtual ~QuicTimeWaitListManagerTest() {} 87 88 void AddGuid(QuicGuid guid) { 89 AddGuid(guid, test::QuicVersionMax(), NULL); 90 } 91 92 void AddGuid(QuicGuid guid, 93 QuicVersion version, 94 QuicEncryptedPacket* packet) { 95 time_wait_list_manager_.AddGuidToTimeWait(guid, version, packet); 96 } 97 98 bool IsGuidInTimeWait(QuicGuid guid) { 99 return time_wait_list_manager_.IsGuidInTimeWait(guid); 100 } 101 102 void ProcessPacket(QuicGuid guid, const QuicEncryptedPacket& packet) { 103 time_wait_list_manager_.ProcessPacket(server_address_, 104 client_address_, 105 guid, 106 packet); 107 } 108 109 QuicEncryptedPacket* ConstructEncryptedPacket( 110 EncryptionLevel level, 111 QuicGuid guid, 112 QuicPacketSequenceNumber sequence_number) { 113 QuicPacketHeader header; 114 header.public_header.guid = guid; 115 header.public_header.guid_length = PACKET_8BYTE_GUID; 116 header.public_header.version_flag = false; 117 header.public_header.reset_flag = false; 118 header.public_header.sequence_number_length = PACKET_6BYTE_SEQUENCE_NUMBER; 119 header.packet_sequence_number = sequence_number; 120 header.entropy_flag = false; 121 header.entropy_hash = 0; 122 header.fec_flag = false; 123 header.is_in_fec_group = NOT_IN_FEC_GROUP; 124 header.fec_group = 0; 125 QuicStreamFrame stream_frame(1, false, 0, MakeIOVector("data")); 126 QuicFrame frame(&stream_frame); 127 QuicFrames frames; 128 frames.push_back(frame); 129 scoped_ptr<QuicPacket> packet( 130 framer_.BuildUnsizedDataPacket(header, frames).packet); 131 EXPECT_TRUE(packet != NULL); 132 QuicEncryptedPacket* encrypted = framer_.EncryptPacket(ENCRYPTION_NONE, 133 sequence_number, 134 *packet); 135 EXPECT_TRUE(encrypted != NULL); 136 return encrypted; 137 } 138 139 MockFakeTimeEpollServer epoll_server_; 140 MockPacketWriter writer_; 141 QuicTimeWaitListManager time_wait_list_manager_; 142 QuicFramer framer_; 143 QuicGuid guid_; 144 IPEndPoint server_address_; 145 IPEndPoint client_address_; 146}; 147 148class ValidatePublicResetPacketPredicate 149 : public MatcherInterface<const std::tr1::tuple<const char*, int> > { 150 public: 151 explicit ValidatePublicResetPacketPredicate(QuicGuid guid, 152 QuicPacketSequenceNumber number) 153 : guid_(guid), sequence_number_(number) { 154 } 155 156 virtual bool MatchAndExplain( 157 const std::tr1::tuple<const char*, int> packet_buffer, 158 testing::MatchResultListener* /* listener */) const { 159 FramerVisitorCapturingPublicReset visitor; 160 QuicFramer framer(QuicSupportedVersions(), 161 QuicTime::Zero(), 162 false); 163 framer.set_visitor(&visitor); 164 QuicEncryptedPacket encrypted(std::tr1::get<0>(packet_buffer), 165 std::tr1::get<1>(packet_buffer)); 166 framer.ProcessPacket(encrypted); 167 QuicPublicResetPacket packet = visitor.public_reset_packet(); 168 return guid_ == packet.public_header.guid && 169 packet.public_header.reset_flag && !packet.public_header.version_flag && 170 sequence_number_ == packet.rejected_sequence_number; 171 } 172 173 virtual void DescribeTo(::std::ostream* os) const { } 174 175 virtual void DescribeNegationTo(::std::ostream* os) const { } 176 177 private: 178 QuicGuid guid_; 179 QuicPacketSequenceNumber sequence_number_; 180}; 181 182 183Matcher<const std::tr1::tuple<const char*, int> > PublicResetPacketEq( 184 QuicGuid guid, 185 QuicPacketSequenceNumber sequence_number) { 186 return MakeMatcher(new ValidatePublicResetPacketPredicate(guid, 187 sequence_number)); 188} 189 190TEST_F(QuicTimeWaitListManagerTest, CheckGuidInTimeWait) { 191 EXPECT_FALSE(IsGuidInTimeWait(guid_)); 192 AddGuid(guid_); 193 EXPECT_TRUE(IsGuidInTimeWait(guid_)); 194} 195 196TEST_F(QuicTimeWaitListManagerTest, SendConnectionClose) { 197 size_t kConnectionCloseLength = 100; 198 AddGuid(guid_, 199 QuicVersionMax(), 200 new QuicEncryptedPacket( 201 new char[kConnectionCloseLength], kConnectionCloseLength, true)); 202 const int kRandomSequenceNumber = 1; 203 scoped_ptr<QuicEncryptedPacket> packet( 204 ConstructEncryptedPacket(ENCRYPTION_NONE, guid_, kRandomSequenceNumber)); 205 EXPECT_CALL(writer_, WritePacket(_, kConnectionCloseLength, 206 server_address_.address(), 207 client_address_, 208 &time_wait_list_manager_)) 209 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 1))); 210 211 ProcessPacket(guid_, *packet); 212} 213 214TEST_F(QuicTimeWaitListManagerTest, SendPublicReset) { 215 AddGuid(guid_); 216 const int kRandomSequenceNumber = 1; 217 scoped_ptr<QuicEncryptedPacket> packet( 218 ConstructEncryptedPacket(ENCRYPTION_NONE, guid_, kRandomSequenceNumber)); 219 EXPECT_CALL(writer_, WritePacket(_, _, 220 server_address_.address(), 221 client_address_, 222 &time_wait_list_manager_)) 223 .With(Args<0, 1>(PublicResetPacketEq(guid_, 224 kRandomSequenceNumber))) 225 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, packet->length()))); 226 227 ProcessPacket(guid_, *packet); 228} 229 230TEST_F(QuicTimeWaitListManagerTest, SendPublicResetUndecryptable) { 231 AddGuid(guid_); 232 const int kRandomSequenceNumber = 1; 233 scoped_ptr<QuicEncryptedPacket> packet( 234 ConstructEncryptedPacket( 235 ENCRYPTION_INITIAL, guid_, kRandomSequenceNumber)); 236 EXPECT_CALL(writer_, WritePacket(_, _, 237 server_address_.address(), 238 client_address_, 239 &time_wait_list_manager_)) 240 .With(Args<0, 1>(PublicResetPacketEq(guid_, 241 kRandomSequenceNumber))) 242 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, packet->length()))); 243 244 ProcessPacket(guid_, *packet); 245} 246 247TEST_F(QuicTimeWaitListManagerTest, DropInvalidPacket) { 248 AddGuid(guid_); 249 const char buffer[] = "invalid"; 250 QuicEncryptedPacket packet(buffer, arraysize(buffer)); 251 // Will get called for a valid packet since received packet count = 1 (2 ^ 0). 252 EXPECT_CALL(writer_, WritePacket(_, _, _, _, _)).Times(0); 253 ProcessPacket(guid_, packet); 254} 255 256TEST_F(QuicTimeWaitListManagerTest, DropPublicResetPacket) { 257 AddGuid(guid_); 258 QuicPublicResetPacket packet; 259 packet.public_header.guid = guid_; 260 packet.public_header.version_flag = false; 261 packet.public_header.reset_flag = true; 262 packet.rejected_sequence_number = 239191; 263 packet.nonce_proof = 1010101; 264 scoped_ptr<QuicEncryptedPacket> public_reset_packet( 265 QuicFramer::BuildPublicResetPacket(packet)); 266 // Will get called for a data packet since received packet count = 1 (2 ^ 0). 267 EXPECT_CALL(writer_, WritePacket(_, _, _, _, _)).Times(0); 268 ProcessPacket(guid_, *public_reset_packet); 269} 270 271TEST_F(QuicTimeWaitListManagerTest, SendPublicResetWithExponentialBackOff) { 272 AddGuid(guid_); 273 for (int sequence_number = 1; sequence_number < 101; ++sequence_number) { 274 scoped_ptr<QuicEncryptedPacket> packet( 275 ConstructEncryptedPacket(ENCRYPTION_NONE, guid_, sequence_number)); 276 if ((sequence_number & (sequence_number - 1)) == 0) { 277 EXPECT_CALL(writer_, WritePacket(_, _, _, _, _)) 278 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 1))); 279 } 280 ProcessPacket(guid_, *packet); 281 // Send public reset with exponential back off. 282 if ((sequence_number & (sequence_number - 1)) == 0) { 283 EXPECT_TRUE(QuicTimeWaitListManagerPeer::ShouldSendResponse( 284 &time_wait_list_manager_, sequence_number)); 285 } else { 286 EXPECT_FALSE(QuicTimeWaitListManagerPeer::ShouldSendResponse( 287 &time_wait_list_manager_, sequence_number)); 288 } 289 } 290} 291 292TEST_F(QuicTimeWaitListManagerTest, CleanUpOldGuids) { 293 const int kGuidCount = 100; 294 const int kOldGuidCount = 31; 295 296 // Add guids such that their expiry time is kTimeWaitPeriod_. 297 epoll_server_.set_now_in_usec(0); 298 for (int guid = 1; guid <= kOldGuidCount; ++guid) { 299 AddGuid(guid); 300 } 301 302 // Add remaining guids such that their add time is 2 * kTimeWaitPeriod. 303 const QuicTime::Delta time_wait_period = 304 QuicTimeWaitListManagerPeer::time_wait_period(&time_wait_list_manager_); 305 epoll_server_.set_now_in_usec(time_wait_period.ToMicroseconds()); 306 for (int guid = kOldGuidCount + 1; guid <= kGuidCount; ++guid) { 307 AddGuid(guid); 308 } 309 310 QuicTime::Delta offset = QuicTime::Delta::FromMicroseconds(39); 311 // Now set the current time as time_wait_period + offset usecs. 312 epoll_server_.set_now_in_usec(time_wait_period.Add(offset).ToMicroseconds()); 313 // After all the old guids are cleaned up, check the next alarm interval. 314 int64 next_alarm_time = epoll_server_.ApproximateNowInUsec() + 315 time_wait_period.Subtract(offset).ToMicroseconds(); 316 EXPECT_CALL(epoll_server_, RegisterAlarm(next_alarm_time, _)); 317 318 time_wait_list_manager_.CleanUpOldGuids(); 319 for (int guid = 1; guid <= kGuidCount; ++guid) { 320 EXPECT_EQ(guid > kOldGuidCount, IsGuidInTimeWait(guid)) 321 << "kOldGuidCount: " << kOldGuidCount 322 << " guid: " << guid; 323 } 324} 325 326TEST_F(QuicTimeWaitListManagerTest, SendQueuedPackets) { 327 QuicGuid guid = 1; 328 AddGuid(guid); 329 QuicPacketSequenceNumber sequence_number = 234; 330 scoped_ptr<QuicEncryptedPacket> packet( 331 ConstructEncryptedPacket(ENCRYPTION_NONE, guid, sequence_number)); 332 // Let first write through. 333 EXPECT_CALL(writer_, WritePacket(_, _, 334 server_address_.address(), 335 client_address_, 336 &time_wait_list_manager_)) 337 .With(Args<0, 1>(PublicResetPacketEq(guid, 338 sequence_number))) 339 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, packet->length()))); 340 ProcessPacket(guid, *packet); 341 EXPECT_FALSE( 342 QuicTimeWaitListManagerPeer::is_write_blocked(&time_wait_list_manager_)); 343 344 // write block for the next packet. 345 EXPECT_CALL(writer_, WritePacket(_, _, 346 server_address_.address(), 347 client_address_, 348 &time_wait_list_manager_)) 349 .With(Args<0, 1>(PublicResetPacketEq(guid, 350 sequence_number))) 351 .WillOnce(Return(WriteResult(WRITE_STATUS_BLOCKED, EAGAIN))); 352 ProcessPacket(guid, *packet); 353 // 3rd packet. No public reset should be sent; 354 ProcessPacket(guid, *packet); 355 EXPECT_TRUE( 356 QuicTimeWaitListManagerPeer::is_write_blocked(&time_wait_list_manager_)); 357 358 // write packet should not be called since already write blocked but the 359 // should be queued. 360 QuicGuid other_guid = 2; 361 AddGuid(other_guid); 362 QuicPacketSequenceNumber other_sequence_number = 23423; 363 scoped_ptr<QuicEncryptedPacket> other_packet( 364 ConstructEncryptedPacket( 365 ENCRYPTION_NONE, other_guid, other_sequence_number)); 366 EXPECT_CALL(writer_, WritePacket(_, _, _, _, _)) 367 .Times(0); 368 ProcessPacket(other_guid, *other_packet); 369 370 // Now expect all the write blocked public reset packets to be sent again. 371 EXPECT_CALL(writer_, WritePacket(_, _, 372 server_address_.address(), 373 client_address_, 374 &time_wait_list_manager_)) 375 .With(Args<0, 1>(PublicResetPacketEq(guid, 376 sequence_number))) 377 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, packet->length()))); 378 EXPECT_CALL(writer_, WritePacket(_, _, 379 server_address_.address(), 380 client_address_, 381 &time_wait_list_manager_)) 382 .With(Args<0, 1>(PublicResetPacketEq(other_guid, 383 other_sequence_number))) 384 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 385 other_packet->length()))); 386 time_wait_list_manager_.OnCanWrite(); 387 EXPECT_FALSE( 388 QuicTimeWaitListManagerPeer::is_write_blocked(&time_wait_list_manager_)); 389} 390 391TEST_F(QuicTimeWaitListManagerTest, MakeSureFramerUsesCorrectVersion) { 392 const int kRandomSequenceNumber = 1; 393 scoped_ptr<QuicEncryptedPacket> packet; 394 395 AddGuid(guid_, test::QuicVersionMin(), NULL); 396 framer_.set_version(test::QuicVersionMin()); 397 packet.reset( 398 ConstructEncryptedPacket(ENCRYPTION_NONE, guid_, kRandomSequenceNumber)); 399 400 // Reset packet should be written, using the minimum quic version. 401 EXPECT_CALL(writer_, WritePacket(_, _, _, _, _)).Times(1) 402 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0))); 403 ProcessPacket(guid_, *packet); 404 EXPECT_EQ(QuicTimeWaitListManagerPeer::version(&time_wait_list_manager_), 405 test::QuicVersionMin()); 406 407 // New guid 408 ++guid_; 409 410 AddGuid(guid_, test::QuicVersionMax(), NULL); 411 framer_.set_version(test::QuicVersionMax()); 412 packet.reset( 413 ConstructEncryptedPacket(ENCRYPTION_NONE, guid_, kRandomSequenceNumber)); 414 415 // Reset packet should be written, using the maximum quic version. 416 EXPECT_CALL(writer_, WritePacket(_, _, _, _, _)).Times(1) 417 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0))); 418 ProcessPacket(guid_, *packet); 419 EXPECT_EQ(QuicTimeWaitListManagerPeer::version(&time_wait_list_manager_), 420 test::QuicVersionMax()); 421} 422 423TEST_F(QuicTimeWaitListManagerTest, GetQuicVersionFromMap) { 424 const int kGuid1 = 123; 425 const int kGuid2 = 456; 426 const int kGuid3 = 789; 427 428 AddGuid(kGuid1, test::QuicVersionMin(), NULL); 429 AddGuid(kGuid2, test::QuicVersionMax(), NULL); 430 AddGuid(kGuid3, test::QuicVersionMax(), NULL); 431 432 EXPECT_EQ(test::QuicVersionMin(), 433 QuicTimeWaitListManagerPeer::GetQuicVersionFromGuid( 434 &time_wait_list_manager_, kGuid1)); 435 EXPECT_EQ(test::QuicVersionMax(), 436 QuicTimeWaitListManagerPeer::GetQuicVersionFromGuid( 437 &time_wait_list_manager_, kGuid2)); 438 EXPECT_EQ(test::QuicVersionMax(), 439 QuicTimeWaitListManagerPeer::GetQuicVersionFromGuid( 440 &time_wait_list_manager_, kGuid3)); 441} 442 443} // namespace 444} // namespace test 445} // namespace tools 446} // namespace net 447