Remove SctpDataChannelControllerInterface::ConnectDataChannel

Bug: webrtc:11547
Change-Id: I389cb641746ef892106c22fd46b8d70218b99f58
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/297421
Commit-Queue: Tomas Gunnarsson <tommi@webrtc.org>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#39608}
diff --git a/pc/BUILD.gn b/pc/BUILD.gn
index c0c2010..812df05 100644
--- a/pc/BUILD.gn
+++ b/pc/BUILD.gn
@@ -887,11 +887,9 @@
     "../rtc_base:macromagic",
     "../rtc_base:ssl",
     "../rtc_base:threading",
-    "../rtc_base:threading",
     "../rtc_base:weak_ptr",
     "../rtc_base/containers:flat_set",
     "../rtc_base/system:unused",
-    "../rtc_base/third_party/sigslot:sigslot",
   ]
   absl_deps = [
     "//third_party/abseil-cpp/absl/cleanup",
@@ -973,7 +971,6 @@
     "../rtc_base:ssl",
     "../rtc_base:threading",
     "../rtc_base:weak_ptr",
-    "../rtc_base/third_party/sigslot",
   ]
   absl_deps = [
     "//third_party/abseil-cpp/absl/algorithm:container",
diff --git a/pc/data_channel_controller.cc b/pc/data_channel_controller.cc
index 85e43c7..23e7a14 100644
--- a/pc/data_channel_controller.cc
+++ b/pc/data_channel_controller.cc
@@ -43,14 +43,6 @@
   return false;
 }
 
-bool DataChannelController::ConnectDataChannel(
-    SctpDataChannel* webrtc_data_channel) {
-  RTC_DCHECK_RUN_ON(signaling_thread());
-  // TODO(bugs.webrtc.org/11547): This method can be removed once not
-  // needed by `SctpDataChannel`.
-  return data_channel_transport() ? true : false;
-}
-
 void DataChannelController::AddSctpDataStream(int sid) {
   if (data_channel_transport()) {
     network_thread()->BlockingCall([this, sid] {
@@ -144,7 +136,7 @@
     data_channel_transport_ready_to_send_ = true;
     auto copy = sctp_data_channels_;
     for (const auto& channel : copy)
-      channel->OnTransportReady(true);
+      channel->OnTransportReady();
   }));
 }
 
@@ -289,9 +281,19 @@
   }
   // In case `sid` has changed. Update `new_config` accordingly.
   new_config.id = sid.stream_id_int();
