Add a configuration parameter for using the media transport for data channels.

Adds a field |use_media_transport_for_data_channels| to RTCConfiguration.
PeerConnection requires a media transport factory to be set if this bit
is set.  As with |use_media_transport|, the value may not be modified
after setting the local or remote description.

If either |use_media_transport| or |use_media_transport_for_data_channel| is
set, PeerConnection uses its media transport factory when creating a JSEP
transport controller.

PeerConnection stops unconditionally using media transport in
CreateVoiceChannel, as it may be present only for use in data channels.  It uses
the media transport if it is present and |use_media_transport| is set.

Bug: webrtc:9719
Change-Id: I59d4ce8f7531fd19d9c17eefe033f063f663ebcc
Reviewed-on: https://webrtc-review.googlesource.com/c/109041
Reviewed-by: Sami Kalliomäki <sakal@webrtc.org>
Reviewed-by: Kári Helgason <kthelgason@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Reviewed-by: Peter Slatala <psla@webrtc.org>
Commit-Queue: Bjorn Mellem <mellem@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#25507}
This commit is contained in:
Bjorn Mellem
2018-11-02 09:07:48 -07:00
committed by Commit Bot
parent 41b5296405
commit a9bbd86849
9 changed files with 141 additions and 7 deletions

View File

@ -583,6 +583,15 @@ class PeerConnectionInterface : public rtc::RefCountInterface {
// provided. // provided.
bool use_media_transport = false; bool use_media_transport = false;
// If MediaTransportFactory is provided in PeerConnectionFactory, this flag
// informs PeerConnection that it should use the MediaTransportInterface for
// data channels. It's invalid to set it to |true| if the
// MediaTransportFactory wasn't provided. Data channels over media
// transport are not compatible with RTP or SCTP data channels. Setting
// both |use_media_transport_for_data_channels| and
// |enable_rtp_data_channel| is invalid.
bool use_media_transport_for_data_channels = false;
// Defines advanced optional cryptographic settings related to SRTP and // Defines advanced optional cryptographic settings related to SRTP and
// frame encryption for native WebRTC. Setting this will overwrite any // frame encryption for native WebRTC. Setting this will overwrite any
// settings set in PeerConnectionFactory (which is deprecated). // settings set in PeerConnectionFactory (which is deprecated).

View File

@ -706,6 +706,7 @@ bool PeerConnectionInterface::RTCConfiguration::operator==(
absl::optional<rtc::AdapterType> network_preference; absl::optional<rtc::AdapterType> network_preference;
bool active_reset_srtp_params; bool active_reset_srtp_params;
bool use_media_transport; bool use_media_transport;
bool use_media_transport_for_data_channels;
absl::optional<CryptoOptions> crypto_options; absl::optional<CryptoOptions> crypto_options;
}; };
static_assert(sizeof(stuff_being_tested_for_equality) == sizeof(*this), static_assert(sizeof(stuff_being_tested_for_equality) == sizeof(*this),
@ -756,6 +757,8 @@ bool PeerConnectionInterface::RTCConfiguration::operator==(
network_preference == o.network_preference && network_preference == o.network_preference &&
active_reset_srtp_params == o.active_reset_srtp_params && active_reset_srtp_params == o.active_reset_srtp_params &&
use_media_transport == o.use_media_transport && use_media_transport == o.use_media_transport &&
use_media_transport_for_data_channels ==
o.use_media_transport_for_data_channels &&
crypto_options == o.crypto_options; crypto_options == o.crypto_options;
} }
@ -946,11 +949,13 @@ bool PeerConnection::Initialize(
#endif #endif
config.active_reset_srtp_params = configuration.active_reset_srtp_params; config.active_reset_srtp_params = configuration.active_reset_srtp_params;
if (configuration.use_media_transport) { if (configuration.use_media_transport ||
configuration.use_media_transport_for_data_channels) {
if (!factory_->media_transport_factory()) { if (!factory_->media_transport_factory()) {
RTC_DCHECK(false) RTC_DCHECK(false)
<< "PeerConnecton is initialized with use_media_transport = true, " << "PeerConnecton is initialized with use_media_transport = true or "
<< "but media transport factory is not set in PeerConnectioFactory"; << "use_media_transport_for_data_channels = true "
<< "but media transport factory is not set in PeerConnectionFactory";
return false; return false;
} }
@ -2919,6 +2924,22 @@ bool PeerConnection::SetConfiguration(const RTCConfiguration& configuration,
return SafeSetError(RTCErrorType::INVALID_MODIFICATION, error); return SafeSetError(RTCErrorType::INVALID_MODIFICATION, error);
} }
if (local_description() &&
configuration.use_media_transport_for_data_channels !=
configuration_.use_media_transport_for_data_channels) {
RTC_LOG(LS_ERROR) << "Can't change media_transport_for_data_channels "
"after calling SetLocalDescription.";
return SafeSetError(RTCErrorType::INVALID_MODIFICATION, error);
}
if (remote_description() &&
configuration.use_media_transport_for_data_channels !=
configuration_.use_media_transport_for_data_channels) {
RTC_LOG(LS_ERROR) << "Can't change media_transport_for_data_channels "
"after calling SetRemoteDescription.";
return SafeSetError(RTCErrorType::INVALID_MODIFICATION, error);
}
if (local_description() && if (local_description() &&
configuration.crypto_options != configuration_.crypto_options) { configuration.crypto_options != configuration_.crypto_options) {
RTC_LOG(LS_ERROR) << "Can't change crypto_options after calling " RTC_LOG(LS_ERROR) << "Can't change crypto_options after calling "
@ -2951,6 +2972,8 @@ bool PeerConnection::SetConfiguration(const RTCConfiguration& configuration,
modified_config.active_reset_srtp_params = modified_config.active_reset_srtp_params =
configuration.active_reset_srtp_params; configuration.active_reset_srtp_params;
modified_config.use_media_transport = configuration.use_media_transport; modified_config.use_media_transport = configuration.use_media_transport;
modified_config.use_media_transport_for_data_channels =
configuration.use_media_transport_for_data_channels;
if (configuration != modified_config) { if (configuration != modified_config) {
RTC_LOG(LS_ERROR) << "Modifying the configuration in an unsupported way."; RTC_LOG(LS_ERROR) << "Modifying the configuration in an unsupported way.";
return SafeSetError(RTCErrorType::INVALID_MODIFICATION, error); return SafeSetError(RTCErrorType::INVALID_MODIFICATION, error);
@ -3009,7 +3032,9 @@ bool PeerConnection::SetConfiguration(const RTCConfiguration& configuration,
transport_controller_->SetIceConfig(ParseIceConfig(modified_config)); transport_controller_->SetIceConfig(ParseIceConfig(modified_config));
transport_controller_->SetMediaTransportFactory( transport_controller_->SetMediaTransportFactory(
modified_config.use_media_transport ? factory_->media_transport_factory() modified_config.use_media_transport ||
modified_config.use_media_transport_for_data_channels
? factory_->media_transport_factory()
: nullptr); : nullptr);
if (configuration_.active_reset_srtp_params != if (configuration_.active_reset_srtp_params !=
@ -5597,7 +5622,10 @@ RTCError PeerConnection::CreateChannels(const SessionDescription& desc) {
cricket::VoiceChannel* PeerConnection::CreateVoiceChannel( cricket::VoiceChannel* PeerConnection::CreateVoiceChannel(
const std::string& mid) { const std::string& mid) {
RtpTransportInternal* rtp_transport = GetRtpTransport(mid); RtpTransportInternal* rtp_transport = GetRtpTransport(mid);
MediaTransportInterface* media_transport = GetMediaTransport(mid); MediaTransportInterface* media_transport = nullptr;
if (configuration_.use_media_transport) {
media_transport = GetMediaTransport(mid);
}
cricket::VoiceChannel* voice_channel = channel_manager()->CreateVoiceChannel( cricket::VoiceChannel* voice_channel = channel_manager()->CreateVoiceChannel(
call_.get(), configuration_.media_config, rtp_transport, media_transport, call_.get(), configuration_.media_config, rtp_transport, media_transport,

View File

@ -938,10 +938,13 @@ class PeerConnection : public PeerConnectionInternal,
// to use media transport. Otherwise returns nullptr. // to use media transport. Otherwise returns nullptr.
MediaTransportInterface* GetMediaTransport(const std::string& mid) { MediaTransportInterface* GetMediaTransport(const std::string& mid) {
auto media_transport = transport_controller_->GetMediaTransport(mid); auto media_transport = transport_controller_->GetMediaTransport(mid);
RTC_DCHECK(configuration_.use_media_transport == RTC_DCHECK((configuration_.use_media_transport ||
configuration_.use_media_transport_for_data_channels) ==
(media_transport != nullptr)) (media_transport != nullptr))
<< "configuration_.use_media_transport=" << "configuration_.use_media_transport="
<< configuration_.use_media_transport << configuration_.use_media_transport
<< ", configuration_.use_media_transport_for_data_channels="
<< configuration_.use_media_transport_for_data_channels
<< ", (media_transport != nullptr)=" << (media_transport != nullptr); << ", (media_transport != nullptr)=" << (media_transport != nullptr);
return media_transport; return media_transport;
} }

View File

@ -1129,6 +1129,74 @@ TEST_P(PeerConnectionMediaTest, MediaTransportPropagatedToVoiceEngine) {
ASSERT_EQ(nullptr, callee_video->media_transport()); ASSERT_EQ(nullptr, callee_video->media_transport());
} }
TEST_P(PeerConnectionMediaTest, MediaTransportOnlyForDataChannels) {
RTCConfiguration config;
// Setup PeerConnection to use media transport for data channels.
config.use_media_transport_for_data_channels = true;
// Force SDES.
config.enable_dtls_srtp = false;
auto caller = CreatePeerConnectionWithAudioVideo(config);
auto callee = CreatePeerConnectionWithAudioVideo(config);
ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
ASSERT_TRUE(callee->SetLocalDescription(callee->CreateAnswer()));
auto caller_voice = caller->media_engine()->GetVoiceChannel(0);
auto callee_voice = callee->media_engine()->GetVoiceChannel(0);
ASSERT_TRUE(caller_voice);
ASSERT_TRUE(callee_voice);
// Make sure media transport is not propagated to voice channel.
EXPECT_EQ(nullptr, caller_voice->media_transport());
EXPECT_EQ(nullptr, callee_voice->media_transport());
}
TEST_P(PeerConnectionMediaTest, MediaTransportForMediaAndDataChannels) {
RTCConfiguration config;
// Setup PeerConnection to use media transport for both media and data
// channels.
config.use_media_transport = true;
config.use_media_transport_for_data_channels = true;
// Force SDES.
config.enable_dtls_srtp = false;
auto caller = CreatePeerConnectionWithAudioVideo(config);
auto callee = CreatePeerConnectionWithAudioVideo(config);
ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
ASSERT_TRUE(callee->SetLocalDescription(callee->CreateAnswer()));
auto caller_voice = caller->media_engine()->GetVoiceChannel(0);
auto callee_voice = callee->media_engine()->GetVoiceChannel(0);
ASSERT_TRUE(caller_voice);
ASSERT_TRUE(callee_voice);
// Make sure media transport is propagated to voice channel.
FakeMediaTransport* caller_voice_media_transport =
static_cast<FakeMediaTransport*>(caller_voice->media_transport());
FakeMediaTransport* callee_voice_media_transport =
static_cast<FakeMediaTransport*>(callee_voice->media_transport());
ASSERT_NE(nullptr, caller_voice_media_transport);
ASSERT_NE(nullptr, callee_voice_media_transport);
// Make sure media transport is created with correct is_caller.
EXPECT_TRUE(caller_voice_media_transport->is_caller());
EXPECT_FALSE(callee_voice_media_transport->is_caller());
// TODO(sukhanov): Propagate media transport to video channel. This test
// will fail once media transport is propagated to video channel and it will
// serve as a reminder to add a test for video channel propagation.
auto caller_video = caller->media_engine()->GetVideoChannel(0);
auto callee_video = callee->media_engine()->GetVideoChannel(0);
ASSERT_EQ(nullptr, caller_video->media_transport());
ASSERT_EQ(nullptr, callee_video->media_transport());
}
TEST_P(PeerConnectionMediaTest, MediaTransportNotPropagatedToVoiceEngine) { TEST_P(PeerConnectionMediaTest, MediaTransportNotPropagatedToVoiceEngine) {
auto caller = CreatePeerConnectionWithAudioVideo(); auto caller = CreatePeerConnectionWithAudioVideo();
auto callee = CreatePeerConnectionWithAudioVideo(); auto callee = CreatePeerConnectionWithAudioVideo();

View File

@ -1431,12 +1431,14 @@ TEST_P(PeerConnectionInterfaceTest, GetConfigurationAfterSetConfiguration) {
PeerConnectionInterface::RTCConfiguration config = pc_->GetConfiguration(); PeerConnectionInterface::RTCConfiguration config = pc_->GetConfiguration();
config.type = PeerConnectionInterface::kRelay; config.type = PeerConnectionInterface::kRelay;
config.use_media_transport = true; config.use_media_transport = true;
config.use_media_transport_for_data_channels = true;
EXPECT_TRUE(pc_->SetConfiguration(config)); EXPECT_TRUE(pc_->SetConfiguration(config));
PeerConnectionInterface::RTCConfiguration returned_config = PeerConnectionInterface::RTCConfiguration returned_config =
pc_->GetConfiguration(); pc_->GetConfiguration();
EXPECT_EQ(PeerConnectionInterface::kRelay, returned_config.type); EXPECT_EQ(PeerConnectionInterface::kRelay, returned_config.type);
EXPECT_TRUE(returned_config.use_media_transport); EXPECT_TRUE(returned_config.use_media_transport);
EXPECT_TRUE(returned_config.use_media_transport_for_data_channels);
} }
TEST_P(PeerConnectionInterfaceTest, SetConfigurationFailsAfterClose) { TEST_P(PeerConnectionInterfaceTest, SetConfigurationFailsAfterClose) {

View File

@ -468,6 +468,12 @@ public class PeerConnection {
*/ */
public boolean useMediaTransport; public boolean useMediaTransport;
/*
* Experimental flag that enables a use of media transport for data channels. If this is true,
* the media transport factory MUST be provided to the PeerConnectionFactory.
*/
public boolean useMediaTransportForDataChannels;
/** /**
* Defines advanced optional cryptographic settings related to SRTP and * Defines advanced optional cryptographic settings related to SRTP and
* frame encryption for native WebRTC. Setting this will overwrite any * frame encryption for native WebRTC. Setting this will overwrite any
@ -515,6 +521,7 @@ public class PeerConnection {
sdpSemantics = SdpSemantics.PLAN_B; sdpSemantics = SdpSemantics.PLAN_B;
activeResetSrtpParams = false; activeResetSrtpParams = false;
useMediaTransport = false; useMediaTransport = false;
useMediaTransportForDataChannels = false;
cryptoOptions = null; cryptoOptions = null;
} }
@ -720,6 +727,11 @@ public class PeerConnection {
return useMediaTransport; return useMediaTransport;
} }
@CalledByNative("RTCConfiguration")
boolean getUseMediaTransportForDataChannels() {
return useMediaTransportForDataChannels;
}
@Nullable @Nullable
@CalledByNative("RTCConfiguration") @CalledByNative("RTCConfiguration")
CryptoOptions getCryptoOptions() { CryptoOptions getCryptoOptions() {

View File

@ -249,6 +249,9 @@ void JavaToNativeRTCConfiguration(
Java_RTCConfiguration_getActiveResetSrtpParams(jni, j_rtc_config); Java_RTCConfiguration_getActiveResetSrtpParams(jni, j_rtc_config);
rtc_config->use_media_transport = rtc_config->use_media_transport =
Java_RTCConfiguration_getUseMediaTransport(jni, j_rtc_config); Java_RTCConfiguration_getUseMediaTransport(jni, j_rtc_config);
rtc_config->use_media_transport_for_data_channels =
Java_RTCConfiguration_getUseMediaTransportForDataChannels(jni,
j_rtc_config);
rtc_config->crypto_options = rtc_config->crypto_options =
JavaToNativeOptionalCryptoOptions(jni, j_crypto_options); JavaToNativeOptionalCryptoOptions(jni, j_crypto_options);
} }

View File

@ -188,6 +188,12 @@ RTC_OBJC_EXPORT
*/ */
@property(nonatomic, assign) BOOL useMediaTransport; @property(nonatomic, assign) BOOL useMediaTransport;
/**
* If MediaTransportFactory is provided in PeerConnectionFactory, this flag informs PeerConnection
* that it should use the MediaTransportInterface for data channels.
*/
@property(nonatomic, assign) BOOL useMediaTransportForDataChannels;
/** /**
* Defines advanced optional cryptographic settings related to SRTP and * Defines advanced optional cryptographic settings related to SRTP and
* frame encryption for native WebRTC. Setting this will overwrite any * frame encryption for native WebRTC. Setting this will overwrite any

View File

@ -51,6 +51,7 @@
@synthesize turnCustomizer = _turnCustomizer; @synthesize turnCustomizer = _turnCustomizer;
@synthesize activeResetSrtpParams = _activeResetSrtpParams; @synthesize activeResetSrtpParams = _activeResetSrtpParams;
@synthesize useMediaTransport = _useMediaTransport; @synthesize useMediaTransport = _useMediaTransport;
@synthesize useMediaTransportForDataChannels = _useMediaTransportForDataChannels;
@synthesize cryptoOptions = _cryptoOptions; @synthesize cryptoOptions = _cryptoOptions;
- (instancetype)init { - (instancetype)init {
@ -100,6 +101,7 @@
_iceBackupCandidatePairPingInterval = _iceBackupCandidatePairPingInterval =
config.ice_backup_candidate_pair_ping_interval; config.ice_backup_candidate_pair_ping_interval;
_useMediaTransport = config.use_media_transport; _useMediaTransport = config.use_media_transport;
_useMediaTransportForDataChannels = config.use_media_transport_for_data_channels;
_keyType = RTCEncryptionKeyTypeECDSA; _keyType = RTCEncryptionKeyTypeECDSA;
_iceCandidatePoolSize = config.ice_candidate_pool_size; _iceCandidatePoolSize = config.ice_candidate_pool_size;
_shouldPruneTurnPorts = config.prune_turn_ports; _shouldPruneTurnPorts = config.prune_turn_ports;
@ -199,6 +201,7 @@
nativeConfig->ice_backup_candidate_pair_ping_interval = nativeConfig->ice_backup_candidate_pair_ping_interval =
_iceBackupCandidatePairPingInterval; _iceBackupCandidatePairPingInterval;
nativeConfig->use_media_transport = _useMediaTransport; nativeConfig->use_media_transport = _useMediaTransport;
nativeConfig->use_media_transport_for_data_channels = _useMediaTransportForDataChannels;
rtc::KeyType keyType = rtc::KeyType keyType =
[[self class] nativeEncryptionKeyTypeForKeyType:_keyType]; [[self class] nativeEncryptionKeyTypeForKeyType:_keyType];
if (_certificate != nullptr) { if (_certificate != nullptr) {