blob: c5ed53961de9f5da4c329a4c85a7af88606418cb [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_);
85 void HandlePacketReceived(EmulatedIpPacket packet) RTC_RUN_ON(task_queue_);
86
87 Clock* const clock_;
88 rtc::TaskQueue* const task_queue_;
89 const std::unique_ptr<NetworkBehaviorInterface> network_behavior_
90 RTC_GUARDED_BY(task_queue_);
91 EmulatedNetworkReceiverInterface* const receiver_;
92 RepeatingTaskHandle process_task_ RTC_GUARDED_BY(task_queue_);
93 std::deque<StoredPacket> packets_ RTC_GUARDED_BY(task_queue_);
94 uint64_t next_packet_id_ RTC_GUARDED_BY(task_queue_) = 1;
95};
96
97class NetworkRouterNode : public EmulatedNetworkReceiverInterface {
98 public:
99 explicit NetworkRouterNode(rtc::TaskQueue* task_queue);
100
101 void OnPacketReceived(EmulatedIpPacket packet) override;
102 void SetReceiver(rtc::IPAddress dest_ip,
103 EmulatedNetworkReceiverInterface* receiver);
104 void RemoveReceiver(rtc::IPAddress dest_ip);
Sebastian Jansson71c6b562019-08-14 11:31:02 +0200105 void SetWatcher(std::function<void(const EmulatedIpPacket&)> watcher);
Sebastian Jansson62bb47f2019-04-01 18:23:58 +0200106
107 private:
108 rtc::TaskQueue* const task_queue_;
109 std::map<rtc::IPAddress, EmulatedNetworkReceiverInterface*> routing_
110 RTC_GUARDED_BY(task_queue_);
Sebastian Jansson71c6b562019-08-14 11:31:02 +0200111 std::function<void(const EmulatedIpPacket&)> watcher_
112 RTC_GUARDED_BY(task_queue_);
Sebastian Jansson62bb47f2019-04-01 18:23:58 +0200113};
114
Artem Titov37d18482019-01-08 15:41:45 +0100115// Represents node in the emulated network. Nodes can be connected with each
116// other to form different networks with different behavior. The behavior of
117// the node itself is determined by a concrete implementation of
118// NetworkBehaviorInterface that is provided on construction.
119class EmulatedNetworkNode : public EmulatedNetworkReceiverInterface {
120 public:
121 // Creates node based on |network_behavior|. The specified |packet_overhead|
122 // is added to the size of each packet in the information provided to
123 // |network_behavior|.
Sebastian Jansson4124dab2019-04-01 14:33:53 +0200124 // |task_queue| is used to process packets and to forward the packets when
125 // they are ready.
Sebastian Jansson62bb47f2019-04-01 18:23:58 +0200126 EmulatedNetworkNode(
Sebastian Jansson4124dab2019-04-01 14:33:53 +0200127 Clock* clock,
128 rtc::TaskQueue* task_queue,
Sebastian Jansson8c8feb92019-01-29 15:59:17 +0100129 std::unique_ptr<NetworkBehaviorInterface> network_behavior);
Artem Titov37d18482019-01-08 15:41:45 +0100130 ~EmulatedNetworkNode() override;
131 RTC_DISALLOW_COPY_AND_ASSIGN(EmulatedNetworkNode);
132
133 void OnPacketReceived(EmulatedIpPacket packet) override;
Sebastian Jansson62bb47f2019-04-01 18:23:58 +0200134
135 LinkEmulation* link() { return &link_; }
136 NetworkRouterNode* router() { return &router_; }
Artem Titov37d18482019-01-08 15:41:45 +0100137
Artem Titov4cd433e2019-04-01 11:01:16 +0200138 // Creates a route for the given receiver_ip over all the given nodes to the
Artem Titov37d18482019-01-08 15:41:45 +0100139 // given receiver.
Artem Titov4cd433e2019-04-01 11:01:16 +0200140 static void CreateRoute(rtc::IPAddress receiver_ip,
Artem Titov37d18482019-01-08 15:41:45 +0100141 std::vector<EmulatedNetworkNode*> nodes,
142 EmulatedNetworkReceiverInterface* receiver);
Artem Titov4cd433e2019-04-01 11:01:16 +0200143 static void ClearRoute(rtc::IPAddress receiver_ip,
Artem Titov37d18482019-01-08 15:41:45 +0100144 std::vector<EmulatedNetworkNode*> nodes);
145
146 private:
Sebastian Jansson62bb47f2019-04-01 18:23:58 +0200147 NetworkRouterNode router_;
148 LinkEmulation link_;
Artem Titov37d18482019-01-08 15:41:45 +0100149};
150
Artem Titov0774bd92019-01-30 15:26:05 +0100151// Represents single network interface on the device.
152// It will be used as sender from socket side to send data to the network and
153// will act as packet receiver from emulated network side to receive packets
154// from other EmulatedNetworkNodes.
Artem Titovaba8dc22019-03-11 10:08:40 +0100155class EmulatedEndpoint : public EmulatedNetworkReceiverInterface {
Artem Titov0774bd92019-01-30 15:26:05 +0100156 public:
Artem Titove5cc85b2019-03-28 12:11:09 +0100157 EmulatedEndpoint(uint64_t id,
Artem Titov612e1792019-04-01 14:43:38 +0200158 const rtc::IPAddress& ip,
Artem Titove5cc85b2019-03-28 12:11:09 +0100159 bool is_enabled,
Artem Titovff393122019-04-05 11:19:52 +0200160 rtc::TaskQueue* task_queue,
Artem Titove5cc85b2019-03-28 12:11:09 +0100161 Clock* clock);
Artem Titovaba8dc22019-03-11 10:08:40 +0100162 ~EmulatedEndpoint() override;
Artem Titov0774bd92019-01-30 15:26:05 +0100163
164 uint64_t GetId() const;
165
Artem Titovff393122019-04-05 11:19:52 +0200166 NetworkRouterNode* router() { return &router_; }
Artem Titov0774bd92019-01-30 15:26:05 +0100167 // Send packet into network.
168 // |from| will be used to set source address for the packet in destination
169 // socket.
170 // |to| will be used for routing verification and picking right socket by port
171 // on destination endpoint.
172 void SendPacket(const rtc::SocketAddress& from,
173 const rtc::SocketAddress& to,
174 rtc::CopyOnWriteBuffer packet);
175
176 // Binds receiver to this endpoint to send and receive data.
177 // |desired_port| is a port that should be used. If it is equal to 0,
178 // endpoint will pick the first available port starting from
179 // |kFirstEphemeralPort|.
180 //
181 // Returns the port, that should be used (it will be equals to desired, if
182 // |desired_port| != 0 and is free or will be the one, selected by endpoint)
183 // or absl::nullopt if desired_port in used. Also fails if there are no more
184 // free ports to bind to.
185 absl::optional<uint16_t> BindReceiver(
186 uint16_t desired_port,
187 EmulatedNetworkReceiverInterface* receiver);
188 void UnbindReceiver(uint16_t port);
189
190 rtc::IPAddress GetPeerLocalAddress() const;
191
192 // Will be called to deliver packet into endpoint from network node.
193 void OnPacketReceived(EmulatedIpPacket packet) override;
194
Artem Titove5cc85b2019-03-28 12:11:09 +0100195 void Enable();
196 void Disable();
197 bool Enabled() const;
198
199 const rtc::Network& network() const { return *network_.get(); }
200
Artem Titov806299e2019-04-12 12:17:19 +0200201 EmulatedNetworkStats stats();
202
Artem Titov0774bd92019-01-30 15:26:05 +0100203 private:
204 static constexpr uint16_t kFirstEphemeralPort = 49152;
205 uint16_t NextPort() RTC_EXCLUSIVE_LOCKS_REQUIRED(receiver_lock_);
Artem Titov806299e2019-04-12 12:17:19 +0200206 void UpdateSendStats(const EmulatedIpPacket& packet);
207 void UpdateReceiveStats(const EmulatedIpPacket& packet);
Artem Titov0774bd92019-01-30 15:26:05 +0100208
209 rtc::CriticalSection receiver_lock_;
Artem Titove5cc85b2019-03-28 12:11:09 +0100210 rtc::ThreadChecker enabled_state_checker_;
Artem Titov0774bd92019-01-30 15:26:05 +0100211
212 uint64_t id_;
213 // Peer's local IP address for this endpoint network interface.
214 const rtc::IPAddress peer_local_addr_;
Artem Titove5cc85b2019-03-28 12:11:09 +0100215 bool is_enabled_ RTC_GUARDED_BY(enabled_state_checker_);
Artem Titov0774bd92019-01-30 15:26:05 +0100216 Clock* const clock_;
Artem Titovff393122019-04-05 11:19:52 +0200217 rtc::TaskQueue* const task_queue_;
Artem Titove5cc85b2019-03-28 12:11:09 +0100218 std::unique_ptr<rtc::Network> network_;
Artem Titovff393122019-04-05 11:19:52 +0200219 NetworkRouterNode router_;
Artem Titov0774bd92019-01-30 15:26:05 +0100220
221 uint16_t next_port_ RTC_GUARDED_BY(receiver_lock_);
222 std::map<uint16_t, EmulatedNetworkReceiverInterface*> port_to_receiver_
223 RTC_GUARDED_BY(receiver_lock_);
Artem Titov806299e2019-04-12 12:17:19 +0200224
225 EmulatedNetworkStats stats_ RTC_GUARDED_BY(task_queue_);
Artem Titov0774bd92019-01-30 15:26:05 +0100226};
227
Artem Titovfc6ab002019-03-12 13:48:32 +0100228class EmulatedRoute {
229 public:
230 EmulatedRoute(EmulatedEndpoint* from,
231 std::vector<EmulatedNetworkNode*> via_nodes,
232 EmulatedEndpoint* to)
233 : from(from), via_nodes(std::move(via_nodes)), to(to), active(true) {}
234
235 EmulatedEndpoint* from;
236 std::vector<EmulatedNetworkNode*> via_nodes;
237 EmulatedEndpoint* to;
238 bool active;
239};
Artem Titove5cc85b2019-03-28 12:11:09 +0100240class EndpointsContainer {
241 public:
Sebastian Janssonb13ccc52019-06-07 13:06:00 +0200242 explicit EndpointsContainer(const std::vector<EmulatedEndpoint*>& endpoints);
Artem Titove5cc85b2019-03-28 12:11:09 +0100243
244 EmulatedEndpoint* LookupByLocalAddress(const rtc::IPAddress& local_ip) const;
245 bool HasEndpoint(EmulatedEndpoint* endpoint) const;
246 // Returns list of networks for enabled endpoints. Caller takes ownership of
247 // returned rtc::Network objects.
248 std::vector<std::unique_ptr<rtc::Network>> GetEnabledNetworks() const;
Artem Titov806299e2019-04-12 12:17:19 +0200249 EmulatedNetworkStats GetStats() const;
Artem Titove5cc85b2019-03-28 12:11:09 +0100250
251 private:
252 const std::vector<EmulatedEndpoint*> endpoints_;
253};
254
Sebastian Janssonb13ccc52019-06-07 13:06:00 +0200255template <typename FakePacketType>
256class FakePacketRoute : public EmulatedNetworkReceiverInterface {
257 public:
258 FakePacketRoute(EmulatedRoute* route,
259 std::function<void(FakePacketType, Timestamp)> action)
260 : route_(route),
261 action_(std::move(action)),
262 send_addr_(route_->from->GetPeerLocalAddress(), 0),
263 recv_addr_(route_->to->GetPeerLocalAddress(),
264 *route_->to->BindReceiver(0, this)) {}
265
266 void SendPacket(size_t size, FakePacketType packet) {
267 RTC_CHECK_GE(size, sizeof(int));
268 sent_.emplace(next_packet_id_, packet);
269 rtc::CopyOnWriteBuffer buf(size);
270 reinterpret_cast<int*>(buf.data())[0] = next_packet_id_++;
271 route_->from->SendPacket(send_addr_, recv_addr_, buf);
272 }
273
274 void OnPacketReceived(EmulatedIpPacket packet) override {
275 int packet_id = reinterpret_cast<int*>(packet.data.data())[0];
276 action_(std::move(sent_[packet_id]), packet.arrival_time);
277 sent_.erase(packet_id);
278 }
279
280 private:
281 EmulatedRoute* const route_;
282 const std::function<void(FakePacketType, Timestamp)> action_;
283 const rtc::SocketAddress send_addr_;
284 const rtc::SocketAddress recv_addr_;
285 int next_packet_id_ = 0;
286 std::map<int, FakePacketType> sent_;
287};
288
289template <typename RequestPacketType, typename ResponsePacketType>
290class TwoWayFakeTrafficRoute {
291 public:
292 class TrafficHandlerInterface {
293 public:
294 virtual void OnRequest(RequestPacketType, Timestamp) = 0;
295 virtual void OnResponse(ResponsePacketType, Timestamp) = 0;
296 virtual ~TrafficHandlerInterface() = default;
297 };
298 TwoWayFakeTrafficRoute(TrafficHandlerInterface* handler,
299 EmulatedRoute* send_route,
300 EmulatedRoute* ret_route)
301 : handler_(handler),
302 request_handler_{send_route,
303 [&](RequestPacketType packet, Timestamp arrival_time) {
304 handler_->OnRequest(std::move(packet), arrival_time);
305 }},
306 response_handler_{
307 ret_route, [&](ResponsePacketType packet, Timestamp arrival_time) {
308 handler_->OnResponse(std::move(packet), arrival_time);
309 }} {}
310 void SendRequest(size_t size, RequestPacketType packet) {
311 request_handler_.SendPacket(size, std::move(packet));
312 }
313 void SendResponse(size_t size, ResponsePacketType packet) {
314 response_handler_.SendPacket(size, std::move(packet));
315 }
316
317 private:
318 TrafficHandlerInterface* handler_;
319 FakePacketRoute<RequestPacketType> request_handler_;
320 FakePacketRoute<ResponsePacketType> response_handler_;
321};
Artem Titov40f51152019-01-04 15:45:01 +0100322} // namespace webrtc
323
Artem Titov386802e2019-07-05 10:48:17 +0200324#endif // TEST_NETWORK_NETWORK_EMULATION_H_