Adding ability for BaseChannel to use PacketTransportInterface.

... As opposed to DtlsTransportInternal.

The code is suboptimal right now, storing two pointers to the different
interfaces. This will all be cleaned up when we have an "RtpTransport"
abstraction that BaseChannel can use.

This CL also cleans up the "fake transport" classes a bit, and gives
them their own header files.

BUG=None

Review-Url: https://codereview.webrtc.org/2648233003
Cr-Commit-Position: refs/heads/master@{#16258}
diff --git a/webrtc/media/engine/webrtcvoiceengine_unittest.cc b/webrtc/media/engine/webrtcvoiceengine_unittest.cc
index eb6f606..526f7cc 100644
--- a/webrtc/media/engine/webrtcvoiceengine_unittest.cc
+++ b/webrtc/media/engine/webrtcvoiceengine_unittest.cc
@@ -15,7 +15,6 @@
 #include "webrtc/base/byteorder.h"
 #include "webrtc/base/gunit.h"
 #include "webrtc/call/call.h"
-#include "webrtc/p2p/base/faketransportcontroller.h"
 #include "webrtc/test/field_trial.h"
 #include "webrtc/logging/rtc_event_log/rtc_event_log.h"
 #include "webrtc/media/base/fakemediaengine.h"
diff --git a/webrtc/media/sctp/sctptransport_unittest.cc b/webrtc/media/sctp/sctptransport_unittest.cc
index 2f34240..4ccc24e 100644
--- a/webrtc/media/sctp/sctptransport_unittest.cc
+++ b/webrtc/media/sctp/sctptransport_unittest.cc
@@ -24,7 +24,7 @@
 #include "webrtc/base/ssladapter.h"
 #include "webrtc/base/thread.h"
 #include "webrtc/media/sctp/sctptransport.h"
-#include "webrtc/p2p/base/faketransportcontroller.h"
+#include "webrtc/p2p/base/fakedtlstransport.h"
 
 namespace {
 static const int kDefaultTimeout = 10000;  // 10 seconds.
diff --git a/webrtc/p2p/BUILD.gn b/webrtc/p2p/BUILD.gn
index 04e9b17..9967b12 100644
--- a/webrtc/p2p/BUILD.gn
+++ b/webrtc/p2p/BUILD.gn
@@ -144,6 +144,9 @@
     sources = [
       "base/asyncstuntcpsocket_unittest.cc",
       "base/dtlstransportchannel_unittest.cc",
+      "base/fakedtlstransport.h",
+      "base/fakeicetransport.h",
+      "base/fakepackettransport.h",
       "base/fakeportallocator.h",
       "base/faketransportcontroller.h",
       "base/jseptransport_unittest.cc",
diff --git a/webrtc/p2p/base/dtlstransportchannel_unittest.cc b/webrtc/p2p/base/dtlstransportchannel_unittest.cc
index 7034343..4473d32 100644
--- a/webrtc/p2p/base/dtlstransportchannel_unittest.cc
+++ b/webrtc/p2p/base/dtlstransportchannel_unittest.cc
@@ -12,7 +12,7 @@
 #include <set>
 
 #include "webrtc/p2p/base/dtlstransportchannel.h"
-#include "webrtc/p2p/base/faketransportcontroller.h"
+#include "webrtc/p2p/base/fakeicetransport.h"
 #include "webrtc/p2p/base/packettransportinterface.h"
 #include "webrtc/base/checks.h"
 #include "webrtc/base/common.h"
diff --git a/webrtc/p2p/base/fakecandidatepair.h b/webrtc/p2p/base/fakecandidatepair.h
new file mode 100644
index 0000000..73e6c67
--- /dev/null
+++ b/webrtc/p2p/base/fakecandidatepair.h
@@ -0,0 +1,54 @@
+/*
+ *  Copyright 2017 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 WEBRTC_P2P_BASE_FAKECANDIDATEPAIR_H_
+#define WEBRTC_P2P_BASE_FAKECANDIDATEPAIR_H_
+
+#include <memory>
+
+#include "webrtc/p2p/base/candidate.h"
+#include "webrtc/p2p/base/candidatepairinterface.h"
+
+namespace cricket {
+
+// Fake candidate pair class, which can be passed to BaseChannel for testing
+// purposes.
+class FakeCandidatePair : public CandidatePairInterface {
+ public:
+  FakeCandidatePair(const Candidate& local_candidate,
+                    const Candidate& remote_candidate)
+      : local_candidate_(local_candidate),
+        remote_candidate_(remote_candidate) {}
+  const Candidate& local_candidate() const override { return local_candidate_; }
+  const Candidate& remote_candidate() const override {
+    return remote_candidate_;
+  }
+
+  static std::unique_ptr<FakeCandidatePair> Create(
+      const rtc::SocketAddress& local_address,
+      int16_t local_network_id,
+      const rtc::SocketAddress& remote_address,
+      int16_t remote_network_id) {
+    Candidate local_candidate(0, "udp", local_address, 0u, "", "", "local", 0,
+                              "foundation", local_network_id, 0);
+    Candidate remote_candidate(0, "udp", remote_address, 0u, "", "", "local", 0,
+                               "foundation", remote_network_id, 0);
+    return std::unique_ptr<FakeCandidatePair>(
+        new FakeCandidatePair(local_candidate, remote_candidate));
+  }
+
+ private:
+  Candidate local_candidate_;
+  Candidate remote_candidate_;
+};
+
+}  // namespace cricket
+
+#endif  // WEBRTC_P2P_BASE_FAKECANDIDATEPAIR_H_
diff --git a/webrtc/p2p/base/fakedtlstransport.h b/webrtc/p2p/base/fakedtlstransport.h
new file mode 100644
index 0000000..1fe66ec
--- /dev/null
+++ b/webrtc/p2p/base/fakedtlstransport.h
@@ -0,0 +1,270 @@
+/*
+ *  Copyright 2017 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 WEBRTC_P2P_BASE_FAKEDTLSTRANSPORT_H_
+#define WEBRTC_P2P_BASE_FAKEDTLSTRANSPORT_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "webrtc/base/fakesslidentity.h"
+#include "webrtc/p2p/base/dtlstransportinternal.h"
+#include "webrtc/p2p/base/fakeicetransport.h"
+
+namespace cricket {
+
+// Fake DTLS transport which is implemented by wrapping a fake ICE transport.
+// Doesn't interact directly with fake ICE transport for anything other than
+// sending packets.
+class FakeDtlsTransport : public DtlsTransportInternal {
+ public:
+  explicit FakeDtlsTransport(FakeIceTransport* ice_transport)
+      : ice_transport_(ice_transport),
+        transport_name_(ice_transport->transport_name()),
+        component_(ice_transport->component()),
+        dtls_fingerprint_("", nullptr, 0) {
+    ice_transport_->SignalReadPacket.connect(
+        this, &FakeDtlsTransport::OnIceTransportReadPacket);
+  }
+
+  // If this constructor is called, a new fake ICE transport will be created,
+  // and this FakeDtlsTransport will take the ownership.
+  explicit FakeDtlsTransport(const std::string& name, int component)
+      : owned_ice_transport_(new FakeIceTransport(name, component)),
+        transport_name_(owned_ice_transport_->transport_name()),
+        component_(owned_ice_transport_->component()),
+        dtls_fingerprint_("", nullptr, 0) {
+    ice_transport_ = owned_ice_transport_.get();
+    ice_transport_->SignalReadPacket.connect(
+        this, &FakeDtlsTransport::OnIceTransportReadPacket);
+  }
+
+  ~FakeDtlsTransport() override {
+    if (dest_ && dest_->dest_ == this) {
+      dest_->dest_ = nullptr;
+    }
+  }
+
+  // Get inner fake ICE transport.
+  FakeIceTransport* fake_ice_transport() { return ice_transport_; }
+
+  // If async, will send packets by "Post"-ing to message queue instead of
+  // synchronously "Send"-ing.
+  void SetAsync(bool async) { ice_transport_->SetAsync(async); }
+  void SetAsyncDelay(int delay_ms) { ice_transport_->SetAsyncDelay(delay_ms); }
+
+  // SetWritable, SetReceiving and SetDestination are the main methods that can
+  // be used for testing, to simulate connectivity or lack thereof.
+  void SetWritable(bool writable) {
+    ice_transport_->SetWritable(writable);
+    set_writable(writable);
+  }
+  void SetReceiving(bool receiving) {
+    ice_transport_->SetReceiving(receiving);
+    set_receiving(receiving);
+  }
+
+  // Simulates the two DTLS transports connecting to each other.
+  // If |asymmetric| is true this method only affects this FakeDtlsTransport.
+  // If false, it affects |dest| as well.
+  void SetDestination(FakeDtlsTransport* dest, bool asymmetric = false) {
+    if (dest == dest_) {
+      return;
+    }
+    RTC_DCHECK(!dest || !dest_)
+        << "Changing fake destination from one to another is not supported.";
+    if (dest && !dest_) {
+      // This simulates the DTLS handshake.
+      dest_ = dest;
+      if (local_cert_ && dest_->local_cert_) {
+        do_dtls_ = true;
+        NegotiateSrtpCiphers();
+      }
+      SetWritable(true);
+      if (!asymmetric) {
+        dest->SetDestination(this, true);
+      }
+      ice_transport_->SetDestination(
+          static_cast<FakeIceTransport*>(dest->ice_transport()), asymmetric);
+    } else {
+      // Simulates loss of connectivity, by asymmetrically forgetting dest_.
+      dest_ = nullptr;
+      SetWritable(false);
+      ice_transport_->SetDestination(nullptr, asymmetric);
+    }
+  }
+
+  // Fake DtlsTransportInternal implementation.
+  DtlsTransportState dtls_state() const override { return dtls_state_; }
+  const std::string& transport_name() const override { return transport_name_; }
+  int component() const override { return component_; }
+  const rtc::SSLFingerprint& dtls_fingerprint() const {
+    return dtls_fingerprint_;
+  }
+  bool SetRemoteFingerprint(const std::string& alg,
+                            const uint8_t* digest,
+                            size_t digest_len) override {
+    dtls_fingerprint_ = rtc::SSLFingerprint(alg, digest, digest_len);
+    return true;
+  }
+  bool SetSslRole(rtc::SSLRole role) override {
+    ssl_role_ = role;
+    return true;
+  }
+  bool GetSslRole(rtc::SSLRole* role) const override {
+    *role = ssl_role_;
+    return true;
+  }
+  bool SetLocalCertificate(
+      const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) override {
+    local_cert_ = certificate;
+    return true;
+  }
+  void SetRemoteSSLCertificate(rtc::FakeSSLCertificate* cert) {
+    remote_cert_ = cert;
+  }
+  bool IsDtlsActive() const override { return do_dtls_; }
+  bool SetSrtpCryptoSuites(const std::vector<int>& ciphers) override {
+    srtp_ciphers_ = ciphers;
+    return true;
+  }
+  bool GetSrtpCryptoSuite(int* crypto_suite) override {
+    if (chosen_crypto_suite_ != rtc::SRTP_INVALID_CRYPTO_SUITE) {
+      *crypto_suite = chosen_crypto_suite_;
+      return true;
+    }
+    return false;
+  }
+  bool GetSslCipherSuite(int* cipher_suite) override { return false; }
+  rtc::scoped_refptr<rtc::RTCCertificate> GetLocalCertificate() const override {
+    return local_cert_;
+  }
+  std::unique_ptr<rtc::SSLCertificate> GetRemoteSSLCertificate()
+      const override {
+    return remote_cert_ ? std::unique_ptr<rtc::SSLCertificate>(
+                              remote_cert_->GetReference())
+                        : nullptr;
+  }
+  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 {
+    if (chosen_crypto_suite_ != rtc::SRTP_INVALID_CRYPTO_SUITE) {
+      memset(result, 0xff, result_len);
+      return true;
+    }
+
+    return false;
+  }
+  void set_ssl_max_protocol_version(rtc::SSLProtocolVersion version) {
+    ssl_max_version_ = version;
+  }
+  rtc::SSLProtocolVersion ssl_max_protocol_version() const {
+    return ssl_max_version_;
+  }
+  bool SetSrtpCiphers(const std::vector<std::string>& ciphers) override {
+    std::vector<int> crypto_suites;
+    for (const auto cipher : ciphers) {
+      crypto_suites.push_back(rtc::SrtpCryptoSuiteFromName(cipher));
+    }
+    return SetSrtpCryptoSuites(crypto_suites);
+  }
+
+  IceTransportInternal* ice_transport() override { return ice_transport_; }
+
+  // PacketTransportInterface implementation, which passes through to fake ICE
+  // transport for sending actual packets.
+  bool writable() const override { return writable_; }
+  bool receiving() const override { return receiving_; }
+  int SendPacket(const char* data,
+                 size_t len,
+                 const rtc::PacketOptions& options,
+                 int flags) override {
+    // We expect only SRTP packets to be sent through this interface.
+    if (flags != PF_SRTP_BYPASS && flags != 0) {
+      return -1;
+    }
+    return ice_transport_->SendPacket(data, len, options, flags);
+  }
+  int SetOption(rtc::Socket::Option opt, int value) override {
+    return ice_transport_->SetOption(opt, value);
+  }
+  bool GetOption(rtc::Socket::Option opt, int* value) override {
+    return ice_transport_->GetOption(opt, value);
+  }
+  int GetError() override { return ice_transport_->GetError(); }
+
+ private:
+  void OnIceTransportReadPacket(PacketTransportInterface* ice_,
+                                const char* data,
+                                size_t len,
+                                const rtc::PacketTime& time,
+                                int flags) {
+    SignalReadPacket(this, data, len, time, flags);
+  }
+
+  void NegotiateSrtpCiphers() {
+    for (std::vector<int>::const_iterator it1 = srtp_ciphers_.begin();
+         it1 != srtp_ciphers_.end(); ++it1) {
+      for (std::vector<int>::const_iterator it2 = dest_->srtp_ciphers_.begin();
+           it2 != dest_->srtp_ciphers_.end(); ++it2) {
+        if (*it1 == *it2) {
+          chosen_crypto_suite_ = *it1;
+          return;
+        }
+      }
+    }
+  }
+
+  void set_receiving(bool receiving) {
+    if (receiving_ == receiving) {
+      return;
+    }
+    receiving_ = receiving;
+    SignalReceivingState(this);
+  }
+
+  void set_writable(bool writable) {
+    if (writable_ == writable) {
+      return;
+    }
+    writable_ = writable;
+    if (writable_) {
+      SignalReadyToSend(this);
+    }
+    SignalWritableState(this);
+  }
+
+  FakeIceTransport* ice_transport_;
+  std::unique_ptr<FakeIceTransport> owned_ice_transport_;
+  std::string transport_name_;
+  int component_;
+  FakeDtlsTransport* dest_ = nullptr;
+  rtc::scoped_refptr<rtc::RTCCertificate> local_cert_;
+  rtc::FakeSSLCertificate* remote_cert_ = nullptr;
+  bool do_dtls_ = false;
+  std::vector<int> srtp_ciphers_;
+  int chosen_crypto_suite_ = rtc::SRTP_INVALID_CRYPTO_SUITE;
+  rtc::SSLProtocolVersion ssl_max_version_ = rtc::SSL_PROTOCOL_DTLS_12;
+  rtc::SSLFingerprint dtls_fingerprint_;
+  rtc::SSLRole ssl_role_ = rtc::SSL_CLIENT;
+
+  DtlsTransportState dtls_state_ = DTLS_TRANSPORT_NEW;
+
+  bool receiving_ = false;
+  bool writable_ = false;
+};
+
+}  // namespace cricket
+
+#endif  // WEBRTC_P2P_BASE_FAKEDTLSTRANSPORT_H_
diff --git a/webrtc/p2p/base/fakeicetransport.h b/webrtc/p2p/base/fakeicetransport.h
new file mode 100644
index 0000000..8daf33b
--- /dev/null
+++ b/webrtc/p2p/base/fakeicetransport.h
@@ -0,0 +1,236 @@
+/*
+ *  Copyright 2017 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 WEBRTC_P2P_BASE_FAKEICETRANSPORT_H_
+#define WEBRTC_P2P_BASE_FAKEICETRANSPORT_H_
+
+#include <string>
+
+#include "webrtc/base/asyncinvoker.h"
+#include "webrtc/base/copyonwritebuffer.h"
+#include "webrtc/p2p/base/icetransportinternal.h"
+
+namespace cricket {
+
+class FakeIceTransport : public IceTransportInternal {
+ public:
+  explicit FakeIceTransport(const std::string& name, int component)
+      : name_(name), component_(component) {}
+  ~FakeIceTransport() override {
+    if (dest_ && dest_->dest_ == this) {
+      dest_->dest_ = nullptr;
+    }
+  }
+
+  // If async, will send packets by "Post"-ing to message queue instead of
+  // synchronously "Send"-ing.
+  void SetAsync(bool async) { async_ = async; }
+  void SetAsyncDelay(int delay_ms) { async_delay_ms_ = delay_ms; }
+
+  // SetWritable, SetReceiving and SetDestination are the main methods that can
+  // be used for testing, to simulate connectivity or lack thereof.
+  void SetWritable(bool writable) { set_writable(writable); }
+  void SetReceiving(bool receiving) { set_receiving(receiving); }
+
+  // Simulates the two transports connecting to each other.
+  // If |asymmetric| is true this method only affects this FakeIceTransport.
+  // If false, it affects |dest| as well.
+  void SetDestination(FakeIceTransport* dest, bool asymmetric = false) {
+    if (dest == dest_) {
+      return;
+    }
+    RTC_DCHECK(!dest || !dest_)
+        << "Changing fake destination from one to another is not supported.";
+    if (dest) {
+      // This simulates the delivery of candidates.
+      dest_ = dest;
+      set_writable(true);
+      if (!asymmetric) {
+        dest->SetDestination(this, true);
+      }
+    } else {
+      // Simulates loss of connectivity, by asymmetrically forgetting dest_.
+      dest_ = nullptr;
+      set_writable(false);
+    }
+  }
+
+  void SetConnectionCount(size_t connection_count) {
+    size_t old_connection_count = connection_count_;
+    connection_count_ = connection_count;
+    if (connection_count) {
+      had_connection_ = true;
+    }
+    // In this fake transport channel, |connection_count_| determines the
+    // transport state.
+    if (connection_count_ < old_connection_count) {
+      SignalStateChanged(this);
+    }
+  }
+
+  void SetCandidatesGatheringComplete() {
+    if (gathering_state_ != kIceGatheringComplete) {
+      gathering_state_ = kIceGatheringComplete;
+      SignalGatheringState(this);
+    }
+  }
+
+  // Convenience functions for accessing ICE config and other things.
+  int receiving_timeout() const { return ice_config_.receiving_timeout; }
+  bool gather_continually() const { return ice_config_.gather_continually(); }
+  const Candidates& remote_candidates() const { return remote_candidates_; }
+
+  // Fake IceTransportInternal implementation.
+  const std::string& transport_name() const override { return name_; }
+  int component() const override { return component_; }
+  uint64_t IceTiebreaker() const { return tiebreaker_; }
+  IceMode remote_ice_mode() const { return remote_ice_mode_; }
+  const std::string& ice_ufrag() const { return ice_ufrag_; }
+  const std::string& ice_pwd() const { return ice_pwd_; }
+  const std::string& remote_ice_ufrag() const { return remote_ice_ufrag_; }
+  const std::string& remote_ice_pwd() const { return remote_ice_pwd_; }
+
+  IceTransportState GetState() const override {
+    if (connection_count_ == 0) {
+      return had_connection_ ? IceTransportState::STATE_FAILED
+                             : IceTransportState::STATE_INIT;
+    }
+
+    if (connection_count_ == 1) {
+      return IceTransportState::STATE_COMPLETED;
+    }
+
+    return IceTransportState::STATE_CONNECTING;
+  }
+
+  void SetIceRole(IceRole role) override { role_ = role; }
+  IceRole GetIceRole() const override { return role_; }
+  void SetIceTiebreaker(uint64_t tiebreaker) override {
+    tiebreaker_ = tiebreaker;
+  }
+  void SetIceParameters(const IceParameters& ice_params) override {
+    ice_ufrag_ = ice_params.ufrag;
+    ice_pwd_ = ice_params.pwd;
+  }
+  void SetRemoteIceParameters(const IceParameters& params) override {
+    remote_ice_ufrag_ = params.ufrag;
+    remote_ice_pwd_ = params.pwd;
+  }
+
+  void SetRemoteIceMode(IceMode mode) override { remote_ice_mode_ = mode; }
+
+  void MaybeStartGathering() override {
+    if (gathering_state_ == kIceGatheringNew) {
+      gathering_state_ = kIceGatheringGathering;
+      SignalGatheringState(this);
+    }
+  }
+
+  IceGatheringState gathering_state() const override {
+    return gathering_state_;
+  }
+
+  void SetIceConfig(const IceConfig& config) override { ice_config_ = config; }
+
+  void AddRemoteCandidate(const Candidate& candidate) override {
+    remote_candidates_.push_back(candidate);
+  }
+  void RemoveRemoteCandidate(const Candidate& candidate) override {}
+
+  bool GetStats(ConnectionInfos* infos) override {
+    ConnectionInfo info;
+    infos->clear();
+    infos->push_back(info);
+    return true;
+  }
+
+  void SetMetricsObserver(webrtc::MetricsObserverInterface* observer) override {
+  }
+
+  // Fake PacketTransportInterface implementation.
+  bool writable() const override { return writable_; }
+  bool receiving() const override { return receiving_; }
+  int SendPacket(const char* data,
+                 size_t len,
+                 const rtc::PacketOptions& options,
+                 int flags) override {
+    if (!dest_) {
+      return -1;
+    }
+    rtc::CopyOnWriteBuffer packet(data, len);
+    if (async_) {
+      invoker_.AsyncInvokeDelayed<void>(
+          RTC_FROM_HERE, rtc::Thread::Current(),
+          rtc::Bind(&FakeIceTransport::SendPacketInternal, this, packet),
+          async_delay_ms_);
+    } else {
+      SendPacketInternal(packet);
+    }
+    rtc::SentPacket sent_packet(options.packet_id, rtc::TimeMillis());
+    SignalSentPacket(this, sent_packet);
+    return static_cast<int>(len);
+  }
+  int SetOption(rtc::Socket::Option opt, int value) override { return true; }
+  bool GetOption(rtc::Socket::Option opt, int* value) override { return true; }
+  int GetError() override { return 0; }
+
+ private:
+  void set_writable(bool writable) {
+    if (writable_ == writable) {
+      return;
+    }
+    LOG(INFO) << "set_writable from:" << writable_ << " to " << writable;
+    writable_ = writable;
+    if (writable_) {
+      SignalReadyToSend(this);
+    }
+    SignalWritableState(this);
+  }
+
+  void set_receiving(bool receiving) {
+    if (receiving_ == receiving) {
+      return;
+    }
+    receiving_ = receiving;
+    SignalReceivingState(this);
+  }
+
+  void SendPacketInternal(const rtc::CopyOnWriteBuffer& packet) {
+    if (dest_) {
+      dest_->SignalReadPacket(dest_, packet.data<char>(), packet.size(),
+                              rtc::CreatePacketTime(0), 0);
+    }
+  }
+
+  rtc::AsyncInvoker invoker_;
+  std::string name_;
+  int component_;
+  FakeIceTransport* dest_ = nullptr;
+  bool async_ = false;
+  int async_delay_ms_ = 0;
+  Candidates remote_candidates_;
+  IceConfig ice_config_;
+  IceRole role_ = ICEROLE_UNKNOWN;
+  uint64_t tiebreaker_ = 0;
+  std::string ice_ufrag_;
+  std::string ice_pwd_;
+  std::string remote_ice_ufrag_;
+  std::string remote_ice_pwd_;
+  IceMode remote_ice_mode_ = ICEMODE_FULL;
+  size_t connection_count_ = 0;
+  IceGatheringState gathering_state_ = kIceGatheringNew;
+  bool had_connection_ = false;
+  bool writable_ = false;
+  bool receiving_ = false;
+};
+
+}  // namespace cricket
+
+#endif  // WEBRTC_P2P_BASE_FAKEICETRANSPORT_H_
diff --git a/webrtc/p2p/base/fakepackettransport.h b/webrtc/p2p/base/fakepackettransport.h
new file mode 100644
index 0000000..c8fc9bb
--- /dev/null
+++ b/webrtc/p2p/base/fakepackettransport.h
@@ -0,0 +1,126 @@
+/*
+ *  Copyright 2017 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 WEBRTC_P2P_BASE_FAKEPACKETTRANSPORT_H_
+#define WEBRTC_P2P_BASE_FAKEPACKETTRANSPORT_H_
+
+#include <string>
+
+#include "webrtc/base/asyncinvoker.h"
+#include "webrtc/base/copyonwritebuffer.h"
+#include "webrtc/p2p/base/packettransportinterface.h"
+
+namespace rtc {
+
+// Used to simulate a packet-based transport.
+class FakePacketTransport : public PacketTransportInterface {
+ public:
+  explicit FakePacketTransport(const std::string& debug_name)
+      : debug_name_(debug_name) {}
+  ~FakePacketTransport() override {
+    if (dest_ && dest_->dest_ == this) {
+      dest_->dest_ = nullptr;
+    }
+  }
+
+  // If async, will send packets by "Post"-ing to message queue instead of
+  // synchronously "Send"-ing.
+  void SetAsync(bool async) { async_ = async; }
+  void SetAsyncDelay(int delay_ms) { async_delay_ms_ = delay_ms; }
+
+  // SetWritable, SetReceiving and SetDestination are the main methods that can
+  // be used for testing, to simulate connectivity or lack thereof.
+  void SetWritable(bool writable) { set_writable(writable); }
+  void SetReceiving(bool receiving) { set_receiving(receiving); }
+
+  // Simulates the two transports connecting to each other.
+  // If |asymmetric| is true this method only affects this FakePacketTransport.
+  // If false, it affects |dest| as well.
+  void SetDestination(FakePacketTransport* dest, bool asymmetric) {
+    if (dest) {
+      dest_ = dest;
+      set_writable(true);
+      if (!asymmetric) {
+        dest->SetDestination(this, true);
+      }
+    } else {
+      // Simulates loss of connectivity, by asymmetrically forgetting dest_.
+      dest_ = nullptr;
+      set_writable(false);
+    }
+  }
+
+  // Fake PacketTransportInterface implementation.
+  std::string debug_name() const override { return debug_name_; }
+  bool writable() const override { return writable_; }
+  bool receiving() const override { return receiving_; }
+  int SendPacket(const char* data,
+                 size_t len,
+                 const PacketOptions& options,
+                 int flags) override {
+    if (!dest_) {
+      return -1;
+    }
+    CopyOnWriteBuffer packet(data, len);
+    if (async_) {
+      invoker_.AsyncInvokeDelayed<void>(
+          RTC_FROM_HERE, Thread::Current(),
+          Bind(&FakePacketTransport::SendPacketInternal, this, packet),
+          async_delay_ms_);
+    } else {
+      SendPacketInternal(packet);
+    }
+    SentPacket sent_packet(options.packet_id, TimeMillis());
+    SignalSentPacket(this, sent_packet);
+    return static_cast<int>(len);
+  }
+  int SetOption(Socket::Option opt, int value) override { return true; }
+  bool GetOption(Socket::Option opt, int* value) override { return true; }
+  int GetError() override { return 0; }
+
+ private:
+  void set_writable(bool writable) {
+    if (writable_ == writable) {
+      return;
+    }
+    writable_ = writable;
+    if (writable_) {
+      SignalReadyToSend(this);
+    }
+    SignalWritableState(this);
+  }
+
+  void set_receiving(bool receiving) {
+    if (receiving_ == receiving) {
+      return;
+    }
+    receiving_ = receiving;
+    SignalReceivingState(this);
+  }
+
+  void SendPacketInternal(const CopyOnWriteBuffer& packet) {
+    if (dest_) {
+      dest_->SignalReadPacket(dest_, packet.data<char>(), packet.size(),
+                              CreatePacketTime(0), 0);
+    }
+  }
+
+  AsyncInvoker invoker_;
+  std::string debug_name_;
+  FakePacketTransport* dest_ = nullptr;
+  bool async_ = false;
+  int async_delay_ms_ = 0;
+  bool writable_ = false;
+  bool receiving_ = false;
+};
+
+}  // namespace rtc
+
+#endif  // WEBRTC_P2P_BASE_FAKEPACKETTRANSPORT_H_
diff --git a/webrtc/p2p/base/faketransportcontroller.h b/webrtc/p2p/base/faketransportcontroller.h
index 76ed370..35af390 100644
--- a/webrtc/p2p/base/faketransportcontroller.h
+++ b/webrtc/p2p/base/faketransportcontroller.h
@@ -11,567 +11,22 @@
 #ifndef WEBRTC_P2P_BASE_FAKETRANSPORTCONTROLLER_H_
 #define WEBRTC_P2P_BASE_FAKETRANSPORTCONTROLLER_H_
 
-#include <map>
 #include <memory>
 #include <string>
 #include <vector>
 
 #include "webrtc/base/bind.h"
-#include "webrtc/base/buffer.h"
-#include "webrtc/base/fakesslidentity.h"
-#include "webrtc/base/messagequeue.h"
-#include "webrtc/base/sigslot.h"
 #include "webrtc/base/sslfingerprint.h"
 #include "webrtc/base/thread.h"
-#include "webrtc/p2p/base/candidatepairinterface.h"
-#include "webrtc/p2p/base/dtlstransportinternal.h"
-#include "webrtc/p2p/base/icetransportinternal.h"
-
+#include "webrtc/p2p/base/fakedtlstransport.h"
+#include "webrtc/p2p/base/fakeicetransport.h"
 #include "webrtc/p2p/base/transportcontroller.h"
 
-#ifdef HAVE_QUIC
-#include "webrtc/p2p/quic/quictransport.h"
-#endif
-
 namespace cricket {
 
-namespace {
-struct PacketMessageData : public rtc::MessageData {
-  PacketMessageData(const char* data, size_t len) : packet(data, len) {}
-  rtc::Buffer packet;
-};
-}  // namespace
-
-class FakeIceTransport : public IceTransportInternal,
-                         public rtc::MessageHandler {
- public:
-  explicit FakeIceTransport(const std::string& name, int component)
-      : name_(name), component_(component) {}
-  ~FakeIceTransport() { Reset(); }
-
-  const std::string& transport_name() const override { return name_; }
-  int component() const override { return component_; }
-  uint64_t IceTiebreaker() const { return tiebreaker_; }
-  IceMode remote_ice_mode() const { return remote_ice_mode_; }
-  const std::string& ice_ufrag() const { return ice_ufrag_; }
-  const std::string& ice_pwd() const { return ice_pwd_; }
-  const std::string& remote_ice_ufrag() const { return remote_ice_ufrag_; }
-  const std::string& remote_ice_pwd() const { return remote_ice_pwd_; }
-
-  // If async, will send packets by "Post"-ing to message queue instead of
-  // synchronously "Send"-ing.
-  void SetAsync(bool async) { async_ = async; }
-  void SetAsyncDelay(int delay_ms) { async_delay_ms_ = delay_ms; }
-
-  IceTransportState GetState() const override {
-    if (connection_count_ == 0) {
-      return had_connection_ ? IceTransportState::STATE_FAILED
-                             : IceTransportState::STATE_INIT;
-    }
-
-    if (connection_count_ == 1) {
-      return IceTransportState::STATE_COMPLETED;
-    }
-
-    return IceTransportState::STATE_CONNECTING;
-  }
-
-  void SetIceRole(IceRole role) override { role_ = role; }
-  IceRole GetIceRole() const override { return role_; }
-  void SetIceTiebreaker(uint64_t tiebreaker) override {
-    tiebreaker_ = tiebreaker;
-  }
-  void SetIceParameters(const IceParameters& ice_params) override {
-    ice_ufrag_ = ice_params.ufrag;
-    ice_pwd_ = ice_params.pwd;
-  }
-  void SetRemoteIceParameters(const IceParameters& params) override {
-    remote_ice_ufrag_ = params.ufrag;
-    remote_ice_pwd_ = params.pwd;
-  }
-
-  void SetRemoteIceMode(IceMode mode) override { remote_ice_mode_ = mode; }
-
-  void MaybeStartGathering() override {
-    if (gathering_state_ == kIceGatheringNew) {
-      gathering_state_ = kIceGatheringGathering;
-      SignalGatheringState(this);
-    }
-  }
-
-  IceGatheringState gathering_state() const override {
-    return gathering_state_;
-  }
-
-  void Reset() {
-    if (state_ != STATE_INIT) {
-      state_ = STATE_INIT;
-      if (dest_) {
-        dest_->state_ = STATE_INIT;
-        dest_->dest_ = nullptr;
-        dest_ = nullptr;
-      }
-    }
-  }
-
-  void SetWritable(bool writable) { set_writable(writable); }
-
-  void set_writable(bool writable) {
-    if (writable_ == writable) {
-      return;
-    }
-    LOG(INFO) << "set_writable from:" << writable_ << " to " << writable;
-    writable_ = writable;
-    if (writable_) {
-      SignalReadyToSend(this);
-    }
-    SignalWritableState(this);
-  }
-  bool writable() const override { return writable_; }
-
-  // Simulates the two transports connecting to each other.
-  // If |asymmetric| is true this method only affects this FakeIceTransport.
-  // If false, it affects |dest| as well.
-  void SetDestination(FakeIceTransport* dest, bool asymmetric = false) {
-    if (state_ == STATE_INIT && dest) {
-      // This simulates the delivery of candidates.
-      dest_ = dest;
-      state_ = STATE_CONNECTED;
-      set_writable(true);
-      if (!asymmetric) {
-        dest->SetDestination(this, true);
-      }
-    } else if (state_ == STATE_CONNECTED && !dest) {
-      // Simulates loss of connectivity, by asymmetrically forgetting dest_.
-      dest_ = nullptr;
-      state_ = STATE_INIT;
-      set_writable(false);
-    }
-  }
-
-  void SetConnectionCount(size_t connection_count) {
-    size_t old_connection_count = connection_count_;
-    connection_count_ = connection_count;
-    if (connection_count)
-      had_connection_ = true;
-    // In this fake transport channel, |connection_count_| determines the
-    // transport channel state.
-    if (connection_count_ < old_connection_count)
-      SignalStateChanged(this);
-  }
-
-  void SetCandidatesGatheringComplete() {
-    if (gathering_state_ != kIceGatheringComplete) {
-      gathering_state_ = kIceGatheringComplete;
-      SignalGatheringState(this);
-    }
-  }
-
-  void SetReceiving(bool receiving) { set_receiving(receiving); }
-
-  void set_receiving(bool receiving) {
-    if (receiving_ == receiving) {
-      return;
-    }
-    receiving_ = receiving;
-    SignalReceivingState(this);
-  }
-  bool receiving() const override { return receiving_; }
-
-  void SetIceConfig(const IceConfig& config) override { ice_config_ = config; }
-
-  int receiving_timeout() const { return ice_config_.receiving_timeout; }
-  bool gather_continually() const { return ice_config_.gather_continually(); }
-
-  int SendPacket(const char* data,
-                 size_t len,
-                 const rtc::PacketOptions& options,
-                 int flags) override {
-    if (state_ != STATE_CONNECTED) {
-      return -1;
-    }
-
-    if (flags != PF_SRTP_BYPASS && flags != 0) {
-      return -1;
-    }
-
-    PacketMessageData* packet = new PacketMessageData(data, len);
-    if (async_) {
-      if (async_delay_ms_) {
-        rtc::Thread::Current()->PostDelayed(RTC_FROM_HERE, async_delay_ms_,
-                                            this, 0, packet);
-      } else {
-        rtc::Thread::Current()->Post(RTC_FROM_HERE, this, 0, packet);
-      }
-    } else {
-      rtc::Thread::Current()->Send(RTC_FROM_HERE, this, 0, packet);
-    }
-    rtc::SentPacket sent_packet(options.packet_id, rtc::TimeMillis());
-    SignalSentPacket(this, sent_packet);
-    return static_cast<int>(len);
-  }
-  int SetOption(rtc::Socket::Option opt, int value) override { return true; }
-  bool GetOption(rtc::Socket::Option opt, int* value) override { return true; }
-  int GetError() override { return 0; }
-
-  void AddRemoteCandidate(const Candidate& candidate) override {
-    remote_candidates_.push_back(candidate);
-  }
-
-  void RemoveRemoteCandidate(const Candidate& candidate) override {}
-
-  const Candidates& remote_candidates() const { return remote_candidates_; }
-
-  void OnMessage(rtc::Message* msg) override {
-    PacketMessageData* data = static_cast<PacketMessageData*>(msg->pdata);
-    dest_->SignalReadPacket(dest_, data->packet.data<char>(),
-                            data->packet.size(), rtc::CreatePacketTime(0), 0);
-    delete data;
-  }
-
-  bool GetStats(ConnectionInfos* infos) override {
-    ConnectionInfo info;
-    infos->clear();
-    infos->push_back(info);
-    return true;
-  }
-
-  void SetMetricsObserver(webrtc::MetricsObserverInterface* observer) override {
-  }
-
- private:
-  std::string name_;
-  int component_;
-  enum State { STATE_INIT, STATE_CONNECTED };
-  FakeIceTransport* dest_ = nullptr;
-  State state_ = STATE_INIT;
-  bool async_ = false;
-  int async_delay_ms_ = 0;
-  Candidates remote_candidates_;
-  IceConfig ice_config_;
-  IceRole role_ = ICEROLE_UNKNOWN;
-  uint64_t tiebreaker_ = 0;
-  std::string ice_ufrag_;
-  std::string ice_pwd_;
-  std::string remote_ice_ufrag_;
-  std::string remote_ice_pwd_;
-  IceMode remote_ice_mode_ = ICEMODE_FULL;
-  size_t connection_count_ = 0;
-  IceGatheringState gathering_state_ = kIceGatheringNew;
-  bool had_connection_ = false;
-  bool writable_ = false;
-  bool receiving_ = false;
-};
-
-class FakeDtlsTransport : public DtlsTransportInternal {
- public:
-  explicit FakeDtlsTransport(FakeIceTransport* ice_transport)
-      : ice_transport_(ice_transport),
-        transport_name_(ice_transport->transport_name()),
-        component_(ice_transport->component()),
-        dtls_fingerprint_("", nullptr, 0) {
-    ice_transport_->SignalReadPacket.connect(
-        this, &FakeDtlsTransport::OnIceTransportReadPacket);
-  }
-
-  // If this constructor is called, a new fake ice transport will be created,
-  // and this FakeDtlsTransport will take the ownership.
-  explicit FakeDtlsTransport(const std::string& name, int component)
-      : owned_ice_transport_(new FakeIceTransport(name, component)),
-        transport_name_(owned_ice_transport_->transport_name()),
-        component_(owned_ice_transport_->component()),
-        dtls_fingerprint_("", nullptr, 0) {
-    ice_transport_ = owned_ice_transport_.get();
-    ice_transport_->SignalReadPacket.connect(
-        this, &FakeDtlsTransport::OnIceTransportReadPacket);
-  }
-
-  ~FakeDtlsTransport() override { Reset(); }
-
-  uint64_t IceTiebreaker() const { return ice_transport_->IceTiebreaker(); }
-  IceMode remote_ice_mode() const { return ice_transport_->remote_ice_mode(); }
-  const std::string& ice_ufrag() const { return ice_transport_->ice_ufrag(); }
-  const std::string& ice_pwd() const { return ice_transport_->ice_pwd(); }
-  const std::string& remote_ice_ufrag() const {
-    return ice_transport_->remote_ice_ufrag();
-  }
-  const std::string& remote_ice_pwd() const {
-    return ice_transport_->remote_ice_pwd();
-  }
-
-  DtlsTransportState dtls_state() const override { return dtls_state_; }
-
-  const std::string& transport_name() const override { return transport_name_; }
-
-  int component() const override { return component_; }
-
-  const rtc::SSLFingerprint& dtls_fingerprint() const {
-    return dtls_fingerprint_;
-  }
-
-  // If async, will send packets by "Post"-ing to message queue instead of
-  // synchronously "Send"-ing.
-  void SetAsync(bool async) { ice_transport_->SetAsync(async); }
-  void SetAsyncDelay(int delay_ms) { ice_transport_->SetAsyncDelay(delay_ms); }
-
-  IceRole GetIceRole() const { return ice_transport_->GetIceRole(); }
-
-  bool SetRemoteFingerprint(const std::string& alg,
-                            const uint8_t* digest,
-                            size_t digest_len) override {
-    dtls_fingerprint_ = rtc::SSLFingerprint(alg, digest, digest_len);
-    return true;
-  }
-
-  bool SetSslRole(rtc::SSLRole role) override {
-    ssl_role_ = role;
-    return true;
-  }
-
-  bool GetSslRole(rtc::SSLRole* role) const override {
-    *role = ssl_role_;
-    return true;
-  }
-
-  IceGatheringState gathering_state() const {
-    return ice_transport_->gathering_state();
-  }
-
-  void Reset() {
-    if (state_ != STATE_INIT) {
-      state_ = STATE_INIT;
-      if (dest_) {
-        dest_->state_ = STATE_INIT;
-        dest_->dest_ = nullptr;
-        dest_ = nullptr;
-      }
-    }
-  }
-
-  void SetWritable(bool writable) { set_writable(writable); }
-
-  // Simulates the two transport channels connecting to each other.
-  // If |asymmetric| is true this method only affects this FakeDtlsTransport.
-  // If false, it affects |dest| as well.
-  void SetDestination(FakeDtlsTransport* dest, bool asymmetric = false) {
-    if (state_ == STATE_INIT && dest) {
-      // This simulates the delivery of candidates.
-      dest_ = dest;
-      if (local_cert_ && dest_->local_cert_) {
-        do_dtls_ = true;
-        NegotiateSrtpCiphers();
-      }
-      state_ = STATE_CONNECTED;
-      SetWritable(true);
-      if (!asymmetric) {
-        dest->SetDestination(this, true);
-      }
-      ice_transport_->SetDestination(
-          static_cast<FakeIceTransport*>(dest->ice_transport()), asymmetric);
-    } else if (state_ == STATE_CONNECTED && !dest) {
-      // Simulates loss of connectivity, by asymmetrically forgetting dest_.
-      dest_ = nullptr;
-      state_ = STATE_INIT;
-      SetWritable(false);
-      ice_transport_->SetDestination(nullptr, asymmetric);
-    }
-  }
-
-  void SetConnectionCount(size_t connection_count) {
-    ice_transport_->SetConnectionCount(connection_count);
-  }
-
-  void SetCandidatesGatheringComplete() {
-    ice_transport_->SetCandidatesGatheringComplete();
-  }
-
-  void SetReceiving(bool receiving) {
-    ice_transport_->SetReceiving(receiving);
-    set_receiving(receiving);
-  }
-
-  int receiving_timeout() const { return ice_transport_->receiving_timeout(); }
-  bool gather_continually() const {
-    return ice_transport_->gather_continually();
-  }
-
-  int SendPacket(const char* data,
-                 size_t len,
-                 const rtc::PacketOptions& options,
-                 int flags) override {
-    return ice_transport_->SendPacket(data, len, options, flags);
-  }
-
-  bool GetOption(rtc::Socket::Option opt, int* value) override { return true; }
-
-  const Candidates& remote_candidates() const {
-    return ice_transport_->remote_candidates();
-  }
-
-  void OnIceTransportReadPacket(PacketTransportInterface* ice_,
-                                const char* data,
-                                size_t len,
-                                const rtc::PacketTime& time,
-                                int flags) {
-    SignalReadPacket(this, data, len, time, flags);
-  }
-
-  bool SetLocalCertificate(
-      const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) override {
-    local_cert_ = certificate;
-    return true;
-  }
-
-  void SetRemoteSSLCertificate(rtc::FakeSSLCertificate* cert) {
-    remote_cert_ = cert;
-  }
-
-  bool IsDtlsActive() const override { return do_dtls_; }
-
-  bool SetSrtpCryptoSuites(const std::vector<int>& ciphers) override {
-    srtp_ciphers_ = ciphers;
-    return true;
-  }
-
-  bool GetSrtpCryptoSuite(int* crypto_suite) override {
-    if (chosen_crypto_suite_ != rtc::SRTP_INVALID_CRYPTO_SUITE) {
-      *crypto_suite = chosen_crypto_suite_;
-      return true;
-    }
-    return false;
-  }
-
-  bool GetSslCipherSuite(int* cipher_suite) override { return false; }
-
-  rtc::scoped_refptr<rtc::RTCCertificate> GetLocalCertificate() const override {
-    return local_cert_;
-  }
-
-  std::unique_ptr<rtc::SSLCertificate> GetRemoteSSLCertificate()
-      const override {
-    return remote_cert_ ? std::unique_ptr<rtc::SSLCertificate>(
-                              remote_cert_->GetReference())
-                        : nullptr;
-  }
-
-  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 {
-    if (chosen_crypto_suite_ != rtc::SRTP_INVALID_CRYPTO_SUITE) {
-      memset(result, 0xff, result_len);
-      return true;
-    }
-
-    return false;
-  }
-
-  void set_ssl_max_protocol_version(rtc::SSLProtocolVersion version) {
-    ssl_max_version_ = version;
-  }
-  rtc::SSLProtocolVersion ssl_max_protocol_version() const {
-    return ssl_max_version_;
-  }
-
-  IceTransportInternal* ice_transport() override { return ice_transport_; }
-
-  bool writable() const override { return writable_; }
-
-  bool receiving() const override { return receiving_; }
-
-  int GetError() override { return ice_transport_->GetError(); }
-
-  int SetOption(rtc::Socket::Option opt, int value) override {
-    return ice_transport_->SetOption(opt, value);
-  }
-
-  bool SetSrtpCiphers(const std::vector<std::string>& ciphers) override {
-    std::vector<int> crypto_suites;
-    for (const auto cipher : ciphers) {
-      crypto_suites.push_back(rtc::SrtpCryptoSuiteFromName(cipher));
-    }
-    return SetSrtpCryptoSuites(crypto_suites);
-  }
-
- private:
-  void NegotiateSrtpCiphers() {
-    for (std::vector<int>::const_iterator it1 = srtp_ciphers_.begin();
-         it1 != srtp_ciphers_.end(); ++it1) {
-      for (std::vector<int>::const_iterator it2 = dest_->srtp_ciphers_.begin();
-           it2 != dest_->srtp_ciphers_.end(); ++it2) {
-        if (*it1 == *it2) {
-          chosen_crypto_suite_ = *it1;
-          return;
-        }
-      }
-    }
-  }
-
-  void set_receiving(bool receiving) {
-    if (receiving_ == receiving) {
-      return;
-    }
-    receiving_ = receiving;
-    SignalReceivingState(this);
-  }
-
-  void set_writable(bool writable) {
-    if (writable_ == writable) {
-      return;
-    }
-    writable_ = writable;
-    if (writable_) {
-      SignalReadyToSend(this);
-    }
-    SignalWritableState(this);
-  }
-
-  enum State { STATE_INIT, STATE_CONNECTED };
-  FakeIceTransport* ice_transport_;
-  std::unique_ptr<FakeIceTransport> owned_ice_transport_;
-  std::string transport_name_;
-  int component_;
-  FakeDtlsTransport* dest_ = nullptr;
-  State state_ = STATE_INIT;
-  Candidates remote_candidates_;
-  rtc::scoped_refptr<rtc::RTCCertificate> local_cert_;
-  rtc::FakeSSLCertificate* remote_cert_ = nullptr;
-  bool do_dtls_ = false;
-  std::vector<int> srtp_ciphers_;
-  int chosen_crypto_suite_ = rtc::SRTP_INVALID_CRYPTO_SUITE;
-  rtc::SSLProtocolVersion ssl_max_version_ = rtc::SSL_PROTOCOL_DTLS_12;
-  rtc::SSLFingerprint dtls_fingerprint_;
-  rtc::SSLRole ssl_role_ = rtc::SSL_CLIENT;
-
-  DtlsTransportState dtls_state_ = DTLS_TRANSPORT_NEW;
-
-  bool receiving_ = false;
-  bool writable_ = false;
-};
-
-// Fake candidate pair class, which can be passed to BaseChannel for testing
-// purposes.
-class FakeCandidatePair : public CandidatePairInterface {
- public:
-  FakeCandidatePair(const Candidate& local_candidate,
-                    const Candidate& remote_candidate)
-      : local_candidate_(local_candidate),
-        remote_candidate_(remote_candidate) {}
-  const Candidate& local_candidate() const override { return local_candidate_; }
-  const Candidate& remote_candidate() const override {
-    return remote_candidate_;
-  }
-
- private:
-  Candidate local_candidate_;
-  Candidate remote_candidate_;
-};
-
-// Fake TransportController class, which can be passed into a BaseChannel object
-// for test purposes. Can be connected to other FakeTransportControllers via
-// Connect().
+// Fake TransportController class, which can be passed into a WebRtcSession
+// object for test purposes. Can be connected to other FakeTransportControllers
+// via Connect().
 //
 // This fake is unusual in that for the most part, it's implemented with the
 // real TransportController code, but with fake TransportChannels underneath.
@@ -653,27 +108,12 @@
                   dest));
   }
 
-  FakeCandidatePair* CreateFakeCandidatePair(
-      const rtc::SocketAddress& local_address,
-      int16_t local_network_id,
-      const rtc::SocketAddress& remote_address,
-      int16_t remote_network_id) {
-    Candidate local_candidate(0, "udp", local_address, 0u, "", "", "local", 0,
-                              "foundation", local_network_id, 0);
-    Candidate remote_candidate(0, "udp", remote_address, 0u, "", "", "local", 0,
-                               "foundation", remote_network_id, 0);
-    return new FakeCandidatePair(local_candidate, remote_candidate);
-  }
-
   void DestroyRtcpTransport(const std::string& transport_name) {
     DestroyDtlsTransport_n(transport_name,
                            cricket::ICE_CANDIDATE_COMPONENT_RTCP);
   }
 
  protected:
-  // The ICE channel is never actually used by TransportController directly,
-  // since (currently) the DTLS channel pretends to be both ICE + DTLS. This
-  // will change when we get rid of TransportChannelImpl.
   IceTransportInternal* CreateIceTransportChannel_n(
       const std::string& transport_name,
       int component) override {
diff --git a/webrtc/p2p/base/jseptransport_unittest.cc b/webrtc/p2p/base/jseptransport_unittest.cc
index 74ed35e..ccb7016 100644
--- a/webrtc/p2p/base/jseptransport_unittest.cc
+++ b/webrtc/p2p/base/jseptransport_unittest.cc
@@ -13,7 +13,8 @@
 #include "webrtc/base/fakesslidentity.h"
 #include "webrtc/base/gunit.h"
 #include "webrtc/base/network.h"
-#include "webrtc/p2p/base/faketransportcontroller.h"
+#include "webrtc/p2p/base/fakedtlstransport.h"
+#include "webrtc/p2p/base/fakeicetransport.h"
 
 using cricket::JsepTransport;
 using cricket::TransportChannel;
@@ -34,15 +35,16 @@
   JsepTransportTest()
       : transport_(new JsepTransport("test content name", nullptr)) {}
   bool SetupChannel() {
-    fake_ice_channel_.reset(new FakeIceTransport(transport_->mid(), 1));
-    fake_dtls_transport_.reset(new FakeDtlsTransport(fake_ice_channel_.get()));
+    fake_ice_transport_.reset(new FakeIceTransport(transport_->mid(), 1));
+    fake_dtls_transport_.reset(
+        new FakeDtlsTransport(fake_ice_transport_.get()));
     return transport_->AddChannel(fake_dtls_transport_.get(), 1);
   }
   void DestroyChannel() { transport_->RemoveChannel(1); }
 
  protected:
   std::unique_ptr<FakeDtlsTransport> fake_dtls_transport_;
-  std::unique_ptr<FakeIceTransport> fake_ice_channel_;
+  std::unique_ptr<FakeIceTransport> fake_ice_transport_;
   std::unique_ptr<JsepTransport> transport_;
 };
 
@@ -53,16 +55,16 @@
   ASSERT_TRUE(transport_->SetLocalTransportDescription(
       local_desc, cricket::CA_OFFER, NULL));
   EXPECT_TRUE(SetupChannel());
-  EXPECT_EQ(cricket::ICEMODE_FULL, fake_dtls_transport_->remote_ice_mode());
-  EXPECT_EQ(kIceUfrag1, fake_dtls_transport_->ice_ufrag());
-  EXPECT_EQ(kIcePwd1, fake_dtls_transport_->ice_pwd());
+  EXPECT_EQ(cricket::ICEMODE_FULL, fake_ice_transport_->remote_ice_mode());
+  EXPECT_EQ(kIceUfrag1, fake_ice_transport_->ice_ufrag());
+  EXPECT_EQ(kIcePwd1, fake_ice_transport_->ice_pwd());
 
   cricket::TransportDescription remote_desc(kIceUfrag1, kIcePwd1);
   ASSERT_TRUE(transport_->SetRemoteTransportDescription(
       remote_desc, cricket::CA_ANSWER, NULL));
-  EXPECT_EQ(cricket::ICEMODE_FULL, fake_dtls_transport_->remote_ice_mode());
-  EXPECT_EQ(kIceUfrag1, fake_dtls_transport_->remote_ice_ufrag());
-  EXPECT_EQ(kIcePwd1, fake_dtls_transport_->remote_ice_pwd());
+  EXPECT_EQ(cricket::ICEMODE_FULL, fake_ice_transport_->remote_ice_mode());
+  EXPECT_EQ(kIceUfrag1, fake_ice_transport_->remote_ice_ufrag());
+  EXPECT_EQ(kIcePwd1, fake_ice_transport_->remote_ice_pwd());
 }
 
 // Verifies that IceCredentialsChanged returns true when either ufrag or pwd
diff --git a/webrtc/p2p/base/transportcontroller_unittest.cc b/webrtc/p2p/base/transportcontroller_unittest.cc
index 1fc71f1..6ea83a4 100644
--- a/webrtc/p2p/base/transportcontroller_unittest.cc
+++ b/webrtc/p2p/base/transportcontroller_unittest.cc
@@ -34,11 +34,10 @@
 namespace cricket {
 
 // Only subclassing from FakeTransportController because currently that's the
-// only way to have a TransportController with fake TransportChannels.
+// only way to have a TransportController with fake ICE/DTLS transports.
 //
-// TODO(deadbeef): Change this once the Transport/TransportChannel class
-// heirarchy is cleaned up, and we can pass a "TransportChannelFactory" or
-// something similar into TransportController.
+// TODO(deadbeef): Pass a "TransportFactory" or something similar into
+// TransportController, instead of using inheritance in this way for testing.
 typedef FakeTransportController TransportControllerForTest;
 
 class TransportControllerTest : public testing::Test,
@@ -71,13 +70,14 @@
         this, &TransportControllerTest::OnCandidatesGathered);
   }
 
-  FakeDtlsTransport* CreateChannel(const std::string& content, int component) {
-    DtlsTransportInternal* channel =
+  FakeDtlsTransport* CreateFakeDtlsTransport(const std::string& content,
+                                             int component) {
+    DtlsTransportInternal* transport =
         transport_controller_->CreateDtlsTransport_n(content, component);
-    return static_cast<FakeDtlsTransport*>(channel);
+    return static_cast<FakeDtlsTransport*>(transport);
   }
 
-  void DestroyChannel(const std::string& content, int component) {
+  void DestroyFakeDtlsTransport(const std::string& content, int component) {
     transport_controller_->DestroyDtlsTransport_n(content, component);
   }
 
@@ -91,20 +91,20 @@
   }
 
   // Used for thread hopping test.
-  void CreateChannelsAndCompleteConnectionOnNetworkThread() {
+  void CreateFakeDtlsTransportsAndCompleteConnectionOnNetworkThread() {
     network_thread_->Invoke<void>(
         RTC_FROM_HERE,
-        rtc::Bind(
-            &TransportControllerTest::CreateChannelsAndCompleteConnection_w,
-            this));
+        rtc::Bind(&TransportControllerTest::
+                      CreateFakeDtlsTransportsAndCompleteConnection_w,
+                  this));
   }
 
-  void CreateChannelsAndCompleteConnection_w() {
+  void CreateFakeDtlsTransportsAndCompleteConnection_w() {
     transport_controller_->SetIceRole(ICEROLE_CONTROLLING);
-    FakeDtlsTransport* channel1 = CreateChannel("audio", 1);
-    ASSERT_NE(nullptr, channel1);
-    FakeDtlsTransport* channel2 = CreateChannel("video", 1);
-    ASSERT_NE(nullptr, channel2);
+    FakeDtlsTransport* transport1 = CreateFakeDtlsTransport("audio", 1);
+    ASSERT_NE(nullptr, transport1);
+    FakeDtlsTransport* transport2 = CreateFakeDtlsTransport("video", 1);
+    ASSERT_NE(nullptr, transport2);
 
     TransportDescription local_desc(std::vector<std::string>(), kIceUfrag1,
                                     kIcePwd1, ICEMODE_FULL,
@@ -115,20 +115,20 @@
     transport_controller_->SetLocalTransportDescription("video", local_desc,
                                                         CA_OFFER, &err);
     transport_controller_->MaybeStartGathering();
-    channel1->ice_transport()->SignalCandidateGathered(
-        channel1->ice_transport(), CreateCandidate(1));
-    channel2->ice_transport()->SignalCandidateGathered(
-        channel2->ice_transport(), CreateCandidate(1));
-    channel1->SetCandidatesGatheringComplete();
-    channel2->SetCandidatesGatheringComplete();
-    channel1->SetConnectionCount(2);
-    channel2->SetConnectionCount(2);
-    channel1->SetReceiving(true);
-    channel2->SetReceiving(true);
-    channel1->SetWritable(true);
-    channel2->SetWritable(true);
-    channel1->SetConnectionCount(1);
-    channel2->SetConnectionCount(1);
+    transport1->fake_ice_transport()->SignalCandidateGathered(
+        transport1->fake_ice_transport(), CreateCandidate(1));
+    transport2->fake_ice_transport()->SignalCandidateGathered(
+        transport2->fake_ice_transport(), CreateCandidate(1));
+    transport1->fake_ice_transport()->SetCandidatesGatheringComplete();
+    transport2->fake_ice_transport()->SetCandidatesGatheringComplete();
+    transport1->fake_ice_transport()->SetConnectionCount(2);
+    transport2->fake_ice_transport()->SetConnectionCount(2);
+    transport1->SetReceiving(true);
+    transport2->SetReceiving(true);
+    transport1->SetWritable(true);
+    transport2->SetWritable(true);
+    transport1->fake_ice_transport()->SetConnectionCount(1);
+    transport2->fake_ice_transport()->SetConnectionCount(1);
   }
 
   IceConfig CreateIceConfig(
@@ -196,30 +196,30 @@
 };
 
 TEST_F(TransportControllerTest, TestSetIceConfig) {
-  FakeDtlsTransport* channel1 = CreateChannel("audio", 1);
-  ASSERT_NE(nullptr, channel1);
+  FakeDtlsTransport* transport1 = CreateFakeDtlsTransport("audio", 1);
+  ASSERT_NE(nullptr, transport1);
 
   transport_controller_->SetIceConfig(
       CreateIceConfig(1000, GATHER_CONTINUALLY));
-  EXPECT_EQ(1000, channel1->receiving_timeout());
-  EXPECT_TRUE(channel1->gather_continually());
+  EXPECT_EQ(1000, transport1->fake_ice_transport()->receiving_timeout());
+  EXPECT_TRUE(transport1->fake_ice_transport()->gather_continually());
 
   transport_controller_->SetIceConfig(
       CreateIceConfig(1000, GATHER_CONTINUALLY_AND_RECOVER));
-  // Test that value stored in controller is applied to new channels.
-  FakeDtlsTransport* channel2 = CreateChannel("video", 1);
-  ASSERT_NE(nullptr, channel2);
-  EXPECT_EQ(1000, channel2->receiving_timeout());
-  EXPECT_TRUE(channel2->gather_continually());
+  // Test that value stored in controller is applied to new transports.
+  FakeDtlsTransport* transport2 = CreateFakeDtlsTransport("video", 1);
+  ASSERT_NE(nullptr, transport2);
+  EXPECT_EQ(1000, transport2->fake_ice_transport()->receiving_timeout());
+  EXPECT_TRUE(transport2->fake_ice_transport()->gather_continually());
 }
 
 TEST_F(TransportControllerTest, TestSetSslMaxProtocolVersion) {
   EXPECT_TRUE(transport_controller_->SetSslMaxProtocolVersion(
       rtc::SSL_PROTOCOL_DTLS_12));
-  FakeDtlsTransport* channel = CreateChannel("audio", 1);
+  FakeDtlsTransport* transport = CreateFakeDtlsTransport("audio", 1);
 
-  ASSERT_NE(nullptr, channel);
-  EXPECT_EQ(rtc::SSL_PROTOCOL_DTLS_12, channel->ssl_max_protocol_version());
+  ASSERT_NE(nullptr, transport);
+  EXPECT_EQ(rtc::SSL_PROTOCOL_DTLS_12, transport->ssl_max_protocol_version());
 
   // Setting max version after transport is created should fail.
   EXPECT_FALSE(transport_controller_->SetSslMaxProtocolVersion(
@@ -227,47 +227,54 @@
 }
 
 TEST_F(TransportControllerTest, TestSetIceRole) {
-  FakeDtlsTransport* channel1 = CreateChannel("audio", 1);
-  ASSERT_NE(nullptr, channel1);
+  FakeDtlsTransport* transport1 = CreateFakeDtlsTransport("audio", 1);
+  ASSERT_NE(nullptr, transport1);
 
   transport_controller_->SetIceRole(ICEROLE_CONTROLLING);
-  EXPECT_EQ(ICEROLE_CONTROLLING, channel1->GetIceRole());
+  EXPECT_EQ(ICEROLE_CONTROLLING,
+            transport1->fake_ice_transport()->GetIceRole());
   transport_controller_->SetIceRole(ICEROLE_CONTROLLED);
-  EXPECT_EQ(ICEROLE_CONTROLLED, channel1->GetIceRole());
+  EXPECT_EQ(ICEROLE_CONTROLLED, transport1->fake_ice_transport()->GetIceRole());
 
-  // Test that value stored in controller is applied to new channels.
-  FakeDtlsTransport* channel2 = CreateChannel("video", 1);
-  ASSERT_NE(nullptr, channel2);
-  EXPECT_EQ(ICEROLE_CONTROLLED, channel2->GetIceRole());
+  // Test that value stored in controller is applied to new transports.
+  FakeDtlsTransport* transport2 = CreateFakeDtlsTransport("video", 1);
+  ASSERT_NE(nullptr, transport2);
+  EXPECT_EQ(ICEROLE_CONTROLLED, transport2->fake_ice_transport()->GetIceRole());
 }
 
-// Test that when one channel encounters a role conflict, the ICE role is
-// swapped on every channel.
+// Test that when one transport encounters a role conflict, the ICE role is
+// swapped on every transport.
 TEST_F(TransportControllerTest, TestIceRoleConflict) {
-  FakeDtlsTransport* channel1 = CreateChannel("audio", 1);
-  ASSERT_NE(nullptr, channel1);
-  FakeDtlsTransport* channel2 = CreateChannel("video", 1);
-  ASSERT_NE(nullptr, channel2);
+  FakeDtlsTransport* transport1 = CreateFakeDtlsTransport("audio", 1);
+  ASSERT_NE(nullptr, transport1);
+  FakeDtlsTransport* transport2 = CreateFakeDtlsTransport("video", 1);
+  ASSERT_NE(nullptr, transport2);
 
   transport_controller_->SetIceRole(ICEROLE_CONTROLLING);
-  EXPECT_EQ(ICEROLE_CONTROLLING, channel1->GetIceRole());
-  EXPECT_EQ(ICEROLE_CONTROLLING, channel2->GetIceRole());
+  EXPECT_EQ(ICEROLE_CONTROLLING,
+            transport1->fake_ice_transport()->GetIceRole());
+  EXPECT_EQ(ICEROLE_CONTROLLING,
+            transport2->fake_ice_transport()->GetIceRole());
 
-  channel1->ice_transport()->SignalRoleConflict(channel1->ice_transport());
-  EXPECT_EQ(ICEROLE_CONTROLLED, channel1->GetIceRole());
-  EXPECT_EQ(ICEROLE_CONTROLLED, channel2->GetIceRole());
+  transport1->fake_ice_transport()->SignalRoleConflict(
+      transport1->fake_ice_transport());
+  EXPECT_EQ(ICEROLE_CONTROLLED, transport1->fake_ice_transport()->GetIceRole());
+  EXPECT_EQ(ICEROLE_CONTROLLED, transport2->fake_ice_transport()->GetIceRole());
 
   // Should be able to handle a second role conflict. The remote endpoint can
   // change its role/tie-breaker when it does an ICE restart.
-  channel2->ice_transport()->SignalRoleConflict(channel2->ice_transport());
-  EXPECT_EQ(ICEROLE_CONTROLLING, channel1->GetIceRole());
-  EXPECT_EQ(ICEROLE_CONTROLLING, channel2->GetIceRole());
+  transport2->fake_ice_transport()->SignalRoleConflict(
+      transport2->fake_ice_transport());
+  EXPECT_EQ(ICEROLE_CONTROLLING,
+            transport1->fake_ice_transport()->GetIceRole());
+  EXPECT_EQ(ICEROLE_CONTROLLING,
+            transport2->fake_ice_transport()->GetIceRole());
 }
 
 TEST_F(TransportControllerTest, TestGetSslRole) {
-  FakeDtlsTransport* channel = CreateChannel("audio", 1);
-  ASSERT_NE(nullptr, channel);
-  ASSERT_TRUE(channel->SetSslRole(rtc::SSL_CLIENT));
+  FakeDtlsTransport* transport = CreateFakeDtlsTransport("audio", 1);
+  ASSERT_NE(nullptr, transport);
+  ASSERT_TRUE(transport->SetSslRole(rtc::SSL_CLIENT));
   rtc::SSLRole role;
   EXPECT_FALSE(transport_controller_->GetSslRole("video", &role));
   EXPECT_TRUE(transport_controller_->GetSslRole("audio", &role));
@@ -283,8 +290,8 @@
           rtc::SSLIdentity::Generate("session2", rtc::KT_DEFAULT)));
   rtc::scoped_refptr<rtc::RTCCertificate> returned_certificate;
 
-  FakeDtlsTransport* channel1 = CreateChannel("audio", 1);
-  ASSERT_NE(nullptr, channel1);
+  FakeDtlsTransport* transport1 = CreateFakeDtlsTransport("audio", 1);
+  ASSERT_NE(nullptr, transport1);
 
   EXPECT_TRUE(transport_controller_->SetLocalCertificate(certificate1));
   EXPECT_TRUE(transport_controller_->GetLocalCertificate(
@@ -296,9 +303,9 @@
   EXPECT_FALSE(transport_controller_->GetLocalCertificate(
       "video", &returned_certificate));
 
-  // Test that identity stored in controller is applied to new channels.
-  FakeDtlsTransport* channel2 = CreateChannel("video", 1);
-  ASSERT_NE(nullptr, channel2);
+  // Test that identity stored in controller is applied to new transports.
+  FakeDtlsTransport* transport2 = CreateFakeDtlsTransport("video", 1);
+  ASSERT_NE(nullptr, transport2);
   EXPECT_TRUE(transport_controller_->GetLocalCertificate(
       "video", &returned_certificate));
   EXPECT_EQ(certificate1->identity()->certificate().ToPEMString(),
@@ -311,10 +318,10 @@
 TEST_F(TransportControllerTest, TestGetRemoteSSLCertificate) {
   rtc::FakeSSLCertificate fake_certificate("fake_data");
 
-  FakeDtlsTransport* channel = CreateChannel("audio", 1);
-  ASSERT_NE(nullptr, channel);
+  FakeDtlsTransport* transport = CreateFakeDtlsTransport("audio", 1);
+  ASSERT_NE(nullptr, transport);
 
-  channel->SetRemoteSSLCertificate(&fake_certificate);
+  transport->SetRemoteSSLCertificate(&fake_certificate);
   std::unique_ptr<rtc::SSLCertificate> returned_certificate =
       transport_controller_->GetRemoteSSLCertificate("audio");
   EXPECT_TRUE(returned_certificate);
@@ -326,17 +333,17 @@
 }
 
 TEST_F(TransportControllerTest, TestSetLocalTransportDescription) {
-  FakeDtlsTransport* channel = CreateChannel("audio", 1);
-  ASSERT_NE(nullptr, channel);
+  FakeDtlsTransport* transport = CreateFakeDtlsTransport("audio", 1);
+  ASSERT_NE(nullptr, transport);
   TransportDescription local_desc(std::vector<std::string>(), kIceUfrag1,
                                   kIcePwd1, ICEMODE_FULL,
                                   CONNECTIONROLE_ACTPASS, nullptr);
   std::string err;
   EXPECT_TRUE(transport_controller_->SetLocalTransportDescription(
       "audio", local_desc, CA_OFFER, &err));
-  // Check that ICE ufrag and pwd were propagated to channel.
-  EXPECT_EQ(kIceUfrag1, channel->ice_ufrag());
-  EXPECT_EQ(kIcePwd1, channel->ice_pwd());
+  // Check that ICE ufrag and pwd were propagated to transport.
+  EXPECT_EQ(kIceUfrag1, transport->fake_ice_transport()->ice_ufrag());
+  EXPECT_EQ(kIcePwd1, transport->fake_ice_transport()->ice_pwd());
   // After setting local description, we should be able to start gathering
   // candidates.
   transport_controller_->MaybeStartGathering();
@@ -345,33 +352,33 @@
 }
 
 TEST_F(TransportControllerTest, TestSetRemoteTransportDescription) {
-  FakeDtlsTransport* channel = CreateChannel("audio", 1);
-  ASSERT_NE(nullptr, channel);
+  FakeDtlsTransport* transport = CreateFakeDtlsTransport("audio", 1);
+  ASSERT_NE(nullptr, transport);
   TransportDescription remote_desc(std::vector<std::string>(), kIceUfrag1,
                                    kIcePwd1, ICEMODE_FULL,
                                    CONNECTIONROLE_ACTPASS, nullptr);
   std::string err;
   EXPECT_TRUE(transport_controller_->SetRemoteTransportDescription(
       "audio", remote_desc, CA_OFFER, &err));
-  // Check that ICE ufrag and pwd were propagated to channel.
-  EXPECT_EQ(kIceUfrag1, channel->remote_ice_ufrag());
-  EXPECT_EQ(kIcePwd1, channel->remote_ice_pwd());
+  // Check that ICE ufrag and pwd were propagated to transport.
+  EXPECT_EQ(kIceUfrag1, transport->fake_ice_transport()->remote_ice_ufrag());
+  EXPECT_EQ(kIcePwd1, transport->fake_ice_transport()->remote_ice_pwd());
 }
 
 TEST_F(TransportControllerTest, TestAddRemoteCandidates) {
-  FakeDtlsTransport* channel = CreateChannel("audio", 1);
-  ASSERT_NE(nullptr, channel);
+  FakeDtlsTransport* transport = CreateFakeDtlsTransport("audio", 1);
+  ASSERT_NE(nullptr, transport);
   Candidates candidates;
   candidates.push_back(CreateCandidate(1));
   std::string err;
   EXPECT_TRUE(
       transport_controller_->AddRemoteCandidates("audio", candidates, &err));
-  EXPECT_EQ(1U, channel->remote_candidates().size());
+  EXPECT_EQ(1U, transport->fake_ice_transport()->remote_candidates().size());
 }
 
 TEST_F(TransportControllerTest, TestReadyForRemoteCandidates) {
-  FakeDtlsTransport* channel = CreateChannel("audio", 1);
-  ASSERT_NE(nullptr, channel);
+  FakeDtlsTransport* transport = CreateFakeDtlsTransport("audio", 1);
+  ASSERT_NE(nullptr, transport);
   // We expect to be ready for remote candidates only after local and remote
   // descriptions are set.
   EXPECT_FALSE(transport_controller_->ReadyForRemoteCandidates("audio"));
@@ -393,12 +400,12 @@
 }
 
 TEST_F(TransportControllerTest, TestGetStats) {
-  FakeDtlsTransport* channel1 = CreateChannel("audio", 1);
-  ASSERT_NE(nullptr, channel1);
-  FakeDtlsTransport* channel2 = CreateChannel("audio", 2);
-  ASSERT_NE(nullptr, channel2);
-  FakeDtlsTransport* channel3 = CreateChannel("video", 1);
-  ASSERT_NE(nullptr, channel3);
+  FakeDtlsTransport* transport1 = CreateFakeDtlsTransport("audio", 1);
+  ASSERT_NE(nullptr, transport1);
+  FakeDtlsTransport* transport2 = CreateFakeDtlsTransport("audio", 2);
+  ASSERT_NE(nullptr, transport2);
+  FakeDtlsTransport* transport3 = CreateFakeDtlsTransport("video", 1);
+  ASSERT_NE(nullptr, transport3);
 
   TransportStats stats;
   EXPECT_TRUE(transport_controller_->GetStats("audio", &stats));
@@ -406,113 +413,115 @@
   EXPECT_EQ(2U, stats.channel_stats.size());
 }
 
-// Test that transport gets destroyed when it has no more channels.
-TEST_F(TransportControllerTest, TestCreateAndDestroyChannel) {
-  FakeDtlsTransport* channel1 = CreateChannel("audio", 1);
-  ASSERT_NE(nullptr, channel1);
-  FakeDtlsTransport* channel2 = CreateChannel("audio", 1);
-  ASSERT_NE(nullptr, channel2);
-  ASSERT_EQ(channel1, channel2);
-  FakeDtlsTransport* channel3 = CreateChannel("audio", 2);
-  ASSERT_NE(nullptr, channel3);
+// Test that a "transport" from a stats perspective (combination of RTP/RTCP
+// transports) goes away when all references to its transports are gone.
+TEST_F(TransportControllerTest, TestCreateAndDestroyFakeDtlsTransport) {
+  FakeDtlsTransport* transport1 = CreateFakeDtlsTransport("audio", 1);
+  ASSERT_NE(nullptr, transport1);
+  FakeDtlsTransport* transport2 = CreateFakeDtlsTransport("audio", 1);
+  ASSERT_NE(nullptr, transport2);
+  ASSERT_EQ(transport1, transport2);
+  FakeDtlsTransport* transport3 = CreateFakeDtlsTransport("audio", 2);
+  ASSERT_NE(nullptr, transport3);
 
   // Using GetStats to check if transport is destroyed from an outside class's
   // perspective.
   TransportStats stats;
   EXPECT_TRUE(transport_controller_->GetStats("audio", &stats));
-  DestroyChannel("audio", 2);
-  DestroyChannel("audio", 1);
+  DestroyFakeDtlsTransport("audio", 2);
+  DestroyFakeDtlsTransport("audio", 1);
   EXPECT_TRUE(transport_controller_->GetStats("audio", &stats));
-  DestroyChannel("audio", 1);
+  DestroyFakeDtlsTransport("audio", 1);
   EXPECT_FALSE(transport_controller_->GetStats("audio", &stats));
 }
 
 TEST_F(TransportControllerTest, TestSignalConnectionStateFailed) {
   // Need controlling ICE role to get in failed state.
   transport_controller_->SetIceRole(ICEROLE_CONTROLLING);
-  FakeDtlsTransport* channel1 = CreateChannel("audio", 1);
-  ASSERT_NE(nullptr, channel1);
-  FakeDtlsTransport* channel2 = CreateChannel("video", 1);
-  ASSERT_NE(nullptr, channel2);
+  FakeDtlsTransport* transport1 = CreateFakeDtlsTransport("audio", 1);
+  ASSERT_NE(nullptr, transport1);
+  FakeDtlsTransport* transport2 = CreateFakeDtlsTransport("video", 1);
+  ASSERT_NE(nullptr, transport2);
 
-  // Should signal "failed" if any channel failed; channel is considered failed
+  // Should signal "failed" if any transport failed; transport is considered
+  // failed
   // if it previously had a connection but now has none, and gathering is
   // complete.
-  channel1->SetCandidatesGatheringComplete();
-  channel1->SetConnectionCount(1);
-  channel1->SetConnectionCount(0);
+  transport1->fake_ice_transport()->SetCandidatesGatheringComplete();
+  transport1->fake_ice_transport()->SetConnectionCount(1);
+  transport1->fake_ice_transport()->SetConnectionCount(0);
   EXPECT_EQ_WAIT(kIceConnectionFailed, connection_state_, kTimeout);
   EXPECT_EQ(1, connection_state_signal_count_);
 }
 
 TEST_F(TransportControllerTest, TestSignalConnectionStateConnected) {
   transport_controller_->SetIceRole(ICEROLE_CONTROLLING);
-  FakeDtlsTransport* channel1 = CreateChannel("audio", 1);
-  ASSERT_NE(nullptr, channel1);
-  FakeDtlsTransport* channel2 = CreateChannel("video", 1);
-  ASSERT_NE(nullptr, channel2);
-  FakeDtlsTransport* channel3 = CreateChannel("video", 2);
-  ASSERT_NE(nullptr, channel3);
+  FakeDtlsTransport* transport1 = CreateFakeDtlsTransport("audio", 1);
+  ASSERT_NE(nullptr, transport1);
+  FakeDtlsTransport* transport2 = CreateFakeDtlsTransport("video", 1);
+  ASSERT_NE(nullptr, transport2);
+  FakeDtlsTransport* transport3 = CreateFakeDtlsTransport("video", 2);
+  ASSERT_NE(nullptr, transport3);
 
-  // First, have one channel connect, and another fail, to ensure that
-  // the first channel connecting didn't trigger a "connected" state signal.
+  // First, have one transport connect, and another fail, to ensure that
+  // the first transport connecting didn't trigger a "connected" state signal.
   // We should only get a signal when all are connected.
-  channel1->SetConnectionCount(2);
-  channel1->SetWritable(true);
-  channel3->SetCandidatesGatheringComplete();
-  channel3->SetConnectionCount(1);
-  channel3->SetConnectionCount(0);
+  transport1->fake_ice_transport()->SetConnectionCount(2);
+  transport1->SetWritable(true);
+  transport3->fake_ice_transport()->SetCandidatesGatheringComplete();
+  transport3->fake_ice_transport()->SetConnectionCount(1);
+  transport3->fake_ice_transport()->SetConnectionCount(0);
   EXPECT_EQ_WAIT(kIceConnectionFailed, connection_state_, kTimeout);
   // Signal count of 1 means that the only signal emitted was "failed".
   EXPECT_EQ(1, connection_state_signal_count_);
 
-  // Destroy the failed channel to return to "connecting" state.
-  DestroyChannel("video", 2);
+  // Destroy the failed transport to return to "connecting" state.
+  DestroyFakeDtlsTransport("video", 2);
   EXPECT_EQ_WAIT(kIceConnectionConnecting, connection_state_, kTimeout);
   EXPECT_EQ(2, connection_state_signal_count_);
 
-  // Make the remaining channel reach a connected state.
-  channel2->SetConnectionCount(2);
-  channel2->SetWritable(true);
+  // Make the remaining transport reach a connected state.
+  transport2->fake_ice_transport()->SetConnectionCount(2);
+  transport2->SetWritable(true);
   EXPECT_EQ_WAIT(kIceConnectionConnected, connection_state_, kTimeout);
   EXPECT_EQ(3, connection_state_signal_count_);
 }
 
 TEST_F(TransportControllerTest, TestSignalConnectionStateComplete) {
   transport_controller_->SetIceRole(ICEROLE_CONTROLLING);
-  FakeDtlsTransport* channel1 = CreateChannel("audio", 1);
-  ASSERT_NE(nullptr, channel1);
-  FakeDtlsTransport* channel2 = CreateChannel("video", 1);
-  ASSERT_NE(nullptr, channel2);
-  FakeDtlsTransport* channel3 = CreateChannel("video", 2);
-  ASSERT_NE(nullptr, channel3);
+  FakeDtlsTransport* transport1 = CreateFakeDtlsTransport("audio", 1);
+  ASSERT_NE(nullptr, transport1);
+  FakeDtlsTransport* transport2 = CreateFakeDtlsTransport("video", 1);
+  ASSERT_NE(nullptr, transport2);
+  FakeDtlsTransport* transport3 = CreateFakeDtlsTransport("video", 2);
+  ASSERT_NE(nullptr, transport3);
 
   // Similar to above test, but we're now reaching the completed state, which
   // means only one connection per FakeDtlsTransport.
-  channel1->SetCandidatesGatheringComplete();
-  channel1->SetConnectionCount(1);
-  channel1->SetWritable(true);
-  channel3->SetCandidatesGatheringComplete();
-  channel3->SetConnectionCount(1);
-  channel3->SetConnectionCount(0);
+  transport1->fake_ice_transport()->SetCandidatesGatheringComplete();
+  transport1->fake_ice_transport()->SetConnectionCount(1);
+  transport1->SetWritable(true);
+  transport3->fake_ice_transport()->SetCandidatesGatheringComplete();
+  transport3->fake_ice_transport()->SetConnectionCount(1);
+  transport3->fake_ice_transport()->SetConnectionCount(0);
   EXPECT_EQ_WAIT(kIceConnectionFailed, connection_state_, kTimeout);
   // Signal count of 1 means that the only signal emitted was "failed".
   EXPECT_EQ(1, connection_state_signal_count_);
 
-  // Destroy the failed channel to return to "connecting" state.
-  DestroyChannel("video", 2);
+  // Destroy the failed transport to return to "connecting" state.
+  DestroyFakeDtlsTransport("video", 2);
   EXPECT_EQ_WAIT(kIceConnectionConnecting, connection_state_, kTimeout);
   EXPECT_EQ(2, connection_state_signal_count_);
 
-  // Make the remaining channel reach a connected state.
-  channel2->SetCandidatesGatheringComplete();
-  channel2->SetConnectionCount(2);
-  channel2->SetWritable(true);
+  // Make the remaining transport reach a connected state.
+  transport2->fake_ice_transport()->SetCandidatesGatheringComplete();
+  transport2->fake_ice_transport()->SetConnectionCount(2);
+  transport2->SetWritable(true);
   EXPECT_EQ_WAIT(kIceConnectionConnected, connection_state_, kTimeout);
   EXPECT_EQ(3, connection_state_signal_count_);
 
   // Finally, transition to completed state.
-  channel2->SetConnectionCount(1);
+  transport2->fake_ice_transport()->SetConnectionCount(1);
   EXPECT_EQ_WAIT(kIceConnectionCompleted, connection_state_, kTimeout);
   EXPECT_EQ(4, connection_state_signal_count_);
 }
@@ -520,24 +529,24 @@
 // Make sure that if we're "connected" and remove a transport, we stay in the
 // "connected" state.
 TEST_F(TransportControllerTest, TestDestroyTransportAndStayConnected) {
-  FakeDtlsTransport* channel1 = CreateChannel("audio", 1);
-  ASSERT_NE(nullptr, channel1);
-  FakeDtlsTransport* channel2 = CreateChannel("video", 1);
-  ASSERT_NE(nullptr, channel2);
+  FakeDtlsTransport* transport1 = CreateFakeDtlsTransport("audio", 1);
+  ASSERT_NE(nullptr, transport1);
+  FakeDtlsTransport* transport2 = CreateFakeDtlsTransport("video", 1);
+  ASSERT_NE(nullptr, transport2);
 
-  channel1->SetCandidatesGatheringComplete();
-  channel1->SetConnectionCount(2);
-  channel1->SetWritable(true);
-  channel2->SetCandidatesGatheringComplete();
-  channel2->SetConnectionCount(2);
-  channel2->SetWritable(true);
+  transport1->fake_ice_transport()->SetCandidatesGatheringComplete();
+  transport1->fake_ice_transport()->SetConnectionCount(2);
+  transport1->SetWritable(true);
+  transport2->fake_ice_transport()->SetCandidatesGatheringComplete();
+  transport2->fake_ice_transport()->SetConnectionCount(2);
+  transport2->SetWritable(true);
   EXPECT_EQ_WAIT(kIceConnectionConnected, connection_state_, kTimeout);
   EXPECT_EQ(1, connection_state_signal_count_);
 
-  // Destroy one channel, then "complete" the other one, so we reach
+  // Destroy one transport, then "complete" the other one, so we reach
   // a known state.
-  DestroyChannel("video", 1);
-  channel1->SetConnectionCount(1);
+  DestroyFakeDtlsTransport("video", 1);
+  transport1->fake_ice_transport()->SetConnectionCount(1);
   EXPECT_EQ_WAIT(kIceConnectionCompleted, connection_state_, kTimeout);
   // Signal count of 2 means the deletion didn't cause any unexpected signals
   EXPECT_EQ(2, connection_state_signal_count_);
@@ -546,75 +555,76 @@
 // If we destroy the last/only transport, we should simply transition to
 // "connecting".
 TEST_F(TransportControllerTest, TestDestroyLastTransportWhileConnected) {
-  FakeDtlsTransport* channel = CreateChannel("audio", 1);
-  ASSERT_NE(nullptr, channel);
+  FakeDtlsTransport* transport = CreateFakeDtlsTransport("audio", 1);
+  ASSERT_NE(nullptr, transport);
 
-  channel->SetCandidatesGatheringComplete();
-  channel->SetConnectionCount(2);
-  channel->SetWritable(true);
+  transport->fake_ice_transport()->SetCandidatesGatheringComplete();
+  transport->fake_ice_transport()->SetConnectionCount(2);
+  transport->SetWritable(true);
   EXPECT_EQ_WAIT(kIceConnectionConnected, connection_state_, kTimeout);
   EXPECT_EQ(1, connection_state_signal_count_);
 
-  DestroyChannel("audio", 1);
+  DestroyFakeDtlsTransport("audio", 1);
   EXPECT_EQ_WAIT(kIceConnectionConnecting, connection_state_, kTimeout);
   // Signal count of 2 means the deletion didn't cause any unexpected signals
   EXPECT_EQ(2, connection_state_signal_count_);
 }
 
 TEST_F(TransportControllerTest, TestSignalReceiving) {
-  FakeDtlsTransport* channel1 = CreateChannel("audio", 1);
-  ASSERT_NE(nullptr, channel1);
-  FakeDtlsTransport* channel2 = CreateChannel("video", 1);
-  ASSERT_NE(nullptr, channel2);
+  FakeDtlsTransport* transport1 = CreateFakeDtlsTransport("audio", 1);
+  ASSERT_NE(nullptr, transport1);
+  FakeDtlsTransport* transport2 = CreateFakeDtlsTransport("video", 1);
+  ASSERT_NE(nullptr, transport2);
 
-  // Should signal receiving as soon as any channel is receiving.
-  channel1->SetReceiving(true);
+  // Should signal receiving as soon as any transport is receiving.
+  transport1->SetReceiving(true);
   EXPECT_TRUE_WAIT(receiving_, kTimeout);
   EXPECT_EQ(1, receiving_signal_count_);
 
-  channel2->SetReceiving(true);
-  channel1->SetReceiving(false);
-  channel2->SetReceiving(false);
+  transport2->SetReceiving(true);
+  transport1->SetReceiving(false);
+  transport2->SetReceiving(false);
   EXPECT_TRUE_WAIT(!receiving_, kTimeout);
   EXPECT_EQ(2, receiving_signal_count_);
 }
 
 TEST_F(TransportControllerTest, TestSignalGatheringStateGathering) {
-  FakeDtlsTransport* channel = CreateChannel("audio", 1);
-  ASSERT_NE(nullptr, channel);
-  channel->ice_transport()->MaybeStartGathering();
+  FakeDtlsTransport* transport = CreateFakeDtlsTransport("audio", 1);
+  ASSERT_NE(nullptr, transport);
+  transport->fake_ice_transport()->MaybeStartGathering();
   // Should be in the gathering state as soon as any transport starts gathering.
   EXPECT_EQ_WAIT(kIceGatheringGathering, gathering_state_, kTimeout);
   EXPECT_EQ(1, gathering_state_signal_count_);
 }
 
 TEST_F(TransportControllerTest, TestSignalGatheringStateComplete) {
-  FakeDtlsTransport* channel1 = CreateChannel("audio", 1);
-  ASSERT_NE(nullptr, channel1);
-  FakeDtlsTransport* channel2 = CreateChannel("video", 1);
-  ASSERT_NE(nullptr, channel2);
-  FakeDtlsTransport* channel3 = CreateChannel("data", 1);
-  ASSERT_NE(nullptr, channel3);
+  FakeDtlsTransport* transport1 = CreateFakeDtlsTransport("audio", 1);
+  ASSERT_NE(nullptr, transport1);
+  FakeDtlsTransport* transport2 = CreateFakeDtlsTransport("video", 1);
+  ASSERT_NE(nullptr, transport2);
+  FakeDtlsTransport* transport3 = CreateFakeDtlsTransport("data", 1);
+  ASSERT_NE(nullptr, transport3);
 
-  channel3->ice_transport()->MaybeStartGathering();
+  transport3->fake_ice_transport()->MaybeStartGathering();
   EXPECT_EQ_WAIT(kIceGatheringGathering, gathering_state_, kTimeout);
   EXPECT_EQ(1, gathering_state_signal_count_);
 
-  // Have one channel finish gathering, then destroy it, to make sure gathering
+  // Have one transport finish gathering, then destroy it, to make sure
+  // gathering
   // completion wasn't signalled if only one transport finished gathering.
-  channel3->SetCandidatesGatheringComplete();
-  DestroyChannel("data", 1);
+  transport3->fake_ice_transport()->SetCandidatesGatheringComplete();
+  DestroyFakeDtlsTransport("data", 1);
   EXPECT_EQ_WAIT(kIceGatheringNew, gathering_state_, kTimeout);
   EXPECT_EQ(2, gathering_state_signal_count_);
 
-  // Make remaining channels start and then finish gathering.
-  channel1->ice_transport()->MaybeStartGathering();
-  channel2->ice_transport()->MaybeStartGathering();
+  // Make remaining transports start and then finish gathering.
+  transport1->fake_ice_transport()->MaybeStartGathering();
+  transport2->fake_ice_transport()->MaybeStartGathering();
   EXPECT_EQ_WAIT(kIceGatheringGathering, gathering_state_, kTimeout);
   EXPECT_EQ(3, gathering_state_signal_count_);
 
-  channel1->SetCandidatesGatheringComplete();
-  channel2->SetCandidatesGatheringComplete();
+  transport1->fake_ice_transport()->SetCandidatesGatheringComplete();
+  transport2->fake_ice_transport()->SetCandidatesGatheringComplete();
   EXPECT_EQ_WAIT(kIceGatheringComplete, gathering_state_, kTimeout);
   EXPECT_EQ(4, gathering_state_signal_count_);
 }
@@ -626,18 +636,18 @@
 TEST_F(TransportControllerTest,
        TestSignalingWhenLastIncompleteTransportDestroyed) {
   transport_controller_->SetIceRole(ICEROLE_CONTROLLING);
-  FakeDtlsTransport* channel1 = CreateChannel("audio", 1);
-  ASSERT_NE(nullptr, channel1);
-  FakeDtlsTransport* channel2 = CreateChannel("video", 1);
-  ASSERT_NE(nullptr, channel2);
+  FakeDtlsTransport* transport1 = CreateFakeDtlsTransport("audio", 1);
+  ASSERT_NE(nullptr, transport1);
+  FakeDtlsTransport* transport2 = CreateFakeDtlsTransport("video", 1);
+  ASSERT_NE(nullptr, transport2);
 
-  channel1->SetCandidatesGatheringComplete();
+  transport1->fake_ice_transport()->SetCandidatesGatheringComplete();
   EXPECT_EQ_WAIT(kIceGatheringGathering, gathering_state_, kTimeout);
   EXPECT_EQ(1, gathering_state_signal_count_);
 
-  channel1->SetConnectionCount(1);
-  channel1->SetWritable(true);
-  DestroyChannel("video", 1);
+  transport1->fake_ice_transport()->SetConnectionCount(1);
+  transport1->SetWritable(true);
+  DestroyFakeDtlsTransport("video", 1);
   EXPECT_EQ_WAIT(kIceConnectionCompleted, connection_state_, kTimeout);
   EXPECT_EQ(1, connection_state_signal_count_);
   EXPECT_EQ_WAIT(kIceGatheringComplete, gathering_state_, kTimeout);
@@ -645,8 +655,8 @@
 }
 
 TEST_F(TransportControllerTest, TestSignalCandidatesGathered) {
-  FakeDtlsTransport* channel = CreateChannel("audio", 1);
-  ASSERT_NE(nullptr, channel);
+  FakeDtlsTransport* transport = CreateFakeDtlsTransport("audio", 1);
+  ASSERT_NE(nullptr, transport);
 
   // Transport won't signal candidates until it has a local description.
   TransportDescription local_desc(std::vector<std::string>(), kIceUfrag1,
@@ -657,15 +667,15 @@
       "audio", local_desc, CA_OFFER, &err));
   transport_controller_->MaybeStartGathering();
 
-  channel->ice_transport()->SignalCandidateGathered(channel->ice_transport(),
-                                                    CreateCandidate(1));
+  transport->fake_ice_transport()->SignalCandidateGathered(
+      transport->fake_ice_transport(), CreateCandidate(1));
   EXPECT_EQ_WAIT(1, candidates_signal_count_, kTimeout);
   EXPECT_EQ(1U, candidates_["audio"].size());
 }
 
 TEST_F(TransportControllerTest, TestSignalingOccursOnSignalingThread) {
   CreateTransportControllerWithNetworkThread();
-  CreateChannelsAndCompleteConnectionOnNetworkThread();
+  CreateFakeDtlsTransportsAndCompleteConnectionOnNetworkThread();
 
   // connecting --> connected --> completed
   EXPECT_EQ_WAIT(kIceConnectionCompleted, connection_state_, kTimeout);
@@ -692,8 +702,8 @@
 // TODO(deadbeef): Remove this when these old versions of Chrome reach a low
 // enough population.
 TEST_F(TransportControllerTest, IceRoleRedeterminedOnIceRestartByDefault) {
-  FakeDtlsTransport* channel = CreateChannel("audio", 1);
-  ASSERT_NE(nullptr, channel);
+  FakeDtlsTransport* transport = CreateFakeDtlsTransport("audio", 1);
+  ASSERT_NE(nullptr, transport);
   std::string err;
   // Do an initial offer answer, so that the next offer is an ICE restart.
   transport_controller_->SetIceRole(ICEROLE_CONTROLLED);
@@ -707,7 +717,7 @@
                                   CONNECTIONROLE_ACTPASS, nullptr);
   EXPECT_TRUE(transport_controller_->SetLocalTransportDescription(
       "audio", local_desc, CA_ANSWER, &err));
-  EXPECT_EQ(ICEROLE_CONTROLLED, channel->GetIceRole());
+  EXPECT_EQ(ICEROLE_CONTROLLED, transport->fake_ice_transport()->GetIceRole());
 
   // The endpoint that initiated an ICE restart should take the controlling
   // role.
@@ -716,7 +726,7 @@
                                         CONNECTIONROLE_ACTPASS, nullptr);
   EXPECT_TRUE(transport_controller_->SetLocalTransportDescription(
       "audio", ice_restart_desc, CA_OFFER, &err));
-  EXPECT_EQ(ICEROLE_CONTROLLING, channel->GetIceRole());
+  EXPECT_EQ(ICEROLE_CONTROLLING, transport->fake_ice_transport()->GetIceRole());
 }
 
 // Test that if the TransportController was created with the
@@ -725,8 +735,8 @@
 TEST_F(TransportControllerTest, IceRoleNotRedetermined) {
   bool redetermine_role = false;
   transport_controller_.reset(new TransportControllerForTest(redetermine_role));
-  FakeDtlsTransport* channel = CreateChannel("audio", 1);
-  ASSERT_NE(nullptr, channel);
+  FakeDtlsTransport* transport = CreateFakeDtlsTransport("audio", 1);
+  ASSERT_NE(nullptr, transport);
   std::string err;
   // Do an initial offer answer, so that the next offer is an ICE restart.
   transport_controller_->SetIceRole(ICEROLE_CONTROLLED);
@@ -740,7 +750,7 @@
                                   CONNECTIONROLE_ACTPASS, nullptr);
   EXPECT_TRUE(transport_controller_->SetLocalTransportDescription(
       "audio", local_desc, CA_ANSWER, &err));
-  EXPECT_EQ(ICEROLE_CONTROLLED, channel->GetIceRole());
+  EXPECT_EQ(ICEROLE_CONTROLLED, transport->fake_ice_transport()->GetIceRole());
 
   // The endpoint that initiated an ICE restart should keep the existing role.
   TransportDescription ice_restart_desc(std::vector<std::string>(), kIceUfrag3,
@@ -748,13 +758,13 @@
                                         CONNECTIONROLE_ACTPASS, nullptr);
   EXPECT_TRUE(transport_controller_->SetLocalTransportDescription(
       "audio", ice_restart_desc, CA_OFFER, &err));
-  EXPECT_EQ(ICEROLE_CONTROLLED, channel->GetIceRole());
+  EXPECT_EQ(ICEROLE_CONTROLLED, transport->fake_ice_transport()->GetIceRole());
 }
 
-// Tests channel role is reversed after receiving ice-lite from remote.
+// Tests ICE role is reversed after receiving ice-lite from remote.
 TEST_F(TransportControllerTest, TestSetRemoteIceLiteInOffer) {
-  FakeDtlsTransport* channel = CreateChannel("audio", 1);
-  ASSERT_NE(nullptr, channel);
+  FakeDtlsTransport* transport = CreateFakeDtlsTransport("audio", 1);
+  ASSERT_NE(nullptr, transport);
   std::string err;
 
   transport_controller_->SetIceRole(ICEROLE_CONTROLLED);
@@ -767,39 +777,39 @@
   ASSERT_TRUE(transport_controller_->SetLocalTransportDescription(
       "audio", local_desc, CA_ANSWER, nullptr));
 
-  EXPECT_EQ(ICEROLE_CONTROLLING, channel->GetIceRole());
-  EXPECT_EQ(ICEMODE_LITE, channel->remote_ice_mode());
+  EXPECT_EQ(ICEROLE_CONTROLLING, transport->fake_ice_transport()->GetIceRole());
+  EXPECT_EQ(ICEMODE_LITE, transport->fake_ice_transport()->remote_ice_mode());
 }
 
 // Tests ice-lite in remote answer.
 TEST_F(TransportControllerTest, TestSetRemoteIceLiteInAnswer) {
-  FakeDtlsTransport* channel = CreateChannel("audio", 1);
-  ASSERT_NE(nullptr, channel);
+  FakeDtlsTransport* transport = CreateFakeDtlsTransport("audio", 1);
+  ASSERT_NE(nullptr, transport);
   std::string err;
 
   transport_controller_->SetIceRole(ICEROLE_CONTROLLING);
   TransportDescription local_desc(kIceUfrag1, kIcePwd1);
   ASSERT_TRUE(transport_controller_->SetLocalTransportDescription(
       "audio", local_desc, CA_OFFER, nullptr));
-  EXPECT_EQ(ICEROLE_CONTROLLING, channel->GetIceRole());
-  // Channels will be created in ICEFULL_MODE.
-  EXPECT_EQ(ICEMODE_FULL, channel->remote_ice_mode());
+  EXPECT_EQ(ICEROLE_CONTROLLING, transport->fake_ice_transport()->GetIceRole());
+  // Transports will be created in ICEFULL_MODE.
+  EXPECT_EQ(ICEMODE_FULL, transport->fake_ice_transport()->remote_ice_mode());
   TransportDescription remote_desc(std::vector<std::string>(), kIceUfrag1,
                                    kIcePwd1, ICEMODE_LITE, CONNECTIONROLE_NONE,
                                    nullptr);
   ASSERT_TRUE(transport_controller_->SetRemoteTransportDescription(
       "audio", remote_desc, CA_ANSWER, nullptr));
-  EXPECT_EQ(ICEROLE_CONTROLLING, channel->GetIceRole());
-  // After receiving remote description with ICEMODE_LITE, channel should
+  EXPECT_EQ(ICEROLE_CONTROLLING, transport->fake_ice_transport()->GetIceRole());
+  // After receiving remote description with ICEMODE_LITE, transport should
   // have mode set to ICEMODE_LITE.
-  EXPECT_EQ(ICEMODE_LITE, channel->remote_ice_mode());
+  EXPECT_EQ(ICEMODE_LITE, transport->fake_ice_transport()->remote_ice_mode());
 }
 
 // Tests SetNeedsIceRestartFlag and NeedsIceRestart, setting the flag and then
 // initiating an ICE restart for one of the transports.
 TEST_F(TransportControllerTest, NeedsIceRestart) {
-  CreateChannel("audio", 1);
-  CreateChannel("video", 1);
+  CreateFakeDtlsTransport("audio", 1);
+  CreateFakeDtlsTransport("video", 1);
 
   // Do initial offer/answer so there's something to restart.
   TransportDescription local_desc(kIceUfrag1, kIcePwd1);
diff --git a/webrtc/pc/channel.cc b/webrtc/pc/channel.cc
index a34e943..3c438f6 100644
--- a/webrtc/pc/channel.cc
+++ b/webrtc/pc/channel.cc
@@ -198,10 +198,14 @@
   // Stop signals from transport channels, but keep them alive because
   // media_channel may use them from a different thread.
   if (rtp_dtls_transport_) {
-    DisconnectFromTransport(rtp_dtls_transport_);
+    DisconnectFromDtlsTransport(rtp_dtls_transport_);
+  } else if (rtp_packet_transport_) {
+    DisconnectFromPacketTransport(rtp_packet_transport_);
   }
   if (rtcp_dtls_transport_) {
-    DisconnectFromTransport(rtcp_dtls_transport_);
+    DisconnectFromDtlsTransport(rtcp_dtls_transport_);
+  } else if (rtcp_packet_transport_) {
+    DisconnectFromPacketTransport(rtcp_packet_transport_);
   }
 
   // Clear pending read packets/messages.
@@ -210,26 +214,33 @@
 }
 
 bool BaseChannel::Init_w(DtlsTransportInternal* rtp_dtls_transport,
-                         DtlsTransportInternal* rtcp_dtls_transport) {
+                         DtlsTransportInternal* rtcp_dtls_transport,
+                         rtc::PacketTransportInterface* rtp_packet_transport,
+                         rtc::PacketTransportInterface* rtcp_packet_transport) {
   if (!network_thread_->Invoke<bool>(
           RTC_FROM_HERE, Bind(&BaseChannel::InitNetwork_n, this,
-                              rtp_dtls_transport, rtcp_dtls_transport))) {
+                              rtp_dtls_transport, rtcp_dtls_transport,
+                              rtp_packet_transport, rtcp_packet_transport))) {
     return false;
   }
-
-  // Both RTP and RTCP channels are set, we can call SetInterface on
-  // media channel and it can set network options.
-  RTC_DCHECK(worker_thread_->IsCurrent());
+  // Both RTP and RTCP channels should be set, we can call SetInterface on
+  // the media channel and it can set network options.
+  RTC_DCHECK_RUN_ON(worker_thread_);
   media_channel_->SetInterface(this);
   return true;
 }
 
-bool BaseChannel::InitNetwork_n(DtlsTransportInternal* rtp_dtls_transport,
-                                DtlsTransportInternal* rtcp_dtls_transport) {
+bool BaseChannel::InitNetwork_n(
+    DtlsTransportInternal* rtp_dtls_transport,
+    DtlsTransportInternal* rtcp_dtls_transport,
+    rtc::PacketTransportInterface* rtp_packet_transport,
+    rtc::PacketTransportInterface* rtcp_packet_transport) {
   RTC_DCHECK(network_thread_->IsCurrent());
-  SetTransports_n(rtp_dtls_transport, rtcp_dtls_transport);
+  SetTransports_n(rtp_dtls_transport, rtcp_dtls_transport, rtp_packet_transport,
+                  rtcp_packet_transport);
 
-  if (!SetDtlsSrtpCryptoSuites_n(rtp_dtls_transport_, false)) {
+  if (rtp_dtls_transport_ &&
+      !SetDtlsSrtpCryptoSuites_n(rtp_dtls_transport_, false)) {
     return false;
   }
   if (rtcp_dtls_transport_ &&
@@ -254,35 +265,56 @@
 
 void BaseChannel::SetTransports(DtlsTransportInternal* rtp_dtls_transport,
                                 DtlsTransportInternal* rtcp_dtls_transport) {
-  network_thread_->Invoke<void>(RTC_FROM_HERE,
-                                Bind(&BaseChannel::SetTransports_n, this,
-                                     rtp_dtls_transport, rtcp_dtls_transport));
+  network_thread_->Invoke<void>(
+      RTC_FROM_HERE,
+      Bind(&BaseChannel::SetTransports_n, this, rtp_dtls_transport,
+           rtcp_dtls_transport, rtp_dtls_transport, rtcp_dtls_transport));
 }
 
-void BaseChannel::SetTransports_n(DtlsTransportInternal* rtp_dtls_transport,
-                                  DtlsTransportInternal* rtcp_dtls_transport) {
-  RTC_DCHECK(network_thread_->IsCurrent());
-  if (!rtp_dtls_transport && !rtcp_dtls_transport) {
-    LOG(LS_ERROR) << "Setting nullptr to RTP Transport and RTCP Transport.";
-    return;
-  }
+void BaseChannel::SetTransports(
+    rtc::PacketTransportInterface* rtp_packet_transport,
+    rtc::PacketTransportInterface* rtcp_packet_transport) {
+  network_thread_->Invoke<void>(
+      RTC_FROM_HERE, Bind(&BaseChannel::SetTransports_n, this, nullptr, nullptr,
+                          rtp_packet_transport, rtcp_packet_transport));
+}
 
+void BaseChannel::SetTransports_n(
+    DtlsTransportInternal* rtp_dtls_transport,
+    DtlsTransportInternal* rtcp_dtls_transport,
+    rtc::PacketTransportInterface* rtp_packet_transport,
+    rtc::PacketTransportInterface* rtcp_packet_transport) {
+  RTC_DCHECK(network_thread_->IsCurrent());
+  // Validate some assertions about the input.
+  RTC_DCHECK(rtp_packet_transport);
+  RTC_DCHECK_EQ(NeedsRtcpTransport(), rtcp_packet_transport != nullptr);
+  if (rtp_dtls_transport || rtcp_dtls_transport) {
+    // DTLS/non-DTLS pointers should be to the same object.
+    RTC_DCHECK(rtp_dtls_transport == rtp_packet_transport);
+    RTC_DCHECK(rtcp_dtls_transport == rtcp_packet_transport);
+    // Can't go from non-DTLS to DTLS.
+    RTC_DCHECK(!rtp_packet_transport_ || rtp_dtls_transport_);
+  } else {
+    // Can't go from DTLS to non-DTLS.
+    RTC_DCHECK(!rtp_dtls_transport_);
+  }
+  // Transport names should be the same.
   if (rtp_dtls_transport && rtcp_dtls_transport) {
     RTC_DCHECK(rtp_dtls_transport->transport_name() ==
                rtcp_dtls_transport->transport_name());
-    RTC_DCHECK(NeedsRtcpTransport());
   }
-
-  std::string transport_name = rtp_dtls_transport
-                                   ? rtp_dtls_transport->transport_name()
-                                   : rtcp_dtls_transport->transport_name();
-  if (transport_name == transport_name_) {
-    // Nothing to do if transport name isn't changing.
+  std::string debug_name;
+  if (rtp_dtls_transport) {
+    transport_name_ = rtp_dtls_transport->transport_name();
+    debug_name = transport_name_;
+  } else {
+    debug_name = rtp_packet_transport->debug_name();
+  }
+  if (rtp_packet_transport == rtp_packet_transport_) {
+    // Nothing to do if transport isn't changing.
     return;
   }
 
-  transport_name_ = transport_name;
-
   // When using DTLS-SRTP, we must reset the SrtpFilter every time the transport
   // changes and wait until the DTLS handshake is complete to set the newly
   // negotiated parameters.
@@ -295,17 +327,15 @@
 
   // If this BaseChannel doesn't require RTCP mux and we haven't fully
   // negotiated RTCP mux, we need an RTCP transport.
-  if (NeedsRtcpTransport()) {
+  if (rtcp_packet_transport) {
     LOG(LS_INFO) << "Setting RTCP Transport for " << content_name() << " on "
-                 << transport_name << " transport " << rtcp_dtls_transport;
-    SetTransport_n(true, rtcp_dtls_transport);
-    RTC_DCHECK(rtcp_dtls_transport_);
+                 << debug_name << " transport " << rtcp_packet_transport;
+    SetTransport_n(true, rtcp_dtls_transport, rtcp_packet_transport);
   }
 
-  LOG(LS_INFO) << "Setting non-RTCP Transport for " << content_name() << " on "
-               << transport_name << " transport " << rtp_dtls_transport;
-  SetTransport_n(false, rtp_dtls_transport);
-  RTC_DCHECK(rtp_dtls_transport_);
+  LOG(LS_INFO) << "Setting RTP Transport for " << content_name() << " on "
+               << debug_name << " transport " << rtp_packet_transport;
+  SetTransport_n(false, rtp_dtls_transport, rtp_packet_transport);
 
   // Update aggregate writable/ready-to-send state between RTP and RTCP upon
   // setting new transport channels.
@@ -320,44 +350,58 @@
   // BaseChannel could have resulted in an error), but even so, we'll just
   // encounter the error again and update "ready to send" accordingly.
   SetTransportChannelReadyToSend(
-      false, rtp_dtls_transport_ && rtp_dtls_transport_->writable());
+      false, rtp_packet_transport_ && rtp_packet_transport_->writable());
   SetTransportChannelReadyToSend(
-      true, rtcp_dtls_transport_ && rtcp_dtls_transport_->writable());
+      true, rtcp_packet_transport_ && rtcp_packet_transport_->writable());
 }
 
-void BaseChannel::SetTransport_n(bool rtcp,
-                                 DtlsTransportInternal* new_transport) {
+void BaseChannel::SetTransport_n(
+    bool rtcp,
+    DtlsTransportInternal* new_dtls_transport,
+    rtc::PacketTransportInterface* new_packet_transport) {
   RTC_DCHECK(network_thread_->IsCurrent());
-  DtlsTransportInternal*& old_transport =
+  DtlsTransportInternal*& old_dtls_transport =
       rtcp ? rtcp_dtls_transport_ : rtp_dtls_transport_;
+  rtc::PacketTransportInterface*& old_packet_transport =
+      rtcp ? rtcp_packet_transport_ : rtp_packet_transport_;
 
-  if (!old_transport && !new_transport) {
+  if (!old_packet_transport && !new_packet_transport) {
     // Nothing to do.
     return;
   }
 
-  RTC_DCHECK(old_transport != new_transport);
-  if (old_transport) {
-    DisconnectFromTransport(old_transport);
+  RTC_DCHECK(old_packet_transport != new_packet_transport);
+  if (old_dtls_transport) {
+    DisconnectFromDtlsTransport(old_dtls_transport);
+  } else if (old_packet_transport) {
+    DisconnectFromPacketTransport(old_packet_transport);
   }
 
-  old_transport = new_transport;
+  old_packet_transport = new_packet_transport;
+  old_dtls_transport = new_dtls_transport;
 
-  if (new_transport) {
-    if (rtcp) {
-      RTC_CHECK(!(ShouldSetupDtlsSrtp_n() && srtp_filter_.IsActive()))
-          << "Setting RTCP for DTLS/SRTP after SrtpFilter is active "
-          << "should never happen.";
-    }
-    ConnectToTransport(new_transport);
-    auto& socket_options = rtcp ? rtcp_socket_options_ : socket_options_;
-    for (const auto& pair : socket_options) {
-      new_transport->SetOption(pair.first, pair.second);
-    }
+  // If there's no new transport, we're done after disconnecting from old one.
+  if (!new_packet_transport) {
+    return;
+  }
+
+  if (rtcp && new_dtls_transport) {
+    RTC_CHECK(!(ShouldSetupDtlsSrtp_n() && srtp_filter_.IsActive()))
+        << "Setting RTCP for DTLS/SRTP after SrtpFilter is active "
+        << "should never happen.";
+  }
+  if (new_dtls_transport) {
+    ConnectToDtlsTransport(new_dtls_transport);
+  } else {
+    ConnectToPacketTransport(new_packet_transport);
+  }
+  auto& socket_options = rtcp ? rtcp_socket_options_ : socket_options_;
+  for (const auto& pair : socket_options) {
+    new_packet_transport->SetOption(pair.first, pair.second);
   }
 }
 
-void BaseChannel::ConnectToTransport(DtlsTransportInternal* transport) {
+void BaseChannel::ConnectToDtlsTransport(DtlsTransportInternal* transport) {
   RTC_DCHECK(network_thread_->IsCurrent());
 
   transport->SignalWritableState.connect(this, &BaseChannel::OnWritableState);
@@ -369,7 +413,8 @@
       this, &BaseChannel::OnSelectedCandidatePairChanged);
 }
 
-void BaseChannel::DisconnectFromTransport(DtlsTransportInternal* transport) {
+void BaseChannel::DisconnectFromDtlsTransport(
+    DtlsTransportInternal* transport) {
   RTC_DCHECK(network_thread_->IsCurrent());
   OnSelectedCandidatePairChanged(transport->ice_transport(), nullptr, -1,
                                  false);
@@ -383,6 +428,24 @@
       this);
 }
 
+void BaseChannel::ConnectToPacketTransport(
+    rtc::PacketTransportInterface* transport) {
+  RTC_DCHECK_RUN_ON(network_thread_);
+  transport->SignalWritableState.connect(this, &BaseChannel::OnWritableState);
+  transport->SignalReadPacket.connect(this, &BaseChannel::OnPacketRead);
+  transport->SignalReadyToSend.connect(this, &BaseChannel::OnReadyToSend);
+  transport->SignalSentPacket.connect(this, &BaseChannel::SignalSentPacket_n);
+}
+
+void BaseChannel::DisconnectFromPacketTransport(
+    rtc::PacketTransportInterface* transport) {
+  RTC_DCHECK_RUN_ON(network_thread_);
+  transport->SignalWritableState.disconnect(this);
+  transport->SignalReadPacket.disconnect(this);
+  transport->SignalReadyToSend.disconnect(this);
+  transport->SignalSentPacket.disconnect(this);
+}
+
 bool BaseChannel::Enable(bool enable) {
   worker_thread_->Invoke<void>(
       RTC_FROM_HERE,
@@ -450,6 +513,9 @@
 
 bool BaseChannel::GetConnectionStats(ConnectionInfos* infos) {
   RTC_DCHECK(network_thread_->IsCurrent());
+  if (!rtp_dtls_transport_) {
+    return false;
+  }
   return rtp_dtls_transport_->ice_transport()->GetStats(infos);
 }
 
@@ -499,20 +565,20 @@
                              rtc::Socket::Option opt,
                              int value) {
   RTC_DCHECK(network_thread_->IsCurrent());
-  DtlsTransportInternal* transport = nullptr;
+  rtc::PacketTransportInterface* transport = nullptr;
   switch (type) {
     case ST_RTP:
-      transport = rtp_dtls_transport_;
+      transport = rtp_packet_transport_;
       socket_options_.push_back(
           std::pair<rtc::Socket::Option, int>(opt, value));
       break;
     case ST_RTCP:
-      transport = rtcp_dtls_transport_;
+      transport = rtcp_packet_transport_;
       rtcp_socket_options_.push_back(
           std::pair<rtc::Socket::Option, int>(opt, value));
       break;
   }
-  return transport ? transport->ice_transport()->SetOption(opt, value) : -1;
+  return transport ? transport->SetOption(opt, value) : -1;
 }
 
 bool BaseChannel::SetCryptoOptions(const rtc::CryptoOptions& crypto_options) {
@@ -521,8 +587,8 @@
 }
 
 void BaseChannel::OnWritableState(rtc::PacketTransportInterface* transport) {
-  RTC_DCHECK(transport == rtp_dtls_transport_ ||
-             transport == rtcp_dtls_transport_);
+  RTC_DCHECK(transport == rtp_packet_transport_ ||
+             transport == rtcp_packet_transport_);
   RTC_DCHECK(network_thread_->IsCurrent());
   UpdateWritableState_n();
 }
@@ -544,9 +610,9 @@
 }
 
 void BaseChannel::OnReadyToSend(rtc::PacketTransportInterface* transport) {
-  RTC_DCHECK(transport == rtp_dtls_transport_ ||
-             transport == rtcp_dtls_transport_);
-  SetTransportChannelReadyToSend(transport == rtcp_dtls_transport_, true);
+  RTC_DCHECK(transport == rtp_packet_transport_ ||
+             transport == rtcp_packet_transport_);
+  SetTransportChannelReadyToSend(transport == rtcp_packet_transport_, true);
 }
 
 void BaseChannel::OnDtlsState(DtlsTransportInternal* transport,
@@ -570,8 +636,10 @@
     CandidatePairInterface* selected_candidate_pair,
     int last_sent_packet_id,
     bool ready_to_send) {
-  RTC_DCHECK(ice_transport == rtp_dtls_transport_->ice_transport() ||
-             ice_transport == rtcp_dtls_transport_->ice_transport());
+  RTC_DCHECK((rtp_dtls_transport_ &&
+              ice_transport == rtp_dtls_transport_->ice_transport()) ||
+             (rtcp_dtls_transport_ &&
+              ice_transport == rtcp_dtls_transport_->ice_transport()));
   RTC_DCHECK(network_thread_->IsCurrent());
   selected_candidate_pair_ = selected_candidate_pair;
   std::string transport_name = ice_transport->transport_name();
@@ -600,8 +668,8 @@
 
   bool ready_to_send =
       (rtp_ready_to_send_ &&
-       // In the case of rtcp mux |rtcp_dtls_transport_| will be null.
-       (rtcp_ready_to_send_ || !rtcp_dtls_transport_));
+       // In the case of rtcp mux |rtcp_packet_transport_| will be null.
+       (rtcp_ready_to_send_ || !rtcp_packet_transport_));
 
   invoker_.AsyncInvoke<void>(
       RTC_FROM_HERE, worker_thread_,
@@ -611,7 +679,7 @@
 bool BaseChannel::PacketIsRtcp(const rtc::PacketTransportInterface* transport,
                                const char* data,
                                size_t len) {
-  return (transport == rtcp_dtls_transport_ ||
+  return (transport == rtcp_packet_transport_ ||
           rtcp_mux_filter_.DemuxRtcp(data, static_cast<int>(len)));
 }
 
@@ -640,9 +708,9 @@
   // packet before doing anything. (We might get RTCP packets that we don't
   // intend to send.) If we've negotiated RTCP mux, send RTCP over the RTP
   // transport.
-  DtlsTransportInternal* transport = (!rtcp || rtcp_mux_filter_.IsActive())
-                                         ? rtp_dtls_transport_
-                                         : rtcp_dtls_transport_;
+  rtc::PacketTransportInterface* transport =
+      (!rtcp || rtcp_mux_filter_.IsActive()) ? rtp_packet_transport_
+                                             : rtcp_packet_transport_;
   if (!transport || !transport->writable()) {
     return false;
   }
@@ -891,8 +959,8 @@
 }
 
 void BaseChannel::UpdateWritableState_n() {
-  if (rtp_dtls_transport_ && rtp_dtls_transport_->writable() &&
-      (!rtcp_dtls_transport_ || rtcp_dtls_transport_->writable())) {
+  if (rtp_packet_transport_ && rtp_packet_transport_->writable() &&
+      (!rtcp_packet_transport_ || rtcp_packet_transport_->writable())) {
     ChannelWritable_n();
   } else {
     ChannelNotWritable_n();
@@ -959,7 +1027,7 @@
 
   DtlsTransportInternal* transport =
       rtcp ? rtcp_dtls_transport_ : rtp_dtls_transport_;
-
+  RTC_DCHECK(transport);
   RTC_DCHECK(transport->IsDtlsActive());
 
   int selected_crypto_suite;
@@ -1110,7 +1178,7 @@
 bool BaseChannel::CheckSrtpConfig_n(const std::vector<CryptoParams>& cryptos,
                                     bool* dtls,
                                     std::string* error_desc) {
-  *dtls = rtp_dtls_transport_->IsDtlsActive();
+  *dtls = rtp_dtls_transport_ && rtp_dtls_transport_->IsDtlsActive();
   if (*dtls && !cryptos.empty()) {
     SafeSetError("Cryptos must be empty when DTLS is active.", error_desc);
     return false;
@@ -1195,9 +1263,9 @@
         LOG(LS_INFO) << "Enabling rtcp-mux for " << content_name()
                      << " by destroying RTCP transport for "
                      << transport_name();
-        if (rtcp_dtls_transport()) {
-          SetTransport_n(true, nullptr);
-          SignalRtcpMuxFullyActive(rtp_dtls_transport()->transport_name());
+        if (rtcp_packet_transport_) {
+          SetTransport_n(true, nullptr, nullptr);
+          SignalRtcpMuxFullyActive(transport_name_);
         }
         UpdateWritableState_n();
         SetTransportChannelReadyToSend(true, false);
@@ -1219,7 +1287,7 @@
   // a final answer.
   if (rtcp_mux_filter_.IsActive()) {
     // If the RTP transport is already writable, then so are we.
-    if (rtp_dtls_transport_->writable()) {
+    if (rtp_packet_transport_->writable()) {
       ChannelWritable_n();
     }
   }
@@ -1479,11 +1547,6 @@
   Deinit();
 }
 
-bool VoiceChannel::Init_w(DtlsTransportInternal* rtp_dtls_transport,
-                          DtlsTransportInternal* rtcp_dtls_transport) {
-  return BaseChannel::Init_w(rtp_dtls_transport, rtcp_dtls_transport);
-}
-
 bool VoiceChannel::SetAudioSend(uint32_t ssrc,
                                 bool enable,
                                 const AudioOptions* options,
@@ -1881,11 +1944,6 @@
                   rtcp_mux_required,
                   srtp_required) {}
 
-bool VideoChannel::Init_w(DtlsTransportInternal* rtp_dtls_transport,
-                          DtlsTransportInternal* rtcp_dtls_transport) {
-  return BaseChannel::Init_w(rtp_dtls_transport, rtcp_dtls_transport);
-}
-
 VideoChannel::~VideoChannel() {
   TRACE_EVENT0("webrtc", "VideoChannel::~VideoChannel");
   StopMediaMonitor();
@@ -2151,9 +2209,13 @@
   Deinit();
 }
 
-bool RtpDataChannel::Init_w(DtlsTransportInternal* rtp_dtls_transport,
-                            DtlsTransportInternal* rtcp_dtls_transport) {
-  if (!BaseChannel::Init_w(rtp_dtls_transport, rtcp_dtls_transport)) {
+bool RtpDataChannel::Init_w(
+    DtlsTransportInternal* rtp_dtls_transport,
+    DtlsTransportInternal* rtcp_dtls_transport,
+    rtc::PacketTransportInterface* rtp_packet_transport,
+    rtc::PacketTransportInterface* rtcp_packet_transport) {
+  if (!BaseChannel::Init_w(rtp_dtls_transport, rtcp_dtls_transport,
+                           rtp_packet_transport, rtcp_packet_transport)) {
     return false;
   }
   media_channel()->SignalDataReceived.connect(this,
diff --git a/webrtc/pc/channel.h b/webrtc/pc/channel.h
index e4848b2..0c95d93 100644
--- a/webrtc/pc/channel.h
+++ b/webrtc/pc/channel.h
@@ -30,6 +30,8 @@
 #include "webrtc/media/base/streamparams.h"
 #include "webrtc/media/base/videosinkinterface.h"
 #include "webrtc/media/base/videosourceinterface.h"
+#include "webrtc/p2p/base/dtlstransportinternal.h"
+#include "webrtc/p2p/base/packettransportinterface.h"
 #include "webrtc/p2p/base/transportcontroller.h"
 #include "webrtc/p2p/client/socketmonitor.h"
 #include "webrtc/pc/audiomonitor.h"
@@ -39,10 +41,6 @@
 #include "webrtc/pc/rtcpmuxfilter.h"
 #include "webrtc/pc/srtpfilter.h"
 
-namespace rtc {
-class PacketTransportInterface;
-}
-
 namespace webrtc {
 class AudioSinkInterface;
 }  // namespace webrtc
@@ -75,7 +73,6 @@
       public MediaChannel::NetworkInterface,
       public ConnectionStatsGetter {
  public:
-  // |rtcp| represents whether or not this channel uses RTCP.
   // If |srtp_required| is true, the channel will not send or receive any
   // RTP/RTCP packets without using SRTP (either using SDES or DTLS-SRTP).
   BaseChannel(rtc::Thread* worker_thread,
@@ -87,7 +84,9 @@
               bool srtp_required);
   virtual ~BaseChannel();
   bool Init_w(DtlsTransportInternal* rtp_dtls_transport,
-              DtlsTransportInternal* rtcp_dtls_transport);
+              DtlsTransportInternal* rtcp_dtls_transport,
+              rtc::PacketTransportInterface* rtp_packet_transport,
+              rtc::PacketTransportInterface* rtcp_packet_transport);
   // Deinit may be called multiple times and is simply ignored if it's already
   // done.
   void Deinit();
@@ -95,6 +94,7 @@
   rtc::Thread* worker_thread() const { return worker_thread_; }
   rtc::Thread* network_thread() const { return network_thread_; }
   const std::string& content_name() const { return content_name_; }
+  // TODO(deadbeef): This is redundant; remove this.
   const std::string& transport_name() const { return transport_name_; }
   bool enabled() const { return enabled_; }
 
@@ -113,8 +113,12 @@
   // RTCP muxing is not fully active yet).
   // |rtp_transport| and |rtcp_transport| must share the same transport name as
   // well.
+  // Can not start with "rtc::PacketTransportInterface" and switch to
+  // "DtlsTransportInternal", or vice-versa.
   void SetTransports(DtlsTransportInternal* rtp_dtls_transport,
                      DtlsTransportInternal* rtcp_dtls_transport);
+  void SetTransports(rtc::PacketTransportInterface* rtp_packet_transport,
+                     rtc::PacketTransportInterface* rtcp_packet_transport);
   bool PushdownLocalDescription(const SessionDescription* local_desc,
                                 ContentAction action,
                                 std::string* error_desc);
@@ -206,11 +210,15 @@
   virtual MediaChannel* media_channel() const { return media_channel_; }
 
   void SetTransports_n(DtlsTransportInternal* rtp_dtls_transport,
-                       DtlsTransportInternal* rtcp_dtls_transport);
+                       DtlsTransportInternal* rtcp_dtls_transport,
+                       rtc::PacketTransportInterface* rtp_packet_transport,
+                       rtc::PacketTransportInterface* rtcp_packet_transport);
 
   // This does not update writability or "ready-to-send" state; it just
   // disconnects from the old channel and connects to the new one.
-  void SetTransport_n(bool rtcp, DtlsTransportInternal* new_transport);
+  void SetTransport_n(bool rtcp,
+                      DtlsTransportInternal* new_dtls_transport,
+                      rtc::PacketTransportInterface* new_packet_transport);
 
   bool was_ever_writable() const { return was_ever_writable_; }
   void set_local_content_direction(MediaContentDirection direction) {
@@ -233,8 +241,10 @@
   bool IsReadyToSendMedia_w() const;
   rtc::Thread* signaling_thread() { return signaling_thread_; }
 
-  void ConnectToTransport(DtlsTransportInternal* transport);
-  void DisconnectFromTransport(DtlsTransportInternal* transport);
+  void ConnectToDtlsTransport(DtlsTransportInternal* transport);
+  void DisconnectFromDtlsTransport(DtlsTransportInternal* transport);
+  void ConnectToPacketTransport(rtc::PacketTransportInterface* transport);
+  void DisconnectFromPacketTransport(rtc::PacketTransportInterface* transport);
 
   void FlushRtcpMessages_n();
 
@@ -366,7 +376,9 @@
 
  private:
   bool InitNetwork_n(DtlsTransportInternal* rtp_dtls_transport,
-                     DtlsTransportInternal* rtcp_dtls_transport);
+                     DtlsTransportInternal* rtcp_dtls_transport,
+                     rtc::PacketTransportInterface* rtp_packet_transport,
+                     rtc::PacketTransportInterface* rtcp_packet_transport);
   void DisconnectTransportChannels_n();
   void SignalSentPacket_n(rtc::PacketTransportInterface* transport,
                           const rtc::SentPacket& sent_packet);
@@ -384,14 +396,20 @@
   const std::string content_name_;
   std::unique_ptr<ConnectionMonitor> connection_monitor_;
 
+  // Won't be set when using raw packet transports. SDP-specific thing.
   std::string transport_name_;
   // True if RTCP-multiplexing is required. In other words, no standalone RTCP
   // transport will ever be used for this channel.
   const bool rtcp_mux_required_;
 
+  // Separate DTLS/non-DTLS pointers to support using BaseChannel without DTLS.
+  // Temporary measure until more refactoring is done.
+  // If non-null, "X_dtls_transport_" will always equal "X_packet_transport_".
   DtlsTransportInternal* rtp_dtls_transport_ = nullptr;
-  std::vector<std::pair<rtc::Socket::Option, int> > socket_options_;
   DtlsTransportInternal* rtcp_dtls_transport_ = nullptr;
+  rtc::PacketTransportInterface* rtp_packet_transport_ = nullptr;
+  rtc::PacketTransportInterface* rtcp_packet_transport_ = nullptr;
+  std::vector<std::pair<rtc::Socket::Option, int> > socket_options_;
   std::vector<std::pair<rtc::Socket::Option, int> > rtcp_socket_options_;
   SrtpFilter srtp_filter_;
   RtcpMuxFilter rtcp_mux_filter_;
@@ -433,8 +451,6 @@
                bool rtcp_mux_required,
                bool srtp_required);
   ~VoiceChannel();
-  bool Init_w(DtlsTransportInternal* rtp_dtls_transport,
-              DtlsTransportInternal* rtcp_dtls_transport);
 
   // Configure sending media on the stream with SSRC |ssrc|
   // If there is only one sending stream SSRC 0 can be used.
@@ -552,8 +568,6 @@
                bool rtcp_mux_required,
                bool srtp_required);
   ~VideoChannel();
-  bool Init_w(DtlsTransportInternal* rtp_dtls_transport,
-              DtlsTransportInternal* rtcp_dtls_transport);
 
   // downcasts a MediaChannel
   VideoMediaChannel* media_channel() const override {
@@ -633,7 +647,9 @@
                  bool srtp_required);
   ~RtpDataChannel();
   bool Init_w(DtlsTransportInternal* rtp_dtls_transport,
-              DtlsTransportInternal* rtcp_dtls_transport);
+              DtlsTransportInternal* rtcp_dtls_transport,
+              rtc::PacketTransportInterface* rtp_packet_transport,
+              rtc::PacketTransportInterface* rtcp_packet_transport);
 
   virtual bool SendData(const SendDataParams& params,
                         const rtc::CopyOnWriteBuffer& payload,
diff --git a/webrtc/pc/channel_unittest.cc b/webrtc/pc/channel_unittest.cc
index d6401a5..57e7afb 100644
--- a/webrtc/pc/channel_unittest.cc
+++ b/webrtc/pc/channel_unittest.cc
@@ -21,8 +21,9 @@
 #include "webrtc/media/base/fakertp.h"
 #include "webrtc/media/base/mediachannel.h"
 #include "webrtc/media/base/testutils.h"
-#include "webrtc/p2p/base/dtlstransportinternal.h"
-#include "webrtc/p2p/base/faketransportcontroller.h"
+#include "webrtc/p2p/base/fakecandidatepair.h"
+#include "webrtc/p2p/base/fakedtlstransport.h"
+#include "webrtc/p2p/base/fakepackettransport.h"
 #include "webrtc/pc/channel.h"
 
 using cricket::CA_OFFER;
@@ -96,7 +97,10 @@
     SECURE = 0x4,
     SSRC_MUX = 0x8,
     DTLS = 0x10,
-    GCM_CIPHER = 0x20
+    GCM_CIPHER = 0x20,
+    // Use BaseChannel with PacketTransportInterface rather than
+    // DtlsTransportInternal.
+    RAW_PACKET_TRANSPORT = 0x40,
   };
 
   ChannelTest(bool verify_playout,
@@ -104,24 +108,15 @@
               rtc::ArrayView<const uint8_t> rtcp_data,
               NetworkIsWorker network_is_worker)
       : verify_playout_(verify_playout),
-        media_channel1_(NULL),
-        media_channel2_(NULL),
         rtp_packet_(rtp_data.data(), rtp_data.size()),
-        rtcp_packet_(rtcp_data.data(), rtcp_data.size()),
-        media_info_callbacks1_(),
-        media_info_callbacks2_() {
+        rtcp_packet_(rtcp_data.data(), rtcp_data.size()) {
     if (network_is_worker == NetworkIsWorker::Yes) {
       network_thread_ = rtc::Thread::Current();
     } else {
       network_thread_keeper_ = rtc::Thread::Create();
       network_thread_keeper_->SetName("Network", nullptr);
-      network_thread_keeper_->Start();
       network_thread_ = network_thread_keeper_.get();
     }
-    transport_controller1_.reset(new cricket::FakeTransportController(
-        network_thread_, cricket::ICEROLE_CONTROLLING));
-    transport_controller2_.reset(new cricket::FakeTransportController(
-        network_thread_, cricket::ICEROLE_CONTROLLED));
   }
 
   void CreateChannels(int flags1, int flags2) {
@@ -133,28 +128,101 @@
                       typename T::MediaChannel* ch2,
                       int flags1,
                       int flags2) {
+    // Network thread is started in CreateChannels, to allow the test to
+    // configure a fake clock before any threads are spawned and attempt to
+    // access the time.
+    if (network_thread_keeper_) {
+      network_thread_keeper_->Start();
+    }
     // Make sure RTCP_MUX_REQUIRED isn't set without RTCP_MUX.
-    ASSERT_NE(RTCP_MUX_REQUIRED, flags1 & (RTCP_MUX | RTCP_MUX_REQUIRED));
-    ASSERT_NE(RTCP_MUX_REQUIRED, flags2 & (RTCP_MUX | RTCP_MUX_REQUIRED));
+    RTC_DCHECK_NE(RTCP_MUX_REQUIRED, flags1 & (RTCP_MUX | RTCP_MUX_REQUIRED));
+    RTC_DCHECK_NE(RTCP_MUX_REQUIRED, flags2 & (RTCP_MUX | RTCP_MUX_REQUIRED));
+    // Make sure if using raw packet transports, they're used for both
+    // channels.
+    RTC_DCHECK_EQ(flags1 & RAW_PACKET_TRANSPORT, flags2 & RAW_PACKET_TRANSPORT);
     rtc::Thread* worker_thread = rtc::Thread::Current();
     media_channel1_ = ch1;
     media_channel2_ = ch2;
+    rtc::PacketTransportInterface* rtp1 = nullptr;
+    rtc::PacketTransportInterface* rtcp1 = nullptr;
+    rtc::PacketTransportInterface* rtp2 = nullptr;
+    rtc::PacketTransportInterface* rtcp2 = nullptr;
+    // Based on flags, create fake DTLS or raw packet transports.
+    if (flags1 & RAW_PACKET_TRANSPORT) {
+      fake_rtp_packet_transport1_.reset(
+          new rtc::FakePacketTransport("channel1_rtp"));
+      rtp1 = fake_rtp_packet_transport1_.get();
+      if (!(flags1 & RTCP_MUX_REQUIRED)) {
+        fake_rtcp_packet_transport1_.reset(
+            new rtc::FakePacketTransport("channel1_rtcp"));
+        rtcp1 = fake_rtcp_packet_transport1_.get();
+      }
+    } else {
+      // Confirmed to work with KT_RSA and KT_ECDSA.
+      fake_rtp_dtls_transport1_.reset(new cricket::FakeDtlsTransport(
+          "channel1", cricket::ICE_CANDIDATE_COMPONENT_RTP));
+      rtp1 = fake_rtp_dtls_transport1_.get();
+      if (!(flags1 & RTCP_MUX_REQUIRED)) {
+        fake_rtcp_dtls_transport1_.reset(new cricket::FakeDtlsTransport(
+            "channel1", cricket::ICE_CANDIDATE_COMPONENT_RTCP));
+        rtcp1 = fake_rtcp_dtls_transport1_.get();
+      }
+      if (flags1 & DTLS) {
+        auto cert1 =
+            rtc::RTCCertificate::Create(std::unique_ptr<rtc::SSLIdentity>(
+                rtc::SSLIdentity::Generate("session1", rtc::KT_DEFAULT)));
+        fake_rtp_dtls_transport1_->SetLocalCertificate(cert1);
+        if (fake_rtcp_dtls_transport1_) {
+          fake_rtcp_dtls_transport1_->SetLocalCertificate(cert1);
+        }
+      }
+    }
+    // Based on flags, create fake DTLS or raw packet transports.
+    if (flags2 & RAW_PACKET_TRANSPORT) {
+      fake_rtp_packet_transport2_.reset(
+          new rtc::FakePacketTransport("channel2_rtp"));
+      rtp2 = fake_rtp_packet_transport2_.get();
+      if (!(flags2 & RTCP_MUX_REQUIRED)) {
+        fake_rtcp_packet_transport2_.reset(
+            new rtc::FakePacketTransport("channel2_rtcp"));
+        rtcp2 = fake_rtcp_packet_transport2_.get();
+      }
+    } else {
+      // Confirmed to work with KT_RSA and KT_ECDSA.
+      fake_rtp_dtls_transport2_.reset(new cricket::FakeDtlsTransport(
+          "channel2", cricket::ICE_CANDIDATE_COMPONENT_RTP));
+      rtp2 = fake_rtp_dtls_transport2_.get();
+      if (!(flags2 & RTCP_MUX_REQUIRED)) {
+        fake_rtcp_dtls_transport2_.reset(new cricket::FakeDtlsTransport(
+            "channel2", cricket::ICE_CANDIDATE_COMPONENT_RTCP));
+        rtcp2 = fake_rtcp_dtls_transport2_.get();
+      }
+      if (flags2 & DTLS) {
+        auto cert2 =
+            rtc::RTCCertificate::Create(std::unique_ptr<rtc::SSLIdentity>(
+                rtc::SSLIdentity::Generate("session2", rtc::KT_DEFAULT)));
+        fake_rtp_dtls_transport2_->SetLocalCertificate(cert2);
+        if (fake_rtcp_dtls_transport2_) {
+          fake_rtcp_dtls_transport2_->SetLocalCertificate(cert2);
+        }
+      }
+    }
     channel1_.reset(
         CreateChannel(worker_thread, network_thread_, &media_engine_, ch1,
-                      transport_controller1_.get(), flags1));
+                      fake_rtp_dtls_transport1_.get(),
+                      fake_rtcp_dtls_transport1_.get(), rtp1, rtcp1, flags1));
     channel2_.reset(
         CreateChannel(worker_thread, network_thread_, &media_engine_, ch2,
-                      transport_controller2_.get(), flags2));
+                      fake_rtp_dtls_transport2_.get(),
+                      fake_rtcp_dtls_transport2_.get(), rtp2, rtcp2, flags2));
     channel1_->SignalMediaMonitor.connect(this,
                                           &ChannelTest<T>::OnMediaMonitor1);
     channel2_->SignalMediaMonitor.connect(this,
                                           &ChannelTest<T>::OnMediaMonitor2);
     channel1_->SignalRtcpMuxFullyActive.connect(
-        transport_controller1_.get(),
-        &cricket::FakeTransportController::DestroyRtcpTransport);
+        this, &ChannelTest<T>::OnRtcpMuxFullyActive1);
     channel2_->SignalRtcpMuxFullyActive.connect(
-        transport_controller2_.get(),
-        &cricket::FakeTransportController::DestroyRtcpTransport);
+        this, &ChannelTest<T>::OnRtcpMuxFullyActive2);
     if ((flags1 & DTLS) && (flags2 & DTLS)) {
       flags1 = (flags1 & ~SECURE);
       flags2 = (flags2 & ~SECURE);
@@ -166,19 +234,6 @@
     CopyContent(local_media_content1_, &remote_media_content1_);
     CopyContent(local_media_content2_, &remote_media_content2_);
 
-    if (flags1 & DTLS) {
-      // Confirmed to work with KT_RSA and KT_ECDSA.
-      transport_controller1_->SetLocalCertificate(
-          rtc::RTCCertificate::Create(std::unique_ptr<rtc::SSLIdentity>(
-              rtc::SSLIdentity::Generate("session1", rtc::KT_DEFAULT))));
-    }
-    if (flags2 & DTLS) {
-      // Confirmed to work with KT_RSA and KT_ECDSA.
-      transport_controller2_->SetLocalCertificate(
-          rtc::RTCCertificate::Create(std::unique_ptr<rtc::SSLIdentity>(
-              rtc::SSLIdentity::Generate("session2", rtc::KT_DEFAULT))));
-    }
-
     // Add stream information (SSRC) to the local content but not to the remote
     // content. This means that we per default know the SSRC of what we send but
     // not what we receive.
@@ -198,11 +253,12 @@
       rtc::Thread* network_thread,
       cricket::MediaEngineInterface* engine,
       typename T::MediaChannel* ch,
-      cricket::TransportController* transport_controller,
+      cricket::DtlsTransportInternal* fake_rtp_dtls_transport,
+      cricket::DtlsTransportInternal* fake_rtcp_dtls_transport,
+      rtc::PacketTransportInterface* fake_rtp_packet_transport,
+      rtc::PacketTransportInterface* fake_rtcp_packet_transport,
       int flags) {
-    rtc::Thread* signaling_thread =
-        transport_controller ? transport_controller->signaling_thread()
-                             : nullptr;
+    rtc::Thread* signaling_thread = rtc::Thread::Current();
     typename T::Channel* channel = new typename T::Channel(
         worker_thread, network_thread, signaling_thread, engine, ch,
         cricket::CN_AUDIO, (flags & RTCP_MUX_REQUIRED) != 0,
@@ -210,21 +266,41 @@
     rtc::CryptoOptions crypto_options;
     crypto_options.enable_gcm_crypto_suites = (flags & GCM_CIPHER) != 0;
     channel->SetCryptoOptions(crypto_options);
-    cricket::DtlsTransportInternal* rtp_dtls_transport =
-        transport_controller->CreateDtlsTransport(
-            channel->content_name(), cricket::ICE_CANDIDATE_COMPONENT_RTP);
-    cricket::DtlsTransportInternal* rtcp_dtls_transport = nullptr;
-    if (channel->NeedsRtcpTransport()) {
-      rtcp_dtls_transport = transport_controller->CreateDtlsTransport(
-          channel->content_name(), cricket::ICE_CANDIDATE_COMPONENT_RTCP);
+    if (!channel->NeedsRtcpTransport()) {
+      fake_rtcp_dtls_transport = nullptr;
     }
-    if (!channel->Init_w(rtp_dtls_transport, rtcp_dtls_transport)) {
+    if (!channel->Init_w(fake_rtp_dtls_transport, fake_rtcp_dtls_transport,
+                         fake_rtp_packet_transport,
+                         fake_rtcp_packet_transport)) {
       delete channel;
       channel = NULL;
     }
     return channel;
   }
 
+  void ConnectFakeTransports() {
+    network_thread_->Invoke<void>(RTC_FROM_HERE, [this] {
+      bool asymmetric = false;
+      // Depending on test flags, could be using DTLS or raw packet transport.
+      if (fake_rtp_dtls_transport1_ && fake_rtp_dtls_transport2_) {
+        fake_rtp_dtls_transport1_->SetDestination(
+            fake_rtp_dtls_transport2_.get(), asymmetric);
+      }
+      if (fake_rtcp_dtls_transport1_ && fake_rtcp_dtls_transport2_) {
+        fake_rtcp_dtls_transport1_->SetDestination(
+            fake_rtcp_dtls_transport2_.get(), asymmetric);
+      }
+      if (fake_rtp_packet_transport1_ && fake_rtp_packet_transport2_) {
+        fake_rtp_packet_transport1_->SetDestination(
+            fake_rtp_packet_transport2_.get(), asymmetric);
+      }
+      if (fake_rtcp_packet_transport1_ && fake_rtcp_packet_transport2_) {
+        fake_rtcp_packet_transport1_->SetDestination(
+            fake_rtcp_packet_transport2_.get(), asymmetric);
+      }
+    });
+  }
+
   bool SendInitiate() {
     bool result = channel1_->SetLocalContent(&local_media_content1_,
                                              CA_OFFER, NULL);
@@ -233,8 +309,7 @@
       result = channel2_->SetRemoteContent(&remote_media_content1_,
                                            CA_OFFER, NULL);
       if (result) {
-        transport_controller1_->Connect(transport_controller2_.get());
-
+        ConnectFakeTransports();
         result = channel2_->SetLocalContent(&local_media_content2_,
                                             CA_ANSWER, NULL);
       }
@@ -266,7 +341,7 @@
       channel2_->Enable(true);
       result = channel1_->SetRemoteContent(&remote_media_content2_,
                                            CA_PRANSWER, NULL);
-      transport_controller1_->Connect(transport_controller2_.get());
+      ConnectFakeTransports();
     }
     return result;
   }
@@ -280,9 +355,20 @@
     return result;
   }
 
-  bool SendTerminate() {
+  bool Terminate() {
     channel1_.reset();
     channel2_.reset();
+    fake_rtp_dtls_transport1_.reset();
+    fake_rtcp_dtls_transport1_.reset();
+    fake_rtp_dtls_transport2_.reset();
+    fake_rtcp_dtls_transport2_.reset();
+    fake_rtp_packet_transport1_.reset();
+    fake_rtcp_packet_transport1_.reset();
+    fake_rtp_packet_transport2_.reset();
+    fake_rtcp_packet_transport2_.reset();
+    if (network_thread_keeper_) {
+      network_thread_keeper_.reset();
+    }
     return true;
   }
 
@@ -293,24 +379,6 @@
     return channel1_->RemoveRecvStream(id);
   }
 
-  std::vector<cricket::DtlsTransportInternal*> GetChannels1() {
-    return transport_controller1_->channels_for_testing();
-  }
-
-  std::vector<cricket::DtlsTransportInternal*> GetChannels2() {
-    return transport_controller2_->channels_for_testing();
-  }
-
-  cricket::FakeDtlsTransport* GetFakeChannel1(int component) {
-    return transport_controller1_->GetFakeDtlsTransport_n(
-        channel1_->content_name(), component);
-  }
-
-  cricket::FakeDtlsTransport* GetFakeChannel2(int component) {
-    return transport_controller2_->GetFakeDtlsTransport_n(
-        channel2_->content_name(), component);
-  }
-
   void SendRtp1() {
     media_channel1_->SendRtp(rtp_packet_.data(), rtp_packet_.size(),
                              rtc::PacketOptions());
@@ -405,7 +473,11 @@
   // Returns true if so.
   bool CheckGcmCipher(typename T::Channel* channel, int flags) {
     int suite;
-    if (!channel->rtp_dtls_transport()->GetSrtpCryptoSuite(&suite)) {
+    cricket::FakeDtlsTransport* transport =
+        (channel == channel1_.get()) ? fake_rtp_dtls_transport1_.get()
+                                     : fake_rtp_dtls_transport2_.get();
+    RTC_DCHECK(transport);
+    if (!transport->GetSrtpCryptoSuite(&suite)) {
       return false;
     }
 
@@ -476,6 +548,12 @@
     RTC_DCHECK_EQ(channel, channel2_.get());
     media_info_callbacks2_++;
   }
+  void OnRtcpMuxFullyActive1(const std::string&) {
+    rtcp_mux_activated_callbacks1_++;
+  }
+  void OnRtcpMuxFullyActive2(const std::string&) {
+    rtcp_mux_activated_callbacks2_++;
+  }
 
   cricket::CandidatePairInterface* last_selected_candidate_pair() {
     return last_selected_candidate_pair_;
@@ -535,43 +613,37 @@
   // mux.
   void TestSetContentsRtcpMux() {
     CreateChannels(0, 0);
-    EXPECT_TRUE(channel1_->rtcp_dtls_transport() != NULL);
-    EXPECT_TRUE(channel2_->rtcp_dtls_transport() != NULL);
     typename T::Content content;
     CreateContent(0, kPcmuCodec, kH264Codec, &content);
     // Both sides agree on mux. Should no longer be a separate RTCP channel.
     content.set_rtcp_mux(true);
     EXPECT_TRUE(channel1_->SetLocalContent(&content, CA_OFFER, NULL));
     EXPECT_TRUE(channel1_->SetRemoteContent(&content, CA_ANSWER, NULL));
-    EXPECT_TRUE(channel1_->rtcp_dtls_transport() == NULL);
     // Only initiator supports mux. Should still have a separate RTCP channel.
     EXPECT_TRUE(channel2_->SetLocalContent(&content, CA_OFFER, NULL));
     content.set_rtcp_mux(false);
     EXPECT_TRUE(channel2_->SetRemoteContent(&content, CA_ANSWER, NULL));
-    EXPECT_TRUE(channel2_->rtcp_dtls_transport() != NULL);
   }
 
   // Test that SetLocalContent and SetRemoteContent properly set RTCP
   // mux when a provisional answer is received.
   void TestSetContentsRtcpMuxWithPrAnswer() {
     CreateChannels(0, 0);
-    EXPECT_TRUE(channel1_->rtcp_dtls_transport() != NULL);
-    EXPECT_TRUE(channel2_->rtcp_dtls_transport() != NULL);
     typename T::Content content;
     CreateContent(0, kPcmuCodec, kH264Codec, &content);
     content.set_rtcp_mux(true);
     EXPECT_TRUE(channel1_->SetLocalContent(&content, CA_OFFER, NULL));
     EXPECT_TRUE(channel1_->SetRemoteContent(&content, CA_PRANSWER, NULL));
-    EXPECT_TRUE(channel1_->rtcp_dtls_transport() != NULL);
+    // Both sides agree on mux. Should signal RTCP mux as fully activated.
+    EXPECT_EQ(0, rtcp_mux_activated_callbacks1_);
     EXPECT_TRUE(channel1_->SetRemoteContent(&content, CA_ANSWER, NULL));
-    // Both sides agree on mux. Should no longer be a separate RTCP channel.
-    EXPECT_TRUE(channel1_->rtcp_dtls_transport() == NULL);
+    EXPECT_EQ(1, rtcp_mux_activated_callbacks1_);
     // Only initiator supports mux. Should still have a separate RTCP channel.
     EXPECT_TRUE(channel2_->SetLocalContent(&content, CA_OFFER, NULL));
     content.set_rtcp_mux(false);
     EXPECT_TRUE(channel2_->SetRemoteContent(&content, CA_PRANSWER, NULL));
     EXPECT_TRUE(channel2_->SetRemoteContent(&content, CA_ANSWER, NULL));
-    EXPECT_TRUE(channel2_->rtcp_dtls_transport() != NULL);
+    EXPECT_EQ(0, rtcp_mux_activated_callbacks2_);
   }
 
   // Test that SetRemoteContent properly deals with a content update.
@@ -777,7 +849,7 @@
 
     EXPECT_TRUE(channel2_->SetRemoteContent(&content1, CA_OFFER, NULL));
     EXPECT_EQ(1u, media_channel2_->recv_streams().size());
-    transport_controller1_->Connect(transport_controller2_.get());
+    ConnectFakeTransports();
 
     // Channel 2 do not send anything.
     typename T::Content content2;
@@ -854,7 +926,7 @@
       EXPECT_FALSE(media_channel2_->playout());
     }
     EXPECT_FALSE(media_channel2_->sending());
-    transport_controller1_->Connect(transport_controller2_.get());
+    ConnectFakeTransports();
     if (verify_playout_) {
       EXPECT_TRUE(media_channel1_->playout());
     }
@@ -902,7 +974,7 @@
     EXPECT_TRUE(channel2_->SetRemoteContent(&content1, CA_OFFER, NULL));
     EXPECT_TRUE(channel2_->SetLocalContent(&content2, CA_PRANSWER, NULL));
     EXPECT_TRUE(channel1_->SetRemoteContent(&content2, CA_PRANSWER, NULL));
-    transport_controller1_->Connect(transport_controller2_.get());
+    ConnectFakeTransports();
 
     if (verify_playout_) {
       EXPECT_TRUE(media_channel1_->playout());
@@ -951,36 +1023,34 @@
 
     CreateChannels(0, 0);
 
-    cricket::DtlsTransportInternal* transport_channel1 =
-        channel1_->rtp_dtls_transport();
-    ASSERT_TRUE(transport_channel1);
     typename T::MediaChannel* media_channel1 =
         static_cast<typename T::MediaChannel*>(channel1_->media_channel());
     ASSERT_TRUE(media_channel1);
 
     media_channel1->set_num_network_route_changes(0);
-    network_thread_->Invoke<void>(RTC_FROM_HERE, [transport_channel1] {
+    network_thread_->Invoke<void>(RTC_FROM_HERE, [this] {
       // The transport channel becomes disconnected.
-      transport_channel1->ice_transport()->SignalSelectedCandidatePairChanged(
-          transport_channel1->ice_transport(), nullptr, -1, false);
+      fake_rtp_dtls_transport1_->ice_transport()
+          ->SignalSelectedCandidatePairChanged(
+              fake_rtp_dtls_transport1_->ice_transport(), nullptr, -1, false);
     });
     WaitForThreads();
     EXPECT_EQ(1, media_channel1->num_network_route_changes());
     EXPECT_FALSE(media_channel1->last_network_route().connected);
     media_channel1->set_num_network_route_changes(0);
 
-    network_thread_->Invoke<void>(RTC_FROM_HERE, [this, transport_channel1,
-                                                  media_channel1, kLocalNetId,
-                                                  kRemoteNetId, kLastPacketId] {
+    network_thread_->Invoke<void>(RTC_FROM_HERE, [this, media_channel1,
+                                                  kLocalNetId, kRemoteNetId,
+                                                  kLastPacketId] {
       // The transport channel becomes connected.
       rtc::SocketAddress local_address("192.168.1.1", 1000 /* port number */);
       rtc::SocketAddress remote_address("192.168.1.2", 2000 /* port number */);
-      std::unique_ptr<cricket::CandidatePairInterface> candidate_pair(
-          transport_controller1_->CreateFakeCandidatePair(
-              local_address, kLocalNetId, remote_address, kRemoteNetId));
-      transport_channel1->ice_transport()->SignalSelectedCandidatePairChanged(
-          transport_channel1->ice_transport(), candidate_pair.get(),
-          kLastPacketId, true);
+      auto candidate_pair = cricket::FakeCandidatePair::Create(
+          local_address, kLocalNetId, remote_address, kRemoteNetId);
+      fake_rtp_dtls_transport1_->ice_transport()
+          ->SignalSelectedCandidatePairChanged(
+              fake_rtp_dtls_transport1_->ice_transport(), candidate_pair.get(),
+              kLastPacketId, true);
     });
     WaitForThreads();
     EXPECT_EQ(1, media_channel1->num_network_route_changes());
