xref: /aosp_15_r20/external/webrtc/p2p/client/basic_port_allocator.h (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright 2004 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_CLIENT_BASIC_PORT_ALLOCATOR_H_
12 #define P2P_CLIENT_BASIC_PORT_ALLOCATOR_H_
13 
14 #include <memory>
15 #include <string>
16 #include <vector>
17 
18 #include "absl/strings/string_view.h"
19 #include "api/field_trials_view.h"
20 #include "api/task_queue/pending_task_safety_flag.h"
21 #include "api/turn_customizer.h"
22 #include "p2p/base/port_allocator.h"
23 #include "p2p/client/relay_port_factory_interface.h"
24 #include "p2p/client/turn_port_factory.h"
25 #include "rtc_base/checks.h"
26 #include "rtc_base/memory/always_valid_pointer.h"
27 #include "rtc_base/network.h"
28 #include "rtc_base/system/rtc_export.h"
29 #include "rtc_base/thread.h"
30 #include "rtc_base/thread_annotations.h"
31 
32 namespace cricket {
33 
34 class RTC_EXPORT BasicPortAllocator : public PortAllocator {
35  public:
36   // The NetworkManager is a mandatory argument. The other arguments are
37   // optional. All pointers are owned by caller and must have a life time
38   // that exceeds that of BasicPortAllocator.
39   BasicPortAllocator(rtc::NetworkManager* network_manager,
40                      rtc::PacketSocketFactory* socket_factory,
41                      webrtc::TurnCustomizer* customizer = nullptr,
42                      RelayPortFactoryInterface* relay_port_factory = nullptr,
43                      const webrtc::FieldTrialsView* field_trials = nullptr);
44   BasicPortAllocator(
45       rtc::NetworkManager* network_manager,
46       std::unique_ptr<rtc::PacketSocketFactory> owned_socket_factory,
47       const webrtc::FieldTrialsView* field_trials = nullptr);
48   BasicPortAllocator(
49       rtc::NetworkManager* network_manager,
50       std::unique_ptr<rtc::PacketSocketFactory> owned_socket_factory,
51       const ServerAddresses& stun_servers,
52       const webrtc::FieldTrialsView* field_trials = nullptr);
53   BasicPortAllocator(rtc::NetworkManager* network_manager,
54                      rtc::PacketSocketFactory* socket_factory,
55                      const ServerAddresses& stun_servers,
56                      const webrtc::FieldTrialsView* field_trials = nullptr);
57   ~BasicPortAllocator() override;
58 
59   // Set to kDefaultNetworkIgnoreMask by default.
60   void SetNetworkIgnoreMask(int network_ignore_mask) override;
61   int GetNetworkIgnoreMask() const;
62 
network_manager()63   rtc::NetworkManager* network_manager() const {
64     CheckRunOnValidThreadIfInitialized();
65     return network_manager_;
66   }
67 
68   // If socket_factory() is set to NULL each PortAllocatorSession
69   // creates its own socket factory.
socket_factory()70   rtc::PacketSocketFactory* socket_factory() {
71     CheckRunOnValidThreadIfInitialized();
72     return socket_factory_.get();
73   }
74 
75   PortAllocatorSession* CreateSessionInternal(
76       absl::string_view content_name,
77       int component,
78       absl::string_view ice_ufrag,
79       absl::string_view ice_pwd) override;
80 
81   // Convenience method that adds a TURN server to the configuration.
82   void AddTurnServerForTesting(const RelayServerConfig& turn_server);
83 
relay_port_factory()84   RelayPortFactoryInterface* relay_port_factory() {
85     CheckRunOnValidThreadIfInitialized();
86     return relay_port_factory_;
87   }
88 
89   void SetVpnList(const std::vector<rtc::NetworkMask>& vpn_list) override;
90 
field_trials()91   const webrtc::FieldTrialsView* field_trials() const {
92     return field_trials_.get();
93   }
94 
95  private:
96   void OnIceRegathering(PortAllocatorSession* session,
97                         IceRegatheringReason reason);
98 
99   // This function makes sure that relay_port_factory_ is set properly.
100   void Init(RelayPortFactoryInterface* relay_port_factory);
101 
102   bool MdnsObfuscationEnabled() const override;
103 
104   webrtc::AlwaysValidPointer<const webrtc::FieldTrialsView,
105                              webrtc::FieldTrialBasedConfig>
106       field_trials_;
107   rtc::NetworkManager* network_manager_;
108   const webrtc::AlwaysValidPointerNoDefault<rtc::PacketSocketFactory>
109       socket_factory_;
110   int network_ignore_mask_ = rtc::kDefaultNetworkIgnoreMask;
111 
112   // This is the factory being used.
113   RelayPortFactoryInterface* relay_port_factory_;
114 
115   // This instance is created if caller does pass a factory.
116   std::unique_ptr<RelayPortFactoryInterface> default_relay_port_factory_;
117 };
118 
119 struct PortConfiguration;
120 class AllocationSequence;
121 
122 enum class SessionState {
123   GATHERING,  // Actively allocating ports and gathering candidates.
124   CLEARED,    // Current allocation process has been stopped but may start
125               // new ones.
126   STOPPED     // This session has completely stopped, no new allocation
127               // process will be started.
128 };
129 
130 // This class is thread-compatible and assumes it's created, operated upon and
131 // destroyed on the network thread.
132 class RTC_EXPORT BasicPortAllocatorSession : public PortAllocatorSession {
133  public:
134   BasicPortAllocatorSession(BasicPortAllocator* allocator,
135                             absl::string_view content_name,
136                             int component,
137                             absl::string_view ice_ufrag,
138                             absl::string_view ice_pwd);
139   ~BasicPortAllocatorSession() override;
140 
141   virtual BasicPortAllocator* allocator();
network_thread()142   rtc::Thread* network_thread() { return network_thread_; }
socket_factory()143   rtc::PacketSocketFactory* socket_factory() { return socket_factory_; }
144 
145   // If the new filter allows new types of candidates compared to the previous
146   // filter, gathered candidates that were discarded because of not matching the
147   // previous filter will be signaled if they match the new one.
148   //
149   // We do not perform any regathering since the port allocator flags decide
150   // the type of candidates to gather and the candidate filter only controls the
151   // signaling of candidates. As a result, with the candidate filter changed
152   // alone, all newly allowed candidates for signaling should already be
153   // gathered by the respective cricket::Port.
154   void SetCandidateFilter(uint32_t filter) override;
155   void StartGettingPorts() override;
156   void StopGettingPorts() override;
157   void ClearGettingPorts() override;
158   bool IsGettingPorts() override;
159   bool IsCleared() const override;
160   bool IsStopped() const override;
161   // These will all be cricket::Ports.
162   std::vector<PortInterface*> ReadyPorts() const override;
163   std::vector<Candidate> ReadyCandidates() const override;
164   bool CandidatesAllocationDone() const override;
165   void RegatherOnFailedNetworks() override;
166   void GetCandidateStatsFromReadyPorts(
167       CandidateStatsList* candidate_stats_list) const override;
168   void SetStunKeepaliveIntervalForReadyPorts(
169       const absl::optional<int>& stun_keepalive_interval) override;
170   void PruneAllPorts() override;
171   static std::vector<const rtc::Network*> SelectIPv6Networks(
172       std::vector<const rtc::Network*>& all_ipv6_networks,
173       int max_ipv6_networks);
174 
175  protected:
176   void UpdateIceParametersInternal() override;
177 
178   // Starts the process of getting the port configurations.
179   virtual void GetPortConfigurations();
180 
181   // Adds a port configuration that is now ready.  Once we have one for each
182   // network (or a timeout occurs), we will start allocating ports.
183   void ConfigReady(std::unique_ptr<PortConfiguration> config);
184   // TODO(bugs.webrtc.org/12840) Remove once unused in downstream projects.
185   ABSL_DEPRECATED(
186       "Use ConfigReady(std::unique_ptr<PortConfiguration>) instead!")
187   void ConfigReady(PortConfiguration* config);
188 
189  private:
190   class PortData {
191    public:
192     enum State {
193       STATE_INPROGRESS,  // Still gathering candidates.
194       STATE_COMPLETE,    // All candidates allocated and ready for process.
195       STATE_ERROR,       // Error in gathering candidates.
196       STATE_PRUNED       // Pruned by higher priority ports on the same network
197                          // interface. Only TURN ports may be pruned.
198     };
199 
PortData()200     PortData() {}
PortData(Port * port,AllocationSequence * seq)201     PortData(Port* port, AllocationSequence* seq)
202         : port_(port), sequence_(seq) {}
203 
port()204     Port* port() const { return port_; }
sequence()205     AllocationSequence* sequence() const { return sequence_; }
has_pairable_candidate()206     bool has_pairable_candidate() const { return has_pairable_candidate_; }
state()207     State state() const { return state_; }
complete()208     bool complete() const { return state_ == STATE_COMPLETE; }
error()209     bool error() const { return state_ == STATE_ERROR; }
pruned()210     bool pruned() const { return state_ == STATE_PRUNED; }
inprogress()211     bool inprogress() const { return state_ == STATE_INPROGRESS; }
212     // Returns true if this port is ready to be used.
ready()213     bool ready() const {
214       return has_pairable_candidate_ && state_ != STATE_ERROR &&
215              state_ != STATE_PRUNED;
216     }
217     // Sets the state to "PRUNED" and prunes the Port.
Prune()218     void Prune() {
219       state_ = STATE_PRUNED;
220       if (port()) {
221         port()->Prune();
222       }
223     }
set_has_pairable_candidate(bool has_pairable_candidate)224     void set_has_pairable_candidate(bool has_pairable_candidate) {
225       if (has_pairable_candidate) {
226         RTC_DCHECK(state_ == STATE_INPROGRESS);
227       }
228       has_pairable_candidate_ = has_pairable_candidate;
229     }
set_state(State state)230     void set_state(State state) {
231       RTC_DCHECK(state != STATE_ERROR || state_ == STATE_INPROGRESS);
232       state_ = state;
233     }
234 
235    private:
236     Port* port_ = nullptr;
237     AllocationSequence* sequence_ = nullptr;
238     bool has_pairable_candidate_ = false;
239     State state_ = STATE_INPROGRESS;
240   };
241 
242   void OnConfigReady(std::unique_ptr<PortConfiguration> config);
243   void OnConfigStop();
244   void AllocatePorts();
245   void OnAllocate(int allocation_epoch);
246   void DoAllocate(bool disable_equivalent_phases);
247   void OnNetworksChanged();
248   void OnAllocationSequenceObjectsCreated();
249   void DisableEquivalentPhases(const rtc::Network* network,
250                                PortConfiguration* config,
251                                uint32_t* flags);
252   void AddAllocatedPort(Port* port, AllocationSequence* seq);
253   void OnCandidateReady(Port* port, const Candidate& c);
254   void OnCandidateError(Port* port, const IceCandidateErrorEvent& event);
255   void OnPortComplete(Port* port);
256   void OnPortError(Port* port);
257   void OnProtocolEnabled(AllocationSequence* seq, ProtocolType proto);
258   void OnPortDestroyed(PortInterface* port);
259   void MaybeSignalCandidatesAllocationDone();
260   void OnPortAllocationComplete();
261   PortData* FindPort(Port* port);
262   std::vector<const rtc::Network*> GetNetworks();
263   std::vector<const rtc::Network*> GetFailedNetworks();
264   void Regather(const std::vector<const rtc::Network*>& networks,
265                 bool disable_equivalent_phases,
266                 IceRegatheringReason reason);
267 
268   bool CheckCandidateFilter(const Candidate& c) const;
269   bool CandidatePairable(const Candidate& c, const Port* port) const;
270 
271   std::vector<PortData*> GetUnprunedPorts(
272       const std::vector<const rtc::Network*>& networks);
273   // Prunes ports and signal the remote side to remove the candidates that
274   // were previously signaled from these ports.
275   void PrunePortsAndRemoveCandidates(
276       const std::vector<PortData*>& port_data_list);
277   // Gets filtered and sanitized candidates generated from a port and
278   // append to `candidates`.
279   void GetCandidatesFromPort(const PortData& data,
280                              std::vector<Candidate>* candidates) const;
281   Port* GetBestTurnPortForNetwork(absl::string_view network_name) const;
282   // Returns true if at least one TURN port is pruned.
283   bool PruneTurnPorts(Port* newly_pairable_turn_port);
284   bool PruneNewlyPairableTurnPort(PortData* newly_pairable_turn_port);
285 
286   BasicPortAllocator* allocator_;
287   rtc::Thread* network_thread_;
288   rtc::PacketSocketFactory* socket_factory_;
289   bool allocation_started_;
290   bool network_manager_started_;
291   bool allocation_sequences_created_;
292   std::vector<std::unique_ptr<PortConfiguration>> configs_;
293   std::vector<AllocationSequence*> sequences_;
294   std::vector<PortData> ports_;
295   std::vector<IceCandidateErrorEvent> candidate_error_events_;
296   uint32_t candidate_filter_ = CF_ALL;
297   // Policy on how to prune turn ports, taken from the port allocator.
298   webrtc::PortPrunePolicy turn_port_prune_policy_;
299   SessionState state_ = SessionState::CLEARED;
300   int allocation_epoch_ RTC_GUARDED_BY(network_thread_) = 0;
301   webrtc::ScopedTaskSafety network_safety_;
302 
303   friend class AllocationSequence;
304 };
305 
306 // Records configuration information useful in creating ports.
307 // TODO(deadbeef): Rename "relay" to "turn_server" in this struct.
308 struct RTC_EXPORT PortConfiguration {
309   // TODO(jiayl): remove `stun_address` when Chrome is updated.
310   rtc::SocketAddress stun_address;
311   ServerAddresses stun_servers;
312   std::string username;
313   std::string password;
314   bool use_turn_server_as_stun_server_disabled = false;
315 
316   typedef std::vector<RelayServerConfig> RelayList;
317   RelayList relays;
318 
319   PortConfiguration(const ServerAddresses& stun_servers,
320                     absl::string_view username,
321                     absl::string_view password,
322                     const webrtc::FieldTrialsView* field_trials = nullptr);
323 
324   // Returns addresses of both the explicitly configured STUN servers,
325   // and TURN servers that should be used as STUN servers.
326   ServerAddresses StunServers();
327 
328   // Adds another relay server, with the given ports and modifier, to the list.
329   void AddRelay(const RelayServerConfig& config);
330 
331   // Determines whether the given relay server supports the given protocol.
332   bool SupportsProtocol(const RelayServerConfig& relay,
333                         ProtocolType type) const;
334   bool SupportsProtocol(ProtocolType type) const;
335   // Helper method returns the server addresses for the matching RelayType and
336   // Protocol type.
337   ServerAddresses GetRelayServerAddresses(ProtocolType type) const;
338 };
339 
340 class UDPPort;
341 class TurnPort;
342 
343 // Performs the allocation of ports, in a sequenced (timed) manner, for a given
344 // network and IP address.
345 // This class is thread-compatible.
346 class AllocationSequence : public sigslot::has_slots<> {
347  public:
348   enum State {
349     kInit,       // Initial state.
350     kRunning,    // Started allocating ports.
351     kStopped,    // Stopped from running.
352     kCompleted,  // All ports are allocated.
353 
354     // kInit --> kRunning --> {kCompleted|kStopped}
355   };
356   // `port_allocation_complete_callback` is called when AllocationSequence is
357   // done with allocating ports. This signal is useful when port allocation
358   // fails which doesn't result in any candidates. Using this signal
359   // BasicPortAllocatorSession can send its candidate discovery conclusion
360   // signal. Without this signal, BasicPortAllocatorSession doesn't have any
361   // event to trigger signal. This can also be achieved by starting a timer in
362   // BPAS, but this is less deterministic.
363   AllocationSequence(BasicPortAllocatorSession* session,
364                      const rtc::Network* network,
365                      PortConfiguration* config,
366                      uint32_t flags,
367                      std::function<void()> port_allocation_complete_callback);
368   void Init();
369   void Clear();
370   void OnNetworkFailed();
371 
state()372   State state() const { return state_; }
network()373   const rtc::Network* network() const { return network_; }
374 
network_failed()375   bool network_failed() const { return network_failed_; }
set_network_failed()376   void set_network_failed() { network_failed_ = true; }
377 
378   // Disables the phases for a new sequence that this one already covers for an
379   // equivalent network setup.
380   void DisableEquivalentPhases(const rtc::Network* network,
381                                PortConfiguration* config,
382                                uint32_t* flags);
383 
384   // Starts and stops the sequence.  When started, it will continue allocating
385   // new ports on its own timed schedule.
386   void Start();
387   void Stop();
388 
389  private:
390   void CreateTurnPort(const RelayServerConfig& config, int relative_priority);
391 
392   typedef std::vector<ProtocolType> ProtocolList;
393 
394   void Process(int epoch);
IsFlagSet(uint32_t flag)395   bool IsFlagSet(uint32_t flag) { return ((flags_ & flag) != 0); }
396   void CreateUDPPorts();
397   void CreateTCPPorts();
398   void CreateStunPorts();
399   void CreateRelayPorts();
400 
401   void OnReadPacket(rtc::AsyncPacketSocket* socket,
402                     const char* data,
403                     size_t size,
404                     const rtc::SocketAddress& remote_addr,
405                     const int64_t& packet_time_us);
406 
407   void OnPortDestroyed(PortInterface* port);
408 
409   BasicPortAllocatorSession* session_;
410   bool network_failed_ = false;
411   const rtc::Network* network_;
412   // Compared with the new best IP in DisableEquivalentPhases.
413   rtc::IPAddress previous_best_ip_;
414   PortConfiguration* config_;
415   State state_;
416   uint32_t flags_;
417   ProtocolList protocols_;
418   std::unique_ptr<rtc::AsyncPacketSocket> udp_socket_;
419   // There will be only one udp port per AllocationSequence.
420   UDPPort* udp_port_;
421   std::vector<Port*> relay_ports_;
422   int phase_;
423   std::function<void()> port_allocation_complete_callback_;
424   // This counter is sampled and passed together with tasks when tasks are
425   // posted. If the sampled counter doesn't match `epoch_` on reception, the
426   // posted task is ignored.
427   int epoch_ = 0;
428   webrtc::ScopedTaskSafety safety_;
429 };
430 
431 }  // namespace cricket
432 
433 #endif  // P2P_CLIENT_BASIC_PORT_ALLOCATOR_H_
434