Don't crash when renegotiating after the peer rejects data channels

Bug: webrtc:11320
Change-Id: I5a58d550574a4e0702fc6f05b7fb663fbc23d0b4
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/168200
Commit-Queue: Steve Anton <steveanton@webrtc.org>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#30463}
diff --git a/pc/media_session.cc b/pc/media_session.cc
index e764101..5f0c1ff 100644
--- a/pc/media_session.cc
+++ b/pc/media_session.cc
@@ -2255,7 +2255,7 @@
   }
 
   desc->AddContent(media_description_options.mid, MediaProtocolType::kSctp,
-                   std::move(data));
+                   media_description_options.stopped, std::move(data));
   if (!AddTransportOffer(media_description_options.mid,
                          media_description_options.transport_options,
                          current_description, desc, ice_credentials)) {
diff --git a/pc/peer_connection.cc b/pc/peer_connection.cc
index 5ace3e3..2e138c4 100644
--- a/pc/peer_connection.cc
+++ b/pc/peer_connection.cc
@@ -5128,13 +5128,18 @@
       }
     } else {
       RTC_CHECK_EQ(cricket::MEDIA_TYPE_DATA, media_type);
-      RTC_CHECK(GetDataMid());
-      if (had_been_rejected || mid != *GetDataMid()) {
+      if (had_been_rejected) {
         session_options->media_description_options.push_back(
             GetMediaDescriptionOptionsForRejectedData(mid));
       } else {
-        session_options->media_description_options.push_back(
-            GetMediaDescriptionOptionsForActiveData(mid));
+        RTC_CHECK(GetDataMid());
+        if (mid == *GetDataMid()) {
+          session_options->media_description_options.push_back(
+              GetMediaDescriptionOptionsForActiveData(mid));
+        } else {
+          session_options->media_description_options.push_back(
+              GetMediaDescriptionOptionsForRejectedData(mid));
+        }
       }
     }
   }
diff --git a/pc/peer_connection_data_channel_unittest.cc b/pc/peer_connection_data_channel_unittest.cc
index 61c669b..0a674f4 100644
--- a/pc/peer_connection_data_channel_unittest.cc
+++ b/pc/peer_connection_data_channel_unittest.cc
@@ -212,6 +212,13 @@
       : PeerConnectionDataChannelBaseTest(GetParam()) {}
 };
 
+class PeerConnectionDataChannelUnifiedPlanTest
+    : public PeerConnectionDataChannelBaseTest {
+ protected:
+  PeerConnectionDataChannelUnifiedPlanTest()
+      : PeerConnectionDataChannelBaseTest(SdpSemantics::kUnifiedPlan) {}
+};
+
 TEST_P(PeerConnectionDataChannelTest,
        NoSctpTransportCreatedIfRtpDataChannelEnabled) {
   RTCConfiguration config;
@@ -411,4 +418,28 @@
                          Values(SdpSemantics::kPlanB,
                                 SdpSemantics::kUnifiedPlan));
 
+TEST_F(PeerConnectionDataChannelUnifiedPlanTest,
+       ReOfferAfterPeerRejectsDataChannel) {
+  auto caller = CreatePeerConnectionWithDataChannel();
+  PeerConnectionFactoryInterface::Options options;
+  options.disable_sctp_data_channels = true;
+  auto callee = CreatePeerConnection(RTCConfiguration(), options);
+
+  ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
+
+  auto offer = caller->CreateOffer();
+  ASSERT_TRUE(offer);
+  const auto& contents = offer->description()->contents();
+  ASSERT_EQ(1u, contents.size());
+  EXPECT_TRUE(contents[0].rejected);
+
+  ASSERT_TRUE(
+      caller->SetLocalDescription(CloneSessionDescription(offer.get())));
+  ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
+
+  auto answer = callee->CreateAnswerAndSetAsLocal();
+  ASSERT_TRUE(answer);
+  EXPECT_TRUE(caller->SetRemoteDescription(std::move(answer)));
+}
+
 }  // namespace webrtc