如果之前没有选择connection,则就用排序好的第一个connection。否则,就要将当前使用的connection和排序后的第一个connection做比较,看哪个更佳就选哪个。
续上一节。
BasicIceController::SortAndSwitchConnection
BasicIceController::ShouldSwitchConnection

selectedconnection 之前前选中的connection
new_connection 排序后的选中connection
IceControllerInterface::SwitchResult BasicIceController::ShouldSwitchConnection(IceControllerEvent reason,const Connection* new_connection) {if (!ReadyToSend(new_connection) || selected_connection_ == new_connection) {return {absl::nullopt, absl::nullopt};}if (selected_connection_ == nullptr) { // 第一次进来这里return HandleInitialSelectDampening(reason, new_connection);}// Do not switch to a connection that is not receiving if it is not on a// preferred network or it has higher cost because it may be just spuriously// better.int compare_a_b_by_networks = CompareCandidatePairNetworks(new_connection, selected_connection_, config_.network_preference);if (compare_a_b_by_networks == b_is_better && !new_connection->receiving()) {return {absl::nullopt, absl::nullopt};}bool missed_receiving_unchanged_threshold = false;absl::optional<int64_t> receiving_unchanged_threshold(rtc::TimeMillis() - config_.receiving_switching_delay_or_default());int cmp = CompareConnections(selected_connection_, new_connection,receiving_unchanged_threshold,&missed_receiving_unchanged_threshold);absl::optional<IceControllerEvent> recheck_event;if (missed_receiving_unchanged_threshold &&config_.receiving_switching_delay_or_default()) {// If we do not switch to the connection because it missed the receiving// threshold, the new connection is in a better receiving state than the// currently selected connection. So we need to re-check whether it needs// to be switched at a later time.recheck_event = reason;recheck_event->recheck_delay_ms =config_.receiving_switching_delay_or_default();}if (cmp < 0) {return {new_connection, absl::nullopt};} else if (cmp > 0) {return {absl::nullopt, recheck_event};}// If everything else is the same, switch only if rtt has improved by// a margin.if (new_connection->rtt() <= selected_connection_->rtt() - kMinImprovement) {return {new_connection, absl::nullopt};}return {absl::nullopt, recheck_event};}
BasicIceController::HandleInitialSelectDampening
如果一开始没有选出connection,则进来这里。

跟踪代码,只执行截图里面的if语句。。
IceControllerInterface::SwitchResultBasicIceController::HandleInitialSelectDampening(IceControllerEvent reason,const Connection* new_connection) {if (!field_trials_->initial_select_dampening.has_value() &&!field_trials_->initial_select_dampening_ping_received.has_value()) {// experiment not enabled => select connection.return {new_connection, absl::nullopt};}int64_t now = rtc::TimeMillis();int64_t max_delay = 0;if (new_connection->last_ping_received() > 0 &&field_trials_->initial_select_dampening_ping_received.has_value()) {max_delay = *field_trials_->initial_select_dampening_ping_received;} else if (field_trials_->initial_select_dampening.has_value()) {max_delay = *field_trials_->initial_select_dampening;}int64_t start_wait =initial_select_timestamp_ms_ == 0 ? now : initial_select_timestamp_ms_;int64_t max_wait_until = start_wait + max_delay;if (now >= max_wait_until) {RTC_LOG(LS_INFO) << "reset initial_select_timestamp_ = "<< initial_select_timestamp_ms_<< " selection delayed by: " << (now - start_wait) << "ms";initial_select_timestamp_ms_ = 0;return {new_connection, absl::nullopt};}// We are not yet ready to select first connection...if (initial_select_timestamp_ms_ == 0) {// Set timestamp on first time...// but run the delayed invokation everytime to// avoid possibility that we miss it.initial_select_timestamp_ms_ = now;RTC_LOG(LS_INFO) << "set initial_select_timestamp_ms_ = "<< initial_select_timestamp_ms_;}int min_delay = max_delay;if (field_trials_->initial_select_dampening.has_value()) {min_delay = std::min(min_delay, *field_trials_->initial_select_dampening);}if (field_trials_->initial_select_dampening_ping_received.has_value()) {min_delay = std::min(min_delay, *field_trials_->initial_select_dampening_ping_received);}RTC_LOG(LS_INFO) << "delay initial selection up to " << min_delay << "ms";reason.type = IceControllerEvent::ICE_CONTROLLER_RECHECK;reason.recheck_delay_ms = min_delay;return {absl::nullopt, reason};}
P2PTransportChannel::OnNominated(Connection* conn)
-》
P2PTransportChannel::MaybeSwitchSelectedConnection
P2PTransportChannel::SortConnectionsAndUpdateState
-》
P2PTransportChannel::MaybeSwitchSelectedConnection
P2PTransportChannel::MaybeSwitchSelectedConnection
P2PTransportChannel::SwitchSelectedConnection

到这里就已经完成了选择connection。
// Change the selected connection, and let listeners know.void P2PTransportChannel::SwitchSelectedConnection(Connection* conn,IceControllerEvent reason) {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_;selected_connection_ = conn;LogCandidatePairConfig(conn, webrtc::IceCandidatePairConfigType::kSelected);network_route_.reset();if (old_selected_connection) {old_selected_connection->set_selected(false);}if (selected_connection_) {++nomination_;selected_connection_->set_selected(true);if (old_selected_connection) {RTC_LOG(LS_INFO) << ToString() << ": Previous selected connection: "<< old_selected_connection->ToString();}RTC_LOG(LS_INFO) << ToString() << ": New selected connection: "<< selected_connection_->ToString();SignalRouteChange(this, selected_connection_->remote_candidate());// This is a temporary, but safe fix to webrtc issue 5705.// TODO(honghaiz): Make all ENOTCONN error routed through the transport// channel so that it knows whether the media channel is allowed to// send; then it will only signal ready-to-send if the media channel// has been disallowed to send.if (selected_connection_->writable() ||PresumedWritable(selected_connection_)) {SignalReadyToSend(this);}network_route_.emplace(rtc::NetworkRoute());network_route_->connected = ReadyToSend(selected_connection_);network_route_->local = CreateRouteEndpointFromCandidate(/* local= */ true, selected_connection_->local_candidate(),/* uses_turn= */ selected_connection_->port()->Type() ==RELAY_PORT_TYPE);network_route_->remote = CreateRouteEndpointFromCandidate(/* local= */ false, selected_connection_->remote_candidate(),/* uses_turn= */ selected_connection_->remote_candidate().type() ==RELAY_PORT_TYPE);network_route_->last_sent_packet_id = last_sent_packet_id_;network_route_->packet_overhead =selected_connection_->local_candidate().address().ipaddr().overhead() +GetProtocolOverhead(selected_connection_->local_candidate().protocol());} else {RTC_LOG(LS_INFO) << ToString() << ": No selected connection";}if (conn != nullptr && ice_role_ == ICEROLE_CONTROLLING &&((field_trials_.send_ping_on_switch_ice_controlling &&old_selected_connection != nullptr) ||field_trials_.send_ping_on_selected_ice_controlling)) {PingConnection(conn);MarkConnectionPinged(conn);}SignalNetworkRouteChanged(network_route_);// Create event for candidate pair change.if (selected_connection_) {CandidatePairChangeEvent pair_change;pair_change.reason = reason.ToString();pair_change.selected_candidate_pair = *GetSelectedCandidatePair();pair_change.last_data_received_ms =selected_connection_->last_data_received();if (old_selected_connection) {pair_change.estimated_disconnected_time_ms =ComputeEstimatedDisconnectedTimeMs(rtc::TimeMillis(),old_selected_connection);} else {pair_change.estimated_disconnected_time_ms = 0;}SignalCandidatePairChanged(pair_change);}++selected_candidate_pair_changes_;ice_controller_->SetSelectedConnection(selected_connection_);}
可能切换连接的几种情况

