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