We started redesigning GpuMemoryBuffer interface to handle multiple buffers [0].
[chromium-blink-merge.git] / net / tools / quic / test_tools / packet_dropping_test_writer.cc
blobe31a72826bbbf4de16353bac7135f4c5190b0af4
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.
5 #include "net/tools/quic/test_tools/packet_dropping_test_writer.h"
7 #include <limits>
9 #include "base/rand_util.h"
10 #include "net/tools/quic/quic_epoll_connection_helper.h"
11 #include "net/tools/quic/quic_socket_utils.h"
13 namespace net {
14 namespace tools {
15 namespace test {
17 // An alarm that is scheduled if a blocked socket is simulated to indicate
18 // it's writable again.
19 class WriteUnblockedAlarm : public QuicAlarm::Delegate {
20 public:
21 explicit WriteUnblockedAlarm(PacketDroppingTestWriter* writer)
22 : writer_(writer) {}
24 QuicTime OnAlarm() override {
25 DVLOG(1) << "Unblocking socket.";
26 writer_->OnCanWrite();
27 return QuicTime::Zero();
30 private:
31 PacketDroppingTestWriter* writer_;
34 // An alarm that is scheduled every time a new packet is to be written at a
35 // later point.
36 class DelayAlarm : public QuicAlarm::Delegate {
37 public:
38 explicit DelayAlarm(PacketDroppingTestWriter* writer) : writer_(writer) {}
40 QuicTime OnAlarm() override { return writer_->ReleaseOldPackets(); }
42 private:
43 PacketDroppingTestWriter* writer_;
46 PacketDroppingTestWriter::PacketDroppingTestWriter()
47 : clock_(nullptr),
48 cur_buffer_size_(0),
49 config_mutex_(),
50 fake_packet_loss_percentage_(0),
51 fake_blocked_socket_percentage_(0),
52 fake_packet_reorder_percentage_(0),
53 fake_packet_delay_(QuicTime::Delta::Zero()),
54 fake_bandwidth_(QuicBandwidth::Zero()),
55 buffer_size_(0) {
56 uint32 seed = base::RandInt(0, std::numeric_limits<int32>::max());
57 VLOG(1) << "Seeding packet loss with " << seed;
58 simple_random_.set_seed(seed);
61 PacketDroppingTestWriter::~PacketDroppingTestWriter() {}
63 void PacketDroppingTestWriter::Initialize(
64 QuicConnectionHelperInterface* helper,
65 Delegate* on_can_write) {
66 clock_ = helper->GetClock();
67 write_unblocked_alarm_.reset(
68 helper->CreateAlarm(new WriteUnblockedAlarm(this)));
69 delay_alarm_.reset(
70 helper->CreateAlarm(new DelayAlarm(this)));
71 on_can_write_.reset(on_can_write);
74 WriteResult PacketDroppingTestWriter::WritePacket(
75 const char* buffer,
76 size_t buf_len,
77 const net::IPAddressNumber& self_address,
78 const net::IPEndPoint& peer_address) {
79 ReleaseOldPackets();
81 base::AutoLock locked(config_mutex_);
82 if (fake_packet_loss_percentage_ > 0 &&
83 simple_random_.RandUint64() % 100 <
84 static_cast<uint64>(fake_packet_loss_percentage_)) {
85 DVLOG(1) << "Dropping packet.";
86 return WriteResult(WRITE_STATUS_OK, buf_len);
88 if (fake_blocked_socket_percentage_ > 0 &&
89 simple_random_.RandUint64() % 100 <
90 static_cast<uint64>(fake_blocked_socket_percentage_)) {
91 CHECK(on_can_write_.get() != nullptr);
92 DVLOG(1) << "Blocking socket.";
93 if (!write_unblocked_alarm_->IsSet()) {
94 // Set the alarm to fire immediately.
95 write_unblocked_alarm_->Set(clock_->ApproximateNow());
97 return WriteResult(WRITE_STATUS_BLOCKED, EAGAIN);
100 if (!fake_packet_delay_.IsZero() || !fake_bandwidth_.IsZero()) {
101 if (buffer_size_ > 0 && buf_len + cur_buffer_size_ > buffer_size_) {
102 // Drop packets which do not fit into the buffer.
103 DVLOG(1) << "Dropping packet because the buffer is full.";
104 return WriteResult(WRITE_STATUS_OK, buf_len);
107 // Queue it to be sent.
108 QuicTime send_time = clock_->ApproximateNow().Add(fake_packet_delay_);
109 if (!fake_bandwidth_.IsZero()) {
110 // Calculate a time the bandwidth limit would impose.
111 QuicTime::Delta bandwidth_delay = QuicTime::Delta::FromMicroseconds(
112 (buf_len * kNumMicrosPerSecond) /
113 fake_bandwidth_.ToBytesPerSecond());
114 send_time = delayed_packets_.empty() ?
115 send_time.Add(bandwidth_delay) :
116 delayed_packets_.back().send_time.Add(bandwidth_delay);
118 delayed_packets_.push_back(DelayedWrite(buffer, buf_len, self_address,
119 peer_address, send_time));
120 cur_buffer_size_ += buf_len;
122 // Set the alarm if it's not yet set.
123 if (!delay_alarm_->IsSet()) {
124 delay_alarm_->Set(send_time);
127 return WriteResult(WRITE_STATUS_OK, buf_len);
130 return QuicPacketWriterWrapper::WritePacket(
131 buffer, buf_len, self_address, peer_address);
134 bool PacketDroppingTestWriter::IsWriteBlocked() const {
135 if (write_unblocked_alarm_.get() != nullptr &&
136 write_unblocked_alarm_->IsSet()) {
137 return true;
139 return QuicPacketWriterWrapper::IsWriteBlocked();
142 void PacketDroppingTestWriter::SetWritable() {
143 if (write_unblocked_alarm_.get() != nullptr &&
144 write_unblocked_alarm_->IsSet()) {
145 write_unblocked_alarm_->Cancel();
147 QuicPacketWriterWrapper::SetWritable();
150 QuicTime PacketDroppingTestWriter::ReleaseNextPacket() {
151 if (delayed_packets_.empty()) {
152 return QuicTime::Zero();
154 base::AutoLock locked(config_mutex_);
155 DelayedPacketList::iterator iter = delayed_packets_.begin();
156 // Determine if we should re-order.
157 if (delayed_packets_.size() > 1 && fake_packet_reorder_percentage_ > 0 &&
158 simple_random_.RandUint64() % 100 <
159 static_cast<uint64>(fake_packet_reorder_percentage_)) {
160 DVLOG(1) << "Reordering packets.";
161 ++iter;
162 // Swap the send times when re-ordering packets.
163 delayed_packets_.begin()->send_time = iter->send_time;
166 DVLOG(1) << "Releasing packet. " << (delayed_packets_.size() - 1)
167 << " remaining.";
168 // Grab the next one off the queue and send it.
169 QuicPacketWriterWrapper::WritePacket(
170 iter->buffer.data(), iter->buffer.length(),
171 iter->self_address, iter->peer_address);
172 DCHECK_GE(cur_buffer_size_, iter->buffer.length());
173 cur_buffer_size_ -= iter->buffer.length();
174 delayed_packets_.erase(iter);
176 // If there are others, find the time for the next to be sent.
177 if (delayed_packets_.empty()) {
178 return QuicTime::Zero();
180 return delayed_packets_.begin()->send_time;
183 QuicTime PacketDroppingTestWriter::ReleaseOldPackets() {
184 while (!delayed_packets_.empty()) {
185 QuicTime next_send_time = delayed_packets_.front().send_time;
186 if (next_send_time > clock_->Now()) {
187 return next_send_time;
189 ReleaseNextPacket();
191 return QuicTime::Zero();
194 void PacketDroppingTestWriter::OnCanWrite() {
195 on_can_write_->OnCanWrite();
198 PacketDroppingTestWriter::DelayedWrite::DelayedWrite(
199 const char* buffer,
200 size_t buf_len,
201 const net::IPAddressNumber& self_address,
202 const net::IPEndPoint& peer_address,
203 QuicTime send_time)
204 : buffer(buffer, buf_len),
205 self_address(self_address),
206 peer_address(peer_address),
207 send_time(send_time) {}
209 PacketDroppingTestWriter::DelayedWrite::~DelayedWrite() {}
211 } // namespace test
212 } // namespace tools
213 } // namespace net