@@ -1032,7 +1102,7 @@
                    RTCP_MUX, RTCP_MUX);
     EXPECT_TRUE(SendInitiate());
     EXPECT_TRUE(SendAccept());
-    EXPECT_TRUE(SendTerminate());
+    EXPECT_TRUE(Terminate());
   }
 
   // Send voice RTP data to the other side and ensure it gets there.
@@ -1040,8 +1110,8 @@
     CreateChannels(RTCP_MUX | RTCP_MUX_REQUIRED, RTCP_MUX | RTCP_MUX_REQUIRED);
     EXPECT_TRUE(SendInitiate());
     EXPECT_TRUE(SendAccept());
-    EXPECT_EQ(1U, GetChannels1().size());
-    EXPECT_EQ(1U, GetChannels2().size());
+    EXPECT_FALSE(channel1_->NeedsRtcpTransport());
+    EXPECT_FALSE(channel2_->NeedsRtcpTransport());
     SendRtp1();
     SendRtp2();
     WaitForThreads();
@@ -1069,8 +1139,8 @@
     CreateChannels(0, 0);
     EXPECT_TRUE(SendInitiate());
     EXPECT_TRUE(SendAccept());
-    EXPECT_EQ(2U, GetChannels1().size());
-    EXPECT_EQ(2U, GetChannels2().size());
+    EXPECT_TRUE(channel1_->NeedsRtcpTransport());
+    EXPECT_TRUE(channel2_->NeedsRtcpTransport());
     SendRtcp1();
     SendRtcp2();
     WaitForThreads();
