diff --git a/p2p/BUILD.gn b/p2p/BUILD.gn index 07d1f711b6..769bd4b209 100644 --- a/p2p/BUILD.gn +++ b/p2p/BUILD.gn @@ -48,8 +48,6 @@ rtc_static_library("rtc_p2p") { "base/portinterface.h", "base/pseudotcp.cc", "base/pseudotcp.h", - "base/regatheringcontroller.cc", - "base/regatheringcontroller.h", "base/relayport.cc", "base/relayport.h", "base/stun.cc", @@ -151,7 +149,6 @@ if (rtc_include_tests) { "base/port_unittest.cc", "base/portallocator_unittest.cc", "base/pseudotcp_unittest.cc", - "base/regatheringcontroller_unittest.cc", "base/relayport_unittest.cc", "base/relayserver_unittest.cc", "base/stun_unittest.cc", diff --git a/p2p/base/fakeportallocator.h b/p2p/base/fakeportallocator.h index 5a52bbcdcb..b5db8238e1 100644 --- a/p2p/base/fakeportallocator.h +++ b/p2p/base/fakeportallocator.h @@ -139,16 +139,7 @@ class FakePortAllocatorSession : public PortAllocatorSession { void StopGettingPorts() override { running_ = false; } bool IsGettingPorts() override { return running_; } - void ClearGettingPorts() override { is_cleared = true; } - bool IsCleared() const override { return is_cleared; } - - void RegatherOnAllNetworks() override { - SignalIceRegathering(this, IceRegatheringReason::OCCASIONAL_REFRESH); - } - - void RegatherOnFailedNetworks() override { - SignalIceRegathering(this, IceRegatheringReason::NETWORK_FAILURE); - } + void ClearGettingPorts() override {} std::vector ReadyPorts() const override { return ready_ports_; @@ -213,7 +204,6 @@ class FakePortAllocatorSession : public PortAllocatorSession { std::vector candidates_; std::vector ready_ports_; bool allocation_done_ = false; - bool is_cleared = false; ServerAddresses stun_servers_; std::vector turn_servers_; uint32_t candidate_filter_ = CF_ALL; diff --git a/p2p/base/p2ptransportchannel.cc b/p2p/base/p2ptransportchannel.cc index d1c58c2162..0b6beb9b3f 100644 --- a/p2p/base/p2ptransportchannel.cc +++ b/p2p/base/p2ptransportchannel.cc @@ -125,6 +125,7 @@ P2PTransportChannel::P2PTransportChannel(const std::string& transport_name, ice_role_(ICEROLE_UNKNOWN), tiebreaker_(0), gathering_state_(kIceGatheringNew), + rand_(rtc::SystemTimeNanos()), config_(RECEIVING_TIMEOUT, BACKUP_CONNECTION_PING_INTERVAL, GATHER_ONCE /* continual_gathering_policy */, @@ -137,11 +138,6 @@ P2PTransportChannel::P2PTransportChannel(const std::string& transport_name, // Validate IceConfig even for mostly built-in constant default values in case // we change them. RTC_DCHECK(ValidateIceConfig(config_).ok()); - webrtc::BasicRegatheringController::Config regathering_config( - config_.regather_all_networks_interval_range, - config_.regather_on_failed_networks_interval_or_default()); - regathering_controller_.reset(new webrtc::BasicRegatheringController( - regathering_config, this, network_thread_)); ice_event_log_.set_event_log(event_log); } @@ -168,7 +164,6 @@ void P2PTransportChannel::AddAllocatorSession( allocator_session()->PruneAllPorts(); } allocator_sessions_.push_back(std::move(session)); - regathering_controller_->set_allocator_session(allocator_session()); // We now only want to apply new candidates that we receive to the ports // created by this new session because these are replacing those of the @@ -576,11 +571,6 @@ void P2PTransportChannel::SetIceConfig(const IceConfig& config) { << config.stun_keepalive_interval_or_default(); } - webrtc::BasicRegatheringController::Config regathering_config( - config_.regather_all_networks_interval_range, - config_.regather_on_failed_networks_interval_or_default()); - regathering_controller_->SetConfig(regathering_config); - RTC_DCHECK(ValidateIceConfig(config_).ok()); } @@ -588,8 +578,6 @@ const IceConfig& P2PTransportChannel::config() const { return config_; } -// TODO(qingsi): Add tests for the config validation starting from -// PeerConnection::SetConfiguration. RTCError P2PTransportChannel::ValidateIceConfig(const IceConfig& config) { if (config.regather_all_networks_interval_range && config.continual_gathering_policy == GATHER_ONCE) { @@ -637,13 +625,6 @@ RTCError P2PTransportChannel::ValidateIceConfig(const IceConfig& config) { "UNRELIABLE is longer than that to become TIMEOUT."); } - if (config.regather_all_networks_interval_range && - config.regather_all_networks_interval_range.value().min() < 0) { - return RTCError( - RTCErrorType::INVALID_RANGE, - "The minimum regathering interval for all networks is negative."); - } - return RTCError::OK(); } @@ -1311,7 +1292,16 @@ void P2PTransportChannel::MaybeStartPinging() { invoker_.AsyncInvoke( RTC_FROM_HERE, thread(), rtc::Bind(&P2PTransportChannel::CheckAndPing, this)); - regathering_controller_->Start(); + invoker_.AsyncInvokeDelayed( + RTC_FROM_HERE, thread(), + rtc::Bind(&P2PTransportChannel::RegatherOnFailedNetworks, this), + config_.regather_on_failed_networks_interval_or_default()); + if (config_.regather_all_networks_interval_range) { + invoker_.AsyncInvokeDelayed( + RTC_FROM_HERE, thread(), + rtc::Bind(&P2PTransportChannel::RegatherOnAllNetworks, this), + SampleRegatherAllNetworksInterval()); + } started_pinging_ = true; } } @@ -2195,6 +2185,31 @@ void P2PTransportChannel::OnCandidatesRemoved( SignalCandidatesRemoved(this, candidates_to_remove); } +void P2PTransportChannel::RegatherOnFailedNetworks() { + // Only re-gather when the current session is in the CLEARED state (i.e., not + // running or stopped). It is only possible to enter this state when we gather + // continually, so there is an implicit check on continual gathering here. + if (!allocator_sessions_.empty() && allocator_session()->IsCleared()) { + allocator_session()->RegatherOnFailedNetworks(); + } + + invoker_.AsyncInvokeDelayed( + RTC_FROM_HERE, thread(), + rtc::Bind(&P2PTransportChannel::RegatherOnFailedNetworks, this), + config_.regather_on_failed_networks_interval_or_default()); +} + +void P2PTransportChannel::RegatherOnAllNetworks() { + if (!allocator_sessions_.empty() && allocator_session()->IsCleared()) { + allocator_session()->RegatherOnAllNetworks(); + } + + invoker_.AsyncInvokeDelayed( + RTC_FROM_HERE, thread(), + rtc::Bind(&P2PTransportChannel::RegatherOnAllNetworks, this), + SampleRegatherAllNetworksInterval()); +} + void P2PTransportChannel::PruneAllPorts() { pruned_ports_.insert(pruned_ports_.end(), ports_.begin(), ports_.end()); ports_.clear(); @@ -2348,6 +2363,12 @@ void P2PTransportChannel::set_receiving(bool receiving) { SignalReceivingState(this); } +int P2PTransportChannel::SampleRegatherAllNetworksInterval() { + auto interval = config_.regather_all_networks_interval_range; + RTC_DCHECK(interval); + return rand_.Rand(interval->min(), interval->max()); +} + void P2PTransportChannel::LogCandidatePairConfig( Connection* conn, webrtc::IceCandidatePairConfigType type) { diff --git a/p2p/base/p2ptransportchannel.h b/p2p/base/p2ptransportchannel.h index 8e3b06ce3e..c061431900 100644 --- a/p2p/base/p2ptransportchannel.h +++ b/p2p/base/p2ptransportchannel.h @@ -36,10 +36,10 @@ #include "p2p/base/p2pconstants.h" #include "p2p/base/portallocator.h" #include "p2p/base/portinterface.h" -#include "p2p/base/regatheringcontroller.h" #include "rtc_base/asyncinvoker.h" #include "rtc_base/asyncpacketsocket.h" #include "rtc_base/constructormagic.h" +#include "rtc_base/random.h" #include "rtc_base/sigslot.h" namespace webrtc { @@ -151,10 +151,7 @@ class P2PTransportChannel : public IceTransportInternal { const std::vector& connections() const { return connections_; } // Public for unit tests. - PortAllocatorSession* allocator_session() const { - if (allocator_sessions_.empty()) { - return nullptr; - } + PortAllocatorSession* allocator_session() { return allocator_sessions_.back().get(); } @@ -174,7 +171,6 @@ class P2PTransportChannel : public IceTransportInternal { private: rtc::Thread* thread() const { return network_thread_; } - bool IsGettingPorts() { return allocator_session()->IsGettingPorts(); } // A transport channel is weak if the current best connection is either @@ -293,6 +289,8 @@ class P2PTransportChannel : public IceTransportInternal { void OnNominated(Connection* conn); void CheckAndPing(); + void RegatherOnFailedNetworks(); + void RegatherOnAllNetworks(); void LogCandidatePairConfig(Connection* conn, webrtc::IceCandidatePairConfigType type); @@ -344,6 +342,10 @@ class P2PTransportChannel : public IceTransportInternal { : static_cast(remote_ice_parameters_.size() - 1); } + // Samples a delay from the uniform distribution defined by the + // regather_on_all_networks_interval ICE configuration pair. + int SampleRegatherAllNetworksInterval(); + // Indicates if the given local port has been pruned. bool IsPortPruned(const Port* port) const; @@ -393,7 +395,10 @@ class P2PTransportChannel : public IceTransportInternal { IceRole ice_role_; uint64_t tiebreaker_; IceGatheringState gathering_state_; - std::unique_ptr regathering_controller_; + + // Used to generate random intervals for regather_all_networks_interval_range. + webrtc::Random rand_; + int64_t last_ping_sent_ms_ = 0; int weak_ping_interval_ = WEAK_PING_INTERVAL; IceTransportState state_ = IceTransportState::STATE_INIT; diff --git a/p2p/base/regatheringcontroller.cc b/p2p/base/regatheringcontroller.cc deleted file mode 100644 index c358e6ab19..0000000000 --- a/p2p/base/regatheringcontroller.cc +++ /dev/null @@ -1,157 +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. - */ - -#include "p2p/base/regatheringcontroller.h" - -namespace webrtc { - -using Config = BasicRegatheringController::Config; - -Config::Config(const rtc::Optional& - regather_on_all_networks_interval_range, - int regather_on_failed_networks_interval) - : regather_on_all_networks_interval_range( - regather_on_all_networks_interval_range), - regather_on_failed_networks_interval( - regather_on_failed_networks_interval) {} - -Config::Config(const Config& other) = default; - -Config::~Config() = default; -Config& Config::operator=(const Config& other) = default; - -BasicRegatheringController::BasicRegatheringController( - const Config& config, - cricket::IceTransportInternal* ice_transport, - rtc::Thread* thread) - : config_(config), - ice_transport_(ice_transport), - thread_(thread), - rand_(rtc::SystemTimeNanos()) { - RTC_DCHECK(ice_transport_); - RTC_DCHECK(thread_); - ice_transport_->SignalStateChanged.connect( - this, &BasicRegatheringController::OnIceTransportStateChanged); - ice_transport->SignalWritableState.connect( - this, &BasicRegatheringController::OnIceTransportWritableState); - ice_transport->SignalReceivingState.connect( - this, &BasicRegatheringController::OnIceTransportReceivingState); - ice_transport->SignalNetworkRouteChanged.connect( - this, &BasicRegatheringController::OnIceTransportNetworkRouteChanged); -} - -BasicRegatheringController::~BasicRegatheringController() = default; - -void BasicRegatheringController::Start() { - ScheduleRecurringRegatheringOnFailedNetworks(); - if (config_.regather_on_all_networks_interval_range) { - ScheduleRecurringRegatheringOnAllNetworks(); - } -} - -void BasicRegatheringController::SetConfig(const Config& config) { - bool need_cancel_on_all_networks = - has_recurring_schedule_on_all_networks_ && - (config_.regather_on_all_networks_interval_range != - config.regather_on_all_networks_interval_range); - bool need_reschedule_on_all_networks = - config.regather_on_all_networks_interval_range && - (config_.regather_on_all_networks_interval_range != - config.regather_on_all_networks_interval_range); - bool need_cancel_and_reschedule_on_failed_networks = - has_recurring_schedule_on_failed_networks_ && - (config_.regather_on_failed_networks_interval != - config.regather_on_failed_networks_interval); - config_ = config; - if (need_cancel_on_all_networks) { - CancelScheduledRecurringRegatheringOnAllNetworks(); - } - if (need_reschedule_on_all_networks) { - ScheduleRecurringRegatheringOnAllNetworks(); - } - if (need_cancel_and_reschedule_on_failed_networks) { - CancelScheduledRecurringRegatheringOnFailedNetworks(); - ScheduleRecurringRegatheringOnFailedNetworks(); - } -} - -void BasicRegatheringController::ScheduleRecurringRegatheringOnAllNetworks() { - RTC_DCHECK(config_.regather_on_all_networks_interval_range && - config_.regather_on_all_networks_interval_range.value().min() >= - 0); - int delay_ms = SampleRegatherAllNetworksInterval( - config_.regather_on_all_networks_interval_range.value()); - CancelScheduledRecurringRegatheringOnAllNetworks(); - has_recurring_schedule_on_all_networks_ = true; - invoker_for_all_networks_.AsyncInvokeDelayed( - RTC_FROM_HERE, thread(), - rtc::Bind( - &BasicRegatheringController::RegatherOnAllNetworksIfDoneGathering, - this, true), - delay_ms); -} - -void BasicRegatheringController::RegatherOnAllNetworksIfDoneGathering( - bool repeated) { - // Only regather when the current session is in the CLEARED state (i.e., not - // running or stopped). It is only possible to enter this state when we gather - // continually, so there is an implicit check on continual gathering here. - if (allocator_session_ && allocator_session_->IsCleared()) { - allocator_session_->RegatherOnAllNetworks(); - } - if (repeated) { - ScheduleRecurringRegatheringOnAllNetworks(); - } -} - -void BasicRegatheringController:: - ScheduleRecurringRegatheringOnFailedNetworks() { - RTC_DCHECK(config_.regather_on_failed_networks_interval >= 0); - CancelScheduledRecurringRegatheringOnFailedNetworks(); - has_recurring_schedule_on_failed_networks_ = true; - invoker_for_failed_networks_.AsyncInvokeDelayed( - RTC_FROM_HERE, thread(), - rtc::Bind( - &BasicRegatheringController::RegatherOnFailedNetworksIfDoneGathering, - this, true), - config_.regather_on_failed_networks_interval); -} - -void BasicRegatheringController::RegatherOnFailedNetworksIfDoneGathering( - bool repeated) { - // Only regather when the current session is in the CLEARED state (i.e., not - // running or stopped). It is only possible to enter this state when we gather - // continually, so there is an implicit check on continual gathering here. - if (allocator_session_ && allocator_session_->IsCleared()) { - allocator_session_->RegatherOnFailedNetworks(); - } - if (repeated) { - ScheduleRecurringRegatheringOnFailedNetworks(); - } -} - -void BasicRegatheringController:: - CancelScheduledRecurringRegatheringOnAllNetworks() { - invoker_for_all_networks_.Clear(); - has_recurring_schedule_on_all_networks_ = false; -} - -void BasicRegatheringController:: - CancelScheduledRecurringRegatheringOnFailedNetworks() { - invoker_for_failed_networks_.Clear(); - has_recurring_schedule_on_failed_networks_ = false; -} - -int BasicRegatheringController::SampleRegatherAllNetworksInterval( - const rtc::IntervalRange& range) { - return rand_.Rand(range.min(), range.max()); -} - -} // namespace webrtc diff --git a/p2p/base/regatheringcontroller.h b/p2p/base/regatheringcontroller.h deleted file mode 100644 index e030ff097c..0000000000 --- a/p2p/base/regatheringcontroller.h +++ /dev/null @@ -1,124 +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_REGATHERINGCONTROLLER_H_ -#define P2P_BASE_REGATHERINGCONTROLLER_H_ - -#include "p2p/base/icetransportinternal.h" -#include "p2p/base/portallocator.h" -#include "rtc_base/asyncinvoker.h" -#include "rtc_base/random.h" -#include "rtc_base/thread.h" - -namespace webrtc { - -// Controls regathering of candidates for the ICE transport passed into it, -// reacting to signals like SignalWritableState, SignalNetworkRouteChange, etc., -// using methods like GetStats to get additional information, and calling -// methods like RegatherOnAllNetworks on the PortAllocatorSession when -// regathering is desired. -// -// TODO(qingsi): Add the description of behavior when autonomous regathering is -// implemented. -// -// "Regathering" is defined as gathering additional candidates within a single -// ICE generation (or in other words, PortAllocatorSession), and is possible -// when "continual gathering" is enabled. This may allow connectivity to be -// maintained and/or restored without a full ICE restart. -// -// Regathering will only begin after PortAllocationSession is set via -// set_allocator_session. This should be called any time the "active" -// PortAllocatorSession is changed (in other words, when an ICE restart occurs), -// so that candidates are gathered for the "current" ICE generation. -// -// All methods of BasicRegatheringController should be called on the same -// thread as the one passed to the constructor, and this thread should be the -// same one where PortAllocatorSession runs, which is also identical to the -// network thread of the ICE transport, as given by -// P2PTransportChannel::thread(). -class BasicRegatheringController : public sigslot::has_slots<> { - public: - struct Config { - Config(const rtc::Optional& - regather_on_all_networks_interval_range, - int regather_on_failed_networks_interval); - Config(const Config& other); - ~Config(); - Config& operator=(const Config& other); - rtc::Optional regather_on_all_networks_interval_range; - int regather_on_failed_networks_interval; - }; - - BasicRegatheringController() = delete; - BasicRegatheringController(const Config& config, - cricket::IceTransportInternal* ice_transport, - rtc::Thread* thread); - ~BasicRegatheringController() override; - // TODO(qingsi): Remove this method after implementing a new signal in - // P2PTransportChannel and reacting to that signal for the initial schedules - // of regathering. - void Start(); - void set_allocator_session(cricket::PortAllocatorSession* allocator_session) { - allocator_session_ = allocator_session; - } - // Setting a different config of the regathering interval range on all - // networks cancels and reschedules the recurring schedules, if any, of - // regathering on all networks. The same applies to the change of the - // regathering interval on the failed networks. This rescheduling behavior is - // seperately defined for the two config parameters. - void SetConfig(const Config& config); - - private: - // TODO(qingsi): Implement the following methods and use methods from the ICE - // transport like GetStats to get additional information for the decision - // making in regathering. - void OnIceTransportStateChanged(cricket::IceTransportInternal*) {} - void OnIceTransportWritableState(rtc::PacketTransportInternal*) {} - void OnIceTransportReceivingState(rtc::PacketTransportInternal*) {} - void OnIceTransportNetworkRouteChanged(rtc::Optional) {} - // Schedules delayed and repeated regathering of local candidates on all - // networks, where the delay in milliseconds is randomly sampled from the - // range in the config. The delay of each repetition is independently sampled - // from the same range. When scheduled, all previous schedules are canceled. - void ScheduleRecurringRegatheringOnAllNetworks(); - // Schedules delayed and repeated regathering of local candidates on failed - // networks, where the delay in milliseconds is given by the config. Each - // repetition is separated by the same delay. When scheduled, all previous - // schedules are canceled. - void ScheduleRecurringRegatheringOnFailedNetworks(); - // Cancels regathering scheduled by ScheduleRecurringRegatheringOnAllNetworks. - void CancelScheduledRecurringRegatheringOnAllNetworks(); - // Cancels regathering scheduled by - // ScheduleRecurringRegatheringOnFailedNetworks. - void CancelScheduledRecurringRegatheringOnFailedNetworks(); - - rtc::Thread* thread() const { return thread_; } - // The following two methods perform the actual regathering, if the recent - // port allocator session has done the initial gathering. - void RegatherOnAllNetworksIfDoneGathering(bool repeated); - void RegatherOnFailedNetworksIfDoneGathering(bool repeated); - // Samples a delay from the uniform distribution in the given range. - int SampleRegatherAllNetworksInterval(const rtc::IntervalRange& range); - - Config config_; - cricket::IceTransportInternal* ice_transport_; - cricket::PortAllocatorSession* allocator_session_ = nullptr; - bool has_recurring_schedule_on_all_networks_ = false; - bool has_recurring_schedule_on_failed_networks_ = false; - rtc::Thread* thread_; - rtc::AsyncInvoker invoker_for_all_networks_; - rtc::AsyncInvoker invoker_for_failed_networks_; - // Used to generate random intervals for regather_all_networks_interval_range. - Random rand_; -}; - -} // namespace webrtc - -#endif // P2P_BASE_REGATHERINGCONTROLLER_H_ diff --git a/p2p/base/regatheringcontroller_unittest.cc b/p2p/base/regatheringcontroller_unittest.cc deleted file mode 100644 index 64f6bbfc35..0000000000 --- a/p2p/base/regatheringcontroller_unittest.cc +++ /dev/null @@ -1,303 +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. - */ - -#include -#include -#include -#include - -#include "api/fakemetricsobserver.h" -#include "p2p/base/fakeportallocator.h" -#include "p2p/base/mockicetransport.h" -#include "p2p/base/p2pconstants.h" -#include "p2p/base/port.h" -#include "p2p/base/regatheringcontroller.h" -#include "p2p/base/stunserver.h" -#include "rtc_base/gunit.h" -#include "rtc_base/refcountedobject.h" -#include "rtc_base/scoped_ref_ptr.h" -#include "rtc_base/socketaddress.h" -#include "rtc_base/thread.h" - -namespace { - -const int kOnlyLocalPorts = cricket::PORTALLOCATOR_DISABLE_STUN | - cricket::PORTALLOCATOR_DISABLE_RELAY | - cricket::PORTALLOCATOR_DISABLE_TCP; -// The address of the public STUN server. -const rtc::SocketAddress kStunAddr("99.99.99.1", cricket::STUN_SERVER_PORT); -// The addresses for the public TURN server. -const rtc::SocketAddress kTurnUdpIntAddr("99.99.99.3", - cricket::STUN_SERVER_PORT); -const cricket::RelayCredentials kRelayCredentials("test", "test"); -const char kIceUfrag[] = "UF00"; -const char kIcePwd[] = "TESTICEPWD00000000000000"; - -} // namespace - -namespace webrtc { - -class RegatheringControllerTest : public testing::Test, - public sigslot::has_slots<> { - public: - RegatheringControllerTest() - : ice_transport_(new cricket::MockIceTransport()), - allocator_( - new cricket::FakePortAllocator(rtc::Thread::Current(), nullptr)) { - BasicRegatheringController::Config regathering_config(rtc::nullopt, 0); - regathering_controller_.reset(new BasicRegatheringController( - regathering_config, ice_transport_.get(), rtc::Thread::Current())); - } - - // Initializes the allocator and gathers candidates once by StartGettingPorts. - void InitializeAndGatherOnce() { - cricket::ServerAddresses stun_servers; - stun_servers.insert(kStunAddr); - cricket::RelayServerConfig turn_server(cricket::RELAY_TURN); - turn_server.credentials = kRelayCredentials; - turn_server.ports.push_back( - cricket::ProtocolAddress(kTurnUdpIntAddr, cricket::PROTO_UDP)); - std::vector turn_servers(1, turn_server); - allocator_->set_flags(kOnlyLocalPorts); - allocator_->SetConfiguration(stun_servers, turn_servers, 0 /* pool size */, - false /* prune turn ports */); - allocator_session_ = allocator_->CreateSession( - "test", cricket::ICE_CANDIDATE_COMPONENT_RTP, kIceUfrag, kIcePwd); - // The gathering will take place on the current thread and the following - // call of StartGettingPorts is blocking. We will not ClearGettingPorts - // prematurely. - allocator_session_->StartGettingPorts(); - allocator_session_->SignalIceRegathering.connect( - this, &RegatheringControllerTest::OnIceRegathering); - regathering_controller_->set_allocator_session(allocator_session_.get()); - } - - // The regathering controller is initialized with the allocator session - // cleared. Only after clearing the session, we would be able to regather. See - // the comments for BasicRegatheringController in regatheringcontroller.h. - void InitializeAndGatherOnceWithSessionCleared() { - InitializeAndGatherOnce(); - allocator_session_->ClearGettingPorts(); - } - - void OnIceRegathering(cricket::PortAllocatorSession* allocator_session, - cricket::IceRegatheringReason reason) { - ++count_[reason]; - } - - int GetRegatheringReasonCount(cricket::IceRegatheringReason reason) { - return count_[reason]; - } - - BasicRegatheringController* regathering_controller() { - return regathering_controller_.get(); - } - - private: - std::unique_ptr ice_transport_; - std::unique_ptr regathering_controller_; - std::unique_ptr allocator_; - std::unique_ptr allocator_session_; - std::map count_; -}; - -// Tests that ICE regathering occurs only if the port allocator session is -// cleared. A port allocation session is not cleared if the initial gathering is -// still in progress or the continual gathering is not enabled. -TEST_F(RegatheringControllerTest, - IceRegatheringDoesNotOccurIfSessionNotCleared) { - rtc::ScopedFakeClock clock; - InitializeAndGatherOnce(); // Session not cleared. - - rtc::IntervalRange regather_all_networks_interval_range(2000, 2000); - BasicRegatheringController::Config config( - regather_all_networks_interval_range, 2000); - regathering_controller()->SetConfig(config); - regathering_controller()->Start(); - SIMULATED_WAIT(false, 10000, clock); - // Expect no regathering in the last 10s. - EXPECT_EQ(0, GetRegatheringReasonCount( - cricket::IceRegatheringReason::OCCASIONAL_REFRESH)); - EXPECT_EQ(0, GetRegatheringReasonCount( - cricket::IceRegatheringReason::NETWORK_FAILURE)); -} - -TEST_F(RegatheringControllerTest, IceRegatheringRepeatsAsScheduled) { - rtc::ScopedFakeClock clock; - InitializeAndGatherOnceWithSessionCleared(); - - rtc::IntervalRange regather_all_networks_interval_range(2000, 2000); - BasicRegatheringController::Config config( - regather_all_networks_interval_range, 2000); - regathering_controller()->SetConfig(config); - regathering_controller()->Start(); - SIMULATED_WAIT(false, 2000 - 1, clock); - // Expect no regathering. - EXPECT_EQ(0, GetRegatheringReasonCount( - cricket::IceRegatheringReason::OCCASIONAL_REFRESH)); - EXPECT_EQ(0, GetRegatheringReasonCount( - cricket::IceRegatheringReason::NETWORK_FAILURE)); - SIMULATED_WAIT(false, 2, clock); - // Expect regathering on all networks and on failed networks to happen once - // respectively in that last 2s with 2s interval. - EXPECT_EQ(1, GetRegatheringReasonCount( - cricket::IceRegatheringReason::OCCASIONAL_REFRESH)); - EXPECT_EQ(1, GetRegatheringReasonCount( - cricket::IceRegatheringReason::NETWORK_FAILURE)); - SIMULATED_WAIT(false, 11000, clock); - // Expect regathering to happen for another 5 times in 11s with 2s interval. - EXPECT_EQ(6, GetRegatheringReasonCount( - cricket::IceRegatheringReason::OCCASIONAL_REFRESH)); - EXPECT_EQ(6, GetRegatheringReasonCount( - cricket::IceRegatheringReason::NETWORK_FAILURE)); -} - -// Tests that the schedule of ICE regathering on all networks can be started -// when not scheduled initially. -TEST_F(RegatheringControllerTest, - IceRegatheringOnAllNetworksCanBeScheduledAfterStart) { - rtc::ScopedFakeClock clock; - InitializeAndGatherOnceWithSessionCleared(); - - BasicRegatheringController::Config config(rtc::nullopt, 2000); - regathering_controller()->SetConfig(config); - regathering_controller()->Start(); - SIMULATED_WAIT(false, 3000, clock); - // Expect no regathering on all networks. - EXPECT_EQ(0, GetRegatheringReasonCount( - cricket::IceRegatheringReason::OCCASIONAL_REFRESH)); - config.regather_on_all_networks_interval_range = - rtc::IntervalRange(2000, 2000); - regathering_controller()->SetConfig(config); - SIMULATED_WAIT(false, 11000, clock); - // Expect regathering to happen for 5 times on all networks in the last 11s - // with 2s interval. - EXPECT_EQ(5, GetRegatheringReasonCount( - cricket::IceRegatheringReason::OCCASIONAL_REFRESH)); -} - -// Tests that ICE regathering on all networks can be canceled by changing the -// config. -TEST_F(RegatheringControllerTest, IceRegatheringOnAllNetworksCanBeCanceled) { - rtc::ScopedFakeClock clock; - InitializeAndGatherOnceWithSessionCleared(); - - rtc::IntervalRange regather_all_networks_interval_range(2000, 2000); - BasicRegatheringController::Config config( - regather_all_networks_interval_range, 2000); - regathering_controller()->SetConfig(config); - regathering_controller()->Start(); - config.regather_on_all_networks_interval_range.reset(); - // Set the regathering interval range on all networks to nullopt should cancel - // the schedule on all networks. - regathering_controller()->SetConfig(config); - SIMULATED_WAIT(false, 10000, clock); - // Expect no regathering on all networks happened in the last 10s. - EXPECT_EQ(0, GetRegatheringReasonCount( - cricket::IceRegatheringReason::OCCASIONAL_REFRESH)); -} - -// Tests that canceling the regathering on all networks does not cancel the -// schedule on failed networks. -TEST_F(RegatheringControllerTest, - CancelingRegatheringOnAllNetworksDoesNotCancelOnFailedNetworks) { - rtc::ScopedFakeClock clock; - InitializeAndGatherOnceWithSessionCleared(); - - rtc::IntervalRange regather_all_networks_interval_range(2000, 2000); - BasicRegatheringController::Config config( - regather_all_networks_interval_range, 2000); - regathering_controller()->SetConfig(config); - regathering_controller()->Start(); - config.regather_on_all_networks_interval_range = - rtc::IntervalRange(20000, 20000); - // Canceling and rescheduling the regathering on all networks should not - // impact the schedule for failed networks. - regathering_controller()->SetConfig(config); - SIMULATED_WAIT(false, 11000, clock); - // Expect regathering to happen for 5 times for failed networks in the last - // 11s with 2s interval. - EXPECT_EQ(5, GetRegatheringReasonCount( - cricket::IceRegatheringReason::NETWORK_FAILURE)); -} - -// Tests that canceling the regathering on failed networks does not cancel the -// schedule on all networks. -TEST_F(RegatheringControllerTest, - CancelingRegatheringOnFailedNetworksDoesNotCancelOnAllNetworks) { - rtc::ScopedFakeClock clock; - InitializeAndGatherOnceWithSessionCleared(); - - rtc::IntervalRange regather_all_networks_interval_range(2000, 2000); - BasicRegatheringController::Config config( - regather_all_networks_interval_range, 2000); - regathering_controller()->SetConfig(config); - regathering_controller()->Start(); - config.regather_on_failed_networks_interval = 20000; - // Canceling and rescheduling the regathering on failed networks should not - // impact the schedule for all networks. - regathering_controller()->SetConfig(config); - SIMULATED_WAIT(false, 11000, clock); - // Expect regathering to happen for 5 times for all networks in the last 11s - // with 2s interval. - EXPECT_EQ(5, GetRegatheringReasonCount( - cricket::IceRegatheringReason::OCCASIONAL_REFRESH)); -} - -// Tests that the schedule of ICE regathering on all networks can be canceled -// and replaced by a new recurring schedule. -TEST_F(RegatheringControllerTest, - ScheduleOfIceRegatheringOnAllNetworksCanBeReplaced) { - rtc::ScopedFakeClock clock; - InitializeAndGatherOnceWithSessionCleared(); - - rtc::IntervalRange regather_all_networks_interval_range(2000, 2000); - BasicRegatheringController::Config config( - regather_all_networks_interval_range, 2000); - regathering_controller()->SetConfig(config); - regathering_controller()->Start(); - config.regather_on_all_networks_interval_range = - rtc::IntervalRange(5000, 5000); - regathering_controller()->SetConfig(config); - SIMULATED_WAIT(false, 3000, clock); - // Expect no regathering from the previous schedule. - EXPECT_EQ(0, GetRegatheringReasonCount( - cricket::IceRegatheringReason::OCCASIONAL_REFRESH)); - SIMULATED_WAIT(false, 11000 - 3000, clock); - // Expect regathering to happen twice in the last 11s with 5s interval. - EXPECT_EQ(2, GetRegatheringReasonCount( - cricket::IceRegatheringReason::OCCASIONAL_REFRESH)); -} - -// Tests that the schedule of ICE regathering on failed networks can be canceled -// and replaced by a new recurring schedule. -TEST_F(RegatheringControllerTest, - ScheduleOfIceRegatheringOnFailedNetworksCanBeReplaced) { - rtc::ScopedFakeClock clock; - InitializeAndGatherOnceWithSessionCleared(); - - rtc::IntervalRange regather_all_networks_interval_range(2000, 2000); - BasicRegatheringController::Config config( - regather_all_networks_interval_range, 2000); - regathering_controller()->SetConfig(config); - regathering_controller()->Start(); - config.regather_on_failed_networks_interval = 5000; - regathering_controller()->SetConfig(config); - SIMULATED_WAIT(false, 3000, clock); - // Expect no regathering from the previous schedule. - EXPECT_EQ(0, GetRegatheringReasonCount( - cricket::IceRegatheringReason::NETWORK_FAILURE)); - SIMULATED_WAIT(false, 11000 - 3000, clock); - // Expect regathering to happen twice in the last 11s with 5s interval. - EXPECT_EQ(2, GetRegatheringReasonCount( - cricket::IceRegatheringReason::NETWORK_FAILURE)); -} - -} // namespace webrtc