Revert "Refactor the regathering of candidates in P2PTransportChannel."
This reverts commit 14f8aba9967ac2f1789ede12ff66107962757fb5.
Reason for revert: breaking internal tests
Original change's description:
> Refactor the regathering of candidates in P2PTransportChannel.
>
> The functionality of regathering candidates is refactored to a separate
> regathering controller owned by P2PTransportChannel. This refactoring
> is part of a long-term plan to restructure a modularied
> P2PTransportChannel and it would also benefit the addition of autonomous
> regathering of candidates that is proactive to the ICE states in the
> near future.
>
> Bug: None
> Change-Id: I74cea974ea628430c77b5d51b7c9179ddffc690d
> Reviewed-on: https://webrtc-review.googlesource.com/75820
> Commit-Queue: Qingsi Wang <qingsi@google.com>
> Reviewed-by: Taylor Brandstetter <deadbeef@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#23588}
TBR=deadbeef@webrtc.org,pthatcher@webrtc.org,qingsi@google.com
Change-Id: I8b08351c9a3fcf89e2a25ed2c668c335cbd2d2d0
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: None
Reviewed-on: https://webrtc-review.googlesource.com/83300
Reviewed-by: Qingsi Wang <qingsi@webrtc.org>
Commit-Queue: Qingsi Wang <qingsi@google.com>
Cr-Commit-Position: refs/heads/master@{#23592}
diff --git a/p2p/BUILD.gn b/p2p/BUILD.gn
index 07d1f71..769bd4b 100644
--- a/p2p/BUILD.gn
+++ b/p2p/BUILD.gn
@@ -48,8 +48,6 @@
"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 @@
"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 5a52bbc..b5db823 100644
--- a/p2p/base/fakeportallocator.h
+++ b/p2p/base/fakeportallocator.h
@@ -139,16 +139,7 @@
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<PortInterface*> ReadyPorts() const override {
return ready_ports_;
@@ -213,7 +204,6 @@
std::vector<Candidate> candidates_;
std::vector<PortInterface*> ready_ports_;
bool allocation_done_ = false;
- bool is_cleared = false;
ServerAddresses stun_servers_;
std::vector<RelayServerConfig> turn_servers_;
uint32_t candidate_filter_ = CF_ALL;
diff --git a/p2p/base/p2ptransportchannel.cc b/p2p/base/p2ptransportchannel.cc
index d1c58c2..0b6beb9 100644
--- a/p2p/base/p2ptransportchannel.cc
+++ b/p2p/base/p2ptransportchannel.cc
@@ -125,6 +125,7 @@
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 @@
// 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 @@
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 @@
<< 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 @@
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 @@
"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 @@
invoker_.AsyncInvoke<void>(
RTC_FROM_HERE, thread(),
rtc::Bind(&P2PTransportChannel::CheckAndPing, this));
- regathering_controller_->Start();
+ invoker_.AsyncInvokeDelayed<void>(
+ 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<void>(
+ RTC_FROM_HERE, thread(),
+ rtc::Bind(&P2PTransportChannel::RegatherOnAllNetworks, this),
+ SampleRegatherAllNetworksInterval());
+ }
started_pinging_ = true;
}
}
@@ -2195,6 +2185,31 @@
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<void>(
+ 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<void>(
+ 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 @@
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 8e3b06c..c061431 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 @@
const std::vector<Connection*>& 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 @@
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 @@
void OnNominated(Connection* conn);
void CheckAndPing();
+ void RegatherOnFailedNetworks();
+ void RegatherOnAllNetworks();
void LogCandidatePairConfig(Connection* conn,
webrtc::IceCandidatePairConfigType type);
@@ -344,6 +342,10 @@
: static_cast<uint32_t>(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 @@
IceRole ice_role_;
uint64_t tiebreaker_;
IceGatheringState gathering_state_;
- std::unique_ptr<webrtc::BasicRegatheringController> 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 c358e6a..0000000
--- 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<rtc::IntervalRange>&
- 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<void>(
- 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<void>(
- 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 e030ff0..0000000
--- 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<rtc::IntervalRange>&
- regather_on_all_networks_interval_range,
- int regather_on_failed_networks_interval);
- Config(const Config& other);
- ~Config();
- Config& operator=(const Config& other);
- rtc::Optional<rtc::IntervalRange> 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<rtc::NetworkRoute>) {}
- // 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 64f6bbf..0000000
--- 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 <map>
-#include <memory>
-#include <string>
-#include <vector>
-
-#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<cricket::RelayServerConfig> 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<cricket::IceTransportInternal> ice_transport_;
- std::unique_ptr<BasicRegatheringController> regathering_controller_;
- std::unique_ptr<cricket::PortAllocator> allocator_;
- std::unique_ptr<cricket::PortAllocatorSession> allocator_session_;
- std::map<cricket::IceRegatheringReason, int> 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