API for periodically regathering ICE candidates

Adds to the RTCConfiguration `ice_regather_interval_range` which, when
set, specifies the randomized delay between automatic runs of ICE
regathering. The regathering will occur on all networks and re-use the
existing ICE ufrag/password. New connections are established once the
candidates come back and WebRTC will automatically switch to the new
connection that corresponds to the currently selected connection.

Bug: webrtc:7969
Change-Id: I6bbf5439a48e285f704aed9f408631cba038c82b
Reviewed-on: https://chromium-review.googlesource.com/562505
Reviewed-by: Peter Thatcher <pthatcher@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#18978}
This commit is contained in:
Steve Anton 2017-07-11 14:38:29 -07:00
parent f1f9889c44
commit aa41f0cfa6
11 changed files with 294 additions and 31 deletions

View File

@ -453,6 +453,13 @@ class PeerConnectionInterface : public rtc::RefCountInterface {
// (STUN pings), in milliseconds. // (STUN pings), in milliseconds.
rtc::Optional<int> ice_check_min_interval; rtc::Optional<int> ice_check_min_interval;
// ICE Periodic Regathering
// If set, WebRTC will periodically create and propose candidates without
// starting a new ICE generation. The regathering happens continuously with
// interval specified in milliseconds by the uniform distribution [a, b].
rtc::Optional<rtc::IntervalRange> ice_regather_interval_range;
// //
// Don't forget to update operator== if adding something. // Don't forget to update operator== if adding something.
// //

View File

@ -184,6 +184,10 @@ struct IceConfig {
// active network having no connection on it. // active network having no connection on it.
rtc::Optional<int> regather_on_failed_networks_interval; rtc::Optional<int> regather_on_failed_networks_interval;
// Interval to perform ICE regathering on all networks
// The delay in milliseconds is sampled from the uniform distribution [a, b]
rtc::Optional<rtc::IntervalRange> regather_all_networks_interval_range;
// The time period in which we will not switch the selected connection // The time period in which we will not switch the selected connection
// when a new connection becomes receiving but the selected connection is not // when a new connection becomes receiving but the selected connection is not
// in case that the selected connection may become receiving soon. // in case that the selected connection may become receiving soon.

View File

@ -12,6 +12,7 @@
#include <algorithm> #include <algorithm>
#include <iterator> #include <iterator>
#include <random>
#include <set> #include <set>
#include "webrtc/api/umametrics.h" #include "webrtc/api/umametrics.h"
@ -32,7 +33,8 @@ namespace {
enum { enum {
MSG_SORT_AND_UPDATE_STATE = 1, MSG_SORT_AND_UPDATE_STATE = 1,
MSG_CHECK_AND_PING, MSG_CHECK_AND_PING,
MSG_REGATHER_ON_FAILED_NETWORKS MSG_REGATHER_ON_FAILED_NETWORKS,
MSG_REGATHER_ON_ALL_NETWORKS
}; };
// The minimum improvement in RTT that justifies a switch. // The minimum improvement in RTT that justifies a switch.
@ -111,6 +113,7 @@ P2PTransportChannel::P2PTransportChannel(const std::string& transport_name,
ice_role_(ICEROLE_UNKNOWN), ice_role_(ICEROLE_UNKNOWN),
tiebreaker_(0), tiebreaker_(0),
gathering_state_(kIceGatheringNew), gathering_state_(kIceGatheringNew),
rand_(std::random_device()()),
check_receiving_interval_(MIN_CHECK_RECEIVING_INTERVAL * 5), check_receiving_interval_(MIN_CHECK_RECEIVING_INTERVAL * 5),
config_(MIN_CHECK_RECEIVING_INTERVAL * 50 /* receiving_timeout */, config_(MIN_CHECK_RECEIVING_INTERVAL * 50 /* receiving_timeout */,
DEFAULT_BACKUP_CONNECTION_PING_INTERVAL, DEFAULT_BACKUP_CONNECTION_PING_INTERVAL,
@ -428,6 +431,14 @@ void P2PTransportChannel::SetIceConfig(const IceConfig& config) {
LOG(LS_INFO) << "Set regather_on_failed_networks_interval to " LOG(LS_INFO) << "Set regather_on_failed_networks_interval to "
<< *config_.regather_on_failed_networks_interval; << *config_.regather_on_failed_networks_interval;
} }
if (config.regather_all_networks_interval_range) {
config_.regather_all_networks_interval_range =
config.regather_all_networks_interval_range;
LOG(LS_INFO) << "Set regather_all_networks_interval_range to "
<< config.regather_all_networks_interval_range->ToString();
}
if (config.receiving_switching_delay) { if (config.receiving_switching_delay) {
config_.receiving_switching_delay = config.receiving_switching_delay; config_.receiving_switching_delay = config.receiving_switching_delay;
LOG(LS_INFO) << "Set receiving_switching_delay to" LOG(LS_INFO) << "Set receiving_switching_delay to"
@ -1077,6 +1088,11 @@ void P2PTransportChannel::MaybeStartPinging() {
thread()->PostDelayed(RTC_FROM_HERE, thread()->PostDelayed(RTC_FROM_HERE,
*config_.regather_on_failed_networks_interval, this, *config_.regather_on_failed_networks_interval, this,
MSG_REGATHER_ON_FAILED_NETWORKS); MSG_REGATHER_ON_FAILED_NETWORKS);
if (config_.regather_all_networks_interval_range) {
thread()->PostDelayed(RTC_FROM_HERE,
SampleRegatherAllNetworksInterval(), this,
MSG_REGATHER_ON_ALL_NETWORKS);
}
started_pinging_ = true; started_pinging_ = true;
} }
} }
@ -1182,8 +1198,39 @@ int P2PTransportChannel::CompareConnectionCandidates(
// If we're still tied at this point, prefer a younger generation. // If we're still tied at this point, prefer a younger generation.
// (Younger generation means a larger generation number). // (Younger generation means a larger generation number).
return (a->remote_candidate().generation() + a->port()->generation()) - int cmp = (a->remote_candidate().generation() + a->port()->generation()) -
(b->remote_candidate().generation() + b->port()->generation()); (b->remote_candidate().generation() + b->port()->generation());
if (cmp != 0) {
return cmp;
}
// A periodic regather (triggered by the regather_all_networks_interval_range)
// will produce candidates that appear the same but would use a new port. We
// want to use the new candidates and purge the old candidates as they come
// in, so use the fact that the old ports get pruned immediately to rank the
// candidates with an active port/remote candidate higher.
bool a_pruned = IsPortPruned(a->port()) ||
IsRemoteCandidatePruned(a->remote_candidate());
bool b_pruned = IsPortPruned(b->port()) ||
IsRemoteCandidatePruned(b->remote_candidate());
if (!a_pruned && b_pruned) {
return a_is_better;
}
if (a_pruned && !b_pruned) {
return b_is_better;
}
// Otherwise, must be equal
return 0;
}
bool P2PTransportChannel::IsPortPruned(const Port* port) const {
return std::find(ports_.begin(), ports_.end(), port) == ports_.end();
}
bool P2PTransportChannel::IsRemoteCandidatePruned(const Candidate& cand) const {
return std::find(remote_candidates_.begin(), remote_candidates_.end(), cand)
== remote_candidates_.end();
} }
int P2PTransportChannel::CompareConnections( int P2PTransportChannel::CompareConnections(
@ -1528,6 +1575,9 @@ void P2PTransportChannel::OnMessage(rtc::Message *pmsg) {
case MSG_REGATHER_ON_FAILED_NETWORKS: case MSG_REGATHER_ON_FAILED_NETWORKS:
OnRegatherOnFailedNetworks(); OnRegatherOnFailedNetworks();
break; break;
case MSG_REGATHER_ON_ALL_NETWORKS:
OnRegatherOnAllNetworks();
break;
default: default:
RTC_NOTREACHED(); RTC_NOTREACHED();
break; break;
@ -1913,6 +1963,16 @@ void P2PTransportChannel::OnRegatherOnFailedNetworks() {
MSG_REGATHER_ON_FAILED_NETWORKS); MSG_REGATHER_ON_FAILED_NETWORKS);
} }
void P2PTransportChannel::OnRegatherOnAllNetworks() {
if (!allocator_sessions_.empty() && allocator_session()->IsCleared()) {
allocator_session()->RegatherOnAllNetworks();
}
thread()->PostDelayed(RTC_FROM_HERE,
SampleRegatherAllNetworksInterval(), this,
MSG_REGATHER_ON_ALL_NETWORKS);
}
void P2PTransportChannel::PruneAllPorts() { void P2PTransportChannel::PruneAllPorts() {
pruned_ports_.insert(pruned_ports_.end(), ports_.begin(), ports_.end()); pruned_ports_.insert(pruned_ports_.end(), ports_.begin(), ports_.end());
ports_.clear(); ports_.clear();
@ -2066,4 +2126,10 @@ void P2PTransportChannel::set_receiving(bool receiving) {
SignalReceivingState(this); SignalReceivingState(this);
} }
int P2PTransportChannel::SampleRegatherAllNetworksInterval() {
auto interval = config_.regather_all_networks_interval_range;
RTC_DCHECK(interval);
return rand_.Rand(interval->min(), interval->max());
}
} // namespace cricket } // namespace cricket

View File

@ -33,6 +33,7 @@
#include "webrtc/p2p/base/portinterface.h" #include "webrtc/p2p/base/portinterface.h"
#include "webrtc/rtc_base/asyncpacketsocket.h" #include "webrtc/rtc_base/asyncpacketsocket.h"
#include "webrtc/rtc_base/constructormagic.h" #include "webrtc/rtc_base/constructormagic.h"
#include "webrtc/rtc_base/random.h"
#include "webrtc/rtc_base/sigslot.h" #include "webrtc/rtc_base/sigslot.h"
namespace cricket { namespace cricket {
@ -280,6 +281,7 @@ class P2PTransportChannel : public IceTransportInternal,
void OnMessage(rtc::Message* pmsg) override; void OnMessage(rtc::Message* pmsg) override;
void OnCheckAndPing(); void OnCheckAndPing();
void OnRegatherOnFailedNetworks(); void OnRegatherOnFailedNetworks();
void OnRegatherOnAllNetworks();
uint32_t GetNominationAttr(Connection* conn) const; uint32_t GetNominationAttr(Connection* conn) const;
bool GetUseCandidateAttr(Connection* conn, NominationMode mode) const; bool GetUseCandidateAttr(Connection* conn, NominationMode mode) const;
@ -328,6 +330,16 @@ class P2PTransportChannel : public IceTransportInternal,
: static_cast<uint32_t>(remote_ice_parameters_.size() - 1); : 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;
// Indicates if the given remote candidate has been pruned.
bool IsRemoteCandidatePruned(const Candidate& cand) const;
// Sets the writable state, signaling if necessary. // Sets the writable state, signaling if necessary.
void set_writable(bool writable); void set_writable(bool writable);
// Sets the receiving state, signaling if necessary. // Sets the receiving state, signaling if necessary.
@ -372,6 +384,9 @@ class P2PTransportChannel : public IceTransportInternal,
uint64_t tiebreaker_; uint64_t tiebreaker_;
IceGatheringState gathering_state_; IceGatheringState gathering_state_;
// Used to generate random intervals for regather_all_networks_interval_range.
webrtc::Random rand_;
int check_receiving_interval_; int check_receiving_interval_;
int64_t last_ping_sent_ms_ = 0; int64_t last_ping_sent_ms_ = 0;
int weak_ping_interval_ = WEAK_PING_INTERVAL; int weak_ping_interval_ = WEAK_PING_INTERVAL;

View File

@ -1362,6 +1362,106 @@ TEST_F(P2PTransportChannelTest,
DestroyChannels(); DestroyChannels();
} }
// Tests that ICE regathering occurs regularly when
// regather_all_networks_interval_range configuration value is set.
TEST_F(P2PTransportChannelTest, TestIceRegatherOnAllNetworksContinual) {
rtc::ScopedFakeClock clock;
ConfigureEndpoints(OPEN, OPEN, kOnlyLocalPorts, kOnlyLocalPorts);
// ep1 gathers continually but ep2 does not.
const int kRegatherInterval = 2000;
IceConfig config1 = CreateIceConfig(1000, GATHER_CONTINUALLY);
config1.regather_all_networks_interval_range.emplace(
kRegatherInterval, kRegatherInterval);
IceConfig config2;
config2.regather_all_networks_interval_range.emplace(
kRegatherInterval, kRegatherInterval);
CreateChannels(config1, config2);
EXPECT_TRUE_SIMULATED_WAIT(ep1_ch1()->receiving() && ep1_ch1()->writable() &&
ep2_ch1()->receiving() &&
ep2_ch1()->writable(),
kDefaultTimeout, clock);
fw()->AddRule(false, rtc::FP_ANY, rtc::FD_ANY, kPublicAddrs[0]);
// Timeout value such that all connections are deleted.
const int kNetworkGatherDuration = 11000;
SIMULATED_WAIT(false, kNetworkGatherDuration, clock);
// Expect regathering to happen 5 times in 11s with 2s interval.
EXPECT_LE(5, GetMetricsObserver(0)->GetEnumCounter(
webrtc::kEnumCounterIceRegathering,
static_cast<int>(IceRegatheringReason::OCCASIONAL_REFRESH)));
// Expect no regathering if continual gathering not configured.
EXPECT_EQ(0, GetMetricsObserver(1)->GetEnumCounter(
webrtc::kEnumCounterIceRegathering,
static_cast<int>(IceRegatheringReason::OCCASIONAL_REFRESH)));
DestroyChannels();
}
// Test that ICE periodic regathering can change the selected connection on the
// specified interval and that the peers can communicate over the new
// connection. The test is parameterized to test that it works when regathering
// is done by the ICE controlling peer and when done by the controlled peer.
class P2PTransportRegatherAllNetworksTest : public P2PTransportChannelTest {
protected:
void TestWithRoles(IceRole p1_role, IceRole p2_role) {
rtc::ScopedFakeClock clock;
ConfigureEndpoints(NAT_SYMMETRIC, NAT_SYMMETRIC, kDefaultPortAllocatorFlags,
kDefaultPortAllocatorFlags);
set_force_relay(true);
const int kRegatherInterval = 2000;
const int kNumRegathers = 2;
// Set up peer 1 to auto regather every 2s.
IceConfig config1 = CreateIceConfig(1000, GATHER_CONTINUALLY);
config1.regather_all_networks_interval_range.emplace(
kRegatherInterval, kRegatherInterval);
IceConfig config2 = CreateIceConfig(1000, GATHER_CONTINUALLY);
// Set peer roles.
SetIceRole(0, p1_role);
SetIceRole(1, p2_role);
CreateChannels(config1, config2);
// Wait for initial connection to be made.
EXPECT_TRUE_SIMULATED_WAIT(ep1_ch1()->receiving() &&
ep1_ch1()->writable() &&
ep2_ch1()->receiving() &&
ep2_ch1()->writable(),
kMediumTimeout, clock);
const Connection* initial_selected = ep1_ch1()->selected_connection();
// Wait long enough for 2 regathering cycles to happen plus some extra so
// the new connection has time to settle.
const int kWaitRegather =
kRegatherInterval * kNumRegathers + kRegatherInterval / 2;
SIMULATED_WAIT(false, kWaitRegather, clock);
EXPECT_EQ(kNumRegathers, GetMetricsObserver(0)->GetEnumCounter(
webrtc::kEnumCounterIceRegathering,
static_cast<int>(IceRegatheringReason::OCCASIONAL_REFRESH)));
const Connection* new_selected = ep1_ch1()->selected_connection();
// Want the new selected connection to be different.
ASSERT_NE(initial_selected, new_selected);
// Make sure we can communicate over the new connection too.
TestSendRecv(clock);
}
};
TEST_F(P2PTransportRegatherAllNetworksTest, TestControlling) {
TestWithRoles(ICEROLE_CONTROLLING, ICEROLE_CONTROLLED);
}
TEST_F(P2PTransportRegatherAllNetworksTest, TestControlled) {
TestWithRoles(ICEROLE_CONTROLLED, ICEROLE_CONTROLLING);
}
// Test that we properly create a connection on a STUN ping from unknown address // Test that we properly create a connection on a STUN ping from unknown address
// when the signaling is slow. // when the signaling is slow.
TEST_F(P2PTransportChannelTest, PeerReflexiveCandidateBeforeSignaling) { TEST_F(P2PTransportChannelTest, PeerReflexiveCandidateBeforeSignaling) {

View File

@ -89,7 +89,12 @@ enum {
}; };
// Defines various reasons that have caused ICE regathering. // Defines various reasons that have caused ICE regathering.
enum class IceRegatheringReason { NETWORK_CHANGE, NETWORK_FAILURE, MAX_VALUE }; enum class IceRegatheringReason {
NETWORK_CHANGE, // Network interfaces on the device changed
NETWORK_FAILURE, // Regather only on networks that have failed
OCCASIONAL_REFRESH, // Periodic regather on all networks
MAX_VALUE
};
const uint32_t kDefaultPortAllocatorFlags = 0; const uint32_t kDefaultPortAllocatorFlags = 0;
@ -238,7 +243,6 @@ class PortAllocatorSession : public sigslot::has_slots<> {
// implementation should start re-gathering on all networks of that interface. // implementation should start re-gathering on all networks of that interface.
virtual void RegatherOnFailedNetworks() {} virtual void RegatherOnFailedNetworks() {}
// Re-gathers candidates on all networks. // Re-gathers candidates on all networks.
// TODO(honghaiz): Implement this in BasicPortAllocator.
virtual void RegatherOnAllNetworks() {} virtual void RegatherOnAllNetworks() {}
// Another way of getting the information provided by the signals below. // Another way of getting the information provided by the signals below.

View File

@ -339,19 +339,43 @@ void BasicPortAllocatorSession::RegatherOnFailedNetworks() {
sequence->set_network_failed(); sequence->set_network_failed();
} }
} }
bool disable_equivalent_phases = true;
Regather(failed_networks, disable_equivalent_phases,
IceRegatheringReason::NETWORK_FAILURE);
}
void BasicPortAllocatorSession::RegatherOnAllNetworks() {
std::vector<rtc::Network*> networks = GetNetworks();
if (networks.empty()) {
return;
}
LOG(LS_INFO) << "Regather candidates on all networks";
// We expect to generate candidates that are equivalent to what we have now.
// Force DoAllocate to generate them instead of skipping.
bool disable_equivalent_phases = false;
Regather(networks, disable_equivalent_phases,
IceRegatheringReason::OCCASIONAL_REFRESH);
}
void BasicPortAllocatorSession::Regather(
const std::vector<rtc::Network*>& networks,
bool disable_equivalent_phases,
IceRegatheringReason reason) {
// Remove ports from being used locally and send signaling to remove // Remove ports from being used locally and send signaling to remove
// the candidates on the remote side. // the candidates on the remote side.
std::vector<PortData*> ports_to_prune = GetUnprunedPorts(failed_networks); std::vector<PortData*> ports_to_prune = GetUnprunedPorts(networks);
if (!ports_to_prune.empty()) { if (!ports_to_prune.empty()) {
LOG(LS_INFO) << "Prune " << ports_to_prune.size() LOG(LS_INFO) << "Prune " << ports_to_prune.size() << " ports";
<< " ports because their networks failed";
PrunePortsAndRemoveCandidates(ports_to_prune); PrunePortsAndRemoveCandidates(ports_to_prune);
} }
if (allocation_started_ && network_manager_started_ && !IsStopped()) { if (allocation_started_ && network_manager_started_ && !IsStopped()) {
SignalIceRegathering(this, IceRegatheringReason::NETWORK_FAILURE); SignalIceRegathering(this, reason);
DoAllocate(); DoAllocate(disable_equivalent_phases);
} }
} }
@ -530,8 +554,10 @@ void BasicPortAllocatorSession::AllocatePorts() {
} }
void BasicPortAllocatorSession::OnAllocate() { void BasicPortAllocatorSession::OnAllocate() {
if (network_manager_started_ && !IsStopped()) if (network_manager_started_ && !IsStopped()) {
DoAllocate(); bool disable_equivalent_phases = true;
DoAllocate(disable_equivalent_phases);
}
allocation_started_ = true; allocation_started_ = true;
} }
@ -586,7 +612,7 @@ std::vector<rtc::Network*> BasicPortAllocatorSession::GetNetworks() {
// For each network, see if we have a sequence that covers it already. If not, // For each network, see if we have a sequence that covers it already. If not,
// create a new sequence to create the appropriate ports. // create a new sequence to create the appropriate ports.
void BasicPortAllocatorSession::DoAllocate() { void BasicPortAllocatorSession::DoAllocate(bool disable_equivalent) {
bool done_signal_needed = false; bool done_signal_needed = false;
std::vector<rtc::Network*> networks = GetNetworks(); std::vector<rtc::Network*> networks = GetNetworks();
if (networks.empty()) { if (networks.empty()) {
@ -622,6 +648,7 @@ void BasicPortAllocatorSession::DoAllocate() {
continue; continue;
} }
if (disable_equivalent) {
// Disable phases that would only create ports equivalent to // Disable phases that would only create ports equivalent to
// ones that we have already made. // ones that we have already made.
DisableEquivalentPhases(networks[i], config, &sequence_flags); DisableEquivalentPhases(networks[i], config, &sequence_flags);
@ -630,6 +657,7 @@ void BasicPortAllocatorSession::DoAllocate() {
// New AllocationSequence would have nothing to do, so don't make it. // New AllocationSequence would have nothing to do, so don't make it.
continue; continue;
} }
}
AllocationSequence* sequence = AllocationSequence* sequence =
new AllocationSequence(this, networks[i], config, sequence_flags); new AllocationSequence(this, networks[i], config, sequence_flags);
@ -671,7 +699,8 @@ void BasicPortAllocatorSession::OnNetworksChanged() {
// If the network manager has started, it must be regathering. // If the network manager has started, it must be regathering.
SignalIceRegathering(this, IceRegatheringReason::NETWORK_CHANGE); SignalIceRegathering(this, IceRegatheringReason::NETWORK_CHANGE);
} }
DoAllocate(); bool disable_equivalent_phases = true;
DoAllocate(disable_equivalent_phases);
} }
if (!network_manager_started_) { if (!network_manager_started_) {

View File

@ -112,6 +112,7 @@ class BasicPortAllocatorSession : public PortAllocatorSession,
std::vector<Candidate> ReadyCandidates() const override; std::vector<Candidate> ReadyCandidates() const override;
bool CandidatesAllocationDone() const override; bool CandidatesAllocationDone() const override;
void RegatherOnFailedNetworks() override; void RegatherOnFailedNetworks() override;
void RegatherOnAllNetworks() override;
void PruneAllPorts() override; void PruneAllPorts() override;
protected: protected:
@ -185,7 +186,7 @@ class BasicPortAllocatorSession : public PortAllocatorSession,
void OnConfigStop(); void OnConfigStop();
void AllocatePorts(); void AllocatePorts();
void OnAllocate(); void OnAllocate();
void DoAllocate(); void DoAllocate(bool disable_equivalent_phases);
void OnNetworksChanged(); void OnNetworksChanged();
void OnAllocationSequenceObjectsCreated(); void OnAllocationSequenceObjectsCreated();
void DisableEquivalentPhases(rtc::Network* network, void DisableEquivalentPhases(rtc::Network* network,
@ -203,6 +204,9 @@ class BasicPortAllocatorSession : public PortAllocatorSession,
PortData* FindPort(Port* port); PortData* FindPort(Port* port);
std::vector<rtc::Network*> GetNetworks(); std::vector<rtc::Network*> GetNetworks();
std::vector<rtc::Network*> GetFailedNetworks(); std::vector<rtc::Network*> GetFailedNetworks();
void Regather(const std::vector<rtc::Network*>& networks,
bool disable_equivalent_phases,
IceRegatheringReason reason);
bool CheckCandidateFilter(const Candidate& c) const; bool CheckCandidateFilter(const Candidate& c) const;
bool CandidatePairable(const Candidate& c, const Port* port) const; bool CandidatePairable(const Candidate& c, const Port* port) const;

View File

@ -223,11 +223,20 @@ namespace webrtc {
bool PeerConnectionInterface::RTCConfiguration::operator==( bool PeerConnectionInterface::RTCConfiguration::operator==(
const PeerConnectionInterface::RTCConfiguration& o) const { const PeerConnectionInterface::RTCConfiguration& o) const {
// This static_assert prevents us from accidentally breaking operator==. // This static_assert prevents us from accidentally breaking operator==.
// Note: Order matters! Fields must be ordered the same as RTCConfiguration.
struct stuff_being_tested_for_equality { struct stuff_being_tested_for_equality {
IceTransportsType type;
IceServers servers; IceServers servers;
IceTransportsType type;
BundlePolicy bundle_policy; BundlePolicy bundle_policy;
RtcpMuxPolicy rtcp_mux_policy; RtcpMuxPolicy rtcp_mux_policy;
std::vector<rtc::scoped_refptr<rtc::RTCCertificate>> certificates;
int ice_candidate_pool_size;
bool disable_ipv6;
bool disable_ipv6_on_wifi;
bool enable_rtp_data_channel;
rtc::Optional<int> screencast_min_bitrate;
rtc::Optional<bool> combined_audio_video_bwe;
rtc::Optional<bool> enable_dtls_srtp;
TcpCandidatePolicy tcp_candidate_policy; TcpCandidatePolicy tcp_candidate_policy;
CandidateNetworkPolicy candidate_network_policy; CandidateNetworkPolicy candidate_network_policy;
int audio_jitter_buffer_max_packets; int audio_jitter_buffer_max_packets;
@ -235,22 +244,15 @@ bool PeerConnectionInterface::RTCConfiguration::operator==(
int ice_connection_receiving_timeout; int ice_connection_receiving_timeout;
int ice_backup_candidate_pair_ping_interval; int ice_backup_candidate_pair_ping_interval;
ContinualGatheringPolicy continual_gathering_policy; ContinualGatheringPolicy continual_gathering_policy;
std::vector<rtc::scoped_refptr<rtc::RTCCertificate>> certificates;
bool prioritize_most_likely_ice_candidate_pairs; bool prioritize_most_likely_ice_candidate_pairs;
struct cricket::MediaConfig media_config; struct cricket::MediaConfig media_config;
bool disable_ipv6;
bool disable_ipv6_on_wifi;
bool enable_rtp_data_channel;
bool enable_quic; bool enable_quic;
rtc::Optional<int> screencast_min_bitrate;
rtc::Optional<bool> combined_audio_video_bwe;
rtc::Optional<bool> enable_dtls_srtp;
int ice_candidate_pool_size;
bool prune_turn_ports; bool prune_turn_ports;
bool presume_writable_when_fully_relayed; bool presume_writable_when_fully_relayed;
bool enable_ice_renomination; bool enable_ice_renomination;
bool redetermine_role_on_ice_restart; bool redetermine_role_on_ice_restart;
rtc::Optional<int> ice_check_min_interval; rtc::Optional<int> ice_check_min_interval;
rtc::Optional<rtc::IntervalRange> ice_regather_interval_range;
}; };
static_assert(sizeof(stuff_being_tested_for_equality) == sizeof(*this), static_assert(sizeof(stuff_being_tested_for_equality) == sizeof(*this),
"Did you add something to RTCConfiguration and forget to " "Did you add something to RTCConfiguration and forget to "
@ -284,7 +286,8 @@ bool PeerConnectionInterface::RTCConfiguration::operator==(
o.presume_writable_when_fully_relayed && o.presume_writable_when_fully_relayed &&
enable_ice_renomination == o.enable_ice_renomination && enable_ice_renomination == o.enable_ice_renomination &&
redetermine_role_on_ice_restart == o.redetermine_role_on_ice_restart && redetermine_role_on_ice_restart == o.redetermine_role_on_ice_restart &&
ice_check_min_interval == o.ice_check_min_interval; ice_check_min_interval == o.ice_check_min_interval &&
ice_regather_interval_range == o.ice_regather_interval_range;
} }
bool PeerConnectionInterface::RTCConfiguration::operator!=( bool PeerConnectionInterface::RTCConfiguration::operator!=(

View File

@ -1222,6 +1222,8 @@ cricket::IceConfig WebRtcSession::ParseIceConfig(
ice_config.presume_writable_when_fully_relayed = ice_config.presume_writable_when_fully_relayed =
config.presume_writable_when_fully_relayed; config.presume_writable_when_fully_relayed;
ice_config.ice_check_min_interval = config.ice_check_min_interval; ice_config.ice_check_min_interval = config.ice_check_min_interval;
ice_config.regather_all_networks_interval_range =
config.ice_regather_interval_range;
return ice_config; return ice_config;
} }

View File

@ -15,6 +15,9 @@
#include <time.h> #include <time.h>
#include <ctime> #include <ctime>
#include <string>
#include "webrtc/rtc_base/checks.h"
namespace rtc { namespace rtc {
@ -124,6 +127,32 @@ int64_t TmToSeconds(const std::tm& tm);
// measuring time intervals and timeouts. // measuring time intervals and timeouts.
int64_t TimeUTCMicros(); int64_t TimeUTCMicros();
// Interval of time from the range [min, max] inclusive.
class IntervalRange {
public:
IntervalRange() : min_(0), max_(0) {}
IntervalRange(int min, int max) : min_(min), max_(max) {
RTC_DCHECK_LE(min, max);
}
int min() const { return min_; }
int max() const { return max_; }
std::string ToString() const {
std::stringstream ss;
ss << "[" << min_ << "," << max_ << "]";
return ss.str();
}
bool operator==(const IntervalRange& o) const {
return min_ == o.min_ && max_ == o.max_;
}
private:
int min_;
int max_;
};
} // namespace rtc } // namespace rtc
#endif // WEBRTC_RTC_BASE_TIMEUTILS_H_ #endif // WEBRTC_RTC_BASE_TIMEUTILS_H_