Make ICE transports injectable. Bug: chromium:1024965 Change-Id: I4961f50aee34c82701299f59a95cb90d231db6f5 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/158820 Commit-Queue: Qingsi Wang <qingsi@webrtc.org> Reviewed-by: Steve Anton <steveanton@webrtc.org> Reviewed-by: Jonas Oreland <jonaso@webrtc.org> Reviewed-by: Harald Alvestrand <hta@webrtc.org> Reviewed-by: Honghai Zhang <honghaiz@webrtc.org> Cr-Commit-Position: refs/heads/master@{#29807}
diff --git a/api/ice_transport_factory.h b/api/ice_transport_factory.h index d981e0b..a9fd04e 100644 --- a/api/ice_transport_factory.h +++ b/api/ice_transport_factory.h
@@ -11,48 +11,16 @@ #ifndef API_ICE_TRANSPORT_FACTORY_H_ #define API_ICE_TRANSPORT_FACTORY_H_ -#include "api/async_resolver_factory.h" #include "api/ice_transport_interface.h" -#include "api/rtc_event_log/rtc_event_log.h" #include "api/scoped_refptr.h" #include "rtc_base/system/rtc_export.h" namespace cricket { class PortAllocator; -} +} // namespace cricket namespace webrtc { -struct IceTransportInit final { - public: - IceTransportInit() = default; - IceTransportInit(const IceTransportInit&) = delete; - IceTransportInit(IceTransportInit&&) = default; - IceTransportInit& operator=(const IceTransportInit&) = delete; - IceTransportInit& operator=(IceTransportInit&&) = default; - - cricket::PortAllocator* port_allocator() { return port_allocator_; } - void set_port_allocator(cricket::PortAllocator* port_allocator) { - port_allocator_ = port_allocator; - } - - AsyncResolverFactory* async_resolver_factory() { - return async_resolver_factory_; - } - void set_async_resolver_factory( - AsyncResolverFactory* async_resolver_factory) { - async_resolver_factory_ = async_resolver_factory; - } - - RtcEventLog* event_log() { return event_log_; } - void set_event_log(RtcEventLog* event_log) { event_log_ = event_log; } - - private: - cricket::PortAllocator* port_allocator_ = nullptr; - AsyncResolverFactory* async_resolver_factory_ = nullptr; - RtcEventLog* event_log_ = nullptr; -}; - // 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
diff --git a/api/ice_transport_interface.h b/api/ice_transport_interface.h index 6e63045..d2f1edc 100644 --- a/api/ice_transport_interface.h +++ b/api/ice_transport_interface.h
@@ -11,12 +11,17 @@ #ifndef API_ICE_TRANSPORT_INTERFACE_H_ #define API_ICE_TRANSPORT_INTERFACE_H_ +#include <string> + +#include "api/async_resolver_factory.h" #include "api/rtc_error.h" +#include "api/rtc_event_log/rtc_event_log.h" #include "api/scoped_refptr.h" #include "rtc_base/ref_count.h" namespace cricket { class IceTransportInternal; +class PortAllocator; } // namespace cricket namespace webrtc { @@ -34,5 +39,57 @@ virtual cricket::IceTransportInternal* internal() = 0; }; +struct IceTransportInit final { + public: + IceTransportInit() = default; + IceTransportInit(const IceTransportInit&) = delete; + IceTransportInit(IceTransportInit&&) = default; + IceTransportInit& operator=(const IceTransportInit&) = delete; + IceTransportInit& operator=(IceTransportInit&&) = default; + + cricket::PortAllocator* port_allocator() { return port_allocator_; } + void set_port_allocator(cricket::PortAllocator* port_allocator) { + port_allocator_ = port_allocator; + } + + AsyncResolverFactory* async_resolver_factory() { + return async_resolver_factory_; + } + void set_async_resolver_factory( + AsyncResolverFactory* async_resolver_factory) { + async_resolver_factory_ = async_resolver_factory; + } + + RtcEventLog* event_log() { return event_log_; } + void set_event_log(RtcEventLog* event_log) { event_log_ = event_log; } + + private: + cricket::PortAllocator* port_allocator_ = nullptr; + AsyncResolverFactory* async_resolver_factory_ = nullptr; + RtcEventLog* event_log_ = nullptr; +}; + +// TODO(qingsi): The factory interface is defined in this file instead of its +// namesake file ice_transport_factory.h to avoid the extra dependency on p2p/ +// introduced there by the p2p/-dependent factory methods. Move the factory +// methods to a different file or rename it. +class IceTransportFactory { + public: + virtual ~IceTransportFactory() = default; + // As a refcounted object, the returned ICE transport may outlive the host + // construct into which its reference is given, e.g. a peer connection. As a + // result, the returned ICE transport should not hold references to any object + // that the transport does not own and that has a lifetime bound to the host + // construct. Also, assumptions on the thread safety of the returned transport + // should be clarified by implementations. For example, a peer connection + // requires the returned transport to be constructed and destroyed on the + // network thread and an ICE transport factory that intends to work with a + // peer connection should offer transports compatible with these assumptions. + virtual rtc::scoped_refptr<IceTransportInterface> CreateIceTransport( + const std::string& transport_name, + int component, + IceTransportInit init) = 0; +}; + } // namespace webrtc #endif // API_ICE_TRANSPORT_INTERFACE_H_
diff --git a/api/peer_connection_interface.h b/api/peer_connection_interface.h index a1280de..f2ef336 100644 --- a/api/peer_connection_interface.h +++ b/api/peer_connection_interface.h
@@ -83,6 +83,7 @@ #include "api/data_channel_interface.h" #include "api/dtls_transport_interface.h" #include "api/fec_controller.h" +#include "api/ice_transport_interface.h" #include "api/jsep.h" #include "api/media_stream_interface.h" #include "api/neteq/neteq_factory.h" @@ -1288,6 +1289,7 @@ std::unique_ptr<cricket::PortAllocator> allocator; std::unique_ptr<rtc::PacketSocketFactory> packet_socket_factory; std::unique_ptr<webrtc::AsyncResolverFactory> async_resolver_factory; + std::unique_ptr<webrtc::IceTransportFactory> ice_transport_factory; std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_generator; std::unique_ptr<rtc::SSLCertificateVerifier> tls_cert_verifier; std::unique_ptr<webrtc::VideoBitrateAllocatorFactory>
diff --git a/p2p/BUILD.gn b/p2p/BUILD.gn index 8c4b6f6..42afcff 100644 --- a/p2p/BUILD.gn +++ b/p2p/BUILD.gn
@@ -41,8 +41,11 @@ "base/connection.h", "base/connection_info.cc", "base/connection_info.h", + "base/default_ice_transport_factory.cc", + "base/default_ice_transport_factory.h", "base/dtls_transport.cc", "base/dtls_transport.h", + "base/dtls_transport_factory.h", "base/dtls_transport_internal.cc", "base/dtls_transport_internal.h", "base/ice_credentials_iterator.cc", @@ -80,7 +83,6 @@ "base/transport_description.h", "base/transport_description_factory.cc", "base/transport_description_factory.h", - "base/transport_factory_interface.h", "base/transport_info.h", "base/turn_port.cc", "base/turn_port.h", @@ -132,6 +134,7 @@ ] deps = [ ":rtc_p2p", + "../api:libjingle_peerconnection_api", "../rtc_base", "../rtc_base:rtc_base_approved", "//third_party/abseil-cpp/absl/algorithm:container",
diff --git a/p2p/base/default_ice_transport_factory.cc b/p2p/base/default_ice_transport_factory.cc new file mode 100644 index 0000000..4430525 --- /dev/null +++ b/p2p/base/default_ice_transport_factory.cc
@@ -0,0 +1,36 @@ +/* + * 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 "p2p/base/default_ice_transport_factory.h" + +#include <utility> + +namespace webrtc { + +DefaultIceTransport::DefaultIceTransport( + std::unique_ptr<cricket::P2PTransportChannel> internal) + : internal_(std::move(internal)) {} + +DefaultIceTransport::~DefaultIceTransport() { + RTC_DCHECK_RUN_ON(&thread_checker_); +} + +rtc::scoped_refptr<IceTransportInterface> +DefaultIceTransportFactory::CreateIceTransport( + const std::string& transport_name, + int component, + IceTransportInit init) { + return new rtc::RefCountedObject<DefaultIceTransport>( + std::make_unique<cricket::P2PTransportChannel>( + transport_name, component, init.port_allocator(), + init.async_resolver_factory(), init.event_log())); +} + +} // namespace webrtc
diff --git a/p2p/base/default_ice_transport_factory.h b/p2p/base/default_ice_transport_factory.h new file mode 100644 index 0000000..4834c9a --- /dev/null +++ b/p2p/base/default_ice_transport_factory.h
@@ -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. + */ + +#ifndef P2P_BASE_DEFAULT_ICE_TRANSPORT_FACTORY_H_ +#define P2P_BASE_DEFAULT_ICE_TRANSPORT_FACTORY_H_ + +#include <memory> +#include <string> + +#include "api/ice_transport_interface.h" +#include "p2p/base/p2p_transport_channel.h" +#include "rtc_base/thread.h" + +namespace webrtc { + +// The default ICE transport wraps the implementation of IceTransportInternal +// provided by P2PTransportChannel. This default transport is not thread safe +// and must be constructed, used and destroyed on the same network thread on +// which the internal P2PTransportChannel lives. +class DefaultIceTransport : public IceTransportInterface { + public: + explicit DefaultIceTransport( + std::unique_ptr<cricket::P2PTransportChannel> internal); + ~DefaultIceTransport(); + + cricket::IceTransportInternal* internal() override { + RTC_DCHECK_RUN_ON(&thread_checker_); + return internal_.get(); + } + + private: + const rtc::ThreadChecker thread_checker_{}; + std::unique_ptr<cricket::P2PTransportChannel> internal_ + RTC_GUARDED_BY(thread_checker_); +}; + +class DefaultIceTransportFactory : public IceTransportFactory { + public: + DefaultIceTransportFactory() = default; + ~DefaultIceTransportFactory() = default; + + // Must be called on the network thread and returns a DefaultIceTransport. + rtc::scoped_refptr<IceTransportInterface> CreateIceTransport( + const std::string& transport_name, + int component, + IceTransportInit init) override; +}; + +} // namespace webrtc + +#endif // P2P_BASE_DEFAULT_ICE_TRANSPORT_FACTORY_H_
diff --git a/p2p/base/dtls_transport_factory.h b/p2p/base/dtls_transport_factory.h new file mode 100644 index 0000000..9ad78a7 --- /dev/null +++ b/p2p/base/dtls_transport_factory.h
@@ -0,0 +1,39 @@ +/* + * Copyright 2018 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef P2P_BASE_DTLS_TRANSPORT_FACTORY_H_ +#define P2P_BASE_DTLS_TRANSPORT_FACTORY_H_ + +#include <memory> +#include <string> + +#include "p2p/base/dtls_transport_internal.h" +#include "p2p/base/ice_transport_internal.h" + +namespace cricket { + +// This interface is used to create DTLS transports. The external transports +// can be injected into the JsepTransportController through it. +// +// TODO(qingsi): Remove this factory in favor of one that produces +// DtlsTransportInterface given by the public API if this is going to be +// injectable. +class DtlsTransportFactory { + public: + virtual ~DtlsTransportFactory() = default; + + virtual std::unique_ptr<DtlsTransportInternal> CreateDtlsTransport( + IceTransportInternal* ice, + const webrtc::CryptoOptions& crypto_options) = 0; +}; + +} // namespace cricket + +#endif // P2P_BASE_DTLS_TRANSPORT_FACTORY_H_
diff --git a/p2p/base/fake_ice_transport.h b/p2p/base/fake_ice_transport.h index b1a83b8..d0fa1ea 100644 --- a/p2p/base/fake_ice_transport.h +++ b/p2p/base/fake_ice_transport.h
@@ -12,11 +12,13 @@ #define P2P_BASE_FAKE_ICE_TRANSPORT_H_ #include <map> +#include <memory> #include <string> #include <utility> #include "absl/algorithm/container.h" #include "absl/types/optional.h" +#include "api/ice_transport_interface.h" #include "p2p/base/ice_transport_internal.h" #include "rtc_base/async_invoker.h" #include "rtc_base/copy_on_write_buffer.h" @@ -330,6 +332,18 @@ rtc::Thread* const network_thread_; }; +class FakeIceTransportWrapper : public webrtc::IceTransportInterface { + public: + explicit FakeIceTransportWrapper( + std::unique_ptr<cricket::FakeIceTransport> internal) + : internal_(std::move(internal)) {} + + cricket::IceTransportInternal* internal() override { return internal_.get(); } + + private: + std::unique_ptr<cricket::FakeIceTransport> internal_; +}; + } // namespace cricket #endif // P2P_BASE_FAKE_ICE_TRANSPORT_H_
diff --git a/p2p/base/transport_factory_interface.h b/p2p/base/transport_factory_interface.h deleted file mode 100644 index e7eead7..0000000 --- a/p2p/base/transport_factory_interface.h +++ /dev/null
@@ -1,42 +0,0 @@ -/* - * Copyright 2018 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef P2P_BASE_TRANSPORT_FACTORY_INTERFACE_H_ -#define P2P_BASE_TRANSPORT_FACTORY_INTERFACE_H_ - -#include <memory> -#include <string> - -#include "p2p/base/dtls_transport_internal.h" -#include "p2p/base/ice_transport_internal.h" - -namespace cricket { - -// This interface is used to create DTLS/ICE transports. The external transports -// can be injected into the JsepTransportController through it. For example, the -// FakeIceTransport/FakeDtlsTransport can be injected by setting a -// FakeTransportFactory which implements this interface to the -// JsepTransportController. -class TransportFactoryInterface { - public: - virtual ~TransportFactoryInterface() {} - - virtual std::unique_ptr<IceTransportInternal> CreateIceTransport( - const std::string& transport_name, - int component) = 0; - - virtual std::unique_ptr<DtlsTransportInternal> CreateDtlsTransport( - IceTransportInternal* ice, - const webrtc::CryptoOptions& crypto_options) = 0; -}; - -} // namespace cricket - -#endif // P2P_BASE_TRANSPORT_FACTORY_INTERFACE_H_
diff --git a/pc/BUILD.gn b/pc/BUILD.gn index 2dcbd91..40f3b50 100644 --- a/pc/BUILD.gn +++ b/pc/BUILD.gn
@@ -87,6 +87,7 @@ "../api:array_view", "../api:audio_options_api", "../api:call_api", + "../api:ice_transport_factory", "../api:libjingle_peerconnection_api", "../api:rtc_error", "../api:rtp_headers", @@ -227,6 +228,7 @@ "../api:audio_options_api", "../api:call_api", "../api:fec_controller_api", + "../api:ice_transport_factory", "../api:libjingle_peerconnection_api", "../api:media_stream_interface", "../api:network_state_predictor_api", @@ -577,6 +579,7 @@ "../modules/audio_device:audio_device_api", "../modules/audio_processing:audio_processing_statistics", "../modules/rtp_rtcp:rtp_rtcp_format", + "../p2p:fake_ice_transport", "../p2p:fake_port_allocator", "../rtc_base:checks", "../rtc_base:gunit_helpers",
diff --git a/pc/jsep_transport.cc b/pc/jsep_transport.cc index 13618c7..79b933c9 100644 --- a/pc/jsep_transport.cc +++ b/pc/jsep_transport.cc
@@ -102,8 +102,8 @@ JsepTransport::JsepTransport( const std::string& mid, const rtc::scoped_refptr<rtc::RTCCertificate>& local_certificate, - std::unique_ptr<cricket::IceTransportInternal> ice_transport, - std::unique_ptr<cricket::IceTransportInternal> rtcp_ice_transport, + rtc::scoped_refptr<webrtc::IceTransportInterface> ice_transport, + rtc::scoped_refptr<webrtc::IceTransportInterface> rtcp_ice_transport, std::unique_ptr<webrtc::RtpTransport> unencrypted_rtp_transport, std::unique_ptr<webrtc::SrtpTransport> sdes_transport, std::unique_ptr<webrtc::DtlsSrtpTransport> dtls_srtp_transport,
diff --git a/pc/jsep_transport.h b/pc/jsep_transport.h index 3c63c47..658e8e7 100644 --- a/pc/jsep_transport.h +++ b/pc/jsep_transport.h
@@ -18,6 +18,7 @@ #include "absl/types/optional.h" #include "api/candidate.h" +#include "api/ice_transport_interface.h" #include "api/jsep.h" #include "api/transport/datagram_transport_interface.h" #include "api/transport/media/media_transport_interface.h" @@ -101,8 +102,8 @@ JsepTransport( const std::string& mid, const rtc::scoped_refptr<rtc::RTCCertificate>& local_certificate, - std::unique_ptr<cricket::IceTransportInternal> ice_transport, - std::unique_ptr<cricket::IceTransportInternal> rtcp_ice_transport, + rtc::scoped_refptr<webrtc::IceTransportInterface> ice_transport, + rtc::scoped_refptr<webrtc::IceTransportInterface> rtcp_ice_transport, std::unique_ptr<webrtc::RtpTransport> unencrypted_rtp_transport, std::unique_ptr<webrtc::SrtpTransport> sdes_transport, std::unique_ptr<webrtc::DtlsSrtpTransport> dtls_srtp_transport, @@ -377,8 +378,8 @@ // Ice transport which may be used by any of upper-layer transports (below). // Owned by JsepTransport and guaranteed to outlive the transports below. - const std::unique_ptr<cricket::IceTransportInternal> ice_transport_; - const std::unique_ptr<cricket::IceTransportInternal> rtcp_ice_transport_; + const rtc::scoped_refptr<webrtc::IceTransportInterface> ice_transport_; + const rtc::scoped_refptr<webrtc::IceTransportInterface> rtcp_ice_transport_; // To avoid downcasting and make it type safe, keep three unique pointers for // different SRTP mode and only one of these is non-nullptr.
diff --git a/pc/jsep_transport_controller.cc b/pc/jsep_transport_controller.cc index d83b16e..41907c8 100644 --- a/pc/jsep_transport_controller.cc +++ b/pc/jsep_transport_controller.cc
@@ -14,6 +14,7 @@ #include <utility> #include "absl/algorithm/container.h" +#include "api/ice_transport_factory.h" #include "api/transport/datagram_transport_interface.h" #include "api/transport/media/media_transport_interface.h" #include "p2p/base/ice_transport_internal.h" @@ -90,6 +91,7 @@ // The |transport_observer| is assumed to be non-null. RTC_DCHECK(config_.transport_observer); RTC_DCHECK(config_.rtcp_handler); + RTC_DCHECK(config_.ice_transport_factory); } JsepTransportController::~JsepTransportController() { @@ -481,20 +483,18 @@ MaybeDestroyJsepTransport(mid); } -std::unique_ptr<cricket::IceTransportInternal> -JsepTransportController::CreateIceTransport(const std::string transport_name, +rtc::scoped_refptr<webrtc::IceTransportInterface> +JsepTransportController::CreateIceTransport(const std::string& transport_name, bool rtcp) { int component = rtcp ? cricket::ICE_CANDIDATE_COMPONENT_RTCP : cricket::ICE_CANDIDATE_COMPONENT_RTP; - if (config_.external_transport_factory) { - return config_.external_transport_factory->CreateIceTransport( - transport_name, component); - } else { - return std::make_unique<cricket::P2PTransportChannel>( - transport_name, component, port_allocator_, async_resolver_factory_, - config_.event_log); - } + IceTransportInit init; + init.set_port_allocator(port_allocator_); + init.set_async_resolver_factory(async_resolver_factory_); + init.set_event_log(config_.event_log); + return config_.ice_transport_factory->CreateIceTransport( + transport_name, component, std::move(init)); } std::unique_ptr<cricket::DtlsTransportInternal> @@ -517,8 +517,8 @@ // Otherwise, DTLS is still created. dtls = std::make_unique<cricket::NoOpDtlsTransport>(ice, config_.crypto_options); - } else if (config_.external_transport_factory) { - dtls = config_.external_transport_factory->CreateDtlsTransport( + } else if (config_.dtls_transport_factory) { + dtls = config_.dtls_transport_factory->CreateDtlsTransport( ice, config_.crypto_options); } else { dtls = std::make_unique<cricket::DtlsTransport>(ice, config_.crypto_options, @@ -1250,24 +1250,25 @@ "SDES and DTLS-SRTP cannot be enabled at the same time."); } - std::unique_ptr<cricket::IceTransportInternal> ice = + rtc::scoped_refptr<webrtc::IceTransportInterface> ice = CreateIceTransport(content_info.name, /*rtcp=*/false); + RTC_DCHECK(ice); std::unique_ptr<MediaTransportInterface> media_transport = MaybeCreateMediaTransport(content_info, description, local); if (media_transport) { media_transport_created_once_ = true; - media_transport->Connect(ice.get()); + media_transport->Connect(ice->internal()); } std::unique_ptr<DatagramTransportInterface> datagram_transport = MaybeCreateDatagramTransport(content_info, description, local); if (datagram_transport) { - datagram_transport->Connect(ice.get()); + datagram_transport->Connect(ice->internal()); } std::unique_ptr<cricket::DtlsTransportInternal> rtp_dtls_transport = - CreateDtlsTransport(content_info, ice.get(), nullptr); + CreateDtlsTransport(content_info, ice->internal(), nullptr); std::unique_ptr<cricket::DtlsTransportInternal> rtcp_dtls_transport; std::unique_ptr<RtpTransport> unencrypted_rtp_transport; @@ -1275,15 +1276,16 @@ std::unique_ptr<DtlsSrtpTransport> dtls_srtp_transport; std::unique_ptr<RtpTransportInternal> datagram_rtp_transport; - std::unique_ptr<cricket::IceTransportInternal> rtcp_ice; + rtc::scoped_refptr<webrtc::IceTransportInterface> rtcp_ice; if (config_.rtcp_mux_policy != PeerConnectionInterface::kRtcpMuxPolicyRequire && content_info.type == cricket::MediaProtocolType::kRtp) { RTC_DCHECK(media_transport == nullptr); RTC_DCHECK(datagram_transport == nullptr); rtcp_ice = CreateIceTransport(content_info.name, /*rtcp=*/true); - rtcp_dtls_transport = CreateDtlsTransport(content_info, rtcp_ice.get(), - /*datagram_transport=*/nullptr); + rtcp_dtls_transport = + CreateDtlsTransport(content_info, rtcp_ice->internal(), + /*datagram_transport=*/nullptr); } // Only create a datagram RTP transport if the datagram transport should be @@ -1300,8 +1302,8 @@ "transport is used."; RTC_DCHECK(!rtcp_dtls_transport); datagram_rtp_transport = std::make_unique<DatagramRtpTransport>( - content_info.media_description()->rtp_header_extensions(), ice.get(), - datagram_transport.get()); + content_info.media_description()->rtp_header_extensions(), + ice->internal(), datagram_transport.get()); } if (config_.disable_encryption) {
diff --git a/pc/jsep_transport_controller.h b/pc/jsep_transport_controller.h index bcaeed5..b07783c 100644 --- a/pc/jsep_transport_controller.h +++ b/pc/jsep_transport_controller.h
@@ -19,14 +19,15 @@ #include "api/candidate.h" #include "api/crypto/crypto_options.h" +#include "api/ice_transport_factory.h" #include "api/peer_connection_interface.h" #include "api/rtc_event_log/rtc_event_log.h" #include "api/transport/media/media_transport_config.h" #include "api/transport/media/media_transport_interface.h" #include "media/sctp/sctp_transport_internal.h" #include "p2p/base/dtls_transport.h" +#include "p2p/base/dtls_transport_factory.h" #include "p2p/base/p2p_transport_channel.h" -#include "p2p/base/transport_factory_interface.h" #include "pc/channel.h" #include "pc/dtls_srtp_transport.h" #include "pc/dtls_transport.h" @@ -91,7 +92,8 @@ bool disable_encryption = false; bool enable_external_auth = false; // Used to inject the ICE/DTLS transports created externally. - cricket::TransportFactoryInterface* external_transport_factory = nullptr; + webrtc::IceTransportFactory* ice_transport_factory = nullptr; + cricket::DtlsTransportFactory* dtls_transport_factory = nullptr; Observer* transport_observer = nullptr; // Must be provided and valid for the lifetime of the // JsepTransportController instance. @@ -404,8 +406,8 @@ const cricket::ContentInfo& content_info, cricket::IceTransportInternal* ice, DatagramTransportInterface* datagram_transport); - std::unique_ptr<cricket::IceTransportInternal> CreateIceTransport( - const std::string transport_name, + rtc::scoped_refptr<webrtc::IceTransportInterface> CreateIceTransport( + const std::string& transport_name, bool rtcp); std::unique_ptr<webrtc::RtpTransport> CreateUnencryptedRtpTransport(
diff --git a/pc/jsep_transport_controller_unittest.cc b/pc/jsep_transport_controller_unittest.cc index 408cb01..b96a999 100644 --- a/pc/jsep_transport_controller_unittest.cc +++ b/pc/jsep_transport_controller_unittest.cc
@@ -16,10 +16,10 @@ #include "api/test/fake_media_transport.h" #include "api/test/loopback_media_transport.h" #include "api/transport/media/media_transport_interface.h" +#include "p2p/base/dtls_transport_factory.h" #include "p2p/base/fake_dtls_transport.h" #include "p2p/base/fake_ice_transport.h" #include "p2p/base/no_op_dtls_transport.h" -#include "p2p/base/transport_factory_interface.h" #include "p2p/base/transport_info.h" #include "rtc_base/gunit.h" #include "rtc_base/thread.h" @@ -59,15 +59,20 @@ } // namespace -class FakeTransportFactory : public cricket::TransportFactoryInterface { +class FakeIceTransportFactory : public webrtc::IceTransportFactory { public: - std::unique_ptr<cricket::IceTransportInternal> CreateIceTransport( + ~FakeIceTransportFactory() override = default; + rtc::scoped_refptr<IceTransportInterface> CreateIceTransport( const std::string& transport_name, - int component) override { - return std::make_unique<cricket::FakeIceTransport>(transport_name, - component); + int component, + IceTransportInit init) override { + return new rtc::RefCountedObject<cricket::FakeIceTransportWrapper>( + std::make_unique<cricket::FakeIceTransport>(transport_name, component)); } +}; +class FakeDtlsTransportFactory : public cricket::DtlsTransportFactory { + public: std::unique_ptr<cricket::DtlsTransportInternal> CreateDtlsTransport( cricket::IceTransportInternal* ice, const webrtc::CryptoOptions& crypto_options) override { @@ -81,7 +86,8 @@ public sigslot::has_slots<> { public: JsepTransportControllerTest() : signaling_thread_(rtc::Thread::Current()) { - fake_transport_factory_ = std::make_unique<FakeTransportFactory>(); + fake_ice_transport_factory_ = std::make_unique<FakeIceTransportFactory>(); + fake_dtls_transport_factory_ = std::make_unique<FakeDtlsTransportFactory>(); } void CreateJsepTransportController( @@ -92,8 +98,8 @@ config.transport_observer = this; config.rtcp_handler = [](const rtc::CopyOnWriteBuffer& packet, int64_t packet_time_us) { RTC_NOTREACHED(); }; - // The tests only works with |fake_transport_factory|; - config.external_transport_factory = fake_transport_factory_.get(); + config.ice_transport_factory = fake_ice_transport_factory_.get(); + config.dtls_transport_factory = fake_dtls_transport_factory_.get(); // TODO(zstein): Provide an AsyncResolverFactory once it is required. transport_controller_ = std::make_unique<JsepTransportController>( signaling_thread, network_thread, port_allocator, nullptr, config); @@ -358,7 +364,8 @@ // |network_thread_| should be destroyed after |transport_controller_| std::unique_ptr<rtc::Thread> network_thread_; - std::unique_ptr<FakeTransportFactory> fake_transport_factory_; + std::unique_ptr<FakeIceTransportFactory> fake_ice_transport_factory_; + std::unique_ptr<FakeDtlsTransportFactory> fake_dtls_transport_factory_; rtc::Thread* const signaling_thread_ = nullptr; bool signaled_on_non_signaling_thread_ = false; // Used to verify the SignalRtpTransportChanged/SignalDtlsTransportChanged are
diff --git a/pc/jsep_transport_unittest.cc b/pc/jsep_transport_unittest.cc index 00f58f6..87d6e87 100644 --- a/pc/jsep_transport_unittest.cc +++ b/pc/jsep_transport_unittest.cc
@@ -14,12 +14,14 @@ #include <tuple> #include <utility> +#include "api/ice_transport_factory.h" #include "media/base/fake_rtp.h" #include "p2p/base/fake_dtls_transport.h" #include "p2p/base/fake_ice_transport.h" #include "rtc_base/gunit.h" namespace cricket { +namespace { using webrtc::SdpType; static const char kIceUfrag1[] = "U001"; @@ -40,6 +42,16 @@ SdpType remote_type; }; +rtc::scoped_refptr<webrtc::IceTransportInterface> CreateIceTransport( + std::unique_ptr<FakeIceTransport> internal) { + if (!internal) { + return nullptr; + } + + return new rtc::RefCountedObject<FakeIceTransportWrapper>( + std::move(internal)); +} + class JsepTransport2Test : public ::testing::Test, public sigslot::has_slots<> { protected: std::unique_ptr<webrtc::SrtpTransport> CreateSdesTransport( @@ -69,17 +81,21 @@ // FakeIceTransport. std::unique_ptr<JsepTransport> CreateJsepTransport2(bool rtcp_mux_enabled, SrtpMode srtp_mode) { - auto ice = std::make_unique<FakeIceTransport>(kTransportName, - ICE_CANDIDATE_COMPONENT_RTP); - auto rtp_dtls_transport = std::make_unique<FakeDtlsTransport>(ice.get()); + auto ice_internal = std::make_unique<FakeIceTransport>( + kTransportName, ICE_CANDIDATE_COMPONENT_RTP); + auto rtp_dtls_transport = + std::make_unique<FakeDtlsTransport>(ice_internal.get()); + auto ice = CreateIceTransport(std::move(ice_internal)); - std::unique_ptr<FakeIceTransport> rtcp_ice; + std::unique_ptr<FakeIceTransport> rtcp_ice_internal; std::unique_ptr<FakeDtlsTransport> rtcp_dtls_transport; if (!rtcp_mux_enabled) { - rtcp_ice = std::make_unique<FakeIceTransport>( + rtcp_ice_internal = std::make_unique<FakeIceTransport>( kTransportName, ICE_CANDIDATE_COMPONENT_RTCP); - rtcp_dtls_transport = std::make_unique<FakeDtlsTransport>(rtcp_ice.get()); + rtcp_dtls_transport = + std::make_unique<FakeDtlsTransport>(rtcp_ice_internal.get()); } + auto rtcp_ice = CreateIceTransport(std::move(rtcp_ice_internal)); std::unique_ptr<webrtc::RtpTransport> unencrypted_rtp_transport; std::unique_ptr<webrtc::SrtpTransport> sdes_transport; @@ -1246,5 +1262,5 @@ std::make_tuple(Scenario::kDtlsBeforeCallerSendOffer, false), std::make_tuple(Scenario::kDtlsBeforeCallerSetAnswer, false), std::make_tuple(Scenario::kDtlsAfterCallerSetAnswer, false))); - +} // namespace } // namespace cricket
diff --git a/pc/peer_connection.cc b/pc/peer_connection.cc index ea3d8e2..1d7b4ea 100644 --- a/pc/peer_connection.cc +++ b/pc/peer_connection.cc
@@ -1139,6 +1139,7 @@ observer_ = dependencies.observer; async_resolver_factory_ = std::move(dependencies.async_resolver_factory); port_allocator_ = std::move(dependencies.allocator); + ice_transport_factory_ = std::move(dependencies.ice_transport_factory); tls_cert_verifier_ = std::move(dependencies.tls_cert_verifier); cricket::ServerAddresses stun_servers; @@ -1334,6 +1335,8 @@ } } + config.ice_transport_factory = ice_transport_factory_.get(); + transport_controller_.reset(new JsepTransportController( signaling_thread(), network_thread(), port_allocator_.get(), async_resolver_factory_.get(), config));
diff --git a/pc/peer_connection.h b/pc/peer_connection.h index 302ff3b..cbff7e7 100644 --- a/pc/peer_connection.h +++ b/pc/peer_connection.h
@@ -1295,6 +1295,12 @@ std::unique_ptr<cricket::PortAllocator> port_allocator_; // TODO(bugs.webrtc.org/9987): Accessed on both // signaling and network thread. + std::unique_ptr<webrtc::IceTransportFactory> + ice_transport_factory_; // TODO(bugs.webrtc.org/9987): Accessed on the + // signaling thread but the underlying raw + // pointer is given to + // |jsep_transport_controller_| and used on the + // network thread. std::unique_ptr<rtc::SSLCertificateVerifier> tls_cert_verifier_; // TODO(bugs.webrtc.org/9987): Accessed on both // signaling and network thread.
diff --git a/pc/peer_connection_factory.cc b/pc/peer_connection_factory.cc index a1a9f04..8909ba9 100644 --- a/pc/peer_connection_factory.cc +++ b/pc/peer_connection_factory.cc
@@ -28,6 +28,7 @@ #include "media/base/rtp_data_engine.h" #include "media/sctp/sctp_transport.h" #include "p2p/base/basic_packet_socket_factory.h" +#include "p2p/base/default_ice_transport_factory.h" #include "p2p/client/basic_port_allocator.h" #include "pc/audio_track.h" #include "pc/local_audio_source.h" @@ -267,6 +268,11 @@ }); } + if (!dependencies.ice_transport_factory) { + dependencies.ice_transport_factory = + std::make_unique<DefaultIceTransportFactory>(); + } + // TODO(zstein): Once chromium injects its own AsyncResolverFactory, set // |dependencies.async_resolver_factory| to a new // |rtc::BasicAsyncResolverFactory| if no factory is provided.
diff --git a/pc/peer_connection_integrationtest.cc b/pc/peer_connection_integrationtest.cc index 536ad01..e59ce9a 100644 --- a/pc/peer_connection_integrationtest.cc +++ b/pc/peer_connection_integrationtest.cc
@@ -36,6 +36,7 @@ #include "media/engine/fake_webrtc_video_engine.h" #include "media/engine/webrtc_media_engine.h" #include "media/engine/webrtc_media_engine_defaults.h" +#include "p2p/base/fake_ice_transport.h" #include "p2p/base/mock_async_resolver.h" #include "p2p/base/p2p_constants.h" #include "p2p/base/port_interface.h" @@ -1166,6 +1167,34 @@ int callee_video_frames_expected_ = 0; }; +class MockIceTransport : public webrtc::IceTransportInterface { + public: + MockIceTransport(const std::string& name, int component) + : internal_(std::make_unique<cricket::FakeIceTransport>( + name, + component, + nullptr /* network_thread */)) {} + ~MockIceTransport() = default; + cricket::IceTransportInternal* internal() { return internal_.get(); } + + private: + std::unique_ptr<cricket::FakeIceTransport> internal_; +}; + +class MockIceTransportFactory : public IceTransportFactory { + public: + ~MockIceTransportFactory() override = default; + rtc::scoped_refptr<IceTransportInterface> CreateIceTransport( + const std::string& transport_name, + int component, + IceTransportInit init) { + RecordIceTransportCreated(); + return new rtc::RefCountedObject<MockIceTransport>(transport_name, + component); + } + MOCK_METHOD0(RecordIceTransportCreated, void()); +}; + // Tests two PeerConnections connecting to each other end-to-end, using a // virtual network, fake A/V capture and fake encoder/decoders. The // PeerConnections share the threads/socket servers, but use separate versions @@ -5529,6 +5558,25 @@ EXPECT_GT(client_2_cert_verifier->call_count_, 0u); } +// Test that the injected ICE transport factory is used to create ICE transports +// for WebRTC connections. +TEST_P(PeerConnectionIntegrationTest, IceTransportFactoryUsedForConnections) { + PeerConnectionInterface::RTCConfiguration default_config; + PeerConnectionDependencies dependencies(nullptr); + auto ice_transport_factory = std::make_unique<MockIceTransportFactory>(); + EXPECT_CALL(*ice_transport_factory, RecordIceTransportCreated()).Times(1); + dependencies.ice_transport_factory = std::move(ice_transport_factory); + auto wrapper = + CreatePeerConnectionWrapper("Caller", nullptr, &default_config, + std::move(dependencies), nullptr, nullptr); + ASSERT_TRUE(wrapper); + wrapper->CreateDataChannel(); + rtc::scoped_refptr<MockSetSessionDescriptionObserver> observer( + new rtc::RefCountedObject<MockSetSessionDescriptionObserver>()); + wrapper->pc()->SetLocalDescription(observer, + wrapper->CreateOfferAndWait().release()); +} + // Test that audio and video flow end-to-end when codec names don't use the // expected casing, given that they're supposed to be case insensitive. To test // this, all but one codec is removed from each media description, and its