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.
5 #include "net/tools/quic/quic_time_wait_list_manager.h"
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/quic_utils.h"
18 #include "net/quic/test_tools/quic_test_utils.h"
19 #include "net/tools/quic/test_tools/mock_epoll_server.h"
20 #include "net/tools/quic/test_tools/quic_test_utils.h"
21 #include "testing/gmock/include/gmock/gmock.h"
22 #include "testing/gtest/include/gtest/gtest.h"
24 using net::test::FramerVisitorCapturingPublicReset
;
27 using testing::Assign
;
29 using testing::Matcher
;
30 using testing::MatcherInterface
;
31 using testing::NiceMock
;
32 using testing::Return
;
33 using testing::ReturnPointee
;
34 using testing::SetArgPointee
;
35 using testing::StrictMock
;
42 class QuicTimeWaitListManagerPeer
{
44 static bool ShouldSendResponse(QuicTimeWaitListManager
* manager
,
45 int received_packet_count
) {
46 return manager
->ShouldSendResponse(received_packet_count
);
49 static QuicTime::Delta
time_wait_period(QuicTimeWaitListManager
* manager
) {
50 return manager
->kTimeWaitPeriod_
;
53 static QuicVersion
GetQuicVersionFromGuid(QuicTimeWaitListManager
* manager
,
55 return manager
->GetQuicVersionFromGuid(guid
);
61 class MockFakeTimeEpollServer
: public FakeTimeEpollServer
{
63 MOCK_METHOD2(RegisterAlarm
, void(int64 timeout_in_us
,
64 EpollAlarmCallbackInterface
* alarm
));
67 class QuicTimeWaitListManagerTest
: public testing::Test
{
69 QuicTimeWaitListManagerTest()
70 : time_wait_list_manager_(&writer_
, &visitor_
,
71 &epoll_server_
, QuicSupportedVersions()),
72 framer_(QuicSupportedVersions(), QuicTime::Zero(), true),
74 client_address_(net::test::TestPeerIPAddress(), kTestPort
),
75 writer_is_blocked_(false) {}
77 virtual ~QuicTimeWaitListManagerTest() {}
79 virtual void SetUp() {
80 EXPECT_CALL(writer_
, IsWriteBlocked())
81 .WillRepeatedly(ReturnPointee(&writer_is_blocked_
));
82 EXPECT_CALL(writer_
, IsWriteBlockedDataBuffered())
83 .WillRepeatedly(Return(false));
86 void AddGuid(QuicGuid guid
) {
87 AddGuid(guid
, net::test::QuicVersionMax(), NULL
);
90 void AddGuid(QuicGuid guid
,
92 QuicEncryptedPacket
* packet
) {
93 time_wait_list_manager_
.AddGuidToTimeWait(guid
, version
, packet
);
96 bool IsGuidInTimeWait(QuicGuid guid
) {
97 return time_wait_list_manager_
.IsGuidInTimeWait(guid
);
100 void ProcessPacket(QuicGuid guid
, QuicPacketSequenceNumber sequence_number
) {
101 time_wait_list_manager_
.ProcessPacket(server_address_
,
107 QuicEncryptedPacket
* ConstructEncryptedPacket(
108 EncryptionLevel level
,
110 QuicPacketSequenceNumber sequence_number
) {
111 QuicPacketHeader header
;
112 header
.public_header
.guid
= guid
;
113 header
.public_header
.guid_length
= PACKET_8BYTE_GUID
;
114 header
.public_header
.version_flag
= false;
115 header
.public_header
.reset_flag
= false;
116 header
.public_header
.sequence_number_length
= PACKET_6BYTE_SEQUENCE_NUMBER
;
117 header
.packet_sequence_number
= sequence_number
;
118 header
.entropy_flag
= false;
119 header
.entropy_hash
= 0;
120 header
.fec_flag
= false;
121 header
.is_in_fec_group
= NOT_IN_FEC_GROUP
;
122 header
.fec_group
= 0;
123 QuicStreamFrame
stream_frame(1, false, 0, MakeIOVector("data"));
124 QuicFrame
frame(&stream_frame
);
126 frames
.push_back(frame
);
127 scoped_ptr
<QuicPacket
> packet(
128 framer_
.BuildUnsizedDataPacket(header
, frames
).packet
);
129 EXPECT_TRUE(packet
!= NULL
);
130 QuicEncryptedPacket
* encrypted
= framer_
.EncryptPacket(ENCRYPTION_NONE
,
133 EXPECT_TRUE(encrypted
!= NULL
);
137 NiceMock
<MockFakeTimeEpollServer
> epoll_server_
;
138 StrictMock
<MockPacketWriter
> writer_
;
139 StrictMock
<MockQuicServerSessionVisitor
> visitor_
;
140 QuicTimeWaitListManager time_wait_list_manager_
;
143 IPEndPoint server_address_
;
144 IPEndPoint client_address_
;
145 bool writer_is_blocked_
;
148 class ValidatePublicResetPacketPredicate
149 : public MatcherInterface
<const std::tr1::tuple
<const char*, int> > {
151 explicit ValidatePublicResetPacketPredicate(QuicGuid guid
,
152 QuicPacketSequenceNumber number
)
153 : guid_(guid
), sequence_number_(number
) {
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(),
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 net::test::TestPeerIPAddress() == packet
.client_address
.address() &&
172 kTestPort
== packet
.client_address
.port();
175 virtual void DescribeTo(::std::ostream
* os
) const { }
177 virtual void DescribeNegationTo(::std::ostream
* os
) const { }
181 QuicPacketSequenceNumber sequence_number_
;
185 Matcher
<const std::tr1::tuple
<const char*, int> > PublicResetPacketEq(
187 QuicPacketSequenceNumber sequence_number
) {
188 return MakeMatcher(new ValidatePublicResetPacketPredicate(guid
,
192 TEST_F(QuicTimeWaitListManagerTest
, CheckGuidInTimeWait
) {
193 EXPECT_FALSE(IsGuidInTimeWait(guid_
));
195 EXPECT_TRUE(IsGuidInTimeWait(guid_
));
198 TEST_F(QuicTimeWaitListManagerTest
, SendConnectionClose
) {
199 size_t kConnectionCloseLength
= 100;
201 net::test::QuicVersionMax(),
202 new QuicEncryptedPacket(
203 new char[kConnectionCloseLength
], kConnectionCloseLength
, true));
204 const int kRandomSequenceNumber
= 1;
205 EXPECT_CALL(writer_
, WritePacket(_
, kConnectionCloseLength
,
206 server_address_
.address(),
208 .WillOnce(Return(WriteResult(WRITE_STATUS_OK
, 1)));
210 ProcessPacket(guid_
, kRandomSequenceNumber
);
213 TEST_F(QuicTimeWaitListManagerTest
, SendPublicReset
) {
215 const int kRandomSequenceNumber
= 1;
216 EXPECT_CALL(writer_
, WritePacket(_
, _
,
217 server_address_
.address(),
219 .With(Args
<0, 1>(PublicResetPacketEq(guid_
,
220 kRandomSequenceNumber
)))
221 .WillOnce(Return(WriteResult(WRITE_STATUS_OK
, 0)));
223 ProcessPacket(guid_
, kRandomSequenceNumber
);
226 TEST_F(QuicTimeWaitListManagerTest
, SendPublicResetWithExponentialBackOff
) {
228 for (int sequence_number
= 1; sequence_number
< 101; ++sequence_number
) {
229 if ((sequence_number
& (sequence_number
- 1)) == 0) {
230 EXPECT_CALL(writer_
, WritePacket(_
, _
, _
, _
))
231 .WillOnce(Return(WriteResult(WRITE_STATUS_OK
, 1)));
233 ProcessPacket(guid_
, sequence_number
);
234 // Send public reset with exponential back off.
235 if ((sequence_number
& (sequence_number
- 1)) == 0) {
236 EXPECT_TRUE(QuicTimeWaitListManagerPeer::ShouldSendResponse(
237 &time_wait_list_manager_
, sequence_number
));
239 EXPECT_FALSE(QuicTimeWaitListManagerPeer::ShouldSendResponse(
240 &time_wait_list_manager_
, sequence_number
));
245 TEST_F(QuicTimeWaitListManagerTest
, CleanUpOldGuids
) {
246 const int kGuidCount
= 100;
247 const int kOldGuidCount
= 31;
249 // Add guids such that their expiry time is kTimeWaitPeriod_.
250 epoll_server_
.set_now_in_usec(0);
251 for (int guid
= 1; guid
<= kOldGuidCount
; ++guid
) {
255 // Add remaining guids such that their add time is 2 * kTimeWaitPeriod.
256 const QuicTime::Delta time_wait_period
=
257 QuicTimeWaitListManagerPeer::time_wait_period(&time_wait_list_manager_
);
258 epoll_server_
.set_now_in_usec(time_wait_period
.ToMicroseconds());
259 for (int guid
= kOldGuidCount
+ 1; guid
<= kGuidCount
; ++guid
) {
263 QuicTime::Delta offset
= QuicTime::Delta::FromMicroseconds(39);
264 // Now set the current time as time_wait_period + offset usecs.
265 epoll_server_
.set_now_in_usec(time_wait_period
.Add(offset
).ToMicroseconds());
266 // After all the old guids are cleaned up, check the next alarm interval.
267 int64 next_alarm_time
= epoll_server_
.ApproximateNowInUsec() +
268 time_wait_period
.Subtract(offset
).ToMicroseconds();
269 EXPECT_CALL(epoll_server_
, RegisterAlarm(next_alarm_time
, _
));
271 time_wait_list_manager_
.CleanUpOldGuids();
272 for (int guid
= 1; guid
<= kGuidCount
; ++guid
) {
273 EXPECT_EQ(guid
> kOldGuidCount
, IsGuidInTimeWait(guid
))
274 << "kOldGuidCount: " << kOldGuidCount
275 << " guid: " << guid
;
279 TEST_F(QuicTimeWaitListManagerTest
, SendQueuedPackets
) {
282 QuicPacketSequenceNumber sequence_number
= 234;
283 scoped_ptr
<QuicEncryptedPacket
> packet(
284 ConstructEncryptedPacket(ENCRYPTION_NONE
, guid
, sequence_number
));
285 // Let first write through.
286 EXPECT_CALL(writer_
, WritePacket(_
, _
,
287 server_address_
.address(),
289 .With(Args
<0, 1>(PublicResetPacketEq(guid
,
291 .WillOnce(Return(WriteResult(WRITE_STATUS_OK
, packet
->length())));
292 ProcessPacket(guid
, sequence_number
);
294 // write block for the next packet.
295 EXPECT_CALL(writer_
, WritePacket(_
, _
,
296 server_address_
.address(),
298 .With(Args
<0, 1>(PublicResetPacketEq(guid
,
301 Assign(&writer_is_blocked_
, true),
302 Return(WriteResult(WRITE_STATUS_BLOCKED
, EAGAIN
))));
303 EXPECT_CALL(visitor_
, OnWriteBlocked(&time_wait_list_manager_
));
304 ProcessPacket(guid
, sequence_number
);
305 // 3rd packet. No public reset should be sent;
306 ProcessPacket(guid
, sequence_number
);
308 // write packet should not be called since we are write blocked but the
310 QuicGuid other_guid
= 2;
312 QuicPacketSequenceNumber other_sequence_number
= 23423;
313 scoped_ptr
<QuicEncryptedPacket
> other_packet(
314 ConstructEncryptedPacket(
315 ENCRYPTION_NONE
, other_guid
, other_sequence_number
));
316 EXPECT_CALL(writer_
, WritePacket(_
, _
, _
, _
))
318 EXPECT_CALL(visitor_
, OnWriteBlocked(&time_wait_list_manager_
));
319 ProcessPacket(other_guid
, other_sequence_number
);
321 // Now expect all the write blocked public reset packets to be sent again.
322 writer_is_blocked_
= false;
323 EXPECT_CALL(writer_
, WritePacket(_
, _
,
324 server_address_
.address(),
326 .With(Args
<0, 1>(PublicResetPacketEq(guid
,
328 .WillOnce(Return(WriteResult(WRITE_STATUS_OK
, packet
->length())));
329 EXPECT_CALL(writer_
, WritePacket(_
, _
,
330 server_address_
.address(),
332 .With(Args
<0, 1>(PublicResetPacketEq(other_guid
,
333 other_sequence_number
)))
334 .WillOnce(Return(WriteResult(WRITE_STATUS_OK
,
335 other_packet
->length())));
336 time_wait_list_manager_
.OnCanWrite();
339 TEST_F(QuicTimeWaitListManagerTest
, GetQuicVersionFromMap
) {
340 const int kGuid1
= 123;
341 const int kGuid2
= 456;
342 const int kGuid3
= 789;
344 AddGuid(kGuid1
, net::test::QuicVersionMin(), NULL
);
345 AddGuid(kGuid2
, net::test::QuicVersionMax(), NULL
);
346 AddGuid(kGuid3
, net::test::QuicVersionMax(), NULL
);
348 EXPECT_EQ(net::test::QuicVersionMin(),
349 QuicTimeWaitListManagerPeer::GetQuicVersionFromGuid(
350 &time_wait_list_manager_
, kGuid1
));
351 EXPECT_EQ(net::test::QuicVersionMax(),
352 QuicTimeWaitListManagerPeer::GetQuicVersionFromGuid(
353 &time_wait_list_manager_
, kGuid2
));
354 EXPECT_EQ(net::test::QuicVersionMax(),
355 QuicTimeWaitListManagerPeer::GetQuicVersionFromGuid(
356 &time_wait_list_manager_
, kGuid3
));
359 TEST_F(QuicTimeWaitListManagerTest
, AddGuidTwice
) {
360 // Add guids such that their expiry time is kTimeWaitPeriod_.
361 epoll_server_
.set_now_in_usec(0);
363 EXPECT_TRUE(IsGuidInTimeWait(guid_
));
364 size_t kConnectionCloseLength
= 100;
366 net::test::QuicVersionMax(),
367 new QuicEncryptedPacket(
368 new char[kConnectionCloseLength
], kConnectionCloseLength
, true));
369 EXPECT_TRUE(IsGuidInTimeWait(guid_
));
371 EXPECT_CALL(writer_
, WritePacket(_
,
372 kConnectionCloseLength
,
373 server_address_
.address(),
375 .WillOnce(Return(WriteResult(WRITE_STATUS_OK
, 1)));
377 const int kRandomSequenceNumber
= 1;
378 ProcessPacket(guid_
, kRandomSequenceNumber
);
380 const QuicTime::Delta time_wait_period
=
381 QuicTimeWaitListManagerPeer::time_wait_period(&time_wait_list_manager_
);
383 QuicTime::Delta offset
= QuicTime::Delta::FromMicroseconds(39);
384 // Now set the current time as time_wait_period + offset usecs.
385 epoll_server_
.set_now_in_usec(time_wait_period
.Add(offset
).ToMicroseconds());
386 // After the guids are cleaned up, check the next alarm interval.
387 int64 next_alarm_time
= epoll_server_
.ApproximateNowInUsec() +
388 time_wait_period
.ToMicroseconds();
390 EXPECT_CALL(epoll_server_
, RegisterAlarm(next_alarm_time
, _
));
391 time_wait_list_manager_
.CleanUpOldGuids();
392 EXPECT_FALSE(IsGuidInTimeWait(guid_
));
395 TEST_F(QuicTimeWaitListManagerTest
, GuidsOrderedByTime
) {
396 // Simple randomization: the values of guids are swapped based on the current
397 // seconds on the clock. If the container is broken, the test will be 50%
399 int odd_second
= static_cast<int>(epoll_server_
.ApproximateNowInUsec()) % 2;
400 EXPECT_TRUE(odd_second
== 0 || odd_second
== 1);
401 const QuicGuid kGuid1
= odd_second
;
402 const QuicGuid kGuid2
= 1 - odd_second
;
404 // 1 will hash lower than 2, but we add it later. They should come out in the
405 // add order, not hash order.
406 epoll_server_
.set_now_in_usec(0);
408 epoll_server_
.set_now_in_usec(10);
411 const QuicTime::Delta time_wait_period
=
412 QuicTimeWaitListManagerPeer::time_wait_period(&time_wait_list_manager_
);
413 epoll_server_
.set_now_in_usec(time_wait_period
.ToMicroseconds() + 1);
415 EXPECT_CALL(epoll_server_
, RegisterAlarm(_
, _
));
417 time_wait_list_manager_
.CleanUpOldGuids();
418 EXPECT_FALSE(IsGuidInTimeWait(kGuid1
));
419 EXPECT_TRUE(IsGuidInTimeWait(kGuid2
));