• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
11 #ifndef API_TEST_NETWORK_EMULATION_MANAGER_H_
12 #define API_TEST_NETWORK_EMULATION_MANAGER_H_
13 
14 #include <functional>
15 #include <memory>
16 #include <string>
17 #include <utility>
18 #include <vector>
19 
20 #include "api/array_view.h"
21 #include "api/packet_socket_factory.h"
22 #include "api/test/network_emulation/cross_traffic.h"
23 #include "api/test/network_emulation/network_emulation_interfaces.h"
24 #include "api/test/peer_network_dependencies.h"
25 #include "api/test/simulated_network.h"
26 #include "api/test/time_controller.h"
27 #include "api/units/timestamp.h"
28 #include "rtc_base/network.h"
29 #include "rtc_base/network_constants.h"
30 #include "rtc_base/thread.h"
31 
32 namespace webrtc {
33 
34 // This API is still in development and can be changed without prior notice.
35 
36 // These classes are forward declared here, because they used as handles, to
37 // make it possible for client code to operate with these abstractions and build
38 // required network configuration. With forward declaration here implementation
39 // is more readable, than with interfaces approach and cause user needn't any
40 // API methods on these abstractions it is acceptable here.
41 
42 // EmulatedNetworkNode is an abstraction for some network in the real world,
43 // like 3G network between peers, or Wi-Fi for one peer and LTE for another.
44 // Multiple networks can be joined into chain emulating a network path from
45 // one peer to another.
46 class EmulatedNetworkNode;
47 
48 // EmulatedRoute is handle for single route from one network interface on one
49 // peer device to another network interface on another peer device.
50 class EmulatedRoute;
51 
52 enum class EmulatedNetworkStatsGatheringMode {
53   // Gather main network stats counters. See more details on which particular
54   // metrics are collected in the `EmulatedNetworkStats` and
55   // `EmulatedNetworkNodeStats` documentation.
56   kDefault,
57   // kDefault + also gather per packet statistics. In this mode more memory
58   // will be used.
59   kDebug
60 };
61 
62 struct EmulatedEndpointConfig {
63   enum class IpAddressFamily { kIpv4, kIpv6 };
64 
65   // If specified will be used to name endpoint for logging purposes.
66   absl::optional<std::string> name = absl::nullopt;
67   IpAddressFamily generated_ip_family = IpAddressFamily::kIpv4;
68   // If specified will be used as IP address for endpoint node. Must be unique
69   // among all created nodes.
70   absl::optional<rtc::IPAddress> ip;
71   // Should endpoint be enabled or not, when it will be created.
72   // Enabled endpoints will be available for webrtc to send packets.
73   bool start_as_enabled = true;
74   // Network type which will be used to represent endpoint to WebRTC.
75   rtc::AdapterType type = rtc::AdapterType::ADAPTER_TYPE_UNKNOWN;
76   // Allow endpoint to send packets specifying source IP address different to
77   // the current endpoint IP address. If false endpoint will crash if attempt
78   // to send such packet will be done.
79   bool allow_send_packet_with_different_source_ip = false;
80   // Allow endpoint to receive packet with destination IP address different to
81   // the current endpoint IP address. If false endpoint will crash if such
82   // packet will arrive.
83   bool allow_receive_packets_with_different_dest_ip = false;
84 };
85 
86 struct EmulatedTURNServerConfig {
87   EmulatedEndpointConfig client_config;
88   EmulatedEndpointConfig peer_config;
89 };
90 
91 // EmulatedTURNServer is an abstraction for a TURN server.
92 class EmulatedTURNServerInterface {
93  public:
94   struct IceServerConfig {
95     std::string username;
96     std::string password;
97     std::string url;
98   };
99 
~EmulatedTURNServerInterface()100   virtual ~EmulatedTURNServerInterface() {}
101 
102   // Get an IceServer configuration suitable to add to a PeerConnection.
103   virtual IceServerConfig GetIceServerConfig() const = 0;
104 
105   // Get non-null client endpoint, an endpoint that accepts TURN allocations.
106   // This shall typically be connected to one or more webrtc endpoint.
107   virtual EmulatedEndpoint* GetClientEndpoint() const = 0;
108 
109   // Returns socket address, which client should use to connect to TURN server
110   // and do TURN allocation.
111   virtual rtc::SocketAddress GetClientEndpointAddress() const = 0;
112 
113   // Get non-null peer endpoint, that is "connected to the internet".
114   // This shall typically be connected to another TURN server.
115   virtual EmulatedEndpoint* GetPeerEndpoint() const = 0;
116 };
117 
118 // Provide interface to obtain all required objects to inject network emulation
119 // layer into PeerConnection. Also contains information about network interfaces
120 // accessible by PeerConnection.
121 class EmulatedNetworkManagerInterface {
122  public:
123   virtual ~EmulatedNetworkManagerInterface() = default;
124 
125   // Returns non-null pointer to thread that have to be used as network thread
126   // for WebRTC to properly setup network emulation. Returned thread is owned
127   // by EmulatedNetworkManagerInterface implementation.
128   virtual rtc::Thread* network_thread() = 0;
129   // Returns non-null pointer to network manager that have to be injected into
130   // WebRTC to properly setup network emulation. Returned manager is owned by
131   // EmulatedNetworkManagerInterface implementation.
132   virtual rtc::NetworkManager* network_manager() = 0;
133   // Returns non-null pointer to packet socket factory that have to be injected
134   // into WebRTC to properly setup network emulation. Returned factory is owned
135   // by EmulatedNetworkManagerInterface implementation.
136   virtual rtc::PacketSocketFactory* packet_socket_factory() = 0;
network_dependencies()137   webrtc::webrtc_pc_e2e::PeerNetworkDependencies network_dependencies() {
138     return {network_thread(), network_manager(), packet_socket_factory()};
139   }
140   // Returns list of endpoints that are associated with this instance. Pointers
141   // are guaranteed to be non-null and are owned by NetworkEmulationManager.
142   virtual std::vector<EmulatedEndpoint*> endpoints() const = 0;
143 
144   // Passes summarized network stats for endpoints for this manager into
145   // specified `stats_callback`. Callback will be executed on network emulation
146   // internal task queue.
147   virtual void GetStats(
148       std::function<void(EmulatedNetworkStats)> stats_callback) const = 0;
149 };
150 
151 enum class TimeMode { kRealTime, kSimulated };
152 
153 // Called implicitly when parsing an ABSL_FLAG of type TimeMode.
154 // from the command line flag value `text`.
155 // Returns `true` and sets `*mode` on success;
156 // returns `false` and sets `*error` on failure.
157 bool AbslParseFlag(absl::string_view text, TimeMode* mode, std::string* error);
158 
159 // AbslUnparseFlag returns a textual flag value corresponding to the TimeMode
160 // `mode`.
161 std::string AbslUnparseFlag(TimeMode mode);
162 
163 // Provides an API for creating and configuring emulated network layer.
164 // All objects returned by this API are owned by NetworkEmulationManager itself
165 // and will be deleted when manager will be deleted.
166 class NetworkEmulationManager {
167  public:
168   // Helper struct to simplify creation of simulated network behaviors. Contains
169   // non-owning pointers as the underlying instances are owned by the manager.
170   struct SimulatedNetworkNode {
171     SimulatedNetworkInterface* simulation;
172     EmulatedNetworkNode* node;
173 
174     class Builder {
175      public:
BuilderSimulatedNetworkNode176       explicit Builder(NetworkEmulationManager* net) : net_(net) {}
BuilderSimulatedNetworkNode177       Builder() : net_(nullptr) {}
178       Builder(const Builder&) = default;
179       // Sets the config state, note that this will replace any previously set
180       // values.
181       Builder& config(BuiltInNetworkBehaviorConfig config);
182       Builder& delay_ms(int queue_delay_ms);
183       Builder& capacity_kbps(int link_capacity_kbps);
184       Builder& capacity_Mbps(int link_capacity_Mbps);
185       Builder& loss(double loss_rate);
186       Builder& packet_queue_length(int max_queue_length_in_packets);
187       SimulatedNetworkNode Build(uint64_t random_seed = 1) const;
188       SimulatedNetworkNode Build(NetworkEmulationManager* net,
189                                  uint64_t random_seed = 1) const;
190 
191      private:
192       NetworkEmulationManager* const net_;
193       BuiltInNetworkBehaviorConfig config_;
194     };
195   };
196   virtual ~NetworkEmulationManager() = default;
197 
198   virtual TimeController* time_controller() = 0;
199   // Returns a mode in which underlying time controller operates.
200   virtual TimeMode time_mode() const = 0;
201 
202   // Creates an emulated network node, which represents ideal network with
203   // unlimited capacity, no delay and no packet loss.
CreateUnconstrainedEmulatedNode()204   EmulatedNetworkNode* CreateUnconstrainedEmulatedNode() {
205     return CreateEmulatedNode(BuiltInNetworkBehaviorConfig());
206   }
207   // Creates an emulated network node, which represents single network in
208   // the emulated network layer. Uses default implementation on network behavior
209   // which can be configured with `config`. `random_seed` can be provided to
210   // alter randomization behavior.
211   virtual EmulatedNetworkNode* CreateEmulatedNode(
212       BuiltInNetworkBehaviorConfig config,
213       uint64_t random_seed = 1) = 0;
214   // Creates an emulated network node, which represents single network in
215   // the emulated network layer. `network_behavior` determines how created node
216   // will forward incoming packets to the next receiver.
217   virtual EmulatedNetworkNode* CreateEmulatedNode(
218       std::unique_ptr<NetworkBehaviorInterface> network_behavior) = 0;
219 
220   virtual SimulatedNetworkNode::Builder NodeBuilder() = 0;
221 
222   // Creates an emulated endpoint, which represents single network interface on
223   // the peer's device.
224   virtual EmulatedEndpoint* CreateEndpoint(EmulatedEndpointConfig config) = 0;
225   // Enable emulated endpoint to make it available for webrtc.
226   // Caller mustn't enable currently enabled endpoint.
227   virtual void EnableEndpoint(EmulatedEndpoint* endpoint) = 0;
228   // Disable emulated endpoint to make it unavailable for webrtc.
229   // Caller mustn't disable currently disabled endpoint.
230   virtual void DisableEndpoint(EmulatedEndpoint* endpoint) = 0;
231 
232   // Creates a route between endpoints going through specified network nodes.
233   // This route is single direction only and describe how traffic that was
234   // sent by network interface `from` have to be delivered to the network
235   // interface `to`. Return object can be used to remove created route. The
236   // route must contains at least one network node inside it.
237   //
238   // Assume that E{0-9} are endpoints and N{0-9} are network nodes, then
239   // creation of the route have to follow these rules:
240   //   1. A route consists of a source endpoint, an ordered list of one or
241   //      more network nodes, and a destination endpoint.
242   //   2. If (E1, ..., E2) is a route, then E1 != E2.
243   //      In other words, the source and the destination may not be the same.
244   //   3. Given two simultaneously existing routes (E1, ..., E2) and
245   //      (E3, ..., E4), either E1 != E3 or E2 != E4.
246   //      In other words, there may be at most one route from any given source
247   //      endpoint to any given destination endpoint.
248   //   4. Given two simultaneously existing routes (E1, ..., N1, ..., E2)
249   //      and (E3, ..., N2, ..., E4), either N1 != N2 or E2 != E4.
250   //      In other words, a network node may not belong to two routes that lead
251   //      to the same destination endpoint.
252   virtual EmulatedRoute* CreateRoute(
253       EmulatedEndpoint* from,
254       const std::vector<EmulatedNetworkNode*>& via_nodes,
255       EmulatedEndpoint* to) = 0;
256 
257   // Creates a route over the given `via_nodes` creating the required endpoints
258   // in the process. The returned EmulatedRoute pointer can be used in other
259   // calls as a transport route for message or cross traffic.
260   virtual EmulatedRoute* CreateRoute(
261       const std::vector<EmulatedNetworkNode*>& via_nodes) = 0;
262 
263   // Creates a default route between endpoints going through specified network
264   // nodes. Default route is used for packet when there is no known route for
265   // packet's destination IP.
266   //
267   // This route is single direction only and describe how traffic that was
268   // sent by network interface `from` have to be delivered in case if routing
269   // was unspecified. Return object can be used to remove created route. The
270   // route must contains at least one network node inside it.
271   //
272   // Assume that E{0-9} are endpoints and N{0-9} are network nodes, then
273   // creation of the route have to follow these rules:
274   //   1. A route consists of a source endpoint, an ordered list of one or
275   //      more network nodes, and a destination endpoint.
276   //   2. If (E1, ..., E2) is a route, then E1 != E2.
277   //      In other words, the source and the destination may not be the same.
278   //   3. Given two simultaneously existing routes (E1, ..., E2) and
279   //      (E3, ..., E4), either E1 != E3 or E2 != E4.
280   //      In other words, there may be at most one route from any given source
281   //      endpoint to any given destination endpoint.
282   //   4. Given two simultaneously existing routes (E1, ..., N1, ..., E2)
283   //      and (E3, ..., N2, ..., E4), either N1 != N2 or E2 != E4.
284   //      In other words, a network node may not belong to two routes that lead
285   //      to the same destination endpoint.
286   //   5. Any node N can belong to only one default route.
287   virtual EmulatedRoute* CreateDefaultRoute(
288       EmulatedEndpoint* from,
289       const std::vector<EmulatedNetworkNode*>& via_nodes,
290       EmulatedEndpoint* to) = 0;
291 
292   // Removes route previously created by CreateRoute(...).
293   // Caller mustn't call this function with route, that have been already
294   // removed earlier. Removing a route that is currently in use will lead to
295   // packets being dropped.
296   virtual void ClearRoute(EmulatedRoute* route) = 0;
297 
298   // Creates a simulated TCP connection using `send_route` for traffic and
299   // `ret_route` for feedback. This can be used to emulate HTTP cross traffic
300   // and to implement realistic reliable signaling over lossy networks.
301   // TODO(srte): Handle clearing of the routes involved.
302   virtual TcpMessageRoute* CreateTcpRoute(EmulatedRoute* send_route,
303                                           EmulatedRoute* ret_route) = 0;
304 
305   // Creates a route over the given `via_nodes`. Returns an object that can be
306   // used to emulate network load with cross traffic over the created route.
307   virtual CrossTrafficRoute* CreateCrossTrafficRoute(
308       const std::vector<EmulatedNetworkNode*>& via_nodes) = 0;
309 
310   // Starts generating cross traffic using given `generator`. Takes ownership
311   // over the generator.
312   virtual CrossTrafficGenerator* StartCrossTraffic(
313       std::unique_ptr<CrossTrafficGenerator> generator) = 0;
314 
315   // Stops generating cross traffic that was started using given `generator`.
316   // The `generator` shouldn't be used after and the reference may be invalid.
317   virtual void StopCrossTraffic(CrossTrafficGenerator* generator) = 0;
318 
319   // Creates EmulatedNetworkManagerInterface which can be used then to inject
320   // network emulation layer into PeerConnection. `endpoints` - are available
321   // network interfaces for PeerConnection. If endpoint is enabled, it will be
322   // immediately available for PeerConnection, otherwise user will be able to
323   // enable endpoint later to make it available for PeerConnection.
324   virtual EmulatedNetworkManagerInterface*
325   CreateEmulatedNetworkManagerInterface(
326       const std::vector<EmulatedEndpoint*>& endpoints) = 0;
327 
328   // Passes combined network stats for all specified `endpoints` into specified
329   // `stats_callback`. Callback will be executed on network emulation
330   // internal task queue.
331   virtual void GetStats(
332       rtc::ArrayView<EmulatedEndpoint* const> endpoints,
333       std::function<void(EmulatedNetworkStats)> stats_callback) = 0;
334 
335   // Passes combined network stats for all specified `nodes` into specified
336   // `stats_callback`. Callback will be executed on network emulation
337   // internal task queue.
338   virtual void GetStats(
339       rtc::ArrayView<EmulatedNetworkNode* const> nodes,
340       std::function<void(EmulatedNetworkNodeStats)> stats_callback) = 0;
341 
342   // Create a EmulatedTURNServer.
343   // The TURN server has 2 endpoints that need to be connected with routes,
344   // - GetClientEndpoint() - the endpoint that accepts TURN allocations.
345   // - GetPeerEndpoint() - the endpoint that is "connected to the internet".
346   virtual EmulatedTURNServerInterface* CreateTURNServer(
347       EmulatedTURNServerConfig config) = 0;
348 
349   // Create a pair of EmulatedNetworkManagerInterfaces connected to each other.
350   std::pair<EmulatedNetworkManagerInterface*, EmulatedNetworkManagerInterface*>
351   CreateEndpointPairWithTwoWayRoutes(
352       const BuiltInNetworkBehaviorConfig& config);
353 };
354 
355 }  // namespace webrtc
356 
357 #endif  // API_TEST_NETWORK_EMULATION_MANAGER_H_
358