-  rtc::scoped_refptr<SctpDataChannel> channel(
-      SctpDataChannel::Create(weak_factory_.GetWeakPtr(), label, new_config,
-                              signaling_thread(), network_thread()));
+  // TODO(bugs.webrtc.org/11547): The `data_channel_transport_` pointer belongs
+  // to the network thread but there are a few places where we check this
+  // pointer from the signaling thread. Instead of this approach, we should have
+  // a separate channel initialization step that runs on the network thread
+  // where we inform the channel of information about whether there's a
+  // transport or not, what the role is, and supply an id if any. Subsequently
+  // all that state in the channel code, is needed for callbacks from the
+  // transport which is already initiated from the network thread. Then we can
+  // Remove the trampoline code (see e.g. PostTask() calls in this file) that
+  // travels between the signaling and network threads.
+  rtc::scoped_refptr<SctpDataChannel> channel(SctpDataChannel::Create(
+      weak_factory_.GetWeakPtr(), label, data_channel_transport() != nullptr,
+      new_config, signaling_thread(), network_thread()));
   if (!channel) {
     sid_allocator_.ReleaseSid(sid);
     return nullptr;
@@ -402,6 +404,7 @@
 
 void DataChannelController::NotifyDataChannelsOfTransportCreated() {
   RTC_DCHECK_RUN_ON(network_thread());
+  RTC_DCHECK(data_channel_transport());
   signaling_thread()->PostTask(SafeTask(signaling_safety_.flag(), [this] {
     RTC_DCHECK_RUN_ON(signaling_thread());
     auto copy = sctp_data_channels_;
diff --git a/pc/data_channel_controller.h b/pc/data_channel_controller.h
index 704dcd3..4dc1d97 100644
--- a/pc/data_channel_controller.h
+++ b/pc/data_channel_controller.h
@@ -51,7 +51,6 @@
                 const SendDataParams& params,
                 const rtc::CopyOnWriteBuffer& payload,
                 cricket::SendDataResult* result) override;
-  bool ConnectDataChannel(SctpDataChannel* webrtc_data_channel) override;
   void AddSctpDataStream(int sid) override;
   void RemoveSctpDataStream(int sid) override;
   bool ReadyToSendData() const override;
diff --git a/pc/data_channel_controller_unittest.cc b/pc/data_channel_controller_unittest.cc
index 0f840e7..1e575e6 100644
--- a/pc/data_channel_controller_unittest.cc
+++ b/pc/data_channel_controller_unittest.cc
@@ -98,11 +98,6 @@
   auto channel = dcc->InternalCreateDataChannelWithProxy(
       "label",
       std::make_unique<InternalDataChannelInit>(DataChannelInit()).get());
-  // Connect to provider
-  auto inner_channel =
-      DowncastProxiedDataChannelInterfaceToSctpDataChannelForTesting(
-          channel.get());
-  dcc->ConnectDataChannel(inner_channel);
   dcc.reset();
   channel->Close();
 }
@@ -122,9 +117,6 @@
   channel = nullptr;  // dcc still holds a reference to `channel`.
   EXPECT_TRUE(dcc.HasDataChannels());
 
-  // Make sure callbacks to dcc are set up.
-  dcc.ConnectDataChannel(inner_channel);
-
   // Trigger a Close() for the channel. This will send events back to dcc,
   // eventually reaching `OnSctpDataChannelClosed` where dcc removes
   // the channel from the internal list of data channels, but does not release
diff --git a/pc/data_channel_unittest.cc b/pc/data_channel_unittest.cc
index f792287..265340f 100644
--- a/pc/data_channel_unittest.cc
+++ b/pc/data_channel_unittest.cc
@@ -71,19 +71,12 @@
   size_t on_buffered_amount_change_count_;
 };
 
-// TODO(deadbeef): The fact that these tests use a fake controller makes them
-// not too valuable. Should rewrite using the
-// peerconnection_datachannel_unittest.cc infrastructure.
 // TODO(bugs.webrtc.org/11547): Incorporate a dedicated network thread.
 class SctpDataChannelTest : public ::testing::Test {
  protected:
   SctpDataChannelTest()
       : controller_(new FakeDataChannelController()),
-        webrtc_data_channel_(SctpDataChannel::Create(controller_->weak_ptr(),
-                                                     "test",
-                                                     init_,
-                                                     rtc::Thread::Current(),
-                                                     rtc::Thread::Current())) {}
+        webrtc_data_channel_(controller_->CreateDataChannel("test", init_)) {}
 
   void SetChannelReady() {
     controller_->set_transport_available(true);
@@ -137,8 +130,7 @@
 TEST_F(SctpDataChannelTest, ConnectedToTransportOnCreated) {
   controller_->set_transport_available(true);
   rtc::scoped_refptr<SctpDataChannel> dc =
-      SctpDataChannel::Create(controller_->weak_ptr(), "test1", init_,
-                              rtc::Thread::Current(), rtc::Thread::Current());
+      controller_->CreateDataChannel("test1", init_);
 
   EXPECT_TRUE(controller_->IsConnected(dc.get()));
   // The sid is not set yet, so it should not have added the streams.
@@ -150,16 +142,6 @@
   EXPECT_TRUE(controller_->IsRecvStreamAdded(dc->id()));
 }
 
-// Verifies that the data channel is connected to the transport if the transport
-// is not available initially and becomes available later.
-TEST_F(SctpDataChannelTest, ConnectedAfterTransportBecomesAvailable) {
-  EXPECT_FALSE(controller_->IsConnected(webrtc_data_channel_.get()));
-
-  controller_->set_transport_available(true);
-  webrtc_data_channel_->OnTransportChannelCreated();
-  EXPECT_TRUE(controller_->IsConnected(webrtc_data_channel_.get()));
-}
-
 // Tests the state of the data channel.
 TEST_F(SctpDataChannelTest, StateTransition) {
   AddObserver();
@@ -327,8 +309,7 @@
   InternalDataChannelInit init;
   init.id = 1;
   rtc::scoped_refptr<SctpDataChannel> dc =
-      SctpDataChannel::Create(controller_->weak_ptr(), "test1", init,
-                              rtc::Thread::Current(), rtc::Thread::Current());
+      controller_->CreateDataChannel("test1", init);
   EXPECT_EQ(DataChannelInterface::kConnecting, dc->state());
   EXPECT_TRUE_WAIT(DataChannelInterface::kOpen == dc->state(), 1000);
 }
@@ -341,8 +322,7 @@
   init.id = 1;
   init.ordered = false;
   rtc::scoped_refptr<SctpDataChannel> dc =
-      SctpDataChannel::Create(controller_->weak_ptr(), "test1", init,
-                              rtc::Thread::Current(), rtc::Thread::Current());
+      controller_->CreateDataChannel("test1", init);
 
   EXPECT_EQ_WAIT(DataChannelInterface::kOpen, dc->state(), 1000);
 
@@ -369,8 +349,7 @@
   init.id = 1;
   init.ordered = false;
   rtc::scoped_refptr<SctpDataChannel> dc =
-      SctpDataChannel::Create(controller_->weak_ptr(), "test1", init,
-                              rtc::Thread::Current(), rtc::Thread::Current());
+      controller_->CreateDataChannel("test1", init);
 
   EXPECT_EQ_WAIT(DataChannelInterface::kOpen, dc->state(), 1000);
 
@@ -449,8 +428,7 @@
 
   SetChannelReady();
   rtc::scoped_refptr<SctpDataChannel> dc =
-      SctpDataChannel::Create(controller_->weak_ptr(), "test1", config,
-                              rtc::Thread::Current(), rtc::Thread::Current());
+      controller_->CreateDataChannel("test1", config);
 
   EXPECT_EQ_WAIT(DataChannelInterface::kOpen, dc->state(), 1000);
   EXPECT_EQ(0, controller_->last_sid());
@@ -511,8 +489,7 @@
 
   SetChannelReady();
   rtc::scoped_refptr<SctpDataChannel> dc =
-      SctpDataChannel::Create(controller_->weak_ptr(), "test1", config,
-                              rtc::Thread::Current(), rtc::Thread::Current());
+      controller_->CreateDataChannel("test1", config);
 
   EXPECT_EQ_WAIT(DataChannelInterface::kOpen, dc->state(), 1000);
 
diff --git a/pc/rtc_stats_collector_unittest.cc b/pc/rtc_stats_collector_unittest.cc
index 423b9c7..3b63f2f 100644
--- a/pc/rtc_stats_collector_unittest.cc
+++ b/pc/rtc_stats_collector_unittest.cc
@@ -2125,10 +2125,10 @@
   // TODO(bugs.webrtc.org/11547): Supply a separate network thread.
   FakeDataChannelController controller;
   rtc::scoped_refptr<SctpDataChannel> dummy_channel_a = SctpDataChannel::Create(
-      controller.weak_ptr(), "DummyChannelA", InternalDataChannelInit(),
+      controller.weak_ptr(), "DummyChannelA", false, InternalDataChannelInit(),
       rtc::Thread::Current(), rtc::Thread::Current());
   rtc::scoped_refptr<SctpDataChannel> dummy_channel_b = SctpDataChannel::Create(
-      controller.weak_ptr(), "DummyChannelB", InternalDataChannelInit(),
+      controller.weak_ptr(), "DummyChannelB", false, InternalDataChannelInit(),
       rtc::Thread::Current(), rtc::Thread::Current());
 
   stats_->stats_collector()->OnSctpDataChannelStateChanged(
diff --git a/pc/sctp_data_channel.cc b/pc/sctp_data_channel.cc
index 4f600ad..34bc909 100644
--- a/pc/sctp_data_channel.cc
+++ b/pc/sctp_data_channel.cc
@@ -143,6 +143,7 @@
 rtc::scoped_refptr<SctpDataChannel> SctpDataChannel::Create(
     rtc::WeakPtr<SctpDataChannelControllerInterface> controller,
     const std::string& label,
+    bool connected_to_transport,
     const InternalDataChannelInit& config,
     rtc::Thread* signaling_thread,
     rtc::Thread* network_thread) {
@@ -155,7 +156,8 @@
   }
 
   auto channel = rtc::make_ref_counted<SctpDataChannel>(
-      config, std::move(controller), label, signaling_thread, network_thread);
+      config, std::move(controller), label, connected_to_transport,
+      signaling_thread, network_thread);
   channel->Init();
   return channel;
 }
@@ -172,6 +174,7 @@
     const InternalDataChannelInit& config,
     rtc::WeakPtr<SctpDataChannelControllerInterface> controller,
     const std::string& label,
+    bool connected_to_transport,
     rtc::Thread* signaling_thread,
     rtc::Thread* network_thread)
     : signaling_thread_(signaling_thread),
@@ -186,7 +189,8 @@
       negotiated_(config.negotiated),
       ordered_(config.ordered),
       observer_(nullptr),
-      controller_(std::move(controller)) {
+      controller_(std::move(controller)),
+      connected_to_transport_(connected_to_transport) {
   RTC_DCHECK_RUN_ON(signaling_thread_);
   RTC_UNUSED(network_thread_);
   RTC_DCHECK(config.IsValid());
@@ -203,27 +207,30 @@
       handshake_state_ = kHandshakeShouldSendAck;
       break;
   }
+
+  // Try to connect to the transport in case the transport channel already
+  // exists.
+  if (id_.HasValue()) {
+    controller_->AddSctpDataStream(id_.stream_id_int());
+  }
 }
 
 void SctpDataChannel::Init() {
   RTC_DCHECK_RUN_ON(signaling_thread_);
 
-  // Try to connect to the transport in case the transport channel already
-  // exists.
-  OnTransportChannelCreated();
-
   // Checks if the transport is ready to send because the initial channel
   // ready signal may have been sent before the DataChannel creation.
   // This has to be done async because the upper layer objects (e.g.
   // Chrome glue and WebKit) are not wired up properly until after this
   // function returns.
   if (controller_->ReadyToSendData()) {
+    RTC_DCHECK(connected_to_transport_);
     AddRef();
     absl::Cleanup release = [this] { Release(); };
     rtc::Thread::Current()->PostTask([this, release = std::move(release)] {
       RTC_DCHECK_RUN_ON(signaling_thread_);
       if (state_ != kClosed)
-        OnTransportReady(true);
+        OnTransportReady();
     });
   }
 }
@@ -362,10 +369,6 @@
   RTC_DCHECK_NE(handshake_state_, kHandshakeWaitingForAck);
   RTC_DCHECK_EQ(state_, kConnecting);
 
-  if (id_ == sid) {
-    return;
-  }
-
   id_ = sid;
   controller_->AddSctpDataStream(sid.stream_id_int());
 }
@@ -397,12 +400,10 @@
 
 void SctpDataChannel::OnTransportChannelCreated() {
   RTC_DCHECK_RUN_ON(signaling_thread_);
-  if (!controller_) {
-    return;
-  }
-  if (!connected_to_transport_) {
-    connected_to_transport_ = controller_->ConnectDataChannel(this);
-  }
+  RTC_DCHECK(controller_);
+
+  connected_to_transport_ = true;
+
   // The sid may have been unassigned when controller_->ConnectDataChannel was
   // done. So always add the streams even if connected_to_transport_ is true.
   if (id_.HasValue()) {
@@ -485,13 +486,23 @@
   }
 }
 
-void SctpDataChannel::OnTransportReady(bool writable) {
+void SctpDataChannel::OnTransportReady() {
   RTC_DCHECK_RUN_ON(signaling_thread_);
 
-  writable_ = writable;
-  if (!writable) {
-    return;
-  }
+  // TODO(tommi, hta): We don't need the `writable_` flag for SCTP datachannels.
+  // Remove it and just rely on `connected_to_transport_` instead.
+  // In practice the transport is configured inside
+  // `PeerConnection::SetupDataChannelTransport_n`, which results in
+  // `SctpDataChannel` getting the OnTransportChannelCreated callback, and then
+  // that's immediately followed by calling `transport->SetDataSink` which is
+  // what triggers the callback to `OnTransportReady()`.
+  // These steps are currently accomplished via two separate PostTask calls to
+  // the signaling thread, but could simply be done in single method call on
+  // the network thread (which incidentally is the thread that we'll need to
+  // be on for the below `Send*` calls, which currently do a BlockingCall
+  // from the signaling thread to the network thread.
+  RTC_DCHECK(connected_to_transport_);
+  writable_ = true;
 
   SendQueuedControlMessages();
   SendQueuedDataMessages();
@@ -506,7 +517,7 @@
     return;
   }
 
-  DisconnectFromTransport();
+  connected_to_transport_ = false;
 
   // Closing abruptly means any queued data gets thrown away.
   queued_send_data_.Clear();
@@ -554,6 +565,8 @@
           // Deliver them now.
           DeliverQueuedReceivedData();
         }
+      } else {
+        RTC_DCHECK(!id_.HasValue());
       }
       break;
     }
