Add configurable STUN binding request interval.

STUN candidates use STUN binding requests to keep NAT bindings open. The
interval at which the STUN keepalive pings are sent is configurable now
via RTCConfiguration.

TBR=sakal@webrtc.org

Bug: None
Change-Id: I5f99ea3fe1e9042fa2bf7dcab0aace78f57739e6
Reviewed-on: https://webrtc-review.googlesource.com/54180
Commit-Queue: Qingsi Wang <qingsi@google.com>
Reviewed-by: Taylor Brandstetter <deadbeef@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#22109}
This commit is contained in:
Qingsi Wang
2018-02-20 14:45:49 -08:00
committed by Commit Bot
parent ed1eceaba5
commit db53f8e604
13 changed files with 98 additions and 14 deletions

View File

@ -493,6 +493,10 @@ 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;
// The interval in milliseconds at which STUN candidates will resend STUN
// binding requests to keep NAT bindings open.
rtc::Optional<int> stun_candidate_keepalive_interval;
// ICE Periodic Regathering // ICE Periodic Regathering
// If set, WebRTC will periodically create and propose candidates without // If set, WebRTC will periodically create and propose candidates without
// starting a new ICE generation. The regathering happens continuously with // starting a new ICE generation. The regathering happens continuously with

View File

@ -114,6 +114,9 @@ struct IceConfig {
// than this, no matter what other settings there are. // than this, no matter what other settings there are.
// Measure in milliseconds. // Measure in milliseconds.
rtc::Optional<int> ice_check_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.
rtc::Optional<int> stun_keepalive_interval;
rtc::Optional<rtc::AdapterType> network_preference; rtc::Optional<rtc::AdapterType> network_preference;

View File

@ -541,6 +541,18 @@ void P2PTransportChannel::SetIceConfig(const IceConfig& config) {
? config_.network_preference.value() ? config_.network_preference.value()
: 0); : 0);
} }
// TODO(qingsi): Resolve the naming conflict of stun_keepalive_delay in
// UDPPort and stun_keepalive_interval.
if (config_.stun_keepalive_interval != config.stun_keepalive_interval) {
config_.stun_keepalive_interval = config.stun_keepalive_interval;
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);
}
} }
const IceConfig& P2PTransportChannel::config() const { const IceConfig& P2PTransportChannel::config() const {

View File

@ -103,7 +103,8 @@ bool PortAllocator::SetConfiguration(
const std::vector<RelayServerConfig>& turn_servers, const std::vector<RelayServerConfig>& turn_servers,
int candidate_pool_size, int candidate_pool_size,
bool prune_turn_ports, bool prune_turn_ports,
webrtc::TurnCustomizer* turn_customizer) { webrtc::TurnCustomizer* turn_customizer,
const rtc::Optional<int>& stun_candidate_keepalive_interval) {
bool ice_servers_changed = bool ice_servers_changed =
(stun_servers != stun_servers_ || turn_servers != turn_servers_); (stun_servers != stun_servers_ || turn_servers != turn_servers_);
stun_servers_ = stun_servers; stun_servers_ = stun_servers;
@ -142,6 +143,16 @@ bool PortAllocator::SetConfiguration(
pooled_sessions_.pop_front(); pooled_sessions_.pop_front();
} }
// |stun_candidate_keepalive_interval_| will be used in STUN port allocation
// in future sessions. We also update the ready ports in the pooled sessions.
// Ports in sessions that are taken and owned by P2PTransportChannel will be
// updated there via IceConfig.
stun_candidate_keepalive_interval_ = stun_candidate_keepalive_interval;
for (const auto& session : pooled_sessions_) {
session->SetStunKeepaliveIntervalForReadyPorts(
stun_candidate_keepalive_interval_);
}
// If |candidate_pool_size_| is greater than the number of pooled sessions, // If |candidate_pool_size_| is greater than the number of pooled sessions,
// create new sessions. // create new sessions.
while (static_cast<int>(pooled_sessions_.size()) < candidate_pool_size_) { while (static_cast<int>(pooled_sessions_.size()) < candidate_pool_size_) {

View File

@ -244,7 +244,12 @@ class PortAllocatorSession : public sigslot::has_slots<> {
virtual void RegatherOnFailedNetworks() {} virtual void RegatherOnFailedNetworks() {}
// Re-gathers candidates on all networks. // Re-gathers candidates on all networks.
virtual void RegatherOnAllNetworks() {} virtual void RegatherOnAllNetworks() {}
// Set the interval at which STUN candidates will resend STUN binding requests
// on the underlying ports to keep NAT bindings open.
// The default value of the interval in implementation is restored if a null
// optional value is passed.
virtual void SetStunKeepaliveIntervalForReadyPorts(
const rtc::Optional<int>& stun_keepalive_interval) {}
// Another way of getting the information provided by the signals below. // Another way of getting the information provided by the signals below.
// //
// Ports and candidates are not guaranteed to be in the same order as the // Ports and candidates are not guaranteed to be in the same order as the
@ -347,7 +352,9 @@ class PortAllocator : public sigslot::has_slots<> {
const std::vector<RelayServerConfig>& turn_servers, const std::vector<RelayServerConfig>& turn_servers,
int candidate_pool_size, int candidate_pool_size,
bool prune_turn_ports, bool prune_turn_ports,
webrtc::TurnCustomizer* turn_customizer = nullptr); webrtc::TurnCustomizer* turn_customizer = nullptr,
const rtc::Optional<int>&
stun_candidate_keepalive_interval = rtc::nullopt);
const ServerAddresses& stun_servers() const { return stun_servers_; } const ServerAddresses& stun_servers() const { return stun_servers_; }
@ -356,6 +363,9 @@ class PortAllocator : public sigslot::has_slots<> {
} }
int candidate_pool_size() const { return candidate_pool_size_; } int candidate_pool_size() const { return candidate_pool_size_; }
const rtc::Optional<int>& stun_candidate_keepalive_interval() const {
return stun_candidate_keepalive_interval_;
}
// Sets the network types to ignore. // Sets the network types to ignore.
// Values are defined by the AdapterType enum. // Values are defined by the AdapterType enum.
@ -506,6 +516,8 @@ class PortAllocator : public sigslot::has_slots<> {
// The instance is owned by application and will be shared among // The instance is owned by application and will be shared among
// all TurnPort(s) created. // all TurnPort(s) created.
webrtc::TurnCustomizer* turn_customizer_ = nullptr; webrtc::TurnCustomizer* turn_customizer_ = nullptr;
rtc::Optional<int> stun_candidate_keepalive_interval_;
}; };
} // namespace cricket } // namespace cricket

View File

@ -317,6 +317,10 @@ ProtocolType UDPPort::GetProtocol() const {
return PROTO_UDP; return PROTO_UDP;
} }
void UDPPort::set_stun_keepalive_delay(const rtc::Optional<int>& delay) {
stun_keepalive_delay_ = (delay.has_value() ? delay.value() : KEEPALIVE_DELAY);
}
void UDPPort::OnLocalAddressReady(rtc::AsyncPacketSocket* socket, void UDPPort::OnLocalAddressReady(rtc::AsyncPacketSocket* socket,
const rtc::SocketAddress& address) { const rtc::SocketAddress& address) {
// When adapter enumeration is disabled and binding to the any address, the // When adapter enumeration is disabled and binding to the any address, the

View File

@ -101,9 +101,7 @@ class UDPPort : public Port {
bool SupportsProtocol(const std::string& protocol) const override; bool SupportsProtocol(const std::string& protocol) const override;
ProtocolType GetProtocol() const override; ProtocolType GetProtocol() const override;
void set_stun_keepalive_delay(int delay) { void set_stun_keepalive_delay(const rtc::Optional<int>& delay);
stun_keepalive_delay_ = delay;
}
int stun_keepalive_delay() const { int stun_keepalive_delay() const {
return stun_keepalive_delay_; return stun_keepalive_delay_;
} }

View File

@ -429,6 +429,17 @@ void BasicPortAllocatorSession::Regather(
} }
} }
void BasicPortAllocatorSession::SetStunKeepaliveIntervalForReadyPorts(
const rtc::Optional<int>& stun_keepalive_interval) {
auto ports = ReadyPorts();
for (PortInterface* port : ports) {
if (port->Type() == STUN_PORT_TYPE) {
static_cast<UDPPort*>(port)->set_stun_keepalive_delay(
stun_keepalive_interval);
}
}
}
std::vector<PortInterface*> BasicPortAllocatorSession::ReadyPorts() const { std::vector<PortInterface*> BasicPortAllocatorSession::ReadyPorts() const {
std::vector<PortInterface*> ret; std::vector<PortInterface*> ret;
for (const PortData& data : ports_) { for (const PortData& data : ports_) {
@ -1357,6 +1368,8 @@ void AllocationSequence::CreateStunPorts() {
session_->username(), session_->password(), config_->StunServers(), session_->username(), session_->password(), config_->StunServers(),
session_->allocator()->origin()); session_->allocator()->origin());
if (port) { if (port) {
port->set_stun_keepalive_delay(
session_->allocator()->stun_candidate_keepalive_interval());
session_->AddAllocatedPort(port, this, true); session_->AddAllocatedPort(port, this, true);
// Since StunPort is not created using shared socket, |port| will not be // Since StunPort is not created using shared socket, |port| will not be
// added to the dequeue. // added to the dequeue.

View File

@ -127,6 +127,8 @@ class BasicPortAllocatorSession : public PortAllocatorSession,
bool CandidatesAllocationDone() const override; bool CandidatesAllocationDone() const override;
void RegatherOnFailedNetworks() override; void RegatherOnFailedNetworks() override;
void RegatherOnAllNetworks() override; void RegatherOnAllNetworks() override;
void SetStunKeepaliveIntervalForReadyPorts(
const rtc::Optional<int>& stun_keepalive_interval) override;
void PruneAllPorts() override; void PruneAllPorts() override;
protected: protected:

View File

@ -636,6 +636,7 @@ bool PeerConnectionInterface::RTCConfiguration::operator==(
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<int> stun_candidate_keepalive_interval;
rtc::Optional<rtc::IntervalRange> ice_regather_interval_range; rtc::Optional<rtc::IntervalRange> ice_regather_interval_range;
webrtc::TurnCustomizer* turn_customizer; webrtc::TurnCustomizer* turn_customizer;
SdpSemantics sdp_semantics; SdpSemantics sdp_semantics;
@ -675,6 +676,8 @@ bool PeerConnectionInterface::RTCConfiguration::operator==(
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 &&
stun_candidate_keepalive_interval ==
o.stun_candidate_keepalive_interval &&
ice_regather_interval_range == o.ice_regather_interval_range && ice_regather_interval_range == o.ice_regather_interval_range &&
turn_customizer == o.turn_customizer && turn_customizer == o.turn_customizer &&
sdp_semantics == o.sdp_semantics && sdp_semantics == o.sdp_semantics &&
@ -2654,6 +2657,8 @@ bool PeerConnection::SetConfiguration(const RTCConfiguration& configuration,
configuration.ice_candidate_pool_size; configuration.ice_candidate_pool_size;
modified_config.prune_turn_ports = configuration.prune_turn_ports; modified_config.prune_turn_ports = configuration.prune_turn_ports;
modified_config.ice_check_min_interval = configuration.ice_check_min_interval; modified_config.ice_check_min_interval = configuration.ice_check_min_interval;
modified_config.stun_candidate_keepalive_interval =
configuration.stun_candidate_keepalive_interval;
modified_config.turn_customizer = configuration.turn_customizer; modified_config.turn_customizer = configuration.turn_customizer;
modified_config.network_preference = configuration.network_preference; modified_config.network_preference = configuration.network_preference;
if (configuration != modified_config) { if (configuration != modified_config) {
@ -2690,7 +2695,8 @@ bool PeerConnection::SetConfiguration(const RTCConfiguration& configuration,
stun_servers, turn_servers, modified_config.type, stun_servers, turn_servers, modified_config.type,
modified_config.ice_candidate_pool_size, modified_config.ice_candidate_pool_size,
modified_config.prune_turn_ports, modified_config.prune_turn_ports,
modified_config.turn_customizer))) { modified_config.turn_customizer,
modified_config.stun_candidate_keepalive_interval))) {
RTC_LOG(LS_ERROR) << "Failed to apply configuration to PortAllocator."; RTC_LOG(LS_ERROR) << "Failed to apply configuration to PortAllocator.";
return SafeSetError(RTCErrorType::INTERNAL_ERROR, error); return SafeSetError(RTCErrorType::INTERNAL_ERROR, error);
} }
@ -4394,10 +4400,10 @@ bool PeerConnection::InitializePortAllocator_n(
// Call this last since it may create pooled allocator sessions using the // Call this last since it may create pooled allocator sessions using the
// properties set above. // properties set above.
port_allocator_->SetConfiguration(stun_servers, turn_servers, port_allocator_->SetConfiguration(
configuration.ice_candidate_pool_size, stun_servers, turn_servers, configuration.ice_candidate_pool_size,
configuration.prune_turn_ports, configuration.prune_turn_ports, configuration.turn_customizer,
configuration.turn_customizer); configuration.stun_candidate_keepalive_interval);
return true; return true;
} }
@ -4407,14 +4413,15 @@ bool PeerConnection::ReconfigurePortAllocator_n(
IceTransportsType type, IceTransportsType type,
int candidate_pool_size, int candidate_pool_size,
bool prune_turn_ports, bool prune_turn_ports,
webrtc::TurnCustomizer* turn_customizer) { webrtc::TurnCustomizer* turn_customizer,
rtc::Optional<int> stun_candidate_keepalive_interval) {
port_allocator_->set_candidate_filter( port_allocator_->set_candidate_filter(
ConvertIceTransportTypeToCandidateFilter(type)); ConvertIceTransportTypeToCandidateFilter(type));
// Call this last since it may create pooled allocator sessions using the // Call this last since it may create pooled allocator sessions using the
// candidate filter set above. // candidate filter set above.
return port_allocator_->SetConfiguration( return port_allocator_->SetConfiguration(
stun_servers, turn_servers, candidate_pool_size, prune_turn_ports, stun_servers, turn_servers, candidate_pool_size, prune_turn_ports,
turn_customizer); turn_customizer, stun_candidate_keepalive_interval);
} }
cricket::ChannelManager* PeerConnection::channel_manager() const { cricket::ChannelManager* PeerConnection::channel_manager() const {
@ -4778,6 +4785,7 @@ cricket::IceConfig PeerConnection::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.stun_keepalive_interval = config.stun_candidate_keepalive_interval;
ice_config.regather_all_networks_interval_range = ice_config.regather_all_networks_interval_range =
config.ice_regather_interval_range; config.ice_regather_interval_range;
ice_config.network_preference = config.network_preference; ice_config.network_preference = config.network_preference;

View File

@ -661,7 +661,8 @@ class PeerConnection : public PeerConnectionInternal,
IceTransportsType type, IceTransportsType type,
int candidate_pool_size, int candidate_pool_size,
bool prune_turn_ports, bool prune_turn_ports,
webrtc::TurnCustomizer* turn_customizer); webrtc::TurnCustomizer* turn_customizer,
rtc::Optional<int> stun_candidate_keepalive_interval);
// Starts output of an RTC event log to the given output object. // Starts output of an RTC event log to the given output object.
// This function should only be called from the worker thread. // This function should only be called from the worker thread.

View File

@ -342,6 +342,7 @@ public class PeerConnection {
} }
/** Java version of PeerConnectionInterface.RTCConfiguration */ /** Java version of PeerConnectionInterface.RTCConfiguration */
// TODO(qingsi): Resolve the naming inconsistency of fields with/without units.
public static class RTCConfiguration { public static class RTCConfiguration {
public IceTransportsType iceTransportsType; public IceTransportsType iceTransportsType;
public List<IceServer> iceServers; public List<IceServer> iceServers;
@ -359,6 +360,10 @@ public class PeerConnection {
public boolean pruneTurnPorts; public boolean pruneTurnPorts;
public boolean presumeWritableWhenFullyRelayed; public boolean presumeWritableWhenFullyRelayed;
public Integer iceCheckMinInterval; public Integer iceCheckMinInterval;
// The interval in milliseconds at which STUN candidates will resend STUN binding requests
// to keep NAT bindings open.
// The default value in the implementation is used if this field is null.
public Integer stunCandidateKeepaliveIntervalMs;
public boolean disableIPv6OnWifi; public boolean disableIPv6OnWifi;
// By default, PeerConnection will use a limited number of IPv6 network // By default, PeerConnection will use a limited number of IPv6 network
// interfaces, in order to avoid too many ICE candidate pairs being created // interfaces, in order to avoid too many ICE candidate pairs being created
@ -405,6 +410,7 @@ public class PeerConnection {
pruneTurnPorts = false; pruneTurnPorts = false;
presumeWritableWhenFullyRelayed = false; presumeWritableWhenFullyRelayed = false;
iceCheckMinInterval = null; iceCheckMinInterval = null;
stunCandidateKeepaliveIntervalMs = null;
disableIPv6OnWifi = false; disableIPv6OnWifi = false;
maxIPv6Networks = 5; maxIPv6Networks = 5;
iceRegatherIntervalRange = null; iceRegatherIntervalRange = null;
@ -499,6 +505,11 @@ public class PeerConnection {
return iceCheckMinInterval; return iceCheckMinInterval;
} }
@CalledByNative("RTCConfiguration")
Integer getStunCandidateKeepaliveInterval() {
return stunCandidateKeepaliveIntervalMs;
}
@CalledByNative("RTCConfiguration") @CalledByNative("RTCConfiguration")
boolean getDisableIPv6OnWifi() { boolean getDisableIPv6OnWifi() {
return disableIPv6OnWifi; return disableIPv6OnWifi;

View File

@ -156,6 +156,11 @@ void JavaToNativeRTCConfiguration(
Java_RTCConfiguration_getIceCheckMinInterval(jni, j_rtc_config); Java_RTCConfiguration_getIceCheckMinInterval(jni, j_rtc_config);
rtc_config->ice_check_min_interval = rtc_config->ice_check_min_interval =
JavaToNativeOptionalInt(jni, j_ice_check_min_interval); JavaToNativeOptionalInt(jni, j_ice_check_min_interval);
ScopedJavaLocalRef<jobject> j_stun_candidate_keepalive_interval =
Java_RTCConfiguration_getStunCandidateKeepaliveInterval(jni,
j_rtc_config);
rtc_config->stun_candidate_keepalive_interval =
JavaToNativeOptionalInt(jni, j_stun_candidate_keepalive_interval);
rtc_config->disable_ipv6_on_wifi = rtc_config->disable_ipv6_on_wifi =
Java_RTCConfiguration_getDisableIPv6OnWifi(jni, j_rtc_config); Java_RTCConfiguration_getDisableIPv6OnWifi(jni, j_rtc_config);
rtc_config->max_ipv6_networks = rtc_config->max_ipv6_networks =