H:\webrtc-20210315\webrtc-20210315\webrtc\webrtc-checkout\src\p2p\base\p2p_transport_channel.cc
你只能裁你同一个network上的connection,多主机上每个network最终都决胜一个最优的connection,最终的网路调整就在每个网卡的最优connection切换。
- 对于Controlling端,每次更新UpdateState后(Connection状态发生变动必然会触发UpdateState),就会面临裁剪.
- 对于Controlled端,只有当选出了Selected_Connection后,并nominated后才会进行裁剪.
https://zhuanlan.zhihu.com/p/443154955
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();
}
P2PTransportChannel::PruneConnections
void P2PTransportChannel::PruneConnections() {
RTC_DCHECK_RUN_ON(network_thread_);
std::vector<const Connection*> connections_to_prune =
ice_controller_->PruneConnections();
for (const Connection* conn : connections_to_prune) {
FromIceController(conn)->Prune();
}
}
PruneConnections
H:\webrtc-20210315\webrtc-20210315\webrtc\webrtc-checkout\src\p2p\base\basic_ice_controller.cc
获取可以裁剪的connections
std::vector<const Connection*> BasicIceController::PruneConnections() {
// We can prune any connection for which there is a connected, writable
// connection on the same network with better or equal priority. We leave
// those with better priority just in case they become writable later (at
// which point, we would prune out the current selected connection). We leave
// connections on other networks because they may not be using the same
// resources and they may represent very distinct paths over which we can
// switch. If |best_conn_on_network| is not connected, we may be reconnecting
// a TCP connection and should not prune connections in this network.
// See the big comment in CompareConnectionStates.
//
// An exception is made for connections on an "any address" network, meaning
// 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.
std::vector<const Connection*> connections_to_prune;
auto best_connection_by_network = GetBestConnectionByNetwork();
for (const Connection* conn : connections_) {
const Connection* best_conn = selected_connection_;
if (!rtc::IPIsAny(conn->network()->ip())) {
// If the connection is bound to a specific network interface (not an
// "any address" network), compare it against the best connection for
// that network interface rather than the best connection overall. This
// ensures that at least one connection per network will be left
// unpruned.
best_conn = best_connection_by_network[conn->network()];
}
// Do not prune connections if the connection being compared against is
// weak. Otherwise, it may delete connections prematurely.
if (best_conn && conn != best_conn && !best_conn->weak() &&
CompareConnectionCandidates(best_conn, conn) >= 0) {
connections_to_prune.push_back(conn);
}
}
return connections_to_prune;
}
BasicIceController::GetBestConnectionByNetwork
遍历所有连接的connections_,获取每个网络的最优connection。
std::map<const rtc::Network*, const Connection*>
BasicIceController::GetBestConnectionByNetwork() const {
// |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.
std::map<const rtc::Network*, const Connection*> best_connection_by_network;
if (selected_connection_) {
best_connection_by_network[selected_connection_->network()] =
selected_connection_;
}
// TODO(honghaiz): Need to update this if |connections_| are not sorted.
for (const Connection* conn : connections_) {
const rtc::Network* network = conn->network();
// This only inserts when the network does not exist in the map.
best_connection_by_network.insert(std::make_pair(network, conn));
}
return best_connection_by_network;
}
Connection::Prune
此时,裁剪的connection已经被标记了,然后等待这些资源被释放掉。