Add thread guards to cricket::P2PTransportChannel.

This gives assurance that we're not calling any function in
cricket::P2PTransportChannel off-thread.

Bug: none
Change-Id: I21d4e496cf5f301ab85abbd53a5abd4f5068ec39
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/138271
Commit-Queue: Harald Alvestrand <hta@webrtc.org>
Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#28077}
This commit is contained in:
Harald Alvestrand 2019-05-27 15:49:31 +02:00 committed by Commit Bot
parent 2e8d78ce42
commit 36bc4f810d
2 changed files with 182 additions and 71 deletions

View File

@ -165,14 +165,14 @@ P2PTransportChannel::~P2PTransportChannel() {
p.resolver_->Destroy(false);
}
resolvers_.clear();
RTC_DCHECK(network_thread_ == rtc::Thread::Current());
RTC_DCHECK_RUN_ON(network_thread_);
}
// Add the allocator session to our list so that we know which sessions
// are still active.
void P2PTransportChannel::AddAllocatorSession(
std::unique_ptr<PortAllocatorSession> session) {
RTC_DCHECK(network_thread_ == rtc::Thread::Current());
RTC_DCHECK_RUN_ON(network_thread_);
session->set_generation(static_cast<uint32_t>(allocator_sessions_.size()));
session->SignalPortReady.connect(this, &P2PTransportChannel::OnPortReady);
@ -196,6 +196,7 @@ void P2PTransportChannel::AddAllocatorSession(
}
void P2PTransportChannel::AddConnection(Connection* connection) {
RTC_DCHECK_RUN_ON(network_thread_);
connections_.push_back(connection);
unpinged_connections_.insert(connection);
connection->set_remote_ice_mode(remote_ice_mode_);
@ -239,6 +240,7 @@ void P2PTransportChannel::AddConnection(Connection* connection) {
bool P2PTransportChannel::ShouldSwitchSelectedConnection(
Connection* new_connection,
bool* missed_receiving_unchanged_threshold) const {
RTC_DCHECK_RUN_ON(network_thread_);
if (!ReadyToSend(new_connection) || selected_connection_ == new_connection) {
return false;
}
@ -273,6 +275,7 @@ bool P2PTransportChannel::ShouldSwitchSelectedConnection(
bool P2PTransportChannel::MaybeSwitchSelectedConnection(
Connection* new_connection,
const std::string& reason) {
RTC_DCHECK_RUN_ON(network_thread_);
bool missed_receiving_unchanged_threshold = false;
if (ShouldSwitchSelectedConnection(new_connection,
&missed_receiving_unchanged_threshold)) {
@ -298,7 +301,7 @@ bool P2PTransportChannel::MaybeSwitchSelectedConnection(
}
void P2PTransportChannel::SetIceRole(IceRole ice_role) {
RTC_DCHECK(network_thread_ == rtc::Thread::Current());
RTC_DCHECK_RUN_ON(network_thread_);
if (ice_role_ != ice_role) {
ice_role_ = ice_role;
for (PortInterface* port : ports_) {
@ -313,11 +316,12 @@ void P2PTransportChannel::SetIceRole(IceRole ice_role) {
}
IceRole P2PTransportChannel::GetIceRole() const {
RTC_DCHECK_RUN_ON(network_thread_);
return ice_role_;
}
void P2PTransportChannel::SetIceTiebreaker(uint64_t tiebreaker) {
RTC_DCHECK(network_thread_ == rtc::Thread::Current());
RTC_DCHECK_RUN_ON(network_thread_);
if (!ports_.empty() || !pruned_ports_.empty()) {
RTC_LOG(LS_ERROR)
<< "Attempt to change tiebreaker after Port has been allocated.";
@ -328,34 +332,42 @@ void P2PTransportChannel::SetIceTiebreaker(uint64_t tiebreaker) {
}
IceTransportState P2PTransportChannel::GetState() const {
RTC_DCHECK_RUN_ON(network_thread_);
return state_;
}
webrtc::IceTransportState P2PTransportChannel::GetIceTransportState() const {
RTC_DCHECK_RUN_ON(network_thread_);
return standardized_state_;
}
const std::string& P2PTransportChannel::transport_name() const {
RTC_DCHECK_RUN_ON(network_thread_);
return transport_name_;
}
int P2PTransportChannel::component() const {
RTC_DCHECK_RUN_ON(network_thread_);
return component_;
}
bool P2PTransportChannel::writable() const {
RTC_DCHECK_RUN_ON(network_thread_);
return writable_;
}
bool P2PTransportChannel::receiving() const {
RTC_DCHECK_RUN_ON(network_thread_);
return receiving_;
}
IceGatheringState P2PTransportChannel::gathering_state() const {
RTC_DCHECK_RUN_ON(network_thread_);
return gathering_state_;
}
absl::optional<int> P2PTransportChannel::GetRttEstimate() {
RTC_DCHECK_RUN_ON(network_thread_);
if (selected_connection_ != nullptr
&& selected_connection_->rtt_samples() > 0) {
return selected_connection_->rtt();
@ -367,6 +379,7 @@ absl::optional<int> P2PTransportChannel::GetRttEstimate() {
// A channel is considered ICE completed once there is at most one active
// connection per network and at least one active connection.
IceTransportState P2PTransportChannel::ComputeState() const {
RTC_DCHECK_RUN_ON(network_thread_);
if (!had_connection_) {
return IceTransportState::STATE_INIT;
}
@ -405,6 +418,7 @@ IceTransportState P2PTransportChannel::ComputeState() const {
// implemented end-of-candidates signalling.
webrtc::IceTransportState P2PTransportChannel::ComputeIceTransportState()
const {
RTC_DCHECK_RUN_ON(network_thread_);
bool has_connection = false;
for (Connection* connection : connections_) {
if (connection->active()) {
@ -435,7 +449,7 @@ webrtc::IceTransportState P2PTransportChannel::ComputeIceTransportState()
}
void P2PTransportChannel::SetIceParameters(const IceParameters& ice_params) {
RTC_DCHECK(network_thread_ == rtc::Thread::Current());
RTC_DCHECK_RUN_ON(network_thread_);
RTC_LOG(LS_INFO) << "Set ICE ufrag: " << ice_params.ufrag
<< " pwd: " << ice_params.pwd << " on transport "
<< transport_name();
@ -446,7 +460,7 @@ void P2PTransportChannel::SetIceParameters(const IceParameters& ice_params) {
void P2PTransportChannel::SetRemoteIceParameters(
const IceParameters& ice_params) {
RTC_DCHECK(network_thread_ == rtc::Thread::Current());
RTC_DCHECK_RUN_ON(network_thread_);
RTC_LOG(LS_INFO) << "Received remote ICE parameters: ufrag="
<< ice_params.ufrag << ", renomination "
<< (ice_params.renomination ? "enabled" : "disabled");
@ -475,6 +489,7 @@ void P2PTransportChannel::SetRemoteIceParameters(
}
void P2PTransportChannel::SetRemoteIceMode(IceMode mode) {
RTC_DCHECK_RUN_ON(network_thread_);
remote_ice_mode_ = mode;
}
@ -484,6 +499,7 @@ void P2PTransportChannel::SetRemoteIceMode(IceMode mode) {
// regather_on_failed_networks_interval, and thus there is no way to restore the
// defaults. Fix this issue later for consistency.
void P2PTransportChannel::SetIceConfig(const IceConfig& config) {
RTC_DCHECK_RUN_ON(network_thread_);
if (config_.continual_gathering_policy != config.continual_gathering_policy) {
if (!allocator_sessions_.empty()) {
RTC_LOG(LS_ERROR) << "Trying to change continual gathering policy "
@ -660,11 +676,13 @@ void P2PTransportChannel::SetIceConfig(const IceConfig& config) {
}
const IceConfig& P2PTransportChannel::config() const {
RTC_DCHECK_RUN_ON(network_thread_);
return config_;
}
// TODO(qingsi): Add tests for the config validation starting from
// PeerConnection::SetConfiguration.
// Static
RTCError P2PTransportChannel::ValidateIceConfig(const IceConfig& config) {
if (config.regather_all_networks_interval_range &&
config.continual_gathering_policy == GATHER_ONCE) {
@ -724,15 +742,18 @@ RTCError P2PTransportChannel::ValidateIceConfig(const IceConfig& config) {
}
const Connection* P2PTransportChannel::selected_connection() const {
RTC_DCHECK_RUN_ON(network_thread_);
return selected_connection_;
}
int P2PTransportChannel::check_receiving_interval() const {
RTC_DCHECK_RUN_ON(network_thread_);
return std::max(MIN_CHECK_RECEIVING_INTERVAL,
config_.receiving_timeout_or_default() / 10);
}
void P2PTransportChannel::MaybeStartGathering() {
RTC_DCHECK_RUN_ON(network_thread_);
if (ice_parameters_.ufrag.empty() || ice_parameters_.pwd.empty()) {
RTC_LOG(LS_ERROR)
<< "Cannot gather candidates because ICE parameters are empty"
@ -794,7 +815,7 @@ void P2PTransportChannel::MaybeStartGathering() {
// A new port is available, attempt to make connections for it
void P2PTransportChannel::OnPortReady(PortAllocatorSession *session,
PortInterface* port) {
RTC_DCHECK(network_thread_ == rtc::Thread::Current());
RTC_DCHECK_RUN_ON(network_thread_);
// Set in-effect options on the new port
for (OptionMap::const_iterator it = options_.begin();
@ -841,7 +862,7 @@ void P2PTransportChannel::OnPortReady(PortAllocatorSession *session,
void P2PTransportChannel::OnCandidatesReady(
PortAllocatorSession* session,
const std::vector<Candidate>& candidates) {
RTC_DCHECK(network_thread_ == rtc::Thread::Current());
RTC_DCHECK_RUN_ON(network_thread_);
for (size_t i = 0; i < candidates.size(); ++i) {
SignalCandidateGathered(this, candidates[i]);
}
@ -849,7 +870,7 @@ void P2PTransportChannel::OnCandidatesReady(
void P2PTransportChannel::OnCandidatesAllocationDone(
PortAllocatorSession* session) {
RTC_DCHECK(network_thread_ == rtc::Thread::Current());
RTC_DCHECK_RUN_ON(network_thread_);
if (config_.gather_continually()) {
RTC_LOG(LS_INFO) << "P2PTransportChannel: " << transport_name()
<< ", component " << component()
@ -869,7 +890,7 @@ void P2PTransportChannel::OnUnknownAddress(
const rtc::SocketAddress& address, ProtocolType proto,
IceMessage* stun_msg, const std::string &remote_username,
bool port_muxed) {
RTC_DCHECK(network_thread_ == rtc::Thread::Current());
RTC_DCHECK_RUN_ON(network_thread_);
// Port has received a valid stun packet from an address that no Connection
// is currently available for. See if we already have a candidate with the
@ -1024,6 +1045,7 @@ void P2PTransportChannel::OnRoleConflict(PortInterface* port) {
const IceParameters* P2PTransportChannel::FindRemoteIceFromUfrag(
const std::string& ufrag,
uint32_t* generation) {
RTC_DCHECK_RUN_ON(network_thread_);
const auto& params = remote_ice_parameters_;
auto it = std::find_if(
params.rbegin(), params.rend(),
@ -1037,7 +1059,7 @@ const IceParameters* P2PTransportChannel::FindRemoteIceFromUfrag(
}
void P2PTransportChannel::OnNominated(Connection* conn) {
RTC_DCHECK(network_thread_ == rtc::Thread::Current());
RTC_DCHECK_RUN_ON(network_thread_);
RTC_DCHECK(ice_role_ == ICEROLE_CONTROLLED);
if (selected_connection_ == conn) {
@ -1059,6 +1081,7 @@ void P2PTransportChannel::OnNominated(Connection* conn) {
}
void P2PTransportChannel::ResolveHostnameCandidate(const Candidate& candidate) {
RTC_DCHECK_RUN_ON(network_thread_);
if (!async_resolver_factory_) {
RTC_LOG(LS_WARNING) << "Dropping ICE candidate with hostname address "
<< "(no AsyncResolverFactory)";
@ -1074,7 +1097,7 @@ void P2PTransportChannel::ResolveHostnameCandidate(const Candidate& candidate) {
}
void P2PTransportChannel::AddRemoteCandidate(const Candidate& candidate) {
RTC_DCHECK(network_thread_ == rtc::Thread::Current());
RTC_DCHECK_RUN_ON(network_thread_);
uint32_t generation = GetRemoteCandidateGeneration(candidate);
// If a remote candidate with a previous generation arrives, drop it.
@ -1125,6 +1148,7 @@ P2PTransportChannel::CandidateAndResolver::~CandidateAndResolver() {}
void P2PTransportChannel::OnCandidateResolved(
rtc::AsyncResolverInterface* resolver) {
RTC_DCHECK_RUN_ON(network_thread_);
auto p =
absl::c_find_if(resolvers_, [resolver](const CandidateAndResolver& cr) {
return cr.resolver_ == resolver;
@ -1145,6 +1169,7 @@ void P2PTransportChannel::OnCandidateResolved(
void P2PTransportChannel::AddRemoteCandidateWithResolver(
Candidate candidate,
rtc::AsyncResolverInterface* resolver) {
RTC_DCHECK_RUN_ON(network_thread_);
if (resolver->GetError()) {
RTC_LOG(LS_WARNING) << "Failed to resolve ICE candidate hostname "
<< candidate.address().HostAsSensitiveURIString()
@ -1175,6 +1200,7 @@ void P2PTransportChannel::AddRemoteCandidateWithResolver(
void P2PTransportChannel::FinishAddingRemoteCandidate(
const Candidate& new_remote_candidate) {
RTC_DCHECK_RUN_ON(network_thread_);
// If this candidate matches what was thought to be a peer reflexive
// candidate, we need to update the candidate priority/etc.
for (Connection* conn : connections_) {
@ -1191,6 +1217,7 @@ void P2PTransportChannel::FinishAddingRemoteCandidate(
void P2PTransportChannel::RemoveRemoteCandidate(
const Candidate& cand_to_remove) {
RTC_DCHECK_RUN_ON(network_thread_);
auto iter =
std::remove_if(remote_candidates_.begin(), remote_candidates_.end(),
[cand_to_remove](const Candidate& candidate) {
@ -1204,6 +1231,7 @@ void P2PTransportChannel::RemoveRemoteCandidate(
}
void P2PTransportChannel::RemoveAllRemoteCandidates() {
RTC_DCHECK_RUN_ON(network_thread_);
remote_candidates_.clear();
}
@ -1212,7 +1240,7 @@ void P2PTransportChannel::RemoveAllRemoteCandidates() {
// the origin port.
bool P2PTransportChannel::CreateConnections(const Candidate& remote_candidate,
PortInterface* origin_port) {
RTC_DCHECK(network_thread_ == rtc::Thread::Current());
RTC_DCHECK_RUN_ON(network_thread_);
// If we've already seen the new remote candidate (in the current candidate
// generation), then we shouldn't try creating connections for it.
@ -1257,6 +1285,7 @@ bool P2PTransportChannel::CreateConnections(const Candidate& remote_candidate,
bool P2PTransportChannel::CreateConnection(PortInterface* port,
const Candidate& remote_candidate,
PortInterface* origin_port) {
RTC_DCHECK_RUN_ON(network_thread_);
if (!port->SupportsProtocol(remote_candidate.protocol())) {
return false;
}
@ -1297,11 +1326,13 @@ bool P2PTransportChannel::CreateConnection(PortInterface* port,
}
bool P2PTransportChannel::FindConnection(Connection* connection) const {
RTC_DCHECK_RUN_ON(network_thread_);
return absl::c_linear_search(connections_, connection);
}
uint32_t P2PTransportChannel::GetRemoteCandidateGeneration(
const Candidate& candidate) {
RTC_DCHECK_RUN_ON(network_thread_);
// If the candidate has a ufrag, use it to find the generation.
if (!candidate.username().empty()) {
uint32_t generation = 0;
@ -1322,6 +1353,7 @@ uint32_t P2PTransportChannel::GetRemoteCandidateGeneration(
// Check if remote candidate is already cached.
bool P2PTransportChannel::IsDuplicateRemoteCandidate(
const Candidate& candidate) {
RTC_DCHECK_RUN_ON(network_thread_);
for (size_t i = 0; i < remote_candidates_.size(); ++i) {
if (remote_candidates_[i].IsEquivalent(candidate)) {
return true;
@ -1333,6 +1365,7 @@ bool P2PTransportChannel::IsDuplicateRemoteCandidate(
// Maintain our remote candidate list, adding this new remote one.
void P2PTransportChannel::RememberRemoteCandidate(
const Candidate& remote_candidate, PortInterface* origin_port) {
RTC_DCHECK_RUN_ON(network_thread_);
// Remove any candidates whose generation is older than this one. The
// presence of a new generation indicates that the old ones are not useful.
size_t i = 0;
@ -1359,7 +1392,7 @@ void P2PTransportChannel::RememberRemoteCandidate(
// Set options on ourselves is simply setting options on all of our available
// port objects.
int P2PTransportChannel::SetOption(rtc::Socket::Option opt, int value) {
RTC_DCHECK(network_thread_ == rtc::Thread::Current());
RTC_DCHECK_RUN_ON(network_thread_);
OptionMap::iterator it = options_.find(opt);
if (it == options_.end()) {
options_.insert(std::make_pair(opt, value));
@ -1382,7 +1415,7 @@ int P2PTransportChannel::SetOption(rtc::Socket::Option opt, int value) {
}
bool P2PTransportChannel::GetOption(rtc::Socket::Option opt, int* value) {
RTC_DCHECK(network_thread_ == rtc::Thread::Current());
RTC_DCHECK_RUN_ON(network_thread_);
const auto& found = options_.find(opt);
if (found == options_.end()) {
@ -1393,6 +1426,7 @@ bool P2PTransportChannel::GetOption(rtc::Socket::Option opt, int* value) {
}
int P2PTransportChannel::GetError() {
RTC_DCHECK_RUN_ON(network_thread_);
return error_;
}
@ -1400,7 +1434,7 @@ int P2PTransportChannel::GetError() {
int P2PTransportChannel::SendPacket(const char *data, size_t len,
const rtc::PacketOptions& options,
int flags) {
RTC_DCHECK(network_thread_ == rtc::Thread::Current());
RTC_DCHECK_RUN_ON(network_thread_);
if (flags != 0) {
error_ = EINVAL;
return -1;
@ -1426,7 +1460,7 @@ int P2PTransportChannel::SendPacket(const char *data, size_t len,
bool P2PTransportChannel::GetStats(ConnectionInfos* candidate_pair_stats_list,
CandidateStatsList* candidate_stats_list) {
RTC_DCHECK(network_thread_ == rtc::Thread::Current());
RTC_DCHECK_RUN_ON(network_thread_);
// Gather candidate and candidate pair stats.
candidate_stats_list->clear();
candidate_pair_stats_list->clear();
@ -1447,10 +1481,12 @@ bool P2PTransportChannel::GetStats(ConnectionInfos* candidate_pair_stats_list,
}
absl::optional<rtc::NetworkRoute> P2PTransportChannel::network_route() const {
RTC_DCHECK_RUN_ON(network_thread_);
return network_route_;
}
rtc::DiffServCodePoint P2PTransportChannel::DefaultDscpValue() const {
RTC_DCHECK_RUN_ON(network_thread_);
OptionMap::const_iterator it = options_.find(rtc::Socket::OPT_DSCP);
if (it == options_.end()) {
return rtc::DSCP_NO_CHANGE;
@ -1460,6 +1496,7 @@ rtc::DiffServCodePoint P2PTransportChannel::DefaultDscpValue() const {
// Monitor connection states.
void P2PTransportChannel::UpdateConnectionStates() {
RTC_DCHECK_RUN_ON(network_thread_);
int64_t now = rtc::TimeMillis();
// We need to copy the list of connections since some may delete themselves
@ -1472,6 +1509,7 @@ void P2PTransportChannel::UpdateConnectionStates() {
// Prepare for best candidate sorting.
void P2PTransportChannel::RequestSortAndStateUpdate(
const std::string& reason_to_sort) {
RTC_DCHECK_RUN_ON(network_thread_);
if (!sort_dirty_) {
invoker_.AsyncInvoke<void>(
RTC_FROM_HERE, thread(),
@ -1482,6 +1520,7 @@ void P2PTransportChannel::RequestSortAndStateUpdate(
}
void P2PTransportChannel::MaybeStartPinging() {
RTC_DCHECK_RUN_ON(network_thread_);
if (started_pinging_) {
return;
}
@ -1505,6 +1544,7 @@ int P2PTransportChannel::CompareCandidatePairNetworks(
const Connection* a,
const Connection* b,
absl::optional<rtc::AdapterType> network_preference) const {
RTC_DCHECK_RUN_ON(network_thread_);
int compare_a_b_by_network_preference =
CompareCandidatePairsByNetworkPreference(a, b,
config_.network_preference);
@ -1532,6 +1572,7 @@ int P2PTransportChannel::CompareConnectionStates(
const Connection* b,
absl::optional<int64_t> receiving_unchanged_threshold,
bool* missed_receiving_unchanged_threshold) const {
RTC_DCHECK_RUN_ON(network_thread_);
// First, prefer a connection that's writable or presumed writable over
// one that's not writable.
bool a_writable = a->writable() || PresumedWritable(a);
@ -1605,6 +1646,7 @@ int P2PTransportChannel::CompareConnectionStates(
int P2PTransportChannel::CompareConnectionCandidates(
const Connection* a,
const Connection* b) const {
RTC_DCHECK_RUN_ON(network_thread_);
int compare_a_b_by_networks =
CompareCandidatePairNetworks(a, b, config_.network_preference);
if (compare_a_b_by_networks != a_and_b_equal) {
@ -1648,10 +1690,12 @@ int P2PTransportChannel::CompareConnectionCandidates(
}
bool P2PTransportChannel::IsPortPruned(const Port* port) const {
RTC_DCHECK_RUN_ON(network_thread_);
return !absl::c_linear_search(ports_, port);
}
bool P2PTransportChannel::IsRemoteCandidatePruned(const Candidate& cand) const {
RTC_DCHECK_RUN_ON(network_thread_);
return !absl::c_linear_search(remote_candidates_, cand);
}
@ -1660,6 +1704,7 @@ int P2PTransportChannel::CompareConnections(
const Connection* b,
absl::optional<int64_t> receiving_unchanged_threshold,
bool* missed_receiving_unchanged_threshold) const {
RTC_DCHECK_RUN_ON(network_thread_);
RTC_CHECK(a != nullptr);
RTC_CHECK(b != nullptr);
@ -1695,6 +1740,7 @@ int P2PTransportChannel::CompareConnections(
}
bool P2PTransportChannel::PresumedWritable(const Connection* conn) const {
RTC_DCHECK_RUN_ON(network_thread_);
return (conn->write_state() == Connection::STATE_WRITE_INIT &&
config_.presume_writable_when_fully_relayed &&
conn->local_candidate().type() == RELAY_PORT_TYPE &&
@ -1706,7 +1752,7 @@ bool P2PTransportChannel::PresumedWritable(const Connection* conn) const {
// the number of available connections and the current state.
void P2PTransportChannel::SortConnectionsAndUpdateState(
const std::string& reason_to_sort) {
RTC_DCHECK(network_thread_ == rtc::Thread::Current());
RTC_DCHECK_RUN_ON(network_thread_);
// Make sure the connection states are up-to-date since this affects how they
// will be sorted.
@ -1783,6 +1829,7 @@ void P2PTransportChannel::SortConnectionsAndUpdateState(
std::map<rtc::Network*, Connection*>
P2PTransportChannel::GetBestConnectionByNetwork() const {
RTC_DCHECK_RUN_ON(network_thread_);
// |connections_| has been sorted, so the first one in the list on a given
// network is the best connection on the network, except that the selected
// connection is always the best connection on the network.
@ -1827,6 +1874,7 @@ void P2PTransportChannel::PruneConnections() {
// not bound to any specific network interface. We don't want to keep one of
// these alive as a backup, since it could be using the same network
// interface as the higher-priority, selected candidate pair.
RTC_DCHECK_RUN_ON(network_thread_);
auto best_connection_by_network = GetBestConnectionByNetwork();
for (Connection* conn : connections_) {
Connection* best_conn = selected_connection_;
@ -1849,6 +1897,7 @@ void P2PTransportChannel::PruneConnections() {
// Change the selected connection, and let listeners know.
void P2PTransportChannel::SwitchSelectedConnection(Connection* conn) {
RTC_DCHECK_RUN_ON(network_thread_);
// Note: if conn is NULL, the previous |selected_connection_| has been
// destroyed, so don't use it.
Connection* old_selected_connection = selected_connection_;
@ -1906,6 +1955,7 @@ void P2PTransportChannel::SwitchSelectedConnection(Connection* conn) {
// change, it should be called after all the connection states have changed. For
// example, we call this at the end of SortConnectionsAndUpdateState.
void P2PTransportChannel::UpdateState() {
RTC_DCHECK_RUN_ON(network_thread_);
// If our selected connection is "presumed writable" (TURN-TURN with no
// CreatePermission required), act like we're already writable to the upper
// layers, so they can start media quicker.
@ -1975,6 +2025,7 @@ void P2PTransportChannel::UpdateState() {
}
void P2PTransportChannel::MaybeStopPortAllocatorSessions() {
RTC_DCHECK_RUN_ON(network_thread_);
if (!IsGettingPorts()) {
return;
}
@ -1995,16 +2046,19 @@ void P2PTransportChannel::MaybeStopPortAllocatorSessions() {
// If all connections timed out, delete them all.
void P2PTransportChannel::HandleAllTimedOut() {
RTC_DCHECK_RUN_ON(network_thread_);
for (Connection* connection : connections_) {
connection->Destroy();
}
}
bool P2PTransportChannel::weak() const {
RTC_DCHECK_RUN_ON(network_thread_);
return !selected_connection_ || selected_connection_->weak();
}
bool P2PTransportChannel::ReadyToSend(Connection* connection) const {
RTC_DCHECK_RUN_ON(network_thread_);
// Note that we allow sending on an unreliable connection, because it's
// possible that it became unreliable simply due to bad chance.
// So this shouldn't prevent attempting to send media.
@ -2016,6 +2070,7 @@ bool P2PTransportChannel::ReadyToSend(Connection* connection) const {
// Handle queued up check-and-ping request
void P2PTransportChannel::CheckAndPing() {
RTC_DCHECK_RUN_ON(network_thread_);
// Make sure the states of the connections are up-to-date (since this affects
// which ones are pingable).
UpdateConnectionStates();
@ -2046,6 +2101,7 @@ void P2PTransportChannel::CheckAndPing() {
// A connection is considered a backup connection if the channel state
// is completed, the connection is not the selected connection and it is active.
bool P2PTransportChannel::IsBackupConnection(const Connection* conn) const {
RTC_DCHECK_RUN_ON(network_thread_);
return state_ == IceTransportState::STATE_COMPLETED &&
conn != selected_connection_ && conn->active();
}
@ -2055,6 +2111,7 @@ bool P2PTransportChannel::IsBackupConnection(const Connection* conn) const {
// how a TCP connection is kicked into reconnecting on the active side.
bool P2PTransportChannel::IsPingable(const Connection* conn,
int64_t now) const {
RTC_DCHECK_RUN_ON(network_thread_);
const Candidate& remote = conn->remote_candidate();
// We should never get this far with an empty remote ufrag.
RTC_DCHECK(!remote.username().empty());
@ -2105,6 +2162,7 @@ bool P2PTransportChannel::IsPingable(const Connection* conn,
bool P2PTransportChannel::WritableConnectionPastPingInterval(
const Connection* conn,
int64_t now) const {
RTC_DCHECK_RUN_ON(network_thread_);
int interval = CalculateActiveWritablePingInterval(conn, now);
return conn->last_ping_sent() + interval <= now;
}
@ -2112,6 +2170,7 @@ bool P2PTransportChannel::WritableConnectionPastPingInterval(
int P2PTransportChannel::CalculateActiveWritablePingInterval(
const Connection* conn,
int64_t now) const {
RTC_DCHECK_RUN_ON(network_thread_);
// Ping each connection at a higher rate at least
// MIN_PINGS_AT_WEAK_PING_INTERVAL times.
if (conn->num_pings_sent() < MIN_PINGS_AT_WEAK_PING_INTERVAL) {
@ -2130,6 +2189,7 @@ int P2PTransportChannel::CalculateActiveWritablePingInterval(
// Returns the next pingable connection to ping.
Connection* P2PTransportChannel::FindNextPingableConnection() {
RTC_DCHECK_RUN_ON(network_thread_);
int64_t now = rtc::TimeMillis();
// Rule 1: Selected connection takes priority over non-selected ones.
@ -2210,6 +2270,7 @@ Connection* P2PTransportChannel::FindNextPingableConnection() {
}
void P2PTransportChannel::MarkConnectionPinged(Connection* conn) {
RTC_DCHECK_RUN_ON(network_thread_);
if (conn && pinged_connections_.insert(conn).second) {
unpinged_connections_.erase(conn);
}
@ -2219,6 +2280,7 @@ void P2PTransportChannel::MarkConnectionPinged(Connection* conn) {
// |use_candidate_attr| and |nomination| flags. One of the flags is set to
// nominate |conn| if this channel is in CONTROLLING.
void P2PTransportChannel::PingConnection(Connection* conn) {
RTC_DCHECK_RUN_ON(network_thread_);
bool use_candidate_attr = false;
uint32_t nomination = 0;
if (ice_role_ == ICEROLE_CONTROLLING) {
@ -2239,12 +2301,14 @@ void P2PTransportChannel::PingConnection(Connection* conn) {
}
uint32_t P2PTransportChannel::GetNominationAttr(Connection* conn) const {
RTC_DCHECK_RUN_ON(network_thread_);
return (conn == selected_connection_) ? nomination_ : 0;
}
// Nominate a connection based on the NominationMode.
bool P2PTransportChannel::GetUseCandidateAttr(Connection* conn,
NominationMode mode) const {
RTC_DCHECK_RUN_ON(network_thread_);
switch (mode) {
case NominationMode::REGULAR:
// TODO(honghaiz): Implement regular nomination.
@ -2283,7 +2347,7 @@ bool P2PTransportChannel::GetUseCandidateAttr(Connection* conn,
// the selected connection again. It could have become usable, or become
// unusable.
void P2PTransportChannel::OnConnectionStateChange(Connection* connection) {
RTC_DCHECK(network_thread_ == rtc::Thread::Current());
RTC_DCHECK_RUN_ON(network_thread_);
// May stop the allocator session when at least one connection becomes
// strongly connected after starting to get ports and the local candidate of
@ -2305,7 +2369,7 @@ void P2PTransportChannel::OnConnectionStateChange(Connection* connection) {
// When a connection is removed, edit it out, and then update our best
// connection.
void P2PTransportChannel::OnConnectionDestroyed(Connection* connection) {
RTC_DCHECK(network_thread_ == rtc::Thread::Current());
RTC_DCHECK_RUN_ON(network_thread_);
// Note: the previous selected_connection_ may be destroyed by now, so don't
// use it.
@ -2341,7 +2405,7 @@ void P2PTransportChannel::OnConnectionDestroyed(Connection* connection) {
// When a port is destroyed, remove it from our list of ports to use for
// connection attempts.
void P2PTransportChannel::OnPortDestroyed(PortInterface* port) {
RTC_DCHECK(network_thread_ == rtc::Thread::Current());
RTC_DCHECK_RUN_ON(network_thread_);
ports_.erase(std::remove(ports_.begin(), ports_.end(), port), ports_.end());
pruned_ports_.erase(
@ -2354,7 +2418,7 @@ void P2PTransportChannel::OnPortDestroyed(PortInterface* port) {
void P2PTransportChannel::OnPortsPruned(
PortAllocatorSession* session,
const std::vector<PortInterface*>& ports) {
RTC_DCHECK(network_thread_ == rtc::Thread::Current());
RTC_DCHECK_RUN_ON(network_thread_);
for (PortInterface* port : ports) {
if (PrunePort(port)) {
RTC_LOG(INFO) << "Removed port: " << port->ToString() << " "
@ -2366,7 +2430,7 @@ void P2PTransportChannel::OnPortsPruned(
void P2PTransportChannel::OnCandidatesRemoved(
PortAllocatorSession* session,
const std::vector<Candidate>& candidates) {
RTC_DCHECK(network_thread_ == rtc::Thread::Current());
RTC_DCHECK_RUN_ON(network_thread_);
// Do not signal candidate removals if continual gathering is not enabled, or
// if this is not the last session because an ICE restart would have signaled
// the remote side to remove all candidates in previous sessions.
@ -2383,11 +2447,13 @@ void P2PTransportChannel::OnCandidatesRemoved(
}
void P2PTransportChannel::PruneAllPorts() {
RTC_DCHECK_RUN_ON(network_thread_);
pruned_ports_.insert(pruned_ports_.end(), ports_.begin(), ports_.end());
ports_.clear();
}
bool P2PTransportChannel::PrunePort(PortInterface* port) {
RTC_DCHECK_RUN_ON(network_thread_);
auto it = absl::c_find(ports_, port);
// Don't need to do anything if the port has been deleted from the port list.
if (it == ports_.end()) {
@ -2403,7 +2469,7 @@ void P2PTransportChannel::OnReadPacket(Connection* connection,
const char* data,
size_t len,
int64_t packet_time_us) {
RTC_DCHECK(network_thread_ == rtc::Thread::Current());
RTC_DCHECK_RUN_ON(network_thread_);
// Do not deliver, if packet doesn't belong to the correct transport channel.
if (!FindConnection(connection))
@ -2420,12 +2486,13 @@ void P2PTransportChannel::OnReadPacket(Connection* connection,
}
void P2PTransportChannel::OnSentPacket(const rtc::SentPacket& sent_packet) {
RTC_DCHECK(network_thread_ == rtc::Thread::Current());
RTC_DCHECK_RUN_ON(network_thread_);
SignalSentPacket(this, sent_packet);
}
void P2PTransportChannel::OnReadyToSend(Connection* connection) {
RTC_DCHECK_RUN_ON(network_thread_);
if (connection == selected_connection_ && writable()) {
SignalReadyToSend(this);
}
@ -2437,6 +2504,7 @@ void P2PTransportChannel::OnReadyToSend(Connection* connection) {
// triggered checks if the connection is already writable.
Connection* P2PTransportChannel::FindOldestConnectionNeedingTriggeredCheck(
int64_t now) {
RTC_DCHECK_RUN_ON(network_thread_);
Connection* oldest_needing_triggered_check = nullptr;
for (auto* conn : connections_) {
if (!IsPingable(conn, now)) {
@ -2462,6 +2530,7 @@ Connection* P2PTransportChannel::FindOldestConnectionNeedingTriggeredCheck(
Connection* P2PTransportChannel::MostLikelyToWork(Connection* conn1,
Connection* conn2) {
RTC_DCHECK_RUN_ON(network_thread_);
bool rr1 = IsRelayRelay(conn1);
bool rr2 = IsRelayRelay(conn2);
if (rr1 && !rr2) {
@ -2482,6 +2551,7 @@ Connection* P2PTransportChannel::MostLikelyToWork(Connection* conn1,
Connection* P2PTransportChannel::LeastRecentlyPinged(Connection* conn1,
Connection* conn2) {
RTC_DCHECK_RUN_ON(network_thread_);
if (conn1->last_ping_sent() < conn2->last_ping_sent()) {
return conn1;
}
@ -2493,6 +2563,7 @@ Connection* P2PTransportChannel::LeastRecentlyPinged(Connection* conn1,
Connection* P2PTransportChannel::MorePingable(Connection* conn1,
Connection* conn2) {
RTC_DCHECK_RUN_ON(network_thread_);
RTC_DCHECK(conn1 != conn2);
if (config_.prioritize_most_likely_candidate_pairs) {
Connection* most_likely_to_work_conn = MostLikelyToWork(conn1, conn2);
@ -2514,6 +2585,7 @@ Connection* P2PTransportChannel::MorePingable(Connection* conn1,
}
void P2PTransportChannel::SetWritable(bool writable) {
RTC_DCHECK_RUN_ON(network_thread_);
if (writable_ == writable) {
return;
}
@ -2528,6 +2600,7 @@ void P2PTransportChannel::SetWritable(bool writable) {
}
void P2PTransportChannel::SetReceiving(bool receiving) {
RTC_DCHECK_RUN_ON(network_thread_);
if (receiving_ == receiving) {
return;
}
@ -2538,6 +2611,7 @@ void P2PTransportChannel::SetReceiving(bool receiving) {
void P2PTransportChannel::LogCandidatePairConfig(
Connection* conn,
webrtc::IceCandidatePairConfigType type) {
RTC_DCHECK_RUN_ON(network_thread_);
if (conn == nullptr) {
return;
}

View File

@ -44,6 +44,7 @@
#include "rtc_base/strings/string_builder.h"
#include "rtc_base/system/rtc_export.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
#include "rtc_base/thread_annotations.h"
namespace webrtc {
class RtcEventLog;
@ -137,16 +138,31 @@ class RTC_EXPORT P2PTransportChannel : public IceTransportInternal {
// TODO(honghaiz): Remove this method once the reference of it in
// Chromoting is removed.
const Connection* best_connection() const { return selected_connection_; }
const Connection* best_connection() const {
RTC_DCHECK_RUN_ON(network_thread_);
return selected_connection_;
}
void set_incoming_only(bool value) { incoming_only_ = value; }
void set_incoming_only(bool value) {
RTC_DCHECK_RUN_ON(network_thread_);
incoming_only_ = value;
}
// Note: These are only for testing purpose.
// |ports_| and |pruned_ports| should not be changed from outside.
const std::vector<PortInterface*>& ports() { return ports_; }
const std::vector<PortInterface*>& pruned_ports() { return pruned_ports_; }
const std::vector<PortInterface*>& ports() {
RTC_DCHECK_RUN_ON(network_thread_);
return ports_;
}
const std::vector<PortInterface*>& pruned_ports() {
RTC_DCHECK_RUN_ON(network_thread_);
return pruned_ports_;
}
IceMode remote_ice_mode() const { return remote_ice_mode_; }
IceMode remote_ice_mode() const {
RTC_DCHECK_RUN_ON(network_thread_);
return remote_ice_mode_;
}
void PruneAllPorts();
int check_receiving_interval() const;
@ -164,6 +180,7 @@ class RTC_EXPORT P2PTransportChannel : public IceTransportInternal {
// Public for unit tests.
PortAllocatorSession* allocator_session() const {
RTC_DCHECK_RUN_ON(network_thread_);
if (allocator_sessions_.empty()) {
return nullptr;
}
@ -172,10 +189,12 @@ class RTC_EXPORT P2PTransportChannel : public IceTransportInternal {
// Public for unit tests.
const std::vector<RemoteCandidate>& remote_candidates() const {
RTC_DCHECK_RUN_ON(network_thread_);
return remote_candidates_;
}
std::string ToString() const {
RTC_DCHECK_RUN_ON(network_thread_);
const std::string RECEIVING_ABBREV[2] = {"_", "R"};
const std::string WRITABLE_ABBREV[2] = {"_", "W"};
rtc::StringBuilder ss;
@ -187,18 +206,23 @@ class RTC_EXPORT P2PTransportChannel : public IceTransportInternal {
private:
rtc::Thread* thread() const { return network_thread_; }
bool IsGettingPorts() { return allocator_session()->IsGettingPorts(); }
bool IsGettingPorts() {
RTC_DCHECK_RUN_ON(network_thread_);
return allocator_session()->IsGettingPorts();
}
// A transport channel is weak if the current best connection is either
// not receiving or not writable, or if there is no best connection at all.
bool weak() const;
int weak_ping_interval() const {
RTC_DCHECK_RUN_ON(network_thread_);
return std::max(config_.ice_check_interval_weak_connectivity_or_default(),
config_.ice_check_min_interval_or_default());
}
int strong_ping_interval() const {
RTC_DCHECK_RUN_ON(network_thread_);
return std::max(config_.ice_check_interval_strong_connectivity_or_default(),
config_.ice_check_min_interval_or_default());
}
@ -350,6 +374,7 @@ class RTC_EXPORT P2PTransportChannel : public IceTransportInternal {
// Returns the latest remote ICE parameters or nullptr if there are no remote
// ICE parameters yet.
IceParameters* remote_ice() {
RTC_DCHECK_RUN_ON(network_thread_);
return remote_ice_parameters_.empty() ? nullptr
: &remote_ice_parameters_.back();
}
@ -360,6 +385,7 @@ class RTC_EXPORT P2PTransportChannel : public IceTransportInternal {
// Returns the index of the latest remote ICE parameters, or 0 if no remote
// ICE parameters have been received.
uint32_t remote_ice_generation() {
RTC_DCHECK_RUN_ON(network_thread_);
return remote_ice_parameters_.empty()
? 0
: static_cast<uint32_t>(remote_ice_parameters_.size() - 1);
@ -376,66 +402,77 @@ class RTC_EXPORT P2PTransportChannel : public IceTransportInternal {
// Sets the receiving state, signaling if necessary.
void SetReceiving(bool receiving);
std::string transport_name_;
int component_;
PortAllocator* allocator_;
webrtc::AsyncResolverFactory* async_resolver_factory_;
std::string transport_name_ RTC_GUARDED_BY(network_thread_);
int component_ RTC_GUARDED_BY(network_thread_);
PortAllocator* allocator_ RTC_GUARDED_BY(network_thread_);
webrtc::AsyncResolverFactory* async_resolver_factory_
RTC_GUARDED_BY(network_thread_);
rtc::Thread* network_thread_;
bool incoming_only_;
int error_;
std::vector<std::unique_ptr<PortAllocatorSession>> allocator_sessions_;
bool incoming_only_ RTC_GUARDED_BY(network_thread_);
int error_ RTC_GUARDED_BY(network_thread_);
std::vector<std::unique_ptr<PortAllocatorSession>> allocator_sessions_
RTC_GUARDED_BY(network_thread_);
// |ports_| contains ports that are used to form new connections when
// new remote candidates are added.
std::vector<PortInterface*> ports_;
std::vector<PortInterface*> ports_ RTC_GUARDED_BY(network_thread_);
// |pruned_ports_| contains ports that have been removed from |ports_| and
// are not being used to form new connections, but that aren't yet destroyed.
// They may have existing connections, and they still fire signals such as
// SignalUnknownAddress.
std::vector<PortInterface*> pruned_ports_;
std::vector<PortInterface*> pruned_ports_ RTC_GUARDED_BY(network_thread_);
// |connections_| is a sorted list with the first one always be the
// |selected_connection_| when it's not nullptr. The combination of
// |pinged_connections_| and |unpinged_connections_| has the same
// connections as |connections_|. These 2 sets maintain whether a
// connection should be pinged next or not.
std::vector<Connection*> connections_;
std::set<Connection*> pinged_connections_;
std::set<Connection*> unpinged_connections_;
std::vector<Connection*> connections_ RTC_GUARDED_BY(network_thread_);
std::set<Connection*> pinged_connections_ RTC_GUARDED_BY(network_thread_);
std::set<Connection*> unpinged_connections_ RTC_GUARDED_BY(network_thread_);
Connection* selected_connection_ = nullptr;
Connection* selected_connection_ RTC_GUARDED_BY(network_thread_) = nullptr;
std::vector<RemoteCandidate> remote_candidates_;
bool sort_dirty_; // indicates whether another sort is needed right now
bool had_connection_ = false; // if connections_ has ever been nonempty
std::vector<RemoteCandidate> remote_candidates_
RTC_GUARDED_BY(network_thread_);
bool sort_dirty_ RTC_GUARDED_BY(
network_thread_); // indicates whether another sort is needed right now
bool had_connection_ RTC_GUARDED_BY(network_thread_) =
false; // if connections_ has ever been nonempty
typedef std::map<rtc::Socket::Option, int> OptionMap;
OptionMap options_;
IceParameters ice_parameters_;
std::vector<IceParameters> remote_ice_parameters_;
IceMode remote_ice_mode_;
IceRole ice_role_;
uint64_t tiebreaker_;
IceGatheringState gathering_state_;
std::unique_ptr<webrtc::BasicRegatheringController> regathering_controller_;
int64_t last_ping_sent_ms_ = 0;
int weak_ping_interval_ = WEAK_PING_INTERVAL;
OptionMap options_ RTC_GUARDED_BY(network_thread_);
IceParameters ice_parameters_ RTC_GUARDED_BY(network_thread_);
std::vector<IceParameters> remote_ice_parameters_
RTC_GUARDED_BY(network_thread_);
IceMode remote_ice_mode_ RTC_GUARDED_BY(network_thread_);
IceRole ice_role_ RTC_GUARDED_BY(network_thread_);
uint64_t tiebreaker_ RTC_GUARDED_BY(network_thread_);
IceGatheringState gathering_state_ RTC_GUARDED_BY(network_thread_);
std::unique_ptr<webrtc::BasicRegatheringController> regathering_controller_
RTC_GUARDED_BY(network_thread_);
int64_t last_ping_sent_ms_ RTC_GUARDED_BY(network_thread_) = 0;
int weak_ping_interval_ RTC_GUARDED_BY(network_thread_) = WEAK_PING_INTERVAL;
// TODO(jonasolsson): Remove state_ and rename standardized_state_ once state_
// is no longer used to compute the ICE connection state.
IceTransportState state_ = IceTransportState::STATE_INIT;
webrtc::IceTransportState standardized_state_ =
webrtc::IceTransportState::kNew;
IceConfig config_;
int last_sent_packet_id_ = -1; // -1 indicates no packet was sent before.
bool started_pinging_ = false;
IceTransportState state_ RTC_GUARDED_BY(network_thread_) =
IceTransportState::STATE_INIT;
webrtc::IceTransportState standardized_state_
RTC_GUARDED_BY(network_thread_) = webrtc::IceTransportState::kNew;
IceConfig config_ RTC_GUARDED_BY(network_thread_);
int last_sent_packet_id_ RTC_GUARDED_BY(network_thread_) =
-1; // -1 indicates no packet was sent before.
bool started_pinging_ RTC_GUARDED_BY(network_thread_) = false;
// The value put in the "nomination" attribute for the next nominated
// connection. A zero-value indicates the connection will not be nominated.
uint32_t nomination_ = 0;
bool receiving_ = false;
bool writable_ = false;
bool has_been_writable_ = false; // if writable_ has ever been true
uint32_t nomination_ RTC_GUARDED_BY(network_thread_) = 0;
bool receiving_ RTC_GUARDED_BY(network_thread_) = false;
bool writable_ RTC_GUARDED_BY(network_thread_) = false;
bool has_been_writable_ RTC_GUARDED_BY(network_thread_) =
false; // if writable_ has ever been true
rtc::AsyncInvoker invoker_;
absl::optional<rtc::NetworkRoute> network_route_;
webrtc::IceEventLog ice_event_log_;
rtc::AsyncInvoker invoker_ RTC_GUARDED_BY(network_thread_);
absl::optional<rtc::NetworkRoute> network_route_
RTC_GUARDED_BY(network_thread_);
webrtc::IceEventLog ice_event_log_ RTC_GUARDED_BY(network_thread_);
struct CandidateAndResolver final {
CandidateAndResolver(const Candidate& candidate,
@ -444,7 +481,7 @@ class RTC_EXPORT P2PTransportChannel : public IceTransportInternal {
Candidate candidate_;
rtc::AsyncResolverInterface* resolver_;
};
std::vector<CandidateAndResolver> resolvers_;
std::vector<CandidateAndResolver> resolvers_ RTC_GUARDED_BY(network_thread_);
void FinishAddingRemoteCandidate(const Candidate& new_remote_candidate);
void OnCandidateResolved(rtc::AsyncResolverInterface* resolver);
void AddRemoteCandidateWithResolver(Candidate candidate,