| // Copyright (c) 2012 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 QUICHE_QUIC_TEST_TOOLS_SIMULATOR_LINK_H_ |
| #define QUICHE_QUIC_TEST_TOOLS_SIMULATOR_LINK_H_ |
| |
| #include <utility> |
| |
| #include "quic/core/crypto/quic_random.h" |
| #include "quic/core/quic_bandwidth.h" |
| #include "quic/test_tools/simulator/actor.h" |
| #include "quic/test_tools/simulator/port.h" |
| #include "common/quiche_circular_deque.h" |
| |
| namespace quic { |
| namespace simulator { |
| |
| // A reliable simplex link between two endpoints with constrained bandwidth. A |
| // few microseconds of random delay are added for every packet to avoid |
| // synchronization issues. |
| class OneWayLink : public Actor, public ConstrainedPortInterface { |
| public: |
| OneWayLink(Simulator* simulator, |
| std::string name, |
| UnconstrainedPortInterface* sink, |
| QuicBandwidth bandwidth, |
| QuicTime::Delta propagation_delay); |
| OneWayLink(const OneWayLink&) = delete; |
| OneWayLink& operator=(const OneWayLink&) = delete; |
| ~OneWayLink() override; |
| |
| void AcceptPacket(std::unique_ptr<Packet> packet) override; |
| QuicTime::Delta TimeUntilAvailable() override; |
| void Act() override; |
| |
| QuicBandwidth bandwidth() const { return bandwidth_; } |
| void set_bandwidth(QuicBandwidth new_bandwidth) { |
| bandwidth_ = new_bandwidth; |
| } |
| |
| protected: |
| // Get the value of a random delay imposed on each packet. By default, this |
| // is a short random delay in order to avoid artifical synchronization |
| // artifacts during the simulation. Subclasses may override this behavior |
| // (for example, to provide a random component of delay). |
| virtual QuicTime::Delta GetRandomDelay(QuicTime::Delta transfer_time); |
| |
| private: |
| struct QueuedPacket { |
| std::unique_ptr<Packet> packet; |
| QuicTime dequeue_time; |
| |
| QueuedPacket(std::unique_ptr<Packet> packet, QuicTime dequeue_time); |
| QueuedPacket(QueuedPacket&& other); |
| ~QueuedPacket(); |
| }; |
| |
| // Schedule the next packet to be egressed out of the link if there are |
| // packets on the link. |
| void ScheduleNextPacketDeparture(); |
| |
| UnconstrainedPortInterface* sink_; |
| quiche::QuicheCircularDeque<QueuedPacket> packets_in_transit_; |
| |
| QuicBandwidth bandwidth_; |
| const QuicTime::Delta propagation_delay_; |
| |
| QuicTime next_write_at_; |
| }; |
| |
| // A full-duplex link between two endpoints, functionally equivalent to two |
| // OneWayLink objects tied together. |
| class SymmetricLink { |
| public: |
| SymmetricLink(Simulator* simulator, |
| std::string name, |
| UnconstrainedPortInterface* sink_a, |
| UnconstrainedPortInterface* sink_b, |
| QuicBandwidth bandwidth, |
| QuicTime::Delta propagation_delay); |
| SymmetricLink(Endpoint* endpoint_a, |
| Endpoint* endpoint_b, |
| QuicBandwidth bandwidth, |
| QuicTime::Delta propagation_delay); |
| SymmetricLink(const SymmetricLink&) = delete; |
| SymmetricLink& operator=(const SymmetricLink&) = delete; |
| |
| QuicBandwidth bandwidth() { return a_to_b_link_.bandwidth(); } |
| void set_bandwidth(QuicBandwidth new_bandwidth) { |
| a_to_b_link_.set_bandwidth(new_bandwidth); |
| b_to_a_link_.set_bandwidth(new_bandwidth); |
| } |
| |
| private: |
| OneWayLink a_to_b_link_; |
| OneWayLink b_to_a_link_; |
| }; |
| |
| } // namespace simulator |
| } // namespace quic |
| |
| #endif // QUICHE_QUIC_TEST_TOOLS_SIMULATOR_LINK_H_ |