Add IceTransportInterface object

This creates the API for an ICE transport object, and lets it
be accessible from a DTLS transport object.

Bug: chromium:907849
Change-Id: Ieb24570217dec75ce0deca8420739c1f116fbba4
Reviewed-on: https://webrtc-review.googlesource.com/c/118703
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
Reviewed-by: Fredrik Solenberg <solenberg@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Commit-Queue: Harald Alvestrand <hta@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26472}
diff --git a/api/BUILD.gn b/api/BUILD.gn
index 6a24aba..52da137 100644
--- a/api/BUILD.gn
+++ b/api/BUILD.gn
@@ -80,6 +80,7 @@
     "data_channel_interface.h",
     "dtls_transport_interface.h",
     "dtmf_sender_interface.h",
+    "ice_transport_interface.h",
     "jsep.cc",
     "jsep.h",
     "jsep_ice_candidate.cc",
@@ -347,6 +348,21 @@
   ]
 }
 
+rtc_source_set("ice_transport_factory") {
+  visibility = [ "*" ]
+  sources = [
+    "ice_transport_factory.cc",
+    "ice_transport_factory.h",
+  ]
+  deps = [
+    ":libjingle_peerconnection_api",
+    ":scoped_refptr",
+    "../p2p:rtc_p2p",
+    "../rtc_base:rtc_base",
+    "//third_party/abseil-cpp/absl/memory:memory",
+  ]
+}
+
 rtc_source_set("libjingle_peerconnection_test_api") {
   visibility = [ "*" ]
   testonly = true
diff --git a/api/DEPS b/api/DEPS
index edc9a23..96fd36b 100644
--- a/api/DEPS
+++ b/api/DEPS
@@ -87,6 +87,10 @@
     "+modules/include/module_fec_types.h",
   ],
 
+  "ice_transport_interface\.h": [
+    "+rtc_base/ref_count.h",
+  ],
+
   "jsep\.h": [
     "+rtc_base/ref_count.h",
   ],
diff --git a/api/dtls_transport_interface.h b/api/dtls_transport_interface.h
index 1faf3f5..ff3b107 100644
--- a/api/dtls_transport_interface.h
+++ b/api/dtls_transport_interface.h
@@ -11,7 +11,9 @@
 #ifndef API_DTLS_TRANSPORT_INTERFACE_H_
 #define API_DTLS_TRANSPORT_INTERFACE_H_
 
+#include "api/ice_transport_interface.h"
 #include "api/rtc_error.h"
