1 /*
2  *  Copyright (c) 2019 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 #ifndef API_TEST_NETWORK_EMULATION_NETWORK_EMULATION_INTERFACES_H_
11 #define API_TEST_NETWORK_EMULATION_NETWORK_EMULATION_INTERFACES_H_
12 
13 #include <map>
14 #include <vector>
15 
16 #include "absl/types/optional.h"
17 #include "api/units/data_rate.h"
18 #include "api/units/data_size.h"
19 #include "api/units/timestamp.h"
20 #include "rtc_base/copy_on_write_buffer.h"
21 #include "rtc_base/ip_address.h"
22 #include "rtc_base/socket_address.h"
23 
24 namespace webrtc {
25 
26 struct EmulatedIpPacket {
27  public:
28   EmulatedIpPacket(const rtc::SocketAddress& from,
29                    const rtc::SocketAddress& to,
30                    rtc::CopyOnWriteBuffer data,
31                    Timestamp arrival_time,
32                    uint16_t application_overhead = 0);
33   ~EmulatedIpPacket() = default;
34   // This object is not copyable or assignable.
35   EmulatedIpPacket(const EmulatedIpPacket&) = delete;
36   EmulatedIpPacket& operator=(const EmulatedIpPacket&) = delete;
37   // This object is only moveable.
38   EmulatedIpPacket(EmulatedIpPacket&&) = default;
39   EmulatedIpPacket& operator=(EmulatedIpPacket&&) = default;
40 
sizeEmulatedIpPacket41   size_t size() const { return data.size(); }
cdataEmulatedIpPacket42   const uint8_t* cdata() const { return data.cdata(); }
43 
ip_packet_sizeEmulatedIpPacket44   size_t ip_packet_size() const { return size() + headers_size; }
45   rtc::SocketAddress from;
46   rtc::SocketAddress to;
47   // Holds the UDP payload.
48   rtc::CopyOnWriteBuffer data;
49   uint16_t headers_size;
50   Timestamp arrival_time;
51 };
52 
53 // Interface for handling IP packets from an emulated network. This is used with
54 // EmulatedEndpoint to receive packets on a specific port.
55 class EmulatedNetworkReceiverInterface {
56  public:
57   virtual ~EmulatedNetworkReceiverInterface() = default;
58 
59   virtual void OnPacketReceived(EmulatedIpPacket packet) = 0;
60 };
61 
62 struct EmulatedNetworkIncomingStats {
63   // Total amount of packets received with or without destination.
64   int64_t packets_received = 0;
65   // Total amount of bytes in received packets.
66   DataSize bytes_received = DataSize::Zero();
67   // Total amount of packets that were received, but no destination was found.
68   int64_t packets_dropped = 0;
69   // Total amount of bytes in dropped packets.
70   DataSize bytes_dropped = DataSize::Zero();
71 
72   DataSize first_received_packet_size = DataSize::Zero();
73 
74   // Timestamps are initialized to different infinities for simplifying
75   // computations. Client have to assume that it is some infinite value
76   // if unset. Client mustn't consider sign of infinit value.
77   Timestamp first_packet_received_time = Timestamp::PlusInfinity();
78   Timestamp last_packet_received_time = Timestamp::MinusInfinity();
79 
AverageReceiveRateEmulatedNetworkIncomingStats80   DataRate AverageReceiveRate() const {
81     RTC_DCHECK_GE(packets_received, 2);
82     RTC_DCHECK(first_packet_received_time.IsFinite());
83     RTC_DCHECK(last_packet_received_time.IsFinite());
84     return (bytes_received - first_received_packet_size) /
85            (last_packet_received_time - first_packet_received_time);
86   }
87 };
88 
89 struct EmulatedNetworkStats {
90   int64_t packets_sent = 0;
91   DataSize bytes_sent = DataSize::Zero();
92 
93   DataSize first_sent_packet_size = DataSize::Zero();
94   Timestamp first_packet_sent_time = Timestamp::PlusInfinity();
95   Timestamp last_packet_sent_time = Timestamp::MinusInfinity();
96 
97   // List of IP addresses that were used to send data considered in this stats
98   // object.
99   std::vector<rtc::IPAddress> local_addresses;
100 
101   std::map<rtc::IPAddress, EmulatedNetworkIncomingStats>
102       incoming_stats_per_source;
103 
AverageSendRateEmulatedNetworkStats104   DataRate AverageSendRate() const {
105     RTC_DCHECK_GE(packets_sent, 2);
106     return (bytes_sent - first_sent_packet_size) /
107            (last_packet_sent_time - first_packet_sent_time);
108   }
109 
110   // Total amount of packets received regardless of the destination address.
PacketsReceivedEmulatedNetworkStats111   int64_t PacketsReceived() const {
112     int64_t packets_received = 0;
113     for (const auto& incoming_stats : incoming_stats_per_source) {
114       packets_received += incoming_stats.second.packets_received;
115     }
116     return packets_received;
117   }
118 
119   // Total amount of bytes in received packets.
BytesReceivedEmulatedNetworkStats120   DataSize BytesReceived() const {
121     DataSize bytes_received = DataSize::Zero();
122     for (const auto& incoming_stats : incoming_stats_per_source) {
123       bytes_received += incoming_stats.second.bytes_received;
124     }
125     return bytes_received;
126   }
127 
128   // Total amount of packets that were received, but no destination was found.
PacketsDroppedEmulatedNetworkStats129   int64_t PacketsDropped() const {
130     int64_t packets_dropped = 0;
131     for (const auto& incoming_stats : incoming_stats_per_source) {
132       packets_dropped += incoming_stats.second.packets_dropped;
133     }
134     return packets_dropped;
135   }
136 
137   // Total amount of bytes in dropped packets.
BytesDroppedEmulatedNetworkStats138   DataSize BytesDropped() const {
139     DataSize bytes_dropped = DataSize::Zero();
140     for (const auto& incoming_stats : incoming_stats_per_source) {
141       bytes_dropped += incoming_stats.second.bytes_dropped;
142     }
143     return bytes_dropped;
144   }
145 
FirstReceivedPacketSizeEmulatedNetworkStats146   DataSize FirstReceivedPacketSize() const {
147     Timestamp first_packet_received_time = Timestamp::PlusInfinity();
148     DataSize first_received_packet_size = DataSize::Zero();
149     for (const auto& incoming_stats : incoming_stats_per_source) {
150       if (first_packet_received_time >
151           incoming_stats.second.first_packet_received_time) {
152         first_packet_received_time =
153             incoming_stats.second.first_packet_received_time;
154         first_received_packet_size =
155             incoming_stats.second.first_received_packet_size;
156       }
157     }
158     return first_received_packet_size;
159   }
160 
FirstPacketReceivedTimeEmulatedNetworkStats161   Timestamp FirstPacketReceivedTime() const {
162     Timestamp first_packet_received_time = Timestamp::PlusInfinity();
163     for (const auto& incoming_stats : incoming_stats_per_source) {
164       if (first_packet_received_time >
165           incoming_stats.second.first_packet_received_time) {
166         first_packet_received_time =
167             incoming_stats.second.first_packet_received_time;
168       }
169     }
170     return first_packet_received_time;
171   }
172 
LastPacketReceivedTimeEmulatedNetworkStats173   Timestamp LastPacketReceivedTime() const {
174     Timestamp last_packet_received_time = Timestamp::MinusInfinity();
175     for (const auto& incoming_stats : incoming_stats_per_source) {
176       if (last_packet_received_time <
177           incoming_stats.second.last_packet_received_time) {
178         last_packet_received_time =
179             incoming_stats.second.last_packet_received_time;
180       }
181     }
182     return last_packet_received_time;
183   }
184 
AverageReceiveRateEmulatedNetworkStats185   DataRate AverageReceiveRate() const {
186     RTC_DCHECK_GE(PacketsReceived(), 2);
187     return (BytesReceived() - FirstReceivedPacketSize()) /
188            (LastPacketReceivedTime() - FirstPacketReceivedTime());
189   }
190 };
191 
192 // EmulatedEndpoint is an abstraction for network interface on device. Instances
193 // of this are created by NetworkEmulationManager::CreateEndpoint.
194 class EmulatedEndpoint : public EmulatedNetworkReceiverInterface {
195  public:
196   // Send packet into network.
197   // |from| will be used to set source address for the packet in destination
198   // socket.
199   // |to| will be used for routing verification and picking right socket by port
200   // on destination endpoint.
201   virtual void SendPacket(const rtc::SocketAddress& from,
202                           const rtc::SocketAddress& to,
203                           rtc::CopyOnWriteBuffer packet_data,
204                           uint16_t application_overhead = 0) = 0;
205 
206   // Binds receiver to this endpoint to send and receive data.
207   // |desired_port| is a port that should be used. If it is equal to 0,
208   // endpoint will pick the first available port starting from
209   // |kFirstEphemeralPort|.
210   //
211   // Returns the port, that should be used (it will be equals to desired, if
212   // |desired_port| != 0 and is free or will be the one, selected by endpoint)
213   // or absl::nullopt if desired_port in used. Also fails if there are no more
214   // free ports to bind to.
215   virtual absl::optional<uint16_t> BindReceiver(
216       uint16_t desired_port,
217       EmulatedNetworkReceiverInterface* receiver) = 0;
218   virtual void UnbindReceiver(uint16_t port) = 0;
219   virtual rtc::IPAddress GetPeerLocalAddress() const = 0;
220 
221   virtual EmulatedNetworkStats stats() = 0;
222 
223  private:
224   // Ensure that there can be no other subclass than EmulatedEndpointImpl. This
225   // means that it's always safe to downcast EmulatedEndpoint instances to
226   // EmulatedEndpointImpl.
227   friend class EmulatedEndpointImpl;
228   EmulatedEndpoint() = default;
229 };
230 
231 // Simulates a TCP connection, this roughly implements the Reno algorithm. In
232 // difference from TCP this only support sending messages with a fixed length,
233 // no streaming. This is useful to simulate signaling and cross traffic using
234 // message based protocols such as HTTP. It differs from UDP messages in that
235 // they are guranteed to be delivered eventually, even on lossy networks.
236 class TcpMessageRoute {
237  public:
238   // Sends a TCP message of the given |size| over the route, |on_received| is
239   // called when the message has been delivered. Note that the connection
240   // parameters are reset iff there's no currently pending message on the route.
241   virtual void SendMessage(size_t size, std::function<void()> on_received) = 0;
242 
243  protected:
244   ~TcpMessageRoute() = default;
245 };
246 }  // namespace webrtc
247 
248 #endif  // API_TEST_NETWORK_EMULATION_NETWORK_EMULATION_INTERFACES_H_
249