Revert "Add an active ICE controller that wraps a legacy controller (#7/n)"
This reverts commit 6326c9c201c7331d68c9beb0a93f6f6e21063cd2.
Reason for revert: breaks upstream project
Original change's description:
> Add an active ICE controller that wraps a legacy controller (#7/n)
>
> The wrapping ICE controller will allow existing ICE controller implementations to migrate to the active interface, and eventually deprecate the legacy interface.
>
> Follow-up CL has unit tests for P2PTransportChannel using the new wrapping controller.
>
> Bug: webrtc:14367, webrtc:14131
> Change-Id: I6c517449ff1e503e8268a7ef91afda793723fdeb
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/275302
> Reviewed-by: Per Kjellander <perkj@webrtc.org>
> Reviewed-by: Jonas Oreland <jonaso@webrtc.org>
> Commit-Queue: Sameer Vijaykar <samvi@google.com>
> Cr-Commit-Position: refs/heads/main@{#38130}
Bug: webrtc:14367, webrtc:14131
Change-Id: I61dd98de62657852068c7566b55f19f662df9ff4
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/276043
Reviewed-by: Per Kjellander <perkj@webrtc.org>
Reviewed-by: Jonas Oreland <jonaso@webrtc.org>
Commit-Queue: Per Kjellander <perkj@webrtc.org>
Auto-Submit: Sameer Vijaykar <samvi@google.com>
Bot-Commit: rubber-stamper@appspot.gserviceaccount.com <rubber-stamper@appspot.gserviceaccount.com>
Cr-Commit-Position: refs/heads/main@{#38131}
diff --git a/api/ice_transport_interface.h b/api/ice_transport_interface.h
index 2ec41aa..cd6ada8 100644
--- a/api/ice_transport_interface.h
+++ b/api/ice_transport_interface.h
@@ -99,10 +99,8 @@
// constructed and used.
//
// 2. If the field trial is enabled
- // a. If an active ICE controller factory is supplied, it is used and
- // the legacy ICE controller factory is not used.
- // b. If not, a default active ICE controller is used, wrapping over the
- // supplied or the default legacy ICE controller.
+ // - then an active ICE controller factory must be supplied and is used.
+ // - the legacy ICE controller factory is not used in this case.
void set_active_ice_controller_factory(
cricket::ActiveIceControllerFactoryInterface*
active_ice_controller_factory) {
diff --git a/p2p/BUILD.gn b/p2p/BUILD.gn
index 85ac605..1009304 100644
--- a/p2p/BUILD.gn
+++ b/p2p/BUILD.gn
@@ -81,8 +81,6 @@
"base/turn_port.cc",
"base/turn_port.h",
"base/udp_port.h",
- "base/wrapping_active_ice_controller.cc",
- "base/wrapping_active_ice_controller.h",
"client/basic_port_allocator.cc",
"client/basic_port_allocator.h",
"client/relay_port_factory_interface.h",
@@ -203,7 +201,6 @@
"base/fake_packet_transport.h",
"base/mock_active_ice_controller.h",
"base/mock_async_resolver.h",
- "base/mock_ice_agent.h",
"base/mock_ice_controller.h",
"base/mock_ice_transport.h",
"base/test_stun_server.cc",
@@ -263,7 +260,6 @@
"base/transport_description_unittest.cc",
"base/turn_port_unittest.cc",
"base/turn_server_unittest.cc",
- "base/wrapping_active_ice_controller_unittest.cc",
"client/basic_port_allocator_unittest.cc",
]
deps = [
diff --git a/p2p/base/mock_ice_agent.h b/p2p/base/mock_ice_agent.h
deleted file mode 100644
index e4100ec..0000000
--- a/p2p/base/mock_ice_agent.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2018 The WebRTC Project Authors. All rights reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
-
-#ifndef P2P_BASE_MOCK_ICE_AGENT_H_
-#define P2P_BASE_MOCK_ICE_AGENT_H_
-
-#include <vector>
-
-#include "p2p/base/connection.h"
-#include "p2p/base/ice_agent_interface.h"
-#include "p2p/base/ice_switch_reason.h"
-#include "p2p/base/transport_description.h"
-#include "test/gmock.h"
-
-namespace cricket {
-
-class MockIceAgent : public IceAgentInterface {
- public:
- ~MockIceAgent() override = default;
-
- MOCK_METHOD(int64_t, GetLastPingSentMs, (), (override, const));
- MOCK_METHOD(IceRole, GetIceRole, (), (override, const));
- MOCK_METHOD(void, OnStartedPinging, (), (override));
- MOCK_METHOD(void, UpdateConnectionStates, (), (override));
- MOCK_METHOD(void, UpdateState, (), (override));
- MOCK_METHOD(void,
- ForgetLearnedStateForConnections,
- (std::vector<const Connection*>),
- (override));
- MOCK_METHOD(void, SendPingRequest, (const Connection*), (override));
- MOCK_METHOD(void,
- SwitchSelectedConnection,
- (const Connection*, IceSwitchReason),
- (override));
- MOCK_METHOD(bool,
- PruneConnections,
- (std::vector<const Connection*>),
- (override));
-};
-
-} // namespace cricket
-
-#endif // P2P_BASE_MOCK_ICE_AGENT_H_
diff --git a/p2p/base/p2p_transport_channel.cc b/p2p/base/p2p_transport_channel.cc
index 0a0d8c8..2b0e906 100644
--- a/p2p/base/p2p_transport_channel.cc
+++ b/p2p/base/p2p_transport_channel.cc
@@ -33,7 +33,6 @@
#include "p2p/base/connection.h"
#include "p2p/base/connection_info.h"
#include "p2p/base/port.h"
-#include "p2p/base/wrapping_active_ice_controller.h"
#include "rtc_base/checks.h"
#include "rtc_base/crc32.h"
#include "rtc_base/experiments/struct_parameters_parser.h"
@@ -2473,15 +2472,10 @@
P2PTransportChannel* transport)
: transport_(transport) {
if (UseActiveIceControllerFieldTrialEnabled(field_trials)) {
- if (active_ice_controller_factory) {
- ActiveIceControllerFactoryArgs active_args{args,
- /* ice_agent= */ transport};
- active_ice_controller_ =
- active_ice_controller_factory->Create(active_args);
- } else {
- active_ice_controller_ = std::make_unique<WrappingActiveIceController>(
- /* ice_agent= */ transport, ice_controller_factory, args);
- }
+ RTC_DCHECK(active_ice_controller_factory);
+ ActiveIceControllerFactoryArgs active_args{args,
+ /* ice_agent= */ transport};
+ active_ice_controller_ = active_ice_controller_factory->Create(active_args);
} else {
if (ice_controller_factory != nullptr) {
legacy_ice_controller_ = ice_controller_factory->Create(args);
diff --git a/p2p/base/wrapping_active_ice_controller.cc b/p2p/base/wrapping_active_ice_controller.cc
deleted file mode 100644
index c665921..0000000
--- a/p2p/base/wrapping_active_ice_controller.cc
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * Copyright 2022 The WebRTC Project Authors. All rights reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
-
-#include "p2p/base/wrapping_active_ice_controller.h"
-
-#include <memory>
-#include <utility>
-#include <vector>
-
-#include "api/sequence_checker.h"
-#include "api/task_queue/pending_task_safety_flag.h"
-#include "api/units/time_delta.h"
-#include "p2p/base/basic_ice_controller.h"
-#include "p2p/base/connection.h"
-#include "p2p/base/ice_agent_interface.h"
-#include "p2p/base/ice_controller_interface.h"
-#include "p2p/base/ice_switch_reason.h"
-#include "p2p/base/ice_transport_internal.h"
-#include "p2p/base/transport_description.h"
-#include "rtc_base/logging.h"
-#include "rtc_base/thread.h"
-#include "rtc_base/time_utils.h"
-
-namespace {
-using ::webrtc::SafeTask;
-using ::webrtc::TimeDelta;
-} // unnamed namespace
-
-namespace cricket {
-
-WrappingActiveIceController::WrappingActiveIceController(
- IceAgentInterface* ice_agent,
- std::unique_ptr<IceControllerInterface> wrapped)
- : network_thread_(rtc::Thread::Current()),
- wrapped_(std::move(wrapped)),
- agent_(*ice_agent) {
- RTC_DCHECK(ice_agent != nullptr);
-}
-
-WrappingActiveIceController::WrappingActiveIceController(
- IceAgentInterface* ice_agent,
- IceControllerFactoryInterface* wrapped_factory,
- const IceControllerFactoryArgs& wrapped_factory_args)
- : network_thread_(rtc::Thread::Current()), agent_(*ice_agent) {
- RTC_DCHECK(ice_agent != nullptr);
- if (wrapped_factory) {
- wrapped_ = wrapped_factory->Create(wrapped_factory_args);
- } else {
- wrapped_ = std::make_unique<BasicIceController>(wrapped_factory_args);
- }
-}
-
-WrappingActiveIceController::~WrappingActiveIceController() {}
-
-void WrappingActiveIceController::SetIceConfig(const IceConfig& config) {
- RTC_DCHECK_RUN_ON(network_thread_);
- wrapped_->SetIceConfig(config);
-}
-
-bool WrappingActiveIceController::GetUseCandidateAttribute(
- const Connection* connection,
- NominationMode mode,
- IceMode remote_ice_mode) const {
- RTC_DCHECK_RUN_ON(network_thread_);
- return wrapped_->GetUseCandidateAttr(connection, mode, remote_ice_mode);
-}
-
-void WrappingActiveIceController::OnConnectionAdded(
- const Connection* connection) {
- RTC_DCHECK_RUN_ON(network_thread_);
- wrapped_->AddConnection(connection);
-}
-
-void WrappingActiveIceController::OnConnectionPinged(
- const Connection* connection) {
- RTC_DCHECK_RUN_ON(network_thread_);
- wrapped_->MarkConnectionPinged(connection);
-}
-
-void WrappingActiveIceController::OnConnectionUpdated(
- const Connection* connection) {
- RTC_LOG(LS_VERBOSE) << "Connection report for " << connection->ToString();
- // Do nothing. Native ICE controllers have direct access to Connection, so no
- // need to update connection state separately.
-}
-
-void WrappingActiveIceController::OnConnectionSwitched(
- const Connection* connection) {
- RTC_DCHECK_RUN_ON(network_thread_);
- selected_connection_ = connection;
- wrapped_->SetSelectedConnection(connection);
-}
-
-void WrappingActiveIceController::OnConnectionDestroyed(
- const Connection* connection) {
- RTC_DCHECK_RUN_ON(network_thread_);
- wrapped_->OnConnectionDestroyed(connection);
-}
-
-void WrappingActiveIceController::MaybeStartPinging() {
- RTC_DCHECK_RUN_ON(network_thread_);
- if (started_pinging_) {
- return;
- }
-
- if (wrapped_->HasPingableConnection()) {
- network_thread_->PostTask(
- SafeTask(task_safety_.flag(), [this]() { SelectAndPingConnection(); }));
- agent_.OnStartedPinging();
- started_pinging_ = true;
- }
-}
-
-void WrappingActiveIceController::SelectAndPingConnection() {
- RTC_DCHECK_RUN_ON(network_thread_);
- agent_.UpdateConnectionStates();
-
- IceControllerInterface::PingResult result =
- wrapped_->SelectConnectionToPing(agent_.GetLastPingSentMs());
- HandlePingResult(result);
-}
-
-void WrappingActiveIceController::HandlePingResult(
- IceControllerInterface::PingResult result) {
- RTC_DCHECK_RUN_ON(network_thread_);
-
- if (result.connection.has_value()) {
- agent_.SendPingRequest(result.connection.value());
- }
-
- network_thread_->PostDelayedTask(
- SafeTask(task_safety_.flag(), [this]() { SelectAndPingConnection(); }),
- TimeDelta::Millis(result.recheck_delay_ms));
-}
-
-void WrappingActiveIceController::OnSortAndSwitchRequest(
- IceSwitchReason reason) {
- RTC_DCHECK_RUN_ON(network_thread_);
- if (!sort_pending_) {
- network_thread_->PostTask(SafeTask(task_safety_.flag(), [this, reason]() {
- SortAndSwitchToBestConnection(reason);
- }));
- sort_pending_ = true;
- }
-}
-
-void WrappingActiveIceController::OnImmediateSortAndSwitchRequest(
- IceSwitchReason reason) {
- RTC_DCHECK_RUN_ON(network_thread_);
- SortAndSwitchToBestConnection(reason);
-}
-
-void WrappingActiveIceController::SortAndSwitchToBestConnection(
- IceSwitchReason reason) {
- RTC_DCHECK_RUN_ON(network_thread_);
-
- // Make sure the connection states are up-to-date since this affects how they
- // will be sorted.
- agent_.UpdateConnectionStates();
-
- // Any changes after this point will require a re-sort.
- sort_pending_ = false;
-
- IceControllerInterface::SwitchResult result =
- wrapped_->SortAndSwitchConnection(reason);
- HandleSwitchResult(reason, result);
- UpdateStateOnConnectionsResorted();
-}
-
-bool WrappingActiveIceController::OnImmediateSwitchRequest(
- IceSwitchReason reason,
- const Connection* selected) {
- RTC_DCHECK_RUN_ON(network_thread_);
- IceControllerInterface::SwitchResult result =
- wrapped_->ShouldSwitchConnection(reason, selected);
- HandleSwitchResult(reason, result);
- return result.connection.has_value();
-}
-
-void WrappingActiveIceController::HandleSwitchResult(
- IceSwitchReason reason_for_switch,
- IceControllerInterface::SwitchResult result) {
- RTC_DCHECK_RUN_ON(network_thread_);
- if (result.connection.has_value()) {
- RTC_LOG(LS_INFO) << "Switching selected connection due to: "
- << IceSwitchReasonToString(reason_for_switch);
- agent_.SwitchSelectedConnection(result.connection.value(),
- reason_for_switch);
- }
-
- if (result.recheck_event.has_value()) {
- // 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.
- network_thread_->PostDelayedTask(
- SafeTask(task_safety_.flag(),
- [this, recheck_reason = result.recheck_event->reason]() {
- SortAndSwitchToBestConnection(recheck_reason);
- }),
- TimeDelta::Millis(result.recheck_event->recheck_delay_ms));
- }
-
- agent_.ForgetLearnedStateForConnections(
- result.connections_to_forget_state_on);
-}
-
-void WrappingActiveIceController::UpdateStateOnConnectionsResorted() {
- RTC_DCHECK_RUN_ON(network_thread_);
- PruneConnections();
-
- // Update the internal state of the ICE agentl.
- agent_.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();
-}
-
-void WrappingActiveIceController::PruneConnections() {
- RTC_DCHECK_RUN_ON(network_thread_);
-
- // 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 (agent_.GetIceRole() == ICEROLE_CONTROLLING ||
- (selected_connection_ && selected_connection_->nominated())) {
- std::vector<const Connection*> connections_to_prune =
- wrapped_->PruneConnections();
- agent_.PruneConnections(connections_to_prune);
- }
-}
-
-// Only for unit tests
-const Connection* WrappingActiveIceController::FindNextPingableConnection() {
- RTC_DCHECK_RUN_ON(network_thread_);
- return wrapped_->FindNextPingableConnection();
-}
-
-} // namespace cricket
diff --git a/p2p/base/wrapping_active_ice_controller.h b/p2p/base/wrapping_active_ice_controller.h
deleted file mode 100644
index 449c0f0..0000000
--- a/p2p/base/wrapping_active_ice_controller.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright 2022 The WebRTC Project Authors. All rights reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
-
-#ifndef P2P_BASE_WRAPPING_ACTIVE_ICE_CONTROLLER_H_
-#define P2P_BASE_WRAPPING_ACTIVE_ICE_CONTROLLER_H_
-
-#include <memory>
-
-#include "absl/types/optional.h"
-#include "api/task_queue/pending_task_safety_flag.h"
-#include "p2p/base/active_ice_controller_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"
-#include "p2p/base/ice_transport_internal.h"
-#include "p2p/base/transport_description.h"
-#include "rtc_base/thread.h"
-#include "rtc_base/thread_annotations.h"
-
-namespace cricket {
-
-// WrappingActiveIceController provides the functionality of a legacy passive
-// ICE controller but packaged as an active ICE Controller.
-class WrappingActiveIceController : public ActiveIceControllerInterface {
- public:
- // Constructs an active ICE controller wrapping an already constructed legacy
- // ICE controller. Does not take ownership of the ICE agent, which must
- // already exist and outlive the ICE controller.
- WrappingActiveIceController(IceAgentInterface* ice_agent,
- std::unique_ptr<IceControllerInterface> wrapped);
- // Constructs an active ICE controller that wraps over a legacy ICE
- // controller. The legacy ICE controller is constructed through a factory, if
- // one is supplied. If not, a default BasicIceController is wrapped instead.
- // Does not take ownership of the ICE agent, which must already exist and
- // outlive the ICE controller.
- WrappingActiveIceController(
- IceAgentInterface* ice_agent,
- IceControllerFactoryInterface* wrapped_factory,
- const IceControllerFactoryArgs& wrapped_factory_args);
- virtual ~WrappingActiveIceController();
-
- void SetIceConfig(const IceConfig& config) override;
- bool GetUseCandidateAttribute(const Connection* connection,
- NominationMode mode,
- IceMode remote_ice_mode) const override;
-
- void OnConnectionAdded(const Connection* connection) override;
- void OnConnectionPinged(const Connection* connection) override;
- void OnConnectionUpdated(const Connection* connection) override;
- void OnConnectionSwitched(const Connection* connection) override;
- void OnConnectionDestroyed(const Connection* connection) override;
-
- void OnSortAndSwitchRequest(IceSwitchReason reason) override;
- void OnImmediateSortAndSwitchRequest(IceSwitchReason reason) override;
- bool OnImmediateSwitchRequest(IceSwitchReason reason,
- const Connection* selected) override;
-
- // Only for unit tests
- const Connection* FindNextPingableConnection() override;
-
- private:
- void MaybeStartPinging();
- void SelectAndPingConnection();
- void HandlePingResult(IceControllerInterface::PingResult result);
-
- void SortAndSwitchToBestConnection(IceSwitchReason reason);
- void HandleSwitchResult(IceSwitchReason reason_for_switch,
- IceControllerInterface::SwitchResult result);
- void UpdateStateOnConnectionsResorted();
-
- void PruneConnections();
-
- rtc::Thread* const network_thread_;
- webrtc::ScopedTaskSafety task_safety_;
-
- bool started_pinging_ RTC_GUARDED_BY(network_thread_) = false;
- bool sort_pending_ RTC_GUARDED_BY(network_thread_) = false;
- const Connection* selected_connection_ RTC_GUARDED_BY(network_thread_) =
- nullptr;
-
- std::unique_ptr<IceControllerInterface> wrapped_
- RTC_GUARDED_BY(network_thread_);
- IceAgentInterface& agent_ RTC_GUARDED_BY(network_thread_);
-};
-
-} // namespace cricket
-
-#endif // P2P_BASE_WRAPPING_ACTIVE_ICE_CONTROLLER_H_
diff --git a/p2p/base/wrapping_active_ice_controller_unittest.cc b/p2p/base/wrapping_active_ice_controller_unittest.cc
deleted file mode 100644
index 19f9b95..0000000
--- a/p2p/base/wrapping_active_ice_controller_unittest.cc
+++ /dev/null
@@ -1,311 +0,0 @@
-/*
- * Copyright 2009 The WebRTC Project Authors. All rights reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
-
-#include "p2p/base/wrapping_active_ice_controller.h"
-
-#include <memory>
-#include <utility>
-#include <vector>
-
-#include "p2p/base/connection.h"
-#include "p2p/base/mock_ice_agent.h"
-#include "p2p/base/mock_ice_controller.h"
-#include "rtc_base/fake_clock.h"
-#include "rtc_base/gunit.h"
-#include "rtc_base/thread.h"
-
-namespace {
-
-using ::cricket::Connection;
-using ::cricket::IceConfig;
-using ::cricket::IceControllerFactoryArgs;
-using ::cricket::IceControllerInterface;
-using ::cricket::IceMode;
-using ::cricket::IceRecheckEvent;
-using ::cricket::IceSwitchReason;
-using ::cricket::MockIceAgent;
-using ::cricket::MockIceController;
-using ::cricket::MockIceControllerFactory;
-using ::cricket::NominationMode;
-using ::cricket::WrappingActiveIceController;
-
-using ::testing::_;
-using ::testing::NiceMock;
-using ::testing::Ref;
-using ::testing::Return;
-using ::testing::Sequence;
-
-using ::rtc::AutoThread;
-using ::rtc::Event;
-using ::rtc::ScopedFakeClock;
-using ::webrtc::TimeDelta;
-
-using NiceMockIceController = NiceMock<MockIceController>;
-
-static const Connection* kConnection =
- reinterpret_cast<const Connection*>(0xabcd);
-static const Connection* kConnectionTwo =
- reinterpret_cast<const Connection*>(0xbcde);
-static const Connection* kConnectionThree =
- reinterpret_cast<const Connection*>(0xcdef);
-
-static const std::vector<const Connection*> kEmptyConnsList =
- std::vector<const Connection*>();
-
-static const TimeDelta kTick = TimeDelta::Millis(1);
-
-TEST(WrappingActiveIceControllerTest, CreateLegacyIceControllerFromFactory) {
- MockIceAgent agent;
- IceControllerFactoryArgs args;
- MockIceControllerFactory legacy_controller_factory;
- EXPECT_CALL(legacy_controller_factory, RecordIceControllerCreated()).Times(1);
- WrappingActiveIceController controller(&agent, &legacy_controller_factory,
- args);
-}
-
-TEST(WrappingActiveIceControllerTest, PassthroughIceControllerInterface) {
- MockIceAgent agent;
- std::unique_ptr<MockIceController> will_move =
- std::make_unique<MockIceController>(IceControllerFactoryArgs{});
- MockIceController* wrapped = will_move.get();
- WrappingActiveIceController controller(&agent, std::move(will_move));
-
- IceConfig config{};
- EXPECT_CALL(*wrapped, SetIceConfig(Ref(config)));
- controller.SetIceConfig(config);
-
- EXPECT_CALL(*wrapped,
- GetUseCandidateAttr(kConnection, NominationMode::AGGRESSIVE,
- IceMode::ICEMODE_LITE))
- .WillOnce(Return(true));
- EXPECT_TRUE(controller.GetUseCandidateAttribute(
- kConnection, NominationMode::AGGRESSIVE, IceMode::ICEMODE_LITE));
-
- EXPECT_CALL(*wrapped, AddConnection(kConnection));
- controller.OnConnectionAdded(kConnection);
-
- EXPECT_CALL(*wrapped, OnConnectionDestroyed(kConnection));
- controller.OnConnectionDestroyed(kConnection);
-
- EXPECT_CALL(*wrapped, SetSelectedConnection(kConnection));
- controller.OnConnectionSwitched(kConnection);
-
- EXPECT_CALL(*wrapped, MarkConnectionPinged(kConnection));
- controller.OnConnectionPinged(kConnection);
-
- EXPECT_CALL(*wrapped, FindNextPingableConnection())
- .WillOnce(Return(kConnection));
- EXPECT_EQ(controller.FindNextPingableConnection(), kConnection);
-}
-
-TEST(WrappingActiveIceControllerTest, HandlesImmediateSwitchRequest) {
- AutoThread main;
- ScopedFakeClock clock;
- NiceMock<MockIceAgent> agent;
- std::unique_ptr<NiceMockIceController> will_move =
- std::make_unique<NiceMockIceController>(IceControllerFactoryArgs{});
- NiceMockIceController* wrapped = will_move.get();
- WrappingActiveIceController controller(&agent, std::move(will_move));
-
- IceSwitchReason reason = IceSwitchReason::NOMINATION_ON_CONTROLLED_SIDE;
- std::vector<const Connection*> conns_to_forget{kConnectionTwo};
- int recheck_delay_ms = 10;
- IceControllerInterface::SwitchResult switch_result{
- kConnection,
- IceRecheckEvent(IceSwitchReason::ICE_CONTROLLER_RECHECK,
- recheck_delay_ms),
- conns_to_forget};
-
- // ICE controller should switch to given connection immediately.
- Sequence check_then_switch;
- EXPECT_CALL(*wrapped, ShouldSwitchConnection(reason, kConnection))
- .InSequence(check_then_switch)
- .WillOnce(Return(switch_result));
- EXPECT_CALL(agent, SwitchSelectedConnection(kConnection, reason))
- .InSequence(check_then_switch);
- EXPECT_CALL(agent, ForgetLearnedStateForConnections(conns_to_forget));
-
- EXPECT_TRUE(controller.OnImmediateSwitchRequest(reason, kConnection));
-
- // No rechecks before recheck delay.
- clock.AdvanceTime(TimeDelta::Millis(recheck_delay_ms - 1));
-
- // ICE controller should recheck for best connection after the recheck delay.
- Sequence recheck_sort;
- EXPECT_CALL(agent, UpdateConnectionStates()).InSequence(recheck_sort);
- EXPECT_CALL(*wrapped,
- SortAndSwitchConnection(IceSwitchReason::ICE_CONTROLLER_RECHECK))
- .InSequence(recheck_sort)
- .WillOnce(Return(IceControllerInterface::SwitchResult{}));
- EXPECT_CALL(agent, ForgetLearnedStateForConnections(kEmptyConnsList));
-
- clock.AdvanceTime(kTick);
-}
-
-TEST(WrappingActiveIceControllerTest, HandlesImmediateSortAndSwitchRequest) {
- AutoThread main;
- ScopedFakeClock clock;
- NiceMock<MockIceAgent> agent;
- std::unique_ptr<NiceMockIceController> will_move =
- std::make_unique<NiceMockIceController>(IceControllerFactoryArgs{});
- NiceMockIceController* wrapped = will_move.get();
- WrappingActiveIceController controller(&agent, std::move(will_move));
-
- IceSwitchReason reason = IceSwitchReason::NEW_CONNECTION_FROM_LOCAL_CANDIDATE;
- std::vector<const Connection*> conns_to_forget{kConnectionTwo};
- std::vector<const Connection*> conns_to_prune{kConnectionThree};
- int recheck_delay_ms = 10;
- IceControllerInterface::SwitchResult switch_result{
- kConnection,
- IceRecheckEvent(IceSwitchReason::ICE_CONTROLLER_RECHECK,
- recheck_delay_ms),
- conns_to_forget};
-
- Sequence sort_and_switch;
- EXPECT_CALL(agent, UpdateConnectionStates()).InSequence(sort_and_switch);
- EXPECT_CALL(*wrapped, SortAndSwitchConnection(reason))
- .InSequence(sort_and_switch)
- .WillOnce(Return(switch_result));
- EXPECT_CALL(agent, SwitchSelectedConnection(kConnection, reason))
- .InSequence(sort_and_switch);
- EXPECT_CALL(*wrapped, PruneConnections())
- .InSequence(sort_and_switch)
- .WillOnce(Return(conns_to_prune));
- EXPECT_CALL(agent, PruneConnections(conns_to_prune))
- .InSequence(sort_and_switch);
-
- controller.OnImmediateSortAndSwitchRequest(reason);
-
- // No rechecks before recheck delay.
- clock.AdvanceTime(TimeDelta::Millis(recheck_delay_ms - 1));
-
- // ICE controller should recheck for best connection after the recheck delay.
- Sequence recheck_sort;
- EXPECT_CALL(agent, UpdateConnectionStates()).InSequence(recheck_sort);
- EXPECT_CALL(*wrapped,
- SortAndSwitchConnection(IceSwitchReason::ICE_CONTROLLER_RECHECK))
- .InSequence(recheck_sort)
- .WillOnce(Return(IceControllerInterface::SwitchResult{}));
- EXPECT_CALL(*wrapped, PruneConnections())
- .InSequence(recheck_sort)
- .WillOnce(Return(kEmptyConnsList));
- EXPECT_CALL(agent, PruneConnections(kEmptyConnsList))
- .InSequence(recheck_sort);
-
- clock.AdvanceTime(kTick);
-}
-
-TEST(WrappingActiveIceControllerTest, HandlesSortAndSwitchRequest) {
- AutoThread main;
- ScopedFakeClock clock;
-
- // Block the main task queue until ready.
- Event init;
- TimeDelta init_delay = TimeDelta::Millis(10);
- main.PostTask([&init, &init_delay] { init.Wait(init_delay); });
-
- NiceMock<MockIceAgent> agent;
- std::unique_ptr<NiceMockIceController> will_move =
- std::make_unique<NiceMockIceController>(IceControllerFactoryArgs{});
- NiceMockIceController* wrapped = will_move.get();
- WrappingActiveIceController controller(&agent, std::move(will_move));
-
- IceSwitchReason reason = IceSwitchReason::NETWORK_PREFERENCE_CHANGE;
-
- // No action should occur immediately
- EXPECT_CALL(agent, UpdateConnectionStates()).Times(0);
- EXPECT_CALL(*wrapped, SortAndSwitchConnection(_)).Times(0);
- EXPECT_CALL(agent, SwitchSelectedConnection(_, _)).Times(0);
-
- controller.OnSortAndSwitchRequest(reason);
-
- std::vector<const Connection*> conns_to_forget{kConnectionTwo};
- int recheck_delay_ms = 10;
- IceControllerInterface::SwitchResult switch_result{
- kConnection,
- IceRecheckEvent(IceSwitchReason::ICE_CONTROLLER_RECHECK,
- recheck_delay_ms),
- conns_to_forget};
-
- // Sort and switch should take place as the subsequent task.
- Sequence sort_and_switch;
- EXPECT_CALL(agent, UpdateConnectionStates()).InSequence(sort_and_switch);
- EXPECT_CALL(*wrapped, SortAndSwitchConnection(reason))
- .InSequence(sort_and_switch)
- .WillOnce(Return(switch_result));
- EXPECT_CALL(agent, SwitchSelectedConnection(kConnection, reason))
- .InSequence(sort_and_switch);
-
- // Unblock the init task.
- clock.AdvanceTime(init_delay);
-}
-
-TEST(WrappingActiveIceControllerTest, StartPingingAfterSortAndSwitch) {
- AutoThread main;
- ScopedFakeClock clock;
-
- // Block the main task queue until ready.
- Event init;
- TimeDelta init_delay = TimeDelta::Millis(10);
- main.PostTask([&init, &init_delay] { init.Wait(init_delay); });
-
- NiceMock<MockIceAgent> agent;
- std::unique_ptr<NiceMockIceController> will_move =
- std::make_unique<NiceMockIceController>(IceControllerFactoryArgs{});
- NiceMockIceController* wrapped = will_move.get();
- WrappingActiveIceController controller(&agent, std::move(will_move));
-
- // Pinging does not start automatically, unless triggered through a sort.
- EXPECT_CALL(*wrapped, HasPingableConnection()).Times(0);
- EXPECT_CALL(*wrapped, SelectConnectionToPing(_)).Times(0);
- EXPECT_CALL(agent, OnStartedPinging()).Times(0);
-
- controller.OnSortAndSwitchRequest(IceSwitchReason::DATA_RECEIVED);
-
- // Pinging does not start if no pingable connection.
- EXPECT_CALL(*wrapped, HasPingableConnection()).WillOnce(Return(false));
- EXPECT_CALL(*wrapped, SelectConnectionToPing(_)).Times(0);
- EXPECT_CALL(agent, OnStartedPinging()).Times(0);
-
- // Unblock the init task.
- clock.AdvanceTime(init_delay);
-
- int recheck_delay_ms = 10;
- IceControllerInterface::PingResult ping_result(kConnection, recheck_delay_ms);
-
- // Pinging starts when there is a pingable connection.
- Sequence start_pinging;
- EXPECT_CALL(*wrapped, HasPingableConnection())
- .InSequence(start_pinging)
- .WillOnce(Return(true));
- EXPECT_CALL(agent, OnStartedPinging()).InSequence(start_pinging);
- EXPECT_CALL(agent, GetLastPingSentMs())
- .InSequence(start_pinging)
- .WillOnce(Return(123));
- EXPECT_CALL(*wrapped, SelectConnectionToPing(123))
- .InSequence(start_pinging)
- .WillOnce(Return(ping_result));
- EXPECT_CALL(agent, SendPingRequest(kConnection)).InSequence(start_pinging);
-
- controller.OnSortAndSwitchRequest(IceSwitchReason::DATA_RECEIVED);
- clock.AdvanceTime(kTick);
-
- // ICE controller should recheck and ping after the recheck delay.
- // No ping should be sent if no connection selected to ping.
- EXPECT_CALL(agent, GetLastPingSentMs()).WillOnce(Return(456));
- EXPECT_CALL(*wrapped, SelectConnectionToPing(456))
- .WillOnce(Return(IceControllerInterface::PingResult(
- /* connection= */ nullptr, recheck_delay_ms)));
- EXPECT_CALL(agent, SendPingRequest(kConnection)).Times(0);
-
- clock.AdvanceTime(TimeDelta::Millis(recheck_delay_ms));
-}
-
-} // namespace