11e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
21e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
31e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// found in the LICENSE file.
41e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
51e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#ifndef NET_TOOLS_QUIC_TEST_TOOLS_PACKET_DROPPING_TEST_WRITER_H_
61e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#define NET_TOOLS_QUIC_TEST_TOOLS_PACKET_DROPPING_TEST_WRITER_H_
71e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
81e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include <list>
91e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/basictypes.h"
111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/logging.h"
121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/synchronization/lock.h"
141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "net/quic/quic_alarm.h"
15f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "net/quic/test_tools/quic_test_utils.h"
161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "net/tools/quic/quic_epoll_clock.h"
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/tools/quic/quic_packet_writer_wrapper.h"
181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "net/tools/quic/test_tools/quic_test_client.h"
191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "net/tools/quic/test_tools/quic_test_utils.h"
201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)namespace net {
221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)namespace tools {
231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)namespace test {
241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Simulates a connection that drops packets a configured percentage of the time
261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// and has a blocked socket a configured percentage of the time.  Also provides
271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// the options to delay packets and reorder packets if delay is enabled.
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class PacketDroppingTestWriter : public QuicPacketWriterWrapper {
291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) public:
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  class Delegate {
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)   public:
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    virtual ~Delegate() {}
3303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    virtual void OnPacketSent(WriteResult result) = 0;
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    virtual void OnCanWrite() = 0;
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  };
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  PacketDroppingTestWriter();
381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  virtual ~PacketDroppingTestWriter();
401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Must be called before blocking, reordering or delaying (loss is OK). May be
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // called after connecting if the helper is not available before.
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // |on_can_write| will be triggered when fake-unblocking; ownership will be
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // assumed.
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void Initialize(QuicEpollConnectionHelper* helper, Delegate* on_can_write);
461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // QuicPacketWriter methods:
481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  virtual WriteResult WritePacket(
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const char* buffer,
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      size_t buf_len,
511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      const IPAddressNumber& self_address,
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const IPEndPoint& peer_address) OVERRIDE;
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual bool IsWriteBlocked() const OVERRIDE;
551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void SetWritable() OVERRIDE;
571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Writes out any packet which should have been sent by now
59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // to the contained writer and returns the time
601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // for the next delayed packet to be written.
61f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  QuicTime ReleaseOldPackets();
621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void OnCanWrite();
641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // The percent of time a packet is simulated as being lost.
661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  void set_fake_packet_loss_percentage(int32 fake_packet_loss_percentage) {
671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    base::AutoLock locked(config_mutex_);
681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    fake_packet_loss_percentage_ = fake_packet_loss_percentage;
691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // The percent of time WritePacket will block and set WriteResult's status
721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // to WRITE_STATUS_BLOCKED.
731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  void set_fake_blocked_socket_percentage(
741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      int32 fake_blocked_socket_percentage) {
751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    DCHECK(clock_);
761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    base::AutoLock locked(config_mutex_);
771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    fake_blocked_socket_percentage_  = fake_blocked_socket_percentage;
781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // The percent of time a packet is simulated as being reordered.
811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  void set_fake_reorder_percentage(int32 fake_packet_reorder_percentage) {
821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    DCHECK(clock_);
831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    base::AutoLock locked(config_mutex_);
841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    DCHECK(!fake_packet_delay_.IsZero());
851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    fake_packet_reorder_percentage_ = fake_packet_reorder_percentage;
861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // The percent of time WritePacket will block and set WriteResult's status
891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // to WRITE_STATUS_BLOCKED.
901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  void set_fake_packet_delay(QuicTime::Delta fake_packet_delay) {
911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    DCHECK(clock_);
921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    base::AutoLock locked(config_mutex_);
931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    fake_packet_delay_  = fake_packet_delay;
941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
96f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // The maximum bandwidth and buffer size of the connection.  When these are
97f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // set, packets will be delayed until a connection with that bandwidth would
98f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // transmit it.  Once the |buffer_size| is reached, all new packets are
99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // dropped.
100f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  void set_max_bandwidth_and_buffer_size(QuicBandwidth fake_bandwidth,
101f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                         QuicByteCount buffer_size) {
102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DCHECK(clock_);
103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    base::AutoLock locked(config_mutex_);
104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    fake_bandwidth_ = fake_bandwidth;
105f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    buffer_size_ = buffer_size;
106f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
107f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  void set_seed(uint64 seed) {
1091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    simple_random_.set_seed(seed);
1101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
1111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) private:
113f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Writes out the next packet to the contained writer and returns the time
114f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // for the next delayed packet to be written.
115f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  QuicTime ReleaseNextPacket();
116f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // A single packet which will be sent at the supplied send_time.
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  struct DelayedWrite {
1191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)   public:
1201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    DelayedWrite(const char* buffer,
1211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                 size_t buf_len,
1221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                 const IPAddressNumber& self_address,
1231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                 const IPEndPoint& peer_address,
1241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                 QuicTime send_time);
1251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    ~DelayedWrite();
1261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    string buffer;
1281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const IPAddressNumber self_address;
1291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const IPEndPoint peer_address;
1301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    QuicTime send_time;
1311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  };
1321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  typedef std::list<DelayedWrite> DelayedPacketList;
1341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const QuicClock* clock_;
1361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  scoped_ptr<QuicAlarm> write_unblocked_alarm_;
1371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  scoped_ptr<QuicAlarm> delay_alarm_;
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<Delegate> on_can_write_;
139f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  net::test::SimpleRandom simple_random_;
140f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Stored packets delayed by fake packet delay or bandwidth restrictions.
1411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DelayedPacketList delayed_packets_;
142f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  QuicByteCount cur_buffer_size_;
1431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  base::Lock config_mutex_;
1451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  int32 fake_packet_loss_percentage_;
1461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  int32 fake_blocked_socket_percentage_;
1471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  int32 fake_packet_reorder_percentage_;
1481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  QuicTime::Delta fake_packet_delay_;
149f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  QuicBandwidth fake_bandwidth_;
150f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  QuicByteCount buffer_size_;
1511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(PacketDroppingTestWriter);
1531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)};
1541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}  // namespace test
1561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}  // namespace tools
1571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}  // namespace net
1581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#endif  // NET_TOOLS_QUIC_TEST_TOOLS_PACKET_DROPPING_TEST_WRITER_H_
160