@@ -1085,8 +1155,8 @@
     CreateChannels(RTCP_MUX, 0);
     EXPECT_TRUE(SendInitiate());
     EXPECT_TRUE(SendAccept());
-    EXPECT_EQ(2U, GetChannels1().size());
-    EXPECT_EQ(2U, GetChannels2().size());
+    EXPECT_TRUE(channel1_->NeedsRtcpTransport());
+    EXPECT_TRUE(channel2_->NeedsRtcpTransport());
     SendRtcp1();
     SendRtcp2();
     WaitForThreads();
@@ -1100,10 +1170,12 @@
   void SendRtcpMuxToRtcpMux() {
     CreateChannels(RTCP_MUX, RTCP_MUX);
     EXPECT_TRUE(SendInitiate());
-    EXPECT_EQ(2U, GetChannels1().size());
-    EXPECT_EQ(1U, GetChannels2().size());
+    EXPECT_TRUE(channel1_->NeedsRtcpTransport());
+    EXPECT_FALSE(channel2_->NeedsRtcpTransport());
+    EXPECT_EQ(0, rtcp_mux_activated_callbacks1_);
     EXPECT_TRUE(SendAccept());
-    EXPECT_EQ(1U, GetChannels1().size());
+    EXPECT_FALSE(channel1_->NeedsRtcpTransport());
+    EXPECT_EQ(1, rtcp_mux_activated_callbacks1_);
     SendRtp1();
     SendRtp2();
     SendRtcp1();
@@ -1124,8 +1196,8 @@
   void SendRequireRtcpMuxToRtcpMux() {
     CreateChannels(RTCP_MUX | RTCP_MUX_REQUIRED, RTCP_MUX);
     EXPECT_TRUE(SendInitiate());
-    EXPECT_EQ(1U, GetChannels1().size());
-    EXPECT_EQ(1U, GetChannels2().size());
+    EXPECT_FALSE(channel1_->NeedsRtcpTransport());
+    EXPECT_FALSE(channel2_->NeedsRtcpTransport());
     EXPECT_TRUE(SendAccept());
     SendRtp1();
     SendRtp2();
@@ -1147,10 +1219,12 @@
   void SendRtcpMuxToRequireRtcpMux() {
     CreateChannels(RTCP_MUX, RTCP_MUX | RTCP_MUX_REQUIRED);
     EXPECT_TRUE(SendInitiate());
-    EXPECT_EQ(2U, GetChannels1().size());
-    EXPECT_EQ(1U, GetChannels2().size());
+    EXPECT_TRUE(channel1_->NeedsRtcpTransport());
+    EXPECT_FALSE(channel2_->NeedsRtcpTransport());
+    EXPECT_EQ(0, rtcp_mux_activated_callbacks1_);
     EXPECT_TRUE(SendAccept());
-    EXPECT_EQ(1U, GetChannels1().size());
+    EXPECT_FALSE(channel1_->NeedsRtcpTransport());
+    EXPECT_EQ(1, rtcp_mux_activated_callbacks1_);
     SendRtp1();
     SendRtp2();
     SendRtcp1();
@@ -1171,10 +1245,10 @@
   void SendRequireRtcpMuxToRequireRtcpMux() {
     CreateChannels(RTCP_MUX | RTCP_MUX_REQUIRED, RTCP_MUX | RTCP_MUX_REQUIRED);
     EXPECT_TRUE(SendInitiate());
-    EXPECT_EQ(1U, GetChannels1().size());
-    EXPECT_EQ(1U, GetChannels2().size());
+    EXPECT_FALSE(channel1_->NeedsRtcpTransport());
+    EXPECT_FALSE(channel2_->NeedsRtcpTransport());
     EXPECT_TRUE(SendAccept());
-    EXPECT_EQ(1U, GetChannels1().size());
+    EXPECT_FALSE(channel1_->NeedsRtcpTransport());
     SendRtp1();
     SendRtp2();
     SendRtcp1();
@@ -1195,8 +1269,8 @@
   void SendRequireRtcpMuxToNoRtcpMux() {
     CreateChannels(RTCP_MUX | RTCP_MUX_REQUIRED, 0);
     EXPECT_TRUE(SendInitiate());
-    EXPECT_EQ(1U, GetChannels1().size());
-    EXPECT_EQ(2U, GetChannels2().size());
+    EXPECT_FALSE(channel1_->NeedsRtcpTransport());
+    EXPECT_TRUE(channel2_->NeedsRtcpTransport());
     EXPECT_FALSE(SendAccept());
   }
 
@@ -1204,8 +1278,8 @@
   void SendEarlyRtcpMuxToRtcp() {
     CreateChannels(RTCP_MUX, 0);
     EXPECT_TRUE(SendInitiate());
-    EXPECT_EQ(2U, GetChannels1().size());
-    EXPECT_EQ(2U, GetChannels2().size());
+    EXPECT_TRUE(channel1_->NeedsRtcpTransport());
+    EXPECT_TRUE(channel2_->NeedsRtcpTransport());
 
     // RTCP can be sent before the call is accepted, if the transport is ready.
     // It should not be muxed though, as the remote side doesn't support mux.
@@ -1222,7 +1296,7 @@
 
     // Complete call setup and ensure everything is still OK.
     EXPECT_TRUE(SendAccept());
-    EXPECT_EQ(2U, GetChannels1().size());
+    EXPECT_TRUE(channel1_->NeedsRtcpTransport());
     SendRtcp1();
     SendRtcp2();
     WaitForThreads();
@@ -1237,8 +1311,8 @@
   void SendEarlyRtcpMuxToRtcpMux() {
     CreateChannels(RTCP_MUX, RTCP_MUX);
     EXPECT_TRUE(SendInitiate());
-    EXPECT_EQ(2U, GetChannels1().size());
-    EXPECT_EQ(1U, GetChannels2().size());
+    EXPECT_TRUE(channel1_->NeedsRtcpTransport());
+    EXPECT_FALSE(channel2_->NeedsRtcpTransport());
 
     // RTCP can't be sent yet, since the RTCP transport isn't writable, and
     // we haven't yet received the accept that says we should mux.
@@ -1253,8 +1327,10 @@
     EXPECT_TRUE(CheckRtcp1());
 
     // Complete call setup and ensure everything is still OK.
+    EXPECT_EQ(0, rtcp_mux_activated_callbacks1_);
     EXPECT_TRUE(SendAccept());
-    EXPECT_EQ(1U, GetChannels1().size());
+    EXPECT_FALSE(channel1_->NeedsRtcpTransport());
+    EXPECT_EQ(1, rtcp_mux_activated_callbacks1_);
     SendRtcp1();
     SendRtcp2();
     WaitForThreads();
@@ -1263,10 +1339,13 @@
   }
 
   // Test that we properly send SRTP with RTCP in both directions.
-  // You can pass in DTLS and/or RTCP_MUX as flags.
+  // You can pass in DTLS, RTCP_MUX, GCM_CIPHER and RAW_PACKET_TRANSPORT as
+  // flags.
   void SendSrtpToSrtp(int flags1_in = 0, int flags2_in = 0) {
-    RTC_CHECK((flags1_in & ~(RTCP_MUX | DTLS | GCM_CIPHER)) == 0);
-    RTC_CHECK((flags2_in & ~(RTCP_MUX | DTLS | GCM_CIPHER)) == 0);
+    RTC_CHECK((flags1_in &
+               ~(RTCP_MUX | DTLS | GCM_CIPHER | RAW_PACKET_TRANSPORT)) == 0);
+    RTC_CHECK((flags2_in &
+               ~(RTCP_MUX | DTLS | GCM_CIPHER | RAW_PACKET_TRANSPORT)) == 0);
 
     int flags1 = SECURE | flags1_in;
     int flags2 = SECURE | flags2_in;
@@ -1342,8 +1421,8 @@
       EXPECT_TRUE(SendProvisionalAnswer());
       EXPECT_TRUE(channel1_->secure());
       EXPECT_TRUE(channel2_->secure());
-      EXPECT_EQ(2U, GetChannels1().size());
-      EXPECT_EQ(2U, GetChannels2().size());
+      EXPECT_TRUE(channel1_->NeedsRtcpTransport());
+      EXPECT_TRUE(channel2_->NeedsRtcpTransport());
       WaitForThreads();  // Wait for 'sending' flag go through network thread.
       SendCustomRtcp1(kSsrc1);
       SendCustomRtp1(kSsrc1, ++sequence_number1_1);
@@ -1359,9 +1438,13 @@
       EXPECT_TRUE(CheckCustomRtp1(kSsrc2, sequence_number2_2));
 
       // Complete call setup and ensure everything is still OK.
+      EXPECT_EQ(0, rtcp_mux_activated_callbacks1_);
+      EXPECT_EQ(0, rtcp_mux_activated_callbacks2_);
       EXPECT_TRUE(SendFinalAnswer());
-      EXPECT_EQ(1U, GetChannels1().size());
-      EXPECT_EQ(1U, GetChannels2().size());
+      EXPECT_FALSE(channel1_->NeedsRtcpTransport());
+      EXPECT_FALSE(channel2_->NeedsRtcpTransport());
+      EXPECT_EQ(1, rtcp_mux_activated_callbacks1_);
+      EXPECT_EQ(1, rtcp_mux_activated_callbacks2_);
       EXPECT_TRUE(channel1_->secure());
       EXPECT_TRUE(channel2_->secure());
       SendCustomRtcp1(kSsrc1);
@@ -1427,8 +1510,8 @@
     CreateChannels(RTCP_MUX | RTCP_MUX_REQUIRED, RTCP_MUX | RTCP_MUX_REQUIRED);
     EXPECT_TRUE(SendInitiate());
     EXPECT_TRUE(SendAccept());
-    EXPECT_EQ(1U, GetChannels1().size());
-    EXPECT_EQ(1U, GetChannels2().size());
+    EXPECT_FALSE(channel1_->NeedsRtcpTransport());
+    EXPECT_FALSE(channel2_->NeedsRtcpTransport());
     SendRtp1();
     SendRtp2();
     WaitForThreads();
@@ -1438,8 +1521,9 @@
     EXPECT_TRUE(CheckNoRtp2());
 
     // Lose writability, which should fail.
-    network_thread_->Invoke<void>(
-        RTC_FROM_HERE, [this] { GetFakeChannel1(1)->SetWritable(false); });
+    network_thread_->Invoke<void>(RTC_FROM_HERE, [this] {
+      fake_rtp_dtls_transport1_->SetWritable(false);
+    });
     SendRtp1();
     SendRtp2();
     WaitForThreads();
@@ -1447,8 +1531,9 @@
     EXPECT_TRUE(CheckNoRtp2());
 
     // Regain writability
-    network_thread_->Invoke<void>(
-        RTC_FROM_HERE, [this] { GetFakeChannel1(1)->SetWritable(true); });
+    network_thread_->Invoke<void>(RTC_FROM_HERE, [this] {
+      fake_rtp_dtls_transport1_->SetWritable(true);
+    });
     EXPECT_TRUE(media_channel1_->sending());
     SendRtp1();
     SendRtp2();
@@ -1459,8 +1544,10 @@
     EXPECT_TRUE(CheckNoRtp2());
 
     // Lose writability completely
-    network_thread_->Invoke<void>(
-        RTC_FROM_HERE, [this] { GetFakeChannel1(1)->SetDestination(nullptr); });
+    network_thread_->Invoke<void>(RTC_FROM_HERE, [this] {
+      bool asymmetric = true;
+      fake_rtp_dtls_transport1_->SetDestination(nullptr, asymmetric);
+    });
     EXPECT_TRUE(media_channel1_->sending());
 
     // Should fail also.
@@ -1473,7 +1560,9 @@
 
     // Gain writability back
     network_thread_->Invoke<void>(RTC_FROM_HERE, [this] {
-      GetFakeChannel1(1)->SetDestination(GetFakeChannel2(1));
+      bool asymmetric = true;
+      fake_rtp_dtls_transport1_->SetDestination(fake_rtp_dtls_transport2_.get(),
+                                                asymmetric);
     });
     EXPECT_TRUE(media_channel1_->sending());
     SendRtp1();
@@ -1495,18 +1584,16 @@
     int pl_type2 = pl_types[1];
     int flags = SSRC_MUX;
     if (secure) flags |= SECURE;
-    uint32_t expected_channels = 2U;
     if (rtcp_mux) {
       flags |= RTCP_MUX;
-      expected_channels = 1U;
     }
     CreateChannels(flags, flags);
     EXPECT_TRUE(SendInitiate());
-    EXPECT_EQ(2U, GetChannels1().size());
-    EXPECT_EQ(expected_channels, GetChannels2().size());
+    EXPECT_TRUE(channel1_->NeedsRtcpTransport());
+    EXPECT_EQ(rtcp_mux, !channel2_->NeedsRtcpTransport());
     EXPECT_TRUE(SendAccept());
-    EXPECT_EQ(expected_channels, GetChannels1().size());
-    EXPECT_EQ(expected_channels, GetChannels2().size());
+    EXPECT_EQ(rtcp_mux, !channel1_->NeedsRtcpTransport());
+    EXPECT_EQ(rtcp_mux, !channel2_->NeedsRtcpTransport());
     EXPECT_TRUE(channel1_->bundle_filter()->FindPayloadType(pl_type1));
     EXPECT_TRUE(channel2_->bundle_filter()->FindPayloadType(pl_type1));
     EXPECT_FALSE(channel1_->bundle_filter()->FindPayloadType(pl_type2));
@@ -1686,8 +1773,8 @@
     CreateChannels(0, 0);
     EXPECT_TRUE(SendInitiate());
     EXPECT_TRUE(SendAccept());
-    EXPECT_EQ(2U, GetChannels1().size());
-    EXPECT_EQ(2U, GetChannels2().size());
+    EXPECT_TRUE(channel1_->NeedsRtcpTransport());
+    EXPECT_TRUE(channel2_->NeedsRtcpTransport());
 
     // Send RTCP1 from a different thread.
     ScopedCallThread send_rtcp([this] { SendRtcp1(); });
@@ -1733,12 +1820,13 @@
     // Using fake clock because this tests that SRTP errors are signaled at
     // specific times based on set_signal_silent_time.
     rtc::ScopedFakeClock fake_clock;
+
+    CreateChannels(SECURE, SECURE);
     // Some code uses a time of 0 as a special value, so we must start with
     // a non-zero time.
     // TODO(deadbeef): Fix this.
     fake_clock.AdvanceTime(rtc::TimeDelta::FromSeconds(1));
 
-    CreateChannels(SECURE, SECURE);
     EXPECT_FALSE(channel1_->secure());
     EXPECT_FALSE(channel2_->secure());
     EXPECT_TRUE(SendInitiate());
@@ -1779,22 +1867,21 @@
     error_handler.mode_ = cricket::SrtpFilter::UNPROTECT;
 
     network_thread_->Invoke<void>(RTC_FROM_HERE, [this] {
-      cricket::DtlsTransportInternal* transport_channel =
-          channel2_->rtp_dtls_transport();
-      transport_channel->SignalReadPacket(
-          transport_channel, reinterpret_cast<const char*>(kBadPacket),
-          sizeof(kBadPacket), rtc::PacketTime(), 0);
+      fake_rtp_dtls_transport2_->SignalReadPacket(
+          fake_rtp_dtls_transport2_.get(),
+          reinterpret_cast<const char*>(kBadPacket), sizeof(kBadPacket),
+          rtc::PacketTime(), 0);
     });
     EXPECT_EQ(cricket::SrtpFilter::ERROR_FAIL, error_handler.error_);
     EXPECT_EQ(cricket::SrtpFilter::UNPROTECT, error_handler.mode_);
-    // Terminate channels before the fake clock is destroyed.
-    EXPECT_TRUE(SendTerminate());
+    // Terminate channels/threads before the fake clock is destroyed.
+    EXPECT_TRUE(Terminate());
   }
 
   void TestOnReadyToSend() {
     CreateChannels(0, 0);
-    DtlsTransportInternal* rtp = channel1_->rtp_dtls_transport();
-    DtlsTransportInternal* rtcp = channel1_->rtcp_dtls_transport();
+    cricket::FakeDtlsTransport* rtp = fake_rtp_dtls_transport1_.get();
+    cricket::FakeDtlsTransport* rtcp = fake_rtcp_dtls_transport1_.get();
     EXPECT_FALSE(media_channel1_->ready_to_send());
 
     network_thread_->Invoke<void>(RTC_FROM_HERE,
@@ -1840,12 +1927,13 @@
     CreateChannels(0, 0);
     typename T::Content content;
     CreateContent(0, kPcmuCodec, kH264Codec, &content);
-    // Both sides agree on mux. Should no longer be a separate RTCP channel.
+    // Both sides agree on mux. Should signal that RTCP mux is fully active.
     content.set_rtcp_mux(true);
     EXPECT_TRUE(channel1_->SetLocalContent(&content, CA_OFFER, NULL));
+    EXPECT_EQ(0, rtcp_mux_activated_callbacks1_);
     EXPECT_TRUE(channel1_->SetRemoteContent(&content, CA_ANSWER, NULL));
-    EXPECT_TRUE(channel1_->rtcp_dtls_transport() == NULL);
-    DtlsTransportInternal* rtp = channel1_->rtp_dtls_transport();
+    EXPECT_EQ(1, rtcp_mux_activated_callbacks1_);
+    cricket::FakeDtlsTransport* rtp = fake_rtp_dtls_transport1_.get();
     EXPECT_FALSE(media_channel1_->ready_to_send());
     // In the case of rtcp mux, the SignalReadyToSend() from rtp channel
     // should trigger the MediaChannel's OnReadyToSend.
@@ -1936,12 +2024,18 @@
   const bool verify_playout_;
   std::unique_ptr<rtc::Thread> network_thread_keeper_;
   rtc::Thread* network_thread_;
-  std::unique_ptr<cricket::FakeTransportController> transport_controller1_;
-  std::unique_ptr<cricket::FakeTransportController> transport_controller2_;
+  std::unique_ptr<cricket::FakeDtlsTransport> fake_rtp_dtls_transport1_;
+  std::unique_ptr<cricket::FakeDtlsTransport> fake_rtcp_dtls_transport1_;
+  std::unique_ptr<cricket::FakeDtlsTransport> fake_rtp_dtls_transport2_;
+  std::unique_ptr<cricket::FakeDtlsTransport> fake_rtcp_dtls_transport2_;
+  std::unique_ptr<rtc::FakePacketTransport> fake_rtp_packet_transport1_;
+  std::unique_ptr<rtc::FakePacketTransport> fake_rtcp_packet_transport1_;
+  std::unique_ptr<rtc::FakePacketTransport> fake_rtp_packet_transport2_;
+  std::unique_ptr<rtc::FakePacketTransport> fake_rtcp_packet_transport2_;
   cricket::FakeMediaEngine media_engine_;
   // The media channels are owned by the voice channel objects below.
-  typename T::MediaChannel* media_channel1_;
-  typename T::MediaChannel* media_channel2_;
+  typename T::MediaChannel* media_channel1_ = nullptr;
+  typename T::MediaChannel* media_channel2_ = nullptr;
   std::unique_ptr<typename T::Channel> channel1_;
   std::unique_ptr<typename T::Channel> channel2_;
   typename T::Content local_media_content1_;
@@ -1951,8 +2045,10 @@
   // The RTP and RTCP packets to send in the tests.
   rtc::Buffer rtp_packet_;
   rtc::Buffer rtcp_packet_;
-  int media_info_callbacks1_;
-  int media_info_callbacks2_;
+  int media_info_callbacks1_ = 0;
+  int media_info_callbacks2_ = 0;
+  int rtcp_mux_activated_callbacks1_ = 0;
+  int rtcp_mux_activated_callbacks2_ = 0;
   cricket::CandidatePairInterface* last_selected_candidate_pair_;
 };
 
@@ -2014,25 +2110,23 @@
     rtc::Thread* network_thread,
     cricket::MediaEngineInterface* engine,
     cricket::FakeVideoMediaChannel* ch,
-    cricket::TransportController* transport_controller,
+    cricket::DtlsTransportInternal* fake_rtp_dtls_transport,
+    cricket::DtlsTransportInternal* fake_rtcp_dtls_transport,
+    rtc::PacketTransportInterface* fake_rtp_packet_transport,
+    rtc::PacketTransportInterface* fake_rtcp_packet_transport,
     int flags) {
-  rtc::Thread* signaling_thread =
-      transport_controller ? transport_controller->signaling_thread() : nullptr;
+  rtc::Thread* signaling_thread = rtc::Thread::Current();
   cricket::VideoChannel* channel = new cricket::VideoChannel(
       worker_thread, network_thread, signaling_thread, ch, cricket::CN_VIDEO,
       (flags & RTCP_MUX_REQUIRED) != 0, (flags & SECURE) != 0);
   rtc::CryptoOptions crypto_options;
   crypto_options.enable_gcm_crypto_suites = (flags & GCM_CIPHER) != 0;
   channel->SetCryptoOptions(crypto_options);
-  cricket::DtlsTransportInternal* rtp_dtls_transport =
-      transport_controller->CreateDtlsTransport(
-          channel->content_name(), cricket::ICE_CANDIDATE_COMPONENT_RTP);
-  cricket::DtlsTransportInternal* rtcp_dtls_transport = nullptr;
-  if (channel->NeedsRtcpTransport()) {
-    rtcp_dtls_transport = transport_controller->CreateDtlsTransport(
-        channel->content_name(), cricket::ICE_CANDIDATE_COMPONENT_RTCP);
+  if (!channel->NeedsRtcpTransport()) {
+    fake_rtcp_dtls_transport = nullptr;
   }
-  if (!channel->Init_w(rtp_dtls_transport, rtcp_dtls_transport)) {
+  if (!channel->Init_w(fake_rtp_dtls_transport, fake_rtcp_dtls_transport,
+                       fake_rtp_packet_transport, fake_rtcp_packet_transport)) {
     delete channel;
     channel = NULL;
   }
@@ -2260,6 +2354,12 @@
   Base::SendSrtpToSrtp(DTLS | RTCP_MUX, DTLS | RTCP_MUX);
 }
 
+// Test using the channel with a raw packet interface, as opposed to a DTLS
+// transport interface.
+TEST_F(VoiceChannelSingleThreadTest, SendSrtpToSrtpWithRawPacketTransport) {
+  Base::SendSrtpToSrtp(RAW_PACKET_TRANSPORT, RAW_PACKET_TRANSPORT);
+}
+
 TEST_F(VoiceChannelSingleThreadTest, SendEarlyMediaUsingRtcpMuxSrtp) {
   Base::SendEarlyMediaUsingRtcpMuxSrtp();
 }
@@ -2587,6 +2687,12 @@
   Base::SendSrtpToSrtp(DTLS | RTCP_MUX, DTLS | RTCP_MUX);
 }
 
+// Test using the channel with a raw packet interface, as opposed to a DTLS
+// transport interface.
+TEST_F(VoiceChannelDoubleThreadTest, SendSrtpToSrtpWithRawPacketTransport) {
+  Base::SendSrtpToSrtp(RAW_PACKET_TRANSPORT, RAW_PACKET_TRANSPORT);
+}
+
 TEST_F(VoiceChannelDoubleThreadTest, SendEarlyMediaUsingRtcpMuxSrtp) {
   Base::SendEarlyMediaUsingRtcpMuxSrtp();
 }
@@ -2894,6 +3000,12 @@
   Base::SendSrtpToSrtp(DTLS | RTCP_MUX, DTLS | RTCP_MUX);
 }
 
+// Test using the channel with a raw packet interface, as opposed to a DTLS
+// transport interface.
+TEST_F(VideoChannelSingleThreadTest, SendSrtpToSrtpWithRawPacketTransport) {
+  Base::SendSrtpToSrtp(RAW_PACKET_TRANSPORT, RAW_PACKET_TRANSPORT);
+}
+
 TEST_F(VideoChannelSingleThreadTest, SendSrtcpMux) {
   Base::SendSrtpToSrtp(RTCP_MUX, RTCP_MUX);
 }
@@ -3123,6 +3235,12 @@
   Base::SendSrtpToSrtp(DTLS | RTCP_MUX, DTLS | RTCP_MUX);
 }
 
+// Test using the channel with a raw packet interface, as opposed to a DTLS
+// transport interface.
+TEST_F(VideoChannelDoubleThreadTest, SendSrtpToSrtpWithRawPacketTransport) {
+  Base::SendSrtpToSrtp(RAW_PACKET_TRANSPORT, RAW_PACKET_TRANSPORT);
+}
+
 TEST_F(VideoChannelDoubleThreadTest, SendSrtcpMux) {
   Base::SendSrtpToSrtp(RTCP_MUX, RTCP_MUX);
 }
@@ -3230,25 +3348,23 @@
     rtc::Thread* network_thread,
     cricket::MediaEngineInterface* engine,
     cricket::FakeDataMediaChannel* ch,
-    cricket::TransportController* transport_controller,
+    cricket::DtlsTransportInternal* fake_rtp_dtls_transport,
+    cricket::DtlsTransportInternal* fake_rtcp_dtls_transport,
+    rtc::PacketTransportInterface* fake_rtp_packet_transport,
+    rtc::PacketTransportInterface* fake_rtcp_packet_transport,
     int flags) {
-  rtc::Thread* signaling_thread =
-      transport_controller ? transport_controller->signaling_thread() : nullptr;
+  rtc::Thread* signaling_thread = rtc::Thread::Current();
   cricket::RtpDataChannel* channel = new cricket::RtpDataChannel(
       worker_thread, network_thread, signaling_thread, ch, cricket::CN_DATA,
       (flags & RTCP_MUX_REQUIRED) != 0, (flags & SECURE) != 0);
   rtc::CryptoOptions crypto_options;
   crypto_options.enable_gcm_crypto_suites = (flags & GCM_CIPHER) != 0;
   channel->SetCryptoOptions(crypto_options);
-  cricket::DtlsTransportInternal* rtp_dtls_transport =
-      transport_controller->CreateDtlsTransport(
-          channel->content_name(), cricket::ICE_CANDIDATE_COMPONENT_RTP);
-  cricket::DtlsTransportInternal* rtcp_dtls_transport = nullptr;
-  if (channel->NeedsRtcpTransport()) {
-    rtcp_dtls_transport = transport_controller->CreateDtlsTransport(
-        channel->content_name(), cricket::ICE_CANDIDATE_COMPONENT_RTCP);
+  if (!channel->NeedsRtcpTransport()) {
+    fake_rtcp_dtls_transport = nullptr;
   }
-  if (!channel->Init_w(rtp_dtls_transport, rtcp_dtls_transport)) {
+  if (!channel->Init_w(fake_rtp_dtls_transport, fake_rtcp_dtls_transport,
+                       fake_rtp_packet_transport, fake_rtcp_packet_transport)) {
     delete channel;
     channel = NULL;
   }
@@ -3565,7 +3681,9 @@
 class BaseChannelDeathTest : public testing::Test {
  public:
   BaseChannelDeathTest()
-      :  // RTCP mux not required, SRTP required.
+      : fake_rtp_dtls_transport_("foo", cricket::ICE_CANDIDATE_COMPONENT_RTP),
+        fake_rtcp_dtls_transport_("foo", cricket::ICE_CANDIDATE_COMPONENT_RTCP),
+        // RTCP mux not required, SRTP required.
         voice_channel_(
             rtc::Thread::Current(),
             rtc::Thread::Current(),
@@ -3575,66 +3693,89 @@
                                                cricket::AudioOptions()),
             cricket::CN_AUDIO,
             false,
-            true) {
-    rtp_transport_ = fake_transport_controller_.CreateDtlsTransport(
-        "foo", cricket::ICE_CANDIDATE_COMPONENT_RTP);
-    rtcp_transport_ = fake_transport_controller_.CreateDtlsTransport(
-        "foo", cricket::ICE_CANDIDATE_COMPONENT_RTCP);
-    EXPECT_TRUE(voice_channel_.Init_w(rtp_transport_, rtcp_transport_));
-  }
+            true) {}
 
  protected:
-  cricket::FakeTransportController fake_transport_controller_;
   cricket::FakeMediaEngine fake_media_engine_;
+  cricket::FakeDtlsTransport fake_rtp_dtls_transport_;
+  cricket::FakeDtlsTransport fake_rtcp_dtls_transport_;
   cricket::VoiceChannel voice_channel_;
-  // Will be cleaned up by FakeTransportController, don't need to worry about
-  // deleting them in this test.
-  cricket::DtlsTransportInternal* rtp_transport_;
-  cricket::DtlsTransportInternal* rtcp_transport_;
 };
 
-TEST_F(BaseChannelDeathTest, SetTransportWithNullRtpTransport) {
-  cricket::DtlsTransportInternal* new_rtcp_transport =
-      fake_transport_controller_.CreateDtlsTransport(
-          "bar", cricket::ICE_CANDIDATE_COMPONENT_RTCP);
-  EXPECT_DEATH(voice_channel_.SetTransports(nullptr, new_rtcp_transport), "");
+TEST_F(BaseChannelDeathTest, SetTransportsWithNullRtpTransport) {
+  ASSERT_TRUE(voice_channel_.Init_w(
+      &fake_rtp_dtls_transport_, &fake_rtcp_dtls_transport_,
+      &fake_rtp_dtls_transport_, &fake_rtcp_dtls_transport_));
+  cricket::FakeDtlsTransport new_rtcp_transport(
+      "bar", cricket::ICE_CANDIDATE_COMPONENT_RTCP);
+  EXPECT_DEATH(voice_channel_.SetTransports(nullptr, &new_rtcp_transport), "");
 }
 
-TEST_F(BaseChannelDeathTest, SetTransportWithMissingRtcpTransport) {
-  cricket::DtlsTransportInternal* new_rtp_transport =
-      fake_transport_controller_.CreateDtlsTransport(
-          "bar", cricket::ICE_CANDIDATE_COMPONENT_RTP);
-  EXPECT_DEATH(voice_channel_.SetTransports(new_rtp_transport, nullptr), "");
+TEST_F(BaseChannelDeathTest, SetTransportsWithMissingRtcpTransport) {
+  ASSERT_TRUE(voice_channel_.Init_w(
+      &fake_rtp_dtls_transport_, &fake_rtcp_dtls_transport_,
+      &fake_rtp_dtls_transport_, &fake_rtcp_dtls_transport_));
+  cricket::FakeDtlsTransport new_rtp_transport(
+      "bar", cricket::ICE_CANDIDATE_COMPONENT_RTP);
+  EXPECT_DEATH(voice_channel_.SetTransports(&new_rtp_transport, nullptr), "");
 }
 
-TEST_F(BaseChannelDeathTest, SetTransportWithUnneededRtcpTransport) {
+TEST_F(BaseChannelDeathTest, SetTransportsWithUnneededRtcpTransport) {
+  ASSERT_TRUE(voice_channel_.Init_w(
+      &fake_rtp_dtls_transport_, &fake_rtcp_dtls_transport_,
+      &fake_rtp_dtls_transport_, &fake_rtcp_dtls_transport_));
   // Activate RTCP muxing, simulating offer/answer negotiation.
   cricket::AudioContentDescription content;
   content.set_rtcp_mux(true);
   ASSERT_TRUE(voice_channel_.SetLocalContent(&content, CA_OFFER, nullptr));
   ASSERT_TRUE(voice_channel_.SetRemoteContent(&content, CA_ANSWER, nullptr));
-  cricket::DtlsTransportInternal* new_rtp_transport =
-      fake_transport_controller_.CreateDtlsTransport(
-          "bar", cricket::ICE_CANDIDATE_COMPONENT_RTP);
-  cricket::DtlsTransportInternal* new_rtcp_transport =
-      fake_transport_controller_.CreateDtlsTransport(
-          "bar", cricket::ICE_CANDIDATE_COMPONENT_RTCP);
+  cricket::FakeDtlsTransport new_rtp_transport(
+      "bar", cricket::ICE_CANDIDATE_COMPONENT_RTP);
+  cricket::FakeDtlsTransport new_rtcp_transport(
+      "bar", cricket::ICE_CANDIDATE_COMPONENT_RTCP);
   // After muxing is enabled, no RTCP transport should be passed in here.
   EXPECT_DEATH(
-      voice_channel_.SetTransports(new_rtp_transport, new_rtcp_transport), "");
+      voice_channel_.SetTransports(&new_rtp_transport, &new_rtcp_transport),
+      "");
 }
 
 // This test will probably go away if/when we move the transport name out of
 // the transport classes and into their parent classes.
-TEST_F(BaseChannelDeathTest, SetTransportWithMismatchingTransportNames) {
-  cricket::DtlsTransportInternal* new_rtp_transport =
-      fake_transport_controller_.CreateDtlsTransport(
-          "bar", cricket::ICE_CANDIDATE_COMPONENT_RTP);
-  cricket::DtlsTransportInternal* new_rtcp_transport =
-      fake_transport_controller_.CreateDtlsTransport(
-          "baz", cricket::ICE_CANDIDATE_COMPONENT_RTCP);
+TEST_F(BaseChannelDeathTest, SetTransportsWithMismatchingTransportNames) {
+  ASSERT_TRUE(voice_channel_.Init_w(
+      &fake_rtp_dtls_transport_, &fake_rtcp_dtls_transport_,
+      &fake_rtp_dtls_transport_, &fake_rtcp_dtls_transport_));
+  cricket::FakeDtlsTransport new_rtp_transport(
+      "bar", cricket::ICE_CANDIDATE_COMPONENT_RTP);
+  cricket::FakeDtlsTransport new_rtcp_transport(
+      "baz", cricket::ICE_CANDIDATE_COMPONENT_RTCP);
   EXPECT_DEATH(
-      voice_channel_.SetTransports(new_rtp_transport, new_rtcp_transport), "");
+      voice_channel_.SetTransports(&new_rtp_transport, &new_rtcp_transport),
+      "");
+}
+
+// Not expected to support going from DtlsTransportInternal to
+// PacketTransportInterface.
+TEST_F(BaseChannelDeathTest, SetTransportsDtlsToNonDtls) {
+  ASSERT_TRUE(voice_channel_.Init_w(
+      &fake_rtp_dtls_transport_, &fake_rtcp_dtls_transport_,
+      &fake_rtp_dtls_transport_, &fake_rtcp_dtls_transport_));
+  EXPECT_DEATH(
+      voice_channel_.SetTransports(static_cast<rtc::PacketTransportInterface*>(
+                                       &fake_rtp_dtls_transport_),
+                                   static_cast<rtc::PacketTransportInterface*>(
+                                       &fake_rtp_dtls_transport_)),
+      "");
+}
+
+// Not expected to support going from PacketTransportInterface to
+// DtlsTransportInternal.
+TEST_F(BaseChannelDeathTest, SetTransportsNonDtlsToDtls) {
+  ASSERT_TRUE(voice_channel_.Init_w(nullptr, nullptr, &fake_rtp_dtls_transport_,
+                                    &fake_rtcp_dtls_transport_));
+  EXPECT_DEATH(voice_channel_.SetTransports(&fake_rtp_dtls_transport_,
+                                            &fake_rtp_dtls_transport_),
+               "");
 }
 
 #endif  // RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
diff --git a/webrtc/pc/channelmanager.cc b/webrtc/pc/channelmanager.cc
index f667900..9657191 100644
--- a/webrtc/pc/channelmanager.cc
+++ b/webrtc/pc/channelmanager.cc
@@ -246,7 +246,8 @@
       media_channel, content_name, rtcp_mux_required, srtp_required);
   voice_channel->SetCryptoOptions(crypto_options_);
 
-  if (!voice_channel->Init_w(rtp_transport, rtcp_transport)) {
+  if (!voice_channel->Init_w(rtp_transport, rtcp_transport, rtp_transport,
+                             rtcp_transport)) {
     delete voice_channel;
     return nullptr;
   }
@@ -317,7 +318,8 @@
       worker_thread_, network_thread_, signaling_thread, media_channel,
       content_name, rtcp_mux_required, srtp_required);
   video_channel->SetCryptoOptions(crypto_options_);
-  if (!video_channel->Init_w(rtp_transport, rtcp_transport)) {
+  if (!video_channel->Init_w(rtp_transport, rtcp_transport, rtp_transport,
+                             rtcp_transport)) {
     delete video_channel;
     return NULL;
   }
@@ -390,7 +392,8 @@
       worker_thread_, network_thread_, signaling_thread, media_channel,
       content_name, rtcp_mux_required, srtp_required);
   data_channel->SetCryptoOptions(crypto_options_);
-  if (!data_channel->Init_w(rtp_transport, rtcp_transport)) {
+  if (!data_channel->Init_w(rtp_transport, rtcp_transport, rtp_transport,
+                            rtcp_transport)) {
     LOG(LS_WARNING) << "Failed to init data channel.";
     delete data_channel;
     return nullptr;
diff --git a/webrtc/pc/peerconnectioninterface_unittest.cc b/webrtc/pc/peerconnectioninterface_unittest.cc
index ba35293..dc75ba1 100644
--- a/webrtc/pc/peerconnectioninterface_unittest.cc
+++ b/webrtc/pc/peerconnectioninterface_unittest.cc
@@ -27,7 +27,6 @@
 #include "webrtc/media/base/fakevideocapturer.h"
 #include "webrtc/media/sctp/sctptransportinternal.h"
 #include "webrtc/p2p/base/fakeportallocator.h"
-#include "webrtc/p2p/base/faketransportcontroller.h"
 #include "webrtc/pc/audiotrack.h"
 #include "webrtc/pc/mediasession.h"
 #include "webrtc/pc/mediastream.h"
diff --git a/webrtc/pc/statscollector_unittest.cc b/webrtc/pc/statscollector_unittest.cc
index ef218c00..e89da1c 100644
--- a/webrtc/pc/statscollector_unittest.cc
+++ b/webrtc/pc/statscollector_unittest.cc
@@ -24,7 +24,6 @@
 #include "webrtc/logging/rtc_event_log/rtc_event_log.h"
 #include "webrtc/media/base/fakemediaengine.h"
 #include "webrtc/media/base/test/mock_mediachannel.h"
-#include "webrtc/p2p/base/faketransportcontroller.h"
 #include "webrtc/pc/channelmanager.h"
 #include "webrtc/pc/mediastream.h"
 #include "webrtc/pc/mediastreamtrack.h"