blob: c15b5de01b5c89dfecace107c282d36967be9644 [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// 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
vasilvv8f9591b2020-10-26 17:01:14 -070012#include "absl/base/attributes.h"
QUICHE team5be974e2020-12-29 18:35:24 -050013#include "quic/core/quic_alarm.h"
14#include "quic/core/quic_clock.h"
15#include "quic/core/quic_packet_writer_wrapper.h"
16#include "quic/test_tools/quic_test_client.h"
17#include "quic/test_tools/quic_test_utils.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050018
19namespace quic {
20namespace test {
21
22// Simulates a connection that drops packets a configured percentage of the time
23// and has a blocked socket a configured percentage of the time. Also provides
24// the options to delay packets and reorder packets if delay is enabled.
25class PacketDroppingTestWriter : public QuicPacketWriterWrapper {
26 public:
27 class Delegate {
28 public:
29 virtual ~Delegate() {}
30 virtual void OnCanWrite() = 0;
31 };
32
33 PacketDroppingTestWriter();
34 PacketDroppingTestWriter(const PacketDroppingTestWriter&) = delete;
35 PacketDroppingTestWriter& operator=(const PacketDroppingTestWriter&) = delete;
36
37 ~PacketDroppingTestWriter() override;
38
39 // Must be called before blocking, reordering or delaying (loss is OK). May be
40 // called after connecting if the helper is not available before.
41 // |on_can_write| will be triggered when fake-unblocking.
42 void Initialize(QuicConnectionHelperInterface* helper,
43 QuicAlarmFactory* alarm_factory,
44 std::unique_ptr<Delegate> on_can_write);
45
46 // QuicPacketWriter methods:
47 WriteResult WritePacket(const char* buffer,
48 size_t buf_len,
49 const QuicIpAddress& self_address,
50 const QuicSocketAddress& peer_address,
51 PerPacketOptions* options) override;
52
53 bool IsWriteBlocked() const override;
54
55 void SetWritable() override;
56
wub50d4c712020-05-19 15:48:28 -070057 QuicPacketBuffer GetNextWriteLocation(
dschinazi17d42422019-06-18 16:35:07 -070058 const QuicIpAddress& /*self_address*/,
59 const QuicSocketAddress& /*peer_address*/) override {
QUICHE teama6ef0a62019-03-07 20:34:33 -050060 // If the wrapped writer supports zero-copy, disable it, because it is not
61 // compatible with delayed writes in this class.
wub50d4c712020-05-19 15:48:28 -070062 return {nullptr, nullptr};
QUICHE teama6ef0a62019-03-07 20:34:33 -050063 }
64
65 // Writes out any packet which should have been sent by now
66 // to the contained writer and returns the time
67 // for the next delayed packet to be written.
68 QuicTime ReleaseOldPackets();
69
70 // Sets |delay_alarm_| to fire at |new_deadline|.
71 void SetDelayAlarm(QuicTime new_deadline);
72
73 void OnCanWrite();
74
75 // The percent of time a packet is simulated as being lost.
bnced1fe4f2020-07-01 04:48:53 -070076 // If |fake_packet_loss_percentage| is 100, then all packages are lost.
77 // Otherwise actual percentage will be lower than
78 // |fake_packet_loss_percentage|, because every dropped package is followed by
79 // a minimum number of successfully written packets.
80 void set_fake_packet_loss_percentage(int32_t fake_packet_loss_percentage) {
81 QuicWriterMutexLock lock(&config_mutex_);
82 fake_packet_loss_percentage_ = fake_packet_loss_percentage;
83 }
QUICHE teama6ef0a62019-03-07 20:34:33 -050084
85 // Simulate dropping the first n packets unconditionally.
86 // Subsequent packets will be lost at fake_packet_loss_percentage_ if set.
87 void set_fake_drop_first_n_packets(int32_t fake_drop_first_n_packets) {
88 QuicWriterMutexLock lock(&config_mutex_);
89 fake_drop_first_n_packets_ = fake_drop_first_n_packets;
90 }
91
92 // The percent of time WritePacket will block and set WriteResult's status
93 // to WRITE_STATUS_BLOCKED.
94 void set_fake_blocked_socket_percentage(
95 int32_t fake_blocked_socket_percentage) {
vasilvv5cef78e2021-01-30 11:11:14 -080096 QUICHE_DCHECK(clock_);
QUICHE teama6ef0a62019-03-07 20:34:33 -050097 QuicWriterMutexLock lock(&config_mutex_);
98 fake_blocked_socket_percentage_ = fake_blocked_socket_percentage;
99 }
100
101 // The percent of time a packet is simulated as being reordered.
102 void set_fake_reorder_percentage(int32_t fake_packet_reorder_percentage) {
vasilvv5cef78e2021-01-30 11:11:14 -0800103 QUICHE_DCHECK(clock_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500104 QuicWriterMutexLock lock(&config_mutex_);
vasilvv5cef78e2021-01-30 11:11:14 -0800105 QUICHE_DCHECK(!fake_packet_delay_.IsZero());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500106 fake_packet_reorder_percentage_ = fake_packet_reorder_percentage;
107 }
108
109 // The delay before writing this packet.
110 void set_fake_packet_delay(QuicTime::Delta fake_packet_delay) {
vasilvv5cef78e2021-01-30 11:11:14 -0800111 QUICHE_DCHECK(clock_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500112 QuicWriterMutexLock lock(&config_mutex_);
113 fake_packet_delay_ = fake_packet_delay;
114 }
115
116 // The maximum bandwidth and buffer size of the connection. When these are
117 // set, packets will be delayed until a connection with that bandwidth would
118 // transmit it. Once the |buffer_size| is reached, all new packets are
119 // dropped.
120 void set_max_bandwidth_and_buffer_size(QuicBandwidth fake_bandwidth,
121 QuicByteCount buffer_size) {
vasilvv5cef78e2021-01-30 11:11:14 -0800122 QUICHE_DCHECK(clock_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500123 QuicWriterMutexLock lock(&config_mutex_);
124 fake_bandwidth_ = fake_bandwidth;
125 buffer_size_ = buffer_size;
126 }
127
128 // Useful for reproducing very flaky issues.
vasilvv8f9591b2020-10-26 17:01:14 -0700129 ABSL_ATTRIBUTE_UNUSED void set_seed(uint64_t seed) {
130 simple_random_.set_seed(seed);
131 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500132
133 private:
134 // Writes out the next packet to the contained writer and returns the time
135 // for the next delayed packet to be written.
136 QuicTime ReleaseNextPacket();
137
138 // A single packet which will be sent at the supplied send_time.
139 struct DelayedWrite {
140 public:
141 DelayedWrite(const char* buffer,
142 size_t buf_len,
143 const QuicIpAddress& self_address,
144 const QuicSocketAddress& peer_address,
145 std::unique_ptr<PerPacketOptions> options,
146 QuicTime send_time);
147 DelayedWrite(const DelayedWrite&) = delete;
148 DelayedWrite(DelayedWrite&&) = default;
149 DelayedWrite& operator=(const DelayedWrite&) = delete;
150 DelayedWrite& operator=(DelayedWrite&&) = default;
151 ~DelayedWrite();
152
vasilvvc48c8712019-03-11 13:38:16 -0700153 std::string buffer;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500154 QuicIpAddress self_address;
155 QuicSocketAddress peer_address;
156 std::unique_ptr<PerPacketOptions> options;
157 QuicTime send_time;
158 };
159
renjietang58b3af32020-11-11 15:48:58 -0800160 using DelayedPacketList = std::list<DelayedWrite>;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500161
162 const QuicClock* clock_;
163 std::unique_ptr<QuicAlarm> write_unblocked_alarm_;
164 std::unique_ptr<QuicAlarm> delay_alarm_;
165 std::unique_ptr<Delegate> on_can_write_;
166 SimpleRandom simple_random_;
167 // Stored packets delayed by fake packet delay or bandwidth restrictions.
168 DelayedPacketList delayed_packets_;
169 QuicByteCount cur_buffer_size_;
170 uint64_t num_calls_to_write_;
bnced1fe4f2020-07-01 04:48:53 -0700171 int32_t num_consecutive_succesful_writes_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500172
173 QuicMutex config_mutex_;
rch52cb79f2019-08-30 13:35:57 -0700174 int32_t fake_packet_loss_percentage_ QUIC_GUARDED_BY(config_mutex_);
175 int32_t fake_drop_first_n_packets_ QUIC_GUARDED_BY(config_mutex_);
176 int32_t fake_blocked_socket_percentage_ QUIC_GUARDED_BY(config_mutex_);
177 int32_t fake_packet_reorder_percentage_ QUIC_GUARDED_BY(config_mutex_);
178 QuicTime::Delta fake_packet_delay_ QUIC_GUARDED_BY(config_mutex_);
179 QuicBandwidth fake_bandwidth_ QUIC_GUARDED_BY(config_mutex_);
180 QuicByteCount buffer_size_ QUIC_GUARDED_BY(config_mutex_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500181};
182
183} // namespace test
184} // namespace quic
185
186#endif // QUICHE_QUIC_TEST_TOOLS_PACKET_DROPPING_TEST_WRITER_H_