代码框图
SortConnectionsAndUpdateState
H:\webrtc-20210315\webrtc-20210315\webrtc\webrtc-checkout\src\p2p\base\p2p_transport_channel.cc
P2PTransportChannel::SortConnectionsAndUpdateState

// Sort the available connections to find the best one. We also monitor// the number of available connections and the current state.void P2PTransportChannel::SortConnectionsAndUpdateState(IceControllerEvent reason_to_sort) {RTC_DCHECK_RUN_ON(network_thread_);// Make sure the connection states are up-to-date since this affects how they// will be sorted.UpdateConnectionStates();// Any changes after this point will require a re-sort.sort_dirty_ = false;// If necessary, switch to the new choice. Note that |top_connection| doesn't// have to be writable to become the selected connection although it will// have higher priority if it is writable.MaybeSwitchSelectedConnection(reason_to_sort, ice_controller_->SortAndSwitchConnection(reason_to_sort));// The controlled side can prune only if the selected connection has been// nominated because otherwise it may prune the connection that will be// selected by the controlling side.// TODO(honghaiz): This is not enough to prevent a connection from being// pruned too early because with aggressive nomination, the controlling side// will nominate every connection until it becomes writable.if (ice_role_ == ICEROLE_CONTROLLING ||(selected_connection_ && selected_connection_->nominated())) {PruneConnections();}// Check if all connections are timedout.bool all_connections_timedout = true;for (const Connection* conn : connections()) {if (conn->write_state() != Connection::STATE_WRITE_TIMEOUT) {all_connections_timedout = false;break;}}// Now update the writable state of the channel with the information we have// so far.if (all_connections_timedout) {HandleAllTimedOut();}// Update the state of this channel.UpdateState();// Also possibly start pinging.// We could start pinging if:// * The first connection was created.// * ICE credentials were provided.// * A TCP connection became connected.MaybeStartPinging();}
BasicIceController::SortAndSwitchConnection


