Index: webrtc/p2p/base/p2ptransportchannel.cc |
diff --git a/webrtc/p2p/base/p2ptransportchannel.cc b/webrtc/p2p/base/p2ptransportchannel.cc |
index b32d149a84941ba56ef94746bad1b8780c771d0f..ec1dfc733f80ed3275038b17608f9cd6531aff9f 100644 |
--- a/webrtc/p2p/base/p2ptransportchannel.cc |
+++ b/webrtc/p2p/base/p2ptransportchannel.cc |
@@ -403,6 +403,12 @@ void P2PTransportChannel::SetIceConfig(const IceConfig& config) { |
LOG(LS_INFO) << "Set receiving_switching_delay to" |
<< *config_.receiving_switching_delay; |
} |
+ |
+ if (config_.default_nomination_mode != config.default_nomination_mode) { |
+ config_.default_nomination_mode = config.default_nomination_mode; |
+ LOG(LS_INFO) << "Set default nomination mode to " |
+ << static_cast<int>(config_.default_nomination_mode); |
+ } |
} |
const IceConfig& P2PTransportChannel::config() const { |
@@ -1140,10 +1146,10 @@ int P2PTransportChannel::CompareConnections( |
if (ice_role_ == ICEROLE_CONTROLLED) { |
// Compare the connections based on the nomination states and the last data |
// received time if this is on the controlled side. |
- if (a->nominated() && !b->nominated()) { |
+ if (a->remote_nomination() > b->remote_nomination()) { |
return a_is_better; |
} |
- if (!a->nominated() && b->nominated()) { |
+ if (a->remote_nomination() < b->remote_nomination()) { |
return b_is_better; |
} |
@@ -1285,6 +1291,7 @@ void P2PTransportChannel::SwitchSelectedConnection(Connection* conn) { |
Connection* old_selected_connection = selected_connection_; |
selected_connection_ = conn; |
if (selected_connection_) { |
+ ++nomination_; |
if (old_selected_connection) { |
LOG_J(LS_INFO, this) << "Previous selected connection: " |
<< old_selected_connection->ToString(); |
@@ -1585,32 +1592,66 @@ void P2PTransportChannel::MarkConnectionPinged(Connection* conn) { |
} |
// Apart from sending ping from |conn| this method also updates |
-// |use_candidate_attr| flag. The criteria to update this flag is |
-// explained below. |
-// Set USE-CANDIDATE if doing ICE AND this channel is in CONTROLLING AND |
-// a) Channel is in FULL ICE AND |
-// a.1) |conn| is the selected connection OR |
-// a.2) there is no selected connection OR |
-// a.3) the selected connection is unwritable OR |
-// a.4) |conn| has higher priority than selected_connection. |
-// b) we're doing LITE ICE AND |
-// b.1) |conn| is the selected_connection AND |
-// b.2) |conn| is writable. |
+// |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) { |
- bool use_candidate = false; |
- if (remote_ice_mode_ == ICEMODE_FULL && ice_role_ == ICEROLE_CONTROLLING) { |
- use_candidate = |
- (conn == selected_connection_) || (selected_connection_ == NULL) || |
- (!selected_connection_->writable()) || |
- (CompareConnectionCandidates(selected_connection_, conn) < 0); |
- } else if (remote_ice_mode_ == ICEMODE_LITE && conn == selected_connection_) { |
- use_candidate = selected_connection_->writable(); |
- } |
- conn->set_use_candidate_attr(use_candidate); |
+ bool use_candidate_attr = false; |
+ uint32_t nomination = 0; |
+ if (ice_role_ == ICEROLE_CONTROLLING) { |
+ if (remote_supports_renomination_) { |
+ nomination = GetNominationAttr(conn); |
+ } else { |
+ use_candidate_attr = |
+ GetUseCandidateAttr(conn, config_.default_nomination_mode); |
+ } |
+ } |
+ conn->set_nomination(nomination); |
+ conn->set_use_candidate_attr(use_candidate_attr); |
last_ping_sent_ms_ = rtc::TimeMillis(); |
conn->Ping(last_ping_sent_ms_); |
} |
+uint32_t P2PTransportChannel::GetNominationAttr(Connection* conn) const { |
+ return (conn == selected_connection_) ? nomination_ : 0; |
+} |
+ |
+// Nominate a connection based on the NominationMode. |
+bool P2PTransportChannel::GetUseCandidateAttr(Connection* conn, |
+ NominationMode mode) const { |
+ switch (mode) { |
+ case NominationMode::REGULAR: |
+ // TODO(honghaiz): Implement regular nomination. |
+ return false; |
+ case NominationMode::AGGRESSIVE: |
+ if (remote_ice_mode_ == ICEMODE_LITE) { |
+ return GetUseCandidateAttr(conn, NominationMode::REGULAR); |
+ } |
+ return true; |
+ case NominationMode::SEMI_AGGRESSIVE: { |
+ // Nominate if |
+ // a) Remote is in FULL ICE AND |
+ // a.1) |conn| is the selected connection OR |
+ // a.2) there is no selected connection OR |
+ // a.3) the selected connection is unwritable OR |
+ // a.4) |conn| has higher priority than selected_connection. |
+ // b) Remote is in LITE ICE AND |
+ // b.1) |conn| is the selected_connection AND |
+ // b.2) |conn| is writable. |
+ bool selected = conn == selected_connection_; |
+ if (remote_ice_mode_ == ICEMODE_LITE) { |
+ return selected && conn->writable(); |
+ } |
+ bool better_than_selected = |
+ !selected_connection_ || !selected_connection_->writable() || |
+ CompareConnectionCandidates(selected_connection_, conn) < 0; |
+ return selected || better_than_selected; |
+ } |
+ default: |
+ RTC_DCHECK(false); |
+ return false; |
+ } |
+} |
+ |
// When a connection's state changes, we need to figure out who to use as |
// the selected connection again. It could have become usable, or become |
// unusable. |