blob: 2051216a40768bfaf6e7377436fbe1985ef076b2 [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:
Niels Möller7536bc52019-10-04 13:54:39 +020038 static constexpr int kUdpHeaderSize = 8;
39
Artem Titov40f51152019-01-04 15:45:01 +010040 EmulatedIpPacket(const rtc::SocketAddress& from,
41 const rtc::SocketAddress& to,
Artem Titov40f51152019-01-04 15:45:01 +010042 rtc::CopyOnWriteBuffer data,
43 Timestamp arrival_time);
Artem Titov612e1792019-04-01 14:43:38 +020044 ~EmulatedIpPacket() = default;
Artem Titov40f51152019-01-04 15:45:01 +010045 // This object is not copyable or assignable.
46 EmulatedIpPacket(const EmulatedIpPacket&) = delete;
47 EmulatedIpPacket& operator=(const EmulatedIpPacket&) = delete;
48 // This object is only moveable.
Artem Titov612e1792019-04-01 14:43:38 +020049 EmulatedIpPacket(EmulatedIpPacket&&) = default;
50 EmulatedIpPacket& operator=(EmulatedIpPacket&&) = default;
Artem Titov40f51152019-01-04 15:45:01 +010051
52 size_t size() const { return data.size(); }
53 const uint8_t* cdata() const { return data.cdata(); }
54
Niels Möller7536bc52019-10-04 13:54:39 +020055 size_t ip_packet_size() const {
56 return size() + kUdpHeaderSize + ip_header_size;
57 }
Artem Titov40f51152019-01-04 15:45:01 +010058 rtc::SocketAddress from;
59 rtc::SocketAddress to;
Niels Möller7536bc52019-10-04 13:54:39 +020060 // Holds the UDP payload.
Artem Titov40f51152019-01-04 15:45:01 +010061 rtc::CopyOnWriteBuffer data;
Niels Möller7536bc52019-10-04 13:54:39 +020062 int ip_header_size;
Artem Titov40f51152019-01-04 15:45:01 +010063 Timestamp arrival_time;
64};
65
66class EmulatedNetworkReceiverInterface {
67 public:
68 virtual ~EmulatedNetworkReceiverInterface() = default;
69
70 virtual void OnPacketReceived(EmulatedIpPacket packet) = 0;
71};
72
Sebastian Jansson62bb47f2019-04-01 18:23:58 +020073class LinkEmulation : public EmulatedNetworkReceiverInterface {
74 public:
75 LinkEmulation(Clock* clock,
76 rtc::TaskQueue* task_queue,
77 std::unique_ptr<NetworkBehaviorInterface> network_behavior,
78 EmulatedNetworkReceiverInterface* receiver)
79 : clock_(clock),
80 task_queue_(task_queue),
81 network_behavior_(std::move(network_behavior)),
82 receiver_(receiver) {}
83 void OnPacketReceived(EmulatedIpPacket packet) override;
84
85 private:
86 struct StoredPacket {
87 uint64_t id;
88 EmulatedIpPacket packet;
89 bool removed;
90 };
91 void Process(Timestamp at_time) RTC_RUN_ON(task_queue_);
Sebastian Jansson62bb47f2019-04-01 18:23:58 +020092
93 Clock* const clock_;
94 rtc::TaskQueue* const task_queue_;
95 const std::unique_ptr<NetworkBehaviorInterface> network_behavior_
96 RTC_GUARDED_BY(task_queue_);
97 EmulatedNetworkReceiverInterface* const receiver_;
98 RepeatingTaskHandle process_task_ RTC_GUARDED_BY(task_queue_);
99 std::deque<StoredPacket> packets_ RTC_GUARDED_BY(task_queue_);
100 uint64_t next_packet_id_ RTC_GUARDED_BY(task_queue_) = 1;
101};
102
103class NetworkRouterNode : public EmulatedNetworkReceiverInterface {
104 public:
105 explicit NetworkRouterNode(rtc::TaskQueue* task_queue);
106
107 void OnPacketReceived(EmulatedIpPacket packet) override;
108 void SetReceiver(rtc::IPAddress dest_ip,
109 EmulatedNetworkReceiverInterface* receiver);
110 void RemoveReceiver(rtc::IPAddress dest_ip);
Sebastian Jansson71c6b562019-08-14 11:31:02 +0200111 void SetWatcher(std::function<void(const EmulatedIpPacket&)> watcher);
Sebastian Jansson62bb47f2019-04-01 18:23:58 +0200112
113 private:
114 rtc::TaskQueue* const task_queue_;
115 std::map<rtc::IPAddress, EmulatedNetworkReceiverInterface*> routing_
116 RTC_GUARDED_BY(task_queue_);
Sebastian Jansson71c6b562019-08-14 11:31:02 +0200117 std::function<void(const EmulatedIpPacket&)> watcher_
118 RTC_GUARDED_BY(task_queue_);
Sebastian Jansson62bb47f2019-04-01 18:23:58 +0200119};
120
Artem Titov37d18482019-01-08 15:41:45 +0100121// Represents node in the emulated network. Nodes can be connected with each
122// other to form different networks with different behavior. The behavior of
123// the node itself is determined by a concrete implementation of
124// NetworkBehaviorInterface that is provided on construction.
125class EmulatedNetworkNode : public EmulatedNetworkReceiverInterface {
126 public:
127 // Creates node based on |network_behavior|. The specified |packet_overhead|
128 // is added to the size of each packet in the information provided to
129 // |network_behavior|.
Sebastian Jansson4124dab2019-04-01 14:33:53 +0200130 // |task_queue| is used to process packets and to forward the packets when
131 // they are ready.
Sebastian Jansson62bb47f2019-04-01 18:23:58 +0200132 EmulatedNetworkNode(
Sebastian Jansson4124dab2019-04-01 14:33:53 +0200133 Clock* clock,
134 rtc::TaskQueue* task_queue,
Sebastian Jansson8c8feb92019-01-29 15:59:17 +0100135 std::unique_ptr<NetworkBehaviorInterface> network_behavior);
Artem Titov37d18482019-01-08 15:41:45 +0100136 ~EmulatedNetworkNode() override;
137 RTC_DISALLOW_COPY_AND_ASSIGN(EmulatedNetworkNode);
138
139 void OnPacketReceived(EmulatedIpPacket packet) override;
Sebastian Jansson62bb47f2019-04-01 18:23:58 +0200140
141 LinkEmulation* link() { return &link_; }
142 NetworkRouterNode* router() { return &router_; }
Artem Titov37d18482019-01-08 15:41:45 +0100143
Artem Titov4cd433e2019-04-01 11:01:16 +0200144 // Creates a route for the given receiver_ip over all the given nodes to the
Artem Titov37d18482019-01-08 15:41:45 +0100145 // given receiver.
Artem Titov4cd433e2019-04-01 11:01:16 +0200146 static void CreateRoute(rtc::IPAddress receiver_ip,
Artem Titov37d18482019-01-08 15:41:45 +0100147 std::vector<EmulatedNetworkNode*> nodes,
148 EmulatedNetworkReceiverInterface* receiver);
Artem Titov4cd433e2019-04-01 11:01:16 +0200149 static void ClearRoute(rtc::IPAddress receiver_ip,
Artem Titov37d18482019-01-08 15:41:45 +0100150 std::vector<EmulatedNetworkNode*> nodes);
151
152 private:
Sebastian Jansson62bb47f2019-04-01 18:23:58 +0200153 NetworkRouterNode router_;
154 LinkEmulation link_;
Artem Titov37d18482019-01-08 15:41:45 +0100155};
156
Artem Titov0774bd92019-01-30 15:26:05 +0100157// Represents single network interface on the device.
158// It will be used as sender from socket side to send data to the network and
159// will act as packet receiver from emulated network side to receive packets
160// from other EmulatedNetworkNodes.
Artem Titovaba8dc22019-03-11 10:08:40 +0100161class EmulatedEndpoint : public EmulatedNetworkReceiverInterface {
Artem Titov0774bd92019-01-30 15:26:05 +0100162 public:
Artem Titove5cc85b2019-03-28 12:11:09 +0100163 EmulatedEndpoint(uint64_t id,
Artem Titov612e1792019-04-01 14:43:38 +0200164 const rtc::IPAddress& ip,
Artem Titove5cc85b2019-03-28 12:11:09 +0100165 bool is_enabled,
Artem Titovff393122019-04-05 11:19:52 +0200166 rtc::TaskQueue* task_queue,
Artem Titove5cc85b2019-03-28 12:11:09 +0100167 Clock* clock);
Artem Titovaba8dc22019-03-11 10:08:40 +0100168 ~EmulatedEndpoint() override;
Artem Titov0774bd92019-01-30 15:26:05 +0100169
170 uint64_t GetId() const;
171
Artem Titovff393122019-04-05 11:19:52 +0200172 NetworkRouterNode* router() { return &router_; }
Artem Titov0774bd92019-01-30 15:26:05 +0100173 // Send packet into network.
174 // |from| will be used to set source address for the packet in destination
175 // socket.
176 // |to| will be used for routing verification and picking right socket by port
177 // on destination endpoint.
178 void SendPacket(const rtc::SocketAddress& from,
179 const rtc::SocketAddress& to,
Sebastian Janssonee5ec9a2019-09-17 20:34:03 +0200180 rtc::CopyOnWriteBuffer packet_data);
Artem Titov0774bd92019-01-30 15:26:05 +0100181
182 // Binds receiver to this endpoint to send and receive data.
183 // |desired_port| is a port that should be used. If it is equal to 0,
184 // endpoint will pick the first available port starting from
185 // |kFirstEphemeralPort|.
186 //
187 // Returns the port, that should be used (it will be equals to desired, if
188 // |desired_port| != 0 and is free or will be the one, selected by endpoint)
189 // or absl::nullopt if desired_port in used. Also fails if there are no more
190 // free ports to bind to.
191 absl::optional<uint16_t> BindReceiver(
192 uint16_t desired_port,
193 EmulatedNetworkReceiverInterface* receiver);
194 void UnbindReceiver(uint16_t port);
195
196 rtc::IPAddress GetPeerLocalAddress() const;
197
198 // Will be called to deliver packet into endpoint from network node.
199 void OnPacketReceived(EmulatedIpPacket packet) override;
200
Artem Titove5cc85b2019-03-28 12:11:09 +0100201 void Enable();
202 void Disable();
203 bool Enabled() const;
204
205 const rtc::Network& network() const { return *network_.get(); }
206
Artem Titov806299e2019-04-12 12:17:19 +0200207 EmulatedNetworkStats stats();
208
Artem Titov0774bd92019-01-30 15:26:05 +0100209 private:
210 static constexpr uint16_t kFirstEphemeralPort = 49152;
211 uint16_t NextPort() RTC_EXCLUSIVE_LOCKS_REQUIRED(receiver_lock_);
Artem Titov806299e2019-04-12 12:17:19 +0200212 void UpdateReceiveStats(const EmulatedIpPacket& packet);
Artem Titov0774bd92019-01-30 15:26:05 +0100213
214 rtc::CriticalSection receiver_lock_;
Artem Titove5cc85b2019-03-28 12:11:09 +0100215 rtc::ThreadChecker enabled_state_checker_;
Artem Titov0774bd92019-01-30 15:26:05 +0100216
217 uint64_t id_;
218 // Peer's local IP address for this endpoint network interface.
219 const rtc::IPAddress peer_local_addr_;
Artem Titove5cc85b2019-03-28 12:11:09 +0100220 bool is_enabled_ RTC_GUARDED_BY(enabled_state_checker_);
Artem Titov0774bd92019-01-30 15:26:05 +0100221 Clock* const clock_;
Artem Titovff393122019-04-05 11:19:52 +0200222 rtc::TaskQueue* const task_queue_;
Artem Titove5cc85b2019-03-28 12:11:09 +0100223 std::unique_ptr<rtc::Network> network_;
Artem Titovff393122019-04-05 11:19:52 +0200224 NetworkRouterNode router_;
Artem Titov0774bd92019-01-30 15:26:05 +0100225
226 uint16_t next_port_ RTC_GUARDED_BY(receiver_lock_);
227 std::map<uint16_t, EmulatedNetworkReceiverInterface*> port_to_receiver_
228 RTC_GUARDED_BY(receiver_lock_);
Artem Titov806299e2019-04-12 12:17:19 +0200229
230 EmulatedNetworkStats stats_ RTC_GUARDED_BY(task_queue_);
Artem Titov0774bd92019-01-30 15:26:05 +0100231};
232
Artem Titovfc6ab002019-03-12 13:48:32 +0100233class EmulatedRoute {
234 public:
235 EmulatedRoute(EmulatedEndpoint* from,
236 std::vector<EmulatedNetworkNode*> via_nodes,
237 EmulatedEndpoint* to)
238 : from(from), via_nodes(std::move(via_nodes)), to(to), active(true) {}
239
240 EmulatedEndpoint* from;
241 std::vector<EmulatedNetworkNode*> via_nodes;
242 EmulatedEndpoint* to;
243 bool active;
244};
Artem Titove5cc85b2019-03-28 12:11:09 +0100245class EndpointsContainer {
246 public:
Sebastian Janssonb13ccc52019-06-07 13:06:00 +0200247 explicit EndpointsContainer(const std::vector<EmulatedEndpoint*>& endpoints);
Artem Titove5cc85b2019-03-28 12:11:09 +0100248
249 EmulatedEndpoint* LookupByLocalAddress(const rtc::IPAddress& local_ip) const;
250 bool HasEndpoint(EmulatedEndpoint* endpoint) const;
251 // Returns list of networks for enabled endpoints. Caller takes ownership of
252 // returned rtc::Network objects.
253 std::vector<std::unique_ptr<rtc::Network>> GetEnabledNetworks() const;
Artem Titov806299e2019-04-12 12:17:19 +0200254 EmulatedNetworkStats GetStats() const;
Artem Titove5cc85b2019-03-28 12:11:09 +0100255
256 private:
257 const std::vector<EmulatedEndpoint*> endpoints_;
258};
259
Sebastian Janssonb13ccc52019-06-07 13:06:00 +0200260template <typename FakePacketType>
261class FakePacketRoute : public EmulatedNetworkReceiverInterface {
262 public:
263 FakePacketRoute(EmulatedRoute* route,
264 std::function<void(FakePacketType, Timestamp)> action)
265 : route_(route),
266 action_(std::move(action)),
267 send_addr_(route_->from->GetPeerLocalAddress(), 0),
268 recv_addr_(route_->to->GetPeerLocalAddress(),
269 *route_->to->BindReceiver(0, this)) {}
270
Sebastian Janssond8aff212019-10-11 17:00:39 +0200271 ~FakePacketRoute() { route_->to->UnbindReceiver(recv_addr_.port()); }
272
Sebastian Janssonb13ccc52019-06-07 13:06:00 +0200273 void SendPacket(size_t size, FakePacketType packet) {
274 RTC_CHECK_GE(size, sizeof(int));
275 sent_.emplace(next_packet_id_, packet);
276 rtc::CopyOnWriteBuffer buf(size);
277 reinterpret_cast<int*>(buf.data())[0] = next_packet_id_++;
278 route_->from->SendPacket(send_addr_, recv_addr_, buf);
279 }
280
281 void OnPacketReceived(EmulatedIpPacket packet) override {
282 int packet_id = reinterpret_cast<int*>(packet.data.data())[0];
283 action_(std::move(sent_[packet_id]), packet.arrival_time);
284 sent_.erase(packet_id);
285 }
286
287 private:
288 EmulatedRoute* const route_;
289 const std::function<void(FakePacketType, Timestamp)> action_;
290 const rtc::SocketAddress send_addr_;
291 const rtc::SocketAddress recv_addr_;
292 int next_packet_id_ = 0;
293 std::map<int, FakePacketType> sent_;
294};
295
296template <typename RequestPacketType, typename ResponsePacketType>
297class TwoWayFakeTrafficRoute {
298 public:
299 class TrafficHandlerInterface {
300 public:
301 virtual void OnRequest(RequestPacketType, Timestamp) = 0;
302 virtual void OnResponse(ResponsePacketType, Timestamp) = 0;
303 virtual ~TrafficHandlerInterface() = default;
304 };
305 TwoWayFakeTrafficRoute(TrafficHandlerInterface* handler,
306 EmulatedRoute* send_route,
307 EmulatedRoute* ret_route)
308 : handler_(handler),
309 request_handler_{send_route,
310 [&](RequestPacketType packet, Timestamp arrival_time) {
311 handler_->OnRequest(std::move(packet), arrival_time);
312 }},
313 response_handler_{
314 ret_route, [&](ResponsePacketType packet, Timestamp arrival_time) {
315 handler_->OnResponse(std::move(packet), arrival_time);
316 }} {}
317 void SendRequest(size_t size, RequestPacketType packet) {
318 request_handler_.SendPacket(size, std::move(packet));
319 }
320 void SendResponse(size_t size, ResponsePacketType packet) {
321 response_handler_.SendPacket(size, std::move(packet));
322 }
323
324 private:
325 TrafficHandlerInterface* handler_;
326 FakePacketRoute<RequestPacketType> request_handler_;
327 FakePacketRoute<ResponsePacketType> response_handler_;
328};
Artem Titov40f51152019-01-04 15:45:01 +0100329} // namespace webrtc
330
Artem Titov386802e2019-07-05 10:48:17 +0200331#endif // TEST_NETWORK_NETWORK_EMULATION_H_