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