Add UMA metrics for ICE regathering reasons.
BUG=webrtc:6462 R=deadbeef@webrtc.org Review URL: https://codereview.webrtc.org/2386783002 . Cr-Commit-Position: refs/heads/master@{#14531}
This commit is contained in:
@ -337,6 +337,7 @@ if (rtc_include_tests) {
|
|||||||
rtc_test("rtc_unittests") {
|
rtc_test("rtc_unittests") {
|
||||||
testonly = true
|
testonly = true
|
||||||
sources = [
|
sources = [
|
||||||
|
"api/fakemetricsobserver.cc",
|
||||||
"base/array_view_unittest.cc",
|
"base/array_view_unittest.cc",
|
||||||
"base/atomicops_unittest.cc",
|
"base/atomicops_unittest.cc",
|
||||||
"base/autodetectproxy_unittest.cc",
|
"base/autodetectproxy_unittest.cc",
|
||||||
|
@ -45,7 +45,9 @@ void FakeMetricsObserver::AddHistogramSample(PeerConnectionMetricsName type,
|
|||||||
int FakeMetricsObserver::GetEnumCounter(PeerConnectionEnumCounterType type,
|
int FakeMetricsObserver::GetEnumCounter(PeerConnectionEnumCounterType type,
|
||||||
int counter) const {
|
int counter) const {
|
||||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||||
RTC_CHECK(counters_.size() > static_cast<size_t>(type));
|
if (counters_.size() <= static_cast<size_t>(type)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
const auto& it = counters_[type].find(counter);
|
const auto& it = counters_[type].find(counter);
|
||||||
if (it == counters_[type].end()) {
|
if (it == counters_[type].end()) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1300,6 +1300,7 @@ void PeerConnection::RegisterUMAObserver(UMAObserver* observer) {
|
|||||||
|
|
||||||
// Send information about IPv4/IPv6 status.
|
// Send information about IPv4/IPv6 status.
|
||||||
if (uma_observer_ && port_allocator_) {
|
if (uma_observer_ && port_allocator_) {
|
||||||
|
port_allocator_->SetMetricsObserver(uma_observer_);
|
||||||
if (port_allocator_->flags() & cricket::PORTALLOCATOR_ENABLE_IPV6) {
|
if (port_allocator_->flags() & cricket::PORTALLOCATOR_ENABLE_IPV6) {
|
||||||
uma_observer_->IncrementEnumCounter(
|
uma_observer_->IncrementEnumCounter(
|
||||||
kEnumCounterAddressFamily, kPeerConnection_IPv6,
|
kEnumCounterAddressFamily, kPeerConnection_IPv6,
|
||||||
|
@ -33,6 +33,8 @@ enum PeerConnectionEnumCounterType {
|
|||||||
kEnumCounterDataSrtpCipher,
|
kEnumCounterDataSrtpCipher,
|
||||||
kEnumCounterDataSslCipher,
|
kEnumCounterDataSslCipher,
|
||||||
kEnumCounterDtlsHandshakeError,
|
kEnumCounterDtlsHandshakeError,
|
||||||
|
kEnumCounterIceRegathering,
|
||||||
|
kEnumCounterIceRestart,
|
||||||
kPeerConnectionEnumCounterMax
|
kPeerConnectionEnumCounterMax
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -293,6 +293,7 @@ class WebRtcSession :
|
|||||||
void set_metrics_observer(
|
void set_metrics_observer(
|
||||||
webrtc::MetricsObserverInterface* metrics_observer) {
|
webrtc::MetricsObserverInterface* metrics_observer) {
|
||||||
metrics_observer_ = metrics_observer;
|
metrics_observer_ = metrics_observer;
|
||||||
|
transport_controller_->SetMetricsObserver(metrics_observer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called when voice_channel_, video_channel_ and data_channel_ are created
|
// Called when voice_channel_, video_channel_ and data_channel_ are created
|
||||||
|
@ -186,6 +186,10 @@ class DtlsTransportChannelWrapper : public TransportChannelImpl {
|
|||||||
channel_->RemoveRemoteCandidate(candidate);
|
channel_->RemoveRemoteCandidate(candidate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetMetricsObserver(webrtc::MetricsObserverInterface* observer) override {
|
||||||
|
channel_->SetMetricsObserver(observer);
|
||||||
|
}
|
||||||
|
|
||||||
void SetIceConfig(const IceConfig& config) override {
|
void SetIceConfig(const IceConfig& config) override {
|
||||||
channel_->SetIceConfig(config);
|
channel_->SetIceConfig(config);
|
||||||
}
|
}
|
||||||
|
@ -299,6 +299,9 @@ class FakeTransportChannel : public TransportChannelImpl,
|
|||||||
return ssl_max_version_;
|
return ssl_max_version_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetMetricsObserver(webrtc::MetricsObserverInterface* observer) override {
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void NegotiateSrtpCiphers() {
|
void NegotiateSrtpCiphers() {
|
||||||
for (std::vector<int>::const_iterator it1 = srtp_ciphers_.begin();
|
for (std::vector<int>::const_iterator it1 = srtp_ciphers_.begin();
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
|
#include "webrtc/api/peerconnectioninterface.h"
|
||||||
#include "webrtc/base/common.h"
|
#include "webrtc/base/common.h"
|
||||||
#include "webrtc/base/crc32.h"
|
#include "webrtc/base/crc32.h"
|
||||||
#include "webrtc/base/logging.h"
|
#include "webrtc/base/logging.h"
|
||||||
@ -435,6 +436,11 @@ const IceConfig& P2PTransportChannel::config() const {
|
|||||||
return config_;
|
return config_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void P2PTransportChannel::SetMetricsObserver(
|
||||||
|
webrtc::MetricsObserverInterface* observer) {
|
||||||
|
metrics_observer_ = observer;
|
||||||
|
}
|
||||||
|
|
||||||
void P2PTransportChannel::MaybeStartGathering() {
|
void P2PTransportChannel::MaybeStartGathering() {
|
||||||
if (ice_parameters_.ufrag.empty() || ice_parameters_.pwd.empty()) {
|
if (ice_parameters_.ufrag.empty() || ice_parameters_.pwd.empty()) {
|
||||||
LOG(LS_ERROR) << "Cannot gather candidates because ICE parameters are empty"
|
LOG(LS_ERROR) << "Cannot gather candidates because ICE parameters are empty"
|
||||||
@ -451,6 +457,21 @@ void P2PTransportChannel::MaybeStartGathering() {
|
|||||||
gathering_state_ = kIceGatheringGathering;
|
gathering_state_ = kIceGatheringGathering;
|
||||||
SignalGatheringState(this);
|
SignalGatheringState(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (metrics_observer_ && !allocator_sessions_.empty()) {
|
||||||
|
IceRestartState state;
|
||||||
|
if (writable()) {
|
||||||
|
state = IceRestartState::CONNECTED;
|
||||||
|
} else if (IsGettingPorts()) {
|
||||||
|
state = IceRestartState::CONNECTING;
|
||||||
|
} else {
|
||||||
|
state = IceRestartState::DISCONNECTED;
|
||||||
|
}
|
||||||
|
metrics_observer_->IncrementEnumCounter(
|
||||||
|
webrtc::kEnumCounterIceRestart, static_cast<int>(state),
|
||||||
|
static_cast<int>(IceRestartState::MAX_VALUE));
|
||||||
|
}
|
||||||
|
|
||||||
// Time for a new allocator.
|
// Time for a new allocator.
|
||||||
std::unique_ptr<PortAllocatorSession> pooled_session =
|
std::unique_ptr<PortAllocatorSession> pooled_session =
|
||||||
allocator_->TakePooledSession(transport_name(), component(),
|
allocator_->TakePooledSession(transport_name(), component(),
|
||||||
@ -473,7 +494,6 @@ void P2PTransportChannel::MaybeStartGathering() {
|
|||||||
AddAllocatorSession(allocator_->CreateSession(
|
AddAllocatorSession(allocator_->CreateSession(
|
||||||
transport_name(), component(), ice_parameters_.ufrag,
|
transport_name(), component(), ice_parameters_.ufrag,
|
||||||
ice_parameters_.pwd));
|
ice_parameters_.pwd));
|
||||||
LOG(LS_INFO) << "Start getting ports";
|
|
||||||
allocator_sessions_.back()->StartGettingPorts();
|
allocator_sessions_.back()->StartGettingPorts();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,10 @@
|
|||||||
|
|
||||||
namespace cricket {
|
namespace cricket {
|
||||||
|
|
||||||
|
// Enum for UMA metrics, used to record whether the channel is
|
||||||
|
// connected/connecting/disconnected when ICE restart happens.
|
||||||
|
enum class IceRestartState { CONNECTING, CONNECTED, DISCONNECTED, MAX_VALUE };
|
||||||
|
|
||||||
extern const int WEAK_PING_INTERVAL;
|
extern const int WEAK_PING_INTERVAL;
|
||||||
extern const int STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL;
|
extern const int STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL;
|
||||||
extern const int STABLE_WRITABLE_CONNECTION_PING_INTERVAL;
|
extern const int STABLE_WRITABLE_CONNECTION_PING_INTERVAL;
|
||||||
@ -95,6 +99,7 @@ class P2PTransportChannel : public TransportChannelImpl,
|
|||||||
// TODO(deadbeef): Use rtc::Optional instead of negative values.
|
// TODO(deadbeef): Use rtc::Optional instead of negative values.
|
||||||
void SetIceConfig(const IceConfig& config) override;
|
void SetIceConfig(const IceConfig& config) override;
|
||||||
const IceConfig& config() const;
|
const IceConfig& config() const;
|
||||||
|
void SetMetricsObserver(webrtc::MetricsObserverInterface* observer) override;
|
||||||
|
|
||||||
// From TransportChannel:
|
// From TransportChannel:
|
||||||
int SendPacket(const char* data,
|
int SendPacket(const char* data,
|
||||||
@ -394,6 +399,8 @@ class P2PTransportChannel : public TransportChannelImpl,
|
|||||||
// connection. A zero-value indicates the connection will not be nominated.
|
// connection. A zero-value indicates the connection will not be nominated.
|
||||||
uint32_t nomination_ = 0;
|
uint32_t nomination_ = 0;
|
||||||
|
|
||||||
|
webrtc::MetricsObserverInterface* metrics_observer_ = nullptr;
|
||||||
|
|
||||||
RTC_DISALLOW_COPY_AND_ASSIGN(P2PTransportChannel);
|
RTC_DISALLOW_COPY_AND_ASSIGN(P2PTransportChannel);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
#include "webrtc/api/fakemetricsobserver.h"
|
||||||
#include "webrtc/p2p/base/fakeportallocator.h"
|
#include "webrtc/p2p/base/fakeportallocator.h"
|
||||||
#include "webrtc/p2p/base/p2ptransportchannel.h"
|
#include "webrtc/p2p/base/p2ptransportchannel.h"
|
||||||
#include "webrtc/p2p/base/testrelayserver.h"
|
#include "webrtc/p2p/base/testrelayserver.h"
|
||||||
@ -198,9 +199,15 @@ class P2PTransportChannelTestBase : public testing::Test,
|
|||||||
ep1_.allocator_.reset(
|
ep1_.allocator_.reset(
|
||||||
CreateBasicPortAllocator(&ep1_.network_manager_, stun_servers,
|
CreateBasicPortAllocator(&ep1_.network_manager_, stun_servers,
|
||||||
kTurnUdpIntAddr, rtc::SocketAddress()));
|
kTurnUdpIntAddr, rtc::SocketAddress()));
|
||||||
|
ep1_.metrics_observer_ =
|
||||||
|
new rtc::RefCountedObject<webrtc::FakeMetricsObserver>();
|
||||||
|
ep1_.allocator_->SetMetricsObserver(ep1_.metrics_observer_);
|
||||||
ep2_.allocator_.reset(
|
ep2_.allocator_.reset(
|
||||||
CreateBasicPortAllocator(&ep2_.network_manager_, stun_servers,
|
CreateBasicPortAllocator(&ep2_.network_manager_, stun_servers,
|
||||||
kTurnUdpIntAddr, rtc::SocketAddress()));
|
kTurnUdpIntAddr, rtc::SocketAddress()));
|
||||||
|
ep2_.metrics_observer_ =
|
||||||
|
new rtc::RefCountedObject<webrtc::FakeMetricsObserver>();
|
||||||
|
ep2_.allocator_->SetMetricsObserver(ep2_.metrics_observer_);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -298,6 +305,9 @@ class P2PTransportChannelTestBase : public testing::Test,
|
|||||||
}
|
}
|
||||||
|
|
||||||
rtc::FakeNetworkManager network_manager_;
|
rtc::FakeNetworkManager network_manager_;
|
||||||
|
// |metrics_observer_| should outlive |allocator_| as the former may be
|
||||||
|
// used by the latter.
|
||||||
|
rtc::scoped_refptr<webrtc::FakeMetricsObserver> metrics_observer_;
|
||||||
std::unique_ptr<BasicPortAllocator> allocator_;
|
std::unique_ptr<BasicPortAllocator> allocator_;
|
||||||
ChannelData cd1_;
|
ChannelData cd1_;
|
||||||
ChannelData cd2_;
|
ChannelData cd2_;
|
||||||
@ -334,6 +344,8 @@ class P2PTransportChannelTestBase : public testing::Test,
|
|||||||
ice_ep1_cd1_ch, ice_ep2_cd1_ch));
|
ice_ep1_cd1_ch, ice_ep2_cd1_ch));
|
||||||
ep2_.cd1_.ch_.reset(CreateChannel(1, ICE_CANDIDATE_COMPONENT_DEFAULT,
|
ep2_.cd1_.ch_.reset(CreateChannel(1, ICE_CANDIDATE_COMPONENT_DEFAULT,
|
||||||
ice_ep2_cd1_ch, ice_ep1_cd1_ch));
|
ice_ep2_cd1_ch, ice_ep1_cd1_ch));
|
||||||
|
ep1_.cd1_.ch_->SetMetricsObserver(ep1_.metrics_observer_);
|
||||||
|
ep2_.cd1_.ch_->SetMetricsObserver(ep2_.metrics_observer_);
|
||||||
ep1_.cd1_.ch_->SetIceConfig(ep1_config);
|
ep1_.cd1_.ch_->SetIceConfig(ep1_config);
|
||||||
ep2_.cd1_.ch_->SetIceConfig(ep2_config);
|
ep2_.cd1_.ch_->SetIceConfig(ep2_config);
|
||||||
ep1_.cd1_.ch_->MaybeStartGathering();
|
ep1_.cd1_.ch_->MaybeStartGathering();
|
||||||
@ -416,6 +428,9 @@ class P2PTransportChannelTestBase : public testing::Test,
|
|||||||
PortAllocator* GetAllocator(int endpoint) {
|
PortAllocator* GetAllocator(int endpoint) {
|
||||||
return GetEndpoint(endpoint)->allocator_.get();
|
return GetEndpoint(endpoint)->allocator_.get();
|
||||||
}
|
}
|
||||||
|
webrtc::FakeMetricsObserver* GetMetricsObserver(int endpoint) {
|
||||||
|
return GetEndpoint(endpoint)->metrics_observer_;
|
||||||
|
}
|
||||||
void AddAddress(int endpoint, const SocketAddress& addr) {
|
void AddAddress(int endpoint, const SocketAddress& addr) {
|
||||||
GetEndpoint(endpoint)->network_manager_.AddInterface(addr);
|
GetEndpoint(endpoint)->network_manager_.AddInterface(addr);
|
||||||
}
|
}
|
||||||
@ -958,13 +973,12 @@ class P2PTransportChannelTest : public P2PTransportChannelTestBase {
|
|||||||
Config config2,
|
Config config2,
|
||||||
int allocator_flags1,
|
int allocator_flags1,
|
||||||
int allocator_flags2) {
|
int allocator_flags2) {
|
||||||
int delay = kMinimumStepDelay;
|
|
||||||
ConfigureEndpoint(0, config1);
|
ConfigureEndpoint(0, config1);
|
||||||
SetAllocatorFlags(0, allocator_flags1);
|
SetAllocatorFlags(0, allocator_flags1);
|
||||||
SetAllocationStepDelay(0, delay);
|
SetAllocationStepDelay(0, kMinimumStepDelay);
|
||||||
ConfigureEndpoint(1, config2);
|
ConfigureEndpoint(1, config2);
|
||||||
SetAllocatorFlags(1, allocator_flags2);
|
SetAllocatorFlags(1, allocator_flags2);
|
||||||
SetAllocationStepDelay(1, delay);
|
SetAllocationStepDelay(1, kMinimumStepDelay);
|
||||||
|
|
||||||
set_remote_ice_parameter_source(FROM_SETICEPARAMETERS);
|
set_remote_ice_parameter_source(FROM_SETICEPARAMETERS);
|
||||||
}
|
}
|
||||||
@ -1172,6 +1186,169 @@ TEST_F(P2PTransportChannelTest, GetStats) {
|
|||||||
DestroyChannels();
|
DestroyChannels();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tests that UMAs are recorded when ICE restarts while the channel
|
||||||
|
// is disconnected.
|
||||||
|
TEST_F(P2PTransportChannelTest, TestUMAIceRestartWhileDisconnected) {
|
||||||
|
rtc::ScopedFakeClock clock;
|
||||||
|
ConfigureEndpoints(OPEN, OPEN, kOnlyLocalPorts, kOnlyLocalPorts);
|
||||||
|
|
||||||
|
CreateChannels();
|
||||||
|
EXPECT_TRUE_SIMULATED_WAIT(ep1_ch1()->receiving() && ep1_ch1()->writable() &&
|
||||||
|
ep2_ch1()->receiving() &&
|
||||||
|
ep2_ch1()->writable(),
|
||||||
|
kDefaultTimeout, clock);
|
||||||
|
|
||||||
|
// Drop all packets so that both channels become not writable.
|
||||||
|
fw()->AddRule(false, rtc::FP_ANY, rtc::FD_ANY, kPublicAddrs[0]);
|
||||||
|
const int kWriteTimeoutDelay = 6000;
|
||||||
|
EXPECT_TRUE_SIMULATED_WAIT(!ep1_ch1()->writable() && !ep2_ch1()->writable(),
|
||||||
|
kWriteTimeoutDelay, clock);
|
||||||
|
|
||||||
|
ep1_ch1()->SetIceParameters(kIceParams[2]);
|
||||||
|
ep1_ch1()->SetRemoteIceParameters(kIceParams[3]);
|
||||||
|
ep1_ch1()->MaybeStartGathering();
|
||||||
|
EXPECT_EQ(1, GetMetricsObserver(0)->GetEnumCounter(
|
||||||
|
webrtc::kEnumCounterIceRestart,
|
||||||
|
static_cast<int>(IceRestartState::DISCONNECTED)));
|
||||||
|
|
||||||
|
ep2_ch1()->SetIceParameters(kIceParams[3]);
|
||||||
|
ep2_ch1()->SetRemoteIceParameters(kIceParams[2]);
|
||||||
|
ep2_ch1()->MaybeStartGathering();
|
||||||
|
EXPECT_EQ(1, GetMetricsObserver(1)->GetEnumCounter(
|
||||||
|
webrtc::kEnumCounterIceRestart,
|
||||||
|
static_cast<int>(IceRestartState::DISCONNECTED)));
|
||||||
|
|
||||||
|
DestroyChannels();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests that UMAs are recorded when ICE restarts while the channel
|
||||||
|
// is connected.
|
||||||
|
TEST_F(P2PTransportChannelTest, TestUMAIceRestartWhileConnected) {
|
||||||
|
rtc::ScopedFakeClock clock;
|
||||||
|
ConfigureEndpoints(OPEN, OPEN, kOnlyLocalPorts, kOnlyLocalPorts);
|
||||||
|
|
||||||
|
CreateChannels();
|
||||||
|
EXPECT_TRUE_SIMULATED_WAIT(ep1_ch1()->receiving() && ep1_ch1()->writable() &&
|
||||||
|
ep2_ch1()->receiving() &&
|
||||||
|
ep2_ch1()->writable(),
|
||||||
|
kDefaultTimeout, clock);
|
||||||
|
|
||||||
|
ep1_ch1()->SetIceParameters(kIceParams[2]);
|
||||||
|
ep1_ch1()->SetRemoteIceParameters(kIceParams[3]);
|
||||||
|
ep1_ch1()->MaybeStartGathering();
|
||||||
|
EXPECT_EQ(1, GetMetricsObserver(0)->GetEnumCounter(
|
||||||
|
webrtc::kEnumCounterIceRestart,
|
||||||
|
static_cast<int>(IceRestartState::CONNECTED)));
|
||||||
|
|
||||||
|
ep2_ch1()->SetIceParameters(kIceParams[3]);
|
||||||
|
ep2_ch1()->SetRemoteIceParameters(kIceParams[2]);
|
||||||
|
ep2_ch1()->MaybeStartGathering();
|
||||||
|
EXPECT_EQ(1, GetMetricsObserver(1)->GetEnumCounter(
|
||||||
|
webrtc::kEnumCounterIceRestart,
|
||||||
|
static_cast<int>(IceRestartState::CONNECTED)));
|
||||||
|
|
||||||
|
DestroyChannels();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests that UMAs are recorded when ICE restarts while the channel
|
||||||
|
// is connecting.
|
||||||
|
TEST_F(P2PTransportChannelTest, TestUMAIceRestartWhileConnecting) {
|
||||||
|
rtc::ScopedFakeClock clock;
|
||||||
|
ConfigureEndpoints(OPEN, OPEN, kOnlyLocalPorts, kOnlyLocalPorts);
|
||||||
|
|
||||||
|
// Create the channels without waiting for them to become connected.
|
||||||
|
CreateChannels();
|
||||||
|
|
||||||
|
ep1_ch1()->SetIceParameters(kIceParams[2]);
|
||||||
|
ep1_ch1()->SetRemoteIceParameters(kIceParams[3]);
|
||||||
|
ep1_ch1()->MaybeStartGathering();
|
||||||
|
EXPECT_EQ(1, GetMetricsObserver(0)->GetEnumCounter(
|
||||||
|
webrtc::kEnumCounterIceRestart,
|
||||||
|
static_cast<int>(IceRestartState::CONNECTING)));
|
||||||
|
|
||||||
|
ep2_ch1()->SetIceParameters(kIceParams[3]);
|
||||||
|
ep2_ch1()->SetRemoteIceParameters(kIceParams[2]);
|
||||||
|
ep2_ch1()->MaybeStartGathering();
|
||||||
|
EXPECT_EQ(1, GetMetricsObserver(1)->GetEnumCounter(
|
||||||
|
webrtc::kEnumCounterIceRestart,
|
||||||
|
static_cast<int>(IceRestartState::CONNECTING)));
|
||||||
|
|
||||||
|
DestroyChannels();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests that a UMA on ICE regathering is recorded when there is a network
|
||||||
|
// change if and only if continual gathering is enabled.
|
||||||
|
TEST_F(P2PTransportChannelTest,
|
||||||
|
TestIceRegatheringReasonContinualGatheringByNetworkChange) {
|
||||||
|
rtc::ScopedFakeClock clock;
|
||||||
|
ConfigureEndpoints(OPEN, OPEN, kOnlyLocalPorts, kOnlyLocalPorts);
|
||||||
|
|
||||||
|
// ep1 gathers continually but ep2 does not.
|
||||||
|
IceConfig continual_gathering_config =
|
||||||
|
CreateIceConfig(1000, GATHER_CONTINUALLY);
|
||||||
|
IceConfig default_config;
|
||||||
|
CreateChannels(continual_gathering_config, default_config);
|
||||||
|
|
||||||
|
EXPECT_TRUE_SIMULATED_WAIT(ep1_ch1()->receiving() && ep1_ch1()->writable() &&
|
||||||
|
ep2_ch1()->receiving() &&
|
||||||
|
ep2_ch1()->writable(),
|
||||||
|
kDefaultTimeout, clock);
|
||||||
|
|
||||||
|
// Adding address in ep1 will trigger continual gathering.
|
||||||
|
AddAddress(0, kAlternateAddrs[0]);
|
||||||
|
EXPECT_EQ_SIMULATED_WAIT(
|
||||||
|
1, GetMetricsObserver(0)->GetEnumCounter(
|
||||||
|
webrtc::kEnumCounterIceRegathering,
|
||||||
|
static_cast<int>(IceRegatheringReason::NETWORK_CHANGE)),
|
||||||
|
kDefaultTimeout, clock);
|
||||||
|
|
||||||
|
ep2_ch1()->SetIceParameters(kIceParams[3]);
|
||||||
|
ep2_ch1()->SetRemoteIceParameters(kIceParams[2]);
|
||||||
|
ep2_ch1()->MaybeStartGathering();
|
||||||
|
|
||||||
|
AddAddress(1, kAlternateAddrs[1]);
|
||||||
|
SIMULATED_WAIT(false, kDefaultTimeout, clock);
|
||||||
|
// ep2 has not enabled continual gathering.
|
||||||
|
EXPECT_EQ(0, GetMetricsObserver(1)->GetEnumCounter(
|
||||||
|
webrtc::kEnumCounterIceRegathering,
|
||||||
|
static_cast<int>(IceRegatheringReason::NETWORK_CHANGE)));
|
||||||
|
|
||||||
|
DestroyChannels();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests that a UMA on ICE regathering is recorded when there is a network
|
||||||
|
// failure if and only if continual gathering is enabled.
|
||||||
|
TEST_F(P2PTransportChannelTest,
|
||||||
|
TestIceRegatheringReasonContinualGatheringByNetworkFailure) {
|
||||||
|
rtc::ScopedFakeClock clock;
|
||||||
|
ConfigureEndpoints(OPEN, OPEN, kOnlyLocalPorts, kOnlyLocalPorts);
|
||||||
|
|
||||||
|
// ep1 gathers continually but ep2 does not.
|
||||||
|
IceConfig config1 = CreateIceConfig(1000, GATHER_CONTINUALLY);
|
||||||
|
config1.regather_on_failed_networks_interval = rtc::Optional<int>(2000);
|
||||||
|
IceConfig config2;
|
||||||
|
config2.regather_on_failed_networks_interval = rtc::Optional<int>(2000);
|
||||||
|
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 kNetworkFailureTimeout = 35000;
|
||||||
|
SIMULATED_WAIT(false, kNetworkFailureTimeout, clock);
|
||||||
|
EXPECT_LE(1, GetMetricsObserver(0)->GetEnumCounter(
|
||||||
|
webrtc::kEnumCounterIceRegathering,
|
||||||
|
static_cast<int>(IceRegatheringReason::NETWORK_FAILURE)));
|
||||||
|
EXPECT_EQ(0, GetMetricsObserver(1)->GetEnumCounter(
|
||||||
|
webrtc::kEnumCounterIceRegathering,
|
||||||
|
static_cast<int>(IceRegatheringReason::NETWORK_FAILURE)));
|
||||||
|
|
||||||
|
DestroyChannels();
|
||||||
|
}
|
||||||
|
|
||||||
// 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) {
|
||||||
|
@ -23,6 +23,10 @@
|
|||||||
#include "webrtc/base/sigslot.h"
|
#include "webrtc/base/sigslot.h"
|
||||||
#include "webrtc/base/thread.h"
|
#include "webrtc/base/thread.h"
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
class MetricsObserverInterface;
|
||||||
|
}
|
||||||
|
|
||||||
namespace cricket {
|
namespace cricket {
|
||||||
|
|
||||||
// PortAllocator is responsible for allocating Port types for a given
|
// PortAllocator is responsible for allocating Port types for a given
|
||||||
@ -72,6 +76,9 @@ enum {
|
|||||||
PORTALLOCATOR_DISABLE_COSTLY_NETWORKS = 0x2000,
|
PORTALLOCATOR_DISABLE_COSTLY_NETWORKS = 0x2000,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Defines various reasons that have caused ICE regathering.
|
||||||
|
enum class IceRegatheringReason { NETWORK_CHANGE, NETWORK_FAILURE, MAX_VALUE };
|
||||||
|
|
||||||
const uint32_t kDefaultPortAllocatorFlags = 0;
|
const uint32_t kDefaultPortAllocatorFlags = 0;
|
||||||
|
|
||||||
const uint32_t kDefaultStepDelay = 1000; // 1 sec step delay.
|
const uint32_t kDefaultStepDelay = 1000; // 1 sec step delay.
|
||||||
@ -216,6 +223,9 @@ class PortAllocatorSession : public sigslot::has_slots<> {
|
|||||||
SignalCandidatesRemoved;
|
SignalCandidatesRemoved;
|
||||||
sigslot::signal1<PortAllocatorSession*> SignalCandidatesAllocationDone;
|
sigslot::signal1<PortAllocatorSession*> SignalCandidatesAllocationDone;
|
||||||
|
|
||||||
|
sigslot::signal2<PortAllocatorSession*, IceRegatheringReason>
|
||||||
|
SignalIceRegathering;
|
||||||
|
|
||||||
virtual uint32_t generation() { return generation_; }
|
virtual uint32_t generation() { return generation_; }
|
||||||
virtual void set_generation(uint32_t generation) { generation_ = generation; }
|
virtual void set_generation(uint32_t generation) { generation_ = generation; }
|
||||||
sigslot::signal1<PortAllocatorSession*> SignalDestroyed;
|
sigslot::signal1<PortAllocatorSession*> SignalDestroyed;
|
||||||
@ -370,6 +380,10 @@ class PortAllocator : public sigslot::has_slots<> {
|
|||||||
const std::string& origin() const { return origin_; }
|
const std::string& origin() const { return origin_; }
|
||||||
void set_origin(const std::string& origin) { origin_ = origin; }
|
void set_origin(const std::string& origin) { origin_ = origin; }
|
||||||
|
|
||||||
|
void SetMetricsObserver(webrtc::MetricsObserverInterface* observer) {
|
||||||
|
metrics_observer_ = observer;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual PortAllocatorSession* CreateSessionInternal(
|
virtual PortAllocatorSession* CreateSessionInternal(
|
||||||
const std::string& content_name,
|
const std::string& content_name,
|
||||||
@ -377,6 +391,14 @@ class PortAllocator : public sigslot::has_slots<> {
|
|||||||
const std::string& ice_ufrag,
|
const std::string& ice_ufrag,
|
||||||
const std::string& ice_pwd) = 0;
|
const std::string& ice_pwd) = 0;
|
||||||
|
|
||||||
|
webrtc::MetricsObserverInterface* metrics_observer() {
|
||||||
|
return metrics_observer_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::deque<std::unique_ptr<PortAllocatorSession>>& pooled_sessions() {
|
||||||
|
return pooled_sessions_;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t flags_;
|
uint32_t flags_;
|
||||||
std::string agent_;
|
std::string agent_;
|
||||||
rtc::ProxyInfo proxy_;
|
rtc::ProxyInfo proxy_;
|
||||||
@ -397,6 +419,8 @@ class PortAllocator : public sigslot::has_slots<> {
|
|||||||
int allocated_pooled_session_count_ = 0;
|
int allocated_pooled_session_count_ = 0;
|
||||||
std::deque<std::unique_ptr<PortAllocatorSession>> pooled_sessions_;
|
std::deque<std::unique_ptr<PortAllocatorSession>> pooled_sessions_;
|
||||||
bool prune_turn_ports_ = false;
|
bool prune_turn_ports_ = false;
|
||||||
|
|
||||||
|
webrtc::MetricsObserverInterface* metrics_observer_ = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace cricket
|
} // namespace cricket
|
||||||
|
@ -18,6 +18,10 @@
|
|||||||
|
|
||||||
namespace buzz { class XmlElement; }
|
namespace buzz { class XmlElement; }
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
class MetricsObserverInterface;
|
||||||
|
}
|
||||||
|
|
||||||
namespace cricket {
|
namespace cricket {
|
||||||
|
|
||||||
class Candidate;
|
class Candidate;
|
||||||
@ -74,6 +78,9 @@ class TransportChannelImpl : public TransportChannel {
|
|||||||
// occurred.
|
// occurred.
|
||||||
virtual void MaybeStartGathering() = 0;
|
virtual void MaybeStartGathering() = 0;
|
||||||
|
|
||||||
|
virtual void SetMetricsObserver(
|
||||||
|
webrtc::MetricsObserverInterface* observer) = 0;
|
||||||
|
|
||||||
sigslot::signal1<TransportChannelImpl*> SignalGatheringState;
|
sigslot::signal1<TransportChannelImpl*> SignalGatheringState;
|
||||||
|
|
||||||
// Handles sending and receiving of candidates. The Transport
|
// Handles sending and receiving of candidates. The Transport
|
||||||
|
@ -187,6 +187,7 @@ TransportChannel* TransportController::CreateTransportChannel_n(
|
|||||||
// Need to create a new channel.
|
// Need to create a new channel.
|
||||||
Transport* transport = GetOrCreateTransport_n(transport_name);
|
Transport* transport = GetOrCreateTransport_n(transport_name);
|
||||||
TransportChannelImpl* channel = transport->CreateChannel(component);
|
TransportChannelImpl* channel = transport->CreateChannel(component);
|
||||||
|
channel->SetMetricsObserver(metrics_observer_);
|
||||||
channel->SignalWritableState.connect(
|
channel->SignalWritableState.connect(
|
||||||
this, &TransportController::OnChannelWritableState_n);
|
this, &TransportController::OnChannelWritableState_n);
|
||||||
channel->SignalReceivingState.connect(
|
channel->SignalReceivingState.connect(
|
||||||
@ -704,4 +705,12 @@ void TransportController::OnDtlsHandshakeError(rtc::SSLHandshakeError error) {
|
|||||||
SignalDtlsHandshakeError(error);
|
SignalDtlsHandshakeError(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TransportController::SetMetricsObserver(
|
||||||
|
webrtc::MetricsObserverInterface* metrics_observer) {
|
||||||
|
metrics_observer_ = metrics_observer;
|
||||||
|
for (auto channel : channels_) {
|
||||||
|
channel->SetMetricsObserver(metrics_observer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace cricket
|
} // namespace cricket
|
||||||
|
@ -25,6 +25,9 @@
|
|||||||
namespace rtc {
|
namespace rtc {
|
||||||
class Thread;
|
class Thread;
|
||||||
}
|
}
|
||||||
|
namespace webrtc {
|
||||||
|
class MetricsObserverInterface;
|
||||||
|
}
|
||||||
|
|
||||||
namespace cricket {
|
namespace cricket {
|
||||||
|
|
||||||
@ -129,6 +132,8 @@ class TransportController : public sigslot::has_slots<>,
|
|||||||
|
|
||||||
sigslot::signal1<rtc::SSLHandshakeError> SignalDtlsHandshakeError;
|
sigslot::signal1<rtc::SSLHandshakeError> SignalDtlsHandshakeError;
|
||||||
|
|
||||||
|
void SetMetricsObserver(webrtc::MetricsObserverInterface* metrics_observer);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Protected and virtual so we can override it in unit tests.
|
// Protected and virtual so we can override it in unit tests.
|
||||||
virtual Transport* CreateTransport_n(const std::string& transport_name);
|
virtual Transport* CreateTransport_n(const std::string& transport_name);
|
||||||
@ -238,6 +243,8 @@ class TransportController : public sigslot::has_slots<>,
|
|||||||
rtc::AsyncInvoker invoker_;
|
rtc::AsyncInvoker invoker_;
|
||||||
// True if QUIC is used instead of DTLS.
|
// True if QUIC is used instead of DTLS.
|
||||||
bool quic_ = false;
|
bool quic_ = false;
|
||||||
|
|
||||||
|
webrtc::MetricsObserverInterface* metrics_observer_ = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace cricket
|
} // namespace cricket
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "webrtc/api/peerconnectioninterface.h"
|
||||||
#include "webrtc/p2p/base/basicpacketsocketfactory.h"
|
#include "webrtc/p2p/base/basicpacketsocketfactory.h"
|
||||||
#include "webrtc/p2p/base/common.h"
|
#include "webrtc/p2p/base/common.h"
|
||||||
#include "webrtc/p2p/base/port.h"
|
#include "webrtc/p2p/base/port.h"
|
||||||
@ -150,14 +151,35 @@ void BasicPortAllocator::Construct() {
|
|||||||
allow_tcp_listen_ = true;
|
allow_tcp_listen_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BasicPortAllocator::OnIceRegathering(PortAllocatorSession* session,
|
||||||
|
IceRegatheringReason reason) {
|
||||||
|
if (!metrics_observer()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// If the session has not been taken by an active channel, do not report the
|
||||||
|
// metric.
|
||||||
|
for (auto& allocator_session : pooled_sessions()) {
|
||||||
|
if (allocator_session.get() == session) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
metrics_observer()->IncrementEnumCounter(
|
||||||
|
webrtc::kEnumCounterIceRegathering, static_cast<int>(reason),
|
||||||
|
static_cast<int>(IceRegatheringReason::MAX_VALUE));
|
||||||
|
}
|
||||||
|
|
||||||
BasicPortAllocator::~BasicPortAllocator() {
|
BasicPortAllocator::~BasicPortAllocator() {
|
||||||
}
|
}
|
||||||
|
|
||||||
PortAllocatorSession* BasicPortAllocator::CreateSessionInternal(
|
PortAllocatorSession* BasicPortAllocator::CreateSessionInternal(
|
||||||
const std::string& content_name, int component,
|
const std::string& content_name, int component,
|
||||||
const std::string& ice_ufrag, const std::string& ice_pwd) {
|
const std::string& ice_ufrag, const std::string& ice_pwd) {
|
||||||
return new BasicPortAllocatorSession(
|
PortAllocatorSession* session = new BasicPortAllocatorSession(
|
||||||
this, content_name, component, ice_ufrag, ice_pwd);
|
this, content_name, component, ice_ufrag, ice_pwd);
|
||||||
|
session->SignalIceRegathering.connect(this,
|
||||||
|
&BasicPortAllocator::OnIceRegathering);
|
||||||
|
return session;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BasicPortAllocator::AddTurnServer(const RelayServerConfig& turn_server) {
|
void BasicPortAllocator::AddTurnServer(const RelayServerConfig& turn_server) {
|
||||||
@ -247,7 +269,7 @@ void BasicPortAllocatorSession::StartGettingPorts() {
|
|||||||
|
|
||||||
network_thread_->Post(RTC_FROM_HERE, this, MSG_CONFIG_START);
|
network_thread_->Post(RTC_FROM_HERE, this, MSG_CONFIG_START);
|
||||||
|
|
||||||
LOG(LS_INFO) << "Pruning turn ports "
|
LOG(LS_INFO) << "Start getting ports with prune_turn_ports "
|
||||||
<< (prune_turn_ports_ ? "enabled" : "disabled");
|
<< (prune_turn_ports_ ? "enabled" : "disabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,6 +324,8 @@ void BasicPortAllocatorSession::RegatherOnFailedNetworks() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOG(LS_INFO) << "Regather candidates on failed networks";
|
||||||
|
|
||||||
// Mark a sequence as "network failed" if its network is in the list of failed
|
// Mark a sequence as "network failed" if its network is in the list of failed
|
||||||
// networks, so that it won't be considered as equivalent when the session
|
// networks, so that it won't be considered as equivalent when the session
|
||||||
// regathers ports and candidates.
|
// regathers ports and candidates.
|
||||||
@ -321,7 +345,9 @@ void BasicPortAllocatorSession::RegatherOnFailedNetworks() {
|
|||||||
PrunePortsAndRemoveCandidates(ports_to_prune);
|
PrunePortsAndRemoveCandidates(ports_to_prune);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (allocation_started_ && network_manager_started_) {
|
if (allocation_started_ && network_manager_started_ && !IsStopped()) {
|
||||||
|
SignalIceRegathering(this, IceRegatheringReason::NETWORK_FAILURE);
|
||||||
|
|
||||||
DoAllocate();
|
DoAllocate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -501,7 +527,7 @@ void BasicPortAllocatorSession::AllocatePorts() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void BasicPortAllocatorSession::OnAllocate() {
|
void BasicPortAllocatorSession::OnAllocate() {
|
||||||
if (network_manager_started_)
|
if (network_manager_started_ && !IsStopped())
|
||||||
DoAllocate();
|
DoAllocate();
|
||||||
|
|
||||||
allocation_started_ = true;
|
allocation_started_ = true;
|
||||||
@ -553,10 +579,6 @@ std::vector<rtc::Network*> BasicPortAllocatorSession::GetNetworks() {
|
|||||||
void BasicPortAllocatorSession::DoAllocate() {
|
void BasicPortAllocatorSession::DoAllocate() {
|
||||||
bool done_signal_needed = false;
|
bool done_signal_needed = false;
|
||||||
std::vector<rtc::Network*> networks = GetNetworks();
|
std::vector<rtc::Network*> networks = GetNetworks();
|
||||||
|
|
||||||
if (IsStopped()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (networks.empty()) {
|
if (networks.empty()) {
|
||||||
LOG(LS_WARNING) << "Machine has no networks; no ports will be allocated";
|
LOG(LS_WARNING) << "Machine has no networks; no ports will be allocated";
|
||||||
done_signal_needed = true;
|
done_signal_needed = true;
|
||||||
@ -627,12 +649,18 @@ void BasicPortAllocatorSession::OnNetworksChanged() {
|
|||||||
PrunePortsAndRemoveCandidates(ports_to_prune);
|
PrunePortsAndRemoveCandidates(ports_to_prune);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (allocation_started_ && !IsStopped()) {
|
||||||
|
if (network_manager_started_) {
|
||||||
|
// If the network manager has started, it must be regathering.
|
||||||
|
SignalIceRegathering(this, IceRegatheringReason::NETWORK_CHANGE);
|
||||||
|
}
|
||||||
|
DoAllocate();
|
||||||
|
}
|
||||||
|
|
||||||
if (!network_manager_started_) {
|
if (!network_manager_started_) {
|
||||||
LOG(LS_INFO) << "Network manager is started";
|
LOG(LS_INFO) << "Network manager has started";
|
||||||
network_manager_started_ = true;
|
network_manager_started_ = true;
|
||||||
}
|
}
|
||||||
if (allocation_started_)
|
|
||||||
DoAllocate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BasicPortAllocatorSession::DisableEquivalentPhases(
|
void BasicPortAllocatorSession::DisableEquivalentPhases(
|
||||||
|
@ -65,6 +65,9 @@ class BasicPortAllocator : public PortAllocator {
|
|||||||
private:
|
private:
|
||||||
void Construct();
|
void Construct();
|
||||||
|
|
||||||
|
void OnIceRegathering(PortAllocatorSession* session,
|
||||||
|
IceRegatheringReason reason);
|
||||||
|
|
||||||
rtc::NetworkManager* network_manager_;
|
rtc::NetworkManager* network_manager_;
|
||||||
rtc::PacketSocketFactory* socket_factory_;
|
rtc::PacketSocketFactory* socket_factory_;
|
||||||
bool allow_tcp_listen_;
|
bool allow_tcp_listen_;
|
||||||
|
@ -199,6 +199,10 @@ class QuicTransportChannel : public TransportChannelImpl,
|
|||||||
void OnProofVerifyDetailsAvailable(
|
void OnProofVerifyDetailsAvailable(
|
||||||
const net::ProofVerifyDetails& verify_details) override;
|
const net::ProofVerifyDetails& verify_details) override;
|
||||||
|
|
||||||
|
void SetMetricsObserver(webrtc::MetricsObserverInterface* observer) override {
|
||||||
|
channel_->SetMetricsObserver(observer);
|
||||||
|
}
|
||||||
|
|
||||||
// Returns true if |quic_| has queued data which wasn't written due
|
// Returns true if |quic_| has queued data which wasn't written due
|
||||||
// to |channel_| being write blocked.
|
// to |channel_| being write blocked.
|
||||||
bool HasDataToWrite() const;
|
bool HasDataToWrite() const;
|
||||||
|
Reference in New Issue
Block a user