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}
This commit is contained in:
Qingsi Wang 2019-11-15 12:33:05 -08:00 committed by Commit Bot
parent 53e157d25c
commit 25ec8882f7
19 changed files with 325 additions and 96 deletions

View File

@ -11,48 +11,16 @@
#ifndef API_ICE_TRANSPORT_FACTORY_H_ #ifndef API_ICE_TRANSPORT_FACTORY_H_
#define 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/ice_transport_interface.h"
#include "api/rtc_event_log/rtc_event_log.h"
#include "api/scoped_refptr.h" #include "api/scoped_refptr.h"
#include "rtc_base/system/rtc_export.h" #include "rtc_base/system/rtc_export.h"
namespace cricket { namespace cricket {
class PortAllocator; class PortAllocator;
} } // namespace cricket
namespace webrtc { 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 // Static factory for an IceTransport object that can be created
// without using a webrtc::PeerConnection. // without using a webrtc::PeerConnection.
// The returned object must be accessed and destroyed on the thread that // The returned object must be accessed and destroyed on the thread that

View File

@ -11,12 +11,17 @@
#ifndef API_ICE_TRANSPORT_INTERFACE_H_ #ifndef API_ICE_TRANSPORT_INTERFACE_H_
#define 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_error.h"
#include "api/rtc_event_log/rtc_event_log.h"
#include "api/scoped_refptr.h" #include "api/scoped_refptr.h"
#include "rtc_base/ref_count.h" #include "rtc_base/ref_count.h"
namespace cricket { namespace cricket {
class IceTransportInternal; class IceTransportInternal;
class PortAllocator;
} // namespace cricket } // namespace cricket
namespace webrtc { namespace webrtc {
@ -34,5 +39,57 @@ class IceTransportInterface : public rtc::RefCountInterface {
virtual cricket::IceTransportInternal* internal() = 0; 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 } // namespace webrtc
#endif // API_ICE_TRANSPORT_INTERFACE_H_ #endif // API_ICE_TRANSPORT_INTERFACE_H_

View File

@ -83,6 +83,7 @@
#include "api/data_channel_interface.h" #include "api/data_channel_interface.h"
#include "api/dtls_transport_interface.h" #include "api/dtls_transport_interface.h"
#include "api/fec_controller.h" #include "api/fec_controller.h"
#include "api/ice_transport_interface.h"
#include "api/jsep.h" #include "api/jsep.h"
#include "api/media_stream_interface.h" #include "api/media_stream_interface.h"
#include "api/neteq/neteq_factory.h" #include "api/neteq/neteq_factory.h"
@ -1288,6 +1289,7 @@ struct RTC_EXPORT PeerConnectionDependencies final {
std::unique_ptr<cricket::PortAllocator> allocator; std::unique_ptr<cricket::PortAllocator> allocator;
std::unique_ptr<rtc::PacketSocketFactory> packet_socket_factory; std::unique_ptr<rtc::PacketSocketFactory> packet_socket_factory;
std::unique_ptr<webrtc::AsyncResolverFactory> async_resolver_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::RTCCertificateGeneratorInterface> cert_generator;
std::unique_ptr<rtc::SSLCertificateVerifier> tls_cert_verifier; std::unique_ptr<rtc::SSLCertificateVerifier> tls_cert_verifier;
std::unique_ptr<webrtc::VideoBitrateAllocatorFactory> std::unique_ptr<webrtc::VideoBitrateAllocatorFactory>

View File

@ -41,8 +41,11 @@ rtc_library("rtc_p2p") {
"base/connection.h", "base/connection.h",
"base/connection_info.cc", "base/connection_info.cc",
"base/connection_info.h", "base/connection_info.h",
"base/default_ice_transport_factory.cc",
"base/default_ice_transport_factory.h",
"base/dtls_transport.cc", "base/dtls_transport.cc",
"base/dtls_transport.h", "base/dtls_transport.h",
"base/dtls_transport_factory.h",
"base/dtls_transport_internal.cc", "base/dtls_transport_internal.cc",
"base/dtls_transport_internal.h", "base/dtls_transport_internal.h",
"base/ice_credentials_iterator.cc", "base/ice_credentials_iterator.cc",
@ -80,7 +83,6 @@ rtc_library("rtc_p2p") {
"base/transport_description.h", "base/transport_description.h",
"base/transport_description_factory.cc", "base/transport_description_factory.cc",
"base/transport_description_factory.h", "base/transport_description_factory.h",
"base/transport_factory_interface.h",
"base/transport_info.h", "base/transport_info.h",
"base/turn_port.cc", "base/turn_port.cc",
"base/turn_port.h", "base/turn_port.h",
@ -132,6 +134,7 @@ if (rtc_include_tests) {
] ]
deps = [ deps = [
":rtc_p2p", ":rtc_p2p",
"../api:libjingle_peerconnection_api",
"../rtc_base", "../rtc_base",
"../rtc_base:rtc_base_approved", "../rtc_base:rtc_base_approved",
"//third_party/abseil-cpp/absl/algorithm:container", "//third_party/abseil-cpp/absl/algorithm:container",

View File

@ -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

View File

@ -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_

View File

@ -8,8 +8,8 @@
* be found in the AUTHORS file in the root of the source tree. * be found in the AUTHORS file in the root of the source tree.
*/ */
#ifndef P2P_BASE_TRANSPORT_FACTORY_INTERFACE_H_ #ifndef P2P_BASE_DTLS_TRANSPORT_FACTORY_H_
#define P2P_BASE_TRANSPORT_FACTORY_INTERFACE_H_ #define P2P_BASE_DTLS_TRANSPORT_FACTORY_H_
#include <memory> #include <memory>
#include <string> #include <string>
@ -19,18 +19,15 @@
namespace cricket { namespace cricket {
// This interface is used to create DTLS/ICE transports. The external transports // This interface is used to create DTLS transports. The external transports
// can be injected into the JsepTransportController through it. For example, the // can be injected into the JsepTransportController through it.
// FakeIceTransport/FakeDtlsTransport can be injected by setting a //
// FakeTransportFactory which implements this interface to the // TODO(qingsi): Remove this factory in favor of one that produces
// JsepTransportController. // DtlsTransportInterface given by the public API if this is going to be
class TransportFactoryInterface { // injectable.
class DtlsTransportFactory {
public: public:
virtual ~TransportFactoryInterface() {} virtual ~DtlsTransportFactory() = default;
virtual std::unique_ptr<IceTransportInternal> CreateIceTransport(
const std::string& transport_name,
int component) = 0;
virtual std::unique_ptr<DtlsTransportInternal> CreateDtlsTransport( virtual std::unique_ptr<DtlsTransportInternal> CreateDtlsTransport(
IceTransportInternal* ice, IceTransportInternal* ice,
@ -39,4 +36,4 @@ class TransportFactoryInterface {
} // namespace cricket } // namespace cricket
#endif // P2P_BASE_TRANSPORT_FACTORY_INTERFACE_H_ #endif // P2P_BASE_DTLS_TRANSPORT_FACTORY_H_

View File

@ -12,11 +12,13 @@
#define P2P_BASE_FAKE_ICE_TRANSPORT_H_ #define P2P_BASE_FAKE_ICE_TRANSPORT_H_
#include <map> #include <map>
#include <memory>
#include <string> #include <string>
#include <utility> #include <utility>
#include "absl/algorithm/container.h" #include "absl/algorithm/container.h"
#include "absl/types/optional.h" #include "absl/types/optional.h"
#include "api/ice_transport_interface.h"
#include "p2p/base/ice_transport_internal.h" #include "p2p/base/ice_transport_internal.h"
#include "rtc_base/async_invoker.h" #include "rtc_base/async_invoker.h"
#include "rtc_base/copy_on_write_buffer.h" #include "rtc_base/copy_on_write_buffer.h"
@ -330,6 +332,18 @@ class FakeIceTransport : public IceTransportInternal {
rtc::Thread* const network_thread_; 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 } // namespace cricket
#endif // P2P_BASE_FAKE_ICE_TRANSPORT_H_ #endif // P2P_BASE_FAKE_ICE_TRANSPORT_H_

View File

@ -87,6 +87,7 @@ rtc_library("rtc_pc_base") {
"../api:array_view", "../api:array_view",
"../api:audio_options_api", "../api:audio_options_api",
"../api:call_api", "../api:call_api",
"../api:ice_transport_factory",
"../api:libjingle_peerconnection_api", "../api:libjingle_peerconnection_api",
"../api:rtc_error", "../api:rtc_error",
"../api:rtp_headers", "../api:rtp_headers",
@ -227,6 +228,7 @@ rtc_library("peerconnection") {
"../api:audio_options_api", "../api:audio_options_api",
"../api:call_api", "../api:call_api",
"../api:fec_controller_api", "../api:fec_controller_api",
"../api:ice_transport_factory",
"../api:libjingle_peerconnection_api", "../api:libjingle_peerconnection_api",
"../api:media_stream_interface", "../api:media_stream_interface",
"../api:network_state_predictor_api", "../api:network_state_predictor_api",
@ -577,6 +579,7 @@ if (rtc_include_tests) {
"../modules/audio_device:audio_device_api", "../modules/audio_device:audio_device_api",
"../modules/audio_processing:audio_processing_statistics", "../modules/audio_processing:audio_processing_statistics",
"../modules/rtp_rtcp:rtp_rtcp_format", "../modules/rtp_rtcp:rtp_rtcp_format",
"../p2p:fake_ice_transport",
"../p2p:fake_port_allocator", "../p2p:fake_port_allocator",
"../rtc_base:checks", "../rtc_base:checks",
"../rtc_base:gunit_helpers", "../rtc_base:gunit_helpers",

View File

@ -102,8 +102,8 @@ JsepTransportDescription& JsepTransportDescription::operator=(
JsepTransport::JsepTransport( JsepTransport::JsepTransport(
const std::string& mid, const std::string& mid,
const rtc::scoped_refptr<rtc::RTCCertificate>& local_certificate, const rtc::scoped_refptr<rtc::RTCCertificate>& local_certificate,
std::unique_ptr<cricket::IceTransportInternal> ice_transport, rtc::scoped_refptr<webrtc::IceTransportInterface> ice_transport,
std::unique_ptr<cricket::IceTransportInternal> rtcp_ice_transport, rtc::scoped_refptr<webrtc::IceTransportInterface> rtcp_ice_transport,
std::unique_ptr<webrtc::RtpTransport> unencrypted_rtp_transport, std::unique_ptr<webrtc::RtpTransport> unencrypted_rtp_transport,
std::unique_ptr<webrtc::SrtpTransport> sdes_transport, std::unique_ptr<webrtc::SrtpTransport> sdes_transport,
std::unique_ptr<webrtc::DtlsSrtpTransport> dtls_srtp_transport, std::unique_ptr<webrtc::DtlsSrtpTransport> dtls_srtp_transport,

View File

@ -18,6 +18,7 @@
#include "absl/types/optional.h" #include "absl/types/optional.h"
#include "api/candidate.h" #include "api/candidate.h"
#include "api/ice_transport_interface.h"
#include "api/jsep.h" #include "api/jsep.h"
#include "api/transport/datagram_transport_interface.h" #include "api/transport/datagram_transport_interface.h"
#include "api/transport/media/media_transport_interface.h" #include "api/transport/media/media_transport_interface.h"
@ -101,8 +102,8 @@ class JsepTransport : public sigslot::has_slots<>,
JsepTransport( JsepTransport(
const std::string& mid, const std::string& mid,
const rtc::scoped_refptr<rtc::RTCCertificate>& local_certificate, const rtc::scoped_refptr<rtc::RTCCertificate>& local_certificate,
std::unique_ptr<cricket::IceTransportInternal> ice_transport, rtc::scoped_refptr<webrtc::IceTransportInterface> ice_transport,
std::unique_ptr<cricket::IceTransportInternal> rtcp_ice_transport, rtc::scoped_refptr<webrtc::IceTransportInterface> rtcp_ice_transport,
std::unique_ptr<webrtc::RtpTransport> unencrypted_rtp_transport, std::unique_ptr<webrtc::RtpTransport> unencrypted_rtp_transport,
std::unique_ptr<webrtc::SrtpTransport> sdes_transport, std::unique_ptr<webrtc::SrtpTransport> sdes_transport,
std::unique_ptr<webrtc::DtlsSrtpTransport> dtls_srtp_transport, std::unique_ptr<webrtc::DtlsSrtpTransport> dtls_srtp_transport,
@ -377,8 +378,8 @@ class JsepTransport : public sigslot::has_slots<>,
// Ice transport which may be used by any of upper-layer transports (below). // Ice transport which may be used by any of upper-layer transports (below).
// Owned by JsepTransport and guaranteed to outlive the transports below. // Owned by JsepTransport and guaranteed to outlive the transports below.
const std::unique_ptr<cricket::IceTransportInternal> ice_transport_; const rtc::scoped_refptr<webrtc::IceTransportInterface> ice_transport_;
const std::unique_ptr<cricket::IceTransportInternal> rtcp_ice_transport_; const rtc::scoped_refptr<webrtc::IceTransportInterface> rtcp_ice_transport_;
// To avoid downcasting and make it type safe, keep three unique pointers for // To avoid downcasting and make it type safe, keep three unique pointers for
// different SRTP mode and only one of these is non-nullptr. // different SRTP mode and only one of these is non-nullptr.

View File

@ -14,6 +14,7 @@
#include <utility> #include <utility>
#include "absl/algorithm/container.h" #include "absl/algorithm/container.h"
#include "api/ice_transport_factory.h"
#include "api/transport/datagram_transport_interface.h" #include "api/transport/datagram_transport_interface.h"
#include "api/transport/media/media_transport_interface.h" #include "api/transport/media/media_transport_interface.h"
#include "p2p/base/ice_transport_internal.h" #include "p2p/base/ice_transport_internal.h"
@ -90,6 +91,7 @@ JsepTransportController::JsepTransportController(
// The |transport_observer| is assumed to be non-null. // The |transport_observer| is assumed to be non-null.
RTC_DCHECK(config_.transport_observer); RTC_DCHECK(config_.transport_observer);
RTC_DCHECK(config_.rtcp_handler); RTC_DCHECK(config_.rtcp_handler);
RTC_DCHECK(config_.ice_transport_factory);
} }
JsepTransportController::~JsepTransportController() { JsepTransportController::~JsepTransportController() {
@ -481,20 +483,18 @@ void JsepTransportController::RollbackTransportForMid(const std::string& mid) {
MaybeDestroyJsepTransport(mid); MaybeDestroyJsepTransport(mid);
} }
std::unique_ptr<cricket::IceTransportInternal> rtc::scoped_refptr<webrtc::IceTransportInterface>
JsepTransportController::CreateIceTransport(const std::string transport_name, JsepTransportController::CreateIceTransport(const std::string& transport_name,
bool rtcp) { bool rtcp) {
int component = rtcp ? cricket::ICE_CANDIDATE_COMPONENT_RTCP int component = rtcp ? cricket::ICE_CANDIDATE_COMPONENT_RTCP
: cricket::ICE_CANDIDATE_COMPONENT_RTP; : cricket::ICE_CANDIDATE_COMPONENT_RTP;
if (config_.external_transport_factory) { IceTransportInit init;
return config_.external_transport_factory->CreateIceTransport( init.set_port_allocator(port_allocator_);
transport_name, component); init.set_async_resolver_factory(async_resolver_factory_);
} else { init.set_event_log(config_.event_log);
return std::make_unique<cricket::P2PTransportChannel>( return config_.ice_transport_factory->CreateIceTransport(
transport_name, component, port_allocator_, async_resolver_factory_, transport_name, component, std::move(init));
config_.event_log);
}
} }
std::unique_ptr<cricket::DtlsTransportInternal> std::unique_ptr<cricket::DtlsTransportInternal>
@ -517,8 +517,8 @@ JsepTransportController::CreateDtlsTransport(
// Otherwise, DTLS is still created. // Otherwise, DTLS is still created.
dtls = std::make_unique<cricket::NoOpDtlsTransport>(ice, dtls = std::make_unique<cricket::NoOpDtlsTransport>(ice,
config_.crypto_options); config_.crypto_options);
} else if (config_.external_transport_factory) { } else if (config_.dtls_transport_factory) {
dtls = config_.external_transport_factory->CreateDtlsTransport( dtls = config_.dtls_transport_factory->CreateDtlsTransport(
ice, config_.crypto_options); ice, config_.crypto_options);
} else { } else {
dtls = std::make_unique<cricket::DtlsTransport>(ice, config_.crypto_options, dtls = std::make_unique<cricket::DtlsTransport>(ice, config_.crypto_options,
@ -1250,24 +1250,25 @@ RTCError JsepTransportController::MaybeCreateJsepTransport(
"SDES and DTLS-SRTP cannot be enabled at the same time."); "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); CreateIceTransport(content_info.name, /*rtcp=*/false);
RTC_DCHECK(ice);
std::unique_ptr<MediaTransportInterface> media_transport = std::unique_ptr<MediaTransportInterface> media_transport =
MaybeCreateMediaTransport(content_info, description, local); MaybeCreateMediaTransport(content_info, description, local);
if (media_transport) { if (media_transport) {
media_transport_created_once_ = true; media_transport_created_once_ = true;
media_transport->Connect(ice.get()); media_transport->Connect(ice->internal());
} }
std::unique_ptr<DatagramTransportInterface> datagram_transport = std::unique_ptr<DatagramTransportInterface> datagram_transport =
MaybeCreateDatagramTransport(content_info, description, local); MaybeCreateDatagramTransport(content_info, description, local);
if (datagram_transport) { if (datagram_transport) {
datagram_transport->Connect(ice.get()); datagram_transport->Connect(ice->internal());
} }
std::unique_ptr<cricket::DtlsTransportInternal> rtp_dtls_transport = 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<cricket::DtlsTransportInternal> rtcp_dtls_transport;
std::unique_ptr<RtpTransport> unencrypted_rtp_transport; std::unique_ptr<RtpTransport> unencrypted_rtp_transport;
@ -1275,15 +1276,16 @@ RTCError JsepTransportController::MaybeCreateJsepTransport(
std::unique_ptr<DtlsSrtpTransport> dtls_srtp_transport; std::unique_ptr<DtlsSrtpTransport> dtls_srtp_transport;
std::unique_ptr<RtpTransportInternal> datagram_rtp_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 != if (config_.rtcp_mux_policy !=
PeerConnectionInterface::kRtcpMuxPolicyRequire && PeerConnectionInterface::kRtcpMuxPolicyRequire &&
content_info.type == cricket::MediaProtocolType::kRtp) { content_info.type == cricket::MediaProtocolType::kRtp) {
RTC_DCHECK(media_transport == nullptr); RTC_DCHECK(media_transport == nullptr);
RTC_DCHECK(datagram_transport == nullptr); RTC_DCHECK(datagram_transport == nullptr);
rtcp_ice = CreateIceTransport(content_info.name, /*rtcp=*/true); rtcp_ice = CreateIceTransport(content_info.name, /*rtcp=*/true);
rtcp_dtls_transport = CreateDtlsTransport(content_info, rtcp_ice.get(), rtcp_dtls_transport =
/*datagram_transport=*/nullptr); CreateDtlsTransport(content_info, rtcp_ice->internal(),
/*datagram_transport=*/nullptr);
} }
// Only create a datagram RTP transport if the datagram transport should be // Only create a datagram RTP transport if the datagram transport should be
@ -1300,8 +1302,8 @@ RTCError JsepTransportController::MaybeCreateJsepTransport(
"transport is used."; "transport is used.";
RTC_DCHECK(!rtcp_dtls_transport); RTC_DCHECK(!rtcp_dtls_transport);
datagram_rtp_transport = std::make_unique<DatagramRtpTransport>( datagram_rtp_transport = std::make_unique<DatagramRtpTransport>(
content_info.media_description()->rtp_header_extensions(), ice.get(), content_info.media_description()->rtp_header_extensions(),
datagram_transport.get()); ice->internal(), datagram_transport.get());
} }
if (config_.disable_encryption) { if (config_.disable_encryption) {

View File

@ -19,14 +19,15 @@
#include "api/candidate.h" #include "api/candidate.h"
#include "api/crypto/crypto_options.h" #include "api/crypto/crypto_options.h"
#include "api/ice_transport_factory.h"
#include "api/peer_connection_interface.h" #include "api/peer_connection_interface.h"
#include "api/rtc_event_log/rtc_event_log.h" #include "api/rtc_event_log/rtc_event_log.h"
#include "api/transport/media/media_transport_config.h" #include "api/transport/media/media_transport_config.h"
#include "api/transport/media/media_transport_interface.h" #include "api/transport/media/media_transport_interface.h"
#include "media/sctp/sctp_transport_internal.h" #include "media/sctp/sctp_transport_internal.h"
#include "p2p/base/dtls_transport.h" #include "p2p/base/dtls_transport.h"
#include "p2p/base/dtls_transport_factory.h"
#include "p2p/base/p2p_transport_channel.h" #include "p2p/base/p2p_transport_channel.h"
#include "p2p/base/transport_factory_interface.h"
#include "pc/channel.h" #include "pc/channel.h"
#include "pc/dtls_srtp_transport.h" #include "pc/dtls_srtp_transport.h"
#include "pc/dtls_transport.h" #include "pc/dtls_transport.h"
@ -91,7 +92,8 @@ class JsepTransportController : public sigslot::has_slots<> {
bool disable_encryption = false; bool disable_encryption = false;
bool enable_external_auth = false; bool enable_external_auth = false;
// Used to inject the ICE/DTLS transports created externally. // 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; Observer* transport_observer = nullptr;
// Must be provided and valid for the lifetime of the // Must be provided and valid for the lifetime of the
// JsepTransportController instance. // JsepTransportController instance.
@ -404,8 +406,8 @@ class JsepTransportController : public sigslot::has_slots<> {
const cricket::ContentInfo& content_info, const cricket::ContentInfo& content_info,
cricket::IceTransportInternal* ice, cricket::IceTransportInternal* ice,
DatagramTransportInterface* datagram_transport); DatagramTransportInterface* datagram_transport);
std::unique_ptr<cricket::IceTransportInternal> CreateIceTransport( rtc::scoped_refptr<webrtc::IceTransportInterface> CreateIceTransport(
const std::string transport_name, const std::string& transport_name,
bool rtcp); bool rtcp);
std::unique_ptr<webrtc::RtpTransport> CreateUnencryptedRtpTransport( std::unique_ptr<webrtc::RtpTransport> CreateUnencryptedRtpTransport(

View File

@ -16,10 +16,10 @@
#include "api/test/fake_media_transport.h" #include "api/test/fake_media_transport.h"
#include "api/test/loopback_media_transport.h" #include "api/test/loopback_media_transport.h"
#include "api/transport/media/media_transport_interface.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_dtls_transport.h"
#include "p2p/base/fake_ice_transport.h" #include "p2p/base/fake_ice_transport.h"
#include "p2p/base/no_op_dtls_transport.h" #include "p2p/base/no_op_dtls_transport.h"
#include "p2p/base/transport_factory_interface.h"
#include "p2p/base/transport_info.h" #include "p2p/base/transport_info.h"
#include "rtc_base/gunit.h" #include "rtc_base/gunit.h"
#include "rtc_base/thread.h" #include "rtc_base/thread.h"
@ -59,15 +59,20 @@ void AddCryptoSettings(cricket::SessionDescription* description) {
} // namespace } // namespace
class FakeTransportFactory : public cricket::TransportFactoryInterface { class FakeIceTransportFactory : public webrtc::IceTransportFactory {
public: public:
std::unique_ptr<cricket::IceTransportInternal> CreateIceTransport( ~FakeIceTransportFactory() override = default;
rtc::scoped_refptr<IceTransportInterface> CreateIceTransport(
const std::string& transport_name, const std::string& transport_name,
int component) override { int component,
return std::make_unique<cricket::FakeIceTransport>(transport_name, IceTransportInit init) override {
component); 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( std::unique_ptr<cricket::DtlsTransportInternal> CreateDtlsTransport(
cricket::IceTransportInternal* ice, cricket::IceTransportInternal* ice,
const webrtc::CryptoOptions& crypto_options) override { const webrtc::CryptoOptions& crypto_options) override {
@ -81,7 +86,8 @@ class JsepTransportControllerTest : public JsepTransportController::Observer,
public sigslot::has_slots<> { public sigslot::has_slots<> {
public: public:
JsepTransportControllerTest() : signaling_thread_(rtc::Thread::Current()) { 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( void CreateJsepTransportController(
@ -92,8 +98,8 @@ class JsepTransportControllerTest : public JsepTransportController::Observer,
config.transport_observer = this; config.transport_observer = this;
config.rtcp_handler = [](const rtc::CopyOnWriteBuffer& packet, config.rtcp_handler = [](const rtc::CopyOnWriteBuffer& packet,
int64_t packet_time_us) { RTC_NOTREACHED(); }; int64_t packet_time_us) { RTC_NOTREACHED(); };
// The tests only works with |fake_transport_factory|; config.ice_transport_factory = fake_ice_transport_factory_.get();
config.external_transport_factory = fake_transport_factory_.get(); config.dtls_transport_factory = fake_dtls_transport_factory_.get();
// TODO(zstein): Provide an AsyncResolverFactory once it is required. // TODO(zstein): Provide an AsyncResolverFactory once it is required.
transport_controller_ = std::make_unique<JsepTransportController>( transport_controller_ = std::make_unique<JsepTransportController>(
signaling_thread, network_thread, port_allocator, nullptr, config); signaling_thread, network_thread, port_allocator, nullptr, config);
@ -358,7 +364,8 @@ class JsepTransportControllerTest : public JsepTransportController::Observer,
// |network_thread_| should be destroyed after |transport_controller_| // |network_thread_| should be destroyed after |transport_controller_|
std::unique_ptr<rtc::Thread> network_thread_; 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; rtc::Thread* const signaling_thread_ = nullptr;
bool signaled_on_non_signaling_thread_ = false; bool signaled_on_non_signaling_thread_ = false;
// Used to verify the SignalRtpTransportChanged/SignalDtlsTransportChanged are // Used to verify the SignalRtpTransportChanged/SignalDtlsTransportChanged are

View File

@ -14,12 +14,14 @@
#include <tuple> #include <tuple>
#include <utility> #include <utility>
#include "api/ice_transport_factory.h"
#include "media/base/fake_rtp.h" #include "media/base/fake_rtp.h"
#include "p2p/base/fake_dtls_transport.h" #include "p2p/base/fake_dtls_transport.h"
#include "p2p/base/fake_ice_transport.h" #include "p2p/base/fake_ice_transport.h"
#include "rtc_base/gunit.h" #include "rtc_base/gunit.h"
namespace cricket { namespace cricket {
namespace {
using webrtc::SdpType; using webrtc::SdpType;
static const char kIceUfrag1[] = "U001"; static const char kIceUfrag1[] = "U001";
@ -40,6 +42,16 @@ struct NegotiateRoleParams {
SdpType remote_type; 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<> { class JsepTransport2Test : public ::testing::Test, public sigslot::has_slots<> {
protected: protected:
std::unique_ptr<webrtc::SrtpTransport> CreateSdesTransport( std::unique_ptr<webrtc::SrtpTransport> CreateSdesTransport(
@ -69,17 +81,21 @@ class JsepTransport2Test : public ::testing::Test, public sigslot::has_slots<> {
// FakeIceTransport. // FakeIceTransport.
std::unique_ptr<JsepTransport> CreateJsepTransport2(bool rtcp_mux_enabled, std::unique_ptr<JsepTransport> CreateJsepTransport2(bool rtcp_mux_enabled,
SrtpMode srtp_mode) { SrtpMode srtp_mode) {
auto ice = std::make_unique<FakeIceTransport>(kTransportName, auto ice_internal = std::make_unique<FakeIceTransport>(
ICE_CANDIDATE_COMPONENT_RTP); kTransportName, ICE_CANDIDATE_COMPONENT_RTP);
auto rtp_dtls_transport = std::make_unique<FakeDtlsTransport>(ice.get()); 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; std::unique_ptr<FakeDtlsTransport> rtcp_dtls_transport;
if (!rtcp_mux_enabled) { if (!rtcp_mux_enabled) {
rtcp_ice = std::make_unique<FakeIceTransport>( rtcp_ice_internal = std::make_unique<FakeIceTransport>(
kTransportName, ICE_CANDIDATE_COMPONENT_RTCP); 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::RtpTransport> unencrypted_rtp_transport;
std::unique_ptr<webrtc::SrtpTransport> sdes_transport; std::unique_ptr<webrtc::SrtpTransport> sdes_transport;
@ -1246,5 +1262,5 @@ INSTANTIATE_TEST_SUITE_P(
std::make_tuple(Scenario::kDtlsBeforeCallerSendOffer, false), std::make_tuple(Scenario::kDtlsBeforeCallerSendOffer, false),
std::make_tuple(Scenario::kDtlsBeforeCallerSetAnswer, false), std::make_tuple(Scenario::kDtlsBeforeCallerSetAnswer, false),
std::make_tuple(Scenario::kDtlsAfterCallerSetAnswer, false))); std::make_tuple(Scenario::kDtlsAfterCallerSetAnswer, false)));
} // namespace
} // namespace cricket } // namespace cricket

View File

@ -1139,6 +1139,7 @@ bool PeerConnection::Initialize(
observer_ = dependencies.observer; observer_ = dependencies.observer;
async_resolver_factory_ = std::move(dependencies.async_resolver_factory); async_resolver_factory_ = std::move(dependencies.async_resolver_factory);
port_allocator_ = std::move(dependencies.allocator); port_allocator_ = std::move(dependencies.allocator);
ice_transport_factory_ = std::move(dependencies.ice_transport_factory);
tls_cert_verifier_ = std::move(dependencies.tls_cert_verifier); tls_cert_verifier_ = std::move(dependencies.tls_cert_verifier);
cricket::ServerAddresses stun_servers; cricket::ServerAddresses stun_servers;
@ -1334,6 +1335,8 @@ bool PeerConnection::Initialize(
} }
} }
config.ice_transport_factory = ice_transport_factory_.get();
transport_controller_.reset(new JsepTransportController( transport_controller_.reset(new JsepTransportController(
signaling_thread(), network_thread(), port_allocator_.get(), signaling_thread(), network_thread(), port_allocator_.get(),
async_resolver_factory_.get(), config)); async_resolver_factory_.get(), config));

View File

@ -1295,6 +1295,12 @@ class PeerConnection : public PeerConnectionInternal,
std::unique_ptr<cricket::PortAllocator> std::unique_ptr<cricket::PortAllocator>
port_allocator_; // TODO(bugs.webrtc.org/9987): Accessed on both port_allocator_; // TODO(bugs.webrtc.org/9987): Accessed on both
// signaling and network thread. // 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> std::unique_ptr<rtc::SSLCertificateVerifier>
tls_cert_verifier_; // TODO(bugs.webrtc.org/9987): Accessed on both tls_cert_verifier_; // TODO(bugs.webrtc.org/9987): Accessed on both
// signaling and network thread. // signaling and network thread.

View File

@ -28,6 +28,7 @@
#include "media/base/rtp_data_engine.h" #include "media/base/rtp_data_engine.h"
#include "media/sctp/sctp_transport.h" #include "media/sctp/sctp_transport.h"
#include "p2p/base/basic_packet_socket_factory.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 "p2p/client/basic_port_allocator.h"
#include "pc/audio_track.h" #include "pc/audio_track.h"
#include "pc/local_audio_source.h" #include "pc/local_audio_source.h"
@ -267,6 +268,11 @@ PeerConnectionFactory::CreatePeerConnection(
}); });
} }
if (!dependencies.ice_transport_factory) {
dependencies.ice_transport_factory =
std::make_unique<DefaultIceTransportFactory>();
}
// TODO(zstein): Once chromium injects its own AsyncResolverFactory, set // TODO(zstein): Once chromium injects its own AsyncResolverFactory, set
// |dependencies.async_resolver_factory| to a new // |dependencies.async_resolver_factory| to a new
// |rtc::BasicAsyncResolverFactory| if no factory is provided. // |rtc::BasicAsyncResolverFactory| if no factory is provided.

View File

@ -36,6 +36,7 @@
#include "media/engine/fake_webrtc_video_engine.h" #include "media/engine/fake_webrtc_video_engine.h"
#include "media/engine/webrtc_media_engine.h" #include "media/engine/webrtc_media_engine.h"
#include "media/engine/webrtc_media_engine_defaults.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/mock_async_resolver.h"
#include "p2p/base/p2p_constants.h" #include "p2p/base/p2p_constants.h"
#include "p2p/base/port_interface.h" #include "p2p/base/port_interface.h"
@ -1166,6 +1167,34 @@ class MediaExpectations {
int callee_video_frames_expected_ = 0; 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 // Tests two PeerConnections connecting to each other end-to-end, using a
// virtual network, fake A/V capture and fake encoder/decoders. The // virtual network, fake A/V capture and fake encoder/decoders. The
// PeerConnections share the threads/socket servers, but use separate versions // PeerConnections share the threads/socket servers, but use separate versions
@ -5529,6 +5558,25 @@ TEST_P(PeerConnectionIntegrationTest,
EXPECT_GT(client_2_cert_verifier->call_count_, 0u); 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 // 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 // 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 // this, all but one codec is removed from each media description, and its