blob: 85dd39cfe8ae6ff10e74e2650da3d38c9b9d2045 [file] [log] [blame]
Artem Titov7bf8c7f2019-03-15 15:00:37 +01001/*
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
Artem Titov3e0b65d2020-07-23 02:19:02 +020014#include <functional>
Artem Titov7bf8c7f2019-03-15 15:00:37 +010015#include <memory>
Jonas Oreland97050112020-11-17 21:30:33 +010016#include <string>
Artem Titov7bf8c7f2019-03-15 15:00:37 +010017#include <vector>
18
Artem Titovcf781282020-07-28 13:45:16 +020019#include "api/array_view.h"
Niels Möller5e7a3ae2021-09-09 15:54:42 +020020#include "api/packet_socket_factory.h"
Andrey Logvinf9ee0e02021-01-14 09:50:32 +000021#include "api/test/network_emulation/cross_traffic.h"
Sebastian Janssoncec24332019-12-04 14:26:50 +010022#include "api/test/network_emulation/network_emulation_interfaces.h"
Niels Möllerf47a7242021-11-22 16:07:35 +010023#include "api/test/peer_network_dependencies.h"
Artem Titov7bf8c7f2019-03-15 15:00:37 +010024#include "api/test/simulated_network.h"
Sebastian Jansson6ce033a2020-01-22 10:12:56 +010025#include "api/test/time_controller.h"
Artem Titov806299e2019-04-12 12:17:19 +020026#include "api/units/timestamp.h"
Artem Titov7bf8c7f2019-03-15 15:00:37 +010027#include "rtc_base/network.h"
Artem Titov1e023392020-01-23 15:46:45 +010028#include "rtc_base/network_constants.h"
Artem Titov7bf8c7f2019-03-15 15:00:37 +010029#include "rtc_base/thread.h"
30
31namespace webrtc {
32
33// This API is still in development and can be changed without prior notice.
34
35// These classes are forward declared here, because they used as handles, to
36// make it possible for client code to operate with these abstractions and build
37// required network configuration. With forward declaration here implementation
38// is more readable, than with interfaces approach and cause user needn't any
39// API methods on these abstractions it is acceptable here.
40
41// EmulatedNetworkNode is an abstraction for some network in the real world,
42// like 3G network between peers, or Wi-Fi for one peer and LTE for another.
43// Multiple networks can be joined into chain emulating a network path from
44// one peer to another.
45class EmulatedNetworkNode;
Sebastian Janssoncec24332019-12-04 14:26:50 +010046
Artem Titov7bf8c7f2019-03-15 15:00:37 +010047// EmulatedRoute is handle for single route from one network interface on one
48// peer device to another network interface on another peer device.
49class EmulatedRoute;
50
51struct EmulatedEndpointConfig {
52 enum class IpAddressFamily { kIpv4, kIpv6 };
Artem Titovcbe6e8a2020-09-22 15:45:00 +020053 enum class StatsGatheringMode {
54 // Gather main network stats counters.
55 kDefault,
56 // kDefault + also gather per packet statistics. In this mode more memory
57 // will be used.
58 kDebug
59 };
Artem Titov7bf8c7f2019-03-15 15:00:37 +010060
Artem Titovd2dd7322021-01-21 17:28:17 +010061 // If specified will be used to name endpoint for logging purposes.
62 absl::optional<std::string> name = absl::nullopt;
Artem Titov7bf8c7f2019-03-15 15:00:37 +010063 IpAddressFamily generated_ip_family = IpAddressFamily::kIpv4;
64 // If specified will be used as IP address for endpoint node. Must be unique
65 // among all created nodes.
66 absl::optional<rtc::IPAddress> ip;
Artem Titove5cc85b2019-03-28 12:11:09 +010067 // Should endpoint be enabled or not, when it will be created.
68 // Enabled endpoints will be available for webrtc to send packets.
69 bool start_as_enabled = true;
Artem Titov1e023392020-01-23 15:46:45 +010070 // Network type which will be used to represent endpoint to WebRTC.
71 rtc::AdapterType type = rtc::AdapterType::ADAPTER_TYPE_UNKNOWN;
Artem Titovcbe6e8a2020-09-22 15:45:00 +020072 StatsGatheringMode stats_gathering_mode = StatsGatheringMode::kDefault;
Artem Titov3d37e062021-02-19 20:26:32 +010073 // Allow endpoint to send packets specifying source IP address different to
74 // the current endpoint IP address. If false endpoint will crash if attempt
75 // to send such packet will be done.
76 bool allow_send_packet_with_different_source_ip = false;
77 // Allow endpoint to receive packet with destination IP address different to
78 // the current endpoint IP address. If false endpoint will crash if such
79 // packet will arrive.
80 bool allow_receive_packets_with_different_dest_ip = false;
Artem Titove5cc85b2019-03-28 12:11:09 +010081};
82
Jonas Oreland97050112020-11-17 21:30:33 +010083struct EmulatedTURNServerConfig {
84 EmulatedEndpointConfig client_config;
85 EmulatedEndpointConfig peer_config;
86};
87
88// EmulatedTURNServer is an abstraction for a TURN server.
89class EmulatedTURNServerInterface {
90 public:
91 struct IceServerConfig {
92 std::string username;
93 std::string password;
94 std::string url;
95 };
96
97 virtual ~EmulatedTURNServerInterface() {}
98
99 // Get an IceServer configuration suitable to add to a PeerConnection.
100 virtual IceServerConfig GetIceServerConfig() const = 0;
101
102 // Get non-null client endpoint, an endpoint that accepts TURN allocations.
103 // This shall typically be connected to one or more webrtc endpoint.
104 virtual EmulatedEndpoint* GetClientEndpoint() const = 0;
105
106 // Returns socket address, which client should use to connect to TURN server
107 // and do TURN allocation.
108 virtual rtc::SocketAddress GetClientEndpointAddress() const = 0;
109
110 // Get non-null peer endpoint, that is "connected to the internet".
111 // This shall typically be connected to another TURN server.
112 virtual EmulatedEndpoint* GetPeerEndpoint() const = 0;
113};
Artem Titov806299e2019-04-12 12:17:19 +0200114
Artem Titove5cc85b2019-03-28 12:11:09 +0100115// Provide interface to obtain all required objects to inject network emulation
Artem Titov806299e2019-04-12 12:17:19 +0200116// layer into PeerConnection. Also contains information about network interfaces
117// accessible by PeerConnection.
Artem Titove5cc85b2019-03-28 12:11:09 +0100118class EmulatedNetworkManagerInterface {
119 public:
120 virtual ~EmulatedNetworkManagerInterface() = default;
121
Artem Titovcf781282020-07-28 13:45:16 +0200122 // Returns non-null pointer to thread that have to be used as network thread
123 // for WebRTC to properly setup network emulation. Returned thread is owned
124 // by EmulatedNetworkManagerInterface implementation.
Artem Titove5cc85b2019-03-28 12:11:09 +0100125 virtual rtc::Thread* network_thread() = 0;
Artem Titovcf781282020-07-28 13:45:16 +0200126 // Returns non-null pointer to network manager that have to be injected into
127 // WebRTC to properly setup network emulation. Returned manager is owned by
128 // EmulatedNetworkManagerInterface implementation.
Artem Titove5cc85b2019-03-28 12:11:09 +0100129 virtual rtc::NetworkManager* network_manager() = 0;
Niels Möller5e7a3ae2021-09-09 15:54:42 +0200130 // Returns non-null pointer to packet socket factory that have to be injected
131 // into WebRTC to properly setup network emulation. Returned factory is owned
132 // by EmulatedNetworkManagerInterface implementation.
133 virtual rtc::PacketSocketFactory* packet_socket_factory() = 0;
Niels Möllerf47a7242021-11-22 16:07:35 +0100134 webrtc::webrtc_pc_e2e::PeerNetworkDependencies network_dependencies() {
135 return {network_thread(), network_manager(), packet_socket_factory()};
136 }
Artem Titovcf781282020-07-28 13:45:16 +0200137 // Returns list of endpoints that are associated with this instance. Pointers
138 // are guaranteed to be non-null and are owned by NetworkEmulationManager.
139 virtual std::vector<EmulatedEndpoint*> endpoints() const = 0;
Artem Titov806299e2019-04-12 12:17:19 +0200140
Artem Titovcf781282020-07-28 13:45:16 +0200141 // Passes summarized network stats for endpoints for this manager into
Artem Titov0e61fdd2021-07-25 21:50:14 +0200142 // specified `stats_callback`. Callback will be executed on network emulation
Artem Titov5501cef2020-08-04 11:49:19 +0200143 // internal task queue.
Artem Titov806299e2019-04-12 12:17:19 +0200144 virtual void GetStats(
Artem Titov3e0b65d2020-07-23 02:19:02 +0200145 std::function<void(std::unique_ptr<EmulatedNetworkStats>)> stats_callback)
146 const = 0;
Artem Titov7bf8c7f2019-03-15 15:00:37 +0100147};
148
Sebastian Jansson6ce033a2020-01-22 10:12:56 +0100149enum class TimeMode { kRealTime, kSimulated };
150
Björn Tereliusb22cabc2022-06-02 10:51:59 +0200151// Called implicitly when parsing an ABSL_FLAG of type TimeMode.
152// from the command line flag value `text`.
153// Returns `true` and sets `*mode` on success;
154// returns `false` and sets `*error` on failure.
155bool AbslParseFlag(absl::string_view text, TimeMode* mode, std::string* error);
156
157// AbslUnparseFlag returns a textual flag value corresponding to the TimeMode
158// `mode`.
159std::string AbslUnparseFlag(TimeMode mode);
160
Artem Titov7bf8c7f2019-03-15 15:00:37 +0100161// Provides an API for creating and configuring emulated network layer.
162// All objects returned by this API are owned by NetworkEmulationManager itself
163// and will be deleted when manager will be deleted.
164class NetworkEmulationManager {
165 public:
Sebastian Janssoncec24332019-12-04 14:26:50 +0100166 // Helper struct to simplify creation of simulated network behaviors. Contains
167 // non-owning pointers as the underlying instances are owned by the manager.
168 struct SimulatedNetworkNode {
169 SimulatedNetworkInterface* simulation;
170 EmulatedNetworkNode* node;
171
172 class Builder {
173 public:
174 explicit Builder(NetworkEmulationManager* net) : net_(net) {}
Sebastian Janssonce911262019-12-11 19:08:40 +0100175 Builder() : net_(nullptr) {}
Sebastian Janssoncec24332019-12-04 14:26:50 +0100176 Builder(const Builder&) = default;
177 // Sets the config state, note that this will replace any previously set
178 // values.
179 Builder& config(BuiltInNetworkBehaviorConfig config);
180 Builder& delay_ms(int queue_delay_ms);
181 Builder& capacity_kbps(int link_capacity_kbps);
182 Builder& capacity_Mbps(int link_capacity_Mbps);
183 Builder& loss(double loss_rate);
Sebastian Jansson39272982019-12-11 19:29:57 +0100184 Builder& packet_queue_length(int max_queue_length_in_packets);
Artem Titovec9b2812021-01-07 15:49:31 +0100185 SimulatedNetworkNode Build(uint64_t random_seed = 1) const;
186 SimulatedNetworkNode Build(NetworkEmulationManager* net,
187 uint64_t random_seed = 1) const;
Sebastian Janssoncec24332019-12-04 14:26:50 +0100188
189 private:
190 NetworkEmulationManager* const net_;
191 BuiltInNetworkBehaviorConfig config_;
192 };
193 };
Artem Titov7bf8c7f2019-03-15 15:00:37 +0100194 virtual ~NetworkEmulationManager() = default;
195
Sebastian Jansson6ce033a2020-01-22 10:12:56 +0100196 virtual TimeController* time_controller() = 0;
Artem Titovcc8a1f82021-01-26 13:58:23 +0100197 // Returns a mode in which underlying time controller operates.
198 virtual TimeMode time_mode() const = 0;
Sebastian Jansson6ce033a2020-01-22 10:12:56 +0100199
Artem Titov1031a4f2022-07-21 16:04:45 +0200200 // Creates an emulated network node, which represents ideal network with
201 // unlimited capacity, no delay and no packet loss.
202 EmulatedNetworkNode* CreateUnconstrainedEmulatedNode() {
203 return CreateEmulatedNode(BuiltInNetworkBehaviorConfig());
204 }
Artem Titov7bf8c7f2019-03-15 15:00:37 +0100205 // Creates an emulated network node, which represents single network in
Artem Titovec9b2812021-01-07 15:49:31 +0100206 // the emulated network layer. Uses default implementation on network behavior
Artem Titov0e61fdd2021-07-25 21:50:14 +0200207 // which can be configured with `config`. `random_seed` can be provided to
Artem Titovec9b2812021-01-07 15:49:31 +0100208 // alter randomization behavior.
Artem Titov7bf8c7f2019-03-15 15:00:37 +0100209 virtual EmulatedNetworkNode* CreateEmulatedNode(
Artem Titovec9b2812021-01-07 15:49:31 +0100210 BuiltInNetworkBehaviorConfig config,
211 uint64_t random_seed = 1) = 0;
212 // Creates an emulated network node, which represents single network in
Artem Titov0e61fdd2021-07-25 21:50:14 +0200213 // the emulated network layer. `network_behavior` determines how created node
Artem Titovec9b2812021-01-07 15:49:31 +0100214 // will forward incoming packets to the next receiver.
Artem Titov48b1b182019-07-05 13:09:48 +0200215 virtual EmulatedNetworkNode* CreateEmulatedNode(
Artem Titov7bf8c7f2019-03-15 15:00:37 +0100216 std::unique_ptr<NetworkBehaviorInterface> network_behavior) = 0;
217
Sebastian Janssoncec24332019-12-04 14:26:50 +0100218 virtual SimulatedNetworkNode::Builder NodeBuilder() = 0;
219
Artem Titov7bf8c7f2019-03-15 15:00:37 +0100220 // Creates an emulated endpoint, which represents single network interface on
221 // the peer's device.
222 virtual EmulatedEndpoint* CreateEndpoint(EmulatedEndpointConfig config) = 0;
Artem Titove5cc85b2019-03-28 12:11:09 +0100223 // Enable emulated endpoint to make it available for webrtc.
224 // Caller mustn't enable currently enabled endpoint.
225 virtual void EnableEndpoint(EmulatedEndpoint* endpoint) = 0;
226 // Disable emulated endpoint to make it unavailable for webrtc.
227 // Caller mustn't disable currently disabled endpoint.
228 virtual void DisableEndpoint(EmulatedEndpoint* endpoint) = 0;
Artem Titov7bf8c7f2019-03-15 15:00:37 +0100229
230 // Creates a route between endpoints going through specified network nodes.
231 // This route is single direction only and describe how traffic that was
Artem Titov0e61fdd2021-07-25 21:50:14 +0200232 // sent by network interface `from` have to be delivered to the network
233 // interface `to`. Return object can be used to remove created route. The
Artem Titovff393122019-04-05 11:19:52 +0200234 // route must contains at least one network node inside it.
Artem Titov7bf8c7f2019-03-15 15:00:37 +0100235 //
Artem Titovff393122019-04-05 11:19:52 +0200236 // Assume that E{0-9} are endpoints and N{0-9} are network nodes, then
237 // creation of the route have to follow these rules:
238 // 1. A route consists of a source endpoint, an ordered list of one or
239 // more network nodes, and a destination endpoint.
240 // 2. If (E1, ..., E2) is a route, then E1 != E2.
241 // In other words, the source and the destination may not be the same.
242 // 3. Given two simultaneously existing routes (E1, ..., E2) and
243 // (E3, ..., E4), either E1 != E3 or E2 != E4.
244 // In other words, there may be at most one route from any given source
245 // endpoint to any given destination endpoint.
246 // 4. Given two simultaneously existing routes (E1, ..., N1, ..., E2)
247 // and (E3, ..., N2, ..., E4), either N1 != N2 or E2 != E4.
248 // In other words, a network node may not belong to two routes that lead
249 // to the same destination endpoint.
Artem Titov7bf8c7f2019-03-15 15:00:37 +0100250 virtual EmulatedRoute* CreateRoute(
251 EmulatedEndpoint* from,
252 const std::vector<EmulatedNetworkNode*>& via_nodes,
253 EmulatedEndpoint* to) = 0;
Sebastian Janssoncec24332019-12-04 14:26:50 +0100254
Artem Titov0e61fdd2021-07-25 21:50:14 +0200255 // Creates a route over the given `via_nodes` creating the required endpoints
Sebastian Janssoncec24332019-12-04 14:26:50 +0100256 // in the process. The returned EmulatedRoute pointer can be used in other
257 // calls as a transport route for message or cross traffic.
258 virtual EmulatedRoute* CreateRoute(
259 const std::vector<EmulatedNetworkNode*>& via_nodes) = 0;
260
Artem Titov3d37e062021-02-19 20:26:32 +0100261 // Creates a default route between endpoints going through specified network
262 // nodes. Default route is used for packet when there is no known route for
263 // packet's destination IP.
264 //
265 // This route is single direction only and describe how traffic that was
Artem Titov0e61fdd2021-07-25 21:50:14 +0200266 // sent by network interface `from` have to be delivered in case if routing
Artem Titov3d37e062021-02-19 20:26:32 +0100267 // was unspecified. Return object can be used to remove created route. The
268 // route must contains at least one network node inside it.
269 //
270 // Assume that E{0-9} are endpoints and N{0-9} are network nodes, then
271 // creation of the route have to follow these rules:
272 // 1. A route consists of a source endpoint, an ordered list of one or
273 // more network nodes, and a destination endpoint.
274 // 2. If (E1, ..., E2) is a route, then E1 != E2.
275 // In other words, the source and the destination may not be the same.
276 // 3. Given two simultaneously existing routes (E1, ..., E2) and
277 // (E3, ..., E4), either E1 != E3 or E2 != E4.
278 // In other words, there may be at most one route from any given source
279 // endpoint to any given destination endpoint.
280 // 4. Given two simultaneously existing routes (E1, ..., N1, ..., E2)
281 // and (E3, ..., N2, ..., E4), either N1 != N2 or E2 != E4.
282 // In other words, a network node may not belong to two routes that lead
283 // to the same destination endpoint.
284 // 5. Any node N can belong to only one default route.
285 virtual EmulatedRoute* CreateDefaultRoute(
286 EmulatedEndpoint* from,
287 const std::vector<EmulatedNetworkNode*>& via_nodes,
288 EmulatedEndpoint* to) = 0;
289
Artem Titov7bf8c7f2019-03-15 15:00:37 +0100290 // Removes route previously created by CreateRoute(...).
291 // Caller mustn't call this function with route, that have been already
Andrey Logvinf9ee0e02021-01-14 09:50:32 +0000292 // removed earlier. Removing a route that is currently in use will lead to
293 // packets being dropped.
Artem Titov7bf8c7f2019-03-15 15:00:37 +0100294 virtual void ClearRoute(EmulatedRoute* route) = 0;
295
Artem Titov0e61fdd2021-07-25 21:50:14 +0200296 // Creates a simulated TCP connection using `send_route` for traffic and
297 // `ret_route` for feedback. This can be used to emulate HTTP cross traffic
Sebastian Janssoncec24332019-12-04 14:26:50 +0100298 // and to implement realistic reliable signaling over lossy networks.
299 // TODO(srte): Handle clearing of the routes involved.
300 virtual TcpMessageRoute* CreateTcpRoute(EmulatedRoute* send_route,
301 EmulatedRoute* ret_route) = 0;
302
Artem Titov0e61fdd2021-07-25 21:50:14 +0200303 // Creates a route over the given `via_nodes`. Returns an object that can be
Andrey Logvinf9ee0e02021-01-14 09:50:32 +0000304 // used to emulate network load with cross traffic over the created route.
305 virtual CrossTrafficRoute* CreateCrossTrafficRoute(
306 const std::vector<EmulatedNetworkNode*>& via_nodes) = 0;
307
Artem Titov0e61fdd2021-07-25 21:50:14 +0200308 // Starts generating cross traffic using given `generator`. Takes ownership
Andrey Logvinf9ee0e02021-01-14 09:50:32 +0000309 // over the generator.
310 virtual CrossTrafficGenerator* StartCrossTraffic(
311 std::unique_ptr<CrossTrafficGenerator> generator) = 0;
312
Artem Titov0e61fdd2021-07-25 21:50:14 +0200313 // Stops generating cross traffic that was started using given `generator`.
314 // The `generator` shouldn't be used after and the reference may be invalid.
Andrey Logvinf9ee0e02021-01-14 09:50:32 +0000315 virtual void StopCrossTraffic(CrossTrafficGenerator* generator) = 0;
316
Artem Titove5cc85b2019-03-28 12:11:09 +0100317 // Creates EmulatedNetworkManagerInterface which can be used then to inject
Artem Titov0e61fdd2021-07-25 21:50:14 +0200318 // network emulation layer into PeerConnection. `endpoints` - are available
Artem Titove5cc85b2019-03-28 12:11:09 +0100319 // network interfaces for PeerConnection. If endpoint is enabled, it will be
320 // immediately available for PeerConnection, otherwise user will be able to
321 // enable endpoint later to make it available for PeerConnection.
322 virtual EmulatedNetworkManagerInterface*
323 CreateEmulatedNetworkManagerInterface(
Artem Titov7bf8c7f2019-03-15 15:00:37 +0100324 const std::vector<EmulatedEndpoint*>& endpoints) = 0;
Artem Titovcf781282020-07-28 13:45:16 +0200325
Artem Titov0e61fdd2021-07-25 21:50:14 +0200326 // Passes summarized network stats for specified `endpoints` into specified
327 // `stats_callback`. Callback will be executed on network emulation
Artem Titov5501cef2020-08-04 11:49:19 +0200328 // internal task queue.
Artem Titovcf781282020-07-28 13:45:16 +0200329 virtual void GetStats(
Per Kjellander410c9982021-02-15 11:24:37 +0100330 rtc::ArrayView<EmulatedEndpoint* const> endpoints,
Artem Titovcf781282020-07-28 13:45:16 +0200331 std::function<void(std::unique_ptr<EmulatedNetworkStats>)>
332 stats_callback) = 0;
Jonas Oreland97050112020-11-17 21:30:33 +0100333
334 // Create a EmulatedTURNServer.
335 // The TURN server has 2 endpoints that need to be connected with routes,
336 // - GetClientEndpoint() - the endpoint that accepts TURN allocations.
337 // - GetPeerEndpoint() - the endpoint that is "connected to the internet".
338 virtual EmulatedTURNServerInterface* CreateTURNServer(
339 EmulatedTURNServerConfig config) = 0;
Artem Titov7bf8c7f2019-03-15 15:00:37 +0100340};
341
342} // namespace webrtc
343
344#endif // API_TEST_NETWORK_EMULATION_MANAGER_H_