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:
parent
f1f9889c44
commit
aa41f0cfa6
@ -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.
|
||||||
//
|
//
|
||||||
|
|||||||
@ -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.
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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) {
|
||||||
|
|||||||
@ -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.
|
||||||
|
|||||||
@ -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,13 +648,15 @@ void BasicPortAllocatorSession::DoAllocate() {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disable phases that would only create ports equivalent to
|
if (disable_equivalent) {
|
||||||
// ones that we have already made.
|
// Disable phases that would only create ports equivalent to
|
||||||
DisableEquivalentPhases(networks[i], config, &sequence_flags);
|
// ones that we have already made.
|
||||||
|
DisableEquivalentPhases(networks[i], config, &sequence_flags);
|
||||||
|
|
||||||
if ((sequence_flags & DISABLE_ALL_PHASES) == DISABLE_ALL_PHASES) {
|
if ((sequence_flags & DISABLE_ALL_PHASES) == DISABLE_ALL_PHASES) {
|
||||||
// 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 =
|
||||||
@ -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_) {
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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!=(
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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_
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user