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 QUICHE_QUIC_TEST_TOOLS_PACKET_DROPPING_TEST_WRITER_H_ 6 #define QUICHE_QUIC_TEST_TOOLS_PACKET_DROPPING_TEST_WRITER_H_ 7 8 #include <cstdint> 9 #include <list> 10 #include <memory> 11 12 #include "absl/base/attributes.h" 13 #include "quiche/quic/core/quic_alarm.h" 14 #include "quiche/quic/core/quic_alarm_factory.h" 15 #include "quiche/quic/core/quic_clock.h" 16 #include "quiche/quic/core/quic_connection.h" 17 #include "quiche/quic/core/quic_packet_writer_wrapper.h" 18 #include "quiche/quic/platform/api/quic_mutex.h" 19 #include "quiche/quic/test_tools/quic_test_utils.h" 20 21 namespace quic { 22 namespace test { 23 24 // Simulates a connection that drops packets a configured percentage of the time 25 // and has a blocked socket a configured percentage of the time. Also provides 26 // the options to delay packets and reorder packets if delay is enabled. 27 class PacketDroppingTestWriter : public QuicPacketWriterWrapper { 28 public: 29 class Delegate { 30 public: ~Delegate()31 virtual ~Delegate() {} 32 virtual void OnCanWrite() = 0; 33 }; 34 35 PacketDroppingTestWriter(); 36 PacketDroppingTestWriter(const PacketDroppingTestWriter&) = delete; 37 PacketDroppingTestWriter& operator=(const PacketDroppingTestWriter&) = delete; 38 39 ~PacketDroppingTestWriter() override; 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. 44 void Initialize(QuicConnectionHelperInterface* helper, 45 QuicAlarmFactory* alarm_factory, 46 std::unique_ptr<Delegate> on_can_write); 47 48 // QuicPacketWriter methods: 49 WriteResult WritePacket(const char* buffer, size_t buf_len, 50 const QuicIpAddress& self_address, 51 const QuicSocketAddress& peer_address, 52 PerPacketOptions* options, 53 const QuicPacketWriterParams& params) override; 54 55 bool IsWriteBlocked() const override; 56 57 void SetWritable() override; 58 GetNextWriteLocation(const QuicIpAddress &,const QuicSocketAddress &)59 QuicPacketBuffer GetNextWriteLocation( 60 const QuicIpAddress& /*self_address*/, 61 const QuicSocketAddress& /*peer_address*/) override { 62 // If the wrapped writer supports zero-copy, disable it, because it is not 63 // compatible with delayed writes in this class. 64 return {nullptr, nullptr}; 65 } 66 67 // Writes out any packet which should have been sent by now 68 // to the contained writer and returns the time 69 // for the next delayed packet to be written. 70 QuicTime ReleaseOldPackets(); 71 72 // Sets |delay_alarm_| to fire at |new_deadline|. 73 void SetDelayAlarm(QuicTime new_deadline); 74 75 void OnCanWrite(); 76 77 // The percent of time a packet is simulated as being lost. 78 // If |fake_packet_loss_percentage| is 100, then all packages are lost. 79 // Otherwise actual percentage will be lower than 80 // |fake_packet_loss_percentage|, because every dropped package is followed by 81 // a minimum number of successfully written packets. set_fake_packet_loss_percentage(int32_t fake_packet_loss_percentage)82 void set_fake_packet_loss_percentage(int32_t fake_packet_loss_percentage) { 83 QuicWriterMutexLock lock(&config_mutex_); 84 fake_packet_loss_percentage_ = fake_packet_loss_percentage; 85 } 86 87 // Once called, the next |passthrough_for_next_n_packets_| WritePacket() calls 88 // will always send the packets immediately, without being affected by the 89 // simulated error conditions. set_passthrough_for_next_n_packets(uint32_t passthrough_for_next_n_packets)90 void set_passthrough_for_next_n_packets( 91 uint32_t passthrough_for_next_n_packets) { 92 QuicWriterMutexLock lock(&config_mutex_); 93 passthrough_for_next_n_packets_ = passthrough_for_next_n_packets; 94 } 95 96 // Simulate dropping the first n packets unconditionally. 97 // Subsequent packets will be lost at fake_packet_loss_percentage_ if set. set_fake_drop_first_n_packets(int32_t fake_drop_first_n_packets)98 void set_fake_drop_first_n_packets(int32_t fake_drop_first_n_packets) { 99 QuicWriterMutexLock lock(&config_mutex_); 100 fake_drop_first_n_packets_ = fake_drop_first_n_packets; 101 } 102 103 // The percent of time WritePacket will block and set WriteResult's status 104 // to WRITE_STATUS_BLOCKED. set_fake_blocked_socket_percentage(int32_t fake_blocked_socket_percentage)105 void set_fake_blocked_socket_percentage( 106 int32_t fake_blocked_socket_percentage) { 107 QUICHE_DCHECK(clock_); 108 QuicWriterMutexLock lock(&config_mutex_); 109 fake_blocked_socket_percentage_ = fake_blocked_socket_percentage; 110 } 111 112 // The percent of time a packet is simulated as being reordered. set_fake_reorder_percentage(int32_t fake_packet_reorder_percentage)113 void set_fake_reorder_percentage(int32_t fake_packet_reorder_percentage) { 114 QUICHE_DCHECK(clock_); 115 QuicWriterMutexLock lock(&config_mutex_); 116 QUICHE_DCHECK(!fake_packet_delay_.IsZero()); 117 fake_packet_reorder_percentage_ = fake_packet_reorder_percentage; 118 } 119 120 // The delay before writing this packet. set_fake_packet_delay(QuicTime::Delta fake_packet_delay)121 void set_fake_packet_delay(QuicTime::Delta fake_packet_delay) { 122 QUICHE_DCHECK(clock_); 123 QuicWriterMutexLock lock(&config_mutex_); 124 fake_packet_delay_ = fake_packet_delay; 125 } 126 127 // The maximum bandwidth and buffer size of the connection. When these are 128 // set, packets will be delayed until a connection with that bandwidth would 129 // transmit it. Once the |buffer_size| is reached, all new packets are 130 // dropped. set_max_bandwidth_and_buffer_size(QuicBandwidth fake_bandwidth,QuicByteCount buffer_size)131 void set_max_bandwidth_and_buffer_size(QuicBandwidth fake_bandwidth, 132 QuicByteCount buffer_size) { 133 QUICHE_DCHECK(clock_); 134 QuicWriterMutexLock lock(&config_mutex_); 135 fake_bandwidth_ = fake_bandwidth; 136 buffer_size_ = buffer_size; 137 } 138 139 // Useful for reproducing very flaky issues. set_seed(uint64_t seed)140 ABSL_ATTRIBUTE_UNUSED void set_seed(uint64_t seed) { 141 simple_random_.set_seed(seed); 142 } 143 144 private: 145 // Writes out the next packet to the contained writer and returns the time 146 // for the next delayed packet to be written. 147 QuicTime ReleaseNextPacket(); 148 149 // A single packet which will be sent at the supplied send_time. 150 struct DelayedWrite { 151 public: 152 DelayedWrite(const char* buffer, size_t buf_len, 153 const QuicIpAddress& self_address, 154 const QuicSocketAddress& peer_address, 155 std::unique_ptr<PerPacketOptions> options, 156 const QuicPacketWriterParams& params, QuicTime send_time); 157 DelayedWrite(const DelayedWrite&) = delete; 158 DelayedWrite(DelayedWrite&&) = default; 159 DelayedWrite& operator=(const DelayedWrite&) = delete; 160 DelayedWrite& operator=(DelayedWrite&&) = default; 161 ~DelayedWrite(); 162 163 std::string buffer; 164 QuicIpAddress self_address; 165 QuicSocketAddress peer_address; 166 std::unique_ptr<PerPacketOptions> options; 167 QuicPacketWriterParams params; 168 QuicTime send_time; 169 }; 170 171 using DelayedPacketList = std::list<DelayedWrite>; 172 173 const QuicClock* clock_; 174 std::unique_ptr<QuicAlarm> write_unblocked_alarm_; 175 std::unique_ptr<QuicAlarm> delay_alarm_; 176 std::unique_ptr<Delegate> on_can_write_; 177 SimpleRandom simple_random_; 178 // Stored packets delayed by fake packet delay or bandwidth restrictions. 179 DelayedPacketList delayed_packets_; 180 QuicByteCount cur_buffer_size_; 181 uint64_t num_calls_to_write_; 182 uint32_t passthrough_for_next_n_packets_ QUIC_GUARDED_BY(config_mutex_); 183 int32_t num_consecutive_succesful_writes_; 184 185 QuicMutex config_mutex_; 186 int32_t fake_packet_loss_percentage_ QUIC_GUARDED_BY(config_mutex_); 187 int32_t fake_drop_first_n_packets_ QUIC_GUARDED_BY(config_mutex_); 188 int32_t fake_blocked_socket_percentage_ QUIC_GUARDED_BY(config_mutex_); 189 int32_t fake_packet_reorder_percentage_ QUIC_GUARDED_BY(config_mutex_); 190 QuicTime::Delta fake_packet_delay_ QUIC_GUARDED_BY(config_mutex_); 191 QuicBandwidth fake_bandwidth_ QUIC_GUARDED_BY(config_mutex_); 192 QuicByteCount buffer_size_ QUIC_GUARDED_BY(config_mutex_); 193 }; 194 195 } // namespace test 196 } // namespace quic 197 198 #endif // QUICHE_QUIC_TEST_TOOLS_PACKET_DROPPING_TEST_WRITER_H_ 199