Change default SDP syntax for SCTP to spec-compliant.

This also introduces an option in CreateOfferOptions for
getting the non-spec behavior (2013 vintage) back.

Bug: chromium:962860
Change-Id: I72267408a61d6eb03e9895fe38b4cc803d8cbbaf
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/136809
Commit-Queue: Harald Alvestrand <hta@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#27941}
diff --git a/api/peer_connection_interface.h b/api/peer_connection_interface.h
index 41a1c0f..f64b623 100644
--- a/api/peer_connection_interface.h
+++ b/api/peer_connection_interface.h
@@ -664,6 +664,10 @@
     // This will apply to all video tracks with a Plan B SDP offer/answer.
     int num_simulcast_layers = 1;
 
+    // If true: Use SDP format from draft-ietf-mmusic-scdp-sdp-03
+    // If false: Use SDP format from draft-ietf-mmusic-sdp-sdp-26 or later
+    bool use_obsolete_sctp_sdp = false;
+
     RTCOfferAnswerOptions() = default;
 
     RTCOfferAnswerOptions(int offer_to_receive_video,
diff --git a/pc/media_session.cc b/pc/media_session.cc
index 77bd715..69ebb84 100644
--- a/pc/media_session.cc
+++ b/pc/media_session.cc
@@ -2237,7 +2237,7 @@
   // generate SSRCs rather than SIDs.
   data->set_protocol(secure_transport ? kMediaProtocolUdpDtlsSctp
                                       : kMediaProtocolSctp);
-
+  data->set_use_sctpmap(session_options.use_obsolete_sctp_sdp);
   if (!CreateContentOffer(media_description_options, session_options,
                           sdes_policy, GetCryptos(current_content),
                           crypto_suites, RtpHeaderExtensions(), ssrc_generator_,
diff --git a/pc/media_session.h b/pc/media_session.h
index dc889b2..73cedc4 100644
--- a/pc/media_session.h
+++ b/pc/media_session.h
@@ -118,6 +118,11 @@
   // supported transports.
   absl::optional<cricket::SessionDescription::MediaTransportSetting>
       media_transport_settings;
+  // Use the draft-ietf-mmusic-sctp-sdp-03 obsolete syntax for SCTP
+  // datachannels.
+  // Default is true for backwards compatibility with clients that use
+  // this internal interface.
+  bool use_obsolete_sctp_sdp = true;
 };
 
 // Creates media session descriptions according to the supplied codecs and
diff --git a/pc/peer_connection.cc b/pc/peer_connection.cc
index 781b3a5..fcd1a2a 100644
--- a/pc/peer_connection.cc
+++ b/pc/peer_connection.cc
@@ -4299,6 +4299,11 @@
     session_options->media_transport_settings =
         transport_controller_->GenerateOrGetLastMediaTransportOffer();
   }
+  // Allow fallback for using obsolete SCTP syntax.
+  // Note that the default in |session_options| is true, while
+  // the default in |options| is false.
+  session_options->use_obsolete_sctp_sdp =
+      offer_answer_options.use_obsolete_sctp_sdp;
 }
 
 void PeerConnection::GetOptionsForPlanBOffer(
diff --git a/pc/peer_connection_data_channel_unittest.cc b/pc/peer_connection_data_channel_unittest.cc
index 4080dd9..435d1eb 100644
--- a/pc/peer_connection_data_channel_unittest.cc
+++ b/pc/peer_connection_data_channel_unittest.cc
@@ -41,6 +41,7 @@
 #include "rtc_base/ref_counted_object.h"
 #include "rtc_base/rtc_certificate_generator.h"
 #include "rtc_base/thread.h"
+#include "test/gmock.h"
 #include "test/gtest.h"
 #ifdef WEBRTC_ANDROID
 #include "pc/test/android_test_initializer.h"
@@ -53,6 +54,8 @@
 
 using RTCConfiguration = PeerConnectionInterface::RTCConfiguration;
 using RTCOfferAnswerOptions = PeerConnectionInterface::RTCOfferAnswerOptions;
+using ::testing::HasSubstr;
+using ::testing::Not;
 using ::testing::Values;
 
 namespace {
@@ -411,6 +414,32 @@
   EXPECT_EQ(nullptr, caller);
 }
 
+TEST_P(PeerConnectionDataChannelTest, ModernSdpSyntaxByDefault) {
+  PeerConnectionInterface::RTCOfferAnswerOptions options;
+  auto caller = CreatePeerConnectionWithDataChannel();
+  auto offer = caller->CreateOffer(options);
+  EXPECT_FALSE(cricket::GetFirstSctpDataContentDescription(offer->description())
+                   ->use_sctpmap());
+  std::string sdp;
+  offer->ToString(&sdp);
+  RTC_LOG(LS_ERROR) << sdp;
+  EXPECT_THAT(sdp, HasSubstr(" UDP/DTLS/SCTP webrtc-datachannel"));
+  EXPECT_THAT(sdp, Not(HasSubstr("a=sctpmap:")));
+}
+
+TEST_P(PeerConnectionDataChannelTest, ObsoleteSdpSyntaxIfSet) {
+  PeerConnectionInterface::RTCOfferAnswerOptions options;
+  options.use_obsolete_sctp_sdp = true;
+  auto caller = CreatePeerConnectionWithDataChannel();
+  auto offer = caller->CreateOffer(options);
+  EXPECT_TRUE(cricket::GetFirstSctpDataContentDescription(offer->description())
+                  ->use_sctpmap());
+  std::string sdp;
+  offer->ToString(&sdp);
+  EXPECT_THAT(sdp, Not(HasSubstr(" UDP/DTLS/SCTP webrtc-datachannel")));
+  EXPECT_THAT(sdp, HasSubstr("a=sctpmap:"));
+}
+
 INSTANTIATE_TEST_SUITE_P(PeerConnectionDataChannelTest,
                          PeerConnectionDataChannelTest,
                          Values(SdpSemantics::kPlanB,