[Connection] Replace local index with a copy of the candidate.
This is to avoid using an index into a vector that's owned by Port.
Bug: none
Change-Id: Ifc67fcc24bcb04e55c7b963de6d29bb9541c1495
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/263643
Commit-Queue: Tomas Gunnarsson <tommi@webrtc.org>
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#37015}
diff --git a/p2p/base/connection.cc b/p2p/base/connection.cc
index b0097b5..876deb1 100644
--- a/p2p/base/connection.cc
+++ b/p2p/base/connection.cc
@@ -291,7 +291,7 @@
: 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 @@
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 @@
}
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::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 @@
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<int>(state_)]
<< "|" << SELECTED_STATE_ABBREV[selected_] << "|" << remote_nomination_
@@ -1504,12 +1515,12 @@
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 @@
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 @@
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 3e8cffb..f0850ab 100644
--- a/p2p/base/connection.h
+++ b/p2p/base/connection.h
@@ -15,6 +15,7 @@
#include <string>
#include <vector>
+#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "api/candidate.h"
#include "api/transport/stun.h"
@@ -202,6 +203,10 @@
// 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 @@
// Check if we sent `val` pings without receving a response.
bool TooManyOutstandingPings(const absl::optional<int>& 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 @@
webrtc::TaskQueueBase* const network_thread_;
const uint32_t id_;
rtc::WeakPtr<Port> 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 59c344b..0d76614 100644
--- a/p2p/base/port.cc
+++ b/p2p/base/port.cc
@@ -239,16 +239,23 @@
}
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<Candidate>& Port::Candidates() const {
@@ -274,6 +281,7 @@
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 @@
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 @@
}
}
-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 @@
// 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 @@
<< ". 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 65560fe..dd7b3e3 100644
--- a/p2p/base/port.h
+++ b/p2p/base/port.h
@@ -265,8 +265,8 @@
// 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 @@
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 @@
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 @@
// username_fragment().
std::string ice_username_fragment_;
std::string password_;
- std::vector<Candidate> candidates_;
+ std::vector<Candidate> candidates_ RTC_GUARDED_BY(thread_);
AddressMap connections_;
int timeout_delay_;
bool enable_port_packets_;
@@ -508,7 +508,7 @@
bool MaybeObfuscateAddress(Candidate* c,
const std::string& type,
- bool is_final);
+ bool is_final) RTC_RUN_ON(thread_);
friend class Connection;
webrtc::CallbackList<PortInterface*> port_destroyed_callback_list_;