Add configurable connectivity check intervals.

The connectivity check intervals for candidate pairs with strong and
weak connectivity are currently constants in the ICE implementation. A
set of suboptimal value of these constants for a given application may
result in undesirable behavior including excessive network switching
latency. This CL adds these intervals to RTCConfiguration that is
available to applications to configure, while maintaining the original
constants as their default value for compatibility with existing
applications.

Bug: webrtc:8988
Change-Id: I804b0f4cf7881be7d3c8aec2776bc9596de72482
Reviewed-on: https://webrtc-review.googlesource.com/60585
Commit-Queue: Qingsi Wang <qingsi@google.com>
Reviewed-by: Taylor Brandstetter <deadbeef@webrtc.org>
Reviewed-by: Sami Kalliomäki <sakal@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#22351}
This commit is contained in:
Qingsi Wang
2018-03-08 14:55:14 -08:00
committed by Commit Bot
parent 6d72c3258f
commit e6826d2461
7 changed files with 142 additions and 20 deletions

View File

@ -489,8 +489,30 @@ class PeerConnectionInterface : public rtc::RefCountInterface {
// re-determining was removed in ICEbis (ICE v2).
bool redetermine_role_on_ice_restart = true;
// If set, the min interval (max rate) at which we will send ICE checks
// (STUN pings), in milliseconds.
// The following fields define intervals in milliseconds at which ICE
// connectivity checks are sent.
//
// We consider ICE is "strongly connected" for an agent when there is at
// least one candidate pair that currently succeeds in connectivity check
// from its direction i.e. sending a STUN ping and receives a STUN ping
// response, AND all candidate pairs have sent a minimum number of pings for
// connectivity (this number is implementation-specific). Otherwise, ICE is
// considered in "weak connectivity".
//
// Note that the above notion of strong and weak connectivity is not defined
// in RFC 5245, and they apply to our current ICE implementation only.
//
// 1) ice_check_interval_strong_connectivity defines the interval applied to
// ALL candidate pairs when ICE is strongly connected, and it overrides the
// default value of this interval in the ICE implementation;
// 2) ice_check_interval_weak_connectivity defines the counterpart for ALL
// pairs when ICE is weakly connected, and it overrides the default value of
// this interval in the ICE implementation;
// 3) ice_check_min_interval defines the minimal interval (equivalently the
// maximum rate) that overrides the above two intervals when either of them
// is less.
rtc::Optional<int> ice_check_interval_strong_connectivity;
rtc::Optional<int> ice_check_interval_weak_connectivity;
rtc::Optional<int> ice_check_min_interval;
// The interval in milliseconds at which STUN candidates will resend STUN

View File

@ -110,9 +110,23 @@ struct IceConfig {
// Default nomination mode if the remote does not support renomination.
NominationMode default_nomination_mode = NominationMode::SEMI_AGGRESSIVE;
// The interval in milliseconds at which ICE checks (STUN pings) will be sent
// for a candidate pair when it is both writable and receiving (strong
// connectivity). This parameter overrides the default value given by
// |STRONG_PING_INTERVAL| in p2ptransport.h if set.
rtc::Optional<int> ice_check_interval_strong_connectivity;
// The interval in milliseconds at which ICE checks (STUN pings) will be sent
// for a candidate pair when it is either not writable or not receiving (weak
// connectivity). This parameter overrides the default value given by
// |WEAK_PING_INTERVAL| in p2ptransport.h if set.
rtc::Optional<int> ice_check_interval_weak_connectivity;
// ICE checks (STUN pings) will not be sent at higher rate (lower interval)
// than this, no matter what other settings there are.
// Measure in milliseconds.
//
// Note that this parameter overrides both the above check intervals for
// candidate pairs with strong or weak connectivity, if either of the above
// interval is shorter than the min interval.
rtc::Optional<int> ice_check_min_interval;
// The interval in milliseconds at which STUN candidates will resend STUN
// binding requests to keep NAT bindings open.

View File

@ -105,9 +105,15 @@ static const int PING_PACKET_SIZE = 60 * 8;
// The next two ping intervals are at the channel level.
// STRONG_PING_INTERVAL (480ms) is applied when the selected connection is both
// writable and receiving.
//
// This constant is the default value of ice_check_interval_strong_connectivity
// in IceConfig if not set.
const int STRONG_PING_INTERVAL = 1000 * PING_PACKET_SIZE / 1000;
// WEAK_PING_INTERVAL (48ms) is applied when the selected connection is either
// not writable or not receiving.
//
// This constant is the default value of ice_check_interval_weak_connectivity in
// IceConfig if not set.
const int WEAK_PING_INTERVAL = 1000 * PING_PACKET_SIZE / 10000;
// The next two ping intervals are at the connection level.
@ -438,6 +444,11 @@ void P2PTransportChannel::SetRemoteIceMode(IceMode mode) {
remote_ice_mode_ = mode;
}
// TODO(qingsi): We apply the convention that setting a rtc::Optional parameter
// to null restores its default value in the implementation. However, some
// rtc::Optional parameters are only processed below if non-null, e.g.,
// regather_on_failed_networks_interval, and thus there is no way to restore the
// defaults. Fix this issue later for consistency.
void P2PTransportChannel::SetIceConfig(const IceConfig& config) {
if (config_.continual_gathering_policy != config.continual_gathering_policy) {
if (!allocator_sessions_.empty()) {
@ -504,7 +515,8 @@ void P2PTransportChannel::SetIceConfig(const IceConfig& config) {
config_.regather_on_failed_networks_interval =
config.regather_on_failed_networks_interval;
RTC_LOG(LS_INFO) << "Set regather_on_failed_networks_interval to "
<< *config_.regather_on_failed_networks_interval;
<< config_.regather_on_failed_networks_interval.value_or(
-1);
}
if (config.regather_all_networks_interval_range) {
@ -513,13 +525,15 @@ void P2PTransportChannel::SetIceConfig(const IceConfig& config) {
config_.regather_all_networks_interval_range =
config.regather_all_networks_interval_range;
RTC_LOG(LS_INFO) << "Set regather_all_networks_interval_range to "
<< config.regather_all_networks_interval_range->ToString();
<< config.regather_all_networks_interval_range
.value_or(rtc::IntervalRange(-1, 0))
.ToString();
}
if (config.receiving_switching_delay) {
config_.receiving_switching_delay = config.receiving_switching_delay;
RTC_LOG(LS_INFO) << "Set receiving_switching_delay to"
<< *config_.receiving_switching_delay;
<< config_.receiving_switching_delay.value_or(-1);
}
if (config_.default_nomination_mode != config.default_nomination_mode) {
@ -528,10 +542,28 @@ void P2PTransportChannel::SetIceConfig(const IceConfig& config) {
<< static_cast<int>(config_.default_nomination_mode);
}
if (config_.ice_check_interval_strong_connectivity !=
config.ice_check_interval_strong_connectivity) {
config_.ice_check_interval_strong_connectivity =
config.ice_check_interval_strong_connectivity;
RTC_LOG(LS_INFO) << "Set strong ping interval to "
<< config_.ice_check_interval_strong_connectivity.value_or(
-1);
}
if (config_.ice_check_interval_weak_connectivity !=
config.ice_check_interval_weak_connectivity) {
config_.ice_check_interval_weak_connectivity =
config.ice_check_interval_weak_connectivity;
RTC_LOG(LS_INFO) << "Set weak ping interval to "
<< config_.ice_check_interval_weak_connectivity.value_or(
-1);
}
if (config_.ice_check_min_interval != config.ice_check_min_interval) {
config_.ice_check_min_interval = config.ice_check_min_interval;
RTC_LOG(LS_INFO) << "Set min ping interval to "
<< *config_.ice_check_min_interval;
<< config_.ice_check_min_interval.value_or(-1);
}
if (config_.network_preference != config.network_preference) {
@ -540,7 +572,8 @@ void P2PTransportChannel::SetIceConfig(const IceConfig& config) {
RTC_LOG(LS_INFO) << "Set network preference to "
<< (config_.network_preference.has_value()
? config_.network_preference.value()
: 0);
: -1); // network_preference cannot be bound to
// int with value_or.
}
// TODO(qingsi): Resolve the naming conflict of stun_keepalive_delay in
@ -550,9 +583,7 @@ void P2PTransportChannel::SetIceConfig(const IceConfig& config) {
allocator_session()->SetStunKeepaliveIntervalForReadyPorts(
config_.stun_keepalive_interval);
RTC_LOG(LS_INFO) << "Set STUN keepalive interval to "
<< (config.stun_keepalive_interval.has_value()
? config_.stun_keepalive_interval.value()
: -1);
<< config.stun_keepalive_interval.value_or(-1);
}
}

View File

@ -20,6 +20,7 @@
#ifndef P2P_BASE_P2PTRANSPORTCHANNEL_H_
#define P2P_BASE_P2PTRANSPORTCHANNEL_H_
#include <algorithm>
#include <map>
#include <memory>
#include <set>
@ -180,19 +181,15 @@ class P2PTransportChannel : public IceTransportInternal,
bool weak() const;
int weak_ping_interval() const {
if (config_.ice_check_min_interval &&
weak_ping_interval_ < *config_.ice_check_min_interval) {
return *config_.ice_check_min_interval;
}
return weak_ping_interval_;
return std::max(config_.ice_check_interval_weak_connectivity.value_or(
weak_ping_interval_),
config_.ice_check_min_interval.value_or(-1));
}
int strong_ping_interval() const {
if (config_.ice_check_min_interval &&
STRONG_PING_INTERVAL < *config_.ice_check_min_interval) {
return *config_.ice_check_min_interval;
}
return STRONG_PING_INTERVAL;
return std::max(config_.ice_check_interval_strong_connectivity.value_or(
STRONG_PING_INTERVAL),
config_.ice_check_min_interval.value_or(-1));
}
// Returns true if it's possible to send packets on |connection|.

View File

@ -663,6 +663,8 @@ bool PeerConnectionInterface::RTCConfiguration::operator==(
bool presume_writable_when_fully_relayed;
bool enable_ice_renomination;
bool redetermine_role_on_ice_restart;
rtc::Optional<int> ice_check_interval_strong_connectivity;
rtc::Optional<int> ice_check_interval_weak_connectivity;
rtc::Optional<int> ice_check_min_interval;
rtc::Optional<int> stun_candidate_keepalive_interval;
rtc::Optional<rtc::IntervalRange> ice_regather_interval_range;
@ -703,6 +705,10 @@ 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_interval_strong_connectivity ==
o.ice_check_interval_strong_connectivity &&
ice_check_interval_weak_connectivity ==
o.ice_check_interval_weak_connectivity &&
ice_check_min_interval == o.ice_check_min_interval &&
stun_candidate_keepalive_interval ==
o.stun_candidate_keepalive_interval &&
@ -2700,6 +2706,10 @@ bool PeerConnection::SetConfiguration(const RTCConfiguration& configuration,
configuration.ice_candidate_pool_size;
modified_config.prune_turn_ports = configuration.prune_turn_ports;
modified_config.ice_check_min_interval = configuration.ice_check_min_interval;
modified_config.ice_check_interval_strong_connectivity =
configuration.ice_check_interval_strong_connectivity;
modified_config.ice_check_interval_weak_connectivity =
configuration.ice_check_interval_weak_connectivity;
modified_config.stun_candidate_keepalive_interval =
configuration.stun_candidate_keepalive_interval;
modified_config.turn_customizer = configuration.turn_customizer;
@ -4860,6 +4870,10 @@ cricket::IceConfig PeerConnection::ParseIceConfig(
ice_config.continual_gathering_policy = gathering_policy;
ice_config.presume_writable_when_fully_relayed =
config.presume_writable_when_fully_relayed;
ice_config.ice_check_interval_strong_connectivity =
config.ice_check_interval_strong_connectivity;
ice_config.ice_check_interval_weak_connectivity =
config.ice_check_interval_weak_connectivity;
ice_config.ice_check_min_interval = config.ice_check_min_interval;
ice_config.stun_keepalive_interval = config.stun_candidate_keepalive_interval;
ice_config.regather_all_networks_interval_range =

View File

@ -386,6 +386,28 @@ public class PeerConnection {
public int iceCandidatePoolSize;
public boolean pruneTurnPorts;
public boolean presumeWritableWhenFullyRelayed;
// The following fields define intervals in milliseconds at which ICE
// connectivity checks are sent.
//
// We consider ICE is "strongly connected" for an agent when there is at
// least one candidate pair that currently succeeds in connectivity check
// from its direction i.e. sending a ping and receives a ping response, AND
// all candidate pairs have sent a minimum number of pings for connectivity
// (this number is implementation-specific). Otherwise, ICE is considered in
// "weak connectivity".
//
// Note that the above notion of strong and weak connectivity is not defined
// in RFC 5245, and they apply to our current ICE implementation only.
//
// 1) iceCheckIntervalStrongConnectivityMs defines the interval applied to
// ALL candidate pairs when ICE is strongly connected,
// 2) iceCheckIntervalWeakConnectivityMs defines the counterpart for ALL
// pairs when ICE is weakly connected, and
// 3) iceCheckMinInterval defines the minimal interval (equivalently the
// maximum rate) that overrides the above two intervals when either of them
// is less.
public Integer iceCheckIntervalStrongConnectivityMs;
public Integer iceCheckIntervalWeakConnectivityMs;
public Integer iceCheckMinInterval;
// The interval in milliseconds at which STUN candidates will resend STUN binding requests
// to keep NAT bindings open.
@ -437,6 +459,8 @@ public class PeerConnection {
iceCandidatePoolSize = 0;
pruneTurnPorts = false;
presumeWritableWhenFullyRelayed = false;
iceCheckIntervalStrongConnectivityMs = null;
iceCheckIntervalWeakConnectivityMs = null;
iceCheckMinInterval = null;
stunCandidateKeepaliveIntervalMs = null;
disableIPv6OnWifi = false;
@ -529,6 +553,16 @@ public class PeerConnection {
return presumeWritableWhenFullyRelayed;
}
@CalledByNative("RTCConfiguration")
Integer getIceCheckIntervalStrongConnectivity() {
return iceCheckIntervalStrongConnectivityMs;
}
@CalledByNative("RTCConfiguration")
Integer getIceCheckIntervalWeakConnectivity() {
return iceCheckIntervalWeakConnectivityMs;
}
@CalledByNative("RTCConfiguration")
Integer getIceCheckMinInterval() {
return iceCheckMinInterval;

View File

@ -173,6 +173,16 @@ void JavaToNativeRTCConfiguration(
rtc_config->presume_writable_when_fully_relayed =
Java_RTCConfiguration_getPresumeWritableWhenFullyRelayed(jni,
j_rtc_config);
ScopedJavaLocalRef<jobject> j_ice_check_interval_strong_connectivity =
Java_RTCConfiguration_getIceCheckIntervalStrongConnectivity(jni,
j_rtc_config);
rtc_config->ice_check_interval_strong_connectivity =
JavaToNativeOptionalInt(jni, j_ice_check_interval_strong_connectivity);
ScopedJavaLocalRef<jobject> j_ice_check_interval_weak_connectivity =
Java_RTCConfiguration_getIceCheckIntervalWeakConnectivity(jni,
j_rtc_config);
rtc_config->ice_check_interval_weak_connectivity =
JavaToNativeOptionalInt(jni, j_ice_check_interval_weak_connectivity);
ScopedJavaLocalRef<jobject> j_ice_check_min_interval =
Java_RTCConfiguration_getIceCheckMinInterval(jni, j_rtc_config);
rtc_config->ice_check_min_interval =