From aa41f0cfa64ece911ae2ecee83fc3190d4a42935 Mon Sep 17 00:00:00 2001 From: Steve Anton Date: Tue, 11 Jul 2017 14:38:29 -0700 Subject: [PATCH] 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 Cr-Commit-Position: refs/heads/master@{#18978} --- webrtc/api/peerconnectioninterface.h | 7 ++ webrtc/p2p/base/jseptransport.h | 4 + webrtc/p2p/base/p2ptransportchannel.cc | 72 ++++++++++++- webrtc/p2p/base/p2ptransportchannel.h | 15 +++ .../p2p/base/p2ptransportchannel_unittest.cc | 100 ++++++++++++++++++ webrtc/p2p/base/portallocator.h | 8 +- webrtc/p2p/client/basicportallocator.cc | 59 ++++++++--- webrtc/p2p/client/basicportallocator.h | 6 +- webrtc/pc/peerconnection.cc | 23 ++-- webrtc/pc/webrtcsession.cc | 2 + webrtc/rtc_base/timeutils.h | 29 +++++ 11 files changed, 294 insertions(+), 31 deletions(-) diff --git a/webrtc/api/peerconnectioninterface.h b/webrtc/api/peerconnectioninterface.h index d6cabf4595..6649f2ab99 100644 --- a/webrtc/api/peerconnectioninterface.h +++ b/webrtc/api/peerconnectioninterface.h @@ -453,6 +453,13 @@ class PeerConnectionInterface : public rtc::RefCountInterface { // (STUN pings), in milliseconds. rtc::Optional 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 ice_regather_interval_range; + // // Don't forget to update operator== if adding something. // diff --git a/webrtc/p2p/base/jseptransport.h b/webrtc/p2p/base/jseptransport.h index 9353cd7d07..aee07180c1 100644 --- a/webrtc/p2p/base/jseptransport.h +++ b/webrtc/p2p/base/jseptransport.h @@ -184,6 +184,10 @@ struct IceConfig { // active network having no connection on it. rtc::Optional 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 regather_all_networks_interval_range; + // The time period in which we will not switch the selected connection // when a new connection becomes receiving but the selected connection is not // in case that the selected connection may become receiving soon. diff --git a/webrtc/p2p/base/p2ptransportchannel.cc b/webrtc/p2p/base/p2ptransportchannel.cc index 78b4c938d4..2c9ee13765 100644 --- a/webrtc/p2p/base/p2ptransportchannel.cc +++ b/webrtc/p2p/base/p2ptransportchannel.cc @@ -12,6 +12,7 @@ #include #include +#include #include #include "webrtc/api/umametrics.h" @@ -32,7 +33,8 @@ namespace { enum { MSG_SORT_AND_UPDATE_STATE = 1, 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. @@ -111,6 +113,7 @@ P2PTransportChannel::P2PTransportChannel(const std::string& transport_name, ice_role_(ICEROLE_UNKNOWN), tiebreaker_(0), gathering_state_(kIceGatheringNew), + rand_(std::random_device()()), check_receiving_interval_(MIN_CHECK_RECEIVING_INTERVAL * 5), config_(MIN_CHECK_RECEIVING_INTERVAL * 50 /* receiving_timeout */, 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 " << *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) { config_.receiving_switching_delay = config.receiving_switching_delay; LOG(LS_INFO) << "Set receiving_switching_delay to" @@ -1077,6 +1088,11 @@ void P2PTransportChannel::MaybeStartPinging() { thread()->PostDelayed(RTC_FROM_HERE, *config_.regather_on_failed_networks_interval, this, 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; } } @@ -1182,8 +1198,39 @@ int P2PTransportChannel::CompareConnectionCandidates( // If we're still tied at this point, prefer a younger generation. // (Younger generation means a larger generation number). - return (a->remote_candidate().generation() + a->port()->generation()) - - (b->remote_candidate().generation() + b->port()->generation()); + int cmp = (a->remote_candidate().generation() + a->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( @@ -1528,6 +1575,9 @@ void P2PTransportChannel::OnMessage(rtc::Message *pmsg) { case MSG_REGATHER_ON_FAILED_NETWORKS: OnRegatherOnFailedNetworks(); break; + case MSG_REGATHER_ON_ALL_NETWORKS: + OnRegatherOnAllNetworks(); + break; default: RTC_NOTREACHED(); break; @@ -1913,6 +1963,16 @@ void P2PTransportChannel::OnRegatherOnFailedNetworks() { 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() { pruned_ports_.insert(pruned_ports_.end(), ports_.begin(), ports_.end()); ports_.clear(); @@ -2066,4 +2126,10 @@ 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()); +} + } // namespace cricket diff --git a/webrtc/p2p/base/p2ptransportchannel.h b/webrtc/p2p/base/p2ptransportchannel.h index beca558eae..d2461dec3d 100644 --- a/webrtc/p2p/base/p2ptransportchannel.h +++ b/webrtc/p2p/base/p2ptransportchannel.h @@ -33,6 +33,7 @@ #include "webrtc/p2p/base/portinterface.h" #include "webrtc/rtc_base/asyncpacketsocket.h" #include "webrtc/rtc_base/constructormagic.h" +#include "webrtc/rtc_base/random.h" #include "webrtc/rtc_base/sigslot.h" namespace cricket { @@ -280,6 +281,7 @@ class P2PTransportChannel : public IceTransportInternal, void OnMessage(rtc::Message* pmsg) override; void OnCheckAndPing(); void OnRegatherOnFailedNetworks(); + void OnRegatherOnAllNetworks(); uint32_t GetNominationAttr(Connection* conn) const; bool GetUseCandidateAttr(Connection* conn, NominationMode mode) const; @@ -328,6 +330,16 @@ class P2PTransportChannel : public IceTransportInternal, : static_cast(remote_ice_parameters_.size() - 1); } + // Samples a delay from the uniform distribution defined by the + // regather_on_all_networks_interval ICE configuration pair. + int SampleRegatherAllNetworksInterval(); + + // Indicates if the given local port has been pruned. + bool IsPortPruned(const Port* port) const; + + // Indicates if the given remote candidate has been pruned. + bool IsRemoteCandidatePruned(const Candidate& cand) const; + // Sets the writable state, signaling if necessary. void set_writable(bool writable); // Sets the receiving state, signaling if necessary. @@ -372,6 +384,9 @@ class P2PTransportChannel : public IceTransportInternal, uint64_t tiebreaker_; IceGatheringState gathering_state_; + // Used to generate random intervals for regather_all_networks_interval_range. + webrtc::Random rand_; + int check_receiving_interval_; int64_t last_ping_sent_ms_ = 0; int weak_ping_interval_ = WEAK_PING_INTERVAL; diff --git a/webrtc/p2p/base/p2ptransportchannel_unittest.cc b/webrtc/p2p/base/p2ptransportchannel_unittest.cc index 7b3fa6aafe..c37b818091 100644 --- a/webrtc/p2p/base/p2ptransportchannel_unittest.cc +++ b/webrtc/p2p/base/p2ptransportchannel_unittest.cc @@ -1362,6 +1362,106 @@ TEST_F(P2PTransportChannelTest, 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(IceRegatheringReason::OCCASIONAL_REFRESH))); + // Expect no regathering if continual gathering not configured. + EXPECT_EQ(0, GetMetricsObserver(1)->GetEnumCounter( + webrtc::kEnumCounterIceRegathering, + static_cast(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(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 // when the signaling is slow. TEST_F(P2PTransportChannelTest, PeerReflexiveCandidateBeforeSignaling) { diff --git a/webrtc/p2p/base/portallocator.h b/webrtc/p2p/base/portallocator.h index 74b67afd9c..9540e40d74 100644 --- a/webrtc/p2p/base/portallocator.h +++ b/webrtc/p2p/base/portallocator.h @@ -89,7 +89,12 @@ enum { }; // 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; @@ -238,7 +243,6 @@ class PortAllocatorSession : public sigslot::has_slots<> { // implementation should start re-gathering on all networks of that interface. virtual void RegatherOnFailedNetworks() {} // Re-gathers candidates on all networks. - // TODO(honghaiz): Implement this in BasicPortAllocator. virtual void RegatherOnAllNetworks() {} // Another way of getting the information provided by the signals below. diff --git a/webrtc/p2p/client/basicportallocator.cc b/webrtc/p2p/client/basicportallocator.cc index 5ddc475493..2970987900 100644 --- a/webrtc/p2p/client/basicportallocator.cc +++ b/webrtc/p2p/client/basicportallocator.cc @@ -339,19 +339,43 @@ void BasicPortAllocatorSession::RegatherOnFailedNetworks() { sequence->set_network_failed(); } } + + bool disable_equivalent_phases = true; + Regather(failed_networks, disable_equivalent_phases, + IceRegatheringReason::NETWORK_FAILURE); +} + +void BasicPortAllocatorSession::RegatherOnAllNetworks() { + std::vector 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& networks, + bool disable_equivalent_phases, + IceRegatheringReason reason) { // Remove ports from being used locally and send signaling to remove // the candidates on the remote side. - std::vector ports_to_prune = GetUnprunedPorts(failed_networks); + std::vector ports_to_prune = GetUnprunedPorts(networks); if (!ports_to_prune.empty()) { - LOG(LS_INFO) << "Prune " << ports_to_prune.size() - << " ports because their networks failed"; + LOG(LS_INFO) << "Prune " << ports_to_prune.size() << " ports"; PrunePortsAndRemoveCandidates(ports_to_prune); } 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() { - if (network_manager_started_ && !IsStopped()) - DoAllocate(); + if (network_manager_started_ && !IsStopped()) { + bool disable_equivalent_phases = true; + DoAllocate(disable_equivalent_phases); + } allocation_started_ = true; } @@ -586,7 +612,7 @@ std::vector BasicPortAllocatorSession::GetNetworks() { // For each network, see if we have a sequence that covers it already. If not, // create a new sequence to create the appropriate ports. -void BasicPortAllocatorSession::DoAllocate() { +void BasicPortAllocatorSession::DoAllocate(bool disable_equivalent) { bool done_signal_needed = false; std::vector networks = GetNetworks(); if (networks.empty()) { @@ -622,13 +648,15 @@ void BasicPortAllocatorSession::DoAllocate() { continue; } - // Disable phases that would only create ports equivalent to - // ones that we have already made. - DisableEquivalentPhases(networks[i], config, &sequence_flags); + if (disable_equivalent) { + // Disable phases that would only create ports equivalent to + // ones that we have already made. + DisableEquivalentPhases(networks[i], config, &sequence_flags); - if ((sequence_flags & DISABLE_ALL_PHASES) == DISABLE_ALL_PHASES) { - // New AllocationSequence would have nothing to do, so don't make it. - continue; + if ((sequence_flags & DISABLE_ALL_PHASES) == DISABLE_ALL_PHASES) { + // New AllocationSequence would have nothing to do, so don't make it. + continue; + } } AllocationSequence* sequence = @@ -671,7 +699,8 @@ void BasicPortAllocatorSession::OnNetworksChanged() { // If the network manager has started, it must be regathering. SignalIceRegathering(this, IceRegatheringReason::NETWORK_CHANGE); } - DoAllocate(); + bool disable_equivalent_phases = true; + DoAllocate(disable_equivalent_phases); } if (!network_manager_started_) { diff --git a/webrtc/p2p/client/basicportallocator.h b/webrtc/p2p/client/basicportallocator.h index 7cdf0baa7d..a991417736 100644 --- a/webrtc/p2p/client/basicportallocator.h +++ b/webrtc/p2p/client/basicportallocator.h @@ -112,6 +112,7 @@ class BasicPortAllocatorSession : public PortAllocatorSession, std::vector ReadyCandidates() const override; bool CandidatesAllocationDone() const override; void RegatherOnFailedNetworks() override; + void RegatherOnAllNetworks() override; void PruneAllPorts() override; protected: @@ -185,7 +186,7 @@ class BasicPortAllocatorSession : public PortAllocatorSession, void OnConfigStop(); void AllocatePorts(); void OnAllocate(); - void DoAllocate(); + void DoAllocate(bool disable_equivalent_phases); void OnNetworksChanged(); void OnAllocationSequenceObjectsCreated(); void DisableEquivalentPhases(rtc::Network* network, @@ -203,6 +204,9 @@ class BasicPortAllocatorSession : public PortAllocatorSession, PortData* FindPort(Port* port); std::vector GetNetworks(); std::vector GetFailedNetworks(); + void Regather(const std::vector& networks, + bool disable_equivalent_phases, + IceRegatheringReason reason); bool CheckCandidateFilter(const Candidate& c) const; bool CandidatePairable(const Candidate& c, const Port* port) const; diff --git a/webrtc/pc/peerconnection.cc b/webrtc/pc/peerconnection.cc index a947c301a1..42664b04ef 100644 --- a/webrtc/pc/peerconnection.cc +++ b/webrtc/pc/peerconnection.cc @@ -223,11 +223,20 @@ namespace webrtc { bool PeerConnectionInterface::RTCConfiguration::operator==( const PeerConnectionInterface::RTCConfiguration& o) const { // 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 { - IceTransportsType type; IceServers servers; + IceTransportsType type; BundlePolicy bundle_policy; RtcpMuxPolicy rtcp_mux_policy; + std::vector> certificates; + int ice_candidate_pool_size; + bool disable_ipv6; + bool disable_ipv6_on_wifi; + bool enable_rtp_data_channel; + rtc::Optional screencast_min_bitrate; + rtc::Optional combined_audio_video_bwe; + rtc::Optional enable_dtls_srtp; TcpCandidatePolicy tcp_candidate_policy; CandidateNetworkPolicy candidate_network_policy; int audio_jitter_buffer_max_packets; @@ -235,22 +244,15 @@ bool PeerConnectionInterface::RTCConfiguration::operator==( int ice_connection_receiving_timeout; int ice_backup_candidate_pair_ping_interval; ContinualGatheringPolicy continual_gathering_policy; - std::vector> certificates; bool prioritize_most_likely_ice_candidate_pairs; struct cricket::MediaConfig media_config; - bool disable_ipv6; - bool disable_ipv6_on_wifi; - bool enable_rtp_data_channel; bool enable_quic; - rtc::Optional screencast_min_bitrate; - rtc::Optional combined_audio_video_bwe; - rtc::Optional enable_dtls_srtp; - int ice_candidate_pool_size; bool prune_turn_ports; bool presume_writable_when_fully_relayed; bool enable_ice_renomination; bool redetermine_role_on_ice_restart; rtc::Optional ice_check_min_interval; + rtc::Optional ice_regather_interval_range; }; static_assert(sizeof(stuff_being_tested_for_equality) == sizeof(*this), "Did you add something to RTCConfiguration and forget to " @@ -284,7 +286,8 @@ bool PeerConnectionInterface::RTCConfiguration::operator==( o.presume_writable_when_fully_relayed && enable_ice_renomination == o.enable_ice_renomination && 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!=( diff --git a/webrtc/pc/webrtcsession.cc b/webrtc/pc/webrtcsession.cc index 4ca4528e74..b4b30a0813 100644 --- a/webrtc/pc/webrtcsession.cc +++ b/webrtc/pc/webrtcsession.cc @@ -1222,6 +1222,8 @@ cricket::IceConfig WebRtcSession::ParseIceConfig( ice_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.regather_all_networks_interval_range = + config.ice_regather_interval_range; return ice_config; } diff --git a/webrtc/rtc_base/timeutils.h b/webrtc/rtc_base/timeutils.h index ea7b17d744..c7f035cdb8 100644 --- a/webrtc/rtc_base/timeutils.h +++ b/webrtc/rtc_base/timeutils.h @@ -15,6 +15,9 @@ #include #include +#include + +#include "webrtc/rtc_base/checks.h" namespace rtc { @@ -124,6 +127,32 @@ int64_t TmToSeconds(const std::tm& tm); // measuring time intervals and timeouts. 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 #endif // WEBRTC_RTC_BASE_TIMEUTILS_H_