Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(346)

Unified Diff: webrtc/p2p/base/p2ptransportchannel.cc

Issue 2069493002: Do not switch best connection on the controlled side too frequently (Closed) Base URL: https://chromium.googlesource.com/external/webrtc@master
Patch Set: Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: webrtc/p2p/base/p2ptransportchannel.cc
diff --git a/webrtc/p2p/base/p2ptransportchannel.cc b/webrtc/p2p/base/p2ptransportchannel.cc
index fc1f0a4e6769ee96ce28f851d0f7cbc368fbf69c..7b5e1e70e9b6af1c51c35f7d02b79ec5354e13d9 100644
--- a/webrtc/p2p/base/p2ptransportchannel.cc
+++ b/webrtc/p2p/base/p2ptransportchannel.cc
@@ -200,6 +200,39 @@ bool ShouldSwitch(cricket::Connection* a_conn,
return b_conn->rtt() <= a_conn->rtt() + kMinImprovement;
}
+// Determines whether we should switch the best connection to |new_connection|
+// based the writable state, the last nominated connection, and the last
+// connection receiving data. This is to prevent that the controlled side may
+// switch the best connection too frequently when the controlling side is doing
+// aggressive nominations. With this implementation, the controlled side will
+// switch the best connection if the new nominated connection is writable, and
+// i) the best connection is nullptr, or
+// ii) the best connection was not nominated, or
+// iii) the new connection has been nominated twice consecutively, or
+// iv) the new connection is nominated and is receiving data, or
+// v) the new connection has lower cost or high priority.
+// TODO(honghaiz): Stop the aggressive nomination on the controlling side and
+// implement the ice-renomination option.
+bool ShouldSwitchOnNominatedOrDataReceived(
+ cricket::Connection* best_connection,
+ cricket::Connection* new_connection,
+ cricket::Connection* last_nominated,
+ cricket::Connection* last_data_received) {
+ RTC_CHECK(new_connection != nullptr);
+ if (!new_connection->writable()) {
+ return false;
+ }
+ if (best_connection == nullptr || !best_connection->nominated()) {
+ return true;
+ }
+ if (new_connection == last_nominated ||
+ new_connection == last_data_received) {
+ return true;
+ }
+ // Compare the network cost and priority.
+ return CompareConnectionCandidates(best_connection, new_connection) < 0;
+}
+
} // unnamed namespace
namespace cricket {
@@ -238,8 +271,6 @@ P2PTransportChannel::P2PTransportChannel(const std::string& transport_name,
worker_thread_(rtc::Thread::Current()),
incoming_only_(false),
error_(0),
- best_connection_(NULL),
- pending_best_connection_(NULL),
sort_dirty_(false),
remote_ice_mode_(ICEMODE_FULL),
ice_role_(ICEROLE_UNKNOWN),
@@ -729,20 +760,25 @@ void P2PTransportChannel::OnNominated(Connection* conn) {
ASSERT(worker_thread_ == rtc::Thread::Current());
ASSERT(ice_role_ == ICEROLE_CONTROLLED);
- if (conn->write_state() == Connection::STATE_WRITABLE) {
- if (best_connection_ != conn) {
- pending_best_connection_ = NULL;
- LOG(LS_INFO) << "Switching best connection on controlled side: "
- << conn->ToString();
- SwitchBestConnectionTo(conn);
- // Now we have selected the best connection, time to prune other existing
- // connections and update the read/write state of the channel.
- RequestSort();
- }
+ if (best_connection_ == conn) {
+ return;
+ }
+
+ if (ShouldSwitchOnNominatedOrDataReceived(best_connection_, conn,
+ last_nominated_conn_,
+ last_data_received_conn_)) {
+ last_nominated_conn_ = nullptr;
+ last_data_received_conn_ = nullptr;
+ LOG(LS_INFO) << "Switching best connection on controlled side: "
+ << conn->ToString();
+ SwitchBestConnectionTo(conn);
+ // Now we have selected the best connection, time to prune other existing
+ // connections and update the read/write state of the channel.
+ RequestSort();
} else {
- LOG(LS_INFO) << "Not switching the best connection on controlled side yet,"
- << " because it's not writable: " << conn->ToString();
- pending_best_connection_ = conn;
+ LOG(LS_INFO) << "Not switching the best connection on controlled side yet: "
+ << conn->ToString();
+ last_nominated_conn_ = conn;
}
}
@@ -1444,9 +1480,18 @@ void P2PTransportChannel::OnConnectionStateChange(Connection* connection) {
// Update the best connection if the state change is from pending best
// connection and role is controlled.
- if (ice_role_ == ICEROLE_CONTROLLED) {
- if (connection == pending_best_connection_ && connection->writable()) {
- pending_best_connection_ = NULL;
+ if (ice_role_ == ICEROLE_CONTROLLED && connection == last_nominated_conn_) {
+ // This essentially requires that the connection is both last nominated
+ // and receiving data, or the best connection is nullptr, in order
+ // to switch to |connection|.
+ if (connection == best_connection_) {
+ // If it is already the best connection, reset the last_nominated_conn_
+ last_nominated_conn_ = nullptr;
+ } else if (ShouldSwitchOnNominatedOrDataReceived(
+ best_connection_, connection, nullptr,
+ last_data_received_conn_)) {
+ last_nominated_conn_ = nullptr;
+ last_data_received_conn_ = nullptr;
LOG(LS_INFO) << "Switching best connection on controlled side"
<< " because it's now writable: " << connection->ToString();
SwitchBestConnectionTo(connection);
@@ -1489,8 +1534,8 @@ void P2PTransportChannel::OnConnectionDestroyed(Connection* connection) {
LOG_J(LS_INFO, this) << "Removed connection ("
<< static_cast<int>(connections_.size()) << " remaining)";
- if (pending_best_connection_ == connection) {
- pending_best_connection_ = NULL;
+ if (last_nominated_conn_ == connection) {
+ last_nominated_conn_ = nullptr;
}
// If this is currently the best connection, then we need to pick a new one.
@@ -1559,9 +1604,17 @@ void P2PTransportChannel::OnReadPacket(Connection* connection,
// May need to switch the sending connection based on the receiving media path
// if this is the controlled side.
- if (ice_role_ == ICEROLE_CONTROLLED && !best_nominated_connection() &&
- connection->writable() && best_connection_ != connection) {
+ if (ice_role_ != ICEROLE_CONTROLLED || best_connection_ == connection) {
+ return;
+ }
+
+ if (ShouldSwitchOnNominatedOrDataReceived(best_connection_, connection,
+ last_nominated_conn_, nullptr)) {
SwitchBestConnectionTo(connection);
+ last_data_received_conn_ = nullptr;
+ last_nominated_conn_ = nullptr;
+ } else {
+ last_data_received_conn_ = connection;
}
}
« webrtc/p2p/base/p2ptransportchannel.h ('K') | « webrtc/p2p/base/p2ptransportchannel.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698