blob: e825c65339a222847a9cf92c4c08c84339926612 [file] [log] [blame]
Artem Titov40f51152019-01-04 15:45:01 +01001/*
2 * Copyright (c) 2018 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
Artem Titov386802e2019-07-05 10:48:17 +020011#ifndef TEST_NETWORK_NETWORK_EMULATION_H_
12#define TEST_NETWORK_NETWORK_EMULATION_H_
Artem Titov40f51152019-01-04 15:45:01 +010013
14#include <cstdint>
Artem Titov386802e2019-07-05 10:48:17 +020015#include <deque>
Artem Titov37d18482019-01-08 15:41:45 +010016#include <map>
Artem Titov40f51152019-01-04 15:45:01 +010017#include <memory>
18#include <string>
19#include <utility>
20#include <vector>
21
22#include "absl/types/optional.h"
Artem Titov806299e2019-04-12 12:17:19 +020023#include "api/test/network_emulation_manager.h"
Artem Titov37d18482019-01-08 15:41:45 +010024#include "api/test/simulated_network.h"
Artem Titov40f51152019-01-04 15:45:01 +010025#include "api/units/timestamp.h"
Steve Anton10542f22019-01-11 09:11:00 -080026#include "rtc_base/copy_on_write_buffer.h"
Artem Titove5cc85b2019-03-28 12:11:09 +010027#include "rtc_base/network.h"
Steve Anton10542f22019-01-11 09:11:00 -080028#include "rtc_base/socket_address.h"
Sebastian Jansson4124dab2019-04-01 14:33:53 +020029#include "rtc_base/task_queue_for_test.h"
30#include "rtc_base/task_utils/repeating_task.h"
Artem Titove5cc85b2019-03-28 12:11:09 +010031#include "rtc_base/thread_checker.h"
Artem Titov0774bd92019-01-30 15:26:05 +010032#include "system_wrappers/include/clock.h"
Artem Titov40f51152019-01-04 15:45:01 +010033
34namespace webrtc {
Artem Titov7bf8c7f2019-03-15 15:00:37 +010035
Artem Titov40f51152019-01-04 15:45:01 +010036struct EmulatedIpPacket {
37 public:
38 EmulatedIpPacket(const rtc::SocketAddress& from,
39 const rtc::SocketAddress& to,
Artem Titov40f51152019-01-04 15:45:01 +010040 rtc::CopyOnWriteBuffer data,
41 Timestamp arrival_time);
Artem Titov612e1792019-04-01 14:43:38 +020042 ~EmulatedIpPacket() = default;
Artem Titov40f51152019-01-04 15:45:01 +010043 // This object is not copyable or assignable.
44 EmulatedIpPacket(const EmulatedIpPacket&) = delete;
45 EmulatedIpPacket& operator=(const EmulatedIpPacket&) = delete;
46 // This object is only moveable.
Artem Titov612e1792019-04-01 14:43:38 +020047 EmulatedIpPacket(EmulatedIpPacket&&) = default;
48 EmulatedIpPacket& operator=(EmulatedIpPacket&&) = default;
Artem Titov40f51152019-01-04 15:45:01 +010049
50 size_t size() const { return data.size(); }
51 const uint8_t* cdata() const { return data.cdata(); }
52
53 rtc::SocketAddress from;
54 rtc::SocketAddress to;
Artem Titov40f51152019-01-04 15:45:01 +010055 rtc::CopyOnWriteBuffer data;
56 Timestamp arrival_time;
57};
58
59class EmulatedNetworkReceiverInterface {
60 public:
61 virtual ~EmulatedNetworkReceiverInterface() = default;
62
63 virtual void OnPacketReceived(EmulatedIpPacket packet) = 0;
64};
65
Sebastian Jansson62bb47f2019-04-01 18:23:58 +020066class LinkEmulation : public EmulatedNetworkReceiverInterface {
67 public:
68 LinkEmulation(Clock* clock,
69 rtc::TaskQueue* task_queue,
70 std::unique_ptr<NetworkBehaviorInterface> network_behavior,
71 EmulatedNetworkReceiverInterface* receiver)
72 : clock_(clock),
73 task_queue_(task_queue),
74 network_behavior_(std::move(network_behavior)),
75 receiver_(receiver) {}
76 void OnPacketReceived(EmulatedIpPacket packet) override;
77
78 private:
79 struct StoredPacket {
80 uint64_t id;
81 EmulatedIpPacket packet;
82 bool removed;
83 };
84 void Process(Timestamp at_time) RTC_RUN_ON(task_queue_);
Sebastian Jansson62bb47f2019-04-01 18:23:58 +020085
86 Clock* const clock_;
87 rtc::TaskQueue* const task_queue_;
88 const std::unique_ptr<NetworkBehaviorInterface> network_behavior_
89 RTC_GUARDED_BY(task_queue_);
90 EmulatedNetworkReceiverInterface* const receiver_;
91 RepeatingTaskHandle process_task_ RTC_GUARDED_BY(task_queue_);
92 std::deque<StoredPacket> packets_ RTC_GUARDED_BY(task_queue_);
93 uint64_t next_packet_id_ RTC_GUARDED_BY(task_queue_) = 1;
94};
95
96class NetworkRouterNode : public EmulatedNetworkReceiverInterface {
97 public:
98 explicit NetworkRouterNode(rtc::TaskQueue* task_queue);
99
100 void OnPacketReceived(EmulatedIpPacket packet) override;
101 void SetReceiver(rtc::IPAddress dest_ip,
102 EmulatedNetworkReceiverInterface* receiver);
103 void RemoveReceiver(rtc::IPAddress dest_ip);
Sebastian Jansson71c6b562019-08-14 11:31:02 +0200104 void SetWatcher(std::function<void(const EmulatedIpPacket&)> watcher);
Sebastian Jansson62bb47f2019-04-01 18:23:58 +0200105
106 private:
107 rtc::TaskQueue* const task_queue_;
108 std::map<rtc::IPAddress, EmulatedNetworkReceiverInterface*> routing_
109 RTC_GUARDED_BY(task_queue_);
Sebastian Jansson71c6b562019-08-14 11:31:02 +0200110 std::function<void(const EmulatedIpPacket&)> watcher_
111 RTC_GUARDED_BY(task_queue_);
Sebastian Jansson62bb47f2019-04-01 18:23:58 +0200112};
113
Artem Titov37d18482019-01-08 15:41:45 +0100114// Represents node in the emulated network. Nodes can be connected with each
115// other to form different networks with different behavior. The behavior of
116// the node itself is determined by a concrete implementation of
117// NetworkBehaviorInterface that is provided on construction.
118class EmulatedNetworkNode : public EmulatedNetworkReceiverInterface {
119 public:
120 // Creates node based on |network_behavior|. The specified |packet_overhead|
121 // is added to the size of each packet in the information provided to
122 // |network_behavior|.
Sebastian Jansson4124dab2019-04-01 14:33:53 +0200123 // |task_queue| is used to process packets and to forward the packets when
124 // they are ready.
Sebastian Jansson62bb47f2019-04-01 18:23:58 +0200125 EmulatedNetworkNode(
Sebastian Jansson4124dab2019-04-01 14:33:53 +0200126 Clock* clock,
127 rtc::TaskQueue* task_queue,
Sebastian Jansson8c8feb92019-01-29 15:59:17 +0100128 std::unique_ptr<NetworkBehaviorInterface> network_behavior);
Artem Titov37d18482019-01-08 15:41:45 +0100129 ~EmulatedNetworkNode() override;
130 RTC_DISALLOW_COPY_AND_ASSIGN(EmulatedNetworkNode);
131
132 void OnPacketReceived(EmulatedIpPacket packet) override;
Sebastian Jansson62bb47f2019-04-01 18:23:58 +0200133
134 LinkEmulation* link() { return &link_; }
135 NetworkRouterNode* router() { return &router_; }
Artem Titov37d18482019-01-08 15:41:45 +0100136
Artem Titov4cd433e2019-04-01 11:01:16 +0200137 // Creates a route for the given receiver_ip over all the given nodes to the
Artem Titov37d18482019-01-08 15:41:45 +0100138 // given receiver.
Artem Titov4cd433e2019-04-01 11:01:16 +0200139 static void CreateRoute(rtc::IPAddress receiver_ip,
Artem Titov37d18482019-01-08 15:41:45 +0100140 std::vector<EmulatedNetworkNode*> nodes,
141 EmulatedNetworkReceiverInterface* receiver);
Artem Titov4cd433e2019-04-01 11:01:16 +0200142 static void ClearRoute(rtc::IPAddress receiver_ip,
Artem Titov37d18482019-01-08 15:41:45 +0100143 std::vector<EmulatedNetworkNode*> nodes);
144
145 private:
Sebastian Jansson62bb47f2019-04-01 18:23:58 +0200146 NetworkRouterNode router_;
147 LinkEmulation link_;
Artem Titov37d18482019-01-08 15:41:45 +0100148};
149
Artem Titov0774bd92019-01-30 15:26:05 +0100150// Represents single network interface on the device.
151// It will be used as sender from socket side to send data to the network and
152// will act as packet receiver from emulated network side to receive packets
153// from other EmulatedNetworkNodes.
Artem Titovaba8dc22019-03-11 10:08:40 +0100154class EmulatedEndpoint : public EmulatedNetworkReceiverInterface {
Artem Titov0774bd92019-01-30 15:26:05 +0100155 public:
Artem Titove5cc85b2019-03-28 12:11:09 +0100156 EmulatedEndpoint(uint64_t id,
Artem Titov612e1792019-04-01 14:43:38 +0200157 const rtc::IPAddress& ip,
Artem Titove5cc85b2019-03-28 12:11:09 +0100158 bool is_enabled,
Artem Titovff393122019-04-05 11:19:52 +0200159 rtc::TaskQueue* task_queue,
Artem Titove5cc85b2019-03-28 12:11:09 +0100160 Clock* clock);
Artem Titovaba8dc22019-03-11 10:08:40 +0100161 ~EmulatedEndpoint() override;
Artem Titov0774bd92019-01-30 15:26:05 +0100162
163 uint64_t GetId() const;
164
Artem Titovff393122019-04-05 11:19:52 +0200165 NetworkRouterNode* router() { return &router_; }
Artem Titov0774bd92019-01-30 15:26:05 +0100166 // Send packet into network.
167 // |from| will be used to set source address for the packet in destination
168 // socket.
169 // |to| will be used for routing verification and picking right socket by port
170 // on destination endpoint.
171 void SendPacket(const rtc::SocketAddress& from,
172 const rtc::SocketAddress& to,
Sebastian Janssonee5ec9a2019-09-17 20:34:03 +0200173 rtc::CopyOnWriteBuffer packet_data);
Artem Titov0774bd92019-01-30 15:26:05 +0100174
175 // Binds receiver to this endpoint to send and receive data.
176 // |desired_port| is a port that should be used. If it is equal to 0,
177 // endpoint will pick the first available port starting from
178 // |kFirstEphemeralPort|.
179 //
180 // Returns the port, that should be used (it will be equals to desired, if
181 // |desired_port| != 0 and is free or will be the one, selected by endpoint)
182 // or absl::nullopt if desired_port in used. Also fails if there are no more
183 // free ports to bind to.
184 absl::optional<uint16_t> BindReceiver(
185 uint16_t desired_port,
186 EmulatedNetworkReceiverInterface* receiver);
187 void UnbindReceiver(uint16_t port);
188
189 rtc::IPAddress GetPeerLocalAddress() const;
190
191 // Will be called to deliver packet into endpoint from network node.
192 void OnPacketReceived(EmulatedIpPacket packet) override;
193
Artem Titove5cc85b2019-03-28 12:11:09 +0100194 void Enable();
195 void Disable();
196 bool Enabled() const;
197
198 const rtc::Network& network() const { return *network_.get(); }
199
Artem Titov806299e2019-04-12 12:17:19 +0200200 EmulatedNetworkStats stats();
201
Artem Titov0774bd92019-01-30 15:26:05 +0100202 private:
203 static constexpr uint16_t kFirstEphemeralPort = 49152;
204 uint16_t NextPort() RTC_EXCLUSIVE_LOCKS_REQUIRED(receiver_lock_);
Artem Titov806299e2019-04-12 12:17:19 +0200205 void UpdateReceiveStats(const EmulatedIpPacket& packet);
Artem Titov0774bd92019-01-30 15:26:05 +0100206
207 rtc::CriticalSection receiver_lock_;
Artem Titove5cc85b2019-03-28 12:11:09 +0100208 rtc::ThreadChecker enabled_state_checker_;
Artem Titov0774bd92019-01-30 15:26:05 +0100209
210 uint64_t id_;
211 // Peer's local IP address for this endpoint network interface.
212 const rtc::IPAddress peer_local_addr_;
Artem Titove5cc85b2019-03-28 12:11:09 +0100213 bool is_enabled_ RTC_GUARDED_BY(enabled_state_checker_);
Artem Titov0774bd92019-01-30 15:26:05 +0100214 Clock* const clock_;
Artem Titovff393122019-04-05 11:19:52 +0200215 rtc::TaskQueue* const task_queue_;
Artem Titove5cc85b2019-03-28 12:11:09 +0100216 std::unique_ptr<rtc::Network> network_;
Artem Titovff393122019-04-05 11:19:52 +0200217 NetworkRouterNode router_;
Artem Titov0774bd92019-01-30 15:26:05 +0100218
219 uint16_t next_port_ RTC_GUARDED_BY(receiver_lock_);
220 std::map<uint16_t, EmulatedNetworkReceiverInterface*> port_to_receiver_
221 RTC_GUARDED_BY(receiver_lock_);
Artem Titov806299e2019-04-12 12:17:19 +0200222
223 EmulatedNetworkStats stats_ RTC_GUARDED_BY(task_queue_);
Artem Titov0774bd92019-01-30 15:26:05 +0100224};
225
Artem Titovfc6ab002019-03-12 13:48:32 +0100226class EmulatedRoute {
227 public:
228 EmulatedRoute(EmulatedEndpoint* from,
229 std::vector<EmulatedNetworkNode*> via_nodes,
230 EmulatedEndpoint* to)
231 : from(from), via_nodes(std::move(via_nodes)), to(to), active(true) {}
232
233 EmulatedEndpoint* from;
234 std::vector<EmulatedNetworkNode*> via_nodes;
235 EmulatedEndpoint* to;
236 bool active;
237};
Artem Titove5cc85b2019-03-28 12:11:09 +0100238class EndpointsContainer {
239 public:
Sebastian Janssonb13ccc52019-06-07 13:06:00 +0200240 explicit EndpointsContainer(const std::vector<EmulatedEndpoint*>& endpoints);
Artem Titove5cc85b2019-03-28 12:11:09 +0100241
242 EmulatedEndpoint* LookupByLocalAddress(const rtc::IPAddress& local_ip) const;
243 bool HasEndpoint(EmulatedEndpoint* endpoint) const;
244 // Returns list of networks for enabled endpoints. Caller takes ownership of
245 // returned rtc::Network objects.
246 std::vector<std::unique_ptr<rtc::Network>> GetEnabledNetworks() const;
Artem Titov806299e2019-04-12 12:17:19 +0200247 EmulatedNetworkStats GetStats() const;
Artem Titove5cc85b2019-03-28 12:11:09 +0100248
249 private:
250 const std::vector<EmulatedEndpoint*> endpoints_;
251};
252
Sebastian Janssonb13ccc52019-06-07 13:06:00 +0200253template <typename FakePacketType>
254class FakePacketRoute : public EmulatedNetworkReceiverInterface {
255 public:
256 FakePacketRoute(EmulatedRoute* route,
257 std::function<void(FakePacketType, Timestamp)> action)
258 : route_(route),
259 action_(std::move(action)),
260 send_addr_(route_->from->GetPeerLocalAddress(), 0),
261 recv_addr_(route_->to->GetPeerLocalAddress(),
262 *route_->to->BindReceiver(0, this)) {}
263
264 void SendPacket(size_t size, FakePacketType packet) {
265 RTC_CHECK_GE(size, sizeof(int));
266 sent_.emplace(next_packet_id_, packet);
267 rtc::CopyOnWriteBuffer buf(size);
268 reinterpret_cast<int*>(buf.data())[0] = next_packet_id_++;
269 route_->from->SendPacket(send_addr_, recv_addr_, buf);
270 }
271
272 void OnPacketReceived(EmulatedIpPacket packet) override {
273 int packet_id = reinterpret_cast<int*>(packet.data.data())[0];
274 action_(std::move(sent_[packet_id]), packet.arrival_time);
275 sent_.erase(packet_id);
276 }
277
278 private:
279 EmulatedRoute* const route_;
280 const std::function<void(FakePacketType, Timestamp)> action_;
281 const rtc::SocketAddress send_addr_;
282 const rtc::SocketAddress recv_addr_;
283 int next_packet_id_ = 0;
284 std::map<int, FakePacketType> sent_;
285};
286
287template <typename RequestPacketType, typename ResponsePacketType>
288class TwoWayFakeTrafficRoute {
289 public:
290 class TrafficHandlerInterface {
291 public:
292 virtual void OnRequest(RequestPacketType, Timestamp) = 0;
293 virtual void OnResponse(ResponsePacketType, Timestamp) = 0;
294 virtual ~TrafficHandlerInterface() = default;
295 };
296 TwoWayFakeTrafficRoute(TrafficHandlerInterface* handler,
297 EmulatedRoute* send_route,
298 EmulatedRoute* ret_route)
299 : handler_(handler),
300 request_handler_{send_route,
301 [&](RequestPacketType packet, Timestamp arrival_time) {
302 handler_->OnRequest(std::move(packet), arrival_time);
303 }},
304 response_handler_{
305 ret_route, [&](ResponsePacketType packet, Timestamp arrival_time) {
306 handler_->OnResponse(std::move(packet), arrival_time);
307 }} {}
308 void SendRequest(size_t size, RequestPacketType packet) {
309 request_handler_.SendPacket(size, std::move(packet));
310 }
311 void SendResponse(size_t size, ResponsePacketType packet) {
312 response_handler_.SendPacket(size, std::move(packet));
313 }
314
315 private:
316 TrafficHandlerInterface* handler_;
317 FakePacketRoute<RequestPacketType> request_handler_;
318 FakePacketRoute<ResponsePacketType> response_handler_;
319};
Artem Titov40f51152019-01-04 15:45:01 +0100320} // namespace webrtc
321
Artem Titov386802e2019-07-05 10:48:17 +0200322#endif // TEST_NETWORK_NETWORK_EMULATION_H_