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 #ifndef NET_TOOLS_QUIC_TEST_TOOLS_PACKET_DROPPING_TEST_WRITER_H_ 6 #define NET_TOOLS_QUIC_TEST_TOOLS_PACKET_DROPPING_TEST_WRITER_H_ 7 8 #include <list> 9 10 #include "base/basictypes.h" 11 #include "base/logging.h" 12 #include "base/memory/scoped_ptr.h" 13 #include "base/synchronization/lock.h" 14 #include "net/quic/quic_alarm.h" 15 #include "net/quic/test_tools/quic_test_utils.h" 16 #include "net/tools/quic/quic_epoll_clock.h" 17 #include "net/tools/quic/quic_packet_writer_wrapper.h" 18 #include "net/tools/quic/test_tools/quic_test_client.h" 19 #include "net/tools/quic/test_tools/quic_test_utils.h" 20 21 namespace net { 22 namespace tools { 23 namespace test { 24 25 // Simulates a connection that drops packets a configured percentage of the time 26 // and has a blocked socket a configured percentage of the time. Also provides 27 // the options to delay packets and reorder packets if delay is enabled. 28 class PacketDroppingTestWriter : public QuicPacketWriterWrapper { 29 public: 30 class Delegate { 31 public: ~Delegate()32 virtual ~Delegate() {} 33 virtual void OnPacketSent(WriteResult result) = 0; 34 virtual void OnCanWrite() = 0; 35 }; 36 37 PacketDroppingTestWriter(); 38 39 virtual ~PacketDroppingTestWriter(); 40 41 // Must be called before blocking, reordering or delaying (loss is OK). May be 42 // called after connecting if the helper is not available before. 43 // |on_can_write| will be triggered when fake-unblocking; ownership will be 44 // assumed. 45 void Initialize(QuicEpollConnectionHelper* helper, Delegate* on_can_write); 46 47 // QuicPacketWriter methods: 48 virtual WriteResult WritePacket( 49 const char* buffer, 50 size_t buf_len, 51 const IPAddressNumber& self_address, 52 const IPEndPoint& peer_address) OVERRIDE; 53 54 virtual bool IsWriteBlocked() const OVERRIDE; 55 56 virtual void SetWritable() OVERRIDE; 57 58 // Writes out any packet which should have been sent by now 59 // to the contained writer and returns the time 60 // for the next delayed packet to be written. 61 QuicTime ReleaseOldPackets(); 62 63 void OnCanWrite(); 64 65 // The percent of time a packet is simulated as being lost. set_fake_packet_loss_percentage(int32 fake_packet_loss_percentage)66 void set_fake_packet_loss_percentage(int32 fake_packet_loss_percentage) { 67 base::AutoLock locked(config_mutex_); 68 fake_packet_loss_percentage_ = fake_packet_loss_percentage; 69 } 70 71 // The percent of time WritePacket will block and set WriteResult's status 72 // to WRITE_STATUS_BLOCKED. set_fake_blocked_socket_percentage(int32 fake_blocked_socket_percentage)73 void set_fake_blocked_socket_percentage( 74 int32 fake_blocked_socket_percentage) { 75 DCHECK(clock_); 76 base::AutoLock locked(config_mutex_); 77 fake_blocked_socket_percentage_ = fake_blocked_socket_percentage; 78 } 79 80 // The percent of time a packet is simulated as being reordered. set_fake_reorder_percentage(int32 fake_packet_reorder_percentage)81 void set_fake_reorder_percentage(int32 fake_packet_reorder_percentage) { 82 DCHECK(clock_); 83 base::AutoLock locked(config_mutex_); 84 DCHECK(!fake_packet_delay_.IsZero()); 85 fake_packet_reorder_percentage_ = fake_packet_reorder_percentage; 86 } 87 88 // The percent of time WritePacket will block and set WriteResult's status 89 // to WRITE_STATUS_BLOCKED. set_fake_packet_delay(QuicTime::Delta fake_packet_delay)90 void set_fake_packet_delay(QuicTime::Delta fake_packet_delay) { 91 DCHECK(clock_); 92 base::AutoLock locked(config_mutex_); 93 fake_packet_delay_ = fake_packet_delay; 94 } 95 96 // The maximum bandwidth and buffer size of the connection. When these are 97 // set, packets will be delayed until a connection with that bandwidth would 98 // transmit it. Once the |buffer_size| is reached, all new packets are 99 // dropped. set_max_bandwidth_and_buffer_size(QuicBandwidth fake_bandwidth,QuicByteCount buffer_size)100 void set_max_bandwidth_and_buffer_size(QuicBandwidth fake_bandwidth, 101 QuicByteCount buffer_size) { 102 DCHECK(clock_); 103 base::AutoLock locked(config_mutex_); 104 fake_bandwidth_ = fake_bandwidth; 105 buffer_size_ = buffer_size; 106 } 107 set_seed(uint64 seed)108 void set_seed(uint64 seed) { 109 simple_random_.set_seed(seed); 110 } 111 112 private: 113 // Writes out the next packet to the contained writer and returns the time 114 // for the next delayed packet to be written. 115 QuicTime ReleaseNextPacket(); 116 117 // A single packet which will be sent at the supplied send_time. 118 struct DelayedWrite { 119 public: 120 DelayedWrite(const char* buffer, 121 size_t buf_len, 122 const IPAddressNumber& self_address, 123 const IPEndPoint& peer_address, 124 QuicTime send_time); 125 ~DelayedWrite(); 126 127 string buffer; 128 const IPAddressNumber self_address; 129 const IPEndPoint peer_address; 130 QuicTime send_time; 131 }; 132 133 typedef std::list<DelayedWrite> DelayedPacketList; 134 135 const QuicClock* clock_; 136 scoped_ptr<QuicAlarm> write_unblocked_alarm_; 137 scoped_ptr<QuicAlarm> delay_alarm_; 138 scoped_ptr<Delegate> on_can_write_; 139 net::test::SimpleRandom simple_random_; 140 // Stored packets delayed by fake packet delay or bandwidth restrictions. 141 DelayedPacketList delayed_packets_; 142 QuicByteCount cur_buffer_size_; 143 144 base::Lock config_mutex_; 145 int32 fake_packet_loss_percentage_; 146 int32 fake_blocked_socket_percentage_; 147 int32 fake_packet_reorder_percentage_; 148 QuicTime::Delta fake_packet_delay_; 149 QuicBandwidth fake_bandwidth_; 150 QuicByteCount buffer_size_; 151 152 DISALLOW_COPY_AND_ASSIGN(PacketDroppingTestWriter); 153 }; 154 155 } // namespace test 156 } // namespace tools 157 } // namespace net 158 159 #endif // NET_TOOLS_QUIC_TEST_TOOLS_PACKET_DROPPING_TEST_WRITER_H_ 160