From 663bdb46c9dbb850d64c2ec4ba3a94a60b098bd6 Mon Sep 17 00:00:00 2001 From: Dan Baker Date: Mon, 9 Jan 2023 16:02:27 -0700 Subject: [PATCH] Bug 1806510 - Vendor libwebrtc from 64edb15e1e Upstream commit: https://webrtc.googlesource.com/src/+/64edb15e1e5bb86bbcb78f0e8be0a6559097f3f3 Make P2PTransportChannel implement IceAgentInterface (#5/n) This functionally no-op change adds the methods to allow an active ICE controller to manipulate the connection used by the ICE transport. Most methods reuse existing code, this will be explicitly marked for cleanup with a follow-up CL which adds active ICE controller support. Non-trivial changes are needed for P2PTransportChannel unit tests to cover the new code, and these are also being added in a follow-up CL. Bug: webrtc:14367, webrtc:14131 Change-Id: I4f012efcd8cb5766eb8c6f0872de50f8375f3a73 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/275301 Reviewed-by: Jonas Oreland Commit-Queue: Sameer Vijaykar Cr-Commit-Position: refs/heads/main@{#38081} --- third_party/libwebrtc/README.moz-ff-commit | 3 + third_party/libwebrtc/README.mozilla | 2 + .../p2p/base/p2p_transport_channel.cc | 160 +++++++++++++----- .../p2p/base/p2p_transport_channel.h | 26 ++- 4 files changed, 143 insertions(+), 48 deletions(-) diff --git a/third_party/libwebrtc/README.moz-ff-commit b/third_party/libwebrtc/README.moz-ff-commit index 3412db7d229a9..5138408c19159 100644 --- a/third_party/libwebrtc/README.moz-ff-commit +++ b/third_party/libwebrtc/README.moz-ff-commit @@ -17802,3 +17802,6 @@ c898c82884 # MOZ_LIBWEBRTC_SRC=/Users/danielbaker/moz-libwebrtc MOZ_LIBWEBRTC_COMMIT=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh # base of lastest vendoring 18408391ad +# MOZ_LIBWEBRTC_SRC=/Users/danielbaker/moz-libwebrtc MOZ_LIBWEBRTC_COMMIT=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh +# base of lastest vendoring +64edb15e1e diff --git a/third_party/libwebrtc/README.mozilla b/third_party/libwebrtc/README.mozilla index ff7ce5432c30a..cd0bf641d9b42 100644 --- a/third_party/libwebrtc/README.mozilla +++ b/third_party/libwebrtc/README.mozilla @@ -11890,3 +11890,5 @@ libwebrtc updated from /Users/danielbaker/moz-libwebrtc commit mozpatches on 202 libwebrtc updated from /Users/danielbaker/moz-libwebrtc commit mozpatches on 2023-01-09T22:59:53.109826. # ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/danielbaker/moz-libwebrtc --commit mozpatches libwebrtc libwebrtc updated from /Users/danielbaker/moz-libwebrtc commit mozpatches on 2023-01-09T23:01:12.545588. +# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/danielbaker/moz-libwebrtc --commit mozpatches libwebrtc +libwebrtc updated from /Users/danielbaker/moz-libwebrtc commit mozpatches on 2023-01-09T23:02:20.336741. diff --git a/third_party/libwebrtc/p2p/base/p2p_transport_channel.cc b/third_party/libwebrtc/p2p/base/p2p_transport_channel.cc index 82d77bba4b1ca..6cc82b826b75d 100644 --- a/third_party/libwebrtc/p2p/base/p2p_transport_channel.cc +++ b/third_party/libwebrtc/p2p/base/p2p_transport_channel.cc @@ -324,6 +324,13 @@ bool P2PTransportChannel::MaybeSwitchSelectedConnection( return result.connection.has_value(); } +void P2PTransportChannel::ForgetLearnedStateForConnections( + std::vector connections) { + for (const Connection* con : connections) { + FromIceController(con)->ForgetLearnedState(); + } +} + void P2PTransportChannel::SetIceRole(IceRole ice_role) { RTC_DCHECK_RUN_ON(network_thread_); if (ice_role_ != ice_role) { @@ -1207,8 +1214,7 @@ void P2PTransportChannel::OnNominated(Connection* conn) { if (ice_field_trials_.send_ping_on_nomination_ice_controlled && conn != nullptr) { - PingConnection(conn); - MarkConnectionPinged(conn); + SendPingRequestInternal(conn); } // TODO(qingsi): RequestSortAndStateUpdate will eventually call @@ -1747,6 +1753,14 @@ void P2PTransportChannel::MaybeStartPinging() { } } +void P2PTransportChannel::OnStartedPinging() { + RTC_DCHECK_RUN_ON(network_thread_); + RTC_LOG(LS_INFO) << ToString() + << ": Have a pingable connection for the first time; " + "starting to ping."; + regathering_controller_->Start(); +} + bool P2PTransportChannel::IsPortPruned(const Port* port) const { RTC_DCHECK_RUN_ON(network_thread_); return !absl::c_linear_search(ports_, port); @@ -1791,8 +1805,7 @@ void P2PTransportChannel::SortConnectionsAndUpdateState( // 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())) { + if (AllowedToPruneConnections()) { PruneConnections(); } @@ -1812,7 +1825,7 @@ void P2PTransportChannel::SortConnectionsAndUpdateState( } // Update the state of this channel. - UpdateState(); + UpdateTransportState(); // Also possibly start pinging. // We could start pinging if: @@ -1822,13 +1835,51 @@ void P2PTransportChannel::SortConnectionsAndUpdateState( MaybeStartPinging(); } +void P2PTransportChannel::UpdateState() { + // 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. + UpdateTransportState(); +} + +bool P2PTransportChannel::AllowedToPruneConnections() const { + RTC_DCHECK_RUN_ON(network_thread_); + return ice_role_ == ICEROLE_CONTROLLING || + (selected_connection_ && selected_connection_->nominated()); +} + +// TODO(bugs.webrtc.org/14367) remove once refactor lands. void P2PTransportChannel::PruneConnections() { RTC_DCHECK_RUN_ON(network_thread_); std::vector connections_to_prune = ice_controller_->PruneConnections(); - for (const Connection* conn : connections_to_prune) { + PruneConnections(connections_to_prune); +} + +bool P2PTransportChannel::PruneConnections( + std::vector connections) { + RTC_DCHECK_RUN_ON(network_thread_); + if (!AllowedToPruneConnections()) { + RTC_LOG(LS_WARNING) << "Not allowed to prune connections"; + return false; + } + for (const Connection* conn : connections) { FromIceController(conn)->Prune(); } + return true; } rtc::NetworkRoute P2PTransportChannel::ConfigureNetworkRoute( @@ -1849,9 +1900,17 @@ rtc::NetworkRoute P2PTransportChannel::ConfigureNetworkRoute( GetProtocolOverhead(conn->local_candidate().protocol())}; } +void P2PTransportChannel::SwitchSelectedConnection( + const Connection* new_connection, + IceSwitchReason reason) { + RTC_DCHECK_RUN_ON(network_thread_); + SwitchSelectedConnectionInternal(FromIceController(new_connection), reason); +} + // Change the selected connection, and let listeners know. -void P2PTransportChannel::SwitchSelectedConnection(Connection* conn, - IceSwitchReason reason) { +void P2PTransportChannel::SwitchSelectedConnectionInternal( + Connection* conn, + IceSwitchReason reason) { RTC_DCHECK_RUN_ON(network_thread_); // Note: if conn is NULL, the previous `selected_connection_` has been // destroyed, so don't use it. @@ -1891,8 +1950,7 @@ void P2PTransportChannel::SwitchSelectedConnection(Connection* conn, ((ice_field_trials_.send_ping_on_switch_ice_controlling && old_selected_connection != nullptr) || ice_field_trials_.send_ping_on_selected_ice_controlling)) { - PingConnection(conn); - MarkConnectionPinged(conn); + SendPingRequestInternal(conn); } SignalNetworkRouteChanged(network_route_); @@ -1931,13 +1989,14 @@ int64_t P2PTransportChannel::ComputeEstimatedDisconnectedTimeMs( return (now_ms - last_data_or_old_ping); } -// Warning: UpdateState should eventually be called whenever a connection -// is added, deleted, or the write state of any connection changes so that the -// transport controller will get the up-to-date channel state. However it -// should not be called too often; in the case that multiple connection states -// change, it should be called after all the connection states have changed. For -// example, we call this at the end of SortConnectionsAndUpdateState. -void P2PTransportChannel::UpdateState() { +// Warning: UpdateTransportState should eventually be called whenever a +// connection is added, deleted, or the write state of any connection changes +// so that the transport controller will get the up-to-date channel state. +// However it should not be called too often; in the case that multiple +// connection states change, it should be called after all the connection +// states have changed. For example, we call this at the end of +// SortConnectionsAndUpdateState. +void P2PTransportChannel::UpdateTransportState() { RTC_DCHECK_RUN_ON(network_thread_); // If our selected connection is "presumed writable" (TURN-TURN with no // CreatePermission required), act like we're already writable to the upper @@ -1965,8 +2024,8 @@ void P2PTransportChannel::UpdateState() { << static_cast(state_) << " to " << static_cast(state); // Check that the requested transition is allowed. Note that - // P2PTransportChannel does not (yet) implement a direct mapping of the ICE - // states from the standard; the difference is covered by + // P2PTransportChannel does not (yet) implement a direct mapping of the + // ICE states from the standard; the difference is covered by // TransportController and PeerConnection. switch (state_) { case IceTransportState::STATE_INIT: @@ -2031,7 +2090,7 @@ void P2PTransportChannel::OnSelectedConnectionDestroyed() { RTC_DCHECK_RUN_ON(network_thread_); RTC_LOG(LS_INFO) << "Selected connection destroyed. Will choose a new one."; IceSwitchReason reason = IceSwitchReason::SELECTED_CONNECTION_DESTROYED; - SwitchSelectedConnection(nullptr, reason); + SwitchSelectedConnectionInternal(nullptr, reason); RequestSortAndStateUpdate(reason); } @@ -2068,17 +2127,15 @@ bool P2PTransportChannel::ReadyToSend(const Connection* connection) const { // Handle queued up check-and-ping request void P2PTransportChannel::CheckAndPing() { RTC_DCHECK_RUN_ON(network_thread_); - // Make sure the states of the connections are up-to-date (since this affects - // which ones are pingable). + // Make sure the states of the connections are up-to-date (since this + // affects which ones are pingable). UpdateConnectionStates(); auto result = ice_controller_->SelectConnectionToPing(last_ping_sent_ms_); TimeDelta delay = TimeDelta::Millis(result.recheck_delay_ms); if (result.connection.value_or(nullptr)) { - Connection* conn = FromIceController(*result.connection); - PingConnection(conn); - MarkConnectionPinged(conn); + SendPingRequest(result.connection.value()); } network_thread_->PostDelayedTask( @@ -2096,8 +2153,25 @@ Connection* P2PTransportChannel::FindNextPingableConnection() { } } +int64_t P2PTransportChannel::GetLastPingSentMs() const { + RTC_DCHECK_RUN_ON(network_thread_); + return last_ping_sent_ms_; +} + +void P2PTransportChannel::SendPingRequest(const Connection* connection) { + RTC_DCHECK_RUN_ON(network_thread_); + SendPingRequestInternal(FromIceController(connection)); +} + +void P2PTransportChannel::SendPingRequestInternal(Connection* connection) { + RTC_DCHECK_RUN_ON(network_thread_); + PingConnection(connection); + MarkConnectionPinged(connection); +} + // A connection is considered a backup connection if the channel state -// is completed, the connection is not the selected connection and it is active. +// is completed, the connection is not the selected connection and it is +// active. void P2PTransportChannel::MarkConnectionPinged(Connection* conn) { RTC_DCHECK_RUN_ON(network_thread_); ice_controller_->MarkConnectionPinged(conn); @@ -2147,8 +2221,8 @@ void P2PTransportChannel::OnConnectionStateChange(Connection* connection) { // May stop the allocator session when at least one connection becomes // strongly connected after starting to get ports and the local candidate of // the connection is at the latest generation. It is not enough to check - // that the connection becomes weakly connected because the connection may be - // changing from (writable, receiving) to (writable, not receiving). + // that the connection becomes weakly connected because the connection may + // be changing from (writable, receiving) to (writable, not receiving). if (ice_field_trials_.stop_gather_on_strongly_connected) { bool strongly_connected = !connection->weak(); bool latest_generation = connection->local_candidate().generation() >= @@ -2181,16 +2255,16 @@ void P2PTransportChannel::OnConnectionDestroyed(Connection* connection) { // If this is currently the selected connection, then we need to pick a new // one. The call to SortConnectionsAndUpdateState will pick a new one. It // looks at the current selected connection in order to avoid switching - // between fairly similar ones. Since this connection is no longer an option, - // we can just set selected to nullptr and re-choose a best assuming that - // there was no selected connection. + // between fairly similar ones. Since this connection is no longer an + // option, we can just set selected to nullptr and re-choose a best assuming + // that there was no selected connection. if (selected_connection_ == connection) { OnSelectedConnectionDestroyed(); } else { - // If a non-selected connection was destroyed, we don't need to re-sort but - // we do need to update state, because we could be switching to "failed" or - // "completed". - UpdateState(); + // If a non-selected connection was destroyed, we don't need to re-sort + // but we do need to update state, because we could be switching to + // "failed" or "completed". + UpdateTransportState(); } } @@ -2231,9 +2305,9 @@ void P2PTransportChannel::OnCandidatesRemoved( PortAllocatorSession* session, const std::vector& candidates) { RTC_DCHECK_RUN_ON(network_thread_); - // Do not signal candidate removals if continual gathering is not enabled, or - // if this is not the last session because an ICE restart would have signaled - // the remote side to remove all candidates in previous sessions. + // Do not signal candidate removals if continual gathering is not enabled, + // or if this is not the last session because an ICE restart would have + // signaled the remote side to remove all candidates in previous sessions. if (!config_.gather_continually() || session != allocator_session()) { return; } @@ -2255,7 +2329,8 @@ void P2PTransportChannel::PruneAllPorts() { bool P2PTransportChannel::PrunePort(PortInterface* port) { RTC_DCHECK_RUN_ON(network_thread_); auto it = absl::c_find(ports_, port); - // Don't need to do anything if the port has been deleted from the port list. + // Don't need to do anything if the port has been deleted from the port + // list. if (it == ports_.end()) { return false; } @@ -2282,7 +2357,8 @@ void P2PTransportChannel::OnReadPacket(Connection* connection, return; } - // Do not deliver, if packet doesn't belong to the correct transport channel. + // Do not deliver, if packet doesn't belong to the correct transport + // channel. if (!FindConnection(connection)) return; @@ -2295,8 +2371,8 @@ void P2PTransportChannel::OnReadPacket(Connection* connection, // Let the client know of an incoming packet SignalReadPacket(this, data, len, packet_time_us, 0); - // May need to switch the sending connection based on the receiving media path - // if this is the controlled side. + // May need to switch the sending connection based on the receiving media + // path if this is the controlled side. if (ice_role_ == ICEROLE_CONTROLLED) { MaybeSwitchSelectedConnection(connection, IceSwitchReason::DATA_RECEIVED); } diff --git a/third_party/libwebrtc/p2p/base/p2p_transport_channel.h b/third_party/libwebrtc/p2p/base/p2p_transport_channel.h index 5e56df64ebf5a..5592a4b1ad8ad 100644 --- a/third_party/libwebrtc/p2p/base/p2p_transport_channel.h +++ b/third_party/libwebrtc/p2p/base/p2p_transport_channel.h @@ -49,6 +49,7 @@ #include "p2p/base/basic_async_resolver_factory.h" #include "p2p/base/candidate_pair_interface.h" #include "p2p/base/connection.h" +#include "p2p/base/ice_agent_interface.h" #include "p2p/base/ice_controller_factory_interface.h" #include "p2p/base/ice_controller_interface.h" #include "p2p/base/ice_switch_reason.h" @@ -104,7 +105,8 @@ class RemoteCandidate : public Candidate { // P2PTransportChannel manages the candidates and connection process to keep // two P2P clients connected to each other. -class RTC_EXPORT P2PTransportChannel : public IceTransportInternal { +class RTC_EXPORT P2PTransportChannel : public IceTransportInternal, + public IceAgentInterface { public: static std::unique_ptr Create( absl::string_view transport_name, @@ -168,6 +170,18 @@ class RTC_EXPORT P2PTransportChannel : public IceTransportInternal { const Connection* selected_connection() const override; absl::optional GetSelectedCandidatePair() const override; + // From IceAgentInterface + void OnStartedPinging() override; + int64_t GetLastPingSentMs() const override; + void UpdateConnectionStates() override; + void UpdateState() override; + void SendPingRequest(const Connection* connection) override; + void SwitchSelectedConnection(const Connection* connection, + IceSwitchReason reason) override; + void ForgetLearnedStateForConnections( + std::vector connections) override; + bool PruneConnections(std::vector connections) override; + // TODO(honghaiz): Remove this method once the reference of it in // Chromoting is removed. const Connection* best_connection() const { @@ -260,18 +274,17 @@ class RTC_EXPORT P2PTransportChannel : public IceTransportInternal { // Returns true if it's possible to send packets on `connection`. bool ReadyToSend(const Connection* connection) const; bool PresumedWritable(const Connection* conn) const; - void UpdateConnectionStates(); void RequestSortAndStateUpdate(IceSwitchReason reason_to_sort); // Start pinging if we haven't already started, and we now have a connection // that's pingable. void MaybeStartPinging(); + void SendPingRequestInternal(Connection* connection); void SortConnectionsAndUpdateState(IceSwitchReason reason_to_sort); - void SortConnections(); - void SortConnectionsIfNeeded(); rtc::NetworkRoute ConfigureNetworkRoute(const Connection* conn); - void SwitchSelectedConnection(Connection* conn, IceSwitchReason reason); - void UpdateState(); + void SwitchSelectedConnectionInternal(Connection* conn, + IceSwitchReason reason); + void UpdateTransportState(); void HandleAllTimedOut(); void MaybeStopPortAllocatorSessions(); void OnSelectedConnectionDestroyed() RTC_RUN_ON(network_thread_); @@ -349,6 +362,7 @@ class RTC_EXPORT P2PTransportChannel : public IceTransportInternal { bool MaybeSwitchSelectedConnection( IceSwitchReason reason, IceControllerInterface::SwitchResult result); + bool AllowedToPruneConnections() const; void PruneConnections(); // Returns the latest remote ICE parameters or nullptr if there are no remote