Reland "Reland "Version 2 "Refactoring DataContentDescription class"""
This reverts commit 46afbf9481fbcc939c998c898ca1031ce41cc6b1.
Reason for revert: Tightened protocol name handling.
Original change's description:
> Revert "Reland "Version 2 "Refactoring DataContentDescription class"""
>
> This reverts commit 37f2b43274a0d718de53a4cfcf02226356edcf6e.
>
> Reason for revert: fuzzer failures
>
> Original change's description:
> > Reland "Version 2 "Refactoring DataContentDescription class""
> >
> > This is a reland of 14b2758726879d21671a21291dfed8fb4fd5c21c
> >
> > Original change's description:
> > > Version 2 "Refactoring DataContentDescription class"
> > >
> > > (substantial changes since version 1)
> > >
> > > This CL splits the cricket::DataContentDescription class into
> > > two classes: cricket::RtpDataContentDescription (used for RTP data)
> > > and cricket::SctpDataContentDescription (used for SCTP only).
> > >
> > > SctpDataContentDescription no longer inherits from
> > > MediaContentDescriptionImpl, and no longer contains "codecs".
> > >
> > > Due to usage of internal interfaces by consumers, shimming the old
> > > DataContentDescription API is needed.
> > >
> > > A new cricket::DataContentDescription class is defined, which is
> > > a shim over RtpDataContentDescription and SctpDataContentDescription.
> > > It exposes as little functionality as possible, but supports the
> > > concerned consumer's usage
> > >
> > > Design document:
> > > https://docs.google.com/document/d/1H5LfQxJA2ikMWTQ8FZ3_GAmaXM7knfVQWiSz6ph8VQ0/edit#
> > >
> > > Version 1 reviewed-on: https://webrtc-review.googlesource.com/c/src/+/132700
> > >
Bug: webrtc:10358
Change-Id: Ia9fb8f4679e082e3d18fbbb6b03fc13a08e06110
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/136581
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Commit-Queue: Harald Alvestrand <hta@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#27933}
diff --git a/media/base/codec.cc b/media/base/codec.cc
index d0ca29b..4380514 100644
--- a/media/base/codec.cc
+++ b/media/base/codec.cc
@@ -334,22 +334,22 @@
return true;
}
-DataCodec::DataCodec(int id, const std::string& name)
+RtpDataCodec::RtpDataCodec(int id, const std::string& name)
: Codec(id, name, kDataCodecClockrate) {}
-DataCodec::DataCodec() : Codec() {
+RtpDataCodec::RtpDataCodec() : Codec() {
clockrate = kDataCodecClockrate;
}
-DataCodec::DataCodec(const DataCodec& c) = default;
-DataCodec::DataCodec(DataCodec&& c) = default;
-DataCodec& DataCodec::operator=(const DataCodec& c) = default;
-DataCodec& DataCodec::operator=(DataCodec&& c) = default;
+RtpDataCodec::RtpDataCodec(const RtpDataCodec& c) = default;
+RtpDataCodec::RtpDataCodec(RtpDataCodec&& c) = default;
+RtpDataCodec& RtpDataCodec::operator=(const RtpDataCodec& c) = default;
+RtpDataCodec& RtpDataCodec::operator=(RtpDataCodec&& c) = default;
-std::string DataCodec::ToString() const {
+std::string RtpDataCodec::ToString() const {
char buf[256];
rtc::SimpleStringBuilder sb(buf);
- sb << "DataCodec[" << id << ":" << name << "]";
+ sb << "RtpDataCodec[" << id << ":" << name << "]";
return sb.str();
}
diff --git a/media/base/codec.h b/media/base/codec.h
index 091adb6..bbb147d 100644
--- a/media/base/codec.h
+++ b/media/base/codec.h
@@ -192,19 +192,23 @@
void SetDefaultParameters();
};
-struct DataCodec : public Codec {
- DataCodec(int id, const std::string& name);
- DataCodec();
- DataCodec(const DataCodec& c);
- DataCodec(DataCodec&& c);
- ~DataCodec() override = default;
+struct RtpDataCodec : public Codec {
+ RtpDataCodec(int id, const std::string& name);
+ RtpDataCodec();
+ RtpDataCodec(const RtpDataCodec& c);
+ RtpDataCodec(RtpDataCodec&& c);
+ ~RtpDataCodec() override = default;
- DataCodec& operator=(const DataCodec& c);
- DataCodec& operator=(DataCodec&& c);
+ RtpDataCodec& operator=(const RtpDataCodec& c);
+ RtpDataCodec& operator=(RtpDataCodec&& 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 a4647ae..b8bfca2 100644
--- a/media/base/rtp_data_engine.h
+++ b/media/base/rtp_data_engine.h
@@ -16,6 +16,7 @@
#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"
@@ -26,8 +27,6 @@
namespace cricket {
-struct DataCodec;
-
class RtpDataEngine : public DataEngineInterface {
public:
RtpDataEngine();
diff --git a/pc/BUILD.gn b/pc/BUILD.gn
index 56078c1..1013f7c 100644
--- a/pc/BUILD.gn
+++ b/pc/BUILD.gn
@@ -72,6 +72,7 @@
]
deps = [
+ ":media_protocol_names",
"../api:array_view",
"../api:audio_options_api",
"../api:call_api",
@@ -122,6 +123,13 @@
]
}
+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 647663e..82de7de 100644
--- a/pc/channel.cc
+++ b/pc/channel.cc
@@ -1143,7 +1143,7 @@
}
bool RtpDataChannel::CheckDataChannelTypeFromContent(
- const DataContentDescription* content,
+ const RtpDataContentDescription* content,
std::string* error_desc) {
bool is_sctp = ((content->protocol() == kMediaProtocolSctp) ||
(content->protocol() == kMediaProtocolDtlsSctp));
@@ -1169,7 +1169,7 @@
return false;
}
- const DataContentDescription* data = content->as_data();
+ const RtpDataContentDescription* data = content->as_rtp_data();
if (!CheckDataChannelTypeFromContent(data, error_desc)) {
return false;
@@ -1223,7 +1223,12 @@
return false;
}
- const DataContentDescription* data = content->as_data();
+ const RtpDataContentDescription* data = content->as_rtp_data();
+
+ if (!data) {
+ RTC_LOG(LS_INFO) << "Accepting and ignoring non-RTP content description";
+ return true;
+ }
// 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 1a4cc72..9747ec2 100644
--- a/pc/channel.h
+++ b/pc/channel.h
@@ -518,7 +518,7 @@
// overrides from BaseChannel
// Checks that data channel type is RTP.
- bool CheckDataChannelTypeFromContent(const DataContentDescription* content,
+ bool CheckDataChannelTypeFromContent(const RtpDataContentDescription* 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 9c5f82b..e31ab53 100644
--- a/pc/channel_unittest.cc
+++ b/pc/channel_unittest.cc
@@ -94,8 +94,8 @@
class DataTraits : public Traits<cricket::RtpDataChannel,
cricket::FakeDataMediaChannel,
- cricket::DataContentDescription,
- cricket::DataCodec,
+ cricket::RtpDataContentDescription,
+ cricket::RtpDataCodec,
cricket::DataMediaInfo,
cricket::DataOptions> {};
@@ -2308,15 +2308,15 @@
int flags,
const cricket::AudioCodec& audio_codec,
const cricket::VideoCodec& video_codec,
- cricket::DataContentDescription* data) {
+ cricket::RtpDataContentDescription* data) {
data->AddCodec(kGoogleDataCodec);
data->set_rtcp_mux((flags & RTCP_MUX) != 0);
}
template <>
void ChannelTest<DataTraits>::CopyContent(
- const cricket::DataContentDescription& source,
- cricket::DataContentDescription* data) {
+ const cricket::RtpDataContentDescription& source,
+ cricket::RtpDataContentDescription* data) {
*data = source;
}
@@ -2330,7 +2330,7 @@
void ChannelTest<DataTraits>::AddLegacyStreamInContent(
uint32_t ssrc,
int flags,
- cricket::DataContentDescription* data) {
+ cricket::RtpDataContentDescription* data) {
data->AddLegacyStream(ssrc);
}
diff --git a/pc/jsep_transport_controller_unittest.cc b/pc/jsep_transport_controller_unittest.cc
index e81b667..c0927b9d 100644
--- a/pc/jsep_transport_controller_unittest.cc
+++ b/pc/jsep_transport_controller_unittest.cc
@@ -175,8 +175,9 @@
cricket::IceMode ice_mode,
cricket::ConnectionRole conn_role,
rtc::scoped_refptr<rtc::RTCCertificate> cert) {
- std::unique_ptr<cricket::DataContentDescription> data(
- new cricket::DataContentDescription());
+ RTC_CHECK(protocol_type == cricket::MediaProtocolType::kSctp);
+ std::unique_ptr<cricket::SctpDataContentDescription> data(
+ new cricket::SctpDataContentDescription());
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
new file mode 100644
index 0000000..3def3f0
--- /dev/null
+++ b/pc/media_protocol_names.cc
@@ -0,0 +1,55 @@
+/*
+ * 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 {
+
+// There are multiple variants of the RTP protocol stack, including
+// UDP/TLS/RTP/SAVPF (WebRTC default), RTP/AVP, RTP/AVPF, RTP/SAVPF,
+// TCP/DTLS/RTP/SAVPF and so on. We accept anything that has RTP/
+// embedded in it somewhere as being an RTP protocol.
+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) {
+ if (protocol.empty()) {
+ return true;
+ }
+ size_t pos = protocol.find(cricket::kMediaProtocolRtpPrefix);
+ if (pos == std::string::npos) {
+ return false;
+ }
+ // RTP must be at the beginning of a string or not preceded by alpha
+ if (pos == 0 || !isalpha(protocol[pos - 1])) {
+ return true;
+ }
+ return false;
+}
+
+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
new file mode 100644
index 0000000..88f1c46
--- /dev/null
+++ b/pc/media_protocol_names.h
@@ -0,0 +1,35 @@
+/*
+ * 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 0eace22..9c03a1e 100644
--- a/pc/media_session.cc
+++ b/pc/media_session.cc
@@ -27,6 +27,7 @@
#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"
@@ -68,13 +69,6 @@
// 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.
@@ -91,20 +85,6 @@
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) {
@@ -489,7 +469,7 @@
StreamParamsVec* current_streams,
MediaContentDescriptionImpl<C>* content_description) {
// SCTP streams are not negotiated using SDP/ContentDescriptions.
- if (IsSctp(content_description->protocol())) {
+ if (IsSctpProtocol(content_description->protocol())) {
return true;
}
@@ -608,11 +588,6 @@
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;
@@ -741,32 +716,22 @@
// 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.
-template <class C>
-static bool CreateMediaContentOffer(
+static bool CreateContentOffer(
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);
-
+ MediaContentDescription* offer) {
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) {
@@ -785,6 +750,30 @@
}
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,
@@ -1186,6 +1175,28 @@
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
@@ -1193,12 +1204,10 @@
// (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 MediaContentDescriptionImpl<C>* offer,
+ const MediaContentDescription* 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,
@@ -1206,13 +1215,7 @@
bool enable_encrypted_rtp_header_extensions,
StreamParamsVec* current_streams,
bool bundle_enabled,
- 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());
-
+ MediaContentDescription* answer) {
answer->set_extmap_allow_mixed_enum(offer->extmap_allow_mixed_enum());
RtpHeaderExtensions negotiated_rtp_extensions;
NegotiateRtpHeaderExtensions(
@@ -1240,12 +1243,6 @@
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(
@@ -1397,7 +1394,7 @@
channel_manager->GetSupportedAudioRtpHeaderExtensions(&audio_rtp_extensions_);
channel_manager->GetSupportedVideoCodecs(&video_codecs_);
channel_manager->GetSupportedVideoRtpHeaderExtensions(&video_rtp_extensions_);
- channel_manager->GetSupportedDataCodecs(&data_codecs_);
+ channel_manager->GetSupportedDataCodecs(&rtp_data_codecs_);
ComputeAudioCodecsIntersectionAndUnion();
}
@@ -1484,15 +1481,15 @@
AudioCodecs offer_audio_codecs;
VideoCodecs offer_video_codecs;
- DataCodecs offer_data_codecs;
+ RtpDataCodecs offer_rtp_data_codecs;
GetCodecsForOffer(current_active_contents, &offer_audio_codecs,
- &offer_video_codecs, &offer_data_codecs);
+ &offer_video_codecs, &offer_rtp_data_codecs);
if (!session_options.vad_enabled) {
// If application doesn't want CN codecs in offer.
StripCNCodecs(&offer_audio_codecs);
}
- FilterDataCodecs(&offer_data_codecs,
+ FilterDataCodecs(&offer_rtp_data_codecs,
session_options.data_channel_type == DCT_SCTP);
RtpHeaderExtensions audio_rtp_extensions;
@@ -1536,7 +1533,7 @@
case MEDIA_TYPE_DATA:
if (!AddDataContentForOffer(media_description_options, session_options,
current_content, current_description,
- offer_data_codecs, ¤t_streams,
+ offer_rtp_data_codecs, ¤t_streams,
offer.get(), &ice_credentials)) {
return nullptr;
}
@@ -1634,15 +1631,15 @@
// sections.
AudioCodecs answer_audio_codecs;
VideoCodecs answer_video_codecs;
- DataCodecs answer_data_codecs;
+ RtpDataCodecs answer_rtp_data_codecs;
GetCodecsForAnswer(current_active_contents, *offer, &answer_audio_codecs,
- &answer_video_codecs, &answer_data_codecs);
+ &answer_video_codecs, &answer_rtp_data_codecs);
if (!session_options.vad_enabled) {
// If application doesn't want CN codecs in answer.
StripCNCodecs(&answer_audio_codecs);
}
- FilterDataCodecs(&answer_data_codecs,
+ FilterDataCodecs(&answer_rtp_data_codecs,
session_options.data_channel_type == DCT_SCTP);
auto answer = absl::make_unique<SessionDescription>();
@@ -1695,8 +1692,8 @@
if (!AddDataContentForAnswer(
media_description_options, session_options, offer_content,
offer, current_content, current_description,
- bundle_transport.get(), answer_data_codecs, ¤t_streams,
- answer.get(), &ice_credentials)) {
+ bundle_transport.get(), answer_rtp_data_codecs,
+ ¤t_streams, answer.get(), &ice_credentials)) {
return nullptr;
}
break;
@@ -1816,7 +1813,7 @@
const std::vector<const ContentInfo*>& current_active_contents,
AudioCodecs* audio_codecs,
VideoCodecs* video_codecs,
- DataCodecs* data_codecs,
+ RtpDataCodecs* rtp_data_codecs,
UsedPayloadTypes* used_pltypes) {
for (const ContentInfo* content : current_active_contents) {
if (IsMediaContentOfType(content, MEDIA_TYPE_AUDIO)) {
@@ -1828,9 +1825,13 @@
content->media_description()->as_video();
MergeCodecs<VideoCodec>(video->codecs(), video_codecs, used_pltypes);
} else if (IsMediaContentOfType(content, MEDIA_TYPE_DATA)) {
- const DataContentDescription* data =
- content->media_description()->as_data();
- MergeCodecs<DataCodec>(data->codecs(), data_codecs, used_pltypes);
+ 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);
+ }
}
}
}
@@ -1845,18 +1846,18 @@
const std::vector<const ContentInfo*>& current_active_contents,
AudioCodecs* audio_codecs,
VideoCodecs* video_codecs,
- DataCodecs* data_codecs) const {
+ RtpDataCodecs* rtp_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, data_codecs, &used_pltypes);
+ video_codecs, rtp_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>(data_codecs_, data_codecs, &used_pltypes);
+ MergeCodecs<DataCodec>(rtp_data_codecs_, rtp_data_codecs, &used_pltypes);
}
// Getting codecs for an answer involves these steps:
@@ -1871,18 +1872,18 @@
const SessionDescription& remote_offer,
AudioCodecs* audio_codecs,
VideoCodecs* video_codecs,
- DataCodecs* data_codecs) const {
+ RtpDataCodecs* rtp_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, data_codecs, &used_pltypes);
+ video_codecs, rtp_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;
- DataCodecs filtered_offered_data_codecs;
+ RtpDataCodecs filtered_offered_rtp_data_codecs;
for (const ContentInfo& content : remote_offer.contents()) {
if (IsMediaContentOfType(&content, MEDIA_TYPE_AUDIO)) {
const AudioContentDescription* audio =
@@ -1909,15 +1910,19 @@
}
}
} else if (IsMediaContentOfType(&content, MEDIA_TYPE_DATA)) {
- 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);
+ 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);
+ }
}
}
}
@@ -1929,7 +1934,7 @@
&used_pltypes);
MergeCodecs<VideoCodec>(filtered_offered_video_codecs, video_codecs,
&used_pltypes);
- MergeCodecs<DataCodec>(filtered_offered_data_codecs, data_codecs,
+ MergeCodecs<DataCodec>(filtered_offered_rtp_data_codecs, rtp_data_codecs,
&used_pltypes);
}
@@ -2206,18 +2211,101 @@
return true;
}
+bool MediaSessionDescriptionFactory::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 {
+ std::unique_ptr<SctpDataContentDescription> data(
+ new SctpDataContentDescription());
+
+ 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;
+ // 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;
+ }
+
+ 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)) {
+ 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;
+ }
+
+ 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)) {
+ return false;
+ }
+ return true;
+}
+
bool MediaSessionDescriptionFactory::AddDataContentForOffer(
const MediaDescriptionOptions& media_description_options,
const MediaSessionOptions& session_options,
const ContentInfo* current_content,
const SessionDescription* current_description,
- const DataCodecs& data_codecs,
+ const RtpDataCodecs& rtp_data_codecs,
StreamParamsVec* current_streams,
SessionDescription* desc,
IceCredentialsIterator* ice_credentials) const {
- 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.
@@ -2226,52 +2314,16 @@
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;
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);
+ return AddSctpDataContentForOffer(
+ media_description_options, session_options, current_content,
+ current_description, current_streams, desc, ice_credentials);
} else {
- GetSupportedDataSdesCryptoSuiteNames(session_options.crypto_options,
- &crypto_suites);
+ return AddRtpDataContentForOffer(media_description_options, session_options,
+ current_content, current_description,
+ rtp_data_codecs, current_streams, 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;
- }
-
- 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());
- }
- if (!AddTransportOffer(media_description_options.mid,
- media_description_options.transport_options,
- current_description, desc, ice_credentials)) {
- return false;
- }
- return true;
}
// |audio_codecs| = set of all possible codecs that can be used, with correct
@@ -2359,9 +2411,15 @@
// 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,
- filtered_codecs, sdes_policy, GetCryptos(current_content),
+ sdes_policy, GetCryptos(current_content),
audio_rtp_header_extensions(), ssrc_generator_,
enable_encrypted_rtp_header_extensions_, current_streams,
bundle_enabled, audio_answer.get())) {
@@ -2454,9 +2512,15 @@
// 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,
- filtered_codecs, sdes_policy, GetCryptos(current_content),
+ sdes_policy, GetCryptos(current_content),
video_rtp_header_extensions(), ssrc_generator_,
enable_encrypted_rtp_header_extensions_, current_streams,
bundle_enabled, video_answer.get())) {
@@ -2492,7 +2556,7 @@
const ContentInfo* current_content,
const SessionDescription* current_description,
const TransportInfo* bundle_transport,
- const DataCodecs& data_codecs,
+ const RtpDataCodecs& rtp_data_codecs,
StreamParamsVec* current_streams,
SessionDescription* answer,
IceCredentialsIterator* ice_credentials) const {
@@ -2504,28 +2568,51 @@
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));
- 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.
- }
+ 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>();
- // 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);
+ 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.
+ }
+ }
bool secure = bundle_transport ? bundle_transport->description.secure()
: data_transport->secure();
@@ -2649,20 +2736,35 @@
const AudioContentDescription* GetFirstAudioContentDescription(
const SessionDescription* sdesc) {
- return static_cast<const AudioContentDescription*>(
- GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_AUDIO));
+ auto desc = GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_AUDIO);
+ return desc ? desc->as_audio() : nullptr;
}
const VideoContentDescription* GetFirstVideoContentDescription(
const SessionDescription* sdesc) {
- return static_cast<const VideoContentDescription*>(
- GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_VIDEO));
+ 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;
+}
+
+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) {
- return static_cast<const DataContentDescription*>(
- GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_DATA));
+ auto desc = GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_DATA);
+ return desc ? desc->as_data() : nullptr;
}
//
@@ -2721,20 +2823,33 @@
AudioContentDescription* GetFirstAudioContentDescription(
SessionDescription* sdesc) {
- return static_cast<AudioContentDescription*>(
- GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_AUDIO));
+ auto desc = GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_AUDIO);
+ return desc ? desc->as_audio() : nullptr;
}
VideoContentDescription* GetFirstVideoContentDescription(
SessionDescription* sdesc) {
- return static_cast<VideoContentDescription*>(
- GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_VIDEO));
+ 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;
+}
+
+// Returns shim
DataContentDescription* GetFirstDataContentDescription(
SessionDescription* sdesc) {
- return static_cast<DataContentDescription*>(
- GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_DATA));
+ auto desc = GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_DATA);
+ return desc ? desc->as_data() : nullptr;
}
} // namespace cricket
diff --git a/pc/media_session.h b/pc/media_session.h
index a369756..dc889b2 100644
--- a/pc/media_session.h
+++ b/pc/media_session.h
@@ -24,6 +24,7 @@
#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"
@@ -154,8 +155,10 @@
video_rtp_extensions_ = extensions;
}
RtpHeaderExtensions video_rtp_header_extensions() const;
- const DataCodecs& data_codecs() const { return data_codecs_; }
- void set_data_codecs(const DataCodecs& codecs) { data_codecs_ = codecs; }
+ const RtpDataCodecs& rtp_data_codecs() const { return rtp_data_codecs_; }
+ void set_rtp_data_codecs(const RtpDataCodecs& codecs) {
+ rtp_data_codecs_ = codecs;
+ }
SecurePolicy secure() const { return secure_; }
void set_secure(SecurePolicy s) { secure_ = s; }
@@ -185,13 +188,13 @@
const std::vector<const ContentInfo*>& current_active_contents,
AudioCodecs* audio_codecs,
VideoCodecs* video_codecs,
- DataCodecs* data_codecs) const;
+ RtpDataCodecs* rtp_data_codecs) const;
void GetCodecsForAnswer(
const std::vector<const ContentInfo*>& current_active_contents,
const SessionDescription& remote_offer,
AudioCodecs* audio_codecs,
VideoCodecs* video_codecs,
- DataCodecs* data_codecs) const;
+ RtpDataCodecs* rtp_data_codecs) const;
void GetRtpHdrExtsToOffer(
const std::vector<const ContentInfo*>& current_active_contents,
RtpHeaderExtensions* audio_extensions,
@@ -240,12 +243,32 @@
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 DataCodecs& data_codecs,
+ const RtpDataCodecs& rtp_data_codecs,
StreamParamsVec* current_streams,
SessionDescription* desc,
IceCredentialsIterator* ice_credentials) const;
@@ -284,7 +307,7 @@
const ContentInfo* current_content,
const SessionDescription* current_description,
const TransportInfo* bundle_transport,
- const DataCodecs& data_codecs,
+ const RtpDataCodecs& rtp_data_codecs,
StreamParamsVec* current_streams,
SessionDescription* answer,
IceCredentialsIterator* ice_credentials) const;
@@ -301,7 +324,7 @@
RtpHeaderExtensions audio_rtp_extensions_;
VideoCodecs video_codecs_;
RtpHeaderExtensions video_rtp_extensions_;
- DataCodecs data_codecs_;
+ RtpDataCodecs rtp_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;
@@ -330,6 +353,11 @@
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.
@@ -347,6 +375,10 @@
SessionDescription* sdesc);
VideoContentDescription* GetFirstVideoContentDescription(
SessionDescription* sdesc);
+RtpDataContentDescription* GetFirstRtpDataContentDescription(
+ SessionDescription* sdesc);
+SctpDataContentDescription* GetFirstSctpDataContentDescription(
+ SessionDescription* sdesc);
DataContentDescription* GetFirstDataContentDescription(
SessionDescription* sdesc);
@@ -370,9 +402,6 @@
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 1136607..b69ded3 100644
--- a/pc/media_session_unittest.cc
+++ b/pc/media_session_unittest.cc
@@ -42,12 +42,10 @@
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::GetFirstDataContentDescription;
+using cricket::GetFirstRtpDataContentDescription;
using cricket::GetFirstVideoContent;
using cricket::GetFirstVideoContentDescription;
using cricket::kAutoBandwidth;
@@ -62,6 +60,9 @@
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;
@@ -126,14 +127,14 @@
static const VideoCodec kVideoCodecsAnswer[] = {VideoCodec(97, "H264")};
-static const DataCodec kDataCodecs1[] = {DataCodec(98, "binary-data"),
- DataCodec(99, "utf8-text")};
+static const RtpDataCodec kDataCodecs1[] = {RtpDataCodec(98, "binary-data"),
+ RtpDataCodec(99, "utf8-text")};
-static const DataCodec kDataCodecs2[] = {DataCodec(126, "binary-data"),
- DataCodec(127, "utf8-text")};
+static const RtpDataCodec kDataCodecs2[] = {RtpDataCodec(126, "binary-data"),
+ RtpDataCodec(127, "utf8-text")};
-static const DataCodec kDataCodecsAnswer[] = {DataCodec(98, "binary-data"),
- DataCodec(99, "utf8-text")};
+static const RtpDataCodec kDataCodecsAnswer[] = {
+ RtpDataCodec(98, "binary-data"), RtpDataCodec(99, "utf8-text")};
static const RtpExtension kAudioRtpExtension1[] = {
RtpExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8),
@@ -412,11 +413,11 @@
f1_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs1),
MAKE_VECTOR(kAudioCodecs1));
f1_.set_video_codecs(MAKE_VECTOR(kVideoCodecs1));
- f1_.set_data_codecs(MAKE_VECTOR(kDataCodecs1));
+ f1_.set_rtp_data_codecs(MAKE_VECTOR(kDataCodecs1));
f2_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs2),
MAKE_VECTOR(kAudioCodecs2));
f2_.set_video_codecs(MAKE_VECTOR(kVideoCodecs2));
- f2_.set_data_codecs(MAKE_VECTOR(kDataCodecs2));
+ f2_.set_rtp_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(
@@ -801,7 +802,7 @@
TEST_F(MediaSessionDescriptionFactoryTest, TestBundleOfferWithSameCodecPlType) {
const VideoCodec& offered_video_codec = f2_.video_codecs()[0];
const AudioCodec& offered_audio_codec = f2_.audio_sendrecv_codecs()[0];
- const DataCodec& offered_data_codec = f2_.data_codecs()[0];
+ const RtpDataCodec& offered_data_codec = f2_.rtp_data_codecs()[0];
ASSERT_EQ(offered_video_codec.id, offered_audio_codec.id);
ASSERT_EQ(offered_video_codec.id, offered_data_codec.id);
@@ -814,8 +815,8 @@
GetFirstVideoContentDescription(offer.get());
const AudioContentDescription* acd =
GetFirstAudioContentDescription(offer.get());
- const DataContentDescription* dcd =
- GetFirstDataContentDescription(offer.get());
+ const RtpDataContentDescription* dcd =
+ GetFirstRtpDataContentDescription(offer.get());
ASSERT_TRUE(NULL != vcd);
ASSERT_TRUE(NULL != acd);
ASSERT_TRUE(NULL != dcd);
@@ -858,8 +859,8 @@
GetFirstAudioContentDescription(updated_offer.get());
const VideoContentDescription* vcd =
GetFirstVideoContentDescription(updated_offer.get());
- const DataContentDescription* dcd =
- GetFirstDataContentDescription(updated_offer.get());
+ const RtpDataContentDescription* dcd =
+ GetFirstRtpDataContentDescription(updated_offer.get());
EXPECT_TRUE(NULL != vcd);
EXPECT_TRUE(NULL != acd);
EXPECT_TRUE(NULL != dcd);
@@ -887,7 +888,7 @@
EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
EXPECT_EQ(MediaProtocolType::kRtp, dc->type);
const AudioContentDescription* acd = ac->media_description()->as_audio();
- const DataContentDescription* dcd = dc->media_description()->as_data();
+ const RtpDataContentDescription* dcd = dc->media_description()->as_rtp_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.
@@ -896,7 +897,7 @@
ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite);
EXPECT_EQ(cricket::kMediaProtocolSavpf, acd->protocol());
EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
- EXPECT_EQ(f1_.data_codecs(), dcd->codecs());
+ EXPECT_EQ(f1_.rtp_data_codecs(), dcd->codecs());
EXPECT_EQ(0U, dcd->first_ssrc()); // no sender is attached.
EXPECT_EQ(cricket::kDataMaxBandwidth,
dcd->bandwidth()); // default bandwidth (auto)
@@ -1280,7 +1281,7 @@
EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
EXPECT_EQ(MediaProtocolType::kRtp, dc->type);
const AudioContentDescription* acd = ac->media_description()->as_audio();
- const DataContentDescription* dcd = dc->media_description()->as_data();
+ const RtpDataContentDescription* dcd = dc->media_description()->as_rtp_data();
EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
EXPECT_THAT(acd->codecs(), ElementsAreArray(kAudioCodecsAnswer));
EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
@@ -1312,7 +1313,7 @@
EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
EXPECT_EQ(MediaProtocolType::kRtp, dc->type);
const AudioContentDescription* acd = ac->media_description()->as_audio();
- const DataContentDescription* dcd = dc->media_description()->as_data();
+ const RtpDataContentDescription* dcd = dc->media_description()->as_rtp_data();
EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
EXPECT_THAT(acd->codecs(), ElementsAreArray(kAudioCodecsAnswer));
EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
@@ -1336,15 +1337,16 @@
ASSERT_TRUE(offer.get() != NULL);
ContentInfo* dc_offer = offer->GetContentByName("data");
ASSERT_TRUE(dc_offer != NULL);
- DataContentDescription* dcd_offer = dc_offer->media_description()->as_data();
+ SctpDataContentDescription* dcd_offer =
+ dc_offer->media_description()->as_sctp();
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 DataContentDescription* dcd_answer =
- dc_answer->media_description()->as_data();
+ const SctpDataContentDescription* dcd_answer =
+ dc_answer->media_description()->as_sctp();
EXPECT_TRUE(dcd_answer->use_sctpmap());
}
@@ -1356,15 +1358,16 @@
ASSERT_TRUE(offer.get() != NULL);
ContentInfo* dc_offer = offer->GetContentByName("data");
ASSERT_TRUE(dc_offer != NULL);
- DataContentDescription* dcd_offer = dc_offer->media_description()->as_data();
+ SctpDataContentDescription* dcd_offer =
+ dc_offer->media_description()->as_sctp();
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 DataContentDescription* dcd_answer =
- dc_answer->media_description()->as_data();
+ const SctpDataContentDescription* dcd_answer =
+ dc_answer->media_description()->as_sctp();
EXPECT_FALSE(dcd_answer->use_sctpmap());
}
@@ -1385,7 +1388,9 @@
ASSERT_TRUE(offer.get() != nullptr);
ContentInfo* dc_offer = offer->GetContentByName("data");
ASSERT_TRUE(dc_offer != nullptr);
- DataContentDescription* dcd_offer = dc_offer->media_description()->as_data();
+ SctpDataContentDescription* dcd_offer =
+ dc_offer->media_description()->as_sctp();
+ ASSERT_TRUE(dcd_offer);
std::vector<std::string> protos = {"DTLS/SCTP", "UDP/DTLS/SCTP",
"TCP/DTLS/SCTP"};
@@ -1395,8 +1400,8 @@
f2_.CreateAnswer(offer.get(), opts, nullptr);
const ContentInfo* dc_answer = answer->GetContentByName("data");
ASSERT_TRUE(dc_answer != nullptr);
- const DataContentDescription* dcd_answer =
- dc_answer->media_description()->as_data();
+ const SctpDataContentDescription* dcd_answer =
+ dc_answer->media_description()->as_sctp();
EXPECT_FALSE(dc_answer->rejected);
EXPECT_EQ(proto, dcd_answer->protocol());
}
@@ -1478,9 +1483,11 @@
std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL);
ContentInfo* dc_offer = offer->GetContentByName("data");
ASSERT_TRUE(dc_offer != NULL);
- DataContentDescription* dcd_offer = dc_offer->media_description()->as_data();
+ RtpDataContentDescription* dcd_offer =
+ dc_offer->media_description()->as_rtp_data();
ASSERT_TRUE(dcd_offer != NULL);
- std::string protocol = "a weird unknown protocol";
+ // Offer must be acceptable as an RTP protocol in order to be set.
+ std::string protocol = "RTP/a weird unknown protocol";
dcd_offer->set_protocol(protocol);
std::unique_ptr<SessionDescription> answer =
@@ -1489,8 +1496,8 @@
const ContentInfo* dc_answer = answer->GetContentByName("data");
ASSERT_TRUE(dc_answer != NULL);
EXPECT_TRUE(dc_answer->rejected);
- const DataContentDescription* dcd_answer =
- dc_answer->media_description()->as_data();
+ const RtpDataContentDescription* dcd_answer =
+ dc_answer->media_description()->as_rtp_data();
ASSERT_TRUE(dcd_answer != NULL);
EXPECT_EQ(protocol, dcd_answer->protocol());
}
@@ -1688,7 +1695,7 @@
ASSERT_TRUE(vc != NULL);
const AudioContentDescription* acd = ac->media_description()->as_audio();
const VideoContentDescription* vcd = vc->media_description()->as_video();
- const DataContentDescription* dcd = dc->media_description()->as_data();
+ const RtpDataContentDescription* dcd = dc->media_description()->as_rtp_data();
EXPECT_FALSE(acd->has_ssrcs()); // No StreamParams.
EXPECT_FALSE(vcd->has_ssrcs()); // No StreamParams.
@@ -1716,16 +1723,16 @@
answer = f2_.CreateAnswer(offer.get(), answer_opts, NULL);
ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
- ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
+ ASSERT_TRUE(NULL != GetFirstRtpDataContentDescription(offer.get()));
ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
- ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
+ ASSERT_TRUE(NULL != GetFirstRtpDataContentDescription(answer.get()));
EXPECT_TRUE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
EXPECT_TRUE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
- EXPECT_TRUE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
+ EXPECT_TRUE(GetFirstRtpDataContentDescription(offer.get())->rtcp_mux());
EXPECT_TRUE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
EXPECT_TRUE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
- EXPECT_TRUE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
+ EXPECT_TRUE(GetFirstRtpDataContentDescription(answer.get())->rtcp_mux());
offer_opts.rtcp_mux_enabled = true;
answer_opts.rtcp_mux_enabled = false;
@@ -1733,16 +1740,16 @@
answer = f2_.CreateAnswer(offer.get(), answer_opts, NULL);
ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
- ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
+ ASSERT_TRUE(NULL != GetFirstRtpDataContentDescription(offer.get()));
ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
- ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
+ ASSERT_TRUE(NULL != GetFirstRtpDataContentDescription(answer.get()));
EXPECT_TRUE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
EXPECT_TRUE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
- EXPECT_TRUE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
+ EXPECT_TRUE(GetFirstRtpDataContentDescription(offer.get())->rtcp_mux());
EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
- EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
+ EXPECT_FALSE(GetFirstRtpDataContentDescription(answer.get())->rtcp_mux());
offer_opts.rtcp_mux_enabled = false;
answer_opts.rtcp_mux_enabled = true;
@@ -1750,16 +1757,16 @@
answer = f2_.CreateAnswer(offer.get(), answer_opts, NULL);
ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
- ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
+ ASSERT_TRUE(NULL != GetFirstRtpDataContentDescription(offer.get()));
ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
- ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
+ ASSERT_TRUE(NULL != GetFirstRtpDataContentDescription(answer.get()));
EXPECT_FALSE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
EXPECT_FALSE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
- EXPECT_FALSE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
+ EXPECT_FALSE(GetFirstRtpDataContentDescription(offer.get())->rtcp_mux());
EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
- EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
+ EXPECT_FALSE(GetFirstRtpDataContentDescription(answer.get())->rtcp_mux());
offer_opts.rtcp_mux_enabled = false;
answer_opts.rtcp_mux_enabled = false;
@@ -1767,16 +1774,16 @@
answer = f2_.CreateAnswer(offer.get(), answer_opts, NULL);
ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
- ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
+ ASSERT_TRUE(NULL != GetFirstRtpDataContentDescription(offer.get()));
ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
- ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
+ ASSERT_TRUE(NULL != GetFirstRtpDataContentDescription(answer.get()));
EXPECT_FALSE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
EXPECT_FALSE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
- EXPECT_FALSE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
+ EXPECT_FALSE(GetFirstRtpDataContentDescription(offer.get())->rtcp_mux());
EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
- EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
+ EXPECT_FALSE(GetFirstRtpDataContentDescription(answer.get())->rtcp_mux());
}
// Create an audio-only answer to a video offer.
@@ -1948,7 +1955,7 @@
ASSERT_TRUE(dc != NULL);
const AudioContentDescription* acd = ac->media_description()->as_audio();
const VideoContentDescription* vcd = vc->media_description()->as_video();
- const DataContentDescription* dcd = dc->media_description()->as_data();
+ const RtpDataContentDescription* dcd = dc->media_description()->as_rtp_data();
EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
EXPECT_EQ(f1_.audio_sendrecv_codecs(), acd->codecs());
@@ -1978,7 +1985,7 @@
EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
- EXPECT_EQ(f1_.data_codecs(), dcd->codecs());
+ EXPECT_EQ(f1_.rtp_data_codecs(), dcd->codecs());
ASSERT_CRYPTO(dcd, 1U, kDefaultSrtpCryptoSuite);
const StreamParamsVec& data_streams = dcd->streams();
@@ -2020,8 +2027,8 @@
ac->media_description()->as_audio();
const VideoContentDescription* updated_vcd =
vc->media_description()->as_video();
- const DataContentDescription* updated_dcd =
- dc->media_description()->as_data();
+ const RtpDataContentDescription* updated_dcd =
+ dc->media_description()->as_rtp_data();
EXPECT_EQ(acd->type(), updated_acd->type());
EXPECT_EQ(acd->codecs(), updated_acd->codecs());
@@ -2307,7 +2314,7 @@
ASSERT_TRUE(dc != NULL);
const AudioContentDescription* acd = ac->media_description()->as_audio();
const VideoContentDescription* vcd = vc->media_description()->as_video();
- const DataContentDescription* dcd = dc->media_description()->as_data();
+ const RtpDataContentDescription* dcd = dc->media_description()->as_rtp_data();
ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite);
ASSERT_CRYPTO(vcd, 1U, kDefaultSrtpCryptoSuite);
ASSERT_CRYPTO(dcd, 1U, kDefaultSrtpCryptoSuite);
@@ -2375,8 +2382,8 @@
ac->media_description()->as_audio();
const VideoContentDescription* updated_vcd =
vc->media_description()->as_video();
- const DataContentDescription* updated_dcd =
- dc->media_description()->as_data();
+ const RtpDataContentDescription* updated_dcd =
+ dc->media_description()->as_rtp_data();
ASSERT_CRYPTO(updated_acd, 1U, kDefaultSrtpCryptoSuite);
EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
@@ -3536,8 +3543,8 @@
const VideoContentDescription* video_offer =
GetFirstVideoContentDescription(offer.get());
ASSERT_TRUE(video_offer->cryptos().empty());
- const DataContentDescription* data_offer =
- GetFirstDataContentDescription(offer.get());
+ const RtpDataContentDescription* data_offer =
+ GetFirstRtpDataContentDescription(offer.get());
ASSERT_TRUE(data_offer->cryptos().empty());
const cricket::TransportDescription* audio_offer_trans_desc =
@@ -4068,11 +4075,11 @@
f1_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs1),
MAKE_VECTOR(kAudioCodecs1));
f1_.set_video_codecs(MAKE_VECTOR(kVideoCodecs1));
- f1_.set_data_codecs(MAKE_VECTOR(kDataCodecs1));
+ f1_.set_rtp_data_codecs(MAKE_VECTOR(kDataCodecs1));
f2_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs2),
MAKE_VECTOR(kAudioCodecs2));
f2_.set_video_codecs(MAKE_VECTOR(kVideoCodecs2));
- f2_.set_data_codecs(MAKE_VECTOR(kDataCodecs2));
+ f2_.set_rtp_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 b4c5fe2..781b3a5 100644
--- a/pc/peer_connection.cc
+++ b/pc/peer_connection.cc
@@ -559,24 +559,13 @@
// Get the SCTP port out of a SessionDescription.
// Return -1 if not found.
int GetSctpPort(const SessionDescription* session_description) {
- const cricket::DataContentDescription* data_desc =
- GetFirstDataContentDescription(session_description);
+ const cricket::SctpDataContentDescription* data_desc =
+ GetFirstSctpDataContentDescription(session_description);
RTC_DCHECK(data_desc);
if (!data_desc) {
return -1;
}
- 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;
+ return data_desc->port();
}
// Returns true if |new_desc| requests an ICE restart (i.e., new ufrag/pwd).
@@ -2423,11 +2412,11 @@
const cricket::ContentInfo* data_content =
GetFirstDataContent(local_description()->description());
if (data_content) {
- const cricket::DataContentDescription* data_desc =
- data_content->media_description()->as_data();
- if (absl::StartsWith(data_desc->protocol(),
- cricket::kMediaProtocolRtpPrefix)) {
- UpdateLocalRtpDataChannels(data_desc->streams());
+ 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());
}
}
@@ -2833,8 +2822,8 @@
GetFirstAudioContentDescription(remote_description()->description());
const cricket::VideoContentDescription* video_desc =
GetFirstVideoContentDescription(remote_description()->description());
- const cricket::DataContentDescription* data_desc =
- GetFirstDataContentDescription(remote_description()->description());
+ const cricket::RtpDataContentDescription* rtp_data_desc =
+ GetFirstRtpDataContentDescription(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".
@@ -2887,12 +2876,10 @@
}
}
- // 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));
- }
+ // 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));
}
// 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 ad3817e..4080dd9 100644
--- a/pc/peer_connection_data_channel_unittest.cc
+++ b/pc/peer_connection_data_channel_unittest.cc
@@ -193,14 +193,11 @@
// 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_data();
- data_desc->set_codecs({sctp_codec});
+ auto* data_desc = data_content->media_description()->as_sctp();
+ RTC_DCHECK(data_desc);
+ data_desc->set_port(port);
}
std::unique_ptr<rtc::VirtualSocketServer> vss_;
diff --git a/pc/peer_connection_integrationtest.cc b/pc/peer_connection_integrationtest.cc
index d514152..3a39971 100644
--- a/pc/peer_connection_integrationtest.cc
+++ b/pc/peer_connection_integrationtest.cc
@@ -3450,8 +3450,8 @@
}
static void MakeSpecCompliantSctpOffer(cricket::SessionDescription* desc) {
- cricket::DataContentDescription* dcd_offer =
- GetFirstDataContentDescription(desc);
+ cricket::SctpDataContentDescription* dcd_offer =
+ GetFirstSctpDataContentDescription(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 d4ccb50..cf3d147 100644
--- a/pc/session_description.cc
+++ b/pc/session_description.cc
@@ -15,6 +15,7 @@
#include "absl/algorithm/container.h"
#include "absl/memory/memory.h"
+#include "pc/media_protocol_names.h"
#include "rtc_base/checks.h"
namespace cricket {
@@ -183,6 +184,24 @@
}
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(
@@ -272,4 +291,406 @@
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();
+ } else {
+ // Copy all information collected so far, including codecs.
+ Super::operator=(*o);
+ }
+}
+
+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 protocol isn't decided at this point, we have a problem.
+ RTC_CHECK(real_description_);
+ 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_) {
+ CreateShimTarget(IsSctpProtocol(protocol));
+ }
+ real_description_->set_protocol(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();
+ }
+ return real_description_->mutable_streams();
+}
+void DataContentDescription::AddStream(const StreamParams& stream) {
+ if (!real_description_) {
+ return Super::AddStream(stream);
+ }
+ 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 7e62510..27b781f 100644
--- a/pc/session_description.h
+++ b/pc/session_description.h
@@ -18,6 +18,7 @@
#include <string>
#include <vector>
+#include "absl/memory/memory.h"
#include "api/crypto_params.h"
#include "api/media_types.h"
#include "api/rtp_parameters.h"
@@ -26,6 +27,7 @@
#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/deprecation.h"
#include "rtc_base/socket_address.h"
@@ -34,7 +36,7 @@
typedef std::vector<AudioCodec> AudioCodecs;
typedef std::vector<VideoCodec> VideoCodecs;
-typedef std::vector<DataCodec> DataCodecs;
+typedef std::vector<RtpDataCodec> RtpDataCodecs;
typedef std::vector<CryptoParams> CryptoParamsVec;
typedef std::vector<webrtc::RtpExtension> RtpHeaderExtensions;
@@ -45,19 +47,15 @@
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 DataContentDescription;
class VideoContentDescription;
+class DataContentDescription;
+class RtpDataContentDescription;
+class SctpDataContentDescription;
// Describes a session description media section. There are subclasses for each
// media type (audio, video, data) that will have additional information.
@@ -78,61 +76,77 @@
virtual VideoContentDescription* as_video() { return nullptr; }
virtual const VideoContentDescription* as_video() const { return nullptr; }
- // Try to cast this media description to a DataContentDescription. Returns
- // nullptr if the cast fails.
+ // Backwards compatible shim: Return a shim object that allows
+ // callers to ignore the distinction between RtpDataContentDescription
+ // and SctpDataContentDescription objects.
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.
- std::string protocol() const { return protocol_; }
- void set_protocol(const std::string& protocol) { protocol_ = protocol; }
+ virtual std::string protocol() const { return protocol_; }
+ virtual void set_protocol(const std::string& protocol) {
+ protocol_ = protocol;
+ }
- webrtc::RtpTransceiverDirection direction() const { return direction_; }
- void set_direction(webrtc::RtpTransceiverDirection direction) {
+ virtual webrtc::RtpTransceiverDirection direction() const {
+ return direction_;
+ }
+ virtual void set_direction(webrtc::RtpTransceiverDirection direction) {
direction_ = direction;
}
- bool rtcp_mux() const { return rtcp_mux_; }
- void set_rtcp_mux(bool mux) { rtcp_mux_ = mux; }
+ virtual bool rtcp_mux() const { return rtcp_mux_; }
+ virtual void set_rtcp_mux(bool mux) { rtcp_mux_ = mux; }
- bool rtcp_reduced_size() const { return rtcp_reduced_size_; }
- void set_rtcp_reduced_size(bool reduced_size) {
+ virtual bool rtcp_reduced_size() const { return rtcp_reduced_size_; }
+ virtual void set_rtcp_reduced_size(bool reduced_size) {
rtcp_reduced_size_ = reduced_size;
}
- int bandwidth() const { return bandwidth_; }
- void set_bandwidth(int bandwidth) { bandwidth_ = bandwidth; }
+ virtual int bandwidth() const { return bandwidth_; }
+ virtual void set_bandwidth(int bandwidth) { bandwidth_ = bandwidth; }
- 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) {
+ 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) {
cryptos_ = cryptos;
}
- const RtpHeaderExtensions& rtp_header_extensions() const {
+ virtual const RtpHeaderExtensions& rtp_header_extensions() const {
return rtp_header_extensions_;
}
- void set_rtp_header_extensions(const RtpHeaderExtensions& extensions) {
+ virtual void set_rtp_header_extensions(
+ const RtpHeaderExtensions& extensions) {
rtp_header_extensions_ = extensions;
rtp_header_extensions_set_ = true;
}
- void AddRtpHeaderExtension(const webrtc::RtpExtension& ext) {
+ virtual void AddRtpHeaderExtension(const webrtc::RtpExtension& ext) {
rtp_header_extensions_.push_back(ext);
rtp_header_extensions_set_ = true;
}
- void AddRtpHeaderExtension(const cricket::RtpHeaderExtension& ext) {
+ virtual 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;
}
- void ClearRtpHeaderExtensions() {
+ virtual void ClearRtpHeaderExtensions() {
rtp_header_extensions_.clear();
rtp_header_extensions_set_ = true;
}
@@ -141,62 +155,65 @@
// 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).
- bool rtp_header_extensions_set() const { return rtp_header_extensions_set_; }
- const StreamParamsVec& streams() const { return send_streams_; }
+ virtual bool rtp_header_extensions_set() const {
+ return rtp_header_extensions_set_;
+ }
+ virtual const StreamParamsVec& streams() const { return send_streams_; }
// TODO(pthatcher): Remove this by giving mediamessage.cc access
// to MediaContentDescription
- StreamParamsVec& mutable_streams() { return send_streams_; }
- void AddStream(const StreamParams& stream) {
+ virtual StreamParamsVec& mutable_streams() { return send_streams_; }
+ virtual void AddStream(const StreamParams& stream) {
send_streams_.push_back(stream);
}
// Legacy streams have an ssrc, but nothing else.
void AddLegacyStream(uint32_t ssrc) {
- send_streams_.push_back(StreamParams::CreateLegacy(ssrc));
+ AddStream(StreamParams::CreateLegacy(ssrc));
}
void AddLegacyStream(uint32_t ssrc, uint32_t fid_ssrc) {
StreamParams sp = StreamParams::CreateLegacy(ssrc);
sp.AddFidSsrc(ssrc, fid_ssrc);
- send_streams_.push_back(sp);
+ AddStream(sp);
}
// Sets the CNAME of all StreamParams if it have not been set.
- void SetCnameIfEmpty(const std::string& cname) {
+ virtual 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;
}
}
- uint32_t first_ssrc() const {
+ virtual uint32_t first_ssrc() const {
if (send_streams_.empty()) {
return 0;
}
return send_streams_[0].first_ssrc();
}
- bool has_ssrcs() const {
+ virtual bool has_ssrcs() const {
if (send_streams_.empty()) {
return false;
}
return send_streams_[0].has_ssrcs();
}
- void set_conference_mode(bool enable) { conference_mode_ = enable; }
- bool conference_mode() const { return conference_mode_; }
+ virtual void set_conference_mode(bool enable) { conference_mode_ = enable; }
+ virtual 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.
- void set_connection_address(const rtc::SocketAddress& address) {
+ virtual void set_connection_address(const rtc::SocketAddress& address) {
connection_address_ = address;
}
- const rtc::SocketAddress& connection_address() const {
+ virtual 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 };
- void set_extmap_allow_mixed_enum(ExtmapAllowMixed new_extmap_allow_mixed) {
+ virtual 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.
@@ -204,10 +221,12 @@
}
extmap_allow_mixed_enum_ = new_extmap_allow_mixed;
}
- ExtmapAllowMixed extmap_allow_mixed_enum() const {
+ virtual ExtmapAllowMixed extmap_allow_mixed_enum() const {
return extmap_allow_mixed_enum_;
}
- bool extmap_allow_mixed() const { return extmap_allow_mixed_enum_ != kNo; }
+ virtual bool extmap_allow_mixed() const {
+ return extmap_allow_mixed_enum_ != kNo;
+ }
// Simulcast functionality.
virtual bool HasSimulcast() const { return !simulcast_.empty(); }
@@ -248,13 +267,18 @@
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).
- 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) {
+ 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) {
bool found = false;
for (typename std::vector<C>::iterator iter = codecs_.begin();
iter != codecs_.end(); ++iter) {
@@ -265,8 +289,8 @@
}
return found;
}
- void AddCodec(const C& codec) { codecs_.push_back(codec); }
- void AddOrReplaceCodec(const C& codec) {
+ virtual void AddCodec(const C& codec) { codecs_.push_back(codec); }
+ virtual void AddOrReplaceCodec(const C& codec) {
for (typename std::vector<C>::iterator iter = codecs_.begin();
iter != codecs_.end(); ++iter) {
if (iter->id == codec.id) {
@@ -276,7 +300,7 @@
}
AddCodec(codec);
}
- void AddCodecs(const std::vector<C>& codecs) {
+ virtual void AddCodecs(const std::vector<C>& codecs) {
typename std::vector<C>::const_iterator codec;
for (codec = codecs.begin(); codec != codecs.end(); ++codec) {
AddCodec(*codec);
@@ -309,22 +333,173 @@
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() {}
+ DataContentDescription();
+ MediaType type() const override { return MEDIA_TYPE_DATA; }
+ DataContentDescription* as_data() override { return this; }
+ const DataContentDescription* as_data() const override { return this; }
- virtual DataContentDescription* Copy() const {
- return new DataContentDescription(*this);
+ // Override all methods defined in MediaContentDescription.
+ bool has_codecs() const override;
+ DataContentDescription* Copy() const override {
+ 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; }
+ 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;
+
+ 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;
+ }
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;
+ 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_;
};
// 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 3b05dca..9797ed5 100644
--- a/pc/session_description_unittest.cc
+++ b/pc/session_description_unittest.cc
@@ -9,6 +9,7 @@
*/
#include "pc/session_description.h"
+#include "absl/memory/memory.h"
#include "test/gtest.h"
namespace cricket {
@@ -121,11 +122,69 @@
video_desc->extmap_allow_mixed_enum());
// Session level setting overrides media level when new content is added.
- MediaContentDescription* data_desc = new DataContentDescription;
+ MediaContentDescription* data_desc = new RtpDataContentDescription;
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 97015fe..c6968b1 100644
--- a/pc/webrtc_sdp.cc
+++ b/pc/webrtc_sdp.cc
@@ -76,7 +76,9 @@
using cricket::MediaProtocolType;
using cricket::MediaType;
using cricket::RidDescription;
+using cricket::RtpDataContentDescription;
using cricket::RtpHeaderExtensions;
+using cricket::SctpDataContentDescription;
using cricket::SimulcastDescription;
using cricket::SimulcastLayer;
using cricket::SimulcastLayerList;
@@ -285,8 +287,6 @@
std::string* message);
static void BuildIceOptions(const std::vector<std::string>& transport_options,
std::string* message);
-static bool IsRtp(const std::string& protocol);
-static bool IsDtlsSctp(const std::string& protocol);
static bool ParseSessionDescription(const std::string& message,
size_t* pos,
std::string* session_id,
@@ -1337,8 +1337,6 @@
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,25 +1364,20 @@
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* sctp_data_desc =
+ media_desc->as_sctp();
+ if (sctp_data_desc) {
fmt.append(" ");
- if (data_desc->use_sctpmap()) {
- 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));
+ if (sctp_data_desc->use_sctpmap()) {
+ fmt.append(rtc::ToString(sctp_data_desc->port()));
} else {
fmt.append(kDefaultSctpmapProtocol);
}
} else {
- for (const cricket::DataCodec& codec : data_desc->codecs()) {
+ const RtpDataContentDescription* rtp_data_desc =
+ media_desc->as_rtp_data();
+ for (const cricket::RtpDataCodec& codec : rtp_data_desc->codecs()) {
fmt.append(" ");
fmt.append(rtc::ToString(codec.id));
}
@@ -1455,7 +1448,7 @@
}
// Add the a=rtcp line.
- if (IsRtp(media_desc->protocol())) {
+ if (cricket::IsRtpProtocol(media_desc->protocol())) {
std::string rtcp_line = GetRtcpLine(candidates);
if (!rtcp_line.empty()) {
AddLine(rtcp_line, message);
@@ -1522,11 +1515,12 @@
os << kSdpDelimiterColon << content_info->name;
AddLine(os.str(), message);
- if (IsDtlsSctp(media_desc->protocol())) {
- const DataContentDescription* data_desc = media_desc->as_data();
+ if (cricket::IsDtlsSctp(media_desc->protocol())) {
+ const cricket::SctpDataContentDescription* data_desc =
+ media_desc->as_sctp();
bool use_sctpmap = data_desc->use_sctpmap();
- BuildSctpContentAttributes(message, sctp_port, use_sctpmap);
- } else if (IsRtp(media_desc->protocol())) {
+ BuildSctpContentAttributes(message, data_desc->port(), use_sctpmap);
+ } else if (cricket::IsRtpProtocol(media_desc->protocol())) {
BuildRtpContentAttributes(media_desc, media_type, msid_signaling, message);
}
}
@@ -1834,43 +1828,6 @@
}
}
-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;
@@ -1960,14 +1917,17 @@
AddAttributeLine(kCodecParamPTime, ptime, message);
}
} else if (media_type == cricket::MEDIA_TYPE_DATA) {
- for (const cricket::DataCodec& codec : media_desc->as_data()->codecs()) {
- // RFC 4566
- // a=rtpmap:<payload type> <encoding name>/<clock rate>
- // [/<encodingparameters>]
- InitAttrLine(kAttributeRtpmap, &os);
- os << kSdpDelimiterColon << codec.id << " " << codec.name << "/"
- << codec.clockrate;
- AddLine(os.str(), message);
+ if (media_desc->as_rtp_data()) {
+ for (const cricket::RtpDataCodec& codec :
+ media_desc->as_rtp_data()->codecs()) {
+ // RFC 4566
+ // a=rtpmap:<payload type> <encoding name>/<clock rate>
+ // [/<encodingparameters>]
+ InitAttrLine(kAttributeRtpmap, &os);
+ os << kSdpDelimiterColon << codec.id << " " << codec.name << "/"
+ << codec.clockrate;
+ AddLine(os.str(), message);
+ }
}
}
}
@@ -2053,16 +2013,6 @@
}
}
-bool IsRtp(const std::string& protocol) {
- return protocol.empty() ||
- (protocol.find(cricket::kMediaProtocolRtpPrefix) != std::string::npos);
-}
-
-bool IsDtlsSctp(const std::string& protocol) {
- // This intentionally excludes "SCTP" and "SCTP/DTLS".
- return protocol.find(cricket::kMediaProtocolDtlsSctp) != std::string::npos;
-}
-
bool ParseConnectionData(const std::string& line,
rtc::SocketAddress* addr,
SdpParseError* error) {
@@ -2710,7 +2660,7 @@
// <fmt>
std::vector<int> payload_types;
- if (IsRtp(protocol)) {
+ if (cricket::IsRtpProtocol(protocol)) {
for (size_t j = 3; j < fields.size(); ++j) {
// TODO(wu): Remove when below bug is fixed.
// https://bugzilla.mozilla.org/show_bug.cgi?id=996329
@@ -2748,24 +2698,37 @@
payload_types, pos, &content_name, &bundle_only,
§ion_msid_signaling, &transport, candidates, error);
} else if (HasAttribute(line, kMediaTypeData)) {
- 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)) {
+ if (cricket::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>();
int p;
if (rtc::FromString(fields[3], &p)) {
- if (!AddOrModifySctpDataCodecPort(data_desc.get(), p)) {
- return false;
- }
+ data_desc->set_port(p);
} 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;
+ }
+ data_desc->set_protocol(protocol);
+ 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;
@@ -2796,7 +2759,8 @@
content_rejected = port_rejected;
}
- if (IsRtp(protocol)) {
+ if (cricket::IsRtpProtocol(protocol) && !content->as_sctp()) {
+ content->set_protocol(protocol);
// Set the extmap.
if (!session_extmaps.empty() &&
!content->rtp_header_extensions().empty()) {
@@ -2808,8 +2772,12 @@
for (size_t i = 0; i < session_extmaps.size(); ++i) {
content->AddRtpHeaderExtension(session_extmaps[i]);
}
+ } else if (content->as_sctp()) {
+ // Do nothing, it's OK
+ } else {
+ RTC_LOG(LS_WARNING) << "Parse failed with unknown protocol " << protocol;
+ return false;
}
- content->set_protocol(protocol);
// Use the session level connection address if the media level addresses are
// not specified.
@@ -2821,8 +2789,8 @@
content->set_connection_address(address);
desc->AddContent(content_name,
- IsDtlsSctp(protocol) ? MediaProtocolType::kSctp
- : MediaProtocolType::kRtp,
+ cricket::IsDtlsSctp(protocol) ? MediaProtocolType::kSctp
+ : MediaProtocolType::kRtp,
content_rejected, bundle_only, content.release());
// Create TransportInfo with the media level "ice-pwd" and "ice-ufrag".
desc->AddTransportInfo(TransportInfo(content_name, transport));
@@ -3051,7 +3019,8 @@
// data channels. Don't allow SDP to set the bandwidth, because
// that would give JS the opportunity to "break the Internet".
// See: https://code.google.com/p/chromium/issues/detail?id=280726
- if (media_type == cricket::MEDIA_TYPE_DATA && IsRtp(protocol) &&
+ if (media_type == cricket::MEDIA_TYPE_DATA &&
+ cricket::IsRtpProtocol(protocol) &&
b > cricket::kDataMaxBandwidth / 1000) {
rtc::StringBuilder description;
description << "RTP-based data channels may not send more than "
@@ -3132,20 +3101,23 @@
if (!ParseDtlsSetup(line, &(transport->connection_role), error)) {
return false;
}
- } else if (IsDtlsSctp(protocol) && HasAttribute(line, kAttributeSctpPort)) {
+ } else if (cricket::IsDtlsSctp(protocol) &&
+ HasAttribute(line, kAttributeSctpPort)) {
if (media_type != cricket::MEDIA_TYPE_DATA) {
return ParseFailed(
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;
}
- if (!AddOrModifySctpDataCodecPort(media_desc->as_data(), sctp_port)) {
- return false;
- }
- } else if (IsDtlsSctp(protocol) &&
+ media_desc->as_sctp()->set_port(sctp_port);
+ } else if (cricket::IsDtlsSctp(protocol) &&
HasAttribute(line, kAttributeMaxMessageSize)) {
if (media_type != cricket::MEDIA_TYPE_DATA) {
return ParseFailed(
@@ -3157,11 +3129,8 @@
if (!ParseSctpMaxMessageSize(line, &max_message_size, error)) {
return false;
}
- if (!AddOrModifySctpDataMaxMessageSize(media_desc->as_data(),
- max_message_size)) {
- return false;
- }
- } else if (IsRtp(protocol)) {
+ media_desc->as_sctp()->set_max_message_size(max_message_size);
+ } else if (cricket::IsRtpProtocol(protocol)) {
//
// RTP specific attrubtes
//
@@ -3621,8 +3590,10 @@
UpdateCodec(payload_type, encoding_name, clock_rate, 0, channels,
audio_desc);
} else if (media_type == cricket::MEDIA_TYPE_DATA) {
- DataContentDescription* data_desc = media_desc->as_data();
- data_desc->AddCodec(cricket::DataCodec(payload_type, encoding_name));
+ RtpDataContentDescription* data_desc = media_desc->as_rtp_data();
+ if (data_desc) {
+ data_desc->AddCodec(cricket::RtpDataCodec(payload_type, encoding_name));
+ }
}
return true;
}
diff --git a/pc/webrtc_sdp_unittest.cc b/pc/webrtc_sdp_unittest.cc
index 7294cfc..9048ee5 100644
--- a/pc/webrtc_sdp_unittest.cc
+++ b/pc/webrtc_sdp_unittest.cc
@@ -56,7 +56,6 @@
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;
@@ -65,6 +64,8 @@
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;
@@ -275,6 +276,7 @@
"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"
@@ -1443,10 +1445,17 @@
simulcast2.receive_layers().size());
}
- void CompareDataContentDescription(const DataContentDescription* dcd1,
- const DataContentDescription* dcd2) {
+ void CompareRtpDataContentDescription(const RtpDataContentDescription* dcd1,
+ const RtpDataContentDescription* dcd2) {
+ CompareMediaContentDescription<RtpDataContentDescription>(dcd1, dcd2);
+ }
+
+ void CompareSctpDataContentDescription(
+ const SctpDataContentDescription* dcd1,
+ const SctpDataContentDescription* dcd2) {
EXPECT_EQ(dcd1->use_sctpmap(), dcd2->use_sctpmap());
- CompareMediaContentDescription<DataContentDescription>(dcd1, dcd2);
+ EXPECT_EQ(dcd1->port(), dcd2->port());
+ EXPECT_EQ(dcd1->max_message_size(), dcd2->max_message_size());
}
void CompareSessionDescription(const SessionDescription& desc1,
@@ -1484,10 +1493,21 @@
}
ASSERT_EQ(IsDataContent(&c1), IsDataContent(&c2));
- if (IsDataContent(&c1)) {
- const DataContentDescription* dcd1 = c1.media_description()->as_data();
- const DataContentDescription* dcd2 = c2.media_description()->as_data();
- CompareDataContentDescription(dcd1, dcd2);
+ 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);
+ }
}
CompareSimulcastDescription(
@@ -1760,14 +1780,12 @@
}
void AddSctpDataChannel(bool use_sctpmap) {
- 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);
+ 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);
desc_.AddContent(kDataContentName, MediaProtocolType::kSctp,
data.release());
desc_.AddTransportInfo(TransportInfo(
@@ -1775,7 +1793,8 @@
}
void AddRtpDataChannel() {
- std::unique_ptr<DataContentDescription> data(new DataContentDescription());
+ std::unique_ptr<RtpDataContentDescription> data(
+ new RtpDataContentDescription());
data_desc_ = data.get();
data_desc_->AddCodec(DataCodec(101, "google-data"));
@@ -2043,7 +2062,8 @@
SessionDescription desc_;
AudioContentDescription* audio_desc_;
VideoContentDescription* video_desc_;
- DataContentDescription* data_desc_;
+ RtpDataContentDescription* data_desc_;
+ SctpDataContentDescription* sctp_desc_;
Candidates candidates_;
std::unique_ptr<IceCandidateInterface> jcandidate_;
JsepSessionDescription jdesc_;
@@ -2215,21 +2235,26 @@
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.
+ std::unique_ptr<cricket::SessionDescription> mutant = desc.Clone();
+ SctpDataContentDescription* dcdesc =
+ mutant->GetContentDescriptionByName(kDataContentName)->as_sctp();
+ dcdesc->set_port(port);
+ ASSERT_TRUE(
+ jdesc->Initialize(std::move(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;
- cricket::DataCodec codec(cricket::kGoogleSctpDataCodecPlType,
- cricket::kGoogleSctpDataCodecName);
- codec.SetParam(cricket::kCodecParamPort, kNewPort);
- dcdesc->AddOrReplaceCodec(codec);
+ MutateJsepSctpPort(&jsep_desc, desc_, kNewPort);
std::string message = webrtc::SdpSerialize(jsep_desc);
@@ -2868,14 +2893,12 @@
// Helper function to set the max-message-size parameter in the
// SCTP data codec.
void MutateJsepSctpMaxMessageSize(const SessionDescription& desc,
- const std::string& new_value,
+ int new_value,
JsepSessionDescription* jdesc) {
std::unique_ptr<cricket::SessionDescription> mutant = desc.Clone();
- 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);
+ SctpDataContentDescription* dcdesc =
+ mutant->GetContentDescriptionByName(kDataContentName)->as_sctp();
+ dcdesc->set_max_message_size(new_value);
jdesc->Initialize(std::move(mutant), kSessionId, kSessionVersion);
}
@@ -2887,7 +2910,7 @@
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.
@@ -2925,6 +2948,44 @@
EXPECT_FALSE(SdpDeserialize(sdp_with_data, &jdesc_output));
}
+// Test behavior if a=rtpmap occurs in an SCTP section.
+TEST_F(WebRtcSdpTest, DeserializeSdpWithRtpmapAttribute) {
+ std::string sdp_with_data = kSdpString;
+ // Append m= attributes
+ sdp_with_data.append(kSdpSctpDataChannelString);
+ // Append a=rtpmap attribute
+ sdp_with_data.append("a=rtpmap:111 opus/48000/2\r\n");
+ JsepSessionDescription jdesc_output(kDummyType);
+ // Correct behavior is to ignore the extra attribute.
+ EXPECT_TRUE(SdpDeserialize(sdp_with_data, &jdesc_output));
+}
+
+TEST_F(WebRtcSdpTest, DeserializeSdpWithStrangeApplicationProtocolNames) {
+ static const char* bad_strings[] = {"DTLS/SCTPRTP/", "obviously-bogus",
+ "UDP/TL/RTSP/SAVPF", "UDP/TL/RTSP/S"};
+ for (auto proto : bad_strings) {
+ std::string sdp_with_data = kSdpString;
+ sdp_with_data.append("m=application 9 ");
+ sdp_with_data.append(proto);
+ sdp_with_data.append(" 47\r\n");
+ JsepSessionDescription jdesc_output(kDummyType);
+ EXPECT_FALSE(SdpDeserialize(sdp_with_data, &jdesc_output))
+ << "Parsing should have failed on " << proto;
+ }
+ // The following strings are strange, but acceptable as RTP.
+ static const char* weird_strings[] = {"DTLS/SCTP/RTP/FOO",
+ "obviously-bogus/RTP/"};
+ for (auto proto : weird_strings) {
+ std::string sdp_with_data = kSdpString;
+ sdp_with_data.append("m=application 9 ");
+ sdp_with_data.append(proto);
+ sdp_with_data.append(" 47\r\n");
+ JsepSessionDescription jdesc_output(kDummyType);
+ EXPECT_TRUE(SdpDeserialize(sdp_with_data, &jdesc_output))
+ << "Parsing should have succeeded on " << proto;
+ }
+}
+
// For crbug/344475.
TEST_F(WebRtcSdpTest, DeserializeSdpWithCorruptedSctpDataChannels) {
std::string sdp_with_data = kSdpString;
@@ -2937,29 +2998,13 @@
// 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_);
+ MutateJsepSctpPort(&jdesc, desc_, kUnusualSctpPort);
// Then get the deserialized JsepSessionDescription.
std::string sdp_with_data = kSdpString;
@@ -2979,7 +3024,7 @@
AddSctpDataChannel(use_sctpmap);
JsepSessionDescription jdesc(kDummyType);
- MutateJsepSctpPort(&jdesc, desc_);
+ MutateJsepSctpPort(&jdesc, desc_, kUnusualSctpPort);
// We need to test the deserialized JsepSessionDescription from
// kSdpSctpDataChannelStringWithSctpPort for
@@ -3015,7 +3060,7 @@
bool use_sctpmap = true;
AddSctpDataChannel(use_sctpmap);
JsepSessionDescription jdesc(kDummyType);
- DataContentDescription* dcd = GetFirstDataContentDescription(&desc_);
+ SctpDataContentDescription* dcd = GetFirstSctpDataContentDescription(&desc_);
dcd->set_bandwidth(100 * 1000);
ASSERT_TRUE(jdesc.Initialize(desc_.Clone(), kSessionId, kSessionVersion));