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