@@ -603,14 +616,6 @@
     controller_->OnChannelStateChanged(this, state_);
 }
 
-void SctpDataChannel::DisconnectFromTransport() {
-  RTC_DCHECK_RUN_ON(signaling_thread_);
-  if (!connected_to_transport_ || !controller_)
-    return;
-
-  connected_to_transport_ = false;
-}
-
 void SctpDataChannel::DeliverQueuedReceivedData() {
   RTC_DCHECK_RUN_ON(signaling_thread_);
   if (!observer_) {
@@ -727,6 +732,7 @@
 bool SctpDataChannel::SendControlMessage(const rtc::CopyOnWriteBuffer& buffer) {
   RTC_DCHECK_RUN_ON(signaling_thread_);
   RTC_DCHECK(writable_);
+  RTC_DCHECK(connected_to_transport_);
   RTC_DCHECK(id_.HasValue());
 
   if (!controller_) {
diff --git a/pc/sctp_data_channel.h b/pc/sctp_data_channel.h
index cdd7ca6..628a905 100644
--- a/pc/sctp_data_channel.h
+++ b/pc/sctp_data_channel.h
@@ -36,8 +36,6 @@
 
 class SctpDataChannel;
 
-// TODO(deadbeef): Get rid of this and have SctpDataChannel depend on
-// SctpTransportInternal (pure virtual SctpTransport interface) instead.
 class SctpDataChannelControllerInterface {
  public:
   // Sends the data to the transport.
@@ -45,8 +43,6 @@
                         const SendDataParams& params,
                         const rtc::CopyOnWriteBuffer& payload,
                         cricket::SendDataResult* result) = 0;
-  // Connects to the transport signals.
-  virtual bool ConnectDataChannel(SctpDataChannel* data_channel) = 0;
   // Adds the data channel SID to the transport for SCTP.
   virtual void AddSctpDataStream(int sid) = 0;
   // Begins the closing procedure by sending an outgoing stream reset. Still
@@ -123,6 +119,7 @@
   static rtc::scoped_refptr<SctpDataChannel> Create(
       rtc::WeakPtr<SctpDataChannelControllerInterface> controller,
       const std::string& label,
+      bool connected_to_transport,
       const InternalDataChannelInit& config,
       rtc::Thread* signaling_thread,
       rtc::Thread* network_thread);
@@ -175,7 +172,7 @@
   // Called when the SctpTransport's ready to use. That can happen when we've
   // finished negotiation, or if the channel was created after negotiation has
   // already finished.
-  void OnTransportReady(bool writable);
+  void OnTransportReady();
 
   void OnDataReceived(DataMessageType type,
                       const rtc::CopyOnWriteBuffer& payload);
@@ -192,7 +189,6 @@
   // asynchronously after RemoveSctpDataStream.
   void OnClosingProcedureComplete();
   // Called when the transport channel is created.
-  // Only needs to be called for SCTP data channels.
   void OnTransportChannelCreated();
   // Called when the transport channel is unusable.
   // This method makes sure the DataChannel is disconnected and changes state
@@ -211,6 +207,7 @@
   SctpDataChannel(const InternalDataChannelInit& config,
                   rtc::WeakPtr<SctpDataChannelControllerInterface> controller,
                   const std::string& label,
+                  bool connected_to_transport,
                   rtc::Thread* signaling_thread,
                   rtc::Thread* network_thread);
   ~SctpDataChannel() override;
@@ -228,7 +225,6 @@
   void Init();
   void UpdateState();
   void SetState(DataState state);
-  void DisconnectFromTransport();
 
   void DeliverQueuedReceivedData();
 
diff --git a/pc/test/fake_data_channel_controller.h b/pc/test/fake_data_channel_controller.h
index d4acf92..8cb8098 100644
--- a/pc/test/fake_data_channel_controller.h
+++ b/pc/test/fake_data_channel_controller.h
@@ -12,6 +12,7 @@
 #define PC_TEST_FAKE_DATA_CHANNEL_CONTROLLER_H_
 
 #include <set>
+#include <string>
 
 #include "pc/sctp_data_channel.h"
 #include "rtc_base/checks.h"
@@ -31,6 +32,18 @@
     return weak_factory_.GetWeakPtr();
   }
 
+  rtc::scoped_refptr<webrtc::SctpDataChannel> CreateDataChannel(
+      absl::string_view label,
+      webrtc::InternalDataChannelInit init,
+      rtc::Thread* network_thread = rtc::Thread::Current()) {
+    rtc::scoped_refptr<webrtc::SctpDataChannel> channel =
+        webrtc::SctpDataChannel::Create(weak_ptr(), std::string(label),
+                                        transport_available_, init,
+                                        rtc::Thread::Current(), network_thread);
+    connected_channels_.insert(channel.get());
+    return channel;
+  }
+
   bool SendData(int sid,
                 const webrtc::SendDataParams& params,
                 const rtc::CopyOnWriteBuffer& payload,
@@ -52,17 +65,6 @@
     return true;
   }
 
-  bool ConnectDataChannel(webrtc::SctpDataChannel* data_channel) override {
-    RTC_CHECK(connected_channels_.find(data_channel) ==
-              connected_channels_.end());
-    if (!transport_available_) {
-      return false;
-    }
-    RTC_LOG(LS_VERBOSE) << "DataChannel connected " << data_channel;
-    connected_channels_.insert(data_channel);
-    return true;
-  }
-
   void AddSctpDataStream(int sid) override {
     RTC_CHECK(sid >= 0);
     if (!transport_available_) {
@@ -78,15 +80,12 @@
     recv_ssrcs_.erase(sid);
     // Unlike the real SCTP transport, act like the closing procedure finished
     // instantly, doing the same snapshot thing as below.
-    for (webrtc::SctpDataChannel* ch : std::set<webrtc::SctpDataChannel*>(
-             connected_channels_.begin(), connected_channels_.end())) {
-      if (connected_channels_.count(ch) && ch->id() == sid) {
-        // This path mimics the DCC's OnChannelClosed handler since the FDCC
-        // (this class) doesn't have a transport that would do that.
-        ch->OnClosingProcedureComplete();
-        return;
-      }
-    }
+    auto it = absl::c_find_if(connected_channels_,
+                              [&](const auto* c) { return c->id() == sid; });
+    // This path mimics the DCC's OnChannelClosed handler since the FDCC
+    // (this class) doesn't have a transport that would do that.
+    if (it != connected_channels_.end())
+      (*it)->OnClosingProcedureComplete();
   }
 
   bool ReadyToSendData() const override { return ready_to_send_; }
@@ -106,15 +105,12 @@
   void set_send_blocked(bool blocked) {
     send_blocked_ = blocked;
     if (!blocked) {
-      // Take a snapshot of the connected channels and check to see whether
-      // each value is still in connected_channels_ before calling
-      // OnTransportReady().  This avoids problems where the set gets modified
-      // in response to OnTransportReady().
-      for (webrtc::SctpDataChannel* ch : std::set<webrtc::SctpDataChannel*>(
-               connected_channels_.begin(), connected_channels_.end())) {
-        if (connected_channels_.count(ch)) {
-          ch->OnTransportReady(true);
-        }
+      RTC_CHECK(transport_available_);
+      // Make a copy since `connected_channels_` may change while
+      // OnTransportReady is called.
+      auto copy = connected_channels_;
+      for (webrtc::SctpDataChannel* ch : copy) {
+        ch->OnTransportReady();
       }
     }
   }
@@ -134,7 +130,7 @@
       std::set<webrtc::SctpDataChannel*>::iterator it;
       for (it = connected_channels_.begin(); it != connected_channels_.end();
            ++it) {
-        (*it)->OnTransportReady(true);
+        (*it)->OnTransportReady();
       }
     }
   }
diff --git a/pc/test/fake_peer_connection_for_stats.h b/pc/test/fake_peer_connection_for_stats.h
index 8d70308..ca3aa5c 100644
--- a/pc/test/fake_peer_connection_for_stats.h
+++ b/pc/test/fake_peer_connection_for_stats.h
@@ -343,7 +343,7 @@
                           const InternalDataChannelInit& init) {
     // TODO(bugs.webrtc.org/11547): Supply a separate network thread.
     AddSctpDataChannel(SctpDataChannel::Create(
-        data_channel_controller_.weak_ptr(), label, init,
+        data_channel_controller_.weak_ptr(), label, false, init,
         rtc::Thread::Current(), rtc::Thread::Current()));
   }
 
diff --git a/pc/test/mock_data_channel.h b/pc/test/mock_data_channel.h
index 659988d..a9d08d2 100644
--- a/pc/test/mock_data_channel.h
+++ b/pc/test/mock_data_channel.h
@@ -50,6 +50,7 @@
       : SctpDataChannel(config,
                         std::move(controller),
                         label,
+                        false,
                         signaling_thread,
                         network_thread) {
     EXPECT_CALL(*this, id()).WillRepeatedly(::testing::Return(id));