From 36d22d82aa202bb199967e9512281e9a53db42c9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 21:33:14 +0200 Subject: Adding upstream version 115.7.0esr. Signed-off-by: Daniel Baumann --- .../libwebrtc/p2p/client/basic_port_allocator.h | 433 +++++++++++++++++++++ 1 file changed, 433 insertions(+) create mode 100644 third_party/libwebrtc/p2p/client/basic_port_allocator.h (limited to 'third_party/libwebrtc/p2p/client/basic_port_allocator.h') diff --git a/third_party/libwebrtc/p2p/client/basic_port_allocator.h b/third_party/libwebrtc/p2p/client/basic_port_allocator.h new file mode 100644 index 0000000000..38c3835ee8 --- /dev/null +++ b/third_party/libwebrtc/p2p/client/basic_port_allocator.h @@ -0,0 +1,433 @@ +/* + * Copyright 2004 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef P2P_CLIENT_BASIC_PORT_ALLOCATOR_H_ +#define P2P_CLIENT_BASIC_PORT_ALLOCATOR_H_ + +#include +#include +#include + +#include "absl/strings/string_view.h" +#include "api/field_trials_view.h" +#include "api/task_queue/pending_task_safety_flag.h" +#include "api/turn_customizer.h" +#include "p2p/base/port_allocator.h" +#include "p2p/client/relay_port_factory_interface.h" +#include "p2p/client/turn_port_factory.h" +#include "rtc_base/checks.h" +#include "rtc_base/memory/always_valid_pointer.h" +#include "rtc_base/network.h" +#include "rtc_base/system/rtc_export.h" +#include "rtc_base/thread.h" +#include "rtc_base/thread_annotations.h" + +namespace cricket { + +class RTC_EXPORT BasicPortAllocator : public PortAllocator { + public: + // The NetworkManager is a mandatory argument. The other arguments are + // optional. All pointers are owned by caller and must have a life time + // that exceeds that of BasicPortAllocator. + BasicPortAllocator(rtc::NetworkManager* network_manager, + rtc::PacketSocketFactory* socket_factory, + webrtc::TurnCustomizer* customizer = nullptr, + RelayPortFactoryInterface* relay_port_factory = nullptr, + const webrtc::FieldTrialsView* field_trials = nullptr); + BasicPortAllocator( + rtc::NetworkManager* network_manager, + std::unique_ptr owned_socket_factory, + const webrtc::FieldTrialsView* field_trials = nullptr); + BasicPortAllocator( + rtc::NetworkManager* network_manager, + std::unique_ptr owned_socket_factory, + const ServerAddresses& stun_servers, + const webrtc::FieldTrialsView* field_trials = nullptr); + BasicPortAllocator(rtc::NetworkManager* network_manager, + rtc::PacketSocketFactory* socket_factory, + const ServerAddresses& stun_servers, + const webrtc::FieldTrialsView* field_trials = nullptr); + ~BasicPortAllocator() override; + + // Set to kDefaultNetworkIgnoreMask by default. + void SetNetworkIgnoreMask(int network_ignore_mask) override; + int GetNetworkIgnoreMask() const; + + rtc::NetworkManager* network_manager() const { + CheckRunOnValidThreadIfInitialized(); + return network_manager_; + } + + // If socket_factory() is set to NULL each PortAllocatorSession + // creates its own socket factory. + rtc::PacketSocketFactory* socket_factory() { + CheckRunOnValidThreadIfInitialized(); + return socket_factory_.get(); + } + + PortAllocatorSession* CreateSessionInternal( + absl::string_view content_name, + int component, + absl::string_view ice_ufrag, + absl::string_view ice_pwd) override; + + // Convenience method that adds a TURN server to the configuration. + void AddTurnServerForTesting(const RelayServerConfig& turn_server); + + RelayPortFactoryInterface* relay_port_factory() { + CheckRunOnValidThreadIfInitialized(); + return relay_port_factory_; + } + + void SetVpnList(const std::vector& vpn_list) override; + + const webrtc::FieldTrialsView* field_trials() const { + return field_trials_.get(); + } + + private: + void OnIceRegathering(PortAllocatorSession* session, + IceRegatheringReason reason); + + // This function makes sure that relay_port_factory_ is set properly. + void Init(RelayPortFactoryInterface* relay_port_factory); + + bool MdnsObfuscationEnabled() const override; + + webrtc::AlwaysValidPointer + field_trials_; + rtc::NetworkManager* network_manager_; + const webrtc::AlwaysValidPointerNoDefault + socket_factory_; + int network_ignore_mask_ = rtc::kDefaultNetworkIgnoreMask; + + // This is the factory being used. + RelayPortFactoryInterface* relay_port_factory_; + + // This instance is created if caller does pass a factory. + std::unique_ptr default_relay_port_factory_; +}; + +struct PortConfiguration; +class AllocationSequence; + +enum class SessionState { + GATHERING, // Actively allocating ports and gathering candidates. + CLEARED, // Current allocation process has been stopped but may start + // new ones. + STOPPED // This session has completely stopped, no new allocation + // process will be started. +}; + +// This class is thread-compatible and assumes it's created, operated upon and +// destroyed on the network thread. +class RTC_EXPORT BasicPortAllocatorSession : public PortAllocatorSession { + public: + BasicPortAllocatorSession(BasicPortAllocator* allocator, + absl::string_view content_name, + int component, + absl::string_view ice_ufrag, + absl::string_view ice_pwd); + ~BasicPortAllocatorSession() override; + + virtual BasicPortAllocator* allocator(); + rtc::Thread* network_thread() { return network_thread_; } + rtc::PacketSocketFactory* socket_factory() { return socket_factory_; } + + // If the new filter allows new types of candidates compared to the previous + // filter, gathered candidates that were discarded because of not matching the + // previous filter will be signaled if they match the new one. + // + // We do not perform any regathering since the port allocator flags decide + // the type of candidates to gather and the candidate filter only controls the + // signaling of candidates. As a result, with the candidate filter changed + // alone, all newly allowed candidates for signaling should already be + // gathered by the respective cricket::Port. + void SetCandidateFilter(uint32_t filter) override; + void StartGettingPorts() override; + void StopGettingPorts() override; + void ClearGettingPorts() override; + bool IsGettingPorts() override; + bool IsCleared() const override; + bool IsStopped() const override; + // These will all be cricket::Ports. + std::vector ReadyPorts() const override; + std::vector ReadyCandidates() const override; + bool CandidatesAllocationDone() const override; + void RegatherOnFailedNetworks() override; + void GetCandidateStatsFromReadyPorts( + CandidateStatsList* candidate_stats_list) const override; + void SetStunKeepaliveIntervalForReadyPorts( + const absl::optional& stun_keepalive_interval) override; + void PruneAllPorts() override; + static std::vector SelectIPv6Networks( + std::vector& all_ipv6_networks, + int max_ipv6_networks); + + protected: + void UpdateIceParametersInternal() override; + + // Starts the process of getting the port configurations. + virtual void GetPortConfigurations(); + + // Adds a port configuration that is now ready. Once we have one for each + // network (or a timeout occurs), we will start allocating ports. + void ConfigReady(std::unique_ptr config); + // TODO(bugs.webrtc.org/12840) Remove once unused in downstream projects. + ABSL_DEPRECATED( + "Use ConfigReady(std::unique_ptr) instead!") + void ConfigReady(PortConfiguration* config); + + private: + class PortData { + public: + enum State { + STATE_INPROGRESS, // Still gathering candidates. + STATE_COMPLETE, // All candidates allocated and ready for process. + STATE_ERROR, // Error in gathering candidates. + STATE_PRUNED // Pruned by higher priority ports on the same network + // interface. Only TURN ports may be pruned. + }; + + PortData() {} + PortData(Port* port, AllocationSequence* seq) + : port_(port), sequence_(seq) {} + + Port* port() const { return port_; } + AllocationSequence* sequence() const { return sequence_; } + bool has_pairable_candidate() const { return has_pairable_candidate_; } + State state() const { return state_; } + bool complete() const { return state_ == STATE_COMPLETE; } + bool error() const { return state_ == STATE_ERROR; } + bool pruned() const { return state_ == STATE_PRUNED; } + bool inprogress() const { return state_ == STATE_INPROGRESS; } + // Returns true if this port is ready to be used. + bool ready() const { + return has_pairable_candidate_ && state_ != STATE_ERROR && + state_ != STATE_PRUNED; + } + // Sets the state to "PRUNED" and prunes the Port. + void Prune() { + state_ = STATE_PRUNED; + if (port()) { + port()->Prune(); + } + } + void set_has_pairable_candidate(bool has_pairable_candidate) { + if (has_pairable_candidate) { + RTC_DCHECK(state_ == STATE_INPROGRESS); + } + has_pairable_candidate_ = has_pairable_candidate; + } + void set_state(State state) { + RTC_DCHECK(state != STATE_ERROR || state_ == STATE_INPROGRESS); + state_ = state; + } + + private: + Port* port_ = nullptr; + AllocationSequence* sequence_ = nullptr; + bool has_pairable_candidate_ = false; + State state_ = STATE_INPROGRESS; + }; + + void OnConfigReady(std::unique_ptr config); + void OnConfigStop(); + void AllocatePorts(); + void OnAllocate(int allocation_epoch); + void DoAllocate(bool disable_equivalent_phases); + void OnNetworksChanged(); + void OnAllocationSequenceObjectsCreated(); + void DisableEquivalentPhases(const rtc::Network* network, + PortConfiguration* config, + uint32_t* flags); + void AddAllocatedPort(Port* port, AllocationSequence* seq); + void OnCandidateReady(Port* port, const Candidate& c); + void OnCandidateError(Port* port, const IceCandidateErrorEvent& event); + void OnPortComplete(Port* port); + void OnPortError(Port* port); + void OnProtocolEnabled(AllocationSequence* seq, ProtocolType proto); + void OnPortDestroyed(PortInterface* port); + void MaybeSignalCandidatesAllocationDone(); + void OnPortAllocationComplete(); + PortData* FindPort(Port* port); + std::vector GetNetworks(); + std::vector GetFailedNetworks(); + void Regather(const std::vector& networks, + bool disable_equivalent_phases, + IceRegatheringReason reason); + + bool CheckCandidateFilter(const Candidate& c) const; + bool CandidatePairable(const Candidate& c, const Port* port) const; + + std::vector GetUnprunedPorts( + const std::vector& networks); + // Prunes ports and signal the remote side to remove the candidates that + // were previously signaled from these ports. + void PrunePortsAndRemoveCandidates( + const std::vector& port_data_list); + // Gets filtered and sanitized candidates generated from a port and + // append to `candidates`. + void GetCandidatesFromPort(const PortData& data, + std::vector* candidates) const; + Port* GetBestTurnPortForNetwork(absl::string_view network_name) const; + // Returns true if at least one TURN port is pruned. + bool PruneTurnPorts(Port* newly_pairable_turn_port); + bool PruneNewlyPairableTurnPort(PortData* newly_pairable_turn_port); + + BasicPortAllocator* allocator_; + rtc::Thread* network_thread_; + rtc::PacketSocketFactory* socket_factory_; + bool allocation_started_; + bool network_manager_started_; + bool allocation_sequences_created_; + std::vector> configs_; + std::vector sequences_; + std::vector ports_; + std::vector candidate_error_events_; + uint32_t candidate_filter_ = CF_ALL; + // Policy on how to prune turn ports, taken from the port allocator. + webrtc::PortPrunePolicy turn_port_prune_policy_; + SessionState state_ = SessionState::CLEARED; + int allocation_epoch_ RTC_GUARDED_BY(network_thread_) = 0; + webrtc::ScopedTaskSafety network_safety_; + + friend class AllocationSequence; +}; + +// Records configuration information useful in creating ports. +// TODO(deadbeef): Rename "relay" to "turn_server" in this struct. +struct RTC_EXPORT PortConfiguration { + // TODO(jiayl): remove `stun_address` when Chrome is updated. + rtc::SocketAddress stun_address; + ServerAddresses stun_servers; + std::string username; + std::string password; + bool use_turn_server_as_stun_server_disabled = false; + + typedef std::vector RelayList; + RelayList relays; + + PortConfiguration(const ServerAddresses& stun_servers, + absl::string_view username, + absl::string_view password, + const webrtc::FieldTrialsView* field_trials = nullptr); + + // Returns addresses of both the explicitly configured STUN servers, + // and TURN servers that should be used as STUN servers. + ServerAddresses StunServers(); + + // Adds another relay server, with the given ports and modifier, to the list. + void AddRelay(const RelayServerConfig& config); + + // Determines whether the given relay server supports the given protocol. + bool SupportsProtocol(const RelayServerConfig& relay, + ProtocolType type) const; + bool SupportsProtocol(ProtocolType type) const; + // Helper method returns the server addresses for the matching RelayType and + // Protocol type. + ServerAddresses GetRelayServerAddresses(ProtocolType type) const; +}; + +class UDPPort; +class TurnPort; + +// Performs the allocation of ports, in a sequenced (timed) manner, for a given +// network and IP address. +// This class is thread-compatible. +class AllocationSequence : public sigslot::has_slots<> { + public: + enum State { + kInit, // Initial state. + kRunning, // Started allocating ports. + kStopped, // Stopped from running. + kCompleted, // All ports are allocated. + + // kInit --> kRunning --> {kCompleted|kStopped} + }; + // `port_allocation_complete_callback` is called when AllocationSequence is + // done with allocating ports. This signal is useful when port allocation + // fails which doesn't result in any candidates. Using this signal + // BasicPortAllocatorSession can send its candidate discovery conclusion + // signal. Without this signal, BasicPortAllocatorSession doesn't have any + // event to trigger signal. This can also be achieved by starting a timer in + // BPAS, but this is less deterministic. + AllocationSequence(BasicPortAllocatorSession* session, + const rtc::Network* network, + PortConfiguration* config, + uint32_t flags, + std::function port_allocation_complete_callback); + void Init(); + void Clear(); + void OnNetworkFailed(); + + State state() const { return state_; } + const rtc::Network* network() const { return network_; } + + bool network_failed() const { return network_failed_; } + void set_network_failed() { network_failed_ = true; } + + // Disables the phases for a new sequence that this one already covers for an + // equivalent network setup. + void DisableEquivalentPhases(const rtc::Network* network, + PortConfiguration* config, + uint32_t* flags); + + // Starts and stops the sequence. When started, it will continue allocating + // new ports on its own timed schedule. + void Start(); + void Stop(); + + private: + void CreateTurnPort(const RelayServerConfig& config, int relative_priority); + + typedef std::vector ProtocolList; + + void Process(int epoch); + bool IsFlagSet(uint32_t flag) { return ((flags_ & flag) != 0); } + void CreateUDPPorts(); + void CreateTCPPorts(); + void CreateStunPorts(); + void CreateRelayPorts(); + + void OnReadPacket(rtc::AsyncPacketSocket* socket, + const char* data, + size_t size, + const rtc::SocketAddress& remote_addr, + const int64_t& packet_time_us); + + void OnPortDestroyed(PortInterface* port); + + BasicPortAllocatorSession* session_; + bool network_failed_ = false; + const rtc::Network* network_; + // Compared with the new best IP in DisableEquivalentPhases. + rtc::IPAddress previous_best_ip_; + PortConfiguration* config_; + State state_; + uint32_t flags_; + ProtocolList protocols_; + std::unique_ptr udp_socket_; + // There will be only one udp port per AllocationSequence. + UDPPort* udp_port_; + std::vector relay_ports_; + int phase_; + std::function port_allocation_complete_callback_; + // This counter is sampled and passed together with tasks when tasks are + // posted. If the sampled counter doesn't match `epoch_` on reception, the + // posted task is ignored. + int epoch_ = 0; + webrtc::ScopedTaskSafety safety_; +}; + +} // namespace cricket + +#endif // P2P_CLIENT_BASIC_PORT_ALLOCATOR_H_ -- cgit v1.2.3