Add API for returning a webrtc::DtlsTransport for a MID on a PC

This includes a refactoring of jseptransport to store a refcounted
object instead of a std::unique_ptr to the cricket::DtlsTransport.

Bug: chromium:907849
Change-Id: Ib557ce72c2e6ce8af297c2b8deb7ec3a103d6d31
Reviewed-on: https://webrtc-review.googlesource.com/c/111920
Reviewed-by: Fredrik Solenberg <solenberg@webrtc.org>
Commit-Queue: Harald Alvestrand <hta@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#25831}
This commit is contained in:
Harald Alvestrand 2018-11-28 16:47:46 +01:00 committed by Commit Bot
parent 3e70781361
commit ad88c886d7
18 changed files with 231 additions and 39 deletions

View File

@ -87,6 +87,7 @@ rtc_static_library("libjingle_peerconnection_api") {
"cryptoparams.h",
"datachannelinterface.cc",
"datachannelinterface.h",
"dtlstransportinterface.h",
"dtmfsenderinterface.h",
"jsep.cc",
"jsep.h",

View File

@ -75,6 +75,10 @@ specific_include_rules = {
"+rtc_base/refcount.h",
],
"dtlstransportinterface\.h": [
"+rtc_base/refcount.h",
],
"dtmfsenderinterface\.h": [
"+rtc_base/refcount.h",
],

View File

@ -0,0 +1,30 @@
/*
* 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 API_DTLSTRANSPORTINTERFACE_H_
#define API_DTLSTRANSPORTINTERFACE_H_
#include "rtc_base/refcount.h"
namespace webrtc {
// A DTLS transport, as represented to the outside world.
// Its role is to report state changes and errors, and make sure information
// about remote certificates is available.
class DtlsTransportInterface : public rtc::RefCountInterface {
public:
// TODO(hta): Need a notifier interface to transmit state changes and
// error events. The generic NotifierInterface of mediasteraminterface.h
// may be suitable, or may be copyable.
};
} // namespace webrtc
#endif // API_DTLSTRANSPORTINTERFACE_H_

View File

@ -9,6 +9,7 @@
*/
#include "api/peerconnectioninterface.h"
#include "api/dtlstransportinterface.h"
namespace webrtc {
@ -175,6 +176,11 @@ bool PeerConnectionInterface::StartRtcEventLog(
return false;
}
rtc::scoped_refptr<DtlsTransportInterface>
PeerConnectionInterface::LookupDtlsTransportByMid(const std::string& mid) {
return nullptr;
}
PeerConnectionInterface::BitrateParameters::BitrateParameters() = default;
PeerConnectionInterface::BitrateParameters::~BitrateParameters() = default;

View File

@ -129,6 +129,7 @@ namespace webrtc {
class AudioDeviceModule;
class AudioMixer;
class AudioProcessing;
class DtlsTransportInterface;
class MediaConstraintsInterface;
class VideoDecoderFactory;
class VideoEncoderFactory;
@ -1029,6 +1030,14 @@ class PeerConnectionInterface : public rtc::RefCountInterface {
// TODO(henrika): deprecate and remove this.
virtual void SetAudioRecording(bool recording) {}
// Looks up the DtlsTransport associated with a MID value.
// In the Javascript API, DtlsTransport is a property of a sender, but
// because the PeerConnection owns the DtlsTransport in this implementation,
// it is better to look them up on the PeerConnection.
virtual rtc::scoped_refptr<DtlsTransportInterface> LookupDtlsTransportByMid(
const std::string& mid);
// TODO(hta): Remove default implementation.
// Returns the current SignalingState.
virtual SignalingState signaling_state() = 0;

View File

@ -36,6 +36,8 @@ rtc_static_library("rtc_pc_base") {
"channelmanager.h",
"dtlssrtptransport.cc",
"dtlssrtptransport.h",
"dtlstransport.cc",
"dtlstransport.h",
"externalhmac.cc",
"externalhmac.h",
"jseptransport.cc",

23
pc/dtlstransport.cc Normal file
View File

@ -0,0 +1,23 @@
/*
* Copyright 2018 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "pc/dtlstransport.h"
#include <utility>
namespace webrtc {
DtlsTransport::DtlsTransport(
std::unique_ptr<cricket::DtlsTransportInternal> internal)
: internal_dtls_transport_(std::move(internal)) {
RTC_DCHECK(internal_dtls_transport_.get());
}
} // namespace webrtc

36
pc/dtlstransport.h Normal file
View File

@ -0,0 +1,36 @@
/*
* 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 PC_DTLSTRANSPORT_H_
#define PC_DTLSTRANSPORT_H_
#include <memory>
#include "api/dtlstransportinterface.h"
#include "p2p/base/dtlstransport.h"
namespace webrtc {
// This implementation wraps a cricket::DtlsTransport, and takes
// ownership of it.
class DtlsTransport : public DtlsTransportInterface {
public:
explicit DtlsTransport(
std::unique_ptr<cricket::DtlsTransportInternal> internal);
cricket::DtlsTransportInternal* internal() {
return internal_dtls_transport_.get();
}
private:
std::unique_ptr<cricket::DtlsTransportInternal> internal_dtls_transport_;
};
} // namespace webrtc
#endif // PC_DTLSTRANSPORT_H_

View File

@ -101,8 +101,15 @@ JsepTransport::JsepTransport(
std::unique_ptr<webrtc::MediaTransportInterface> media_transport)
: mid_(mid),
local_certificate_(local_certificate),
rtp_dtls_transport_(std::move(rtp_dtls_transport)),
rtcp_dtls_transport_(std::move(rtcp_dtls_transport)),
rtp_dtls_transport_(
rtp_dtls_transport ? new rtc::RefCountedObject<webrtc::DtlsTransport>(
std::move(rtp_dtls_transport))
: nullptr),
rtcp_dtls_transport_(
rtcp_dtls_transport
? new rtc::RefCountedObject<webrtc::DtlsTransport>(
std::move(rtcp_dtls_transport))
: nullptr),
media_transport_(std::move(media_transport)) {
RTC_DCHECK(rtp_dtls_transport_);
if (unencrypted_rtp_transport) {
@ -185,10 +192,10 @@ webrtc::RTCError JsepTransport::SetLocalJsepTransportDescription(
}
}
SetLocalIceParameters(rtp_dtls_transport_->ice_transport());
SetLocalIceParameters(rtp_dtls_transport_->internal()->ice_transport());
if (rtcp_dtls_transport_) {
SetLocalIceParameters(rtcp_dtls_transport_->ice_transport());
SetLocalIceParameters(rtcp_dtls_transport_->internal()->ice_transport());
}
// If PRANSWER/ANSWER is set, we should decide transport protocol type.
@ -248,10 +255,10 @@ webrtc::RTCError JsepTransport::SetRemoteJsepTransportDescription(
}
remote_description_.reset(new JsepTransportDescription(jsep_description));
SetRemoteIceParameters(rtp_dtls_transport_->ice_transport());
SetRemoteIceParameters(rtp_dtls_transport_->internal()->ice_transport());
if (rtcp_dtls_transport_) {
SetRemoteIceParameters(rtcp_dtls_transport_->ice_transport());
SetRemoteIceParameters(rtcp_dtls_transport_->internal()->ice_transport());
}
// If PRANSWER/ANSWER is set, we should decide transport protocol type.
@ -278,14 +285,14 @@ webrtc::RTCError JsepTransport::AddRemoteCandidates(
for (const cricket::Candidate& candidate : candidates) {
auto transport =
candidate.component() == cricket::ICE_CANDIDATE_COMPONENT_RTP
? rtp_dtls_transport_.get()
: rtcp_dtls_transport_.get();
? rtp_dtls_transport_
: rtcp_dtls_transport_;
if (!transport) {
return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
"Candidate has an unknown component: " +
candidate.ToString() + " for mid " + mid());
}
transport->ice_transport()->AddRemoteCandidate(candidate);
transport->internal()->ice_transport()->AddRemoteCandidate(candidate);
}
return webrtc::RTCError::OK();
}
@ -300,7 +307,7 @@ void JsepTransport::SetNeedsIceRestartFlag() {
absl::optional<rtc::SSLRole> JsepTransport::GetDtlsRole() const {
RTC_DCHECK(rtp_dtls_transport_);
rtc::SSLRole dtls_role;
if (!rtp_dtls_transport_->GetDtlsRole(&dtls_role)) {
if (!rtp_dtls_transport_->internal()->GetDtlsRole(&dtls_role)) {
return absl::optional<rtc::SSLRole>();
}
@ -310,9 +317,9 @@ absl::optional<rtc::SSLRole> JsepTransport::GetDtlsRole() const {
bool JsepTransport::GetStats(TransportStats* stats) {
stats->transport_name = mid();
stats->channel_stats.clear();
bool ret = GetTransportStats(rtp_dtls_transport_.get(), stats);
bool ret = GetTransportStats(rtp_dtls_transport_->internal(), stats);
if (rtcp_dtls_transport_) {
ret &= GetTransportStats(rtcp_dtls_transport_.get(), stats);
ret &= GetTransportStats(rtcp_dtls_transport_->internal(), stats);
}
return ret;
}
@ -440,7 +447,7 @@ void JsepTransport::ActivateRtcpMux() {
dtls_srtp_transport_->SetDtlsTransports(rtp_dtls_transport(),
/*rtcp_dtls_transport=*/nullptr);
}
rtcp_dtls_transport_.reset();
rtcp_dtls_transport_ = nullptr; // Destroy this reference.
// Notify the JsepTransportController to update the aggregate states.
SignalRtcpMuxActive();
}
@ -528,14 +535,14 @@ webrtc::RTCError JsepTransport::NegotiateAndSetDtlsParameters(
// creation, we have the negotiation state saved until a new
// negotiation happens.
webrtc::RTCError error = SetNegotiatedDtlsParameters(
rtp_dtls_transport_.get(), negotiated_dtls_role,
rtp_dtls_transport_->internal(), negotiated_dtls_role,
remote_fingerprint.get());
if (!error.ok()) {
return error;
}
if (rtcp_dtls_transport_) {
error = SetNegotiatedDtlsParameters(rtcp_dtls_transport_.get(),
error = SetNegotiatedDtlsParameters(rtcp_dtls_transport_->internal(),
negotiated_dtls_role,
remote_fingerprint.get());
}
@ -634,9 +641,13 @@ bool JsepTransport::GetTransportStats(DtlsTransportInternal* dtls_transport,
TransportStats* stats) {
RTC_DCHECK(dtls_transport);
TransportChannelStats substats;
substats.component = dtls_transport == rtcp_dtls_transport_.get()
? ICE_CANDIDATE_COMPONENT_RTCP
: ICE_CANDIDATE_COMPONENT_RTP;
if (rtcp_dtls_transport_) {
substats.component = dtls_transport == rtcp_dtls_transport_->internal()
? ICE_CANDIDATE_COMPONENT_RTCP
: ICE_CANDIDATE_COMPONENT_RTP;
} else {
substats.component = ICE_CANDIDATE_COMPONENT_RTP;
}
dtls_transport->GetSrtpCryptoSuite(&substats.srtp_crypto_suite);
dtls_transport->GetSslCipherSuite(&substats.ssl_cipher_suite);
substats.dtls_state = dtls_transport->dtls_state();

View File

@ -24,6 +24,7 @@
#include "p2p/base/p2pconstants.h"
#include "p2p/base/transportinfo.h"
#include "pc/dtlssrtptransport.h"
#include "pc/dtlstransport.h"
#include "pc/rtcpmuxfilter.h"
#include "pc/rtptransport.h"
#include "pc/sessiondescription.h"
@ -117,7 +118,6 @@ class JsepTransport : public sigslot::has_slots<>,
webrtc::RTCError SetRemoteJsepTransportDescription(
const JsepTransportDescription& jsep_description,
webrtc::SdpType type);
webrtc::RTCError AddRemoteCandidates(const Candidates& candidates);
// Set the "needs-ice-restart" flag as described in JSEP. After the flag is
@ -157,12 +157,40 @@ class JsepTransport : public sigslot::has_slots<>,
}
}
DtlsTransportInternal* rtp_dtls_transport() const {
return rtp_dtls_transport_.get();
const DtlsTransportInternal* rtp_dtls_transport() const {
if (rtp_dtls_transport_) {
return rtp_dtls_transport_->internal();
} else {
return nullptr;
}
}
DtlsTransportInternal* rtcp_dtls_transport() const {
return rtcp_dtls_transport_.get();
DtlsTransportInternal* rtp_dtls_transport() {
if (rtp_dtls_transport_) {
return rtp_dtls_transport_->internal();
} else {
return nullptr;
}
}
const DtlsTransportInternal* rtcp_dtls_transport() const {
if (rtcp_dtls_transport_) {
return rtcp_dtls_transport_->internal();
} else {
return nullptr;
}
}
DtlsTransportInternal* rtcp_dtls_transport() {
if (rtcp_dtls_transport_) {
return rtcp_dtls_transport_->internal();
} else {
return nullptr;
}
}
rtc::scoped_refptr<webrtc::DtlsTransportInterface> RtpDtlsTransport() {
return rtp_dtls_transport_;
}
// Returns media transport, if available.
@ -256,8 +284,8 @@ class JsepTransport : public sigslot::has_slots<>,
std::unique_ptr<webrtc::SrtpTransport> sdes_transport_;
std::unique_ptr<webrtc::DtlsSrtpTransport> dtls_srtp_transport_;
std::unique_ptr<DtlsTransportInternal> rtp_dtls_transport_;
std::unique_ptr<DtlsTransportInternal> rtcp_dtls_transport_;
rtc::scoped_refptr<webrtc::DtlsTransport> rtp_dtls_transport_;
rtc::scoped_refptr<webrtc::DtlsTransport> rtcp_dtls_transport_;
SrtpFilter sdes_negotiator_;
RtcpMuxFilter rtcp_mux_negotiator_;

View File

@ -870,7 +870,7 @@ TEST_F(JsepTransport2Test, RtcpMuxNegotiation) {
CreateJsepTransport2(/*rtcp_mux_enabled=*/false, SrtpMode::kDtlsSrtp);
JsepTransportDescription local_desc;
local_desc.rtcp_mux_enabled = true;
EXPECT_NE(nullptr, jsep_transport_->rtcp_dtls_transport());
ASSERT_NE(nullptr, jsep_transport_->rtcp_dtls_transport());
EXPECT_FALSE(signal_rtcp_mux_active_received_);
// The remote side supports RTCP-mux.

View File

@ -153,7 +153,7 @@ MediaTransportState JsepTransportController::GetMediaTransportState(
}
cricket::DtlsTransportInternal* JsepTransportController::GetDtlsTransport(
const std::string& mid) const {
const std::string& mid) {
auto jsep_transport = GetJsepTransportForMid(mid);
if (!jsep_transport) {
return nullptr;
@ -161,8 +161,8 @@ cricket::DtlsTransportInternal* JsepTransportController::GetDtlsTransport(
return jsep_transport->rtp_dtls_transport();
}
cricket::DtlsTransportInternal* JsepTransportController::GetRtcpDtlsTransport(
const std::string& mid) const {
const cricket::DtlsTransportInternal*
JsepTransportController::GetRtcpDtlsTransport(const std::string& mid) const {
auto jsep_transport = GetJsepTransportForMid(mid);
if (!jsep_transport) {
return nullptr;
@ -170,6 +170,15 @@ cricket::DtlsTransportInternal* JsepTransportController::GetRtcpDtlsTransport(
return jsep_transport->rtcp_dtls_transport();
}
rtc::scoped_refptr<webrtc::DtlsTransportInterface>
JsepTransportController::LookupDtlsTransportByMid(const std::string& mid) {
auto jsep_transport = GetJsepTransportForMid(mid);
if (!jsep_transport) {
return nullptr;
}
return jsep_transport->RtpDtlsTransport();
}
void JsepTransportController::SetIceConfig(const cricket::IceConfig& config) {
if (!network_thread_->IsCurrent()) {
network_thread_->Invoke<void>(RTC_FROM_HERE, [&] { SetIceConfig(config); });
@ -346,9 +355,10 @@ RTCError JsepTransportController::RemoveRemoteCandidates(
continue;
}
for (const cricket::Candidate& candidate : candidates) {
auto dtls = candidate.component() == cricket::ICE_CANDIDATE_COMPONENT_RTP
? jsep_transport->rtp_dtls_transport()
: jsep_transport->rtcp_dtls_transport();
cricket::DtlsTransportInternal* dtls =
candidate.component() == cricket::ICE_CANDIDATE_COMPONENT_RTP
? jsep_transport->rtp_dtls_transport()
: jsep_transport->rtcp_dtls_transport();
if (dtls) {
dtls->ice_transport()->RemoveRemoteCandidate(candidate);
}

View File

@ -28,6 +28,7 @@
#include "p2p/base/transportfactoryinterface.h"
#include "pc/channel.h"
#include "pc/dtlssrtptransport.h"
#include "pc/dtlstransport.h"
#include "pc/jseptransport.h"
#include "pc/rtptransport.h"
#include "pc/srtptransport.h"
@ -112,10 +113,12 @@ class JsepTransportController : public sigslot::has_slots<> {
// Get transports to be used for the provided |mid|. If bundling is enabled,
// calling GetRtpTransport for multiple MIDs may yield the same object.
RtpTransportInternal* GetRtpTransport(const std::string& mid) const;
cricket::DtlsTransportInternal* GetDtlsTransport(
const std::string& mid) const;
cricket::DtlsTransportInternal* GetRtcpDtlsTransport(
cricket::DtlsTransportInternal* GetDtlsTransport(const std::string& mid);
const cricket::DtlsTransportInternal* GetRtcpDtlsTransport(
const std::string& mid) const;
// Gets the externally sharable version of the DtlsTransport.
rtc::scoped_refptr<webrtc::DtlsTransportInterface> LookupDtlsTransportByMid(
const std::string& mid);
MediaTransportInterface* GetMediaTransport(const std::string& mid) const;
MediaTransportState GetMediaTransportState(const std::string& mid) const;

View File

@ -371,11 +371,20 @@ TEST_F(JsepTransportControllerTest, GetDtlsTransport) {
.ok());
EXPECT_NE(nullptr, transport_controller_->GetDtlsTransport(kAudioMid1));
EXPECT_NE(nullptr, transport_controller_->GetRtcpDtlsTransport(kAudioMid1));
EXPECT_NE(nullptr,
transport_controller_->LookupDtlsTransportByMid(kAudioMid1));
EXPECT_NE(nullptr, transport_controller_->GetDtlsTransport(kVideoMid1));
EXPECT_NE(nullptr, transport_controller_->GetRtcpDtlsTransport(kVideoMid1));
EXPECT_NE(nullptr,
transport_controller_->LookupDtlsTransportByMid(kVideoMid1));
// Lookup for all MIDs should return different transports (no bundle)
EXPECT_NE(transport_controller_->LookupDtlsTransportByMid(kAudioMid1),
transport_controller_->LookupDtlsTransportByMid(kVideoMid1));
// Return nullptr for non-existing ones.
EXPECT_EQ(nullptr, transport_controller_->GetDtlsTransport(kVideoMid2));
EXPECT_EQ(nullptr, transport_controller_->GetRtcpDtlsTransport(kVideoMid2));
EXPECT_EQ(nullptr,
transport_controller_->LookupDtlsTransportByMid(kVideoMid2));
}
TEST_F(JsepTransportControllerTest, GetDtlsTransportWithRtcpMux) {
@ -1275,6 +1284,9 @@ TEST_F(JsepTransportControllerTest, MultipleMediaSectionsOfSameTypeWithBundle) {
EXPECT_EQ(transport1, transport3);
EXPECT_EQ(transport1, transport4);
EXPECT_EQ(transport_controller_->LookupDtlsTransportByMid(kAudioMid1),
transport_controller_->LookupDtlsTransportByMid(kVideoMid1));
// Verify the OnRtpTransport/DtlsTransportChanged signals are fired correctly.
auto it = changed_rtp_transport_by_mid_.find(kAudioMid2);
ASSERT_TRUE(it != changed_rtp_transport_by_mid_.end());

View File

@ -3346,6 +3346,11 @@ void PeerConnection::StopRtcEventLog() {
RTC_FROM_HERE, rtc::Bind(&PeerConnection::StopRtcEventLog_w, this));
}
rtc::scoped_refptr<DtlsTransportInterface>
PeerConnection::LookupDtlsTransportByMid(const std::string& mid) {
return transport_controller_->LookupDtlsTransportByMid(mid);
}
const SessionDescriptionInterface* PeerConnection::local_description() const {
return pending_local_description_ ? pending_local_description_.get()
: current_local_description_.get();

View File

@ -194,6 +194,9 @@ class PeerConnection : public PeerConnectionInternal,
void SetAudioPlayout(bool playout) override;
void SetAudioRecording(bool recording) override;
rtc::scoped_refptr<DtlsTransportInterface> LookupDtlsTransportByMid(
const std::string& mid) override;
RTC_DEPRECATED bool StartRtcEventLog(rtc::PlatformFile file,
int64_t max_size_bytes) override;
bool StartRtcEventLog(std::unique_ptr<RtcEventLogOutput> output,

View File

@ -51,6 +51,18 @@ constexpr int kDefaultTimeout = 10000;
// will use: https://www.w3.org/TR/webrtc/#dom-rtcrtpsender-transport
// Should also be able to remove GetTransceiversForTesting at that point.
class FakeNetworkManagerWithNoAnyNetwork : public rtc::FakeNetworkManager {
public:
void GetAnyAddressNetworks(NetworkList* networks) override {
// This function allocates networks that are owned by the
// NetworkManager. But some tests assume that they can release
// all networks independent of the network manager.
// In order to prevent use-after-free issues, don't allow this
// function to have any effect when run in tests.
RTC_LOG(LS_INFO) << "FakeNetworkManager::GetAnyAddressNetworks ignored";
}
};
class PeerConnectionWrapperForBundleTest : public PeerConnectionWrapper {
public:
using PeerConnectionWrapper::PeerConnectionWrapper;
@ -235,7 +247,7 @@ class PeerConnectionBundleBaseTest : public ::testing::Test {
// base class members). Therefore, the test fixture will own all the fake
// networks even though tests should access the fake network through the
// PeerConnectionWrapper.
auto* fake_network = new rtc::FakeNetworkManager();
auto* fake_network = new FakeNetworkManagerWithNoAnyNetwork();
fake_networks_.emplace_back(fake_network);
return fake_network;
}

View File

@ -129,9 +129,6 @@ class FakeNetworkManager : public NetworkManagerBase, public MessageHandler {
int start_count_ = 0;
bool sent_first_update_ = false;
IPAddress default_local_ipv4_address_;
IPAddress default_local_ipv6_address_;
std::unique_ptr<webrtc::FakeMdnsResponder> mdns_responder_;
};