diff --git a/p2p/base/connection.cc b/p2p/base/connection.cc index b0097b569b..876deb1b37 100644 --- a/p2p/base/connection.cc +++ b/p2p/base/connection.cc @@ -291,7 +291,7 @@ Connection::Connection(rtc::WeakPtr port, : network_thread_(port->thread()), id_(rtc::CreateRandomId()), port_(std::move(port)), - local_candidate_index_(index), + local_candidate_(port_->Candidates()[index]), remote_candidate_(remote_candidate), recv_rate_tracker_(100, 10u), send_rate_tracker_(100, 10u), @@ -328,8 +328,7 @@ webrtc::TaskQueueBase* Connection::network_thread() const { const Candidate& Connection::local_candidate() const { RTC_DCHECK_RUN_ON(network_thread_); - RTC_DCHECK(local_candidate_index_ < port_->Candidates().size()); - return port_->Candidates()[local_candidate_index_]; + return local_candidate_; } const Candidate& Connection::remote_candidate() const { @@ -345,6 +344,9 @@ int Connection::generation() const { } uint64_t Connection::priority() const { + if (!port_) + return 0; + uint64_t priority = 0; // RFC 5245 - 5.7.2. Computing Pair Priority and Ordering Pairs // Let G be the priority for the candidate provided by the controlling @@ -968,6 +970,15 @@ void Connection::UpdateState(int64_t now) { } } +void Connection::UpdateLocalIceParameters(int component, + absl::string_view username_fragment, + absl::string_view password) { + RTC_DCHECK_RUN_ON(network_thread_); + local_candidate_.set_component(component); + local_candidate_.set_username(username_fragment); + local_candidate_.set_password(password); +} + int64_t Connection::last_ping_sent() const { RTC_DCHECK_RUN_ON(network_thread_); return last_ping_sent_; @@ -1216,23 +1227,23 @@ std::string Connection::ToString() const { ss << "Conn[" << ToDebugId(); if (!port_) { - // No content name for pending delete, so temporarily substitute the name - // with a hash (rhyming with trash) and don't include any information about - // the network or candidates, state that belongs to a potentially deleted - // `port_`. - ss << ":#:"; + // No content or network names for pending delete. Temporarily substitute + // the names with a hash (rhyming with trash). + ss << ":#:#:"; } else { - const Candidate& local = local_candidate(); - const Candidate& remote = remote_candidate(); ss << ":" << port_->content_name() << ":" << port_->Network()->ToString() - << ":" << local.id() << ":" << local.component() << ":" - << local.generation() << ":" << local.type() << ":" << local.protocol() - << ":" << local.address().ToSensitiveString() << "->" << remote.id() - << ":" << remote.component() << ":" << remote.priority() << ":" - << remote.type() << ":" << remote.protocol() << ":" - << remote.address().ToSensitiveString() << "|"; + << ":"; } + const Candidate& local = local_candidate(); + const Candidate& remote = remote_candidate(); + ss << local.id() << ":" << local.component() << ":" << local.generation() + << ":" << local.type() << ":" << local.protocol() << ":" + << local.address().ToSensitiveString() << "->" << remote.id() << ":" + << remote.component() << ":" << remote.priority() << ":" << remote.type() + << ":" << remote.protocol() << ":" << remote.address().ToSensitiveString() + << "|"; + ss << CONNECT_STATE_ABBREV[connected_] << RECEIVE_STATE_ABBREV[receiving_] << WRITE_STATE_ABBREV[write_state_] << ICESTATE[static_cast(state_)] << "|" << SELECTED_STATE_ABBREV[selected_] << "|" << remote_nomination_ @@ -1504,12 +1515,12 @@ void Connection::MaybeUpdateLocalCandidate(ConnectionRequest* request, return; } - for (size_t i = 0; i < port_->Candidates().size(); ++i) { - if (port_->Candidates()[i].address() == addr->GetAddress()) { - if (local_candidate_index_ != i) { + for (const Candidate& candidate : port_->Candidates()) { + if (candidate.address() == addr->GetAddress()) { + if (local_candidate_ != candidate) { RTC_LOG(LS_INFO) << ToString() << ": Updating local candidate type to srflx."; - local_candidate_index_ = i; + local_candidate_ = candidate; // SignalStateChange to force a re-sort in P2PTransportChannel as this // Connection's local candidate has changed. SignalStateChange(this); @@ -1533,19 +1544,20 @@ void Connection::MaybeUpdateLocalCandidate(ConnectionRequest* request, std::string id = rtc::CreateRandomString(8); // Create a peer-reflexive candidate based on the local candidate. - Candidate new_local_candidate(local_candidate()); - new_local_candidate.set_id(id); - new_local_candidate.set_type(PRFLX_PORT_TYPE); - new_local_candidate.set_address(addr->GetAddress()); - new_local_candidate.set_priority(priority); - new_local_candidate.set_related_address(local_candidate().address()); - new_local_candidate.set_foundation(Port::ComputeFoundation( - PRFLX_PORT_TYPE, local_candidate().protocol(), - local_candidate().relay_protocol(), local_candidate().address())); + local_candidate_.set_id(id); + local_candidate_.set_type(PRFLX_PORT_TYPE); + // Set the related address and foundation attributes before changing the + // address. + local_candidate_.set_related_address(local_candidate_.address()); + local_candidate_.set_foundation(Port::ComputeFoundation( + PRFLX_PORT_TYPE, local_candidate_.protocol(), + local_candidate_.relay_protocol(), local_candidate_.address())); + local_candidate_.set_priority(priority); + local_candidate_.set_address(addr->GetAddress()); // Change the local candidate of this Connection to the new prflx candidate. RTC_LOG(LS_INFO) << ToString() << ": Updating local candidate type to prflx."; - local_candidate_index_ = port_->AddPrflxCandidate(new_local_candidate); + port_->AddPrflxCandidate(local_candidate_); // SignalStateChange to force a re-sort in P2PTransportChannel as this // Connection's local candidate has changed. @@ -1580,6 +1592,20 @@ bool Connection::TooManyOutstandingPings( return true; } +void Connection::SetLocalCandidateNetworkCost(uint16_t cost) { + RTC_DCHECK_RUN_ON(network_thread_); + + if (cost == local_candidate_.network_cost()) + return; + + local_candidate_.set_network_cost(cost); + + // Network cost change will affect the connection selection criteria. + // Signal the connection state change to force a re-sort in + // P2PTransportChannel. + SignalStateChange(this); +} + // RTC_RUN_ON(network_thread_). bool Connection::ShouldSendGoogPing(const StunMessage* message) { if (remote_support_goog_ping_ == true && cached_stun_binding_ && diff --git a/p2p/base/connection.h b/p2p/base/connection.h index 3e8cffbfda..f0850abf65 100644 --- a/p2p/base/connection.h +++ b/p2p/base/connection.h @@ -15,6 +15,7 @@ #include #include +#include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "api/candidate.h" #include "api/transport/stun.h" @@ -202,6 +203,10 @@ class Connection : public CandidatePairInterface { // the current time, which is compared against various timeouts. void UpdateState(int64_t now); + void UpdateLocalIceParameters(int component, + absl::string_view username_fragment, + absl::string_view password); + // Called when this connection should try checking writability again. int64_t last_ping_sent() const; void Ping(int64_t now); @@ -284,6 +289,9 @@ class Connection : public CandidatePairInterface { // Check if we sent `val` pings without receving a response. bool TooManyOutstandingPings(const absl::optional& val) const; + // Called by Port when the network cost changes. + void SetLocalCandidateNetworkCost(uint16_t cost); + void SetIceFieldTrials(const IceFieldTrials* field_trials); const rtc::EventBasedExponentialMovingAverage& GetRttEstimate() const { return rtt_estimate_; @@ -357,7 +365,7 @@ class Connection : public CandidatePairInterface { webrtc::TaskQueueBase* const network_thread_; const uint32_t id_; rtc::WeakPtr port_; - size_t local_candidate_index_ RTC_GUARDED_BY(network_thread_); + Candidate local_candidate_ RTC_GUARDED_BY(network_thread_); Candidate remote_candidate_; ConnectionInfo stats_; diff --git a/p2p/base/port.cc b/p2p/base/port.cc index 59c344bacd..0d76614857 100644 --- a/p2p/base/port.cc +++ b/p2p/base/port.cc @@ -239,16 +239,23 @@ bool Port::SharedSocket() const { } void Port::SetIceParameters(int component, - const std::string& username_fragment, - const std::string& password) { + absl::string_view username_fragment, + absl::string_view password) { + RTC_DCHECK_RUN_ON(thread_); component_ = component; - ice_username_fragment_ = username_fragment; - password_ = password; + ice_username_fragment_ = std::string(username_fragment); + password_ = std::string(password); for (Candidate& c : candidates_) { c.set_component(component); c.set_username(username_fragment); c.set_password(password); } + + // In case any connections exist make sure we update them too. + for (auto& [unused, connection] : connections_) { + connection->UpdateLocalIceParameters(component, username_fragment, + password); + } } const std::vector& Port::Candidates() const { @@ -274,6 +281,7 @@ void Port::AddAddress(const rtc::SocketAddress& address, uint32_t relay_preference, const std::string& url, bool is_final) { + RTC_DCHECK_RUN_ON(thread_); if (protocol == TCP_PROTOCOL_NAME && type == LOCAL_PORT_TYPE) { RTC_DCHECK(!tcptype.empty()); } @@ -325,6 +333,7 @@ bool Port::MaybeObfuscateAddress(Candidate* c, copy.set_address(hostname_address); copy.set_related_address(rtc::SocketAddress()); if (weak_ptr != nullptr) { + RTC_DCHECK_RUN_ON(weak_ptr->thread_); weak_ptr->set_mdns_name_registration_status( MdnsNameRegistrationStatus::kCompleted); weak_ptr->FinishAddingAddress(copy, is_final); @@ -429,9 +438,9 @@ void Port::OnReadyToSend() { } } -size_t Port::AddPrflxCandidate(const Candidate& local) { +void Port::AddPrflxCandidate(const Candidate& local) { + RTC_DCHECK_RUN_ON(thread_); candidates_.push_back(local); - return (candidates_.size() - 1); } bool Port::GetStunMessage(const char* data, @@ -891,6 +900,7 @@ std::string Port::ToString() const { // TODO(honghaiz): Make the network cost configurable from user setting. void Port::UpdateNetworkCost() { + RTC_DCHECK_RUN_ON(thread_); uint16_t new_cost = network_->GetCost(*field_trials_); if (network_cost_ == new_cost) { return; @@ -901,16 +911,11 @@ void Port::UpdateNetworkCost() { << ". Number of connections created: " << connections_.size(); network_cost_ = new_cost; - for (cricket::Candidate& candidate : candidates_) { + for (cricket::Candidate& candidate : candidates_) candidate.set_network_cost(network_cost_); - } - // Network cost change will affect the connection selection criteria. - // Signal the connection state change on each connection to force a - // re-sort in P2PTransportChannel. - for (const auto& kv : connections_) { - Connection* conn = kv.second; - conn->SignalStateChange(conn); - } + + for (auto& [unused, connection] : connections_) + connection->SetLocalCandidateNetworkCost(network_cost_); } void Port::EnablePortPackets() { diff --git a/p2p/base/port.h b/p2p/base/port.h index 65560fe196..dd7b3e3c02 100644 --- a/p2p/base/port.h +++ b/p2p/base/port.h @@ -265,8 +265,8 @@ class Port : public PortInterface, // PortAllocatorSession, and is now being assigned to an ICE transport. // Updates the information for candidates as well. void SetIceParameters(int component, - const std::string& username_fragment, - const std::string& password); + absl::string_view username_fragment, + absl::string_view password); // Fired when candidates are discovered by the port. When all candidates // are discovered that belong to port SignalAddressReady is fired. @@ -367,8 +367,7 @@ class Port : public PortInterface, void OnReadyToSend(); // Called when the Connection discovers a local peer reflexive candidate. - // Returns the index of the new local candidate. - size_t AddPrflxCandidate(const Candidate& local); + void AddPrflxCandidate(const Candidate& local); int16_t network_cost() const { return network_cost_; } @@ -406,7 +405,8 @@ class Port : public PortInterface, const std::string& url, bool is_final); - void FinishAddingAddress(const Candidate& c, bool is_final); + void FinishAddingAddress(const Candidate& c, bool is_final) + RTC_RUN_ON(thread_); virtual void PostAddAddress(bool is_final); @@ -481,7 +481,7 @@ class Port : public PortInterface, // username_fragment(). std::string ice_username_fragment_; std::string password_; - std::vector candidates_; + std::vector candidates_ RTC_GUARDED_BY(thread_); AddressMap connections_; int timeout_delay_; bool enable_port_packets_; @@ -508,7 +508,7 @@ class Port : public PortInterface, bool MaybeObfuscateAddress(Candidate* c, const std::string& type, - bool is_final); + bool is_final) RTC_RUN_ON(thread_); friend class Connection; webrtc::CallbackList port_destroyed_callback_list_;