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}
This commit is contained in:
@ -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",
|
||||
|
@ -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<PortInterface*> ReadyPorts() const override {
|
||||
return ready_ports_;
|
||||
@ -213,7 +204,6 @@ class FakePortAllocatorSession : public PortAllocatorSession {
|
||||
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;
|
||||
|
@ -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<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 @@ 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<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 @@ 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) {
|
||||
|
@ -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<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 @@ 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<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 @@ class P2PTransportChannel : public IceTransportInternal {
|
||||
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;
|
||||
|
@ -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
|
@ -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_
|
@ -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
|
Reference in New Issue
Block a user