+#include "api/scoped_refptr.h"
 #include "rtc_base/ref_count.h"
 
 namespace webrtc {
@@ -59,6 +61,8 @@
 // be initiated by other threads.
 class DtlsTransportInterface : public rtc::RefCountInterface {
  public:
+  // Returns a pointer to the ICE transport that is owned by the DTLS transport.
+  virtual rtc::scoped_refptr<IceTransportInterface> ice_transport() = 0;
   // These functions can only be called from the signalling thread.
   virtual DtlsTransportInformation Information() = 0;
   // Observer management.
diff --git a/api/ice_transport_factory.cc b/api/ice_transport_factory.cc
new file mode 100644
index 0000000..b632f09
--- /dev/null
+++ b/api/ice_transport_factory.cc
@@ -0,0 +1,58 @@
+/*
+ *  Copyright 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "api/ice_transport_factory.h"
+
+#include <memory>
+#include <utility>
+
+#include "absl/memory/memory.h"
+#include "p2p/base/ice_transport_internal.h"
+#include "p2p/base/p2p_transport_channel.h"
+#include "p2p/base/port_allocator.h"
+#include "rtc_base/thread.h"
+
+namespace webrtc {
+
+namespace {
+
+// This implementation of IceTransportInterface is used in cases where
+// the only reference to the P2PTransport will be through this class.
+// It must be constructed, accessed and destroyed on the signaling thread.
+class IceTransportWithTransportChannel : public IceTransportInterface {
+ public:
+  IceTransportWithTransportChannel(
+      std::unique_ptr<cricket::IceTransportInternal> internal)
+      : internal_(std::move(internal)) {}
+
+  ~IceTransportWithTransportChannel() override {
+    RTC_DCHECK_RUN_ON(&thread_checker_);
+  }
+
+  cricket::IceTransportInternal* internal() override {
+    RTC_DCHECK_RUN_ON(&thread_checker_);
+    return internal_.get();
+  }
+
+ private:
+  const rtc::ThreadChecker thread_checker_;
+  const std::unique_ptr<cricket::IceTransportInternal> internal_
+      RTC_GUARDED_BY(thread_checker_);
+};
+
+}  // namespace
+
+rtc::scoped_refptr<IceTransportInterface> CreateIceTransport(
+    cricket::PortAllocator* port_allocator) {
+  return new rtc::RefCountedObject<IceTransportWithTransportChannel>(
+      absl::make_unique<cricket::P2PTransportChannel>("", 0, port_allocator));
+}
+
+}  // namespace webrtc
diff --git a/api/ice_transport_factory.h b/api/ice_transport_factory.h
new file mode 100644
index 0000000..a8330df
--- /dev/null
+++ b/api/ice_transport_factory.h
@@ -0,0 +1,33 @@
+/*
+ *  Copyright 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef API_ICE_TRANSPORT_FACTORY_H_
+#define API_ICE_TRANSPORT_FACTORY_H_
+
+#include "api/ice_transport_interface.h"
+#include "api/scoped_refptr.h"
+
+namespace cricket {
+class PortAllocator;
+}
+
+namespace webrtc {
+
+// Static factory for an IceTransport object that can be created
+// without using a webrtc::PeerConnection.
+// The returned object must be accessed and destroyed on the thread that
+// created it.
+// The PortAllocator must outlive the created IceTransportInterface object.
+rtc::scoped_refptr<IceTransportInterface> CreateIceTransport(
+    cricket::PortAllocator* port_allocator);
+
+}  // namespace webrtc
+
+#endif  // API_ICE_TRANSPORT_FACTORY_H_
diff --git a/api/ice_transport_interface.h b/api/ice_transport_interface.h
new file mode 100644
index 0000000..6e63045
--- /dev/null
+++ b/api/ice_transport_interface.h
@@ -0,0 +1,38 @@
+/*
+ *  Copyright 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef API_ICE_TRANSPORT_INTERFACE_H_
+#define API_ICE_TRANSPORT_INTERFACE_H_
+
+#include "api/rtc_error.h"
+#include "api/scoped_refptr.h"
+#include "rtc_base/ref_count.h"
+
+namespace cricket {
+class IceTransportInternal;
+}  // namespace cricket
+
+namespace webrtc {
+
+// An ICE transport, as represented to the outside world.
+// This object is refcounted, and is therefore alive until the
+// last holder has released it.
+class IceTransportInterface : public rtc::RefCountInterface {
+ public:
+  // Accessor for the internal representation of an ICE transport.
+  // The returned object can only be safely used on the signalling thread.
+  // TODO(crbug.com/907849): Add API calls for the functions that have to
+  // be exposed to clients, and stop allowing access to the
+  // cricket::IceTransportInternal API.
+  virtual cricket::IceTransportInternal* internal() = 0;
+};
+
+}  // namespace webrtc
+#endif  // API_ICE_TRANSPORT_INTERFACE_H_
diff --git a/pc/BUILD.gn b/pc/BUILD.gn
index 6fdbbcb..b0b2ea0 100644
--- a/pc/BUILD.gn
+++ b/pc/BUILD.gn
@@ -40,6 +40,8 @@
     "dtls_transport.h",
     "external_hmac.cc",
     "external_hmac.h",
+    "ice_transport.cc",
+    "ice_transport.h",
     "jsep_transport.cc",
     "jsep_transport.h",
     "jsep_transport_controller.cc",
@@ -246,6 +248,7 @@
       "channel_unittest.cc",
       "dtls_srtp_transport_unittest.cc",
       "dtlstransport_unittest.cc",
+      "ice_transport_unittest.cc",
       "jsep_transport_controller_unittest.cc",
       "jsep_transport_unittest.cc",
       "media_session_unittest.cc",
@@ -278,6 +281,7 @@
       "../api:array_view",
       "../api:audio_options_api",
       "../api:fake_media_transport",
+      "../api:ice_transport_factory",
       "../api:libjingle_peerconnection_api",
       "../call:rtp_interfaces",
       "../call:rtp_receiver",
diff --git a/pc/dtls_transport.cc b/pc/dtls_transport.cc
index 4709107..62a75f2 100644
--- a/pc/dtls_transport.cc
+++ b/pc/dtls_transport.cc
@@ -12,6 +12,8 @@
 
 #include <utility>
 
+#include "pc/ice_transport.h"
+
 namespace webrtc {
 
 namespace {
@@ -46,6 +48,8 @@
   RTC_DCHECK(internal_dtls_transport_.get());
   internal_dtls_transport_->SignalDtlsState.connect(
       this, &DtlsTransport::OnInternalDtlsState);
+  ice_transport_ = new rtc::RefCountedObject<IceTransportWithPointer>(
+      internal_dtls_transport_->ice_transport());
 }
 
 DtlsTransport::~DtlsTransport() {
@@ -74,6 +78,10 @@
   observer_ = nullptr;
 }
 
+rtc::scoped_refptr<IceTransportInterface> DtlsTransport::ice_transport() {
+  return ice_transport_;
+}
+
 // Internal functions
 void DtlsTransport::Clear() {
   RTC_DCHECK(signaling_thread_->IsCurrent());
@@ -86,6 +94,7 @@
   } else {
     internal_dtls_transport_.reset();
   }
+  ice_transport_->Clear();
 }
 
 void DtlsTransport::OnInternalDtlsState(
diff --git a/pc/dtls_transport.h b/pc/dtls_transport.h
index 0fdcc0f..535c7eb 100644
--- a/pc/dtls_transport.h
+++ b/pc/dtls_transport.h
@@ -14,11 +14,15 @@
 #include <memory>
 
 #include "api/dtls_transport_interface.h"
+#include "api/ice_transport_interface.h"
+#include "api/scoped_refptr.h"
 #include "p2p/base/dtls_transport.h"
 #include "rtc_base/async_invoker.h"
 
 namespace webrtc {
 
+class IceTransportWithPointer;
+
 // This implementation wraps a cricket::DtlsTransport, and takes
 // ownership of it.
 class DtlsTransport : public DtlsTransportInterface,
@@ -28,6 +32,7 @@
   explicit DtlsTransport(
       std::unique_ptr<cricket::DtlsTransportInternal> internal);
 
+  rtc::scoped_refptr<IceTransportInterface> ice_transport() override;
   DtlsTransportInformation Information() override;
   void RegisterObserver(DtlsTransportObserverInterface* observer) override;
   void UnregisterObserver() override;
@@ -51,6 +56,7 @@
   DtlsTransportObserverInterface* observer_ = nullptr;
   rtc::Thread* signaling_thread_;
   std::unique_ptr<cricket::DtlsTransportInternal> internal_dtls_transport_;
+  rtc::scoped_refptr<IceTransportWithPointer> ice_transport_;
 };
 
 }  // namespace webrtc
diff --git a/pc/ice_transport.cc b/pc/ice_transport.cc
new file mode 100644
index 0000000..e395354
--- /dev/null
+++ b/pc/ice_transport.cc
@@ -0,0 +1,37 @@
+/*
+ *  Copyright 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "pc/ice_transport.h"
+
+#include <memory>
+#include <utility>
+
+namespace webrtc {
+
+IceTransportWithPointer::~IceTransportWithPointer() {
+  // We depend on the signaling thread to call Clear() before dropping
+  // its last reference to this object; if the destructor is called
+  // on the signaling thread, it's OK to not have called Clear().
+  if (internal_) {
+    RTC_DCHECK_RUN_ON(creator_thread_);
+  }
+}
+
+cricket::IceTransportInternal* IceTransportWithPointer::internal() {
+  RTC_DCHECK_RUN_ON(creator_thread_);
+  return internal_;
+}
+
+void IceTransportWithPointer::Clear() {
+  RTC_DCHECK_RUN_ON(creator_thread_);
+  internal_ = nullptr;
+}
+
+}  // namespace webrtc
diff --git a/pc/ice_transport.h b/pc/ice_transport.h
new file mode 100644
index 0000000..69b69e4
--- /dev/null
+++ b/pc/ice_transport.h
@@ -0,0 +1,49 @@
+/*
+ *  Copyright 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef PC_ICE_TRANSPORT_H_
+#define PC_ICE_TRANSPORT_H_
+
+#include "api/ice_transport_interface.h"
+#include "rtc_base/constructor_magic.h"
+#include "rtc_base/thread.h"
+#include "rtc_base/thread_checker.h"
+
+namespace webrtc {
+
+// Implementation of IceTransportInterface that does not take ownership
+// of its underlying IceTransport. It depends on its creator class to
+// ensure that Clear() is called before the underlying IceTransport
+// is deallocated.
+class IceTransportWithPointer : public IceTransportInterface {
+ public:
+  explicit IceTransportWithPointer(cricket::IceTransportInternal* internal)
+      : creator_thread_(rtc::Thread::Current()), internal_(internal) {
+    RTC_DCHECK(internal_);
+  }
+
+  cricket::IceTransportInternal* internal() override;
+  // This call will ensure that the pointer passed at construction is
+  // no longer in use by this object. Later calls to internal() will return
+  // null.
+  void Clear();
+
+ protected:
+  ~IceTransportWithPointer() override;
+
+ private:
+  RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(IceTransportWithPointer);
+  const rtc::Thread* creator_thread_;
+  cricket::IceTransportInternal* internal_ RTC_GUARDED_BY(creator_thread_);
+};
+
+}  // namespace webrtc
+
+#endif  // PC_ICE_TRANSPORT_H_
diff --git a/pc/ice_transport_unittest.cc b/pc/ice_transport_unittest.cc
index c299b2c..8d668de 100644
--- a/pc/ice_transport_unittest.cc
+++ b/pc/ice_transport_unittest.cc
@@ -9,18 +9,39 @@
  */
 
 #include "pc/ice_transport.h"
-#include "p2p/base/fake_port_allocator.h"
 
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include "absl/memory/memory.h"
+#include "api/ice_transport_factory.h"
+#include "p2p/base/fake_ice_transport.h"
+#include "p2p/base/fake_port_allocator.h"
+#include "rtc_base/gunit.h"
+#include "test/gmock.h"
 #include "test/gtest.h"
 
 namespace webrtc {
 
 class IceTransportTest : public testing::Test {};
 
-TEST_F(IceTransportTest, CreateStandaloneIceTransport) {
-  auto port_allocator = new cricket::FakePortAllocator(nullptr, nullptr);
-  auto transport = CreateIceTransport(port_allocator);
-  ASSERT_TRUE(transport->internal());
+TEST_F(IceTransportTest, CreateNonSelfDeletingTransport) {
+  auto cricket_transport =
+      absl::make_unique<cricket::FakeIceTransport>("name", 0, nullptr);
+  rtc::scoped_refptr<IceTransportWithPointer> ice_transport =
+      new rtc::RefCountedObject<IceTransportWithPointer>(
+          cricket_transport.get());
+  EXPECT_EQ(ice_transport->internal(), cricket_transport.get());
+  ice_transport->Clear();
+  EXPECT_NE(ice_transport->internal(), cricket_transport.get());
+}
+
+TEST_F(IceTransportTest, CreateSelfDeletingTransport) {
+  std::unique_ptr<cricket::FakePortAllocator> port_allocator(
+      absl::make_unique<cricket::FakePortAllocator>(nullptr, nullptr));
+  auto ice_transport = CreateIceTransport(port_allocator.get());
+  EXPECT_NE(nullptr, ice_transport->internal());
 }
 
 }  // namespace webrtc