1 /*
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 #include "test/network/emulated_network_manager.h"
12
13 #include <memory>
14 #include <utility>
15
16 #include "absl/memory/memory.h"
17 #include "p2p/base/basic_packet_socket_factory.h"
18 #include "test/network/fake_network_socket_server.h"
19
20 namespace webrtc {
21 namespace test {
22
EmulatedNetworkManager(TimeController * time_controller,TaskQueueForTest * task_queue,EndpointsContainer * endpoints_container)23 EmulatedNetworkManager::EmulatedNetworkManager(
24 TimeController* time_controller,
25 TaskQueueForTest* task_queue,
26 EndpointsContainer* endpoints_container)
27 : task_queue_(task_queue),
28 endpoints_container_(endpoints_container),
29 sent_first_update_(false),
30 start_count_(0) {
31 auto socket_server =
32 std::make_unique<FakeNetworkSocketServer>(endpoints_container);
33 packet_socket_factory_ =
34 std::make_unique<rtc::BasicPacketSocketFactory>(socket_server.get());
35 // Since we pass ownership of the socket server to `network_thread_`, we must
36 // arrange that it outlives `packet_socket_factory_` which refers to it.
37 network_thread_ =
38 time_controller->CreateThread("net_thread", std::move(socket_server));
39 }
40
EnableEndpoint(EmulatedEndpointImpl * endpoint)41 void EmulatedNetworkManager::EnableEndpoint(EmulatedEndpointImpl* endpoint) {
42 RTC_CHECK(endpoints_container_->HasEndpoint(endpoint))
43 << "No such interface: " << endpoint->GetPeerLocalAddress().ToString();
44 network_thread_->PostTask([this, endpoint]() {
45 endpoint->Enable();
46 UpdateNetworksOnce();
47 });
48 }
49
DisableEndpoint(EmulatedEndpointImpl * endpoint)50 void EmulatedNetworkManager::DisableEndpoint(EmulatedEndpointImpl* endpoint) {
51 RTC_CHECK(endpoints_container_->HasEndpoint(endpoint))
52 << "No such interface: " << endpoint->GetPeerLocalAddress().ToString();
53 network_thread_->PostTask([this, endpoint]() {
54 endpoint->Disable();
55 UpdateNetworksOnce();
56 });
57 }
58
59 // Network manager interface. All these methods are supposed to be called from
60 // the same thread.
StartUpdating()61 void EmulatedNetworkManager::StartUpdating() {
62 RTC_DCHECK_RUN_ON(network_thread_.get());
63
64 if (start_count_) {
65 // If network interfaces are already discovered and signal is sent,
66 // we should trigger network signal immediately for the new clients
67 // to start allocating ports.
68 if (sent_first_update_)
69 network_thread_->PostTask([this]() { MaybeSignalNetworksChanged(); });
70 } else {
71 network_thread_->PostTask([this]() { UpdateNetworksOnce(); });
72 }
73 ++start_count_;
74 }
75
StopUpdating()76 void EmulatedNetworkManager::StopUpdating() {
77 RTC_DCHECK_RUN_ON(network_thread_.get());
78 if (!start_count_)
79 return;
80
81 --start_count_;
82 if (!start_count_) {
83 sent_first_update_ = false;
84 }
85 }
86
GetStats(std::function<void (EmulatedNetworkStats)> stats_callback) const87 void EmulatedNetworkManager::GetStats(
88 std::function<void(EmulatedNetworkStats)> stats_callback) const {
89 task_queue_->PostTask([stats_callback, this]() {
90 stats_callback(endpoints_container_->GetStats());
91 });
92 }
93
UpdateNetworksOnce()94 void EmulatedNetworkManager::UpdateNetworksOnce() {
95 RTC_DCHECK_RUN_ON(network_thread_.get());
96
97 std::vector<std::unique_ptr<rtc::Network>> networks;
98 for (std::unique_ptr<rtc::Network>& net :
99 endpoints_container_->GetEnabledNetworks()) {
100 net->set_default_local_address_provider(this);
101 networks.push_back(std::move(net));
102 }
103
104 bool changed;
105 MergeNetworkList(std::move(networks), &changed);
106 if (changed || !sent_first_update_) {
107 MaybeSignalNetworksChanged();
108 sent_first_update_ = true;
109 }
110 }
111
MaybeSignalNetworksChanged()112 void EmulatedNetworkManager::MaybeSignalNetworksChanged() {
113 RTC_DCHECK_RUN_ON(network_thread_.get());
114 // If manager is stopped we don't need to signal anything.
115 if (start_count_ == 0) {
116 return;
117 }
118 SignalNetworksChanged();
119 }
120
121 } // namespace test
122 } // namespace webrtc
123