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