diff --git a/api/peerconnectioninterface.h b/api/peerconnectioninterface.h index 63912b22e7..9463c34c63 100644 --- a/api/peerconnectioninterface.h +++ b/api/peerconnectioninterface.h @@ -493,6 +493,10 @@ class PeerConnectionInterface : public rtc::RefCountInterface { // (STUN pings), in milliseconds. rtc::Optional ice_check_min_interval; + // The interval in milliseconds at which STUN candidates will resend STUN + // binding requests to keep NAT bindings open. + rtc::Optional stun_candidate_keepalive_interval; + // ICE Periodic Regathering // If set, WebRTC will periodically create and propose candidates without // starting a new ICE generation. The regathering happens continuously with diff --git a/p2p/base/icetransportinternal.h b/p2p/base/icetransportinternal.h index 6888992618..13ba3316d9 100644 --- a/p2p/base/icetransportinternal.h +++ b/p2p/base/icetransportinternal.h @@ -114,6 +114,9 @@ struct IceConfig { // than this, no matter what other settings there are. // Measure in milliseconds. rtc::Optional ice_check_min_interval; + // The interval in milliseconds at which STUN candidates will resend STUN + // binding requests to keep NAT bindings open. + rtc::Optional stun_keepalive_interval; rtc::Optional network_preference; diff --git a/p2p/base/p2ptransportchannel.cc b/p2p/base/p2ptransportchannel.cc index 71af657c3b..2ad4114c27 100644 --- a/p2p/base/p2ptransportchannel.cc +++ b/p2p/base/p2ptransportchannel.cc @@ -541,6 +541,18 @@ void P2PTransportChannel::SetIceConfig(const IceConfig& config) { ? config_.network_preference.value() : 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 { diff --git a/p2p/base/portallocator.cc b/p2p/base/portallocator.cc index 84c1df24da..6ef084ca63 100644 --- a/p2p/base/portallocator.cc +++ b/p2p/base/portallocator.cc @@ -103,7 +103,8 @@ bool PortAllocator::SetConfiguration( const std::vector& turn_servers, int candidate_pool_size, bool prune_turn_ports, - webrtc::TurnCustomizer* turn_customizer) { + webrtc::TurnCustomizer* turn_customizer, + const rtc::Optional& stun_candidate_keepalive_interval) { bool ice_servers_changed = (stun_servers != stun_servers_ || turn_servers != turn_servers_); stun_servers_ = stun_servers; @@ -142,6 +143,16 @@ bool PortAllocator::SetConfiguration( 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, // create new sessions. while (static_cast(pooled_sessions_.size()) < candidate_pool_size_) { diff --git a/p2p/base/portallocator.h b/p2p/base/portallocator.h index 1081448918..f32fa07476 100644 --- a/p2p/base/portallocator.h +++ b/p2p/base/portallocator.h @@ -244,7 +244,12 @@ class PortAllocatorSession : public sigslot::has_slots<> { virtual void RegatherOnFailedNetworks() {} // Re-gathers candidates on all networks. 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& stun_keepalive_interval) {} // 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 @@ -347,7 +352,9 @@ class PortAllocator : public sigslot::has_slots<> { const std::vector& turn_servers, int candidate_pool_size, bool prune_turn_ports, - webrtc::TurnCustomizer* turn_customizer = nullptr); + webrtc::TurnCustomizer* turn_customizer = nullptr, + const rtc::Optional& + stun_candidate_keepalive_interval = rtc::nullopt); 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_; } + const rtc::Optional& stun_candidate_keepalive_interval() const { + return stun_candidate_keepalive_interval_; + } // Sets the network types to ignore. // 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 // all TurnPort(s) created. webrtc::TurnCustomizer* turn_customizer_ = nullptr; + + rtc::Optional stun_candidate_keepalive_interval_; }; } // namespace cricket diff --git a/p2p/base/stunport.cc b/p2p/base/stunport.cc index 69196cf130..2df14b7c62 100644 --- a/p2p/base/stunport.cc +++ b/p2p/base/stunport.cc @@ -317,6 +317,10 @@ ProtocolType UDPPort::GetProtocol() const { return PROTO_UDP; } +void UDPPort::set_stun_keepalive_delay(const rtc::Optional& delay) { + stun_keepalive_delay_ = (delay.has_value() ? delay.value() : KEEPALIVE_DELAY); +} + void UDPPort::OnLocalAddressReady(rtc::AsyncPacketSocket* socket, const rtc::SocketAddress& address) { // When adapter enumeration is disabled and binding to the any address, the diff --git a/p2p/base/stunport.h b/p2p/base/stunport.h index cf45d1df59..eaeea3ae91 100644 --- a/p2p/base/stunport.h +++ b/p2p/base/stunport.h @@ -101,9 +101,7 @@ class UDPPort : public Port { bool SupportsProtocol(const std::string& protocol) const override; ProtocolType GetProtocol() const override; - void set_stun_keepalive_delay(int delay) { - stun_keepalive_delay_ = delay; - } + void set_stun_keepalive_delay(const rtc::Optional& delay); int stun_keepalive_delay() const { return stun_keepalive_delay_; } diff --git a/p2p/client/basicportallocator.cc b/p2p/client/basicportallocator.cc index 86cec8fb34..712d5959a4 100644 --- a/p2p/client/basicportallocator.cc +++ b/p2p/client/basicportallocator.cc @@ -429,6 +429,17 @@ void BasicPortAllocatorSession::Regather( } } +void BasicPortAllocatorSession::SetStunKeepaliveIntervalForReadyPorts( + const rtc::Optional& stun_keepalive_interval) { + auto ports = ReadyPorts(); + for (PortInterface* port : ports) { + if (port->Type() == STUN_PORT_TYPE) { + static_cast(port)->set_stun_keepalive_delay( + stun_keepalive_interval); + } + } +} + std::vector BasicPortAllocatorSession::ReadyPorts() const { std::vector ret; for (const PortData& data : ports_) { @@ -1357,6 +1368,8 @@ void AllocationSequence::CreateStunPorts() { session_->username(), session_->password(), config_->StunServers(), session_->allocator()->origin()); if (port) { + port->set_stun_keepalive_delay( + session_->allocator()->stun_candidate_keepalive_interval()); session_->AddAllocatedPort(port, this, true); // Since StunPort is not created using shared socket, |port| will not be // added to the dequeue. diff --git a/p2p/client/basicportallocator.h b/p2p/client/basicportallocator.h index 23faff1cba..fb74ba5d74 100644 --- a/p2p/client/basicportallocator.h +++ b/p2p/client/basicportallocator.h @@ -127,6 +127,8 @@ class BasicPortAllocatorSession : public PortAllocatorSession, bool CandidatesAllocationDone() const override; void RegatherOnFailedNetworks() override; void RegatherOnAllNetworks() override; + void SetStunKeepaliveIntervalForReadyPorts( + const rtc::Optional& stun_keepalive_interval) override; void PruneAllPorts() override; protected: diff --git a/pc/peerconnection.cc b/pc/peerconnection.cc index 73f79c8a11..f32b478cc3 100644 --- a/pc/peerconnection.cc +++ b/pc/peerconnection.cc @@ -636,6 +636,7 @@ bool PeerConnectionInterface::RTCConfiguration::operator==( bool enable_ice_renomination; bool redetermine_role_on_ice_restart; rtc::Optional ice_check_min_interval; + rtc::Optional stun_candidate_keepalive_interval; rtc::Optional ice_regather_interval_range; webrtc::TurnCustomizer* turn_customizer; SdpSemantics sdp_semantics; @@ -675,6 +676,8 @@ bool PeerConnectionInterface::RTCConfiguration::operator==( enable_ice_renomination == o.enable_ice_renomination && redetermine_role_on_ice_restart == o.redetermine_role_on_ice_restart && ice_check_min_interval == o.ice_check_min_interval && + stun_candidate_keepalive_interval == + o.stun_candidate_keepalive_interval && ice_regather_interval_range == o.ice_regather_interval_range && turn_customizer == o.turn_customizer && sdp_semantics == o.sdp_semantics && @@ -2654,6 +2657,8 @@ 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.stun_candidate_keepalive_interval = + configuration.stun_candidate_keepalive_interval; modified_config.turn_customizer = configuration.turn_customizer; modified_config.network_preference = configuration.network_preference; if (configuration != modified_config) { @@ -2690,7 +2695,8 @@ bool PeerConnection::SetConfiguration(const RTCConfiguration& configuration, stun_servers, turn_servers, modified_config.type, modified_config.ice_candidate_pool_size, 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."; 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 // properties set above. - port_allocator_->SetConfiguration(stun_servers, turn_servers, - configuration.ice_candidate_pool_size, - configuration.prune_turn_ports, - configuration.turn_customizer); + port_allocator_->SetConfiguration( + stun_servers, turn_servers, configuration.ice_candidate_pool_size, + configuration.prune_turn_ports, configuration.turn_customizer, + configuration.stun_candidate_keepalive_interval); return true; } @@ -4407,14 +4413,15 @@ bool PeerConnection::ReconfigurePortAllocator_n( IceTransportsType type, int candidate_pool_size, bool prune_turn_ports, - webrtc::TurnCustomizer* turn_customizer) { + webrtc::TurnCustomizer* turn_customizer, + rtc::Optional stun_candidate_keepalive_interval) { port_allocator_->set_candidate_filter( ConvertIceTransportTypeToCandidateFilter(type)); // Call this last since it may create pooled allocator sessions using the // candidate filter set above. return port_allocator_->SetConfiguration( stun_servers, turn_servers, candidate_pool_size, prune_turn_ports, - turn_customizer); + turn_customizer, stun_candidate_keepalive_interval); } cricket::ChannelManager* PeerConnection::channel_manager() const { @@ -4778,6 +4785,7 @@ cricket::IceConfig PeerConnection::ParseIceConfig( ice_config.presume_writable_when_fully_relayed = config.presume_writable_when_fully_relayed; ice_config.ice_check_min_interval = config.ice_check_min_interval; + ice_config.stun_keepalive_interval = config.stun_candidate_keepalive_interval; ice_config.regather_all_networks_interval_range = config.ice_regather_interval_range; ice_config.network_preference = config.network_preference; diff --git a/pc/peerconnection.h b/pc/peerconnection.h index 3eccb96b96..d788b1e76d 100644 --- a/pc/peerconnection.h +++ b/pc/peerconnection.h @@ -661,7 +661,8 @@ class PeerConnection : public PeerConnectionInternal, IceTransportsType type, int candidate_pool_size, bool prune_turn_ports, - webrtc::TurnCustomizer* turn_customizer); + webrtc::TurnCustomizer* turn_customizer, + rtc::Optional stun_candidate_keepalive_interval); // Starts output of an RTC event log to the given output object. // This function should only be called from the worker thread. diff --git a/sdk/android/api/org/webrtc/PeerConnection.java b/sdk/android/api/org/webrtc/PeerConnection.java index c6598b76d1..de1e57d787 100644 --- a/sdk/android/api/org/webrtc/PeerConnection.java +++ b/sdk/android/api/org/webrtc/PeerConnection.java @@ -342,6 +342,7 @@ public class PeerConnection { } /** Java version of PeerConnectionInterface.RTCConfiguration */ + // TODO(qingsi): Resolve the naming inconsistency of fields with/without units. public static class RTCConfiguration { public IceTransportsType iceTransportsType; public List iceServers; @@ -359,6 +360,10 @@ public class PeerConnection { public boolean pruneTurnPorts; public boolean presumeWritableWhenFullyRelayed; 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; // By default, PeerConnection will use a limited number of IPv6 network // interfaces, in order to avoid too many ICE candidate pairs being created @@ -405,6 +410,7 @@ public class PeerConnection { pruneTurnPorts = false; presumeWritableWhenFullyRelayed = false; iceCheckMinInterval = null; + stunCandidateKeepaliveIntervalMs = null; disableIPv6OnWifi = false; maxIPv6Networks = 5; iceRegatherIntervalRange = null; @@ -499,6 +505,11 @@ public class PeerConnection { return iceCheckMinInterval; } + @CalledByNative("RTCConfiguration") + Integer getStunCandidateKeepaliveInterval() { + return stunCandidateKeepaliveIntervalMs; + } + @CalledByNative("RTCConfiguration") boolean getDisableIPv6OnWifi() { return disableIPv6OnWifi; diff --git a/sdk/android/src/jni/pc/peerconnection.cc b/sdk/android/src/jni/pc/peerconnection.cc index f6f3932fa5..f954a4330c 100644 --- a/sdk/android/src/jni/pc/peerconnection.cc +++ b/sdk/android/src/jni/pc/peerconnection.cc @@ -156,6 +156,11 @@ void JavaToNativeRTCConfiguration( Java_RTCConfiguration_getIceCheckMinInterval(jni, j_rtc_config); rtc_config->ice_check_min_interval = JavaToNativeOptionalInt(jni, j_ice_check_min_interval); + ScopedJavaLocalRef 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 = Java_RTCConfiguration_getDisableIPv6OnWifi(jni, j_rtc_config); rtc_config->max_ipv6_networks =