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