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