| Index: webrtc/pc/mediasession.cc
|
| diff --git a/webrtc/pc/mediasession.cc b/webrtc/pc/mediasession.cc
|
| index eb12a71bc20c82d009d474ac70ecba49c37aa6ff..f6190c2e8f266ba3d6c24ac498b6234b39f9f1ff 100644
|
| --- a/webrtc/pc/mediasession.cc
|
| +++ b/webrtc/pc/mediasession.cc
|
| @@ -956,33 +956,70 @@ static void FindCodecsToOffer(
|
| static bool FindByUri(const RtpHeaderExtensions& extensions,
|
| const webrtc::RtpExtension& ext_to_match,
|
| webrtc::RtpExtension* found_extension) {
|
| + // We assume that all URIs are given in a canonical format.
|
| + const webrtc::RtpExtension* found =
|
| + webrtc::RtpExtension::FindHeaderExtensionByUri(extensions,
|
| + ext_to_match.uri);
|
| + if (!found) {
|
| + return false;
|
| + }
|
| + if (found_extension) {
|
| + *found_extension = *found;
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +static bool FindByUriWithEncryptionPreference(
|
| + const RtpHeaderExtensions& extensions,
|
| + const webrtc::RtpExtension& ext_to_match, bool encryption_preference,
|
| + webrtc::RtpExtension* found_extension) {
|
| + const webrtc::RtpExtension* unencrypted_extension = nullptr;
|
| for (RtpHeaderExtensions::const_iterator it = extensions.begin();
|
| it != extensions.end(); ++it) {
|
| // We assume that all URIs are given in a canonical format.
|
| if (it->uri == ext_to_match.uri) {
|
| - if (found_extension != NULL) {
|
| - *found_extension = *it;
|
| + if (!encryption_preference || it->encrypt) {
|
| + if (found_extension) {
|
| + *found_extension = *it;
|
| + }
|
| + return true;
|
| }
|
| - return true;
|
| + unencrypted_extension = &(*it);
|
| + }
|
| + }
|
| + if (unencrypted_extension) {
|
| + if (found_extension) {
|
| + *found_extension = *unencrypted_extension;
|
| }
|
| + return true;
|
| }
|
| return false;
|
| }
|
|
|
| -// Iterates through |offered_extensions|, adding each one to |all_extensions|
|
| -// and |used_ids|, and resolving ID conflicts. If an offered extension has the
|
| -// same URI as one in |all_extensions|, it will re-use the same ID and won't be
|
| -// treated as a conflict.
|
| +// Iterates through |offered_extensions|, adding each one to
|
| +// |regular_extensions| (or |encrypted_extensions| if encrypted) and |used_ids|,
|
| +// and resolving ID conflicts.
|
| +// If an offered extension has the same URI as one in |regular_extensions| or
|
| +// |encrypted_extensions|, it will re-use the same ID and won't be treated as
|
| +// a conflict.
|
| static void FindAndSetRtpHdrExtUsed(RtpHeaderExtensions* offered_extensions,
|
| - RtpHeaderExtensions* all_extensions,
|
| + RtpHeaderExtensions* regular_extensions,
|
| + RtpHeaderExtensions* encrypted_extensions,
|
| UsedRtpHeaderExtensionIds* used_ids) {
|
| for (auto& extension : *offered_extensions) {
|
| webrtc::RtpExtension existing;
|
| - if (FindByUri(*all_extensions, extension, &existing)) {
|
| + if ((extension.encrypt &&
|
| + FindByUri(*encrypted_extensions, extension, &existing)) ||
|
| + (!extension.encrypt &&
|
| + FindByUri(*regular_extensions, extension, &existing))) {
|
| extension.id = existing.id;
|
| } else {
|
| used_ids->FindAndSetIdUsed(&extension);
|
| - all_extensions->push_back(extension);
|
| + if (extension.encrypt) {
|
| + encrypted_extensions->push_back(extension);
|
| + } else {
|
| + regular_extensions->push_back(extension);
|
| + }
|
| }
|
| }
|
| }
|
| @@ -1008,15 +1045,47 @@ static void FindRtpHdrExtsToOffer(
|
| }
|
| }
|
|
|
| +static void AddEncryptedVersionsOfHdrExts(RtpHeaderExtensions* extensions,
|
| + RtpHeaderExtensions* all_extensions,
|
| + UsedRtpHeaderExtensionIds* used_ids) {
|
| + RtpHeaderExtensions encrypted_extensions;
|
| + for (const webrtc::RtpExtension& extension : *extensions) {
|
| + webrtc::RtpExtension existing;
|
| + // Don't add encrypted extensions again that were already included in a
|
| + // previous offer or regular extensions that are also included as encrypted
|
| + // extensions.
|
| + if (extension.encrypt ||
|
| + !webrtc::RtpExtension::IsEncryptionSupported(extension.uri) ||
|
| + (FindByUriWithEncryptionPreference(*extensions, extension, true,
|
| + &existing) && existing.encrypt)) {
|
| + continue;
|
| + }
|
| +
|
| + if (FindByUri(*all_extensions, extension, &existing)) {
|
| + encrypted_extensions.push_back(existing);
|
| + } else {
|
| + webrtc::RtpExtension encrypted(extension);
|
| + encrypted.encrypt = true;
|
| + used_ids->FindAndSetIdUsed(&encrypted);
|
| + all_extensions->push_back(encrypted);
|
| + encrypted_extensions.push_back(encrypted);
|
| + }
|
| + }
|
| + extensions->insert(extensions->end(), encrypted_extensions.begin(),
|
| + encrypted_extensions.end());
|
| +}
|
| +
|
| static void NegotiateRtpHeaderExtensions(
|
| const RtpHeaderExtensions& local_extensions,
|
| const RtpHeaderExtensions& offered_extensions,
|
| + bool enable_encrypted_rtp_header_extensions,
|
| RtpHeaderExtensions* negotiated_extenstions) {
|
| RtpHeaderExtensions::const_iterator ours;
|
| for (ours = local_extensions.begin();
|
| ours != local_extensions.end(); ++ours) {
|
| webrtc::RtpExtension theirs;
|
| - if (FindByUri(offered_extensions, *ours, &theirs)) {
|
| + if (FindByUriWithEncryptionPreference(offered_extensions, *ours,
|
| + enable_encrypted_rtp_header_extensions, &theirs)) {
|
| // We respond with their RTP header extension id.
|
| negotiated_extenstions->push_back(theirs);
|
| }
|
| @@ -1051,6 +1120,7 @@ static bool CreateMediaContentAnswer(
|
| const SecurePolicy& sdes_policy,
|
| const CryptoParamsVec* current_cryptos,
|
| const RtpHeaderExtensions& local_rtp_extenstions,
|
| + bool enable_encrypted_rtp_header_extensions,
|
| StreamParamsVec* current_streams,
|
| bool add_legacy_stream,
|
| bool bundle_enabled,
|
| @@ -1062,6 +1132,7 @@ static bool CreateMediaContentAnswer(
|
| RtpHeaderExtensions negotiated_rtp_extensions;
|
| NegotiateRtpHeaderExtensions(local_rtp_extenstions,
|
| offer->rtp_header_extensions(),
|
| + enable_encrypted_rtp_header_extensions,
|
| &negotiated_rtp_extensions);
|
| answer->set_rtp_header_extensions(negotiated_rtp_extensions);
|
|
|
| @@ -1580,7 +1651,8 @@ void MediaSessionDescriptionFactory::GetRtpHdrExtsToOffer(
|
| // All header extensions allocated from the same range to avoid potential
|
| // issues when using BUNDLE.
|
| UsedRtpHeaderExtensionIds used_ids;
|
| - RtpHeaderExtensions all_extensions;
|
| + RtpHeaderExtensions all_regular_extensions;
|
| + RtpHeaderExtensions all_encrypted_extensions;
|
| audio_extensions->clear();
|
| video_extensions->clear();
|
|
|
| @@ -1593,22 +1665,32 @@ void MediaSessionDescriptionFactory::GetRtpHdrExtsToOffer(
|
| GetFirstAudioContentDescription(current_description);
|
| if (audio) {
|
| *audio_extensions = audio->rtp_header_extensions();
|
| - FindAndSetRtpHdrExtUsed(audio_extensions, &all_extensions, &used_ids);
|
| + FindAndSetRtpHdrExtUsed(audio_extensions, &all_regular_extensions,
|
| + &all_encrypted_extensions, &used_ids);
|
| }
|
| const VideoContentDescription* video =
|
| GetFirstVideoContentDescription(current_description);
|
| if (video) {
|
| *video_extensions = video->rtp_header_extensions();
|
| - FindAndSetRtpHdrExtUsed(video_extensions, &all_extensions, &used_ids);
|
| + FindAndSetRtpHdrExtUsed(video_extensions, &all_regular_extensions,
|
| + &all_encrypted_extensions, &used_ids);
|
| }
|
| }
|
|
|
| // Add our default RTP header extensions that are not in
|
| // |current_description|.
|
| FindRtpHdrExtsToOffer(audio_rtp_header_extensions(), audio_extensions,
|
| - &all_extensions, &used_ids);
|
| + &all_regular_extensions, &used_ids);
|
| FindRtpHdrExtsToOffer(video_rtp_header_extensions(), video_extensions,
|
| - &all_extensions, &used_ids);
|
| + &all_regular_extensions, &used_ids);
|
| + // TODO(jbauch): Support adding encrypted header extensions to existing
|
| + // sessions.
|
| + if (enable_encrypted_rtp_header_extensions_ && !current_description) {
|
| + AddEncryptedVersionsOfHdrExts(audio_extensions, &all_encrypted_extensions,
|
| + &used_ids);
|
| + AddEncryptedVersionsOfHdrExts(video_extensions, &all_encrypted_extensions,
|
| + &used_ids);
|
| + }
|
| }
|
|
|
| bool MediaSessionDescriptionFactory::AddTransportOffer(
|
| @@ -1886,6 +1968,7 @@ bool MediaSessionDescriptionFactory::AddAudioContentForAnswer(
|
| sdes_policy,
|
| GetCryptos(GetFirstAudioContentDescription(current_description)),
|
| audio_rtp_extensions_,
|
| + enable_encrypted_rtp_header_extensions_,
|
| current_streams,
|
| add_legacy_,
|
| bundle_enabled,
|
| @@ -1942,6 +2025,7 @@ bool MediaSessionDescriptionFactory::AddVideoContentForAnswer(
|
| sdes_policy,
|
| GetCryptos(GetFirstVideoContentDescription(current_description)),
|
| video_rtp_extensions_,
|
| + enable_encrypted_rtp_header_extensions_,
|
| current_streams,
|
| add_legacy_,
|
| bundle_enabled,
|
| @@ -2003,6 +2087,7 @@ bool MediaSessionDescriptionFactory::AddDataContentForAnswer(
|
| sdes_policy,
|
| GetCryptos(GetFirstDataContentDescription(current_description)),
|
| RtpHeaderExtensions(),
|
| + enable_encrypted_rtp_header_extensions_,
|
| current_streams,
|
| add_legacy_,
|
| bundle_enabled,
|
|
|