H:\webrtc-20210315\webrtc-20210315\webrtc\webrtc-checkout\src\p2p\base\p2p_transport_channel.cc
你只能裁你同一个network上的connection,多主机上每个network最终都决胜一个最优的connection,最终的网路调整就在每个网卡的最优connection切换。

  1. 对于Controlling端,每次更新UpdateState后(Connection状态发生变动必然会触发UpdateState),就会面临裁剪.
  2. 对于Controlled端,只有当选出了Selected_Connection后,并nominated后才会进行裁剪.

https://zhuanlan.zhihu.com/p/443154955

SortConnectionsAndUpdateState

image.png

  1. // Sort the available connections to find the best one. We also monitor
  2. // the number of available connections and the current state.
  3. void P2PTransportChannel::SortConnectionsAndUpdateState(
  4. IceControllerEvent reason_to_sort) {
  5. RTC_DCHECK_RUN_ON(network_thread_);
  6. // Make sure the connection states are up-to-date since this affects how they
  7. // will be sorted.
  8. UpdateConnectionStates();
  9. // Any changes after this point will require a re-sort.
  10. sort_dirty_ = false;
  11. // If necessary, switch to the new choice. Note that |top_connection| doesn't
  12. // have to be writable to become the selected connection although it will
  13. // have higher priority if it is writable.
  14. MaybeSwitchSelectedConnection(
  15. reason_to_sort, ice_controller_->SortAndSwitchConnection(reason_to_sort));
  16. // The controlled side can prune only if the selected connection has been
  17. // nominated because otherwise it may prune the connection that will be
  18. // selected by the controlling side.
  19. // TODO(honghaiz): This is not enough to prevent a connection from being
  20. // pruned too early because with aggressive nomination, the controlling side
  21. // will nominate every connection until it becomes writable.
  22. if (ice_role_ == ICEROLE_CONTROLLING ||
  23. (selected_connection_ && selected_connection_->nominated())) {
  24. PruneConnections();
  25. }
  26. // Check if all connections are timedout.
  27. bool all_connections_timedout = true;
  28. for (const Connection* conn : connections()) {
  29. if (conn->write_state() != Connection::STATE_WRITE_TIMEOUT) {
  30. all_connections_timedout = false;
  31. break;
  32. }
  33. }
  34. // Now update the writable state of the channel with the information we have
  35. // so far.
  36. if (all_connections_timedout) {
  37. HandleAllTimedOut();
  38. }
  39. // Update the state of this channel.
  40. UpdateState();
  41. // Also possibly start pinging.
  42. // We could start pinging if:
  43. // * The first connection was created.
  44. // * ICE credentials were provided.
  45. // * A TCP connection became connected.
  46. MaybeStartPinging();
  47. }

P2PTransportChannel::PruneConnections

image.png

  1. void P2PTransportChannel::PruneConnections() {
  2. RTC_DCHECK_RUN_ON(network_thread_);
  3. std::vector<const Connection*> connections_to_prune =
  4. ice_controller_->PruneConnections();
  5. for (const Connection* conn : connections_to_prune) {
  6. FromIceController(conn)->Prune();
  7. }
  8. }

PruneConnections

H:\webrtc-20210315\webrtc-20210315\webrtc\webrtc-checkout\src\p2p\base\basic_ice_controller.cc
获取可以裁剪的connections
image.png

  1. std::vector<const Connection*> BasicIceController::PruneConnections() {
  2. // We can prune any connection for which there is a connected, writable
  3. // connection on the same network with better or equal priority. We leave
  4. // those with better priority just in case they become writable later (at
  5. // which point, we would prune out the current selected connection). We leave
  6. // connections on other networks because they may not be using the same
  7. // resources and they may represent very distinct paths over which we can
  8. // switch. If |best_conn_on_network| is not connected, we may be reconnecting
  9. // a TCP connection and should not prune connections in this network.
  10. // See the big comment in CompareConnectionStates.
  11. //
  12. // An exception is made for connections on an "any address" network, meaning
  13. // not bound to any specific network interface. We don't want to keep one of
  14. // these alive as a backup, since it could be using the same network
  15. // interface as the higher-priority, selected candidate pair.
  16. std::vector<const Connection*> connections_to_prune;
  17. auto best_connection_by_network = GetBestConnectionByNetwork();
  18. for (const Connection* conn : connections_) {
  19. const Connection* best_conn = selected_connection_;
  20. if (!rtc::IPIsAny(conn->network()->ip())) {
  21. // If the connection is bound to a specific network interface (not an
  22. // "any address" network), compare it against the best connection for
  23. // that network interface rather than the best connection overall. This
  24. // ensures that at least one connection per network will be left
  25. // unpruned.
  26. best_conn = best_connection_by_network[conn->network()];
  27. }
  28. // Do not prune connections if the connection being compared against is
  29. // weak. Otherwise, it may delete connections prematurely.
  30. if (best_conn && conn != best_conn && !best_conn->weak() &&
  31. CompareConnectionCandidates(best_conn, conn) >= 0) {
  32. connections_to_prune.push_back(conn);
  33. }
  34. }
  35. return connections_to_prune;
  36. }

BasicIceController::GetBestConnectionByNetwork

遍历所有连接的connections_,获取每个网络的最优connection。

image.png

  1. std::map<const rtc::Network*, const Connection*>
  2. BasicIceController::GetBestConnectionByNetwork() const {
  3. // |connections_| has been sorted, so the first one in the list on a given
  4. // network is the best connection on the network, except that the selected
  5. // connection is always the best connection on the network.
  6. std::map<const rtc::Network*, const Connection*> best_connection_by_network;
  7. if (selected_connection_) {
  8. best_connection_by_network[selected_connection_->network()] =
  9. selected_connection_;
  10. }
  11. // TODO(honghaiz): Need to update this if |connections_| are not sorted.
  12. for (const Connection* conn : connections_) {
  13. const rtc::Network* network = conn->network();
  14. // This only inserts when the network does not exist in the map.
  15. best_connection_by_network.insert(std::make_pair(network, conn));
  16. }
  17. return best_connection_by_network;
  18. }

Connection::Prune

image.png
此时,裁剪的connection已经被标记了,然后等待这些资源被释放掉。