diff options
-rw-r--r-- | media/base/codec.cc | 16 | ||||
-rw-r--r-- | media/base/codec.h | 20 | ||||
-rw-r--r-- | media/base/rtp_data_engine.h | 3 | ||||
-rw-r--r-- | pc/BUILD.gn | 8 | ||||
-rw-r--r-- | pc/channel.cc | 11 | ||||
-rw-r--r-- | pc/channel.h | 2 | ||||
-rw-r--r-- | pc/channel_unittest.cc | 12 | ||||
-rw-r--r-- | pc/jsep_transport_controller_unittest.cc | 5 | ||||
-rw-r--r-- | pc/media_protocol_names.cc | 41 | ||||
-rw-r--r-- | pc/media_protocol_names.h | 35 | ||||
-rw-r--r-- | pc/media_session.cc | 427 | ||||
-rw-r--r-- | pc/media_session.h | 49 | ||||
-rw-r--r-- | pc/media_session_unittest.cc | 129 | ||||
-rw-r--r-- | pc/peer_connection.cc | 41 | ||||
-rw-r--r-- | pc/peer_connection_data_channel_unittest.cc | 9 | ||||
-rw-r--r-- | pc/peer_connection_integrationtest.cc | 4 | ||||
-rw-r--r-- | pc/session_description.cc | 419 | ||||
-rw-r--r-- | pc/session_description.h | 291 | ||||
-rw-r--r-- | pc/session_description_unittest.cc | 61 | ||||
-rw-r--r-- | pc/webrtc_sdp.cc | 136 | ||||
-rw-r--r-- | pc/webrtc_sdp_unittest.cc | 111 |
21 files changed, 486 insertions, 1344 deletions
diff --git a/media/base/codec.cc b/media/base/codec.cc index 4380514957..d0ca29b6f5 100644 --- a/media/base/codec.cc +++ b/media/base/codec.cc @@ -334,22 +334,22 @@ bool VideoCodec::ValidateCodecFormat() const { return true; } -RtpDataCodec::RtpDataCodec(int id, const std::string& name) +DataCodec::DataCodec(int id, const std::string& name) : Codec(id, name, kDataCodecClockrate) {} -RtpDataCodec::RtpDataCodec() : Codec() { +DataCodec::DataCodec() : Codec() { clockrate = kDataCodecClockrate; } -RtpDataCodec::RtpDataCodec(const RtpDataCodec& c) = default; -RtpDataCodec::RtpDataCodec(RtpDataCodec&& c) = default; -RtpDataCodec& RtpDataCodec::operator=(const RtpDataCodec& c) = default; -RtpDataCodec& RtpDataCodec::operator=(RtpDataCodec&& c) = default; +DataCodec::DataCodec(const DataCodec& c) = default; +DataCodec::DataCodec(DataCodec&& c) = default; +DataCodec& DataCodec::operator=(const DataCodec& c) = default; +DataCodec& DataCodec::operator=(DataCodec&& c) = default; -std::string RtpDataCodec::ToString() const { +std::string DataCodec::ToString() const { char buf[256]; rtc::SimpleStringBuilder sb(buf); - sb << "RtpDataCodec[" << id << ":" << name << "]"; + sb << "DataCodec[" << id << ":" << name << "]"; return sb.str(); } diff --git a/media/base/codec.h b/media/base/codec.h index bbb147d4a2..091adb6cfa 100644 --- a/media/base/codec.h +++ b/media/base/codec.h @@ -192,23 +192,19 @@ struct RTC_EXPORT VideoCodec : public Codec { void SetDefaultParameters(); }; -struct RtpDataCodec : public Codec { - RtpDataCodec(int id, const std::string& name); - RtpDataCodec(); - RtpDataCodec(const RtpDataCodec& c); - RtpDataCodec(RtpDataCodec&& c); - ~RtpDataCodec() override = default; +struct DataCodec : public Codec { + DataCodec(int id, const std::string& name); + DataCodec(); + DataCodec(const DataCodec& c); + DataCodec(DataCodec&& c); + ~DataCodec() override = default; - RtpDataCodec& operator=(const RtpDataCodec& c); - RtpDataCodec& operator=(RtpDataCodec&& c); + DataCodec& operator=(const DataCodec& c); + DataCodec& operator=(DataCodec&& c); std::string ToString() const; }; -// For backwards compatibility -// TODO(bugs.webrtc.org/10597): Remove when no longer needed. -typedef RtpDataCodec DataCodec; - // Get the codec setting associated with |payload_type|. If there // is no codec associated with that payload type it returns nullptr. template <class Codec> diff --git a/media/base/rtp_data_engine.h b/media/base/rtp_data_engine.h index b8bfca2c03..a4647aef34 100644 --- a/media/base/rtp_data_engine.h +++ b/media/base/rtp_data_engine.h @@ -16,7 +16,6 @@ #include <string> #include <vector> -#include "media/base/codec.h" #include "media/base/media_channel.h" #include "media/base/media_constants.h" #include "media/base/media_engine.h" @@ -27,6 +26,8 @@ class DataRateLimiter; namespace cricket { +struct DataCodec; + class RtpDataEngine : public DataEngineInterface { public: RtpDataEngine(); diff --git a/pc/BUILD.gn b/pc/BUILD.gn index e93fa7a0c1..d4065208b2 100644 --- a/pc/BUILD.gn +++ b/pc/BUILD.gn @@ -72,7 +72,6 @@ rtc_static_library("rtc_pc_base") { ] deps = [ - ":media_protocol_names", "../api:array_view", "../api:audio_options_api", "../api:call_api", @@ -122,13 +121,6 @@ rtc_source_set("rtc_pc") { ] } -rtc_source_set("media_protocol_names") { - sources = [ - "media_protocol_names.cc", - "media_protocol_names.h", - ] -} - rtc_static_library("peerconnection") { visibility = [ "*" ] cflags = [] diff --git a/pc/channel.cc b/pc/channel.cc index 82de7de381..647663e250 100644 --- a/pc/channel.cc +++ b/pc/channel.cc @@ -1143,7 +1143,7 @@ bool RtpDataChannel::SendData(const SendDataParams& params, } bool RtpDataChannel::CheckDataChannelTypeFromContent( - const RtpDataContentDescription* content, + const DataContentDescription* content, std::string* error_desc) { bool is_sctp = ((content->protocol() == kMediaProtocolSctp) || (content->protocol() == kMediaProtocolDtlsSctp)); @@ -1169,7 +1169,7 @@ bool RtpDataChannel::SetLocalContent_w(const MediaContentDescription* content, return false; } - const RtpDataContentDescription* data = content->as_rtp_data(); + const DataContentDescription* data = content->as_data(); if (!CheckDataChannelTypeFromContent(data, error_desc)) { return false; @@ -1223,12 +1223,7 @@ bool RtpDataChannel::SetRemoteContent_w(const MediaContentDescription* content, return false; } - const RtpDataContentDescription* data = content->as_rtp_data(); - - if (!data) { - RTC_LOG(LS_INFO) << "Accepting and ignoring non-RTP content description"; - return true; - } + const DataContentDescription* data = content->as_data(); // If the remote data doesn't have codecs, it must be empty, so ignore it. if (!data->has_codecs()) { diff --git a/pc/channel.h b/pc/channel.h index 9747ec27cb..1a4cc72201 100644 --- a/pc/channel.h +++ b/pc/channel.h @@ -518,7 +518,7 @@ class RtpDataChannel : public BaseChannel { // overrides from BaseChannel // Checks that data channel type is RTP. - bool CheckDataChannelTypeFromContent(const RtpDataContentDescription* content, + bool CheckDataChannelTypeFromContent(const DataContentDescription* content, std::string* error_desc); bool SetLocalContent_w(const MediaContentDescription* content, webrtc::SdpType type, diff --git a/pc/channel_unittest.cc b/pc/channel_unittest.cc index e31ab538e1..9c5f82b0d4 100644 --- a/pc/channel_unittest.cc +++ b/pc/channel_unittest.cc @@ -94,8 +94,8 @@ class VideoTraits : public Traits<cricket::VideoChannel, class DataTraits : public Traits<cricket::RtpDataChannel, cricket::FakeDataMediaChannel, - cricket::RtpDataContentDescription, - cricket::RtpDataCodec, + cricket::DataContentDescription, + cricket::DataCodec, cricket::DataMediaInfo, cricket::DataOptions> {}; @@ -2308,15 +2308,15 @@ void ChannelTest<DataTraits>::CreateContent( int flags, const cricket::AudioCodec& audio_codec, const cricket::VideoCodec& video_codec, - cricket::RtpDataContentDescription* data) { + cricket::DataContentDescription* data) { data->AddCodec(kGoogleDataCodec); data->set_rtcp_mux((flags & RTCP_MUX) != 0); } template <> void ChannelTest<DataTraits>::CopyContent( - const cricket::RtpDataContentDescription& source, - cricket::RtpDataContentDescription* data) { + const cricket::DataContentDescription& source, + cricket::DataContentDescription* data) { *data = source; } @@ -2330,7 +2330,7 @@ template <> void ChannelTest<DataTraits>::AddLegacyStreamInContent( uint32_t ssrc, int flags, - cricket::RtpDataContentDescription* data) { + cricket::DataContentDescription* data) { data->AddLegacyStream(ssrc); } diff --git a/pc/jsep_transport_controller_unittest.cc b/pc/jsep_transport_controller_unittest.cc index c0927b9db4..e81b667514 100644 --- a/pc/jsep_transport_controller_unittest.cc +++ b/pc/jsep_transport_controller_unittest.cc @@ -175,9 +175,8 @@ class JsepTransportControllerTest : public JsepTransportController::Observer, cricket::IceMode ice_mode, cricket::ConnectionRole conn_role, rtc::scoped_refptr<rtc::RTCCertificate> cert) { - RTC_CHECK(protocol_type == cricket::MediaProtocolType::kSctp); - std::unique_ptr<cricket::SctpDataContentDescription> data( - new cricket::SctpDataContentDescription()); + std::unique_ptr<cricket::DataContentDescription> data( + new cricket::DataContentDescription()); data->set_rtcp_mux(true); description->AddContent(mid, protocol_type, /*rejected=*/false, data.release()); diff --git a/pc/media_protocol_names.cc b/pc/media_protocol_names.cc deleted file mode 100644 index 6ce2f02517..0000000000 --- a/pc/media_protocol_names.cc +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2019 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include "pc/media_protocol_names.h" - -namespace cricket { - -const char kMediaProtocolRtpPrefix[] = "RTP/"; - -const char kMediaProtocolSctp[] = "SCTP"; -const char kMediaProtocolDtlsSctp[] = "DTLS/SCTP"; -const char kMediaProtocolUdpDtlsSctp[] = "UDP/DTLS/SCTP"; -const char kMediaProtocolTcpDtlsSctp[] = "TCP/DTLS/SCTP"; - -bool IsDtlsSctp(const std::string& protocol) { - return protocol == kMediaProtocolDtlsSctp || - protocol == kMediaProtocolUdpDtlsSctp || - protocol == kMediaProtocolTcpDtlsSctp; -} - -bool IsPlainSctp(const std::string& protocol) { - return protocol == kMediaProtocolSctp; -} - -bool IsRtpProtocol(const std::string& protocol) { - return protocol.empty() || - (protocol.find(cricket::kMediaProtocolRtpPrefix) != std::string::npos); -} - -bool IsSctpProtocol(const std::string& protocol) { - return IsPlainSctp(protocol) || IsDtlsSctp(protocol); -} - -} // namespace cricket diff --git a/pc/media_protocol_names.h b/pc/media_protocol_names.h deleted file mode 100644 index 88f1c4659d..0000000000 --- a/pc/media_protocol_names.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2019 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef PC_MEDIA_PROTOCOL_NAMES_H_ -#define PC_MEDIA_PROTOCOL_NAMES_H_ - -#include <string> - -namespace cricket { - -// Names or name prefixes of protocols as defined by SDP specifications. -extern const char kMediaProtocolRtpPrefix[]; -extern const char kMediaProtocolSctp[]; -extern const char kMediaProtocolDtlsSctp[]; -extern const char kMediaProtocolUdpDtlsSctp[]; -extern const char kMediaProtocolTcpDtlsSctp[]; - -bool IsDtlsSctp(const std::string& protocol); -bool IsPlainSctp(const std::string& protocol); - -// Returns true if the given media section protocol indicates use of RTP. -bool IsRtpProtocol(const std::string& protocol); -// Returns true if the given media section protocol indicates use of SCTP. -bool IsSctpProtocol(const std::string& protocol); - -} // namespace cricket - -#endif // PC_MEDIA_PROTOCOL_NAMES_H_ diff --git a/pc/media_session.cc b/pc/media_session.cc index 9c03a1e43a..0eace22c6a 100644 --- a/pc/media_session.cc +++ b/pc/media_session.cc @@ -27,7 +27,6 @@ #include "media/base/media_constants.h" #include "p2p/base/p2p_constants.h" #include "pc/channel_manager.h" -#include "pc/media_protocol_names.h" #include "pc/rtp_media_utils.h" #include "pc/srtp_filter.h" #include "rtc_base/checks.h" @@ -69,6 +68,13 @@ const char kMediaProtocolDtlsSavpf[] = "UDP/TLS/RTP/SAVPF"; // but we tolerate "RTP/SAVPF" in offers we receive, for compatibility. const char kMediaProtocolSavpf[] = "RTP/SAVPF"; +const char kMediaProtocolRtpPrefix[] = "RTP/"; + +const char kMediaProtocolSctp[] = "SCTP"; +const char kMediaProtocolDtlsSctp[] = "DTLS/SCTP"; +const char kMediaProtocolUdpDtlsSctp[] = "UDP/DTLS/SCTP"; +const char kMediaProtocolTcpDtlsSctp[] = "TCP/DTLS/SCTP"; + // Note that the below functions support some protocol strings purely for // legacy compatibility, as required by JSEP in Section 5.1.2, Profile Names // and Interoperability. @@ -85,6 +91,20 @@ static bool IsPlainRtp(const std::string& protocol) { protocol == "RTP/SAVP" || protocol == "RTP/AVP"; } +static bool IsDtlsSctp(const std::string& protocol) { + return protocol == kMediaProtocolDtlsSctp || + protocol == kMediaProtocolUdpDtlsSctp || + protocol == kMediaProtocolTcpDtlsSctp; +} + +static bool IsPlainSctp(const std::string& protocol) { + return protocol == kMediaProtocolSctp; +} + +static bool IsSctp(const std::string& protocol) { + return IsPlainSctp(protocol) || IsDtlsSctp(protocol); +} + static RtpTransceiverDirection NegotiateRtpTransceiverDirection( RtpTransceiverDirection offer, RtpTransceiverDirection wants) { @@ -469,7 +489,7 @@ static bool AddStreamParams( StreamParamsVec* current_streams, MediaContentDescriptionImpl<C>* content_description) { // SCTP streams are not negotiated using SDP/ContentDescriptions. - if (IsSctpProtocol(content_description->protocol())) { + if (IsSctp(content_description->protocol())) { return true; } @@ -588,6 +608,11 @@ static void PruneCryptos(const CryptoParamsVec& filter, target_cryptos->end()); } +bool IsRtpProtocol(const std::string& protocol) { + return protocol.empty() || + (protocol.find(cricket::kMediaProtocolRtpPrefix) != std::string::npos); +} + static bool IsRtpContent(SessionDescription* sdesc, const std::string& content_name) { bool is_rtp = false; @@ -716,22 +741,32 @@ static bool IsFlexfecCodec(const C& codec) { // crypto (in current_cryptos) and it is enabled (in secure_policy), crypto is // created (according to crypto_suites). The created content is added to the // offer. -static bool CreateContentOffer( +template <class C> +static bool CreateMediaContentOffer( const MediaDescriptionOptions& media_description_options, const MediaSessionOptions& session_options, + const std::vector<C>& codecs, const SecurePolicy& secure_policy, const CryptoParamsVec* current_cryptos, const std::vector<std::string>& crypto_suites, const RtpHeaderExtensions& rtp_extensions, UniqueRandomIdGenerator* ssrc_generator, StreamParamsVec* current_streams, - MediaContentDescription* offer) { + MediaContentDescriptionImpl<C>* offer) { + offer->AddCodecs(codecs); + offer->set_rtcp_mux(session_options.rtcp_mux_enabled); if (offer->type() == cricket::MEDIA_TYPE_VIDEO) { offer->set_rtcp_reduced_size(true); } offer->set_rtp_header_extensions(rtp_extensions); + if (!AddStreamParams(media_description_options.sender_options, + session_options.rtcp_cname, ssrc_generator, + current_streams, offer)) { + return false; + } + AddSimulcastToMediaDescription(media_description_options, offer); if (secure_policy != SEC_DISABLED) { @@ -750,30 +785,6 @@ static bool CreateContentOffer( } return true; } -template <class C> -static bool CreateMediaContentOffer( - const MediaDescriptionOptions& media_description_options, - const MediaSessionOptions& session_options, - const std::vector<C>& codecs, - const SecurePolicy& secure_policy, - const CryptoParamsVec* current_cryptos, - const std::vector<std::string>& crypto_suites, - const RtpHeaderExtensions& rtp_extensions, - UniqueRandomIdGenerator* ssrc_generator, - StreamParamsVec* current_streams, - MediaContentDescriptionImpl<C>* offer) { - offer->AddCodecs(codecs); - if (!AddStreamParams(media_description_options.sender_options, - session_options.rtcp_cname, ssrc_generator, - current_streams, offer)) { - return false; - } - - return CreateContentOffer(media_description_options, session_options, - secure_policy, current_cryptos, crypto_suites, - rtp_extensions, ssrc_generator, current_streams, - offer); -} template <class C> static bool ReferencedCodecsMatch(const std::vector<C>& codecs1, @@ -1175,28 +1186,6 @@ static void StripCNCodecs(AudioCodecs* audio_codecs) { audio_codecs->end()); } -template <class C> -static bool SetCodecsInAnswer( - const MediaContentDescriptionImpl<C>* offer, - const std::vector<C>& local_codecs, - const MediaDescriptionOptions& media_description_options, - const MediaSessionOptions& session_options, - UniqueRandomIdGenerator* ssrc_generator, - StreamParamsVec* current_streams, - MediaContentDescriptionImpl<C>* answer) { - std::vector<C> negotiated_codecs; - NegotiateCodecs(local_codecs, offer->codecs(), &negotiated_codecs, - media_description_options.codec_preferences.empty()); - answer->AddCodecs(negotiated_codecs); - answer->set_protocol(offer->protocol()); - if (!AddStreamParams(media_description_options.sender_options, - session_options.rtcp_cname, ssrc_generator, - current_streams, answer)) { - return false; // Something went seriously wrong. - } - return true; -} - // Create a media content to be answered for the given |sender_options| // according to the given session_options.rtcp_mux, session_options.streams, // codecs, crypto, and current_streams. If we don't currently have crypto (in @@ -1204,10 +1193,12 @@ static bool SetCodecsInAnswer( // (according to crypto_suites). The codecs, rtcp_mux, and crypto are all // negotiated with the offer. If the negotiation fails, this method returns // false. The created content is added to the offer. +template <class C> static bool CreateMediaContentAnswer( - const MediaContentDescription* offer, + const MediaContentDescriptionImpl<C>* offer, const MediaDescriptionOptions& media_description_options, const MediaSessionOptions& session_options, + const std::vector<C>& local_codecs, const SecurePolicy& sdes_policy, const CryptoParamsVec* current_cryptos, const RtpHeaderExtensions& local_rtp_extenstions, @@ -1215,7 +1206,13 @@ static bool CreateMediaContentAnswer( bool enable_encrypted_rtp_header_extensions, StreamParamsVec* current_streams, bool bundle_enabled, - MediaContentDescription* answer) { + MediaContentDescriptionImpl<C>* answer) { + std::vector<C> negotiated_codecs; + NegotiateCodecs(local_codecs, offer->codecs(), &negotiated_codecs, + media_description_options.codec_preferences.empty()); + answer->AddCodecs(negotiated_codecs); + answer->set_protocol(offer->protocol()); + answer->set_extmap_allow_mixed_enum(offer->extmap_allow_mixed_enum()); RtpHeaderExtensions negotiated_rtp_extensions; NegotiateRtpHeaderExtensions( @@ -1243,6 +1240,12 @@ static bool CreateMediaContentAnswer( return false; } + if (!AddStreamParams(media_description_options.sender_options, + session_options.rtcp_cname, ssrc_generator, + current_streams, answer)) { + return false; // Something went seriously wrong. + } + AddSimulcastToMediaDescription(media_description_options, answer); answer->set_direction(NegotiateRtpTransceiverDirection( @@ -1394,7 +1397,7 @@ MediaSessionDescriptionFactory::MediaSessionDescriptionFactory( channel_manager->GetSupportedAudioRtpHeaderExtensions(&audio_rtp_extensions_); channel_manager->GetSupportedVideoCodecs(&video_codecs_); channel_manager->GetSupportedVideoRtpHeaderExtensions(&video_rtp_extensions_); - channel_manager->GetSupportedDataCodecs(&rtp_data_codecs_); + channel_manager->GetSupportedDataCodecs(&data_codecs_); ComputeAudioCodecsIntersectionAndUnion(); } @@ -1481,15 +1484,15 @@ std::unique_ptr<SessionDescription> MediaSessionDescriptionFactory::CreateOffer( AudioCodecs offer_audio_codecs; VideoCodecs offer_video_codecs; - RtpDataCodecs offer_rtp_data_codecs; + DataCodecs offer_data_codecs; GetCodecsForOffer(current_active_contents, &offer_audio_codecs, - &offer_video_codecs, &offer_rtp_data_codecs); + &offer_video_codecs, &offer_data_codecs); if (!session_options.vad_enabled) { // If application doesn't want CN codecs in offer. StripCNCodecs(&offer_audio_codecs); } - FilterDataCodecs(&offer_rtp_data_codecs, + FilterDataCodecs(&offer_data_codecs, session_options.data_channel_type == DCT_SCTP); RtpHeaderExtensions audio_rtp_extensions; @@ -1533,7 +1536,7 @@ std::unique_ptr<SessionDescription> MediaSessionDescriptionFactory::CreateOffer( case MEDIA_TYPE_DATA: if (!AddDataContentForOffer(media_description_options, session_options, current_content, current_description, - offer_rtp_data_codecs, ¤t_streams, + offer_data_codecs, ¤t_streams, offer.get(), &ice_credentials)) { return nullptr; } @@ -1631,15 +1634,15 @@ MediaSessionDescriptionFactory::CreateAnswer( // sections. AudioCodecs answer_audio_codecs; VideoCodecs answer_video_codecs; - RtpDataCodecs answer_rtp_data_codecs; + DataCodecs answer_data_codecs; GetCodecsForAnswer(current_active_contents, *offer, &answer_audio_codecs, - &answer_video_codecs, &answer_rtp_data_codecs); + &answer_video_codecs, &answer_data_codecs); if (!session_options.vad_enabled) { // If application doesn't want CN codecs in answer. StripCNCodecs(&answer_audio_codecs); } - FilterDataCodecs(&answer_rtp_data_codecs, + FilterDataCodecs(&answer_data_codecs, session_options.data_channel_type == DCT_SCTP); auto answer = absl::make_unique<SessionDescription>(); @@ -1692,8 +1695,8 @@ MediaSessionDescriptionFactory::CreateAnswer( if (!AddDataContentForAnswer( media_description_options, session_options, offer_content, offer, current_content, current_description, - bundle_transport.get(), answer_rtp_data_codecs, - ¤t_streams, answer.get(), &ice_credentials)) { + bundle_transport.get(), answer_data_codecs, ¤t_streams, + answer.get(), &ice_credentials)) { return nullptr; } break; @@ -1813,7 +1816,7 @@ void MergeCodecsFromDescription( const std::vector<const ContentInfo*>& current_active_contents, AudioCodecs* audio_codecs, VideoCodecs* video_codecs, - RtpDataCodecs* rtp_data_codecs, + DataCodecs* data_codecs, UsedPayloadTypes* used_pltypes) { for (const ContentInfo* content : current_active_contents) { if (IsMediaContentOfType(content, MEDIA_TYPE_AUDIO)) { @@ -1825,13 +1828,9 @@ void MergeCodecsFromDescription( content->media_description()->as_video(); MergeCodecs<VideoCodec>(video->codecs(), video_codecs, used_pltypes); } else if (IsMediaContentOfType(content, MEDIA_TYPE_DATA)) { - const RtpDataContentDescription* data = - content->media_description()->as_rtp_data(); - if (data) { - // Only relevant for RTP datachannels - MergeCodecs<RtpDataCodec>(data->codecs(), rtp_data_codecs, - used_pltypes); - } + const DataContentDescription* data = + content->media_description()->as_data(); + MergeCodecs<DataCodec>(data->codecs(), data_codecs, used_pltypes); } } } @@ -1846,18 +1845,18 @@ void MediaSessionDescriptionFactory::GetCodecsForOffer( const std::vector<const ContentInfo*>& current_active_contents, AudioCodecs* audio_codecs, VideoCodecs* video_codecs, - RtpDataCodecs* rtp_data_codecs) const { + DataCodecs* data_codecs) const { // First - get all codecs from the current description if the media type // is used. Add them to |used_pltypes| so the payload type is not reused if a // new media type is added. UsedPayloadTypes used_pltypes; MergeCodecsFromDescription(current_active_contents, audio_codecs, - video_codecs, rtp_data_codecs, &used_pltypes); + video_codecs, data_codecs, &used_pltypes); // Add our codecs that are not in the current description. MergeCodecs<AudioCodec>(all_audio_codecs_, audio_codecs, &used_pltypes); MergeCodecs<VideoCodec>(video_codecs_, video_codecs, &used_pltypes); - MergeCodecs<DataCodec>(rtp_data_codecs_, rtp_data_codecs, &used_pltypes); + MergeCodecs<DataCodec>(data_codecs_, data_codecs, &used_pltypes); } // Getting codecs for an answer involves these steps: @@ -1872,18 +1871,18 @@ void MediaSessionDescriptionFactory::GetCodecsForAnswer( const SessionDescription& remote_offer, AudioCodecs* audio_codecs, VideoCodecs* video_codecs, - RtpDataCodecs* rtp_data_codecs) const { + DataCodecs* data_codecs) const { // First - get all codecs from the current description if the media type // is used. Add them to |used_pltypes| so the payload type is not reused if a // new media type is added. UsedPayloadTypes used_pltypes; MergeCodecsFromDescription(current_active_contents, audio_codecs, - video_codecs, rtp_data_codecs, &used_pltypes); + video_codecs, data_codecs, &used_pltypes); // Second - filter out codecs that we don't support at all and should ignore. AudioCodecs filtered_offered_audio_codecs; VideoCodecs filtered_offered_video_codecs; - RtpDataCodecs filtered_offered_rtp_data_codecs; + DataCodecs filtered_offered_data_codecs; for (const ContentInfo& content : remote_offer.contents()) { if (IsMediaContentOfType(&content, MEDIA_TYPE_AUDIO)) { const AudioContentDescription* audio = @@ -1910,19 +1909,15 @@ void MediaSessionDescriptionFactory::GetCodecsForAnswer( } } } else if (IsMediaContentOfType(&content, MEDIA_TYPE_DATA)) { - const RtpDataContentDescription* data = - content.media_description()->as_rtp_data(); - if (data) { - // RTP data. This part is inactive for SCTP data. - for (const RtpDataCodec& offered_rtp_data_codec : data->codecs()) { - if (!FindMatchingCodec<RtpDataCodec>( - data->codecs(), filtered_offered_rtp_data_codecs, - offered_rtp_data_codec, nullptr) && - FindMatchingCodec<RtpDataCodec>(data->codecs(), rtp_data_codecs_, - offered_rtp_data_codec, - nullptr)) { - filtered_offered_rtp_data_codecs.push_back(offered_rtp_data_codec); - } + const DataContentDescription* data = + content.media_description()->as_data(); + for (const DataCodec& offered_data_codec : data->codecs()) { + if (!FindMatchingCodec<DataCodec>(data->codecs(), + filtered_offered_data_codecs, + offered_data_codec, nullptr) && + FindMatchingCodec<DataCodec>(data->codecs(), data_codecs_, + offered_data_codec, nullptr)) { + filtered_offered_data_codecs.push_back(offered_data_codec); } } } @@ -1934,7 +1929,7 @@ void MediaSessionDescriptionFactory::GetCodecsForAnswer( &used_pltypes); MergeCodecs<VideoCodec>(filtered_offered_video_codecs, video_codecs, &used_pltypes); - MergeCodecs<DataCodec>(filtered_offered_rtp_data_codecs, rtp_data_codecs, + MergeCodecs<DataCodec>(filtered_offered_data_codecs, data_codecs, &used_pltypes); } @@ -2211,84 +2206,66 @@ bool MediaSessionDescriptionFactory::AddVideoContentForOffer( return true; } -bool MediaSessionDescriptionFactory::AddSctpDataContentForOffer( +bool MediaSessionDescriptionFactory::AddDataContentForOffer( const MediaDescriptionOptions& media_description_options, const MediaSessionOptions& session_options, const ContentInfo* current_content, const SessionDescription* current_description, + const DataCodecs& data_codecs, StreamParamsVec* current_streams, SessionDescription* desc, IceCredentialsIterator* ice_credentials) const { - std::unique_ptr<SctpDataContentDescription> data( - new SctpDataContentDescription()); - bool secure_transport = (transport_desc_factory_->secure() != SEC_DISABLED); + std::unique_ptr<DataContentDescription> data(new DataContentDescription()); + bool is_sctp = (session_options.data_channel_type == DCT_SCTP); + // If the DataChannel type is not specified, use the DataChannel type in + // the current description. + if (session_options.data_channel_type == DCT_NONE && current_content) { + RTC_CHECK(IsMediaContentOfType(current_content, MEDIA_TYPE_DATA)); + is_sctp = (current_content->media_description()->protocol() == + kMediaProtocolSctp); + } + cricket::SecurePolicy sdes_policy = IsDtlsActive(current_content, current_description) ? cricket::SEC_DISABLED : secure(); std::vector<std::string> crypto_suites; - // SDES doesn't make sense for SCTP, so we disable it, and we only - // get SDES crypto suites for RTP-based data channels. - sdes_policy = cricket::SEC_DISABLED; - // Unlike SetMediaProtocol below, we need to set the protocol - // before we call CreateMediaContentOffer. Otherwise, - // CreateMediaContentOffer won't know this is SCTP and will - // generate SSRCs rather than SIDs. - // TODO(deadbeef): Offer kMediaProtocolUdpDtlsSctp (or TcpDtlsSctp), once - // it's safe to do so. Older versions of webrtc would reject these - // protocols; see https://bugs.chromium.org/p/webrtc/issues/detail?id=7706. - data->set_protocol(secure_transport ? kMediaProtocolDtlsSctp - : kMediaProtocolSctp); - - if (!CreateContentOffer(media_description_options, session_options, - sdes_policy, GetCryptos(current_content), - crypto_suites, RtpHeaderExtensions(), ssrc_generator_, - current_streams, data.get())) { - return false; + if (is_sctp) { + // SDES doesn't make sense for SCTP, so we disable it, and we only + // get SDES crypto suites for RTP-based data channels. + sdes_policy = cricket::SEC_DISABLED; + // Unlike SetMediaProtocol below, we need to set the protocol + // before we call CreateMediaContentOffer. Otherwise, + // CreateMediaContentOffer won't know this is SCTP and will + // generate SSRCs rather than SIDs. + // TODO(deadbeef): Offer kMediaProtocolUdpDtlsSctp (or TcpDtlsSctp), once + // it's safe to do so. Older versions of webrtc would reject these + // protocols; see https://bugs.chromium.org/p/webrtc/issues/detail?id=7706. + data->set_protocol(secure_transport ? kMediaProtocolDtlsSctp + : kMediaProtocolSctp); + } else { + GetSupportedDataSdesCryptoSuiteNames(session_options.crypto_options, + &crypto_suites); } - desc->AddContent(media_description_options.mid, MediaProtocolType::kSctp, - data.release()); - if (!AddTransportOffer(media_description_options.mid, - media_description_options.transport_options, - current_description, desc, ice_credentials)) { + // Even SCTP uses a "codec". + if (!CreateMediaContentOffer( + media_description_options, session_options, data_codecs, sdes_policy, + GetCryptos(current_content), crypto_suites, RtpHeaderExtensions(), + ssrc_generator_, current_streams, data.get())) { return false; } - return true; -} - -bool MediaSessionDescriptionFactory::AddRtpDataContentForOffer( - const MediaDescriptionOptions& media_description_options, - const MediaSessionOptions& session_options, - const ContentInfo* current_content, - const SessionDescription* current_description, - const RtpDataCodecs& rtp_data_codecs, - StreamParamsVec* current_streams, - SessionDescription* desc, - IceCredentialsIterator* ice_credentials) const { - std::unique_ptr<RtpDataContentDescription> data( - new RtpDataContentDescription()); - bool secure_transport = (transport_desc_factory_->secure() != SEC_DISABLED); - cricket::SecurePolicy sdes_policy = - IsDtlsActive(current_content, current_description) ? cricket::SEC_DISABLED - : secure(); - std::vector<std::string> crypto_suites; - GetSupportedDataSdesCryptoSuiteNames(session_options.crypto_options, - &crypto_suites); - if (!CreateMediaContentOffer(media_description_options, session_options, - rtp_data_codecs, sdes_policy, - GetCryptos(current_content), crypto_suites, - RtpHeaderExtensions(), ssrc_generator_, - current_streams, data.get())) { - return false; + if (is_sctp) { + desc->AddContent(media_description_options.mid, MediaProtocolType::kSctp, + data.release()); + } else { + data->set_bandwidth(kDataMaxBandwidth); + SetMediaProtocol(secure_transport, data.get()); + desc->AddContent(media_description_options.mid, MediaProtocolType::kRtp, + media_description_options.stopped, data.release()); } - - data->set_bandwidth(kDataMaxBandwidth); - SetMediaProtocol(secure_transport, data.get()); - desc->AddContent(media_description_options.mid, MediaProtocolType::kRtp, - media_description_options.stopped, data.release()); if (!AddTransportOffer(media_description_options.mid, media_description_options.transport_options, current_description, desc, ice_credentials)) { @@ -2297,35 +2274,6 @@ bool MediaSessionDescriptionFactory::AddRtpDataContentForOffer( return true; } -bool MediaSessionDescriptionFactory::AddDataContentForOffer( - const MediaDescriptionOptions& media_description_options, - const MediaSessionOptions& session_options, - const ContentInfo* current_content, - const SessionDescription* current_description, - const RtpDataCodecs& rtp_data_codecs, - StreamParamsVec* current_streams, - SessionDescription* desc, - IceCredentialsIterator* ice_credentials) const { - bool is_sctp = (session_options.data_channel_type == DCT_SCTP); - // If the DataChannel type is not specified, use the DataChannel type in - // the current description. - if (session_options.data_channel_type == DCT_NONE && current_content) { - RTC_CHECK(IsMediaContentOfType(current_content, MEDIA_TYPE_DATA)); - is_sctp = (current_content->media_description()->protocol() == - kMediaProtocolSctp); - } - if (is_sctp) { - return AddSctpDataContentForOffer( - media_description_options, session_options, current_content, - current_description, current_streams, desc, ice_credentials); - } else { - return AddRtpDataContentForOffer(media_description_options, session_options, - current_content, current_description, - rtp_data_codecs, current_streams, desc, - ice_credentials); - } -} - // |audio_codecs| = set of all possible codecs that can be used, with correct // payload type mappings // @@ -2411,15 +2359,9 @@ bool MediaSessionDescriptionFactory::AddAudioContentForAnswer( // Do not require or create SDES cryptos if DTLS is used. cricket::SecurePolicy sdes_policy = audio_transport->secure() ? cricket::SEC_DISABLED : secure(); - if (!SetCodecsInAnswer(offer_audio_description, filtered_codecs, - media_description_options, session_options, - ssrc_generator_, current_streams, - audio_answer.get())) { - return false; - } if (!CreateMediaContentAnswer( offer_audio_description, media_description_options, session_options, - sdes_policy, GetCryptos(current_content), + filtered_codecs, sdes_policy, GetCryptos(current_content), audio_rtp_header_extensions(), ssrc_generator_, enable_encrypted_rtp_header_extensions_, current_streams, bundle_enabled, audio_answer.get())) { @@ -2512,15 +2454,9 @@ bool MediaSessionDescriptionFactory::AddVideoContentForAnswer( // Do not require or create SDES cryptos if DTLS is used. cricket::SecurePolicy sdes_policy = video_transport->secure() ? cricket::SEC_DISABLED : secure(); - if (!SetCodecsInAnswer(offer_video_description, filtered_codecs, - media_description_options, session_options, - ssrc_generator_, current_streams, - video_answer.get())) { - return false; - } if (!CreateMediaContentAnswer( offer_video_description, media_description_options, session_options, - sdes_policy, GetCryptos(current_content), + filtered_codecs, sdes_policy, GetCryptos(current_content), video_rtp_header_extensions(), ssrc_generator_, enable_encrypted_rtp_header_extensions_, current_streams, bundle_enabled, video_answer.get())) { @@ -2556,7 +2492,7 @@ bool MediaSessionDescriptionFactory::AddDataContentForAnswer( const ContentInfo* current_content, const SessionDescription* current_description, const TransportInfo* bundle_transport, - const RtpDataCodecs& rtp_data_codecs, + const DataCodecs& data_codecs, StreamParamsVec* current_streams, SessionDescription* answer, IceCredentialsIterator* ice_credentials) const { @@ -2568,52 +2504,29 @@ bool MediaSessionDescriptionFactory::AddDataContentForAnswer( return false; } + std::unique_ptr<DataContentDescription> data_answer( + new DataContentDescription()); // Do not require or create SDES cryptos if DTLS is used. cricket::SecurePolicy sdes_policy = data_transport->secure() ? cricket::SEC_DISABLED : secure(); bool bundle_enabled = offer_description->HasGroup(GROUP_TYPE_BUNDLE) && session_options.bundle_enabled; RTC_CHECK(IsMediaContentOfType(offer_content, MEDIA_TYPE_DATA)); - std::unique_ptr<MediaContentDescription> data_answer; - if (offer_content->media_description()->as_sctp()) { - // SCTP data content - data_answer = absl::make_unique<SctpDataContentDescription>(); - const SctpDataContentDescription* offer_data_description = - offer_content->media_description()->as_sctp(); - // Respond with the offerer's proto, whatever it is. - data_answer->as_sctp()->set_protocol(offer_data_description->protocol()); - if (!CreateMediaContentAnswer( - offer_data_description, media_description_options, session_options, - sdes_policy, GetCryptos(current_content), RtpHeaderExtensions(), - ssrc_generator_, enable_encrypted_rtp_header_extensions_, - current_streams, bundle_enabled, data_answer.get())) { - return false; // Fails the session setup. - } - // Respond with sctpmap if the offer uses sctpmap. - bool offer_uses_sctpmap = offer_data_description->use_sctpmap(); - data_answer->as_sctp()->set_use_sctpmap(offer_uses_sctpmap); - } else { - // RTP offer - data_answer = absl::make_unique<RtpDataContentDescription>(); - - const RtpDataContentDescription* offer_data_description = - offer_content->media_description()->as_rtp_data(); - RTC_CHECK(offer_data_description); - if (!SetCodecsInAnswer(offer_data_description, rtp_data_codecs, - media_description_options, session_options, - ssrc_generator_, current_streams, - data_answer->as_rtp_data())) { - return false; - } - if (!CreateMediaContentAnswer( - offer_data_description, media_description_options, session_options, - sdes_policy, GetCryptos(current_content), RtpHeaderExtensions(), - ssrc_generator_, enable_encrypted_rtp_header_extensions_, - current_streams, bundle_enabled, data_answer.get())) { - return false; // Fails the session setup. - } + const DataContentDescription* offer_data_description = + offer_content->media_description()->as_data(); + if (!CreateMediaContentAnswer( + offer_data_description, media_description_options, session_options, + data_codecs, sdes_policy, GetCryptos(current_content), + RtpHeaderExtensions(), ssrc_generator_, + enable_encrypted_rtp_header_extensions_, current_streams, + bundle_enabled, data_answer.get())) { + return false; // Fails the session setup. } + // Respond with sctpmap if the offer uses sctpmap. + bool offer_uses_sctpmap = offer_data_description->use_sctpmap(); + data_answer->set_use_sctpmap(offer_uses_sctpmap); + bool secure = bundle_transport ? bundle_transport->description.secure() : data_transport->secure(); @@ -2736,35 +2649,20 @@ const MediaContentDescription* GetFirstMediaContentDescription( const AudioContentDescription* GetFirstAudioContentDescription( const SessionDescription* sdesc) { - auto desc = GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_AUDIO); - return desc ? desc->as_audio() : nullptr; + return static_cast<const AudioContentDescription*>( + GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_AUDIO)); } const VideoContentDescription* GetFirstVideoContentDescription( const SessionDescription* sdesc) { - auto desc = GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_VIDEO); - return desc ? desc->as_video() : nullptr; -} - -const RtpDataContentDescription* GetFirstRtpDataContentDescription( - const SessionDescription* sdesc) { - auto desc = GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_DATA); - return desc ? desc->as_rtp_data() : nullptr; + return static_cast<const VideoContentDescription*>( + GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_VIDEO)); } -const SctpDataContentDescription* GetFirstSctpDataContentDescription( - const SessionDescription* sdesc) { - auto desc = GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_DATA); - return desc ? desc->as_sctp() : nullptr; -} - -// Returns a shim representing either an SctpDataContentDescription -// or an RtpDataContentDescription, as appropriate. -// TODO(bugs.webrtc.org/10597): Remove together with shim. const DataContentDescription* GetFirstDataContentDescription( const SessionDescription* sdesc) { - auto desc = GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_DATA); - return desc ? desc->as_data() : nullptr; + return static_cast<const DataContentDescription*>( + GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_DATA)); } // @@ -2823,33 +2721,20 @@ MediaContentDescription* GetFirstMediaContentDescription( AudioContentDescription* GetFirstAudioContentDescription( SessionDescription* sdesc) { - auto desc = GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_AUDIO); - return desc ? desc->as_audio() : nullptr; + return static_cast<AudioContentDescription*>( + GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_AUDIO)); } VideoContentDescription* GetFirstVideoContentDescription( SessionDescription* sdesc) { - auto desc = GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_VIDEO); - return desc ? desc->as_video() : nullptr; -} - -RtpDataContentDescription* GetFirstRtpDataContentDescription( - SessionDescription* sdesc) { - auto desc = GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_DATA); - return desc ? desc->as_rtp_data() : nullptr; -} - -SctpDataContentDescription* GetFirstSctpDataContentDescription( - SessionDescription* sdesc) { - auto desc = GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_DATA); - return desc ? desc->as_sctp() : nullptr; + return static_cast<VideoContentDescription*>( + GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_VIDEO)); } -// Returns shim DataContentDescription* GetFirstDataContentDescription( SessionDescription* sdesc) { - auto desc = GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_DATA); - return desc ? desc->as_data() : nullptr; + return static_cast<DataContentDescription*>( + GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_DATA)); } } // namespace cricket diff --git a/pc/media_session.h b/pc/media_session.h index dc889b215f..a369756964 100644 --- a/pc/media_session.h +++ b/pc/media_session.h @@ -24,7 +24,6 @@ #include "p2p/base/ice_credentials_iterator.h" #include "p2p/base/transport_description_factory.h" #include "pc/jsep_transport.h" -#include "pc/media_protocol_names.h" #include "pc/session_description.h" #include "rtc_base/unique_id_generator.h" @@ -155,10 +154,8 @@ class MediaSessionDescriptionFactory { video_rtp_extensions_ = extensions; } RtpHeaderExtensions video_rtp_header_extensions() const; - const RtpDataCodecs& rtp_data_codecs() const { return rtp_data_codecs_; } - void set_rtp_data_codecs(const RtpDataCodecs& codecs) { - rtp_data_codecs_ = codecs; - } + const DataCodecs& data_codecs() const { return data_codecs_; } + void set_data_codecs(const DataCodecs& codecs) { data_codecs_ = codecs; } SecurePolicy secure() const { return secure_; } void set_secure(SecurePolicy s) { secure_ = s; } @@ -188,13 +185,13 @@ class MediaSessionDescriptionFactory { const std::vector<const ContentInfo*>& current_active_contents, AudioCodecs* audio_codecs, VideoCodecs* video_codecs, - RtpDataCodecs* rtp_data_codecs) const; + DataCodecs* data_codecs) const; void GetCodecsForAnswer( const std::vector<const ContentInfo*>& current_active_contents, const SessionDescription& remote_offer, AudioCodecs* audio_codecs, VideoCodecs* video_codecs, - RtpDataCodecs* rtp_data_codecs) const; + DataCodecs* data_codecs) const; void GetRtpHdrExtsToOffer( const std::vector<const ContentInfo*>& current_active_contents, RtpHeaderExtensions* audio_extensions, @@ -243,32 +240,12 @@ class MediaSessionDescriptionFactory { SessionDescription* desc, IceCredentialsIterator* ice_credentials) const; - bool AddSctpDataContentForOffer( - const MediaDescriptionOptions& media_description_options, - const MediaSessionOptions& session_options, - const ContentInfo* current_content, - const SessionDescription* current_description, - StreamParamsVec* current_streams, - SessionDescription* desc, - IceCredentialsIterator* ice_credentials) const; - bool AddRtpDataContentForOffer( - const MediaDescriptionOptions& media_description_options, - const MediaSessionOptions& session_options, - const ContentInfo* current_content, - const SessionDescription* current_description, - const RtpDataCodecs& rtp_data_codecs, - StreamParamsVec* current_streams, - SessionDescription* desc, - IceCredentialsIterator* ice_credentials) const; - // This function calls either AddRtpDataContentForOffer or - // AddSctpDataContentForOffer depending on protocol. - // The codecs argument is ignored for SCTP. bool AddDataContentForOffer( const MediaDescriptionOptions& media_description_options, const MediaSessionOptions& session_options, const ContentInfo* current_content, const SessionDescription* current_description, - const RtpDataCodecs& rtp_data_codecs, + const DataCodecs& data_codecs, StreamParamsVec* current_streams, SessionDescription* desc, IceCredentialsIterator* ice_credentials) const; @@ -307,7 +284,7 @@ class MediaSessionDescriptionFactory { const ContentInfo* current_content, const SessionDescription* current_description, const TransportInfo* bundle_transport, - const RtpDataCodecs& rtp_data_codecs, + const DataCodecs& data_codecs, StreamParamsVec* current_streams, SessionDescription* answer, IceCredentialsIterator* ice_credentials) const; @@ -324,7 +301,7 @@ class MediaSessionDescriptionFactory { RtpHeaderExtensions audio_rtp_extensions_; VideoCodecs video_codecs_; RtpHeaderExtensions video_rtp_extensions_; - RtpDataCodecs rtp_data_codecs_; + DataCodecs data_codecs_; // This object is not owned by the channel so it must outlive it. rtc::UniqueRandomIdGenerator* const ssrc_generator_; bool enable_encrypted_rtp_header_extensions_ = false; @@ -353,11 +330,6 @@ const AudioContentDescription* GetFirstAudioContentDescription( const SessionDescription* sdesc); const VideoContentDescription* GetFirstVideoContentDescription( const SessionDescription* sdesc); -const RtpDataContentDescription* GetFirstRtpDataContentDescription( - const SessionDescription* sdesc); -const SctpDataContentDescription* GetFirstSctpDataContentDescription( - const SessionDescription* sdesc); -// Returns shim. Deprecated - ask for the right protocol instead. const DataContentDescription* GetFirstDataContentDescription( const SessionDescription* sdesc); // Non-const versions of the above functions. @@ -375,10 +347,6 @@ AudioContentDescription* GetFirstAudioContentDescription( SessionDescription* sdesc); VideoContentDescription* GetFirstVideoContentDescription( SessionDescription* sdesc); -RtpDataContentDescription* GetFirstRtpDataContentDescription( - SessionDescription* sdesc); -SctpDataContentDescription* GetFirstSctpDataContentDescription( - SessionDescription* sdesc); DataContentDescription* GetFirstDataContentDescription( SessionDescription* sdesc); @@ -402,6 +370,9 @@ void GetSupportedDataSdesCryptoSuiteNames( const webrtc::CryptoOptions& crypto_options, std::vector<std::string>* crypto_suite_names); +// Returns true if the given media section protocol indicates use of RTP. +bool IsRtpProtocol(const std::string& protocol); + } // namespace cricket #endif // PC_MEDIA_SESSION_H_ diff --git a/pc/media_session_unittest.cc b/pc/media_session_unittest.cc index b69ded3e1f..11366071ce 100644 --- a/pc/media_session_unittest.cc +++ b/pc/media_session_unittest.cc @@ -42,10 +42,12 @@ using cricket::AudioCodec; using cricket::AudioContentDescription; using cricket::ContentInfo; using cricket::CryptoParamsVec; +using cricket::DataCodec; +using cricket::DataContentDescription; using cricket::GetFirstAudioContent; using cricket::GetFirstAudioContentDescription; using cricket::GetFirstDataContent; -using cricket::GetFirstRtpDataContentDescription; +using cricket::GetFirstDataContentDescription; using cricket::GetFirstVideoContent; using cricket::GetFirstVideoContentDescription; using cricket::kAutoBandwidth; @@ -60,9 +62,6 @@ using cricket::MediaSessionOptions; using cricket::MediaType; using cricket::RidDescription; using cricket::RidDirection; -using cricket::RtpDataCodec; -using cricket::RtpDataContentDescription; -using cricket::SctpDataContentDescription; using cricket::SEC_DISABLED; using cricket::SEC_ENABLED; using cricket::SEC_REQUIRED; @@ -127,14 +126,14 @@ static const VideoCodec kVideoCodecs2[] = {VideoCodec(126, "H264"), static const VideoCodec kVideoCodecsAnswer[] = {VideoCodec(97, "H264")}; -static const RtpDataCodec kDataCodecs1[] = {RtpDataCodec(98, "binary-data"), - RtpDataCodec(99, "utf8-text")}; +static const DataCodec kDataCodecs1[] = {DataCodec(98, "binary-data"), + DataCodec(99, "utf8-text")}; -static const RtpDataCodec kDataCodecs2[] = {RtpDataCodec(126, "binary-data"), - RtpDataCodec(127, "utf8-text")}; +static const DataCodec kDataCodecs2[] = {DataCodec(126, "binary-data"), + DataCodec(127, "utf8-text")}; -static const RtpDataCodec kDataCodecsAnswer[] = { - RtpDataCodec(98, "binary-data"), RtpDataCodec(99, "utf8-text")}; +static const DataCodec kDataCodecsAnswer[] = {DataCodec(98, "binary-data"), + DataCodec(99, "utf8-text")}; static const RtpExtension kAudioRtpExtension1[] = { RtpExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8), @@ -413,11 +412,11 @@ class MediaSessionDescriptionFactoryTest : public ::testing::Test { f1_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs1), MAKE_VECTOR(kAudioCodecs1)); f1_.set_video_codecs(MAKE_VECTOR(kVideoCodecs1)); - f1_.set_rtp_data_codecs(MAKE_VECTOR(kDataCodecs1)); + f1_.set_data_codecs(MAKE_VECTOR(kDataCodecs1)); f2_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs2), MAKE_VECTOR(kAudioCodecs2)); f2_.set_video_codecs(MAKE_VECTOR(kVideoCodecs2)); - f2_.set_rtp_data_codecs(MAKE_VECTOR(kDataCodecs2)); + f2_.set_data_codecs(MAKE_VECTOR(kDataCodecs2)); tdf1_.set_certificate(rtc::RTCCertificate::Create( std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id1")))); tdf2_.set_certificate(rtc::RTCCertificate::Create( @@ -802,7 +801,7 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoOffer) { TEST_F(MediaSessionDescriptionFactoryTest, TestBundleOfferWithSameCodecPlType) { const VideoCodec& offered_video_codec = f2_.video_codecs()[0]; const AudioCodec& offered_audio_codec = f2_.audio_sendrecv_codecs()[0]; - const RtpDataCodec& offered_data_codec = f2_.rtp_data_codecs()[0]; + const DataCodec& offered_data_codec = f2_.data_codecs()[0]; ASSERT_EQ(offered_video_codec.id, offered_audio_codec.id); ASSERT_EQ(offered_video_codec.id, offered_data_codec.id); @@ -815,8 +814,8 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestBundleOfferWithSameCodecPlType) { GetFirstVideoContentDescription(offer.get()); const AudioContentDescription* acd = GetFirstAudioContentDescription(offer.get()); - const RtpDataContentDescription* dcd = - GetFirstRtpDataContentDescription(offer.get()); + const DataContentDescription* dcd = + GetFirstDataContentDescription(offer.get()); ASSERT_TRUE(NULL != vcd); ASSERT_TRUE(NULL != acd); ASSERT_TRUE(NULL != dcd); @@ -859,8 +858,8 @@ TEST_F(MediaSessionDescriptionFactoryTest, GetFirstAudioContentDescription(updated_offer.get()); const VideoContentDescription* vcd = GetFirstVideoContentDescription(updated_offer.get()); - const RtpDataContentDescription* dcd = - GetFirstRtpDataContentDescription(updated_offer.get()); + const DataContentDescription* dcd = + GetFirstDataContentDescription(updated_offer.get()); EXPECT_TRUE(NULL != vcd); EXPECT_TRUE(NULL != acd); EXPECT_TRUE(NULL != dcd); @@ -888,7 +887,7 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateRtpDataOffer) { EXPECT_EQ(MediaProtocolType::kRtp, ac->type); EXPECT_EQ(MediaProtocolType::kRtp, dc->type); const AudioContentDescription* acd = ac->media_description()->as_audio(); - const RtpDataContentDescription* dcd = dc->media_description()->as_rtp_data(); + const DataContentDescription* dcd = dc->media_description()->as_data(); EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type()); EXPECT_EQ(f1_.audio_sendrecv_codecs(), acd->codecs()); EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attched. @@ -897,7 +896,7 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateRtpDataOffer) { ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite); EXPECT_EQ(cricket::kMediaProtocolSavpf, acd->protocol()); EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type()); - EXPECT_EQ(f1_.rtp_data_codecs(), dcd->codecs()); + EXPECT_EQ(f1_.data_codecs(), dcd->codecs()); EXPECT_EQ(0U, dcd->first_ssrc()); // no sender is attached. EXPECT_EQ(cricket::kDataMaxBandwidth, dcd->bandwidth()); // default bandwidth (auto) @@ -1281,7 +1280,7 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswer) { EXPECT_EQ(MediaProtocolType::kRtp, ac->type); EXPECT_EQ(MediaProtocolType::kRtp, dc->type); const AudioContentDescription* acd = ac->media_description()->as_audio(); - const RtpDataContentDescription* dcd = dc->media_description()->as_rtp_data(); + const DataContentDescription* dcd = dc->media_description()->as_data(); EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type()); EXPECT_THAT(acd->codecs(), ElementsAreArray(kAudioCodecsAnswer)); EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw @@ -1313,7 +1312,7 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswerGcm) { EXPECT_EQ(MediaProtocolType::kRtp, ac->type); EXPECT_EQ(MediaProtocolType::kRtp, dc->type); const AudioContentDescription* acd = ac->media_description()->as_audio(); - const RtpDataContentDescription* dcd = dc->media_description()->as_rtp_data(); + const DataContentDescription* dcd = dc->media_description()->as_data(); EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type()); EXPECT_THAT(acd->codecs(), ElementsAreArray(kAudioCodecsAnswer)); EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw @@ -1337,16 +1336,15 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswerUsesSctpmap) { ASSERT_TRUE(offer.get() != NULL); ContentInfo* dc_offer = offer->GetContentByName("data"); ASSERT_TRUE(dc_offer != NULL); - SctpDataContentDescription* dcd_offer = - dc_offer->media_description()->as_sctp(); + DataContentDescription* dcd_offer = dc_offer->media_description()->as_data(); EXPECT_TRUE(dcd_offer->use_sctpmap()); std::unique_ptr<SessionDescription> answer = f2_.CreateAnswer(offer.get(), opts, NULL); const ContentInfo* dc_answer = answer->GetContentByName("data"); ASSERT_TRUE(dc_answer != NULL); - const SctpDataContentDescription* dcd_answer = - dc_answer->media_description()->as_sctp(); + const DataContentDescription* dcd_answer = + dc_answer->media_description()->as_data(); EXPECT_TRUE(dcd_answer->use_sctpmap()); } @@ -1358,16 +1356,15 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswerWithoutSctpmap) { ASSERT_TRUE(offer.get() != NULL); ContentInfo* dc_offer = offer->GetContentByName("data"); ASSERT_TRUE(dc_offer != NULL); - SctpDataContentDescription* dcd_offer = - dc_offer->media_description()->as_sctp(); + DataContentDescription* dcd_offer = dc_offer->media_description()->as_data(); dcd_offer->set_use_sctpmap(false); std::unique_ptr<SessionDescription> answer = f2_.CreateAnswer(offer.get(), opts, NULL); const ContentInfo* dc_answer = answer->GetContentByName("data"); ASSERT_TRUE(dc_answer != NULL); - const SctpDataContentDescription* dcd_answer = - dc_answer->media_description()->as_sctp(); + const DataContentDescription* dcd_answer = + dc_answer->media_description()->as_data(); EXPECT_FALSE(dcd_answer->use_sctpmap()); } @@ -1388,9 +1385,7 @@ TEST_F(MediaSessionDescriptionFactoryTest, ASSERT_TRUE(offer.get() != nullptr); ContentInfo* dc_offer = offer->GetContentByName("data"); ASSERT_TRUE(dc_offer != nullptr); - SctpDataContentDescription* dcd_offer = - dc_offer->media_description()->as_sctp(); - ASSERT_TRUE(dcd_offer); + DataContentDescription* dcd_offer = dc_offer->media_description()->as_data(); std::vector<std::string> protos = {"DTLS/SCTP", "UDP/DTLS/SCTP", "TCP/DTLS/SCTP"}; @@ -1400,8 +1395,8 @@ TEST_F(MediaSessionDescriptionFactoryTest, f2_.CreateAnswer(offer.get(), opts, nullptr); const ContentInfo* dc_answer = answer->GetContentByName("data"); ASSERT_TRUE(dc_answer != nullptr); - const SctpDataContentDescription* dcd_answer = - dc_answer->media_description()->as_sctp(); + const DataContentDescription* dcd_answer = + dc_answer->media_description()->as_data(); EXPECT_FALSE(dc_answer->rejected); EXPECT_EQ(proto, dcd_answer->protocol()); } @@ -1483,11 +1478,9 @@ TEST_F(MediaSessionDescriptionFactoryTest, std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL); ContentInfo* dc_offer = offer->GetContentByName("data"); ASSERT_TRUE(dc_offer != NULL); - RtpDataContentDescription* dcd_offer = - dc_offer->media_description()->as_rtp_data(); + DataContentDescription* dcd_offer = dc_offer->media_description()->as_data(); ASSERT_TRUE(dcd_offer != NULL); - // Offer must be acceptable as an RTP protocol in order to be set. - std::string protocol = "RTP/a weird unknown protocol"; + std::string protocol = "a weird unknown protocol"; dcd_offer->set_protocol(protocol); std::unique_ptr<SessionDescription> answer = @@ -1496,8 +1489,8 @@ TEST_F(MediaSessionDescriptionFactoryTest, const ContentInfo* dc_answer = answer->GetContentByName("data"); ASSERT_TRUE(dc_answer != NULL); EXPECT_TRUE(dc_answer->rejected); - const RtpDataContentDescription* dcd_answer = - dc_answer->media_description()->as_rtp_data(); + const DataContentDescription* dcd_answer = + dc_answer->media_description()->as_data(); ASSERT_TRUE(dcd_answer != NULL); EXPECT_EQ(protocol, dcd_answer->protocol()); } @@ -1695,7 +1688,7 @@ TEST_F(MediaSessionDescriptionFactoryTest, ASSERT_TRUE(vc != NULL); const AudioContentDescription* acd = ac->media_description()->as_audio(); const VideoContentDescription* vcd = vc->media_description()->as_video(); - const RtpDataContentDescription* dcd = dc->media_description()->as_rtp_data(); + const DataContentDescription* dcd = dc->media_description()->as_data(); EXPECT_FALSE(acd->has_ssrcs()); // No StreamParams. EXPECT_FALSE(vcd->has_ssrcs()); // No StreamParams. @@ -1723,16 +1716,16 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerRtcpMux) { answer = f2_.CreateAnswer(offer.get(), answer_opts, NULL); ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get())); ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get())); - ASSERT_TRUE(NULL != GetFirstRtpDataContentDescription(offer.get())); + ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get())); ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get())); ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get())); - ASSERT_TRUE(NULL != GetFirstRtpDataContentDescription(answer.get())); + ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get())); EXPECT_TRUE(GetFirstAudioContentDescription(offer.get())->rtcp_mux()); EXPECT_TRUE(GetFirstVideoContentDescription(offer.get())->rtcp_mux()); - EXPECT_TRUE(GetFirstRtpDataContentDescription(offer.get())->rtcp_mux()); + EXPECT_TRUE(GetFirstDataContentDescription(offer.get())->rtcp_mux()); EXPECT_TRUE(GetFirstAudioContentDescription(answer.get())->rtcp_mux()); EXPECT_TRUE(GetFirstVideoContentDescription(answer.get())->rtcp_mux()); - EXPECT_TRUE(GetFirstRtpDataContentDescription(answer.get())->rtcp_mux()); + EXPECT_TRUE(GetFirstDataContentDescription(answer.get())->rtcp_mux()); offer_opts.rtcp_mux_enabled = true; answer_opts.rtcp_mux_enabled = false; @@ -1740,16 +1733,16 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerRtcpMux) { answer = f2_.CreateAnswer(offer.get(), answer_opts, NULL); ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get())); ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get())); - ASSERT_TRUE(NULL != GetFirstRtpDataContentDescription(offer.get())); + ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get())); ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get())); ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get())); - ASSERT_TRUE(NULL != GetFirstRtpDataContentDescription(answer.get())); + ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get())); EXPECT_TRUE(GetFirstAudioContentDescription(offer.get())->rtcp_mux()); EXPECT_TRUE(GetFirstVideoContentDescription(offer.get())->rtcp_mux()); - EXPECT_TRUE(GetFirstRtpDataContentDescription(offer.get())->rtcp_mux()); + EXPECT_TRUE(GetFirstDataContentDescription(offer.get())->rtcp_mux()); EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux()); EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux()); - EXPECT_FALSE(GetFirstRtpDataContentDescription(answer.get())->rtcp_mux()); + EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux()); offer_opts.rtcp_mux_enabled = false; answer_opts.rtcp_mux_enabled = true; @@ -1757,16 +1750,16 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerRtcpMux) { answer = f2_.CreateAnswer(offer.get(), answer_opts, NULL); ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get())); ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get())); - ASSERT_TRUE(NULL != GetFirstRtpDataContentDescription(offer.get())); + ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get())); ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get())); ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get())); - ASSERT_TRUE(NULL != GetFirstRtpDataContentDescription(answer.get())); + ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get())); EXPECT_FALSE(GetFirstAudioContentDescription(offer.get())->rtcp_mux()); EXPECT_FALSE(GetFirstVideoContentDescription(offer.get())->rtcp_mux()); - EXPECT_FALSE(GetFirstRtpDataContentDescription(offer.get())->rtcp_mux()); + EXPECT_FALSE(GetFirstDataContentDescription(offer.get())->rtcp_mux()); EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux()); EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux()); - EXPECT_FALSE(GetFirstRtpDataContentDescription(answer.get())->rtcp_mux()); + EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux()); offer_opts.rtcp_mux_enabled = false; answer_opts.rtcp_mux_enabled = false; @@ -1774,16 +1767,16 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerRtcpMux) { answer = f2_.CreateAnswer(offer.get(), answer_opts, NULL); ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get())); ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get())); - ASSERT_TRUE(NULL != GetFirstRtpDataContentDescription(offer.get())); + ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get())); ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get())); ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get())); - ASSERT_TRUE(NULL != GetFirstRtpDataContentDescription(answer.get())); + ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get())); EXPECT_FALSE(GetFirstAudioContentDescription(offer.get())->rtcp_mux()); EXPECT_FALSE(GetFirstVideoContentDescription(offer.get())->rtcp_mux()); - EXPECT_FALSE(GetFirstRtpDataContentDescription(offer.get())->rtcp_mux()); + EXPECT_FALSE(GetFirstDataContentDescription(offer.get())->rtcp_mux()); EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux()); EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux()); - EXPECT_FALSE(GetFirstRtpDataContentDescription(answer.get())->rtcp_mux()); + EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux()); } // Create an audio-only answer to a video offer. @@ -1955,7 +1948,7 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoOffer) { ASSERT_TRUE(dc != NULL); const AudioContentDescription* acd = ac->media_description()->as_audio(); const VideoContentDescription* vcd = vc->media_description()->as_video(); - const RtpDataContentDescription* dcd = dc->media_description()->as_rtp_data(); + const DataContentDescription* dcd = dc->media_description()->as_data(); EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type()); EXPECT_EQ(f1_.audio_sendrecv_codecs(), acd->codecs()); @@ -1985,7 +1978,7 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoOffer) { EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type()); - EXPECT_EQ(f1_.rtp_data_codecs(), dcd->codecs()); + EXPECT_EQ(f1_.data_codecs(), dcd->codecs()); ASSERT_CRYPTO(dcd, 1U, kDefaultSrtpCryptoSuite); const StreamParamsVec& data_streams = dcd->streams(); @@ -2027,8 +2020,8 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoOffer) { ac->media_description()->as_audio(); const VideoContentDescription* updated_vcd = vc->media_description()->as_video(); - const RtpDataContentDescription* updated_dcd = - dc->media_description()->as_rtp_data(); + const DataContentDescription* updated_dcd = + dc->media_description()->as_data(); EXPECT_EQ(acd->type(), updated_acd->type()); EXPECT_EQ(acd->codecs(), updated_acd->codecs()); @@ -2314,7 +2307,7 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoAnswer) { ASSERT_TRUE(dc != NULL); const AudioContentDescription* acd = ac->media_description()->as_audio(); const VideoContentDescription* vcd = vc->media_description()->as_video(); - const RtpDataContentDescription* dcd = dc->media_description()->as_rtp_data(); + const DataContentDescription* dcd = dc->media_description()->as_data(); ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite); ASSERT_CRYPTO(vcd, 1U, kDefaultSrtpCryptoSuite); ASSERT_CRYPTO(dcd, 1U, kDefaultSrtpCryptoSuite); @@ -2382,8 +2375,8 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoAnswer) { ac->media_description()->as_audio(); const VideoContentDescription* updated_vcd = vc->media_description()->as_video(); - const RtpDataContentDescription* updated_dcd = - dc->media_description()->as_rtp_data(); + const DataContentDescription* updated_dcd = + dc->media_description()->as_data(); ASSERT_CRYPTO(updated_acd, 1U, kDefaultSrtpCryptoSuite); EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos())); @@ -3543,8 +3536,8 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoOfferDtlsButNotSdes) { const VideoContentDescription* video_offer = GetFirstVideoContentDescription(offer.get()); ASSERT_TRUE(video_offer->cryptos().empty()); - const RtpDataContentDescription* data_offer = - GetFirstRtpDataContentDescription(offer.get()); + const DataContentDescription* data_offer = + GetFirstDataContentDescription(offer.get()); ASSERT_TRUE(data_offer->cryptos().empty()); const cricket::TransportDescription* audio_offer_trans_desc = @@ -4075,11 +4068,11 @@ class MediaProtocolTest : public ::testing::TestWithParam<const char*> { f1_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs1), MAKE_VECTOR(kAudioCodecs1)); f1_.set_video_codecs(MAKE_VECTOR(kVideoCodecs1)); - f1_.set_rtp_data_codecs(MAKE_VECTOR(kDataCodecs1)); + f1_.set_data_codecs(MAKE_VECTOR(kDataCodecs1)); f2_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs2), MAKE_VECTOR(kAudioCodecs2)); f2_.set_video_codecs(MAKE_VECTOR(kVideoCodecs2)); - f2_.set_rtp_data_codecs(MAKE_VECTOR(kDataCodecs2)); + f2_.set_data_codecs(MAKE_VECTOR(kDataCodecs2)); f1_.set_secure(SEC_ENABLED); f2_.set_secure(SEC_ENABLED); tdf1_.set_certificate(rtc::RTCCertificate::Create( diff --git a/pc/peer_connection.cc b/pc/peer_connection.cc index 7cdd9831fb..8a6d0e57ac 100644 --- a/pc/peer_connection.cc +++ b/pc/peer_connection.cc @@ -559,13 +559,24 @@ bool VerifyIceUfragPwdPresent(const SessionDescription* desc) { // Get the SCTP port out of a SessionDescription. // Return -1 if not found. int GetSctpPort(const SessionDescription* session_description) { - const cricket::SctpDataContentDescription* data_desc = - GetFirstSctpDataContentDescription(session_description); + const cricket::DataContentDescription* data_desc = + GetFirstDataContentDescription(session_description); RTC_DCHECK(data_desc); if (!data_desc) { return -1; } - return data_desc->port(); + std::string value; + cricket::DataCodec match_pattern(cricket::kGoogleSctpDataCodecPlType, + cricket::kGoogleSctpDataCodecName); + for (const cricket::DataCodec& codec : data_desc->codecs()) { + if (!codec.Matches(match_pattern)) { + continue; + } + if (codec.GetParam(cricket::kCodecParamPort, &value)) { + return rtc::FromString<int>(value); + } + } + return -1; } // Returns true if |new_desc| requests an ICE restart (i.e., new ufrag/pwd). @@ -2412,11 +2423,11 @@ RTCError PeerConnection::ApplyLocalDescription( const cricket::ContentInfo* data_content = GetFirstDataContent(local_description()->description()); if (data_content) { - const cricket::RtpDataContentDescription* rtp_data_desc = - data_content->media_description()->as_rtp_data(); - // rtp_data_desc will be null if this is an SCTP description. - if (rtp_data_desc) { - UpdateLocalRtpDataChannels(rtp_data_desc->streams()); + const cricket::DataContentDescription* data_desc = + data_content->media_description()->as_data(); + if (absl::StartsWith(data_desc->protocol(), + cricket::kMediaProtocolRtpPrefix)) { + UpdateLocalRtpDataChannels(data_desc->streams()); } } @@ -2822,8 +2833,8 @@ RTCError PeerConnection::ApplyRemoteDescription( GetFirstAudioContentDescription(remote_description()->description()); const cricket::VideoContentDescription* video_desc = GetFirstVideoContentDescription(remote_description()->description()); - const cricket::RtpDataContentDescription* rtp_data_desc = - GetFirstRtpDataContentDescription(remote_description()->description()); + const cricket::DataContentDescription* data_desc = + GetFirstDataContentDescription(remote_description()->description()); // Check if the descriptions include streams, just in case the peer supports // MSID, but doesn't indicate so with "a=msid-semantic". @@ -2876,10 +2887,12 @@ RTCError PeerConnection::ApplyRemoteDescription( } } - // If this is an RTP data transport, update the DataChannels with the - // information from the remote peer. - if (rtp_data_desc) { - UpdateRemoteRtpDataChannels(GetActiveStreams(rtp_data_desc)); + // Update the DataChannels with the information from the remote peer. + if (data_desc) { + if (absl::StartsWith(data_desc->protocol(), + cricket::kMediaProtocolRtpPrefix)) { + UpdateRemoteRtpDataChannels(GetActiveStreams(data_desc)); + } } // Iterate new_streams and notify the observer about new MediaStreams. diff --git a/pc/peer_connection_data_channel_unittest.cc b/pc/peer_connection_data_channel_unittest.cc index 4080dd98bb..ad3817e5b5 100644 --- a/pc/peer_connection_data_channel_unittest.cc +++ b/pc/peer_connection_data_channel_unittest.cc @@ -193,11 +193,14 @@ class PeerConnectionDataChannelBaseTest : public ::testing::Test { // Changes the SCTP data channel port on the given session description. void ChangeSctpPortOnDescription(cricket::SessionDescription* desc, int port) { + cricket::DataCodec sctp_codec(cricket::kGoogleSctpDataCodecPlType, + cricket::kGoogleSctpDataCodecName); + sctp_codec.SetParam(cricket::kCodecParamPort, port); + auto* data_content = cricket::GetFirstDataContent(desc); RTC_DCHECK(data_content); - auto* data_desc = data_content->media_description()->as_sctp(); - RTC_DCHECK(data_desc); - data_desc->set_port(port); + auto* data_desc = data_content->media_description()->as_data(); + data_desc->set_codecs({sctp_codec}); } std::unique_ptr<rtc::VirtualSocketServer> vss_; diff --git a/pc/peer_connection_integrationtest.cc b/pc/peer_connection_integrationtest.cc index e84ffe0360..6087f0f4f6 100644 --- a/pc/peer_connection_integrationtest.cc +++ b/pc/peer_connection_integrationtest.cc @@ -3450,8 +3450,8 @@ TEST_P(PeerConnectionIntegrationTest, SctpDataChannelToAudioVideoUpgrade) { } static void MakeSpecCompliantSctpOffer(cricket::SessionDescription* desc) { - cricket::SctpDataContentDescription* dcd_offer = - GetFirstSctpDataContentDescription(desc); + cricket::DataContentDescription* dcd_offer = + GetFirstDataContentDescription(desc); ASSERT_TRUE(dcd_offer); dcd_offer->set_use_sctpmap(false); dcd_offer->set_protocol("UDP/DTLS/SCTP"); diff --git a/pc/session_description.cc b/pc/session_description.cc index 925acb6819..d4ccb5082e 100644 --- a/pc/session_description.cc +++ b/pc/session_description.cc @@ -15,7 +15,6 @@ #include "absl/algorithm/container.h" #include "absl/memory/memory.h" -#include "pc/media_protocol_names.h" #include "rtc_base/checks.h" namespace cricket { @@ -184,24 +183,6 @@ void SessionDescription::AddContent(const std::string& name, } void SessionDescription::AddContent(ContentInfo* content) { - // Unwrap the as_data shim layer before using. - auto* description = content->media_description(); - bool should_delete = false; - if (description->as_rtp_data()) { - if (description->as_rtp_data() != description) { - content->set_media_description( - description->as_data()->Unshim(&should_delete)); - } - } - if (description->as_sctp()) { - if (description->as_sctp() != description) { - content->set_media_description( - description->as_data()->Unshim(&should_delete)); - } - } - if (should_delete) { - delete description; - } if (extmap_allow_mixed()) { // Mixed support on session level overrides setting on media level. content->description->set_extmap_allow_mixed_enum( @@ -291,404 +272,4 @@ const ContentGroup* SessionDescription::GetGroupByName( return NULL; } -// DataContentDescription shim creation -DataContentDescription* RtpDataContentDescription::as_data() { - if (!shim_) { - shim_.reset(new DataContentDescription(this)); - } - return shim_.get(); -} - -const DataContentDescription* RtpDataContentDescription::as_data() const { - return const_cast<RtpDataContentDescription*>(this)->as_data(); -} - -DataContentDescription* SctpDataContentDescription::as_data() { - if (!shim_) { - shim_.reset(new DataContentDescription(this)); - } - return shim_.get(); -} - -const DataContentDescription* SctpDataContentDescription::as_data() const { - return const_cast<SctpDataContentDescription*>(this)->as_data(); -} - -DataContentDescription::DataContentDescription() { - // In this case, we will initialize |owned_description_| as soon as - // we are told what protocol to use via set_protocol or another function - // calling CreateShimTarget. -} - -DataContentDescription::DataContentDescription( - SctpDataContentDescription* wrapped) - : real_description_(wrapped) { - // SctpDataContentDescription doesn't contain codecs, but code - // using DataContentDescription expects to see one. - Super::AddCodec( - cricket::DataCodec(kGoogleSctpDataCodecPlType, kGoogleSctpDataCodecName)); -} - -DataContentDescription::DataContentDescription( - RtpDataContentDescription* wrapped) - : real_description_(wrapped) {} - -DataContentDescription::DataContentDescription( - const DataContentDescription* o) { - if (o->real_description_) { - owned_description_ = absl::WrapUnique(o->real_description_->Copy()); - real_description_ = owned_description_.get(); - } -} - -void DataContentDescription::CreateShimTarget(bool is_sctp) { - RTC_LOG(LS_INFO) << "Creating shim target, is_sctp is " << is_sctp; - RTC_CHECK(!owned_description_.get()); - if (is_sctp) { - owned_description_ = absl::make_unique<SctpDataContentDescription>(); - // Copy all information collected so far, except codecs. - owned_description_->MediaContentDescription::operator=(*this); - } else { - owned_description_ = absl::make_unique<RtpDataContentDescription>(); - // Copy all information collected so far, including codecs. - owned_description_->as_rtp_data() - ->MediaContentDescriptionImpl<RtpDataCodec>::operator=(*this); - } - real_description_ = owned_description_.get(); -} - -MediaContentDescription* DataContentDescription::Unshim(bool* should_delete) { - if (owned_description_) { - // Pass ownership to caller, and remove myself. - // Since caller can't know if I was owner or owned, tell them. - MediaContentDescription* to_return = owned_description_.release(); - *should_delete = true; - return to_return; - } - // Real object is owner, and presumably referenced from elsewhere. - *should_delete = false; - return real_description_; -} - -void DataContentDescription::set_protocol(const std::string& protocol) { - if (real_description_) { - real_description_->set_protocol(protocol); - } else { - CreateShimTarget(IsSctpProtocol(protocol)); - } -} - -bool DataContentDescription::IsSctp() const { - return (real_description_ && real_description_->as_sctp()); -} - -void DataContentDescription::EnsureIsRtp() { - RTC_CHECK(real_description_); - RTC_CHECK(real_description_->as_rtp_data()); -} - -RtpDataContentDescription* DataContentDescription::as_rtp_data() { - if (real_description_) { - return real_description_->as_rtp_data(); - } - return nullptr; -} - -SctpDataContentDescription* DataContentDescription::as_sctp() { - if (real_description_) { - return real_description_->as_sctp(); - } - return nullptr; -} - -// Override all methods defined in MediaContentDescription. -bool DataContentDescription::has_codecs() const { - if (!real_description_) { - return Super::has_codecs(); - } - return real_description_->has_codecs(); -} -std::string DataContentDescription::protocol() const { - if (!real_description_) { - return Super::protocol(); - } - return real_description_->protocol(); -} - -webrtc::RtpTransceiverDirection DataContentDescription::direction() const { - if (!real_description_) { - return Super::direction(); - } - return real_description_->direction(); -} -void DataContentDescription::set_direction( - webrtc::RtpTransceiverDirection direction) { - if (!real_description_) { - return Super::set_direction(direction); - } - return real_description_->set_direction(direction); -} -bool DataContentDescription::rtcp_mux() const { - if (!real_description_) { - return Super::rtcp_mux(); - } - return real_description_->rtcp_mux(); -} -void DataContentDescription::set_rtcp_mux(bool mux) { - if (!real_description_) { - Super::set_rtcp_mux(mux); - return; - } - real_description_->set_rtcp_mux(mux); -} -bool DataContentDescription::rtcp_reduced_size() const { - if (!real_description_) { - return Super::rtcp_reduced_size(); - } - return real_description_->rtcp_reduced_size(); -} -void DataContentDescription::set_rtcp_reduced_size(bool reduced_size) { - if (!real_description_) { - return Super::set_rtcp_reduced_size(reduced_size); - } - - return real_description_->set_rtcp_reduced_size(reduced_size); -} -int DataContentDescription::bandwidth() const { - if (!real_description_) { - return Super::bandwidth(); - } - - return real_description_->bandwidth(); -} -void DataContentDescription::set_bandwidth(int bandwidth) { - if (!real_description_) { - return Super::set_bandwidth(bandwidth); - } - - return real_description_->set_bandwidth(bandwidth); -} -const std::vector<CryptoParams>& DataContentDescription::cryptos() const { - if (!real_description_) { - return Super::cryptos(); - } - - return real_description_->cryptos(); -} -void DataContentDescription::AddCrypto(const CryptoParams& params) { - if (!real_description_) { - return Super::AddCrypto(params); - } - - return real_description_->AddCrypto(params); -} -void DataContentDescription::set_cryptos( - const std::vector<CryptoParams>& cryptos) { - if (!real_description_) { - return Super::set_cryptos(cryptos); - } - - return real_description_->set_cryptos(cryptos); -} -const RtpHeaderExtensions& DataContentDescription::rtp_header_extensions() - const { - if (!real_description_) { - return Super::rtp_header_extensions(); - } - - return real_description_->rtp_header_extensions(); -} -void DataContentDescription::set_rtp_header_extensions( - const RtpHeaderExtensions& extensions) { - if (!real_description_) { - return Super::set_rtp_header_extensions(extensions); - } - - return real_description_->set_rtp_header_extensions(extensions); -} -void DataContentDescription::AddRtpHeaderExtension( - const webrtc::RtpExtension& ext) { - if (!real_description_) { - return Super::AddRtpHeaderExtension(ext); - } - return real_description_->AddRtpHeaderExtension(ext); -} -void DataContentDescription::AddRtpHeaderExtension( - const cricket::RtpHeaderExtension& ext) { - if (!real_description_) { - return Super::AddRtpHeaderExtension(ext); - } - return real_description_->AddRtpHeaderExtension(ext); -} -void DataContentDescription::ClearRtpHeaderExtensions() { - if (!real_description_) { - return Super::ClearRtpHeaderExtensions(); - } - return real_description_->ClearRtpHeaderExtensions(); -} -bool DataContentDescription::rtp_header_extensions_set() const { - if (!real_description_) { - return Super::rtp_header_extensions_set(); - } - return real_description_->rtp_header_extensions_set(); -} -const StreamParamsVec& DataContentDescription::streams() const { - if (!real_description_) { - return Super::streams(); - } - return real_description_->streams(); -} -StreamParamsVec& DataContentDescription::mutable_streams() { - if (!real_description_) { - return Super::mutable_streams(); - } - EnsureIsRtp(); - return real_description_->mutable_streams(); -} -void DataContentDescription::AddStream(const StreamParams& stream) { - if (!real_description_) { - return Super::AddStream(stream); - } - EnsureIsRtp(); - return real_description_->AddStream(stream); -} -void DataContentDescription::SetCnameIfEmpty(const std::string& cname) { - if (!real_description_) { - return Super::SetCnameIfEmpty(cname); - } - return real_description_->SetCnameIfEmpty(cname); -} -uint32_t DataContentDescription::first_ssrc() const { - if (!real_description_) { - return Super::first_ssrc(); - } - return real_description_->first_ssrc(); -} -bool DataContentDescription::has_ssrcs() const { - if (!real_description_) { - return Super::has_ssrcs(); - } - return real_description_->has_ssrcs(); -} -void DataContentDescription::set_conference_mode(bool enable) { - if (!real_description_) { - return Super::set_conference_mode(enable); - } - return real_description_->set_conference_mode(enable); -} -bool DataContentDescription::conference_mode() const { - if (!real_description_) { - return Super::conference_mode(); - } - return real_description_->conference_mode(); -} -void DataContentDescription::set_connection_address( - const rtc::SocketAddress& address) { - if (!real_description_) { - return Super::set_connection_address(address); - } - return real_description_->set_connection_address(address); -} -const rtc::SocketAddress& DataContentDescription::connection_address() const { - if (!real_description_) { - return Super::connection_address(); - } - return real_description_->connection_address(); -} -void DataContentDescription::set_extmap_allow_mixed_enum( - ExtmapAllowMixed mixed) { - if (!real_description_) { - return Super::set_extmap_allow_mixed_enum(mixed); - } - return real_description_->set_extmap_allow_mixed_enum(mixed); -} -MediaContentDescription::ExtmapAllowMixed -DataContentDescription::extmap_allow_mixed_enum() const { - if (!real_description_) { - return Super::extmap_allow_mixed_enum(); - } - return real_description_->extmap_allow_mixed_enum(); -} -bool DataContentDescription::HasSimulcast() const { - if (!real_description_) { - return Super::HasSimulcast(); - } - return real_description_->HasSimulcast(); -} -SimulcastDescription& DataContentDescription::simulcast_description() { - if (!real_description_) { - return Super::simulcast_description(); - } - return real_description_->simulcast_description(); -} -const SimulcastDescription& DataContentDescription::simulcast_description() - const { - if (!real_description_) { - return Super::simulcast_description(); - } - return real_description_->simulcast_description(); -} -void DataContentDescription::set_simulcast_description( - const SimulcastDescription& simulcast) { - if (!real_description_) { - return Super::set_simulcast_description(simulcast); - } - return real_description_->set_simulcast_description(simulcast); -} - -// Methods defined in MediaContentDescriptionImpl. -// For SCTP, we implement codec handling. -// For RTP, we pass the codecs. -// In the cases where type hasn't been decided yet, we return dummies. - -const std::vector<DataCodec>& DataContentDescription::codecs() const { - if (IsSctp() || !real_description_) { - return Super::codecs(); - } - return real_description_->as_rtp_data()->codecs(); -} - -void DataContentDescription::set_codecs(const std::vector<DataCodec>& codecs) { - if (IsSctp() || !real_description_) { - Super::set_codecs(codecs); - } else { - EnsureIsRtp(); - real_description_->as_rtp_data()->set_codecs(codecs); - } -} - -bool DataContentDescription::HasCodec(int id) { - if (IsSctp() || !real_description_) { - return Super::HasCodec(id); - } - return real_description_->as_rtp_data()->HasCodec(id); -} - -void DataContentDescription::AddCodec(const DataCodec& codec) { - if (IsSctp() || !real_description_) { - Super::AddCodec(codec); - } else { - EnsureIsRtp(); - real_description_->as_rtp_data()->AddCodec(codec); - } -} - -void DataContentDescription::AddOrReplaceCodec(const DataCodec& codec) { - if (IsSctp() || real_description_) { - Super::AddOrReplaceCodec(codec); - } else { - EnsureIsRtp(); - real_description_->as_rtp_data()->AddOrReplaceCodec(codec); - } -} - -void DataContentDescription::AddCodecs(const std::vector<DataCodec>& codecs) { - if (IsSctp() || !real_description_) { - Super::AddCodecs(codecs); - } else { - EnsureIsRtp(); - real_description_->as_rtp_data()->AddCodecs(codecs); - } -} - } // namespace cricket diff --git a/pc/session_description.h b/pc/session_description.h index 60c3d6b92c..7b70ddf556 100644 --- a/pc/session_description.h +++ b/pc/session_description.h @@ -18,7 +18,6 @@ #include <string> #include <vector> -#include "absl/memory/memory.h" #include "api/crypto_params.h" #include "api/media_types.h" #include "api/rtp_parameters.h" @@ -27,7 +26,6 @@ #include "media/base/stream_params.h" #include "p2p/base/transport_description.h" #include "p2p/base/transport_info.h" -#include "pc/media_protocol_names.h" #include "pc/simulcast_description.h" #include "rtc_base/socket_address.h" @@ -35,7 +33,7 @@ namespace cricket { typedef std::vector<AudioCodec> AudioCodecs; typedef std::vector<VideoCodec> VideoCodecs; -typedef std::vector<RtpDataCodec> RtpDataCodecs; +typedef std::vector<DataCodec> DataCodecs; typedef std::vector<CryptoParams> CryptoParamsVec; typedef std::vector<webrtc::RtpExtension> RtpHeaderExtensions; @@ -46,15 +44,19 @@ extern const char kMediaProtocolSavpf[]; extern const char kMediaProtocolDtlsSavpf[]; +extern const char kMediaProtocolRtpPrefix[]; + +extern const char kMediaProtocolSctp[]; +extern const char kMediaProtocolDtlsSctp[]; +extern const char kMediaProtocolUdpDtlsSctp[]; +extern const char kMediaProtocolTcpDtlsSctp[]; // Options to control how session descriptions are generated. const int kAutoBandwidth = -1; class AudioContentDescription; -class VideoContentDescription; class DataContentDescription; -class RtpDataContentDescription; -class SctpDataContentDescription; +class VideoContentDescription; // Describes a session description media section. There are subclasses for each // media type (audio, video, data) that will have additional information. @@ -75,77 +77,61 @@ class MediaContentDescription { virtual VideoContentDescription* as_video() { return nullptr; } virtual const VideoContentDescription* as_video() const { return nullptr; } - // Backwards compatible shim: Return a shim object that allows - // callers to ignore the distinction between RtpDataContentDescription - // and SctpDataContentDescription objects. + // Try to cast this media description to a DataContentDescription. Returns + // nullptr if the cast fails. virtual DataContentDescription* as_data() { return nullptr; } virtual const DataContentDescription* as_data() const { return nullptr; } - virtual RtpDataContentDescription* as_rtp_data() { return nullptr; } - virtual const RtpDataContentDescription* as_rtp_data() const { - return nullptr; - } - - virtual SctpDataContentDescription* as_sctp() { return nullptr; } - virtual const SctpDataContentDescription* as_sctp() const { return nullptr; } - virtual bool has_codecs() const = 0; virtual MediaContentDescription* Copy() const = 0; // |protocol| is the expected media transport protocol, such as RTP/AVPF, // RTP/SAVPF or SCTP/DTLS. - virtual std::string protocol() const { return protocol_; } - virtual void set_protocol(const std::string& protocol) { - protocol_ = protocol; - } + std::string protocol() const { return protocol_; } + void set_protocol(const std::string& protocol) { protocol_ = protocol; } - virtual webrtc::RtpTransceiverDirection direction() const { - return direction_; - } - virtual void set_direction(webrtc::RtpTransceiverDirection direction) { + webrtc::RtpTransceiverDirection direction() const { return direction_; } + void set_direction(webrtc::RtpTransceiverDirection direction) { direction_ = direction; } - virtual bool rtcp_mux() const { return rtcp_mux_; } - virtual void set_rtcp_mux(bool mux) { rtcp_mux_ = mux; } + bool rtcp_mux() const { return rtcp_mux_; } + void set_rtcp_mux(bool mux) { rtcp_mux_ = mux; } - virtual bool rtcp_reduced_size() const { return rtcp_reduced_size_; } - virtual void set_rtcp_reduced_size(bool reduced_size) { + bool rtcp_reduced_size() const { return rtcp_reduced_size_; } + void set_rtcp_reduced_size(bool reduced_size) { rtcp_reduced_size_ = reduced_size; } - virtual int bandwidth() const { return bandwidth_; } - virtual void set_bandwidth(int bandwidth) { bandwidth_ = bandwidth; } + int bandwidth() const { return bandwidth_; } + void set_bandwidth(int bandwidth) { bandwidth_ = bandwidth; } - virtual const std::vector<CryptoParams>& cryptos() const { return cryptos_; } - virtual void AddCrypto(const CryptoParams& params) { - cryptos_.push_back(params); - } - virtual void set_cryptos(const std::vector<CryptoParams>& cryptos) { + const std::vector<CryptoParams>& cryptos() const { return cryptos_; } + void AddCrypto(const CryptoParams& params) { cryptos_.push_back(params); } + void set_cryptos(const std::vector<CryptoParams>& cryptos) { cryptos_ = cryptos; } - virtual const RtpHeaderExtensions& rtp_header_extensions() const { + const RtpHeaderExtensions& rtp_header_extensions() const { return rtp_header_extensions_; } - virtual void set_rtp_header_extensions( - const RtpHeaderExtensions& extensions) { + void set_rtp_header_extensions(const RtpHeaderExtensions& extensions) { rtp_header_extensions_ = extensions; rtp_header_extensions_set_ = true; } - virtual void AddRtpHeaderExtension(const webrtc::RtpExtension& ext) { + void AddRtpHeaderExtension(const webrtc::RtpExtension& ext) { rtp_header_extensions_.push_back(ext); rtp_header_extensions_set_ = true; } - virtual void AddRtpHeaderExtension(const cricket::RtpHeaderExtension& ext) { + void AddRtpHeaderExtension(const cricket::RtpHeaderExtension& ext) { webrtc::RtpExtension webrtc_extension; webrtc_extension.uri = ext.uri; webrtc_extension.id = ext.id; rtp_header_extensions_.push_back(webrtc_extension); rtp_header_extensions_set_ = true; } - virtual void ClearRtpHeaderExtensions() { + void ClearRtpHeaderExtensions() { rtp_header_extensions_.clear(); rtp_header_extensions_set_ = true; } @@ -154,65 +140,62 @@ class MediaContentDescription { // signal them. For now we assume an empty list means no signaling, but // provide the ClearRtpHeaderExtensions method to allow "no support" to be // clearly indicated (i.e. when derived from other information). - virtual bool rtp_header_extensions_set() const { - return rtp_header_extensions_set_; - } - virtual const StreamParamsVec& streams() const { return send_streams_; } + bool rtp_header_extensions_set() const { return rtp_header_extensions_set_; } + const StreamParamsVec& streams() const { return send_streams_; } // TODO(pthatcher): Remove this by giving mediamessage.cc access // to MediaContentDescription - virtual StreamParamsVec& mutable_streams() { return send_streams_; } - virtual void AddStream(const StreamParams& stream) { + StreamParamsVec& mutable_streams() { return send_streams_; } + void AddStream(const StreamParams& stream) { send_streams_.push_back(stream); } // Legacy streams have an ssrc, but nothing else. void AddLegacyStream(uint32_t ssrc) { - AddStream(StreamParams::CreateLegacy(ssrc)); + send_streams_.push_back(StreamParams::CreateLegacy(ssrc)); } void AddLegacyStream(uint32_t ssrc, uint32_t fid_ssrc) { StreamParams sp = StreamParams::CreateLegacy(ssrc); sp.AddFidSsrc(ssrc, fid_ssrc); - AddStream(sp); + send_streams_.push_back(sp); } // Sets the CNAME of all StreamParams if it have not been set. - virtual void SetCnameIfEmpty(const std::string& cname) { + void SetCnameIfEmpty(const std::string& cname) { for (cricket::StreamParamsVec::iterator it = send_streams_.begin(); it != send_streams_.end(); ++it) { if (it->cname.empty()) it->cname = cname; } } - virtual uint32_t first_ssrc() const { + uint32_t first_ssrc() const { if (send_streams_.empty()) { return 0; } return send_streams_[0].first_ssrc(); } - virtual bool has_ssrcs() const { + bool has_ssrcs() const { if (send_streams_.empty()) { return false; } return send_streams_[0].has_ssrcs(); } - virtual void set_conference_mode(bool enable) { conference_mode_ = enable; } - virtual bool conference_mode() const { return conference_mode_; } + void set_conference_mode(bool enable) { conference_mode_ = enable; } + bool conference_mode() const { return conference_mode_; } // https://tools.ietf.org/html/rfc4566#section-5.7 // May be present at the media or session level of SDP. If present at both // levels, the media-level attribute overwrites the session-level one. - virtual void set_connection_address(const rtc::SocketAddress& address) { + void set_connection_address(const rtc::SocketAddress& address) { connection_address_ = address; } - virtual const rtc::SocketAddress& connection_address() const { + const rtc::SocketAddress& connection_address() const { return connection_address_; } // Determines if it's allowed to mix one- and two-byte rtp header extensions // within the same rtp stream. enum ExtmapAllowMixed { kNo, kSession, kMedia }; - virtual void set_extmap_allow_mixed_enum( - ExtmapAllowMixed new_extmap_allow_mixed) { + void set_extmap_allow_mixed_enum(ExtmapAllowMixed new_extmap_allow_mixed) { if (new_extmap_allow_mixed == kMedia && extmap_allow_mixed_enum_ == kSession) { // Do not downgrade from session level to media level. @@ -220,12 +203,10 @@ class MediaContentDescription { } extmap_allow_mixed_enum_ = new_extmap_allow_mixed; } - virtual ExtmapAllowMixed extmap_allow_mixed_enum() const { + ExtmapAllowMixed extmap_allow_mixed_enum() const { return extmap_allow_mixed_enum_; } - virtual bool extmap_allow_mixed() const { - return extmap_allow_mixed_enum_ != kNo; - } + bool extmap_allow_mixed() const { return extmap_allow_mixed_enum_ != kNo; } // Simulcast functionality. virtual bool HasSimulcast() const { return !simulcast_.empty(); } @@ -266,18 +247,13 @@ using ContentDescription = MediaContentDescription; template <class C> class MediaContentDescriptionImpl : public MediaContentDescription { public: - void set_protocol(const std::string& protocol) override { - RTC_DCHECK(IsRtpProtocol(protocol)); - protocol_ = protocol; - } - typedef C CodecType; // Codecs should be in preference order (most preferred codec first). - virtual const std::vector<C>& codecs() const { return codecs_; } - virtual void set_codecs(const std::vector<C>& codecs) { codecs_ = codecs; } - bool has_codecs() const override { return !codecs_.empty(); } - virtual bool HasCodec(int id) { + const std::vector<C>& codecs() const { return codecs_; } + void set_codecs(const std::vector<C>& codecs) { codecs_ = codecs; } + virtual bool has_codecs() const { return !codecs_.empty(); } + bool HasCodec(int id) { bool found = false; for (typename std::vector<C>::iterator iter = codecs_.begin(); iter != codecs_.end(); ++iter) { @@ -288,8 +264,8 @@ class MediaContentDescriptionImpl : public MediaContentDescription { } return found; } - virtual void AddCodec(const C& codec) { codecs_.push_back(codec); } - virtual void AddOrReplaceCodec(const C& codec) { + void AddCodec(const C& codec) { codecs_.push_back(codec); } + void AddOrReplaceCodec(const C& codec) { for (typename std::vector<C>::iterator iter = codecs_.begin(); iter != codecs_.end(); ++iter) { if (iter->id == codec.id) { @@ -299,7 +275,7 @@ class MediaContentDescriptionImpl : public MediaContentDescription { } AddCodec(codec); } - virtual void AddCodecs(const std::vector<C>& codecs) { + void AddCodecs(const std::vector<C>& codecs) { typename std::vector<C>::const_iterator codec; for (codec = codecs.begin(); codec != codecs.end(); ++codec) { AddCodec(*codec); @@ -332,173 +308,22 @@ class VideoContentDescription : public MediaContentDescriptionImpl<VideoCodec> { virtual const VideoContentDescription* as_video() const { return this; } }; -// The DataContentDescription is a shim over the RtpDataContentDescription -// and SctpDataContentDescription classes that is used for external callers -// into this internal API. -// It is a templated derivation of MediaContentDescriptionImpl because -// that's what the external caller expects it to be. -// TODO(bugs.webrtc.org/10597): Declare this class obsolete and remove it -// once external callers have been updated. class DataContentDescription : public MediaContentDescriptionImpl<DataCodec> { public: - DataContentDescription(); - MediaType type() const override { return MEDIA_TYPE_DATA; } - DataContentDescription* as_data() override { return this; } - const DataContentDescription* as_data() const override { return this; } - - // Override all methods defined in MediaContentDescription. - bool has_codecs() const override; - DataContentDescription* Copy() const override { - return new DataContentDescription(this); - } - std::string protocol() const override; - void set_protocol(const std::string& protocol) override; - webrtc::RtpTransceiverDirection direction() const override; - void set_direction(webrtc::RtpTransceiverDirection direction) override; - bool rtcp_mux() const override; - void set_rtcp_mux(bool mux) override; - bool rtcp_reduced_size() const override; - void set_rtcp_reduced_size(bool) override; - int bandwidth() const override; - void set_bandwidth(int bandwidth) override; - const std::vector<CryptoParams>& cryptos() const override; - void AddCrypto(const CryptoParams& params) override; - void set_cryptos(const std::vector<CryptoParams>& cryptos) override; - const RtpHeaderExtensions& rtp_header_extensions() const override; - void set_rtp_header_extensions( - const RtpHeaderExtensions& extensions) override; - void AddRtpHeaderExtension(const webrtc::RtpExtension& ext) override; - void AddRtpHeaderExtension(const cricket::RtpHeaderExtension& ext) override; - void ClearRtpHeaderExtensions() override; - bool rtp_header_extensions_set() const override; - const StreamParamsVec& streams() const override; - StreamParamsVec& mutable_streams() override; - void AddStream(const StreamParams& stream) override; - void SetCnameIfEmpty(const std::string& cname) override; - uint32_t first_ssrc() const override; - bool has_ssrcs() const override; - void set_conference_mode(bool enable) override; - bool conference_mode() const override; - void set_connection_address(const rtc::SocketAddress& address) override; - const rtc::SocketAddress& connection_address() const override; - void set_extmap_allow_mixed_enum(ExtmapAllowMixed) override; - ExtmapAllowMixed extmap_allow_mixed_enum() const override; - bool HasSimulcast() const override; - SimulcastDescription& simulcast_description() override; - const SimulcastDescription& simulcast_description() const override; - void set_simulcast_description( - const SimulcastDescription& simulcast) override; - - // Override all methods defined in MediaContentDescriptionImpl. - const std::vector<CodecType>& codecs() const override; - void set_codecs(const std::vector<CodecType>& codecs) override; - bool HasCodec(int id) override; - void AddCodec(const CodecType& codec) override; - void AddOrReplaceCodec(const CodecType& codec) override; - void AddCodecs(const std::vector<CodecType>& codec) override; + DataContentDescription() {} - private: - typedef MediaContentDescriptionImpl<DataCodec> Super; - // Friend classes are allowed to create proxies for themselves. - friend class RtpDataContentDescription; // for constructors - friend class SctpDataContentDescription; - friend class SessionDescription; // for Unshim() - // Copy constructor. A copy results in an object that owns its - // real description, which is a copy of the original description - // (whether that was owned or not). - explicit DataContentDescription(const DataContentDescription* o); - - explicit DataContentDescription(RtpDataContentDescription*); - explicit DataContentDescription(SctpDataContentDescription*); - - // Exposed for internal use - new clients should not use this class. - RtpDataContentDescription* as_rtp_data() override; - SctpDataContentDescription* as_sctp() override; - - // Create a shimmed object, owned by the shim. - void CreateShimTarget(bool is_sctp); - - // Return the shimmed object, passing ownership if owned, and set - // |should_delete| to true if it was the owner. If |should_delete| - // is true on return, the caller should immediately delete the - // DataContentDescription object. - MediaContentDescription* Unshim(bool* should_delete); - - // Returns whether SCTP is in use. False when it's not decided. - bool IsSctp() const; - // Check function for use when caller obviously assumes RTP. - void EnsureIsRtp(); - - MediaContentDescription* real_description_ = nullptr; - std::unique_ptr<MediaContentDescription> owned_description_; -}; - -class RtpDataContentDescription - : public MediaContentDescriptionImpl<RtpDataCodec> { - public: - RtpDataContentDescription() {} - RtpDataContentDescription(const RtpDataContentDescription& o) - : MediaContentDescriptionImpl<RtpDataCodec>(o), shim_(nullptr) {} - RtpDataContentDescription& operator=(const RtpDataContentDescription& o) { - this->MediaContentDescriptionImpl<RtpDataCodec>::operator=(o); - // Do not copy the shim. - return *this; - } - - RtpDataContentDescription* Copy() const override { - return new RtpDataContentDescription(*this); - } - MediaType type() const override { return MEDIA_TYPE_DATA; } - RtpDataContentDescription* as_rtp_data() override { return this; } - const RtpDataContentDescription* as_rtp_data() const override { return this; } - // Shim support - DataContentDescription* as_data() override; - const DataContentDescription* as_data() const override; - - private: - std::unique_ptr<DataContentDescription> shim_; -}; - -class SctpDataContentDescription : public MediaContentDescription { - public: - SctpDataContentDescription() {} - SctpDataContentDescription(const SctpDataContentDescription& o) - : MediaContentDescription(o), - use_sctpmap_(o.use_sctpmap_), - port_(o.port_), - max_message_size_(o.max_message_size_), - shim_(nullptr) {} - SctpDataContentDescription* Copy() const override { - return new SctpDataContentDescription(*this); - } - MediaType type() const override { return MEDIA_TYPE_DATA; } - SctpDataContentDescription* as_sctp() override { return this; } - const SctpDataContentDescription* as_sctp() const override { return this; } - // Shim support - DataContentDescription* as_data() override; - const DataContentDescription* as_data() const override; - - bool has_codecs() const override { return false; } - void set_protocol(const std::string& protocol) override { - RTC_DCHECK(IsSctpProtocol(protocol)); - protocol_ = protocol; + virtual DataContentDescription* Copy() const { + return new DataContentDescription(*this); } + virtual MediaType type() const { return MEDIA_TYPE_DATA; } + virtual DataContentDescription* as_data() { return this; } + virtual const DataContentDescription* as_data() const { return this; } bool use_sctpmap() const { return use_sctpmap_; } void set_use_sctpmap(bool enable) { use_sctpmap_ = enable; } - int port() const { return port_; } - void set_port(int port) { port_ = port; } - int max_message_size() const { return max_message_size_; } - void set_max_message_size(int max_message_size) { - max_message_size_ = max_message_size; - } private: - bool use_sctpmap_ = true; // Note: "true" is no longer conformant. - // Defaults should be constants imported from SCTP. Quick hack. - int port_ = 5000; - int max_message_size_ = 256 * 1024; - std::unique_ptr<DataContentDescription> shim_; + bool use_sctpmap_ = true; }; // Protocol used for encoding media. This is the "top level" protocol that may diff --git a/pc/session_description_unittest.cc b/pc/session_description_unittest.cc index 9797ed5627..3b05dca381 100644 --- a/pc/session_description_unittest.cc +++ b/pc/session_description_unittest.cc @@ -9,7 +9,6 @@ */ #include "pc/session_description.h" -#include "absl/memory/memory.h" #include "test/gtest.h" namespace cricket { @@ -122,69 +121,11 @@ TEST(SessionDescriptionTest, AddContentTransfersExtmapAllowMixedSetting) { video_desc->extmap_allow_mixed_enum()); // Session level setting overrides media level when new content is added. - MediaContentDescription* data_desc = new RtpDataContentDescription; + MediaContentDescription* data_desc = new DataContentDescription; data_desc->set_extmap_allow_mixed_enum(MediaContentDescription::kMedia); session_desc.AddContent("data", MediaProtocolType::kRtp, data_desc); EXPECT_EQ(MediaContentDescription::kSession, data_desc->extmap_allow_mixed_enum()); } -TEST(SessionDescriptionTest, DataContentDescriptionCanAddStream) { - auto description = absl::make_unique<DataContentDescription>(); - // Adding a stream without setting protocol first should work. - description->AddLegacyStream(1234); - EXPECT_EQ(1UL, description->streams().size()); -} - -TEST(SessionDescriptionTest, DataContentDescriptionCopyWorks) { - auto description = absl::make_unique<RtpDataContentDescription>(); - auto shim_description = description->as_data(); - auto shim_copy = shim_description->Copy(); - delete shim_copy; -} - -TEST(SessionDescriptionTest, DataContentDescriptionCodecsCallableOnNull) { - auto shim_description = absl::make_unique<DataContentDescription>(); - auto codec_list = shim_description->codecs(); - EXPECT_EQ(0UL, codec_list.size()); -} - -TEST(SessionDescriptionTest, DataContentDescriptionSctpConferenceMode) { - auto description = absl::make_unique<SctpDataContentDescription>(); - auto shim_description = description->as_data(); - EXPECT_FALSE(shim_description->conference_mode()); - shim_description->set_conference_mode(true); - EXPECT_TRUE(shim_description->conference_mode()); -} - -TEST(SessionDescriptionTest, DataContentDesriptionInSessionIsUnwrapped) { - auto description = absl::make_unique<DataContentDescription>(); - // Create a DTLS object behind the shim. - description->set_protocol(kMediaProtocolUdpDtlsSctp); - SessionDescription session; - session.AddContent("name", MediaProtocolType::kSctp, description.release()); - ContentInfo* content = &(session.contents()[0]); - ASSERT_TRUE(content); - ASSERT_TRUE(content->media_description()->type() == MEDIA_TYPE_DATA); - ASSERT_TRUE(content->media_description()->as_sctp()); -} - -TEST(SessionDescriptionTest, - DataContentDescriptionInfoSurvivesInstantiationAsSctp) { - auto description = absl::make_unique<DataContentDescription>(); - description->set_rtcp_mux(true); - description->set_protocol(kMediaProtocolUdpDtlsSctp); - EXPECT_TRUE(description->rtcp_mux()); -} - -TEST(SessionDescriptionTest, - DataContentDescriptionStreamInfoSurvivesInstantiationAsRtp) { - auto description = absl::make_unique<DataContentDescription>(); - StreamParams stream; - description->AddLegacyStream(1234); - EXPECT_EQ(1UL, description->streams().size()); - description->set_protocol(kMediaProtocolDtlsSavpf); - EXPECT_EQ(1UL, description->streams().size()); -} - } // namespace cricket diff --git a/pc/webrtc_sdp.cc b/pc/webrtc_sdp.cc index d89bd78390..984a1e14a1 100644 --- a/pc/webrtc_sdp.cc +++ b/pc/webrtc_sdp.cc @@ -54,31 +54,29 @@ using cricket::Candidates; using cricket::ContentInfo; using cricket::CryptoParams; using cricket::DataContentDescription; -using cricket::ICE_CANDIDATE_COMPONENT_RTCP; using cricket::ICE_CANDIDATE_COMPONENT_RTP; -using cricket::kCodecParamAssociatedPayloadType; -using cricket::kCodecParamMaxAverageBitrate; +using cricket::ICE_CANDIDATE_COMPONENT_RTCP; using cricket::kCodecParamMaxBitrate; -using cricket::kCodecParamMaxPlaybackRate; using cricket::kCodecParamMaxPTime; using cricket::kCodecParamMaxQuantization; using cricket::kCodecParamMinBitrate; using cricket::kCodecParamMinPTime; using cricket::kCodecParamPTime; -using cricket::kCodecParamSctpProtocol; -using cricket::kCodecParamSctpStreams; using cricket::kCodecParamSPropStereo; using cricket::kCodecParamStartBitrate; using cricket::kCodecParamStereo; -using cricket::kCodecParamUseDtx; using cricket::kCodecParamUseInbandFec; +using cricket::kCodecParamUseDtx; +using cricket::kCodecParamSctpProtocol; +using cricket::kCodecParamSctpStreams; +using cricket::kCodecParamMaxAverageBitrate; +using cricket::kCodecParamMaxPlaybackRate; +using cricket::kCodecParamAssociatedPayloadType; using cricket::MediaContentDescription; -using cricket::MediaProtocolType; using cricket::MediaType; -using cricket::RidDescription; -using cricket::RtpDataContentDescription; using cricket::RtpHeaderExtensions; -using cricket::SctpDataContentDescription; +using cricket::MediaProtocolType; +using cricket::RidDescription; using cricket::SimulcastDescription; using cricket::SimulcastLayer; using cricket::SimulcastLayerList; @@ -1339,6 +1337,8 @@ void BuildMediaDescription(const ContentInfo* content_info, const MediaContentDescription* media_desc = content_info->media_description(); RTC_DCHECK(media_desc); + int sctp_port = cricket::kSctpDefaultPort; + // RFC 4566 // m=<media> <port> <proto> <fmt> // fmt is a list of payload type numbers that MAY be used in the session. @@ -1366,19 +1366,25 @@ void BuildMediaDescription(const ContentInfo* content_info, fmt.append(rtc::ToString(codec.id)); } } else if (media_type == cricket::MEDIA_TYPE_DATA) { + const DataContentDescription* data_desc = media_desc->as_data(); if (IsDtlsSctp(media_desc->protocol())) { - const cricket::SctpDataContentDescription* data_desc = - media_desc->as_sctp(); fmt.append(" "); if (data_desc->use_sctpmap()) { - fmt.append(rtc::ToString(data_desc->port())); + for (const cricket::DataCodec& codec : data_desc->codecs()) { + if (absl::EqualsIgnoreCase(codec.name, + cricket::kGoogleSctpDataCodecName) && + codec.GetParam(cricket::kCodecParamPort, &sctp_port)) { + break; + } + } + + fmt.append(rtc::ToString(sctp_port)); } else { fmt.append(kDefaultSctpmapProtocol); } } else { - const RtpDataContentDescription* data_desc = media_desc->as_rtp_data(); - for (const cricket::RtpDataCodec& codec : data_desc->codecs()) { + for (const cricket::DataCodec& codec : data_desc->codecs()) { fmt.append(" "); fmt.append(rtc::ToString(codec.id)); } @@ -1517,10 +1523,9 @@ void BuildMediaDescription(const ContentInfo* content_info, AddLine(os.str(), message); if (IsDtlsSctp(media_desc->protocol())) { - const cricket::SctpDataContentDescription* data_desc = - media_desc->as_sctp(); + const DataContentDescription* data_desc = media_desc->as_data(); bool use_sctpmap = data_desc->use_sctpmap(); - BuildSctpContentAttributes(message, data_desc->port(), use_sctpmap); + BuildSctpContentAttributes(message, sctp_port, use_sctpmap); } else if (IsRtp(media_desc->protocol())) { BuildRtpContentAttributes(media_desc, media_type, msid_signaling, message); } @@ -1829,6 +1834,43 @@ void AddRtcpFbLines(const T& codec, std::string* message) { } } +cricket::DataCodec FindOrMakeSctpDataCodec(DataContentDescription* media_desc) { + for (const auto& codec : media_desc->codecs()) { + if (absl::EqualsIgnoreCase(codec.name, cricket::kGoogleSctpDataCodecName)) { + return codec; + } + } + cricket::DataCodec codec_port(cricket::kGoogleSctpDataCodecPlType, + cricket::kGoogleSctpDataCodecName); + return codec_port; +} + +bool AddOrModifySctpDataCodecPort(DataContentDescription* media_desc, + int sctp_port) { + // Add the SCTP Port number as a pseudo-codec "port" parameter + auto codec = FindOrMakeSctpDataCodec(media_desc); + int dummy; + if (codec.GetParam(cricket::kCodecParamPort, &dummy)) { + return false; + } + codec.SetParam(cricket::kCodecParamPort, sctp_port); + media_desc->AddOrReplaceCodec(codec); + return true; +} + +bool AddOrModifySctpDataMaxMessageSize(DataContentDescription* media_desc, + int max_message_size) { + // Add the SCTP Max Message Size as a pseudo-parameter to the codec + auto codec = FindOrMakeSctpDataCodec(media_desc); + int dummy; + if (codec.GetParam(cricket::kCodecParamMaxMessageSize, &dummy)) { + return false; + } + codec.SetParam(cricket::kCodecParamMaxMessageSize, max_message_size); + media_desc->AddOrReplaceCodec(codec); + return true; +} + bool GetMinValue(const std::vector<int>& values, int* value) { if (values.empty()) { return false; @@ -1918,8 +1960,7 @@ void BuildRtpMap(const MediaContentDescription* media_desc, AddAttributeLine(kCodecParamPTime, ptime, message); } } else if (media_type == cricket::MEDIA_TYPE_DATA) { - for (const cricket::RtpDataCodec& codec : - media_desc->as_rtp_data()->codecs()) { + for (const cricket::DataCodec& codec : media_desc->as_data()->codecs()) { // RFC 4566 // a=rtpmap:<payload type> <encoding name>/<clock rate> // [/<encodingparameters>] @@ -2707,36 +2748,24 @@ bool ParseMediaDescription( payload_types, pos, &content_name, &bundle_only, §ion_msid_signaling, &transport, candidates, error); } else if (HasAttribute(line, kMediaTypeData)) { - if (IsDtlsSctp(protocol)) { - // The draft-03 format is: - // m=application <port> DTLS/SCTP <sctp-port>... - // use_sctpmap should be false. - // The draft-26 format is: - // m=application <port> UDP/DTLS/SCTP webrtc-datachannel - // use_sctpmap should be false. - auto data_desc = absl::make_unique<SctpDataContentDescription>(); + std::unique_ptr<DataContentDescription> data_desc = + ParseContentDescription<DataContentDescription>( + message, cricket::MEDIA_TYPE_DATA, mline_index, protocol, + payload_types, pos, &content_name, &bundle_only, + §ion_msid_signaling, &transport, candidates, error); + + if (data_desc && IsDtlsSctp(protocol)) { int p; if (rtc::FromString(fields[3], &p)) { - data_desc->set_port(p); + if (!AddOrModifySctpDataCodecPort(data_desc.get(), p)) { + return false; + } } else if (fields[3] == kDefaultSctpmapProtocol) { data_desc->set_use_sctpmap(false); } - if (!ParseContent(message, cricket::MEDIA_TYPE_DATA, mline_index, - protocol, payload_types, pos, &content_name, - &bundle_only, §ion_msid_signaling, - data_desc.get(), &transport, candidates, error)) { - return false; - } - content = std::move(data_desc); - } else { - // RTP - std::unique_ptr<RtpDataContentDescription> data_desc = - ParseContentDescription<RtpDataContentDescription>( - message, cricket::MEDIA_TYPE_DATA, mline_index, protocol, - payload_types, pos, &content_name, &bundle_only, - §ion_msid_signaling, &transport, candidates, error); - content = std::move(data_desc); } + + content = std::move(data_desc); } else { RTC_LOG(LS_WARNING) << "Unsupported media type: " << line; continue; @@ -3109,15 +3138,13 @@ bool ParseContent(const std::string& message, line, "sctp-port attribute found in non-data media description.", error); } - if (media_desc->as_sctp()->use_sctpmap()) { - return ParseFailed( - line, "sctp-port attribute can't be used with sctpmap.", error); - } int sctp_port; if (!ParseSctpPort(line, &sctp_port, error)) { return false; } - media_desc->as_sctp()->set_port(sctp_port); + if (!AddOrModifySctpDataCodecPort(media_desc->as_data(), sctp_port)) { + return false; + } } else if (IsDtlsSctp(protocol) && HasAttribute(line, kAttributeMaxMessageSize)) { if (media_type != cricket::MEDIA_TYPE_DATA) { @@ -3130,7 +3157,10 @@ bool ParseContent(const std::string& message, if (!ParseSctpMaxMessageSize(line, &max_message_size, error)) { return false; } - media_desc->as_sctp()->set_max_message_size(max_message_size); + if (!AddOrModifySctpDataMaxMessageSize(media_desc->as_data(), + max_message_size)) { + return false; + } } else if (IsRtp(protocol)) { // // RTP specific attrubtes @@ -3591,8 +3621,8 @@ bool ParseRtpmapAttribute(const std::string& line, UpdateCodec(payload_type, encoding_name, clock_rate, 0, channels, audio_desc); } else if (media_type == cricket::MEDIA_TYPE_DATA) { - RtpDataContentDescription* data_desc = media_desc->as_rtp_data(); - data_desc->AddCodec(cricket::RtpDataCodec(payload_type, encoding_name)); + DataContentDescription* data_desc = media_desc->as_data(); + data_desc->AddCodec(cricket::DataCodec(payload_type, encoding_name)); } return true; } diff --git a/pc/webrtc_sdp_unittest.cc b/pc/webrtc_sdp_unittest.cc index 367fac84d7..3de2b602dd 100644 --- a/pc/webrtc_sdp_unittest.cc +++ b/pc/webrtc_sdp_unittest.cc @@ -56,6 +56,7 @@ using cricket::ContentGroup; using cricket::ContentInfo; using cricket::CryptoParams; using cricket::DataCodec; +using cricket::DataContentDescription; using cricket::ICE_CANDIDATE_COMPONENT_RTCP; using cricket::ICE_CANDIDATE_COMPONENT_RTP; using cricket::kFecSsrcGroupSemantics; @@ -64,8 +65,6 @@ using cricket::MediaProtocolType; using cricket::RELAY_PORT_TYPE; using cricket::RidDescription; using cricket::RidDirection; -using cricket::RtpDataContentDescription; -using cricket::SctpDataContentDescription; using cricket::SessionDescription; using cricket::SimulcastDescription; using cricket::SimulcastLayer; @@ -276,7 +275,6 @@ static const char kSdpRtpDataChannelString[] = "a=ssrc:10 mslabel:data_channel\r\n" "a=ssrc:10 label:data_channeld0\r\n"; -// draft-ietf-mmusic-sctp-sdp-03 static const char kSdpSctpDataChannelString[] = "m=application 9 DTLS/SCTP 5000\r\n" "c=IN IP4 0.0.0.0\r\n" @@ -1445,17 +1443,10 @@ class WebRtcSdpTest : public ::testing::Test { simulcast2.receive_layers().size()); } - void CompareRtpDataContentDescription(const RtpDataContentDescription* dcd1, - const RtpDataContentDescription* dcd2) { - CompareMediaContentDescription<RtpDataContentDescription>(dcd1, dcd2); - } - - void CompareSctpDataContentDescription( - const SctpDataContentDescription* dcd1, - const SctpDataContentDescription* dcd2) { + void CompareDataContentDescription(const DataContentDescription* dcd1, + const DataContentDescription* dcd2) { EXPECT_EQ(dcd1->use_sctpmap(), dcd2->use_sctpmap()); - EXPECT_EQ(dcd1->port(), dcd2->port()); - EXPECT_EQ(dcd1->max_message_size(), dcd2->max_message_size()); + CompareMediaContentDescription<DataContentDescription>(dcd1, dcd2); } void CompareSessionDescription(const SessionDescription& desc1, @@ -1493,21 +1484,10 @@ class WebRtcSdpTest : public ::testing::Test { } ASSERT_EQ(IsDataContent(&c1), IsDataContent(&c2)); - if (c1.media_description()->as_sctp()) { - ASSERT_TRUE(c2.media_description()->as_sctp()); - const SctpDataContentDescription* scd1 = - c1.media_description()->as_sctp(); - const SctpDataContentDescription* scd2 = - c2.media_description()->as_sctp(); - CompareSctpDataContentDescription(scd1, scd2); - } else { - if (IsDataContent(&c1)) { - const RtpDataContentDescription* dcd1 = - c1.media_description()->as_rtp_data(); - const RtpDataContentDescription* dcd2 = - c2.media_description()->as_rtp_data(); - CompareRtpDataContentDescription(dcd1, dcd2); - } + if (IsDataContent(&c1)) { + const DataContentDescription* dcd1 = c1.media_description()->as_data(); + const DataContentDescription* dcd2 = c2.media_description()->as_data(); + CompareDataContentDescription(dcd1, dcd2); } CompareSimulcastDescription( @@ -1780,12 +1760,14 @@ class WebRtcSdpTest : public ::testing::Test { } void AddSctpDataChannel(bool use_sctpmap) { - std::unique_ptr<SctpDataContentDescription> data( - new SctpDataContentDescription()); - sctp_desc_ = data.get(); - sctp_desc_->set_use_sctpmap(use_sctpmap); - sctp_desc_->set_protocol(cricket::kMediaProtocolDtlsSctp); - sctp_desc_->set_port(kDefaultSctpPort); + std::unique_ptr<DataContentDescription> data(new DataContentDescription()); + data_desc_ = data.get(); + data_desc_->set_use_sctpmap(use_sctpmap); + data_desc_->set_protocol(cricket::kMediaProtocolDtlsSctp); + DataCodec codec(cricket::kGoogleSctpDataCodecPlType, + cricket::kGoogleSctpDataCodecName); + codec.SetParam(cricket::kCodecParamPort, kDefaultSctpPort); + data_desc_->AddCodec(codec); desc_.AddContent(kDataContentName, MediaProtocolType::kSctp, data.release()); desc_.AddTransportInfo(TransportInfo( @@ -1793,8 +1775,7 @@ class WebRtcSdpTest : public ::testing::Test { } void AddRtpDataChannel() { - std::unique_ptr<RtpDataContentDescription> data( - new RtpDataContentDescription()); + std::unique_ptr<DataContentDescription> data(new DataContentDescription()); data_desc_ = data.get(); data_desc_->AddCodec(DataCodec(101, "google-data")); @@ -2062,8 +2043,7 @@ class WebRtcSdpTest : public ::testing::Test { SessionDescription desc_; AudioContentDescription* audio_desc_; VideoContentDescription* video_desc_; - RtpDataContentDescription* data_desc_; - SctpDataContentDescription* sctp_desc_; + DataContentDescription* data_desc_; Candidates candidates_; std::unique_ptr<IceCandidateInterface> jcandidate_; JsepSessionDescription jdesc_; @@ -2235,26 +2215,21 @@ TEST_F(WebRtcSdpTest, SerializeSessionDescriptionWithSctpDataChannel) { EXPECT_EQ(message, expected_sdp); } -void MutateJsepSctpPort(JsepSessionDescription* jdesc, - const SessionDescription& desc, - int port) { - // Take our pre-built session description and change the SCTP port. - cricket::SessionDescription* mutant = desc.Copy(); - SctpDataContentDescription* dcdesc = - mutant->GetContentDescriptionByName(kDataContentName)->as_sctp(); - dcdesc->set_port(port); - // Note: mutant's owned by jdesc now. - ASSERT_TRUE(jdesc->Initialize(mutant, kSessionId, kSessionVersion)); -} - TEST_F(WebRtcSdpTest, SerializeWithSctpDataChannelAndNewPort) { bool use_sctpmap = true; AddSctpDataChannel(use_sctpmap); JsepSessionDescription jsep_desc(kDummyType); MakeDescriptionWithoutCandidates(&jsep_desc); + DataContentDescription* dcdesc = + jsep_desc.description() + ->GetContentDescriptionByName(kDataContentName) + ->as_data(); const int kNewPort = 1234; - MutateJsepSctpPort(&jsep_desc, desc_, kNewPort); + cricket::DataCodec codec(cricket::kGoogleSctpDataCodecPlType, + cricket::kGoogleSctpDataCodecName); + codec.SetParam(cricket::kCodecParamPort, kNewPort); + dcdesc->AddOrReplaceCodec(codec); std::string message = webrtc::SdpSerialize(jsep_desc); @@ -2893,12 +2868,14 @@ TEST_F(WebRtcSdpTest, DeserializeSdpWithSctpDataChannelsWithSctpColonPort) { // Helper function to set the max-message-size parameter in the // SCTP data codec. void MutateJsepSctpMaxMessageSize(const SessionDescription& desc, - int new_value, + const std::string& new_value, JsepSessionDescription* jdesc) { cricket::SessionDescription* mutant = desc.Copy(); - SctpDataContentDescription* dcdesc = - mutant->GetContentDescriptionByName(kDataContentName)->as_sctp(); - dcdesc->set_max_message_size(new_value); + DataContentDescription* dcdesc = + mutant->GetContentDescriptionByName(kDataContentName)->as_data(); + std::vector<cricket::DataCodec> codecs(dcdesc->codecs()); + codecs[0].SetParam(cricket::kCodecParamMaxMessageSize, new_value); + dcdesc->set_codecs(codecs); jdesc->Initialize(mutant, kSessionId, kSessionVersion); } @@ -2910,7 +2887,7 @@ TEST_F(WebRtcSdpTest, DeserializeSdpWithSctpDataChannelsWithMaxMessageSize) { sdp_with_data.append(kSdpSctpDataChannelStringWithSctpColonPort); sdp_with_data.append("a=max-message-size:12345\r\n"); - MutateJsepSctpMaxMessageSize(desc_, 12345, &jdesc); + MutateJsepSctpMaxMessageSize(desc_, "12345", &jdesc); JsepSessionDescription jdesc_output(kDummyType); // Verify with DTLS/SCTP. @@ -2960,13 +2937,29 @@ TEST_F(WebRtcSdpTest, DeserializeSdpWithCorruptedSctpDataChannels) { // No crash is a pass. } +void MutateJsepSctpPort(JsepSessionDescription* jdesc, + const SessionDescription& desc) { + // take our pre-built session description and change the SCTP port. + std::unique_ptr<cricket::SessionDescription> mutant = desc.Clone(); + DataContentDescription* dcdesc = + mutant->GetContentDescriptionByName(kDataContentName)->as_data(); + std::vector<cricket::DataCodec> codecs(dcdesc->codecs()); + EXPECT_EQ(1U, codecs.size()); + EXPECT_EQ(cricket::kGoogleSctpDataCodecPlType, codecs[0].id); + codecs[0].SetParam(cricket::kCodecParamPort, kUnusualSctpPort); + dcdesc->set_codecs(codecs); + + ASSERT_TRUE( + jdesc->Initialize(std::move(mutant), kSessionId, kSessionVersion)); +} + TEST_F(WebRtcSdpTest, DeserializeSdpWithSctpDataChannelAndUnusualPort) { bool use_sctpmap = true; AddSctpDataChannel(use_sctpmap); // First setup the expected JsepSessionDescription. JsepSessionDescription jdesc(kDummyType); - MutateJsepSctpPort(&jdesc, desc_, kUnusualSctpPort); + MutateJsepSctpPort(&jdesc, desc_); // Then get the deserialized JsepSessionDescription. std::string sdp_with_data = kSdpString; @@ -2986,7 +2979,7 @@ TEST_F(WebRtcSdpTest, AddSctpDataChannel(use_sctpmap); JsepSessionDescription jdesc(kDummyType); - MutateJsepSctpPort(&jdesc, desc_, kUnusualSctpPort); + MutateJsepSctpPort(&jdesc, desc_); // We need to test the deserialized JsepSessionDescription from // kSdpSctpDataChannelStringWithSctpPort for @@ -3022,7 +3015,7 @@ TEST_F(WebRtcSdpTest, DeserializeSdpWithSctpDataChannelsAndBandwidth) { bool use_sctpmap = true; AddSctpDataChannel(use_sctpmap); JsepSessionDescription jdesc(kDummyType); - SctpDataContentDescription* dcd = GetFirstSctpDataContentDescription(&desc_); + DataContentDescription* dcd = GetFirstDataContentDescription(&desc_); dcd->set_bandwidth(100 * 1000); ASSERT_TRUE(jdesc.Initialize(desc_.Clone(), kSessionId, kSessionVersion)); |