xref: /aosp_15_r20/external/webrtc/p2p/base/fake_port_allocator.h (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright 2010 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 #ifndef P2P_BASE_FAKE_PORT_ALLOCATOR_H_
12 #define P2P_BASE_FAKE_PORT_ALLOCATOR_H_
13 
14 #include <memory>
15 #include <string>
16 #include <utility>
17 #include <vector>
18 
19 #include "absl/strings/string_view.h"
20 #include "p2p/base/basic_packet_socket_factory.h"
21 #include "p2p/base/port_allocator.h"
22 #include "p2p/base/udp_port.h"
23 #include "rtc_base/memory/always_valid_pointer.h"
24 #include "rtc_base/net_helpers.h"
25 #include "rtc_base/task_queue_for_test.h"
26 #include "rtc_base/thread.h"
27 #include "test/scoped_key_value_config.h"
28 
29 namespace rtc {
30 class SocketFactory;
31 }
32 
33 namespace cricket {
34 
35 class TestUDPPort : public UDPPort {
36  public:
Create(rtc::Thread * thread,rtc::PacketSocketFactory * factory,const rtc::Network * network,uint16_t min_port,uint16_t max_port,absl::string_view username,absl::string_view password,bool emit_localhost_for_anyaddress,const webrtc::FieldTrialsView * field_trials)37   static TestUDPPort* Create(rtc::Thread* thread,
38                              rtc::PacketSocketFactory* factory,
39                              const rtc::Network* network,
40                              uint16_t min_port,
41                              uint16_t max_port,
42                              absl::string_view username,
43                              absl::string_view password,
44                              bool emit_localhost_for_anyaddress,
45                              const webrtc::FieldTrialsView* field_trials) {
46     TestUDPPort* port =
47         new TestUDPPort(thread, factory, network, min_port, max_port, username,
48                         password, emit_localhost_for_anyaddress, field_trials);
49     if (!port->Init()) {
50       delete port;
51       port = nullptr;
52     }
53     return port;
54   }
55 
56  protected:
TestUDPPort(rtc::Thread * thread,rtc::PacketSocketFactory * factory,const rtc::Network * network,uint16_t min_port,uint16_t max_port,absl::string_view username,absl::string_view password,bool emit_localhost_for_anyaddress,const webrtc::FieldTrialsView * field_trials)57   TestUDPPort(rtc::Thread* thread,
58               rtc::PacketSocketFactory* factory,
59               const rtc::Network* network,
60               uint16_t min_port,
61               uint16_t max_port,
62               absl::string_view username,
63               absl::string_view password,
64               bool emit_localhost_for_anyaddress,
65               const webrtc::FieldTrialsView* field_trials)
66       : UDPPort(thread,
67                 factory,
68                 network,
69                 min_port,
70                 max_port,
71                 username,
72                 password,
73                 emit_localhost_for_anyaddress,
74                 field_trials) {}
75 };
76 
77 // A FakePortAllocatorSession can be used with either a real or fake socket
78 // factory. It gathers a single loopback port, using IPv6 if available and
79 // not disabled.
80 class FakePortAllocatorSession : public PortAllocatorSession {
81  public:
FakePortAllocatorSession(PortAllocator * allocator,rtc::Thread * network_thread,rtc::PacketSocketFactory * factory,absl::string_view content_name,int component,absl::string_view ice_ufrag,absl::string_view ice_pwd,const webrtc::FieldTrialsView & field_trials)82   FakePortAllocatorSession(PortAllocator* allocator,
83                            rtc::Thread* network_thread,
84                            rtc::PacketSocketFactory* factory,
85                            absl::string_view content_name,
86                            int component,
87                            absl::string_view ice_ufrag,
88                            absl::string_view ice_pwd,
89                            const webrtc::FieldTrialsView& field_trials)
90       : PortAllocatorSession(content_name,
91                              component,
92                              ice_ufrag,
93                              ice_pwd,
94                              allocator->flags()),
95         network_thread_(network_thread),
96         factory_(factory),
97         ipv4_network_("network",
98                       "unittest",
99                       rtc::IPAddress(INADDR_LOOPBACK),
100                       32),
101         ipv6_network_("network",
102                       "unittest",
103                       rtc::IPAddress(in6addr_loopback),
104                       64),
105         port_(),
106         port_config_count_(0),
107         stun_servers_(allocator->stun_servers()),
108         turn_servers_(allocator->turn_servers()),
109         field_trials_(field_trials) {
110     ipv4_network_.AddIP(rtc::IPAddress(INADDR_LOOPBACK));
111     ipv6_network_.AddIP(rtc::IPAddress(in6addr_loopback));
112     set_ice_tiebreaker(/*kTiebreakerDefault = */ 44444);
113   }
114 
SetCandidateFilter(uint32_t filter)115   void SetCandidateFilter(uint32_t filter) override {
116     candidate_filter_ = filter;
117   }
118 
StartGettingPorts()119   void StartGettingPorts() override {
120     if (!port_) {
121       rtc::Network& network =
122           (rtc::HasIPv6Enabled() && (flags() & PORTALLOCATOR_ENABLE_IPV6))
123               ? ipv6_network_
124               : ipv4_network_;
125       port_.reset(TestUDPPort::Create(network_thread_, factory_, &network, 0, 0,
126                                       username(), password(), false,
127                                       &field_trials_));
128       RTC_DCHECK(port_);
129       port_->SetIceTiebreaker(ice_tiebreaker());
130       port_->SubscribePortDestroyed(
131           [this](PortInterface* port) { OnPortDestroyed(port); });
132       AddPort(port_.get());
133     }
134     ++port_config_count_;
135     running_ = true;
136   }
137 
StopGettingPorts()138   void StopGettingPorts() override { running_ = false; }
IsGettingPorts()139   bool IsGettingPorts() override { return running_; }
ClearGettingPorts()140   void ClearGettingPorts() override { is_cleared = true; }
IsCleared()141   bool IsCleared() const override { return is_cleared; }
142 
RegatherOnFailedNetworks()143   void RegatherOnFailedNetworks() override {
144     SignalIceRegathering(this, IceRegatheringReason::NETWORK_FAILURE);
145   }
146 
ReadyPorts()147   std::vector<PortInterface*> ReadyPorts() const override {
148     return ready_ports_;
149   }
ReadyCandidates()150   std::vector<Candidate> ReadyCandidates() const override {
151     return candidates_;
152   }
PruneAllPorts()153   void PruneAllPorts() override { port_->Prune(); }
CandidatesAllocationDone()154   bool CandidatesAllocationDone() const override { return allocation_done_; }
155 
port_config_count()156   int port_config_count() { return port_config_count_; }
157 
stun_servers()158   const ServerAddresses& stun_servers() const { return stun_servers_; }
159 
turn_servers()160   const std::vector<RelayServerConfig>& turn_servers() const {
161     return turn_servers_;
162   }
163 
candidate_filter()164   uint32_t candidate_filter() const { return candidate_filter_; }
165 
transport_info_update_count()166   int transport_info_update_count() const {
167     return transport_info_update_count_;
168   }
169 
170  protected:
UpdateIceParametersInternal()171   void UpdateIceParametersInternal() override {
172     // Since this class is a fake and this method only is overridden for tests,
173     // we don't need to actually update the transport info.
174     ++transport_info_update_count_;
175   }
176 
177  private:
AddPort(cricket::Port * port)178   void AddPort(cricket::Port* port) {
179     port->set_component(component());
180     port->set_generation(generation());
181     port->SignalPortComplete.connect(this,
182                                      &FakePortAllocatorSession::OnPortComplete);
183     port->PrepareAddress();
184     ready_ports_.push_back(port);
185     SignalPortReady(this, port);
186     port->KeepAliveUntilPruned();
187   }
OnPortComplete(cricket::Port * port)188   void OnPortComplete(cricket::Port* port) {
189     const std::vector<Candidate>& candidates = port->Candidates();
190     candidates_.insert(candidates_.end(), candidates.begin(), candidates.end());
191     SignalCandidatesReady(this, candidates);
192 
193     allocation_done_ = true;
194     SignalCandidatesAllocationDone(this);
195   }
OnPortDestroyed(cricket::PortInterface * port)196   void OnPortDestroyed(cricket::PortInterface* port) {
197     // Don't want to double-delete port if it deletes itself.
198     port_.release();
199   }
200 
201   rtc::Thread* network_thread_;
202   rtc::PacketSocketFactory* factory_;
203   rtc::Network ipv4_network_;
204   rtc::Network ipv6_network_;
205   std::unique_ptr<cricket::Port> port_;
206   int port_config_count_;
207   std::vector<Candidate> candidates_;
208   std::vector<PortInterface*> ready_ports_;
209   bool allocation_done_ = false;
210   bool is_cleared = false;
211   ServerAddresses stun_servers_;
212   std::vector<RelayServerConfig> turn_servers_;
213   uint32_t candidate_filter_ = CF_ALL;
214   int transport_info_update_count_ = 0;
215   bool running_ = false;
216   const webrtc::FieldTrialsView& field_trials_;
217 };
218 
219 class FakePortAllocator : public cricket::PortAllocator {
220  public:
FakePortAllocator(rtc::Thread * network_thread,rtc::PacketSocketFactory * factory)221   FakePortAllocator(rtc::Thread* network_thread,
222                     rtc::PacketSocketFactory* factory)
223       : FakePortAllocator(network_thread, factory, nullptr) {}
224 
FakePortAllocator(rtc::Thread * network_thread,std::unique_ptr<rtc::PacketSocketFactory> factory)225   FakePortAllocator(rtc::Thread* network_thread,
226                     std::unique_ptr<rtc::PacketSocketFactory> factory)
227       : FakePortAllocator(network_thread, nullptr, std::move(factory)) {}
228 
SetNetworkIgnoreMask(int network_ignore_mask)229   void SetNetworkIgnoreMask(int network_ignore_mask) override {}
230 
CreateSessionInternal(absl::string_view content_name,int component,absl::string_view ice_ufrag,absl::string_view ice_pwd)231   cricket::PortAllocatorSession* CreateSessionInternal(
232       absl::string_view content_name,
233       int component,
234       absl::string_view ice_ufrag,
235       absl::string_view ice_pwd) override {
236     return new FakePortAllocatorSession(
237         this, network_thread_, factory_.get(), std::string(content_name),
238         component, std::string(ice_ufrag), std::string(ice_pwd), field_trials_);
239   }
240 
initialized()241   bool initialized() const { return initialized_; }
242 
243   // For testing: Manipulate MdnsObfuscationEnabled()
MdnsObfuscationEnabled()244   bool MdnsObfuscationEnabled() const override {
245     return mdns_obfuscation_enabled_;
246   }
SetMdnsObfuscationEnabledForTesting(bool enabled)247   void SetMdnsObfuscationEnabledForTesting(bool enabled) {
248     mdns_obfuscation_enabled_ = enabled;
249   }
250 
251  private:
FakePortAllocator(rtc::Thread * network_thread,rtc::PacketSocketFactory * factory,std::unique_ptr<rtc::PacketSocketFactory> owned_factory)252   FakePortAllocator(rtc::Thread* network_thread,
253                     rtc::PacketSocketFactory* factory,
254                     std::unique_ptr<rtc::PacketSocketFactory> owned_factory)
255       : network_thread_(network_thread),
256         factory_(std::move(owned_factory), factory) {
257     if (network_thread_ == nullptr) {
258       network_thread_ = rtc::Thread::Current();
259       Initialize();
260       return;
261     }
262     SendTask(network_thread_, [this] { Initialize(); });
263   }
264 
265   webrtc::test::ScopedKeyValueConfig field_trials_;
266   rtc::Thread* network_thread_;
267   const webrtc::AlwaysValidPointerNoDefault<rtc::PacketSocketFactory> factory_;
268   bool mdns_obfuscation_enabled_ = false;
269 };
270 
271 }  // namespace cricket
272 
273 #endif  // P2P_BASE_FAKE_PORT_ALLOCATOR_H_
274