| // Copyright 2013 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef NET_TOOLS_QUIC_TEST_TOOLS_PACKET_DROPPING_TEST_WRITER_H_ |
| #define NET_TOOLS_QUIC_TEST_TOOLS_PACKET_DROPPING_TEST_WRITER_H_ |
| |
| #include <list> |
| |
| #include "base/basictypes.h" |
| #include "base/logging.h" |
| #include "base/memory/scoped_ptr.h" |
| #include "base/synchronization/lock.h" |
| #include "net/quic/quic_alarm.h" |
| #include "net/quic/test_tools/quic_test_utils.h" |
| #include "net/tools/quic/quic_epoll_clock.h" |
| #include "net/tools/quic/quic_packet_writer_wrapper.h" |
| #include "net/tools/quic/test_tools/quic_test_client.h" |
| #include "net/tools/quic/test_tools/quic_test_utils.h" |
| |
| namespace net { |
| namespace tools { |
| namespace test { |
| |
| // Simulates a connection that drops packets a configured percentage of the time |
| // and has a blocked socket a configured percentage of the time. Also provides |
| // the options to delay packets and reorder packets if delay is enabled. |
| class PacketDroppingTestWriter : public QuicPacketWriterWrapper { |
| public: |
| class Delegate { |
| public: |
| virtual ~Delegate() {} |
| virtual void OnPacketSent(WriteResult result) = 0; |
| virtual void OnCanWrite() = 0; |
| }; |
| |
| PacketDroppingTestWriter(); |
| |
| virtual ~PacketDroppingTestWriter(); |
| |
| // Must be called before blocking, reordering or delaying (loss is OK). May be |
| // called after connecting if the helper is not available before. |
| // |on_can_write| will be triggered when fake-unblocking; ownership will be |
| // assumed. |
| void Initialize(QuicEpollConnectionHelper* helper, Delegate* on_can_write); |
| |
| // QuicPacketWriter methods: |
| virtual WriteResult WritePacket( |
| const char* buffer, |
| size_t buf_len, |
| const IPAddressNumber& self_address, |
| const IPEndPoint& peer_address) OVERRIDE; |
| |
| virtual bool IsWriteBlocked() const OVERRIDE; |
| |
| virtual void SetWritable() OVERRIDE; |
| |
| // Writes out any packet which should have been sent by now |
| // to the contained writer and returns the time |
| // for the next delayed packet to be written. |
| QuicTime ReleaseOldPackets(); |
| |
| void OnCanWrite(); |
| |
| // The percent of time a packet is simulated as being lost. |
| void set_fake_packet_loss_percentage(int32 fake_packet_loss_percentage) { |
| base::AutoLock locked(config_mutex_); |
| fake_packet_loss_percentage_ = fake_packet_loss_percentage; |
| } |
| |
| // The percent of time WritePacket will block and set WriteResult's status |
| // to WRITE_STATUS_BLOCKED. |
| void set_fake_blocked_socket_percentage( |
| int32 fake_blocked_socket_percentage) { |
| DCHECK(clock_); |
| base::AutoLock locked(config_mutex_); |
| fake_blocked_socket_percentage_ = fake_blocked_socket_percentage; |
| } |
| |
| // The percent of time a packet is simulated as being reordered. |
| void set_fake_reorder_percentage(int32 fake_packet_reorder_percentage) { |
| DCHECK(clock_); |
| base::AutoLock locked(config_mutex_); |
| DCHECK(!fake_packet_delay_.IsZero()); |
| fake_packet_reorder_percentage_ = fake_packet_reorder_percentage; |
| } |
| |
| // The percent of time WritePacket will block and set WriteResult's status |
| // to WRITE_STATUS_BLOCKED. |
| void set_fake_packet_delay(QuicTime::Delta fake_packet_delay) { |
| DCHECK(clock_); |
| base::AutoLock locked(config_mutex_); |
| fake_packet_delay_ = fake_packet_delay; |
| } |
| |
| // The maximum bandwidth and buffer size of the connection. When these are |
| // set, packets will be delayed until a connection with that bandwidth would |
| // transmit it. Once the |buffer_size| is reached, all new packets are |
| // dropped. |
| void set_max_bandwidth_and_buffer_size(QuicBandwidth fake_bandwidth, |
| QuicByteCount buffer_size) { |
| DCHECK(clock_); |
| base::AutoLock locked(config_mutex_); |
| fake_bandwidth_ = fake_bandwidth; |
| buffer_size_ = buffer_size; |
| } |
| |
| void set_seed(uint64 seed) { |
| simple_random_.set_seed(seed); |
| } |
| |
| private: |
| // Writes out the next packet to the contained writer and returns the time |
| // for the next delayed packet to be written. |
| QuicTime ReleaseNextPacket(); |
| |
| // A single packet which will be sent at the supplied send_time. |
| struct DelayedWrite { |
| public: |
| DelayedWrite(const char* buffer, |
| size_t buf_len, |
| const IPAddressNumber& self_address, |
| const IPEndPoint& peer_address, |
| QuicTime send_time); |
| ~DelayedWrite(); |
| |
| string buffer; |
| const IPAddressNumber self_address; |
| const IPEndPoint peer_address; |
| QuicTime send_time; |
| }; |
| |
| typedef std::list<DelayedWrite> DelayedPacketList; |
| |
| const QuicClock* clock_; |
| scoped_ptr<QuicAlarm> write_unblocked_alarm_; |
| scoped_ptr<QuicAlarm> delay_alarm_; |
| scoped_ptr<Delegate> on_can_write_; |
| net::test::SimpleRandom simple_random_; |
| // Stored packets delayed by fake packet delay or bandwidth restrictions. |
| DelayedPacketList delayed_packets_; |
| QuicByteCount cur_buffer_size_; |
| |
| base::Lock config_mutex_; |
| int32 fake_packet_loss_percentage_; |
| int32 fake_blocked_socket_percentage_; |
| int32 fake_packet_reorder_percentage_; |
| QuicTime::Delta fake_packet_delay_; |
| QuicBandwidth fake_bandwidth_; |
| QuicByteCount buffer_size_; |
| |
| DISALLOW_COPY_AND_ASSIGN(PacketDroppingTestWriter); |
| }; |
| |
| } // namespace test |
| } // namespace tools |
| } // namespace net |
| |
| #endif // NET_TOOLS_QUIC_TEST_TOOLS_PACKET_DROPPING_TEST_WRITER_H_ |