blob: 24e2fd9098ec5909174e559c62c6f2c78a02f072 [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);
105
106 private:
107 rtc::TaskQueue* const task_queue_;
108 std::map<rtc::IPAddress, EmulatedNetworkReceiverInterface*> routing_
109 RTC_GUARDED_BY(task_queue_);
110};
111
Artem Titov37d18482019-01-08 15:41:45 +0100112// Represents node in the emulated network. Nodes can be connected with each
113// other to form different networks with different behavior. The behavior of
114// the node itself is determined by a concrete implementation of
115// NetworkBehaviorInterface that is provided on construction.
116class EmulatedNetworkNode : public EmulatedNetworkReceiverInterface {
117 public:
118 // Creates node based on |network_behavior|. The specified |packet_overhead|
119 // is added to the size of each packet in the information provided to
120 // |network_behavior|.
Sebastian Jansson4124dab2019-04-01 14:33:53 +0200121 // |task_queue| is used to process packets and to forward the packets when
122 // they are ready.
Sebastian Jansson62bb47f2019-04-01 18:23:58 +0200123 EmulatedNetworkNode(
Sebastian Jansson4124dab2019-04-01 14:33:53 +0200124 Clock* clock,
125 rtc::TaskQueue* task_queue,
Sebastian Jansson8c8feb92019-01-29 15:59:17 +0100126 std::unique_ptr<NetworkBehaviorInterface> network_behavior);
Artem Titov37d18482019-01-08 15:41:45 +0100127 ~EmulatedNetworkNode() override;
128 RTC_DISALLOW_COPY_AND_ASSIGN(EmulatedNetworkNode);
129
130 void OnPacketReceived(EmulatedIpPacket packet) override;
Sebastian Jansson62bb47f2019-04-01 18:23:58 +0200131
132 LinkEmulation* link() { return &link_; }
133 NetworkRouterNode* router() { return &router_; }
Artem Titov37d18482019-01-08 15:41:45 +0100134
Artem Titov4cd433e2019-04-01 11:01:16 +0200135 // Creates a route for the given receiver_ip over all the given nodes to the
Artem Titov37d18482019-01-08 15:41:45 +0100136 // given receiver.
Artem Titov4cd433e2019-04-01 11:01:16 +0200137 static void CreateRoute(rtc::IPAddress receiver_ip,
Artem Titov37d18482019-01-08 15:41:45 +0100138 std::vector<EmulatedNetworkNode*> nodes,
139 EmulatedNetworkReceiverInterface* receiver);
Artem Titov4cd433e2019-04-01 11:01:16 +0200140 static void ClearRoute(rtc::IPAddress receiver_ip,
Artem Titov37d18482019-01-08 15:41:45 +0100141 std::vector<EmulatedNetworkNode*> nodes);
142
143 private:
Sebastian Jansson62bb47f2019-04-01 18:23:58 +0200144 NetworkRouterNode router_;
145 LinkEmulation link_;
Artem Titov37d18482019-01-08 15:41:45 +0100146};
147
Artem Titov0774bd92019-01-30 15:26:05 +0100148// Represents single network interface on the device.
149// It will be used as sender from socket side to send data to the network and
150// will act as packet receiver from emulated network side to receive packets
151// from other EmulatedNetworkNodes.
Artem Titovaba8dc22019-03-11 10:08:40 +0100152class EmulatedEndpoint : public EmulatedNetworkReceiverInterface {
Artem Titov0774bd92019-01-30 15:26:05 +0100153 public:
Artem Titove5cc85b2019-03-28 12:11:09 +0100154 EmulatedEndpoint(uint64_t id,
Artem Titov612e1792019-04-01 14:43:38 +0200155 const rtc::IPAddress& ip,
Artem Titove5cc85b2019-03-28 12:11:09 +0100156 bool is_enabled,
Artem Titovff393122019-04-05 11:19:52 +0200157 rtc::TaskQueue* task_queue,
Artem Titove5cc85b2019-03-28 12:11:09 +0100158 Clock* clock);
Artem Titovaba8dc22019-03-11 10:08:40 +0100159 ~EmulatedEndpoint() override;
Artem Titov0774bd92019-01-30 15:26:05 +0100160
161 uint64_t GetId() const;
162
Artem Titovff393122019-04-05 11:19:52 +0200163 NetworkRouterNode* router() { return &router_; }
Artem Titov0774bd92019-01-30 15:26:05 +0100164 // Send packet into network.
165 // |from| will be used to set source address for the packet in destination
166 // socket.
167 // |to| will be used for routing verification and picking right socket by port
168 // on destination endpoint.
169 void SendPacket(const rtc::SocketAddress& from,
170 const rtc::SocketAddress& to,
171 rtc::CopyOnWriteBuffer packet);
172
173 // Binds receiver to this endpoint to send and receive data.
174 // |desired_port| is a port that should be used. If it is equal to 0,
175 // endpoint will pick the first available port starting from
176 // |kFirstEphemeralPort|.
177 //
178 // Returns the port, that should be used (it will be equals to desired, if
179 // |desired_port| != 0 and is free or will be the one, selected by endpoint)
180 // or absl::nullopt if desired_port in used. Also fails if there are no more
181 // free ports to bind to.
182 absl::optional<uint16_t> BindReceiver(
183 uint16_t desired_port,
184 EmulatedNetworkReceiverInterface* receiver);
185 void UnbindReceiver(uint16_t port);
186
187 rtc::IPAddress GetPeerLocalAddress() const;
188
189 // Will be called to deliver packet into endpoint from network node.
190 void OnPacketReceived(EmulatedIpPacket packet) override;
191
Artem Titove5cc85b2019-03-28 12:11:09 +0100192 void Enable();
193 void Disable();
194 bool Enabled() const;
195
196 const rtc::Network& network() const { return *network_.get(); }
197
Artem Titov806299e2019-04-12 12:17:19 +0200198 EmulatedNetworkStats stats();
199
Artem Titov0774bd92019-01-30 15:26:05 +0100200 private:
201 static constexpr uint16_t kFirstEphemeralPort = 49152;
202 uint16_t NextPort() RTC_EXCLUSIVE_LOCKS_REQUIRED(receiver_lock_);
Artem Titov806299e2019-04-12 12:17:19 +0200203 void UpdateSendStats(const EmulatedIpPacket& packet);
204 void UpdateReceiveStats(const EmulatedIpPacket& packet);
Artem Titov0774bd92019-01-30 15:26:05 +0100205
206 rtc::CriticalSection receiver_lock_;
Artem Titove5cc85b2019-03-28 12:11:09 +0100207 rtc::ThreadChecker enabled_state_checker_;
Artem Titov0774bd92019-01-30 15:26:05 +0100208
209 uint64_t id_;
210 // Peer's local IP address for this endpoint network interface.
211 const rtc::IPAddress peer_local_addr_;
Artem Titove5cc85b2019-03-28 12:11:09 +0100212 bool is_enabled_ RTC_GUARDED_BY(enabled_state_checker_);
Artem Titov0774bd92019-01-30 15:26:05 +0100213 Clock* const clock_;
Artem Titovff393122019-04-05 11:19:52 +0200214 rtc::TaskQueue* const task_queue_;
Artem Titove5cc85b2019-03-28 12:11:09 +0100215 std::unique_ptr<rtc::Network> network_;
Artem Titovff393122019-04-05 11:19:52 +0200216 NetworkRouterNode router_;
Artem Titov0774bd92019-01-30 15:26:05 +0100217
218 uint16_t next_port_ RTC_GUARDED_BY(receiver_lock_);
219 std::map<uint16_t, EmulatedNetworkReceiverInterface*> port_to_receiver_
220 RTC_GUARDED_BY(receiver_lock_);
Artem Titov806299e2019-04-12 12:17:19 +0200221
222 EmulatedNetworkStats stats_ RTC_GUARDED_BY(task_queue_);
Artem Titov0774bd92019-01-30 15:26:05 +0100223};
224
Artem Titovfc6ab002019-03-12 13:48:32 +0100225class EmulatedRoute {
226 public:
227 EmulatedRoute(EmulatedEndpoint* from,
228 std::vector<EmulatedNetworkNode*> via_nodes,
229 EmulatedEndpoint* to)
230 : from(from), via_nodes(std::move(via_nodes)), to(to), active(true) {}
231
232 EmulatedEndpoint* from;
233 std::vector<EmulatedNetworkNode*> via_nodes;
234 EmulatedEndpoint* to;
235 bool active;
236};
Artem Titove5cc85b2019-03-28 12:11:09 +0100237class EndpointsContainer {
238 public:
Sebastian Janssonb13ccc52019-06-07 13:06:00 +0200239 explicit EndpointsContainer(const std::vector<EmulatedEndpoint*>& endpoints);
Artem Titove5cc85b2019-03-28 12:11:09 +0100240
241 EmulatedEndpoint* LookupByLocalAddress(const rtc::IPAddress& local_ip) const;
242 bool HasEndpoint(EmulatedEndpoint* endpoint) const;
243 // Returns list of networks for enabled endpoints. Caller takes ownership of
244 // returned rtc::Network objects.
245 std::vector<std::unique_ptr<rtc::Network>> GetEnabledNetworks() const;
Artem Titov806299e2019-04-12 12:17:19 +0200246 EmulatedNetworkStats GetStats() const;
Artem Titove5cc85b2019-03-28 12:11:09 +0100247
248 private:
249 const std::vector<EmulatedEndpoint*> endpoints_;
250};
251
Sebastian Janssonb13ccc52019-06-07 13:06:00 +0200252template <typename FakePacketType>
253class FakePacketRoute : public EmulatedNetworkReceiverInterface {
254 public:
255 FakePacketRoute(EmulatedRoute* route,
256 std::function<void(FakePacketType, Timestamp)> action)
257 : route_(route),
258 action_(std::move(action)),
259 send_addr_(route_->from->GetPeerLocalAddress(), 0),
260 recv_addr_(route_->to->GetPeerLocalAddress(),
261 *route_->to->BindReceiver(0, this)) {}
262
263 void SendPacket(size_t size, FakePacketType packet) {
264 RTC_CHECK_GE(size, sizeof(int));
265 sent_.emplace(next_packet_id_, packet);
266 rtc::CopyOnWriteBuffer buf(size);
267 reinterpret_cast<int*>(buf.data())[0] = next_packet_id_++;
268 route_->from->SendPacket(send_addr_, recv_addr_, buf);
269 }
270
271 void OnPacketReceived(EmulatedIpPacket packet) override {
272 int packet_id = reinterpret_cast<int*>(packet.data.data())[0];
273 action_(std::move(sent_[packet_id]), packet.arrival_time);
274 sent_.erase(packet_id);
275 }
276
277 private:
278 EmulatedRoute* const route_;
279 const std::function<void(FakePacketType, Timestamp)> action_;
280 const rtc::SocketAddress send_addr_;
281 const rtc::SocketAddress recv_addr_;
282 int next_packet_id_ = 0;
283 std::map<int, FakePacketType> sent_;
284};
285
286template <typename RequestPacketType, typename ResponsePacketType>
287class TwoWayFakeTrafficRoute {
288 public:
289 class TrafficHandlerInterface {
290 public:
291 virtual void OnRequest(RequestPacketType, Timestamp) = 0;
292 virtual void OnResponse(ResponsePacketType, Timestamp) = 0;
293 virtual ~TrafficHandlerInterface() = default;
294 };
295 TwoWayFakeTrafficRoute(TrafficHandlerInterface* handler,
296 EmulatedRoute* send_route,
297 EmulatedRoute* ret_route)
298 : handler_(handler),
299 request_handler_{send_route,
300 [&](RequestPacketType packet, Timestamp arrival_time) {
301 handler_->OnRequest(std::move(packet), arrival_time);
302 }},
303 response_handler_{
304 ret_route, [&](ResponsePacketType packet, Timestamp arrival_time) {
305 handler_->OnResponse(std::move(packet), arrival_time);
306 }} {}
307 void SendRequest(size_t size, RequestPacketType packet) {
308 request_handler_.SendPacket(size, std::move(packet));
309 }
310 void SendResponse(size_t size, ResponsePacketType packet) {
311 response_handler_.SendPacket(size, std::move(packet));
312 }
313
314 private:
315 TrafficHandlerInterface* handler_;
316 FakePacketRoute<RequestPacketType> request_handler_;
317 FakePacketRoute<ResponsePacketType> response_handler_;
318};
Artem Titov40f51152019-01-04 15:45:01 +0100319} // namespace webrtc
320
Artem Titov386802e2019-07-05 10:48:17 +0200321#endif // TEST_NETWORK_NETWORK_EMULATION_H_