Propagate content name to ports at construction time, add sanity checks
This sets the Port::content_name (i.e. mid) at construction time and
removes one call to `set_content_name()`. One call to
`set_content_name()` still remains, which is when sessions are pooled
and reused. Because of that, Port::content_name_ can still not be const.
However, this CL improves constness in P2PTransportChannel and adds
several RTC_DCHECKs to ensure the correctness of the content_name field,
including when it belongs to a pooled and not-pooled sessions.
Bug: none
Change-Id: I9730c2ff13efb33d6ad43f9ca152d8fe93929550
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/407281
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Commit-Queue: Tomas Gunnarsson <tommi@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#45513}
diff --git a/p2p/base/connection.cc b/p2p/base/connection.cc
index 1afd41b..577e4b0 100644
--- a/p2p/base/connection.cc
+++ b/p2p/base/connection.cc
@@ -287,16 +287,19 @@
}
const Network* Connection::network() const {
+ RTC_DCHECK_RUN_ON(network_thread_);
RTC_DCHECK(port_) << ToDebugId() << ": port_ null in network()";
return port()->Network();
}
int Connection::generation() const {
+ RTC_DCHECK_RUN_ON(network_thread_);
RTC_DCHECK(port_) << ToDebugId() << ": port_ null in generation()";
return port()->generation();
}
uint64_t Connection::priority() const {
+ RTC_DCHECK_RUN_ON(network_thread_);
RTC_DCHECK(port_) << ToDebugId() << ": port_ null in priority()";
if (!port_)
return 0;
@@ -1391,6 +1394,7 @@
}
uint32_t Connection::ComputeNetworkCost() const {
+ RTC_DCHECK_RUN_ON(network_thread_);
// TODO(honghaiz): Will add rtt as part of the network cost.
RTC_DCHECK(port_) << ToDebugId() << ": port_ null in ComputeNetworkCost()";
return port()->network_cost() + remote_candidate_.network_cost();
diff --git a/p2p/base/connection.h b/p2p/base/connection.h
index 55de3f9..1cb0c20 100644
--- a/p2p/base/connection.h
+++ b/p2p/base/connection.h
@@ -117,7 +117,10 @@
bool connected() const;
bool weak() const;
bool active() const;
- bool pending_delete() const { return !port_; }
+ bool pending_delete() const {
+ RTC_DCHECK_RUN_ON(network_thread_);
+ return !port_;
+ }
// A connection is dead if it can be safely deleted.
bool dead(Timestamp now) const;
@@ -391,8 +394,14 @@
void SendResponseMessage(const StunMessage& response);
// An accessor for unit tests.
- PortInterface* PortForTest() { return port_.get(); }
- const PortInterface* PortForTest() const { return port_.get(); }
+ PortInterface* PortForTest() {
+ RTC_DCHECK_RUN_ON(network_thread_);
+ return port_.get();
+ }
+ const PortInterface* PortForTest() const {
+ RTC_DCHECK_RUN_ON(network_thread_);
+ return port_.get();
+ }
std::unique_ptr<IceMessage> BuildPingRequestForTest() {
RTC_DCHECK_RUN_ON(network_thread_);
@@ -478,7 +487,10 @@
void set_connected(bool value);
// The local port where this connection sends and receives packets.
- PortInterface* port() { return port_.get(); }
+ PortInterface* port() {
+ RTC_DCHECK_RUN_ON(network_thread_);
+ return port_.get();
+ }
const Environment& env() { return env_; }
ConnectionInfo& mutable_stats() { return stats_; }
@@ -511,7 +523,7 @@
// TODO(tommi): This ^^^ should be fixed.
TaskQueueBase* const network_thread_;
const uint32_t id_;
- WeakPtr<PortInterface> port_;
+ WeakPtr<PortInterface> port_ RTC_GUARDED_BY(network_thread_);
Candidate local_candidate_ RTC_GUARDED_BY(network_thread_);
Candidate remote_candidate_;
diff --git a/p2p/base/p2p_transport_channel.cc b/p2p/base/p2p_transport_channel.cc
index 82d854f..db6c987 100644
--- a/p2p/base/p2p_transport_channel.cc
+++ b/p2p/base/p2p_transport_channel.cc
@@ -866,17 +866,16 @@
ice_parameters_.ufrag,
ice_parameters_.pwd);
if (pooled_session) {
+ PortAllocatorSession* raw_session = pooled_session.get();
AddAllocatorSession(std::move(pooled_session));
- PortAllocatorSession* raw_pooled_session =
- allocator_sessions_.back().get();
+ RTC_DCHECK_EQ(raw_session, allocator_sessions_.back().get());
// Process the pooled session's existing candidates/ports, if they exist.
- OnCandidatesReady(raw_pooled_session,
- raw_pooled_session->ReadyCandidates());
- for (PortInterface* port : allocator_sessions_.back()->ReadyPorts()) {
- OnPortReady(raw_pooled_session, port);
+ OnCandidatesReady(raw_session, raw_session->ReadyCandidates());
+ for (PortInterface* port : raw_session->ReadyPorts()) {
+ OnPortReady(raw_session, port);
}
- if (allocator_sessions_.back()->CandidatesAllocationDone()) {
- OnCandidatesAllocationDone(raw_pooled_session);
+ if (raw_session->CandidatesAllocationDone()) {
+ OnCandidatesAllocationDone(raw_session);
}
} else {
AddAllocatorSession(allocator_->CreateSession(
diff --git a/p2p/base/p2p_transport_channel.h b/p2p/base/p2p_transport_channel.h
index 7f087ba..8ce03f6 100644
--- a/p2p/base/p2p_transport_channel.h
+++ b/p2p/base/p2p_transport_channel.h
@@ -443,9 +443,9 @@
void GoogDeltaAckReceived(RTCErrorOr<const StunUInt64Attribute*>);
const Environment env_;
- std::string transport_name_ RTC_GUARDED_BY(network_thread_);
+ const std::string transport_name_ RTC_GUARDED_BY(network_thread_);
int component_ RTC_GUARDED_BY(network_thread_);
- PortAllocator* allocator_ RTC_GUARDED_BY(network_thread_);
+ PortAllocator* const allocator_ RTC_GUARDED_BY(network_thread_);
AsyncDnsResolverFactoryInterface* const async_dns_resolver_factory_
RTC_GUARDED_BY(network_thread_);
const std::unique_ptr<AsyncDnsResolverFactoryInterface>
diff --git a/p2p/base/port.cc b/p2p/base/port.cc
index c7c1de2..ea6b045 100644
--- a/p2p/base/port.cc
+++ b/p2p/base/port.cc
@@ -121,6 +121,7 @@
network_(args.network),
min_port_(min_port),
max_port_(max_port),
+ content_name_(args.content_name),
component_(ICE_CANDIDATE_COMPONENT_DEFAULT),
generation_(0),
ice_username_fragment_(args.ice_username_fragment),
diff --git a/p2p/base/port.h b/p2p/base/port.h
index 1a237be..134d9eb 100644
--- a/p2p/base/port.h
+++ b/p2p/base/port.h
@@ -169,6 +169,7 @@
const ::webrtc::Network* network;
absl::string_view ice_username_fragment;
absl::string_view ice_password;
+ absl::string_view content_name;
LocalNetworkAccessPermissionFactoryInterface* lna_permission_factory =
nullptr;
};
diff --git a/p2p/base/port_allocator.cc b/p2p/base/port_allocator.cc
index ba95687..cd7bd07 100644
--- a/p2p/base/port_allocator.cc
+++ b/p2p/base/port_allocator.cc
@@ -241,6 +241,7 @@
auto it =
pooled_sessions_.begin() + std::distance(pooled_sessions_.cbegin(), cit);
std::unique_ptr<PortAllocatorSession> ret = std::move(*it);
+ RTC_DCHECK(ret->pooled());
ret->SetIceParameters(content_name, component, ice_ufrag, ice_pwd);
ret->set_pooled(false);
// According to JSEP, a pooled session should filter candidates only
@@ -256,9 +257,8 @@
auto it = FindPooledSession(ice_credentials);
if (it == pooled_sessions_.end()) {
return nullptr;
- } else {
- return it->get();
}
+ return it->get();
}
std::vector<std::unique_ptr<PortAllocatorSession>>::const_iterator
diff --git a/p2p/base/port_allocator.h b/p2p/base/port_allocator.h
index 87490f2..643fb7b 100644
--- a/p2p/base/port_allocator.h
+++ b/p2p/base/port_allocator.h
@@ -303,6 +303,9 @@
int component,
absl::string_view ice_ufrag,
absl::string_view ice_pwd) {
+ RTC_DCHECK(pooled_);
+ RTC_DCHECK(!content_name.empty());
+ RTC_DCHECK(content_name_.empty());
content_name_ = std::string(content_name);
component_ = component;
ice_ufrag_ = std::string(ice_ufrag);
@@ -310,7 +313,12 @@
UpdateIceParametersInternal();
}
- void set_pooled(bool value) { pooled_ = value; }
+ void set_pooled(bool value) {
+ pooled_ = value;
+ if (pooled_) {
+ content_name_.clear();
+ }
+ }
uint32_t flags_;
uint32_t generation_;
diff --git a/p2p/base/port_allocator_unittest.cc b/p2p/base/port_allocator_unittest.cc
index 8bc61da..d7272ba 100644
--- a/p2p/base/port_allocator_unittest.cc
+++ b/p2p/base/port_allocator_unittest.cc
@@ -239,6 +239,7 @@
static_cast<webrtc::FakePortAllocatorSession*>(
allocator_->TakePooledSession(kContentName, 1, kIceUfrag, kIcePwd)
.release()));
+ EXPECT_FALSE(session->pooled());
EXPECT_EQ(1, session->transport_info_update_count());
EXPECT_EQ(kContentName, session->content_name());
EXPECT_EQ(1, session->component());
diff --git a/p2p/base/turn_port.h b/p2p/base/turn_port.h
index c74feae..0674a5a 100644
--- a/p2p/base/turn_port.h
+++ b/p2p/base/turn_port.h
@@ -93,6 +93,7 @@
.network = args.network,
.ice_username_fragment = args.username,
.ice_password = args.password,
+ .content_name = args.content_name,
.lna_permission_factory = args.lna_permission_factory},
socket, *args.server_address, args.config->credentials,
args.relative_priority, args.config->tls_alpn_protocols,
@@ -116,6 +117,7 @@
.network = args.network,
.ice_username_fragment = args.username,
.ice_password = args.password,
+ .content_name = args.content_name,
.lna_permission_factory = args.lna_permission_factory},
min_port, max_port, *args.server_address, args.config->credentials,
args.relative_priority, args.config->tls_alpn_protocols,
diff --git a/p2p/client/basic_port_allocator.cc b/p2p/client/basic_port_allocator.cc
index ee47628..e288c71 100644
--- a/p2p/client/basic_port_allocator.cc
+++ b/p2p/client/basic_port_allocator.cc
@@ -567,6 +567,7 @@
void BasicPortAllocatorSession::UpdateIceParametersInternal() {
RTC_DCHECK_RUN_ON(network_thread_);
+ RTC_DCHECK(pooled());
for (PortData& port : ports_) {
port.port()->set_content_name(content_name());
port.port()->SetIceParameters(component(), ice_ufrag(), ice_pwd());
@@ -907,18 +908,15 @@
void BasicPortAllocatorSession::AddAllocatedPort(Port* port,
AllocationSequence* seq) {
RTC_DCHECK_RUN_ON(network_thread_);
- if (!port)
- return;
+ RTC_DCHECK_EQ(port->content_name(), content_name());
RTC_LOG(LS_INFO) << "Adding allocated port for " << content_name();
- port->set_content_name(content_name());
port->set_component(component());
port->set_generation(generation());
port->set_send_retransmit_count_attribute(
(flags() & PORTALLOCATOR_ENABLE_STUN_RETRANSMIT_ATTRIBUTE) != 0);
- PortData data(port, seq);
- ports_.push_back(data);
+ ports_.emplace_back(port, seq);
port->SubscribeCandidateReadyCallback(
[this](Port* port, const Candidate& c) { OnCandidateReady(port, c); });
@@ -1453,6 +1451,7 @@
.network = network_,
.ice_username_fragment = session_->username(),
.ice_password = session_->password(),
+ .content_name = session_->content_name(),
.lna_permission_factory =
session_->allocator()->lna_permission_factory()},
udp_socket_.get(), emit_local_candidate_for_anyaddress,
@@ -1465,6 +1464,7 @@
.network = network_,
.ice_username_fragment = session_->username(),
.ice_password = session_->password(),
+ .content_name = session_->content_name(),
.lna_permission_factory =
session_->allocator()->lna_permission_factory()},
session_->allocator()->min_port(), session_->allocator()->max_port(),
@@ -1478,9 +1478,6 @@
// UDPPort.
if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET)) {
udp_port_ = port.get();
- port->SubscribePortDestroyed(
- [this](PortInterface* port) { OnPortDestroyed(port); });
-
// If STUN is not disabled, setting stun server address to port.
if (!IsFlagSet(PORTALLOCATOR_DISABLE_STUN)) {
if (config_ && !config_->StunServers().empty()) {
@@ -1503,12 +1500,15 @@
}
std::unique_ptr<Port> port = TCPPort::Create(
- {.env = session_->allocator()->env(),
- .network_thread = session_->network_thread(),
- .socket_factory = session_->socket_factory(),
- .network = network_,
- .ice_username_fragment = session_->username(),
- .ice_password = session_->password()},
+ {
+ .env = session_->allocator()->env(),
+ .network_thread = session_->network_thread(),
+ .socket_factory = session_->socket_factory(),
+ .network = network_,
+ .ice_username_fragment = session_->username(),
+ .ice_password = session_->password(),
+ .content_name = session_->content_name(),
+ },
session_->allocator()->min_port(), session_->allocator()->max_port(),
session_->allocator()->allow_tcp_listen());
if (port) {
@@ -1542,6 +1542,7 @@
.network = network_,
.ice_username_fragment = session_->username(),
.ice_password = session_->password(),
+ .content_name = session_->content_name(),
.lna_permission_factory =
session_->allocator()->lna_permission_factory()},
session_->allocator()->min_port(), session_->allocator()->max_port(),
@@ -1611,6 +1612,7 @@
args.network = network_;
args.username = session_->username();
args.password = session_->password();
+ args.content_name = session_->content_name();
args.server_address = &(*relay_port);
args.config = &config;
args.turn_customizer = session_->allocator()->turn_customizer();
@@ -1635,11 +1637,6 @@
}
relay_ports_.push_back(port.get());
- // Listen to the port destroyed signal, to allow AllocationSequence to
- // remove the entry from it's map.
- port->SubscribePortDestroyed(
- [this](PortInterface* port) { OnPortDestroyed(port); });
-
} else {
port = session_->allocator()->relay_port_factory()->Create(
args, session_->allocator()->min_port(),
diff --git a/p2p/client/basic_port_allocator.h b/p2p/client/basic_port_allocator.h
index ced785f..f2242a7 100644
--- a/p2p/client/basic_port_allocator.h
+++ b/p2p/client/basic_port_allocator.h
@@ -201,10 +201,13 @@
// interface. Only TURN ports may be pruned.
};
- PortData() {}
+ PortData() = delete;
+ PortData(PortData&&) = default;
PortData(Port* port, AllocationSequence* seq)
: port_(port), sequence_(seq) {}
+ PortData& operator=(PortData&&) = default;
+
Port* port() const { return port_; }
AllocationSequence* sequence() const { return sequence_; }
bool has_pairable_candidate() const { return has_pairable_candidate_; }
diff --git a/p2p/client/relay_port_factory_interface.h b/p2p/client/relay_port_factory_interface.h
index 63b7c8b..2bcb2e0 100644
--- a/p2p/client/relay_port_factory_interface.h
+++ b/p2p/client/relay_port_factory_interface.h
@@ -40,6 +40,7 @@
const RelayServerConfig* config;
std::string username;
std::string password;
+ std::string content_name;
TurnCustomizer* turn_customizer = nullptr;
// Relative priority of candidates from this TURN server in relation
// to the candidates from other servers. Required because ICE priorities