IceControllerInterface::SwitchResultBasicIceController::SortAndSwitchConnection(IceControllerEvent reason) {// Find the best alternative connection by sorting. It is important to note// that amongst equal preference, writable connections, this will choose the// one whose estimated latency is lowest. So it is the only one that we// need to consider switching to.// TODO(honghaiz): Don't sort; Just use std::max_element in the right places.absl::c_stable_sort(connections_, [this](const Connection* a, const Connection* b) {int cmp = CompareConnections(a, b, absl::nullopt, nullptr);if (cmp != 0) {return cmp > 0;}// Otherwise, sort based on latency estimate.return a->rtt() < b->rtt();});RTC_LOG(LS_VERBOSE) << "Sorting " << connections_.size()<< " available connections";for (size_t i = 0; i < connections_.size(); ++i) {RTC_LOG(LS_VERBOSE) << connections_[i]->ToString();}const Connection* top_connection =(!connections_.empty()) ? connections_[0] : nullptr;return ShouldSwitchConnection(reason, top_connection);}
依次比较,a b c d e , a和b比较,将结果b和c 比较,c和d比较。。。
BasicIceController::CompareConnections

remote_nomination提名
int BasicIceController::CompareConnections(const Connection* a,const Connection* b,absl::optional<int64_t> receiving_unchanged_threshold,bool* missed_receiving_unchanged_threshold) const {RTC_CHECK(a != nullptr);RTC_CHECK(b != nullptr);// We prefer to switch to a writable and receiving connection over a// non-writable or non-receiving connection, even if the latter has// been nominated by the controlling side.int state_cmp = CompareConnectionStates(a, b, receiving_unchanged_threshold,missed_receiving_unchanged_threshold);if (state_cmp != 0) {return state_cmp;}if (ice_role_func_() == 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->remote_nomination() > b->remote_nomination()) {return a_is_better;}if (a->remote_nomination() < b->remote_nomination()) {return b_is_better;}if (a->last_data_received() > b->last_data_received()) {return a_is_better;}if (a->last_data_received() < b->last_data_received()) {return b_is_better;}}// Compare the network cost and priority.return CompareConnectionCandidates(a, b);}
BasicIceController::CompareConnectionStates

// Compare two connections based on their writing, receiving, and connected// states.int BasicIceController::CompareConnectionStates(const Connection* a,const Connection* b,absl::optional<int64_t> receiving_unchanged_threshold,bool* missed_receiving_unchanged_threshold) const {// First, prefer a connection that's writable or presumed writable over// one that's not writable.bool a_writable = a->writable() || PresumedWritable(a);bool b_writable = b->writable() || PresumedWritable(b);if (a_writable && !b_writable) {return a_is_better;}if (!a_writable && b_writable) {return b_is_better;}// Sort based on write-state. Better states have lower values.if (a->write_state() < b->write_state()) {return a_is_better;}if (b->write_state() < a->write_state()) {return b_is_better;}// We prefer a receiving connection to a non-receiving, higher-priority// connection when sorting connections and choosing which connection to// switch to.if (a->receiving() && !b->receiving()) {return a_is_better;}if (!a->receiving() && b->receiving()) {if (!receiving_unchanged_threshold ||(a->receiving_unchanged_since() <= *receiving_unchanged_threshold &&b->receiving_unchanged_since() <= *receiving_unchanged_threshold)) {return b_is_better;}*missed_receiving_unchanged_threshold = true;}// WARNING: Some complexity here about TCP reconnecting.// When a TCP connection fails because of a TCP socket disconnecting, the// active side of the connection will attempt to reconnect for 5 seconds while// pretending to be writable (the connection is not set to the unwritable// state). On the passive side, the connection also remains writable even// though it is disconnected, and a new connection is created when the active// side connects. At that point, there are two TCP connections on the passive// side: 1. the old, disconnected one that is pretending to be writable, and// 2. the new, connected one that is maybe not yet writable. For purposes of// pruning, pinging, and selecting the selected connection, we want to treat// the new connection as "better" than the old one. We could add a method// called something like Connection::ImReallyBadEvenThoughImWritable, but that// is equivalent to the existing Connection::connected(), which we already// have. So, in code throughout this file, we'll check whether the connection// is connected() or not, and if it is not, treat it as "worse" than a// connected one, even though it's writable. In the code below, we're doing// so to make sure we treat a new writable connection as better than an old// disconnected connection.// In the case where we reconnect TCP connections, the original best// connection is disconnected without changing to WRITE_TIMEOUT. In this case,// the new connection, when it becomes writable, should have higher priority.if (a->write_state() == Connection::STATE_WRITABLE &&b->write_state() == Connection::STATE_WRITABLE) {if (a->connected() && !b->connected()) {return a_is_better;}if (!a->connected() && b->connected()) {return b_is_better;}}return 0;}
BasicIceController::CompareConnectionCandidates

// Compares two connections based only on the candidate and network information.// Returns positive if |a| is better than |b|.int BasicIceController::CompareConnectionCandidates(const Connection* a,const Connection* b) const {int compare_a_b_by_networks =CompareCandidatePairNetworks(a, b, config_.network_preference);if (compare_a_b_by_networks != a_and_b_equal) {return compare_a_b_by_networks;}// Compare connection priority. Lower values get sorted last.if (a->priority() > b->priority()) {return a_is_better;}if (a->priority() < b->priority()) {return b_is_better;}// If we're still tied at this point, prefer a younger generation.// (Younger generation means a larger generation number).int cmp = (a->remote_candidate().generation() + a->generation()) -(b->remote_candidate().generation() + b->generation());if (cmp != 0) {return cmp;}// A periodic regather (triggered by the regather_all_networks_interval_range)// will produce candidates that appear the same but would use a new port. We// want to use the new candidates and purge the old candidates as they come// in, so use the fact that the old ports get pruned immediately to rank the// candidates with an active port/remote candidate higher.bool a_pruned = is_connection_pruned_func_(a);bool b_pruned = is_connection_pruned_func_(b);if (!a_pruned && b_pruned) {return a_is_better;}if (a_pruned && !b_pruned) {return b_is_better;}// Otherwise, must be equalreturn 0;}
BasicIceController::CompareCandidatePairNetworks

int BasicIceController::CompareCandidatePairNetworks(const Connection* a,const Connection* b,absl::optional<rtc::AdapterType> network_preference) const {int compare_a_b_by_network_preference =CompareCandidatePairsByNetworkPreference(a, b,config_.network_preference);// The network preference has a higher precedence than the network cost.if (compare_a_b_by_network_preference != a_and_b_equal) {return compare_a_b_by_network_preference;}uint32_t a_cost = a->ComputeNetworkCost();uint32_t b_cost = b->ComputeNetworkCost();// Prefer lower network cost.if (a_cost < b_cost) {return a_is_better;}if (a_cost > b_cost) {return b_is_better;}return a_and_b_equal;}
CompareCandidatePairsByNetworkPreference
int CompareCandidatePairsByNetworkPreference(const cricket::Connection* a,const cricket::Connection* b,absl::optional<rtc::AdapterType> network_preference) {bool a_uses_preferred_network =LocalCandidateUsesPreferredNetwork(a, network_preference);bool b_uses_preferred_network =LocalCandidateUsesPreferredNetwork(b, network_preference);if (a_uses_preferred_network && !b_uses_preferred_network) {return a_is_better;} else if (!a_uses_preferred_network && b_uses_preferred_network) {return b_is_better;}return a_and_b_equal;}
