fake_network_pipe.h (8937B)
1 /* 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #ifndef CALL_FAKE_NETWORK_PIPE_H_ 12 #define CALL_FAKE_NETWORK_PIPE_H_ 13 14 #include <cstddef> 15 #include <cstdint> 16 #include <deque> 17 #include <map> 18 #include <memory> 19 #include <optional> 20 21 #include "api/array_view.h" 22 #include "api/call/transport.h" 23 #include "api/test/simulated_network.h" 24 #include "call/simulated_packet_receiver.h" 25 #include "modules/rtp_rtcp/source/rtp_packet_received.h" 26 #include "rtc_base/copy_on_write_buffer.h" 27 #include "rtc_base/synchronization/mutex.h" 28 #include "rtc_base/thread_annotations.h" 29 30 namespace webrtc { 31 32 class Clock; 33 class PacketReceiver; 34 enum class MediaType; 35 36 class NetworkPacket { 37 public: 38 NetworkPacket(CopyOnWriteBuffer packet, 39 int64_t send_time, 40 int64_t arrival_time, 41 std::optional<PacketOptions> packet_options, 42 bool is_rtcp, 43 MediaType media_type, 44 std::optional<int64_t> packet_time_us, 45 Transport* transport); 46 47 NetworkPacket(RtpPacketReceived packet, 48 MediaType media_type, 49 int64_t send_time, 50 int64_t arrival_time); 51 52 // Disallow copy constructor and copy assignment (no deep copies of `data_`). 53 NetworkPacket(const NetworkPacket&) = delete; 54 ~NetworkPacket(); 55 NetworkPacket& operator=(const NetworkPacket&) = delete; 56 // Allow move constructor/assignment, so that we can use in stl containers. 57 NetworkPacket(NetworkPacket&&); 58 NetworkPacket& operator=(NetworkPacket&&); 59 60 const uint8_t* data() const { return packet_.data(); } 61 size_t data_length() const { return packet_.size(); } 62 CopyOnWriteBuffer* raw_packet() { return &packet_; } 63 int64_t send_time() const { return send_time_; } 64 int64_t arrival_time() const { return arrival_time_; } 65 void IncrementArrivalTime(int64_t extra_delay) { 66 arrival_time_ += extra_delay; 67 } 68 PacketOptions packet_options() const { 69 return packet_options_.value_or(PacketOptions()); 70 } 71 bool is_rtcp() const { return is_rtcp_; } 72 MediaType media_type() const { return media_type_; } 73 std::optional<int64_t> packet_time_us() const { return packet_time_us_; } 74 RtpPacketReceived* packet_received() { 75 return packet_received_ ? &packet_received_.value() : nullptr; 76 } 77 std::optional<RtpPacketReceived> packet_received() const { 78 return packet_received_; 79 } 80 Transport* transport() const { return transport_; } 81 82 private: 83 CopyOnWriteBuffer packet_; 84 // The time the packet was sent out on the network. 85 int64_t send_time_; 86 // The time the packet should arrive at the receiver. 87 int64_t arrival_time_; 88 // If using a Transport for outgoing degradation, populate with 89 // PacketOptions (transport-wide sequence number) for RTP. 90 std::optional<PacketOptions> packet_options_; 91 bool is_rtcp_; 92 // If using a PacketReceiver for incoming degradation, populate with 93 // appropriate MediaType and packet time. This type/timing will be kept and 94 // forwarded. The packet time might be altered to reflect time spent in fake 95 // network pipe. 96 MediaType media_type_; 97 std::optional<int64_t> packet_time_us_; 98 std::optional<RtpPacketReceived> packet_received_; 99 Transport* transport_; 100 }; 101 102 // Class faking a network link, internally is uses an implementation of a 103 // SimulatedNetworkInterface to simulate network behavior. 104 class FakeNetworkPipe : public SimulatedPacketReceiverInterface { 105 public: 106 // Will keep `network_behavior` alive while pipe is alive itself. 107 FakeNetworkPipe(Clock* clock, 108 std::unique_ptr<NetworkBehaviorInterface> network_behavior); 109 FakeNetworkPipe(Clock* clock, 110 std::unique_ptr<NetworkBehaviorInterface> network_behavior, 111 PacketReceiver* receiver); 112 FakeNetworkPipe(Clock* clock, 113 std::unique_ptr<NetworkBehaviorInterface> network_behavior, 114 PacketReceiver* receiver, 115 uint64_t seed); 116 117 ~FakeNetworkPipe() override; 118 119 FakeNetworkPipe(const FakeNetworkPipe&) = delete; 120 FakeNetworkPipe& operator=(const FakeNetworkPipe&) = delete; 121 122 void SetClockOffset(int64_t offset_ms); 123 124 // Must not be called in parallel with DeliverPacket or Process. 125 void SetReceiver(PacketReceiver* receiver) override; 126 127 // Adds/subtracts references to Transport instances. If a Transport is 128 // destroyed we cannot use to forward a potential delayed packet, these 129 // methods are used to maintain a map of which instances are live. 130 void AddActiveTransport(Transport* transport); 131 void RemoveActiveTransport(Transport* transport); 132 133 // Methods for use with Transport interface. When/if packets are delivered, 134 // they will be passed to the instance specified by the `transport` parameter. 135 // Note that that instance must be in the map of active transports. 136 bool SendRtp(ArrayView<const uint8_t> packet, 137 const PacketOptions& options, 138 Transport* transport); 139 bool SendRtcp(ArrayView<const uint8_t> packet, Transport* transport); 140 141 // Implements the PacketReceiver interface. When/if packets are delivered, 142 // they will be passed directly to the receiver instance given in 143 // SetReceiver(). The receive time will be increased by the amount of time the 144 // packet spent in the fake network pipe. 145 void DeliverRtpPacket( 146 MediaType media_type, 147 RtpPacketReceived packet, 148 OnUndemuxablePacketHandler undemuxable_packet_handler) override; 149 void DeliverRtcpPacket(CopyOnWriteBuffer packet) override; 150 151 // Processes the network queues and trigger PacketReceiver::IncomingPacket for 152 // packets ready to be delivered. 153 void Process() override; 154 std::optional<int64_t> TimeUntilNextProcess() override; 155 156 // Get statistics. 157 float PercentageLoss(); 158 int AverageDelay() override; 159 size_t DroppedPackets(); 160 size_t SentPackets(); 161 void ResetStats(); 162 163 protected: 164 void DeliverPacketWithLock(NetworkPacket* packet); 165 int64_t GetTimeInMicroseconds() const; 166 bool ShouldProcess(int64_t time_now_us) const; 167 void SetTimeToNextProcess(int64_t skip_us); 168 169 private: 170 struct StoredPacket { 171 NetworkPacket packet; 172 bool removed = false; 173 explicit StoredPacket(NetworkPacket&& packet); 174 StoredPacket(StoredPacket&&) = default; 175 StoredPacket(const StoredPacket&) = delete; 176 StoredPacket& operator=(const StoredPacket&) = delete; 177 StoredPacket() = delete; 178 }; 179 180 // Returns true if enqueued, or false if packet was dropped. Use this method 181 // when enqueueing packets that should be received by PacketReceiver instance. 182 bool EnqueuePacket(CopyOnWriteBuffer packet, 183 std::optional<PacketOptions> options, 184 bool is_rtcp, 185 MediaType media_type, 186 std::optional<int64_t> packet_time_us); 187 188 // Returns true if enqueued, or false if packet was dropped. Use this method 189 // when enqueueing packets that should be received by Transport instance. 190 bool EnqueuePacket(CopyOnWriteBuffer packet, 191 std::optional<PacketOptions> options, 192 bool is_rtcp, 193 Transport* transport); 194 195 bool EnqueuePacket(NetworkPacket&& net_packet) 196 RTC_EXCLUSIVE_LOCKS_REQUIRED(process_lock_); 197 198 void DeliverNetworkPacket(NetworkPacket* packet) 199 RTC_EXCLUSIVE_LOCKS_REQUIRED(config_lock_); 200 bool HasReceiver() const; 201 202 Clock* const clock_; 203 // `config_lock` guards the mostly constant things like the callbacks. 204 mutable Mutex config_lock_; 205 const std::unique_ptr<NetworkBehaviorInterface> network_behavior_; 206 PacketReceiver* receiver_ RTC_GUARDED_BY(config_lock_); 207 208 // `process_lock` guards the data structures involved in delay and loss 209 // processes, such as the packet queues. 210 Mutex process_lock_; 211 // Packets are added at the back of the deque, this makes the deque ordered 212 // by increasing send time. The common case when removing packets from the 213 // deque is removing early packets, which will be close to the front of the 214 // deque. This makes finding the packets in the deque efficient in the common 215 // case. 216 std::deque<StoredPacket> packets_in_flight_ RTC_GUARDED_BY(process_lock_); 217 218 int64_t clock_offset_ms_ RTC_GUARDED_BY(config_lock_); 219 220 // Statistics. 221 size_t dropped_packets_ RTC_GUARDED_BY(process_lock_); 222 size_t sent_packets_ RTC_GUARDED_BY(process_lock_); 223 int64_t total_packet_delay_us_ RTC_GUARDED_BY(process_lock_); 224 int64_t last_log_time_us_; 225 226 std::map<Transport*, size_t> active_transports_ RTC_GUARDED_BY(config_lock_); 227 }; 228 229 } // namespace webrtc 230 231 #endif // CALL_FAKE_NETWORK_PIPE_H_