Create no-op DTLS if media transport is used.

We'd like to disable RTP code path when media transport is used. In particular, we don't want occasional RTP/RTCP packets sent from the RTP code path when media transport is used.

Long term we will remove this new NoOp DTLS transport, when we stop creating rtp transport.

Bug: webrtc:9719
Change-Id: I27f121edef394465ddc8fe8003e6f4428b10c022
Reviewed-on: https://webrtc-review.googlesource.com/c/117700
Reviewed-by: Anton Sukhanov <sukhanov@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Commit-Queue: Peter Slatala <psla@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26286}
diff --git a/p2p/BUILD.gn b/p2p/BUILD.gn
index f5c00cc..dcc7caf 100644
--- a/p2p/BUILD.gn
+++ b/p2p/BUILD.gn
@@ -43,6 +43,8 @@
     "base/icetransportinternal.h",
     "base/mdns_message.cc",
     "base/mdns_message.h",
+    "base/no_op_dtls_transport.cc",
+    "base/no_op_dtls_transport.h",
     "base/p2p_constants.cc",
     "base/p2p_constants.h",
     "base/p2p_transport_channel.cc",
diff --git a/p2p/base/no_op_dtls_transport.cc b/p2p/base/no_op_dtls_transport.cc
new file mode 100644
index 0000000..3662d88
--- /dev/null
+++ b/p2p/base/no_op_dtls_transport.cc
@@ -0,0 +1,143 @@
+/*
+ *  Copyright 2018 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 <algorithm>
+#include <memory>
+#include <utility>
+
+#include "p2p/base/no_op_dtls_transport.h"
+
+#include "absl/memory/memory.h"
+#include "logging/rtc_event_log/events/rtc_event_dtls_transport_state.h"
+#include "logging/rtc_event_log/events/rtc_event_dtls_writable_state.h"
+#include "logging/rtc_event_log/rtc_event_log.h"
+#include "p2p/base/packet_transport_internal.h"
+#include "rtc_base/buffer.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/dscp.h"
+#include "rtc_base/logging.h"
+#include "rtc_base/message_queue.h"
+#include "rtc_base/rtc_certificate.h"
+#include "rtc_base/ssl_stream_adapter.h"
+#include "rtc_base/stream.h"
+#include "rtc_base/thread.h"
+
+namespace cricket {
+
+NoOpDtlsTransport::NoOpDtlsTransport(
+    std::unique_ptr<IceTransportInternal> ice_transport,
+    const webrtc::CryptoOptions& crypto_options)
+    : crypto_options_(webrtc::CryptoOptions::NoGcm()),
+      ice_transport_(std::move(ice_transport)) {
+  RTC_DCHECK(ice_transport_);
+  ice_transport_->SignalWritableState.connect(
+      this, &NoOpDtlsTransport::OnWritableState);
+  ice_transport_->SignalReadyToSend.connect(this,
+                                            &NoOpDtlsTransport::OnReadyToSend);
+}
+
+NoOpDtlsTransport::~NoOpDtlsTransport() {}
+const webrtc::CryptoOptions& NoOpDtlsTransport::crypto_options() const {
+  return crypto_options_;
+}
+DtlsTransportState NoOpDtlsTransport::dtls_state() const {
+  return DTLS_TRANSPORT_CONNECTED;
+}
+int NoOpDtlsTransport::component() const {
+  return kNoOpDtlsTransportComponent;
+}
+bool NoOpDtlsTransport::IsDtlsActive() const {
+  return true;
+}
+bool NoOpDtlsTransport::GetDtlsRole(rtc::SSLRole* role) const {
+  return false;
+}
+bool NoOpDtlsTransport::SetDtlsRole(rtc::SSLRole role) {
+  return false;
+}
+bool NoOpDtlsTransport::GetSrtpCryptoSuite(int* cipher) {
+  return false;
+}
+bool NoOpDtlsTransport::GetSslCipherSuite(int* cipher) {
+  return false;
+}
+rtc::scoped_refptr<rtc::RTCCertificate> NoOpDtlsTransport::GetLocalCertificate()
+    const {
+  return rtc::scoped_refptr<rtc::RTCCertificate>();
+}
+bool NoOpDtlsTransport::SetLocalCertificate(
+    const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) {
+  return false;
+}
+std::unique_ptr<rtc::SSLCertChain> NoOpDtlsTransport::GetRemoteSSLCertChain()
+    const {
+  return std::unique_ptr<rtc::SSLCertChain>();
+}
+bool NoOpDtlsTransport::ExportKeyingMaterial(const std::string& label,
+                                             const uint8_t* context,
+                                             size_t context_len,
+                                             bool use_context,
+                                             uint8_t* result,
+                                             size_t result_len) {
+  return false;
+}
+bool NoOpDtlsTransport::SetRemoteFingerprint(const std::string& digest_alg,
+                                             const uint8_t* digest,
+                                             size_t digest_len) {
+  return true;
+}
+bool NoOpDtlsTransport::SetSslMaxProtocolVersion(
+    rtc::SSLProtocolVersion version) {
+  return true;
+}
+IceTransportInternal* NoOpDtlsTransport::ice_transport() {
+  return ice_transport_.get();
+}
+
+void NoOpDtlsTransport::OnReadyToSend(rtc::PacketTransportInternal* transport) {
+  RTC_DCHECK_RUN_ON(&thread_checker_);
+  if (is_writable_) {
+    SignalReadyToSend(this);
+  }
+}
+
+void NoOpDtlsTransport::OnWritableState(
+    rtc::PacketTransportInternal* transport) {
+  RTC_DCHECK_RUN_ON(&thread_checker_);
+  is_writable_ = ice_transport_->writable();
+  if (is_writable_) {
+    SignalWritableState(this);
+  }
+}
+const std::string& NoOpDtlsTransport::transport_name() const {
+  return ice_transport_->transport_name();
+}
+bool NoOpDtlsTransport::writable() const {
+  return ice_transport_->writable();
+}
+bool NoOpDtlsTransport::receiving() const {
+  return ice_transport_->receiving();
+}
+int NoOpDtlsTransport::SendPacket(const char* data,
+                                  size_t len,
+                                  const rtc::PacketOptions& options,
+                                  int flags) {
+  return 0;
+}
+
+int NoOpDtlsTransport::SetOption(rtc::Socket::Option opt, int value) {
+  return ice_transport_->SetOption(opt, value);
+}
+
+int NoOpDtlsTransport::GetError() {
+  return ice_transport_->GetError();
+}
+
+}  // namespace cricket
diff --git a/p2p/base/no_op_dtls_transport.h b/p2p/base/no_op_dtls_transport.h
new file mode 100644
index 0000000..4211160
--- /dev/null
+++ b/p2p/base/no_op_dtls_transport.h
@@ -0,0 +1,109 @@
+/*
+ *  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 P2P_BASE_NO_OP_DTLS_TRANSPORT_H_
+#define P2P_BASE_NO_OP_DTLS_TRANSPORT_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "api/crypto/crypto_options.h"
+#include "p2p/base/dtls_transport_internal.h"
+#include "p2p/base/ice_transport_internal.h"
+#include "p2p/base/packet_transport_internal.h"
+#include "rtc_base/buffer.h"
+#include "rtc_base/buffer_queue.h"
+#include "rtc_base/constructor_magic.h"
+#include "rtc_base/ssl_stream_adapter.h"
+#include "rtc_base/stream.h"
+#include "rtc_base/strings/string_builder.h"
+#include "rtc_base/thread_checker.h"
+
+namespace cricket {
+
+constexpr int kNoOpDtlsTransportComponent = -1;
+
+// This implementation wraps a cricket::DtlsTransport, and takes
+// ownership of it.
+// The implementation does not perform any operations, except of being
+// "connected". The purpose of this implementation is to disable RTP transport
+// while MediaTransport is used.
+//
+// This implementation is only temporary. Long-term we will refactor and disable
+// RTP transport entirely when MediaTransport is used. Always connected (after
+// ICE), no-op, dtls transport. This is used when DTLS is disabled.
+//
+// MaybeCreateJsepTransport controller expects DTLS connection to send a
+// 'connected' signal _after_ it is created (if it is created in a connected
+// state, that would not be noticed by jsep transport controller). Therefore,
+// the no-op dtls transport will wait for ICE event "writable", and then
+// immediately report that it's connected (emulating 0-rtt connection).
+//
+// We could simply not set a dtls to active (not set a certificate on the DTLS),
+// and it would use an underyling connection instead.
+// However, when MediaTransport is used, we want to entirely disable
+// dtls/srtp/rtp, in order to avoid multiplexing issues, such as "Failed to
+// unprotect RTCP packet".
+class NoOpDtlsTransport : public DtlsTransportInternal {
+ public:
+  NoOpDtlsTransport(std::unique_ptr<IceTransportInternal> ice_transport,
+                    const webrtc::CryptoOptions& crypto_options);
+
+  ~NoOpDtlsTransport() override;
+  const webrtc::CryptoOptions& crypto_options() const override;
+  DtlsTransportState dtls_state() const override;
+  int component() const override;
+  bool IsDtlsActive() const override;
+  bool GetDtlsRole(rtc::SSLRole* role) const override;
+  bool SetDtlsRole(rtc::SSLRole role) override;
+  bool GetSrtpCryptoSuite(int* cipher) override;
+  bool GetSslCipherSuite(int* cipher) override;
+  rtc::scoped_refptr<rtc::RTCCertificate> GetLocalCertificate() const override;
+  bool SetLocalCertificate(
+      const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) override;
+  std::unique_ptr<rtc::SSLCertChain> GetRemoteSSLCertChain() const override;
+  bool ExportKeyingMaterial(const std::string& label,
+                            const uint8_t* context,
+                            size_t context_len,
+                            bool use_context,
+                            uint8_t* result,
+                            size_t result_len) override;
+  bool SetRemoteFingerprint(const std::string& digest_alg,
+                            const uint8_t* digest,
+                            size_t digest_len) override;
+  bool SetSslMaxProtocolVersion(rtc::SSLProtocolVersion version) override;
+  IceTransportInternal* ice_transport() override;
+
+  const std::string& transport_name() const override;
+  bool writable() const override;
+  bool receiving() const override;
+
+ private:
+  void OnReadyToSend(rtc::PacketTransportInternal* transport);
+  void OnWritableState(rtc::PacketTransportInternal* transport);
+
+  int SendPacket(const char* data,
+                 size_t len,
+                 const rtc::PacketOptions& options,
+                 int flags) override;
+  int SetOption(rtc::Socket::Option opt, int value) override;
+  int GetError() override;
+
+  rtc::ThreadChecker thread_checker_;
+
+  webrtc::CryptoOptions crypto_options_;
+  std::unique_ptr<IceTransportInternal> ice_transport_;
+  bool is_writable_ = false;
+};
+
+}  // namespace cricket
+
+#endif  // P2P_BASE_NO_OP_DTLS_TRANSPORT_H_
diff --git a/pc/jsep_transport_controller.cc b/pc/jsep_transport_controller.cc
index dc05073..926d71d 100644
--- a/pc/jsep_transport_controller.cc
+++ b/pc/jsep_transport_controller.cc
@@ -15,6 +15,8 @@
 #include <utility>
 
 #include "absl/memory/memory.h"
+#include "p2p/base/ice_transport_internal.h"
+#include "p2p/base/no_op_dtls_transport.h"
 #include "p2p/base/port.h"
 #include "pc/srtp_filter.h"
 #include "rtc_base/bind.h"
@@ -409,23 +411,35 @@
   config_.media_transport_factory = media_transport_factory;
 }
 
-std::unique_ptr<cricket::DtlsTransportInternal>
-JsepTransportController::CreateDtlsTransport(const std::string& transport_name,
-                                             bool rtcp) {
-  RTC_DCHECK(network_thread_->IsCurrent());
+std::unique_ptr<cricket::IceTransportInternal>
+JsepTransportController::CreateIceTransport(const std::string transport_name,
+                                            bool rtcp) {
   int component = rtcp ? cricket::ICE_CANDIDATE_COMPONENT_RTCP
                        : cricket::ICE_CANDIDATE_COMPONENT_RTP;
 
-  std::unique_ptr<cricket::DtlsTransportInternal> dtls;
   if (config_.external_transport_factory) {
-    auto ice = config_.external_transport_factory->CreateIceTransport(
+    return config_.external_transport_factory->CreateIceTransport(
         transport_name, component);
+  } else {
+    return absl::make_unique<cricket::P2PTransportChannel>(
+        transport_name, component, port_allocator_, async_resolver_factory_,
+        config_.event_log);
+  }
+}
+
+std::unique_ptr<cricket::DtlsTransportInternal>
+JsepTransportController::CreateDtlsTransport(
+    std::unique_ptr<cricket::IceTransportInternal> ice) {
+  RTC_DCHECK(network_thread_->IsCurrent());
+
+  std::unique_ptr<cricket::DtlsTransportInternal> dtls;
+  if (config_.media_transport_factory) {
+    dtls = absl::make_unique<cricket::NoOpDtlsTransport>(
+        std::move(ice), config_.crypto_options);
+  } else if (config_.external_transport_factory) {
     dtls = config_.external_transport_factory->CreateDtlsTransport(
         std::move(ice), config_.crypto_options);
   } else {
-    auto ice = absl::make_unique<cricket::P2PTransportChannel>(
-        transport_name, component, port_allocator_, async_resolver_factory_,
-        config_.event_log);
     dtls = absl::make_unique<cricket::DtlsTransport>(
         std::move(ice), config_.crypto_options, config_.event_log);
   }
@@ -1032,26 +1046,30 @@
                     "SDES and DTLS-SRTP cannot be enabled at the same time.");
   }
 
+  std::unique_ptr<cricket::IceTransportInternal> ice =
+      CreateIceTransport(content_info.name, /*rtcp=*/false);
+
+  std::unique_ptr<MediaTransportInterface> media_transport =
+      MaybeCreateMediaTransport(content_info, local, ice.get());
+
   std::unique_ptr<cricket::DtlsTransportInternal> rtp_dtls_transport =
