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