• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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) override;
53 
54   bool IsWriteBlocked() const override;
55 
56   void SetWritable() override;
57 
GetNextWriteLocation(const QuicIpAddress &,const QuicSocketAddress &)58   QuicPacketBuffer GetNextWriteLocation(
59       const QuicIpAddress& /*self_address*/,
60       const QuicSocketAddress& /*peer_address*/) override {
61     // If the wrapped writer supports zero-copy, disable it, because it is not
62     // compatible with delayed writes in this class.
63     return {nullptr, nullptr};
64   }
65 
66   // Writes out any packet which should have been sent by now
67   // to the contained writer and returns the time
68   // for the next delayed packet to be written.
69   QuicTime ReleaseOldPackets();
70 
71   // Sets |delay_alarm_| to fire at |new_deadline|.
72   void SetDelayAlarm(QuicTime new_deadline);
73 
74   void OnCanWrite();
75 
76   // The percent of time a packet is simulated as being lost.
77   // If |fake_packet_loss_percentage| is 100, then all packages are lost.
78   // Otherwise actual percentage will be lower than
79   // |fake_packet_loss_percentage|, because every dropped package is followed by
80   // a minimum number of successfully written packets.
set_fake_packet_loss_percentage(int32_t fake_packet_loss_percentage)81   void set_fake_packet_loss_percentage(int32_t fake_packet_loss_percentage) {
82     QuicWriterMutexLock lock(&config_mutex_);
83     fake_packet_loss_percentage_ = fake_packet_loss_percentage;
84   }
85 
86   // Simulate dropping the first n packets unconditionally.
87   // 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)88   void set_fake_drop_first_n_packets(int32_t fake_drop_first_n_packets) {
89     QuicWriterMutexLock lock(&config_mutex_);
90     fake_drop_first_n_packets_ = fake_drop_first_n_packets;
91   }
92 
93   // The percent of time WritePacket will block and set WriteResult's status
94   // to WRITE_STATUS_BLOCKED.
set_fake_blocked_socket_percentage(int32_t fake_blocked_socket_percentage)95   void set_fake_blocked_socket_percentage(
96       int32_t fake_blocked_socket_percentage) {
97     QUICHE_DCHECK(clock_);
98     QuicWriterMutexLock lock(&config_mutex_);
99     fake_blocked_socket_percentage_ = fake_blocked_socket_percentage;
100   }
101 
102   // The percent of time a packet is simulated as being reordered.
set_fake_reorder_percentage(int32_t fake_packet_reorder_percentage)103   void set_fake_reorder_percentage(int32_t fake_packet_reorder_percentage) {
104     QUICHE_DCHECK(clock_);
105     QuicWriterMutexLock lock(&config_mutex_);
106     QUICHE_DCHECK(!fake_packet_delay_.IsZero());
107     fake_packet_reorder_percentage_ = fake_packet_reorder_percentage;
108   }
109 
110   // The delay before writing this packet.
set_fake_packet_delay(QuicTime::Delta fake_packet_delay)111   void set_fake_packet_delay(QuicTime::Delta fake_packet_delay) {
112     QUICHE_DCHECK(clock_);
113     QuicWriterMutexLock lock(&config_mutex_);
114     fake_packet_delay_ = fake_packet_delay;
115   }
116 
117   // The maximum bandwidth and buffer size of the connection.  When these are
118   // set, packets will be delayed until a connection with that bandwidth would
119   // transmit it.  Once the |buffer_size| is reached, all new packets are
120   // dropped.
set_max_bandwidth_and_buffer_size(QuicBandwidth fake_bandwidth,QuicByteCount buffer_size)121   void set_max_bandwidth_and_buffer_size(QuicBandwidth fake_bandwidth,
122                                          QuicByteCount buffer_size) {
123     QUICHE_DCHECK(clock_);
124     QuicWriterMutexLock lock(&config_mutex_);
125     fake_bandwidth_ = fake_bandwidth;
126     buffer_size_ = buffer_size;
127   }
128 
129   // Useful for reproducing very flaky issues.
set_seed(uint64_t seed)130   ABSL_ATTRIBUTE_UNUSED void set_seed(uint64_t seed) {
131     simple_random_.set_seed(seed);
132   }
133 
134  private:
135   // Writes out the next packet to the contained writer and returns the time
136   // for the next delayed packet to be written.
137   QuicTime ReleaseNextPacket();
138 
139   // A single packet which will be sent at the supplied send_time.
140   struct DelayedWrite {
141    public:
142     DelayedWrite(const char* buffer, size_t buf_len,
143                  const QuicIpAddress& self_address,
144                  const QuicSocketAddress& peer_address,
145                  std::unique_ptr<PerPacketOptions> options, QuicTime send_time);
146     DelayedWrite(const DelayedWrite&) = delete;
147     DelayedWrite(DelayedWrite&&) = default;
148     DelayedWrite& operator=(const DelayedWrite&) = delete;
149     DelayedWrite& operator=(DelayedWrite&&) = default;
150     ~DelayedWrite();
151 
152     std::string buffer;
153     QuicIpAddress self_address;
154     QuicSocketAddress peer_address;
155     std::unique_ptr<PerPacketOptions> options;
156     QuicTime send_time;
157   };
158 
159   using DelayedPacketList = std::list<DelayedWrite>;
160 
161   const QuicClock* clock_;
162   std::unique_ptr<QuicAlarm> write_unblocked_alarm_;
163   std::unique_ptr<QuicAlarm> delay_alarm_;
164   std::unique_ptr<Delegate> on_can_write_;
165   SimpleRandom simple_random_;
166   // Stored packets delayed by fake packet delay or bandwidth restrictions.
167   DelayedPacketList delayed_packets_;
168   QuicByteCount cur_buffer_size_;
169   uint64_t num_calls_to_write_;
170   int32_t num_consecutive_succesful_writes_;
171 
172   QuicMutex config_mutex_;
173   int32_t fake_packet_loss_percentage_ QUIC_GUARDED_BY(config_mutex_);
174   int32_t fake_drop_first_n_packets_ QUIC_GUARDED_BY(config_mutex_);
175   int32_t fake_blocked_socket_percentage_ QUIC_GUARDED_BY(config_mutex_);
176   int32_t fake_packet_reorder_percentage_ QUIC_GUARDED_BY(config_mutex_);
177   QuicTime::Delta fake_packet_delay_ QUIC_GUARDED_BY(config_mutex_);
178   QuicBandwidth fake_bandwidth_ QUIC_GUARDED_BY(config_mutex_);
179   QuicByteCount buffer_size_ QUIC_GUARDED_BY(config_mutex_);
180 };
181 
182 }  // namespace test
183 }  // namespace quic
184 
185 #endif  // QUICHE_QUIC_TEST_TOOLS_PACKET_DROPPING_TEST_WRITER_H_
186