-      CreateDtlsTransport(content_info.name, /*rtcp =*/false);
+      CreateDtlsTransport(std::move(ice));
 
   std::unique_ptr<cricket::DtlsTransportInternal> rtcp_dtls_transport;
   std::unique_ptr<RtpTransport> unencrypted_rtp_transport;
   std::unique_ptr<SrtpTransport> sdes_transport;
   std::unique_ptr<DtlsSrtpTransport> dtls_srtp_transport;
-  std::unique_ptr<MediaTransportInterface> media_transport;
 
   if (config_.rtcp_mux_policy !=
           PeerConnectionInterface::kRtcpMuxPolicyRequire &&
       content_info.type == cricket::MediaProtocolType::kRtp) {
-    rtcp_dtls_transport =
-        CreateDtlsTransport(content_info.name, /*rtcp =*/true);
+    RTC_DCHECK(media_transport == nullptr);
+    rtcp_dtls_transport = CreateDtlsTransport(
+        CreateIceTransport(content_info.name, /*rtcp=*/true));
   }
-  media_transport = MaybeCreateMediaTransport(
-      content_info, local, rtp_dtls_transport->ice_transport());
 
   // TODO(sukhanov): Do not create RTP/RTCP transports if media transport is
-  // used.
+  // used, and remove the no-op dtls transport when that's done.
   if (config_.disable_encryption) {
     unencrypted_rtp_transport = CreateUnencryptedRtpTransport(
         content_info.name, rtp_dtls_transport.get(), rtcp_dtls_transport.get());
diff --git a/pc/jsep_transport_controller.h b/pc/jsep_transport_controller.h
index 1f4a632..e57b7d8 100644
--- a/pc/jsep_transport_controller.h
+++ b/pc/jsep_transport_controller.h
@@ -295,7 +295,9 @@
       bool local);
 
   std::unique_ptr<cricket::DtlsTransportInternal> CreateDtlsTransport(
-      const std::string& transport_name,
+      std::unique_ptr<cricket::IceTransportInternal> ice);
+  std::unique_ptr<cricket::IceTransportInternal> CreateIceTransport(
+      const std::string transport_name,
       bool rtcp);
 
   std::unique_ptr<webrtc::RtpTransport> CreateUnencryptedRtpTransport(
diff --git a/pc/jsep_transport_controller_unittest.cc b/pc/jsep_transport_controller_unittest.cc
index 018140d..d6a31c8 100644
--- a/pc/jsep_transport_controller_unittest.cc
+++ b/pc/jsep_transport_controller_unittest.cc
@@ -16,6 +16,7 @@
 #include "api/test/fake_media_transport.h"
 #include "p2p/base/fake_dtls_transport.h"
 #include "p2p/base/fake_ice_transport.h"
+#include "p2p/base/no_op_dtls_transport.h"
 #include "p2p/base/transport_factory_interface.h"
 #include "p2p/base/transport_info.h"
 #include "pc/jsep_transport_controller.h"
@@ -418,10 +419,10 @@
   FakeMediaTransportFactory fake_media_transport_factory;
   JsepTransportController::Config config;
 
-  config.rtcp_mux_policy = PeerConnectionInterface::kRtcpMuxPolicyNegotiate;
+  config.rtcp_mux_policy = PeerConnectionInterface::kRtcpMuxPolicyRequire;
   config.media_transport_factory = &fake_media_transport_factory;
   CreateJsepTransportController(config);
-  auto description = CreateSessionDescriptionWithoutBundle();
+  auto description = CreateSessionDescriptionWithBundleGroup();
   AddCryptoSettings(description.get());
 
   EXPECT_TRUE(transport_controller_
@@ -439,16 +440,20 @@
 
   // Return nullptr for non-existing mids.
   EXPECT_EQ(nullptr, transport_controller_->GetMediaTransport(kVideoMid2));
+
+  EXPECT_EQ(cricket::kNoOpDtlsTransportComponent,
+            transport_controller_->GetDtlsTransport(kAudioMid1)->component())
+      << "Because media transport is used, expected no-op DTLS transport.";
 }
 
 TEST_F(JsepTransportControllerTest, GetMediaTransportInCallee) {
   FakeMediaTransportFactory fake_media_transport_factory;
   JsepTransportController::Config config;
 
-  config.rtcp_mux_policy = PeerConnectionInterface::kRtcpMuxPolicyNegotiate;
+  config.rtcp_mux_policy = PeerConnectionInterface::kRtcpMuxPolicyRequire;
   config.media_transport_factory = &fake_media_transport_factory;
   CreateJsepTransportController(config);
-  auto description = CreateSessionDescriptionWithoutBundle();
+  auto description = CreateSessionDescriptionWithBundleGroup();
   AddCryptoSettings(description.get());
   EXPECT_TRUE(transport_controller_
                   ->SetRemoteDescription(SdpType::kOffer, description.get())
@@ -465,6 +470,10 @@
 
   // Return nullptr for non-existing mids.
   EXPECT_EQ(nullptr, transport_controller_->GetMediaTransport(kVideoMid2));
+
+  EXPECT_EQ(cricket::kNoOpDtlsTransportComponent,
+            transport_controller_->GetDtlsTransport(kAudioMid1)->component())
+      << "Because media transport is used, expected no-op DTLS transport.";
 }
 
 TEST_F(JsepTransportControllerTest, GetMediaTransportIsNotSetIfNoSdes) {
@@ -490,6 +499,10 @@
                   .ok());
 
   EXPECT_EQ(nullptr, transport_controller_->GetMediaTransport(kAudioMid1));
+  EXPECT_EQ(cricket::ICE_CANDIDATE_COMPONENT_RTP,
+            transport_controller_->GetDtlsTransport(kAudioMid1)->component())
+      << "Because media transport is NOT used (fallback to RTP), expected "
+         "actual DTLS transport for RTP";
 }
 
 TEST_F(JsepTransportControllerTest,
@@ -497,7 +510,7 @@
   FakeMediaTransportFactory fake_media_transport_factory;
   JsepTransportController::Config config;
 
-  config.rtcp_mux_policy = PeerConnectionInterface::kRtcpMuxPolicyNegotiate;
+  config.rtcp_mux_policy = PeerConnectionInterface::kRtcpMuxPolicyRequire;
   config.media_transport_factory = &fake_media_transport_factory;
   CreateJsepTransportController(config);
   auto description = CreateSessionDescriptionWithoutBundle();
@@ -813,25 +826,24 @@
   JsepTransportController::Config config;
   config.media_transport_factory = &fake_media_transport_factory;
   CreateJsepTransportController(config);
-  auto description = CreateSessionDescriptionWithoutBundle();
+
+  // Media Transport is only used with bundle.
+  auto description = CreateSessionDescriptionWithBundleGroup();
   AddCryptoSettings(description.get());
   EXPECT_TRUE(transport_controller_
                   ->SetLocalDescription(SdpType::kOffer, description.get())
                   .ok());
 
-  auto fake_audio_dtls = static_cast<FakeDtlsTransport*>(
-      transport_controller_->GetDtlsTransport(kAudioMid1));
-  auto fake_video_dtls = static_cast<FakeDtlsTransport*>(
-      transport_controller_->GetDtlsTransport(kVideoMid1));
-  fake_audio_dtls->SetWritable(true);
-  fake_video_dtls->SetWritable(true);
-  // Decreasing connection count from 2 to 1 triggers connection state event.
-  fake_audio_dtls->fake_ice_transport()->SetConnectionCount(2);
-  fake_audio_dtls->fake_ice_transport()->SetConnectionCount(1);
-  fake_video_dtls->fake_ice_transport()->SetConnectionCount(2);
-  fake_video_dtls->fake_ice_transport()->SetConnectionCount(1);
-  fake_audio_dtls->SetDtlsState(cricket::DTLS_TRANSPORT_CONNECTED);
-  fake_video_dtls->SetDtlsState(cricket::DTLS_TRANSPORT_CONNECTED);
+  auto fake_audio_ice = static_cast<cricket::FakeIceTransport*>(
+      transport_controller_->GetDtlsTransport(kAudioMid1)->ice_transport());
+  auto fake_video_ice = static_cast<cricket::FakeIceTransport*>(
+      transport_controller_->GetDtlsTransport(kVideoMid1)->ice_transport());
+  fake_audio_ice->SetConnectionCount(2);
+  fake_audio_ice->SetConnectionCount(1);
+  fake_video_ice->SetConnectionCount(2);
+  fake_video_ice->SetConnectionCount(1);
+  fake_audio_ice->SetWritable(true);
+  fake_video_ice->SetWritable(true);
 
   // Still not connected, because we are waiting for media transport.
   EXPECT_EQ_WAIT(cricket::kIceConnectionConnecting, connection_state_,
@@ -864,19 +876,17 @@
                   ->SetLocalDescription(SdpType::kOffer, description.get())
                   .ok());
 
-  auto fake_audio_dtls = static_cast<FakeDtlsTransport*>(
-      transport_controller_->GetDtlsTransport(kAudioMid1));
-  auto fake_video_dtls = static_cast<FakeDtlsTransport*>(
-      transport_controller_->GetDtlsTransport(kVideoMid1));
-  fake_audio_dtls->SetWritable(true);
-  fake_video_dtls->SetWritable(true);
+  auto fake_audio_ice = static_cast<cricket::FakeIceTransport*>(
+      transport_controller_->GetDtlsTransport(kAudioMid1)->ice_transport());
+  auto fake_video_ice = static_cast<cricket::FakeIceTransport*>(
+      transport_controller_->GetDtlsTransport(kVideoMid1)->ice_transport());
+  fake_audio_ice->SetWritable(true);
+  fake_video_ice->SetWritable(true);
   // Decreasing connection count from 2 to 1 triggers connection state event.
-  fake_audio_dtls->fake_ice_transport()->SetConnectionCount(2);
-  fake_audio_dtls->fake_ice_transport()->SetConnectionCount(1);
-  fake_video_dtls->fake_ice_transport()->SetConnectionCount(2);
-  fake_video_dtls->fake_ice_transport()->SetConnectionCount(1);
-  fake_audio_dtls->SetDtlsState(cricket::DTLS_TRANSPORT_CONNECTED);
-  fake_video_dtls->SetDtlsState(cricket::DTLS_TRANSPORT_CONNECTED);
+  fake_audio_ice->SetConnectionCount(2);
+  fake_audio_ice->SetConnectionCount(1);
+  fake_video_ice->SetConnectionCount(2);
+  fake_video_ice->SetConnectionCount(1);
 
   FakeMediaTransport* media_transport = static_cast<FakeMediaTransport*>(
       transport_controller_->GetMediaTransport(kAudioMid1));