QUIC - Changed DelatedWrite to be a struct and other nits from internal
[chromium-blink-merge.git] / net / tools / quic / test_tools / packet_dropping_test_writer.cc
blob9cb0045c331602cfc762012133cbd03a7695e3da
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 virtual QuicTime OnAlarm() OVERRIDE {
25 DCHECK(writer_->blocked_writer());
26 writer_->blocked_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)
39 : writer_(writer) { }
41 virtual QuicTime OnAlarm() OVERRIDE {
42 return writer_->ReleaseOldPackets();
45 private:
46 PacketDroppingTestWriter* writer_;
49 PacketDroppingTestWriter::PacketDroppingTestWriter()
50 : clock_(NULL),
51 blocked_writer_(NULL),
52 cur_buffer_size_(0),
53 config_mutex_(),
54 fake_packet_loss_percentage_(0),
55 fake_blocked_socket_percentage_(0),
56 fake_packet_reorder_percentage_(0),
57 fake_packet_delay_(QuicTime::Delta::Zero()),
58 fake_bandwidth_(QuicBandwidth::Zero()),
59 buffer_size_(0) {
60 uint32 seed = base::RandInt(0, std::numeric_limits<int32>::max());
61 VLOG(1) << "Seeding packet loss with " << seed;
62 simple_random_.set_seed(seed);
65 PacketDroppingTestWriter::~PacketDroppingTestWriter() {}
67 void PacketDroppingTestWriter::SetConnectionHelper(
68 QuicEpollConnectionHelper* helper) {
69 clock_ = helper->GetClock();
70 write_unblocked_alarm_.reset(
71 helper->CreateAlarm(new WriteUnblockedAlarm(this)));
72 delay_alarm_.reset(
73 helper->CreateAlarm(new DelayAlarm(this)));
76 WriteResult PacketDroppingTestWriter::WritePacket(
77 const char* buffer,
78 size_t buf_len,
79 const net::IPAddressNumber& self_address,
80 const net::IPEndPoint& peer_address,
81 QuicBlockedWriterInterface* blocked_writer) {
82 ReleaseOldPackets();
84 base::AutoLock locked(config_mutex_);
85 if (fake_packet_loss_percentage_ > 0 &&
86 simple_random_.RandUint64() % 100 <
87 static_cast<uint64>(fake_packet_loss_percentage_)) {
88 DVLOG(1) << "Dropping packet.";
89 return WriteResult(WRITE_STATUS_OK, buf_len);
91 if (fake_blocked_socket_percentage_ > 0 &&
92 simple_random_.RandUint64() % 100 <
93 static_cast<uint64>(fake_blocked_socket_percentage_)) {
94 DVLOG(1) << "Blocking socket.";
95 if (!write_unblocked_alarm_->IsSet()) {
96 blocked_writer_ = blocked_writer;
97 // Set the alarm for 1ms in the future.
98 write_unblocked_alarm_->Set(
99 clock_->ApproximateNow().Add(
100 QuicTime::Delta::FromMilliseconds(1)));
102 return WriteResult(WRITE_STATUS_BLOCKED, EAGAIN);
105 if (!fake_packet_delay_.IsZero() || !fake_bandwidth_.IsZero()) {
106 if (buffer_size_ > 0 && buf_len + cur_buffer_size_ > buffer_size_) {
107 // Drop packets which do not fit into the buffer.
108 DVLOG(1) << "Dropping packet because the buffer is full.";
109 return WriteResult(WRITE_STATUS_OK, buf_len);
112 // Queue it to be sent.
113 QuicTime send_time = clock_->ApproximateNow().Add(fake_packet_delay_);
114 if (!fake_bandwidth_.IsZero()) {
115 // Calculate a time the bandwidth limit would impose.
116 QuicTime::Delta bandwidth_delay = QuicTime::Delta::FromMicroseconds(
117 (buf_len * kNumMicrosPerSecond) /
118 fake_bandwidth_.ToBytesPerSecond());
119 send_time = delayed_packets_.empty() ?
120 send_time.Add(bandwidth_delay) :
121 delayed_packets_.back().send_time.Add(bandwidth_delay);
123 delayed_packets_.push_back(DelayedWrite(buffer, buf_len, self_address,
124 peer_address, send_time));
125 cur_buffer_size_ += buf_len;
127 // Set the alarm if it's not yet set.
128 if (!delay_alarm_->IsSet()) {
129 delay_alarm_->Set(send_time);
132 return WriteResult(WRITE_STATUS_OK, buf_len);
135 return QuicPacketWriterWrapper::WritePacket(
136 buffer, buf_len, self_address, peer_address, blocked_writer);
139 QuicTime PacketDroppingTestWriter::ReleaseNextPacket() {
140 if (delayed_packets_.empty()) {
141 return QuicTime::Zero();
143 base::AutoLock locked(config_mutex_);
144 DelayedPacketList::iterator iter = delayed_packets_.begin();
145 // Determine if we should re-order.
146 if (delayed_packets_.size() > 1 && fake_packet_reorder_percentage_ > 0 &&
147 simple_random_.RandUint64() % 100 <
148 static_cast<uint64>(fake_packet_reorder_percentage_)) {
149 DVLOG(1) << "Reordering packets.";
150 ++iter;
151 // Swap the send times when re-ordering packets.
152 delayed_packets_.begin()->send_time = iter->send_time;
155 DVLOG(1) << "Releasing packet. " << (delayed_packets_.size() - 1)
156 << " remaining.";
157 // Grab the next one off the queue and send it.
158 QuicPacketWriterWrapper::WritePacket(
159 iter->buffer.data(), iter->buffer.length(),
160 iter->self_address, iter->peer_address, NULL);
161 DCHECK_GE(cur_buffer_size_, iter->buffer.length());
162 cur_buffer_size_ -= iter->buffer.length();
163 delayed_packets_.erase(iter);
165 // If there are others, find the time for the next to be sent.
166 if (delayed_packets_.empty()) {
167 return QuicTime::Zero();
169 return delayed_packets_.begin()->send_time;
172 QuicTime PacketDroppingTestWriter::ReleaseOldPackets() {
173 while (!delayed_packets_.empty()) {
174 QuicTime next_send_time = delayed_packets_.front().send_time;
175 if (next_send_time > clock_->Now()) {
176 return next_send_time;
178 ReleaseNextPacket();
180 return QuicTime::Zero();
183 PacketDroppingTestWriter::DelayedWrite::DelayedWrite(
184 const char* buffer,
185 size_t buf_len,
186 const net::IPAddressNumber& self_address,
187 const net::IPEndPoint& peer_address,
188 QuicTime send_time)
189 : buffer(buffer, buf_len),
190 self_address(self_address),
191 peer_address(peer_address),
192 send_time(send_time) {}
194 PacketDroppingTestWriter::DelayedWrite::~DelayedWrite() {}
196 } // namespace test
197 } // namespace tools
198 } // namespace net