Revert "Reland "Replace BundleFilter with RtpDemuxer in RtpTransport.""

This reverts commit 27f3bf512827b483f9e0c67ce76362d83faa1950.

Reason for revert: Broken internal project.

Original change's description:
> Reland "Replace BundleFilter with RtpDemuxer in RtpTransport."
> 
> This reverts commit 97d5e5b32c77bf550f1d788454f2db10ac9fbb1c.
> 
> Reason for revert: <INSERT REASONING HERE>
> 
> Original change's description:
> > Revert "Replace BundleFilter with RtpDemuxer in RtpTransport."
> > 
> > This reverts commit ea8b62a3e74fe91cd6bf66304839cd5677880a4e.
> > 
> > Reason for revert: Broke chromium tests.
> > Original change's description:
> > > Replace BundleFilter with RtpDemuxer in RtpTransport.
> > > 
> > > BundleFilter is replaced by RtpDemuxer in RtpTransport for payload
> > > type-based demuxing. RtpTransport will support MID-based demuxing later.
> > > 
> > > Each BaseChannel has its own RTP demuxing criteria and when connecting
> > > to the RtpTransport, BaseChannel will register itself as a demuxer sink.
> > > 
> > > The inheritance model is changed. New inheritance chain:
> > > DtlsSrtpTransport->SrtpTransport->RtpTranpsort
> > > 
> > > NOTE:
> > > When RTCP packets are received, Call::DeliverRtcp will be called for
> > > multiple times (webrtc:9035) which is an existing issue. With this CL,
> > > it will become more of a problem and should be fixed.
> > > 
> > > Bug: webrtc:8587
> > > Change-Id: I1d8a00443bd4bcbacc56e5e19b7294205cdc38f0
> > > Reviewed-on: https://webrtc-review.googlesource.com/61360
> > > Commit-Queue: Zhi Huang <zhihuang@webrtc.org>
> > > Reviewed-by: Steve Anton <steveanton@webrtc.org>
> > > Reviewed-by: Taylor Brandstetter <deadbeef@webrtc.org>
> > > Cr-Commit-Position: refs/heads/master@{#22613}
> > 
> > TBR=steveanton@webrtc.org,deadbeef@webrtc.org,zhihuang@webrtc.org
> > 
> > Change-Id: If245da9d1ce970ac8dab7f45015e9b268a5dbcbd
> > No-Presubmit: true
> > No-Tree-Checks: true
> > No-Try: true
> > Bug: webrtc:8587
> > Reviewed-on: https://webrtc-review.googlesource.com/64860
> > Reviewed-by: Zhi Huang <zhihuang@webrtc.org>
> > Commit-Queue: Zhi Huang <zhihuang@webrtc.org>
> > Cr-Commit-Position: refs/heads/master@{#22614}
> 
> TBR=steveanton@webrtc.org,deadbeef@webrtc.org,zhihuang@webrtc.org
> 
> Change-Id: I3c272588ab4388ecadc4edc6786d5195c701855f
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Bug: webrtc:8587
> Reviewed-on: https://webrtc-review.googlesource.com/64862
> Commit-Queue: Zhi Huang <zhihuang@webrtc.org>
> Reviewed-by: Zhi Huang <zhihuang@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#22615}

TBR=steveanton@webrtc.org,deadbeef@webrtc.org,zhihuang@webrtc.org

# Not skipping CQ checks because original CL landed > 1 day ago.

Bug: webrtc:8587
Change-Id: I694ce9a039ed52c5961cdc0cba57587bed4cbde4
Reviewed-on: https://webrtc-review.googlesource.com/65381
Reviewed-by: Zhi Huang <zhihuang@webrtc.org>
Commit-Queue: Zhi Huang <zhihuang@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#22665}
This commit is contained in:
Zhi Huang 2018-03-29 00:08:03 +00:00 committed by Commit Bot
parent dea6889ef6
commit 95e7dbb7c7
28 changed files with 713 additions and 592 deletions

View File

@ -275,16 +275,6 @@ bool IsRtpPacket(const void* data, size_t len) {
return (static_cast<const uint8_t*>(data)[0] >> 6) == kRtpVersion;
}
// Check the RTP payload type. If 63 < payload type < 96, it's RTCP.
// For additional details, see http://tools.ietf.org/html/rfc5761.
bool IsRtcp(const char* data, int len) {
if (len < 2) {
return false;
}
char pt = data[1] & 0x7F;
return (63 < pt) && (pt < 96);
}
bool IsValidRtpPayloadType(int payload_type) {
return payload_type >= 0 && payload_type <= 127;
}

View File

@ -55,7 +55,6 @@ bool SetRtpHeader(void* data, size_t len, const RtpHeader& header);
bool IsRtpPacket(const void* data, size_t len);
bool IsRtcp(const char* data, int len);
// True if |payload type| is 0-127.
bool IsValidRtpPayloadType(int payload_type);

View File

@ -30,6 +30,8 @@ rtc_static_library("rtc_pc_base") {
defines = []
sources = [
"audiomonitor.h",
"bundlefilter.cc",
"bundlefilter.h",
"channel.cc",
"channel.h",
"channelmanager.cc",
@ -78,13 +80,10 @@ rtc_static_library("rtc_pc_base") {
"../api:optional",
"../api:ortc_api",
"../api:video_frame_api",
"../call:rtp_interfaces",
"../call:rtp_receiver",
"../common_video:common_video",
"../media:rtc_data",
"../media:rtc_h264_profile_id",
"../media:rtc_media_base",
"../modules/rtp_rtcp:rtp_rtcp_format",
"../p2p:rtc_p2p",
"../rtc_base:checks",
"../rtc_base:rtc_base",
@ -275,6 +274,7 @@ if (rtc_include_tests) {
testonly = true
sources = [
"bundlefilter_unittest.cc",
"channel_unittest.cc",
"channelmanager_unittest.cc",
"currentspeakermonitor_unittest.cc",
@ -314,11 +314,9 @@ if (rtc_include_tests) {
"../api:array_view",
"../api:fakemetricsobserver",
"../api:libjingle_peerconnection_api",
"../call:rtp_interfaces",
"../logging:rtc_event_log_api",
"../media:rtc_media_base",
"../media:rtc_media_tests_utils",
"../modules/rtp_rtcp:rtp_rtcp_format",
"../p2p:p2p_test_utils",
"../p2p:rtc_p2p",
"../rtc_base:checks",

49
pc/bundlefilter.cc Normal file
View File

@ -0,0 +1,49 @@
/*
* Copyright 2004 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/bundlefilter.h"
#include "media/base/rtputils.h"
#include "rtc_base/logging.h"
namespace cricket {
BundleFilter::BundleFilter() {
}
BundleFilter::~BundleFilter() {
}
bool BundleFilter::DemuxPacket(const uint8_t* data, size_t len) {
// For RTP packets, we check whether the payload type can be found.
if (!IsRtpPacket(data, len)) {
return false;
}
int payload_type = 0;
if (!GetRtpPayloadType(data, len, &payload_type)) {
return false;
}
return FindPayloadType(payload_type);
}
void BundleFilter::AddPayloadType(int payload_type) {
payload_types_.insert(payload_type);
}
bool BundleFilter::FindPayloadType(int pl_type) const {
return payload_types_.find(pl_type) != payload_types_.end();
}
void BundleFilter::ClearAllPayloadTypes() {
payload_types_.clear();
}
} // namespace cricket

54
pc/bundlefilter.h Normal file
View File

@ -0,0 +1,54 @@
/*
* Copyright 2004 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_BUNDLEFILTER_H_
#define PC_BUNDLEFILTER_H_
#include <stdint.h>
#include <set>
#include <vector>
#include "media/base/streamparams.h"
#include "rtc_base/basictypes.h"
namespace cricket {
// In case of single RTP session and single transport channel, all session
// (or media) channels share a common transport channel. Hence they all get
// SignalReadPacket when packet received on transport channel. This requires
// cricket::BaseChannel to know all the valid sources, else media channel
// will decode invalid packets.
//
// This class determines whether a packet is destined for cricket::BaseChannel.
// This is only to be used for RTP packets as RTCP packets are not filtered.
// For RTP packets, this is decided based on the payload type.
class BundleFilter {
public:
BundleFilter();
~BundleFilter();
// Determines if a RTP packet belongs to valid cricket::BaseChannel.
bool DemuxPacket(const uint8_t* data, size_t len);
// Adds the supported payload type.
void AddPayloadType(int payload_type);
// Public for unittests.
bool FindPayloadType(int pl_type) const;
void ClearAllPayloadTypes();
private:
std::set<int> payload_types_;
};
} // namespace cricket
#endif // PC_BUNDLEFILTER_H_

View File

@ -0,0 +1,72 @@
/*
* Copyright 2004 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/bundlefilter.h"
#include "rtc_base/gunit.h"
using cricket::StreamParams;
static const int kPayloadType1 = 0x11;
static const int kPayloadType2 = 0x22;
static const int kPayloadType3 = 0x33;
// SSRC = 0x1111, Payload type = 0x11
static const unsigned char kRtpPacketPt1Ssrc1[] = {
0x80, kPayloadType1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
0x11,
};
// SSRC = 0x2222, Payload type = 0x22
static const unsigned char kRtpPacketPt2Ssrc2[] = {
0x80, 0x80 + kPayloadType2, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x22, 0x22,
};
// SSRC = 0x2222, Payload type = 0x33
static const unsigned char kRtpPacketPt3Ssrc2[] = {
0x80, kPayloadType3, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22,
0x22,
};
// An SCTP packet.
static const unsigned char kSctpPacket[] = {
0x00, 0x01, 0x00, 0x01,
0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x04,
0x00, 0x00, 0x00, 0x00,
};
TEST(BundleFilterTest, RtpPacketTest) {
cricket::BundleFilter bundle_filter;
bundle_filter.AddPayloadType(kPayloadType1);
EXPECT_TRUE(bundle_filter.DemuxPacket(kRtpPacketPt1Ssrc1,
sizeof(kRtpPacketPt1Ssrc1)));
bundle_filter.AddPayloadType(kPayloadType2);
EXPECT_TRUE(bundle_filter.DemuxPacket(kRtpPacketPt2Ssrc2,
sizeof(kRtpPacketPt2Ssrc2)));
// Payload type 0x33 is not added.
EXPECT_FALSE(bundle_filter.DemuxPacket(kRtpPacketPt3Ssrc2,
sizeof(kRtpPacketPt3Ssrc2)));
// Size is too small.
EXPECT_FALSE(bundle_filter.DemuxPacket(kRtpPacketPt1Ssrc1, 11));
bundle_filter.ClearAllPayloadTypes();
EXPECT_FALSE(bundle_filter.DemuxPacket(kRtpPacketPt1Ssrc1,
sizeof(kRtpPacketPt1Ssrc1)));
EXPECT_FALSE(bundle_filter.DemuxPacket(kRtpPacketPt2Ssrc2,
sizeof(kRtpPacketPt2Ssrc2)));
}
TEST(BundleFilterTest, InvalidRtpPacket) {
cricket::BundleFilter bundle_filter;
EXPECT_FALSE(bundle_filter.DemuxPacket(kSctpPacket, sizeof(kSctpPacket)));
}

View File

@ -29,7 +29,6 @@
// Adding 'nogncheck' to disable the gn include headers check to support modular
// WebRTC build targets.
#include "media/engine/webrtcvoiceengine.h" // nogncheck
#include "modules/rtp_rtcp/source/rtp_packet_received.h"
#include "p2p/base/packettransportinternal.h"
#include "pc/channelmanager.h"
#include "pc/rtpmediautils.h"
@ -111,7 +110,6 @@ BaseChannel::BaseChannel(rtc::Thread* worker_thread,
srtp_required_(srtp_required),
media_channel_(std::move(media_channel)) {
RTC_DCHECK_RUN_ON(worker_thread_);
demuxer_criteria_.mid = content_name;
rtp_transport_ = unencrypted_rtp_transport_.get();
ConnectToRtpTransport();
RTC_LOG(LS_INFO) << "Created channel for " << content_name;
@ -133,12 +131,13 @@ BaseChannel::~BaseChannel() {
void BaseChannel::ConnectToRtpTransport() {
RTC_DCHECK(rtp_transport_);
bool success = RegisterRtpDemuxerSink();
RTC_DCHECK(success);
rtp_transport_->SignalReadyToSend.connect(
this, &BaseChannel::OnTransportReadyToSend);
rtp_transport_->SignalRtcpPacketReceived.connect(
this, &BaseChannel::OnRtcpPacketReceived);
// TODO(zstein): RtpTransport::SignalPacketReceived will probably be replaced
// with a callback interface later so that the demuxer can select which
// channel to signal.
rtp_transport_->SignalPacketReceived.connect(this,
&BaseChannel::OnPacketReceived);
rtp_transport_->SignalNetworkRouteChanged.connect(
this, &BaseChannel::OnNetworkRouteChanged);
rtp_transport_->SignalWritableState.connect(this,
@ -155,9 +154,8 @@ void BaseChannel::ConnectToRtpTransport() {
void BaseChannel::DisconnectFromRtpTransport() {
RTC_DCHECK(rtp_transport_);
rtp_transport_->UnregisterRtpDemuxerSink(this);
rtp_transport_->SignalReadyToSend.disconnect(this);
rtp_transport_->SignalRtcpPacketReceived.disconnect(this);
rtp_transport_->SignalPacketReceived.disconnect(this);
rtp_transport_->SignalNetworkRouteChanged.disconnect(this);
rtp_transport_->SignalWritableState.disconnect(this);
rtp_transport_->SignalSentPacket.disconnect(this);
@ -205,26 +203,17 @@ void BaseChannel::Deinit() {
// functions, so need to stop this process in Deinit that is called in
// derived classes destructor.
network_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
if (rtp_transport_) {
FlushRtcpMessages_n();
if (dtls_srtp_transport_) {
dtls_srtp_transport_->SetDtlsTransports(nullptr, nullptr);
} else {
rtp_transport_->SetRtpPacketTransport(nullptr);
rtp_transport_->SetRtcpPacketTransport(nullptr);
}
DisconnectFromRtpTransport();
}
FlushRtcpMessages_n();
if (dtls_srtp_transport_) {
dtls_srtp_transport_->SetDtlsTransports(nullptr, nullptr);
} else {
rtp_transport_->SetRtpPacketTransport(nullptr);
rtp_transport_->SetRtcpPacketTransport(nullptr);
}
// Clear pending read packets/messages.
network_thread_->Clear(&invoker_);
network_thread_->Clear(this);
// Because RTP level transports are accessed from the |network_thread_|,
// it's safer to release them from the |network_thread_| as well.
unencrypted_rtp_transport_.reset();
sdes_transport_.reset();
dtls_srtp_transport_.reset();
rtp_transport_ = nullptr;
});
}
@ -235,10 +224,8 @@ void BaseChannel::SetRtpTransport(webrtc::RtpTransportInternal* rtp_transport) {
return;
});
}
RTC_DCHECK(rtp_transport);
if (rtp_transport == rtp_transport_) {
return;
}
if (rtp_transport_) {
DisconnectFromRtpTransport();
@ -594,37 +581,12 @@ bool BaseChannel::SendPacket(bool rtcp,
: rtp_transport_->SendRtpPacket(packet, options, PF_SRTP_BYPASS);
}
void BaseChannel::OnRtpPacket(const webrtc::RtpPacketReceived& parsed_packet) {
// Reconstruct the PacketTime from the |parsed_packet|.
// RtpPacketReceived.arrival_time_ms = (PacketTime + 500) / 1000;
// Note: The |not_before| field is always 0 here. This field is not currently
// used, so it should be fine.
int64_t timestamp = -1;
if (parsed_packet.arrival_time_ms() > 0) {
timestamp = parsed_packet.arrival_time_ms() * 1000;
}
rtc::PacketTime packet_time(timestamp, /*not_before=*/0);
OnPacketReceived(/*rtcp=*/false, parsed_packet.Buffer(), packet_time);
}
void BaseChannel::UpdateRtpHeaderExtensionMap(
const RtpHeaderExtensions& header_extensions) {
RTC_DCHECK(rtp_transport_);
rtp_transport_->UpdateRtpHeaderExtensionMap(header_extensions);
}
bool BaseChannel::RegisterRtpDemuxerSink() {
RTC_DCHECK(rtp_transport_);
return rtp_transport_->RegisterRtpDemuxerSink(demuxer_criteria_, this);
}
void BaseChannel::OnRtcpPacketReceived(rtc::CopyOnWriteBuffer* packet,
const rtc::PacketTime& packet_time) {
OnPacketReceived(/*rtcp=*/true, *packet, packet_time);
bool BaseChannel::HandlesPayloadType(int packet_type) const {
return rtp_transport_->HandlesPayloadType(packet_type);
}
void BaseChannel::OnPacketReceived(bool rtcp,
const rtc::CopyOnWriteBuffer& packet,
rtc::CopyOnWriteBuffer* packet,
const rtc::PacketTime& packet_time) {
if (!has_received_packet_ && !rtcp) {
has_received_packet_ = true;
@ -651,7 +613,7 @@ void BaseChannel::OnPacketReceived(bool rtcp,
invoker_.AsyncInvoke<void>(
RTC_FROM_HERE, worker_thread_,
Bind(&BaseChannel::ProcessPacket, this, rtcp, packet, packet_time));
Bind(&BaseChannel::ProcessPacket, this, rtcp, *packet, packet_time));
}
void BaseChannel::ProcessPacket(bool rtcp,
@ -793,17 +755,14 @@ void BaseChannel::EnableSdes_n() {
// DtlsSrtpTransport and SrtpTransport shouldn't be enabled at the same
// time.
RTC_DCHECK(!dtls_srtp_transport_);
sdes_transport_ = rtc::MakeUnique<webrtc::SrtpTransport>(rtcp_mux_required_);
RTC_DCHECK(unencrypted_rtp_transport_);
sdes_transport_ = rtc::MakeUnique<webrtc::SrtpTransport>(
std::move(unencrypted_rtp_transport_));
#if defined(ENABLE_EXTERNAL_AUTH)
sdes_transport_->EnableExternalAuth();
#endif
sdes_transport_->SetRtpPacketTransport(
rtp_transport_->rtp_packet_transport());
sdes_transport_->SetRtcpPacketTransport(
rtp_transport_->rtcp_packet_transport());
SetRtpTransport(sdes_transport_.get());
RTC_LOG(LS_INFO) << "SrtpTransport is created for SDES.";
RTC_LOG(LS_INFO) << "Wrapping RtpTransport in SrtpTransport.";
}
void BaseChannel::EnableDtlsSrtp_n() {
@ -813,12 +772,15 @@ void BaseChannel::EnableDtlsSrtp_n() {
// DtlsSrtpTransport and SrtpTransport shouldn't be enabled at the same
// time.
RTC_DCHECK(!sdes_transport_);
RTC_DCHECK(unencrypted_rtp_transport_);
dtls_srtp_transport_ =
rtc::MakeUnique<webrtc::DtlsSrtpTransport>(rtcp_mux_required_);
auto srtp_transport = rtc::MakeUnique<webrtc::SrtpTransport>(
std::move(unencrypted_rtp_transport_));
#if defined(ENABLE_EXTERNAL_AUTH)
dtls_srtp_transport_->EnableExternalAuth();
srtp_transport->EnableExternalAuth();
#endif
dtls_srtp_transport_ =
rtc::MakeUnique<webrtc::DtlsSrtpTransport>(std::move(srtp_transport));
SetRtpTransport(dtls_srtp_transport_.get());
if (cached_send_extension_ids_) {
@ -834,7 +796,8 @@ void BaseChannel::EnableDtlsSrtp_n() {
RTC_DCHECK(rtp_dtls_transport_);
dtls_srtp_transport_->SetDtlsTransports(rtp_dtls_transport_,
rtcp_dtls_transport_);
RTC_LOG(LS_INFO) << "DtlsSrtpTransport is created for DTLS-SRTP.";
RTC_LOG(LS_INFO) << "Wrapping SrtpTransport in DtlsSrtpTransport.";
}
bool BaseChannel::SetSrtp_n(const std::vector<CryptoParams>& cryptos,
@ -1114,7 +1077,7 @@ void BaseChannel::OnMessage(rtc::Message *pmsg) {
}
void BaseChannel::AddHandledPayloadType(int payload_type) {
demuxer_criteria_.payload_types.insert(static_cast<uint8_t>(payload_type));
rtp_transport_->AddHandledPayloadType(payload_type);
}
void BaseChannel::FlushRtcpMessages_n() {
@ -1244,7 +1207,6 @@ bool VoiceChannel::SetLocalContent_w(const MediaContentDescription* content,
RtpHeaderExtensions rtp_header_extensions =
GetFilteredRtpHeaderExtensions(audio->rtp_header_extensions());
UpdateRtpHeaderExtensionMap(rtp_header_extensions);
if (!SetRtpTransportParameters(content, type, CS_LOCAL, rtp_header_extensions,
error_desc)) {
@ -1258,16 +1220,9 @@ bool VoiceChannel::SetLocalContent_w(const MediaContentDescription* content,
error_desc);
return false;
}
for (const AudioCodec& codec : audio->codecs()) {
AddHandledPayloadType(codec.id);
}
// Need to re-register the sink to update the handled payload.
if (!RegisterRtpDemuxerSink()) {
RTC_LOG(LS_ERROR) << "Failed to set up audio demuxing.";
return false;
}
last_recv_params_ = recv_params;
// TODO(pthatcher): Move local streams into AudioSendParameters, and
@ -1302,7 +1257,6 @@ bool VoiceChannel::SetRemoteContent_w(const MediaContentDescription* content,
RtpHeaderExtensions rtp_header_extensions =
GetFilteredRtpHeaderExtensions(audio->rtp_header_extensions());
UpdateRtpHeaderExtensionMap(rtp_header_extensions);
if (!SetRtpTransportParameters(content, type, CS_REMOTE,
rtp_header_extensions, error_desc)) {
return false;
@ -1358,6 +1312,7 @@ VideoChannel::~VideoChannel() {
TRACE_EVENT0("webrtc", "VideoChannel::~VideoChannel");
// this can't be done in the base class, since it calls a virtual
DisableMedia_w();
Deinit();
}
@ -1395,7 +1350,6 @@ bool VideoChannel::SetLocalContent_w(const MediaContentDescription* content,
RtpHeaderExtensions rtp_header_extensions =
GetFilteredRtpHeaderExtensions(video->rtp_header_extensions());
UpdateRtpHeaderExtensionMap(rtp_header_extensions);
if (!SetRtpTransportParameters(content, type, CS_LOCAL, rtp_header_extensions,
error_desc)) {
@ -1409,16 +1363,9 @@ bool VideoChannel::SetLocalContent_w(const MediaContentDescription* content,
error_desc);
return false;
}
for (const VideoCodec& codec : video->codecs()) {
AddHandledPayloadType(codec.id);
}
// Need to re-register the sink to update the handled payload.
if (!RegisterRtpDemuxerSink()) {
RTC_LOG(LS_ERROR) << "Failed to set up video demuxing.";
return false;
}
last_recv_params_ = recv_params;
// TODO(pthatcher): Move local streams into VideoSendParameters, and
@ -1453,7 +1400,6 @@ bool VideoChannel::SetRemoteContent_w(const MediaContentDescription* content,
RtpHeaderExtensions rtp_header_extensions =
GetFilteredRtpHeaderExtensions(video->rtp_header_extensions());
UpdateRtpHeaderExtensionMap(rtp_header_extensions);
if (!SetRtpTransportParameters(content, type, CS_REMOTE,
rtp_header_extensions, error_desc)) {
return false;
@ -1513,6 +1459,7 @@ RtpDataChannel::~RtpDataChannel() {
TRACE_EVENT0("webrtc", "RtpDataChannel::~RtpDataChannel");
// this can't be done in the base class, since it calls a virtual
DisableMedia_w();
Deinit();
}
@ -1581,7 +1528,6 @@ bool RtpDataChannel::SetLocalContent_w(const MediaContentDescription* content,
RtpHeaderExtensions rtp_header_extensions =
GetFilteredRtpHeaderExtensions(data->rtp_header_extensions());
UpdateRtpHeaderExtensionMap(rtp_header_extensions);
if (!SetRtpTransportParameters(content, type, CS_LOCAL, rtp_header_extensions,
error_desc)) {
@ -1595,16 +1541,9 @@ bool RtpDataChannel::SetLocalContent_w(const MediaContentDescription* content,
error_desc);
return false;
}
for (const DataCodec& codec : data->codecs()) {
AddHandledPayloadType(codec.id);
}
// Need to re-register the sink to update the handled payload.
if (!RegisterRtpDemuxerSink()) {
RTC_LOG(LS_ERROR) << "Failed to set up data demuxing.";
return false;
}
last_recv_params_ = recv_params;
// TODO(pthatcher): Move local streams into DataSendParameters, and
@ -1648,7 +1587,6 @@ bool RtpDataChannel::SetRemoteContent_w(const MediaContentDescription* content,
RtpHeaderExtensions rtp_header_extensions =
GetFilteredRtpHeaderExtensions(data->rtp_header_extensions());
UpdateRtpHeaderExtensionMap(rtp_header_extensions);
RTC_LOG(LS_INFO) << "Setting remote data description";
if (!SetRtpTransportParameters(content, type, CS_REMOTE,
rtp_header_extensions, error_desc)) {

View File

@ -23,7 +23,6 @@
#include "api/rtpreceiverinterface.h"
#include "api/videosinkinterface.h"
#include "api/videosourceinterface.h"
#include "call/rtp_packet_sink_interface.h"
#include "media/base/mediachannel.h"
#include "media/base/mediaengine.h"
#include "media/base/streamparams.h"
@ -70,10 +69,9 @@ class MediaContentDescription;
// vtable, and the media channel's thread using BaseChannel as the
// NetworkInterface.
class BaseChannel : public rtc::MessageHandler,
public sigslot::has_slots<>,
public MediaChannel::NetworkInterface,
public webrtc::RtpPacketSinkInterface {
class BaseChannel
: public rtc::MessageHandler, public sigslot::has_slots<>,
public MediaChannel::NetworkInterface {
public:
// If |srtp_required| is true, the channel will not send or receive any
// RTP/RTCP packets without using SRTP (either using SDES or DTLS-SRTP).
@ -195,8 +193,10 @@ class BaseChannel : public rtc::MessageHandler,
virtual cricket::MediaType media_type() = 0;
// RtpPacketSinkInterface overrides.
void OnRtpPacket(const webrtc::RtpPacketReceived& packet) override;
// Public for testing.
// TODO(zstein): Remove this once channels register themselves with
// an RtpTransport in a more explicit way.
bool HandlesPayloadType(int payload_type) const;
// Used by the RTCStatsCollector tests to set the transport name without
// creating RtpTransports.
@ -264,10 +264,12 @@ class BaseChannel : public rtc::MessageHandler,
rtc::CopyOnWriteBuffer* packet,
const rtc::PacketOptions& options);
void OnRtcpPacketReceived(rtc::CopyOnWriteBuffer* packet,
const rtc::PacketTime& packet_time);
bool WantsPacket(bool rtcp, const rtc::CopyOnWriteBuffer* packet);
void HandlePacket(bool rtcp, rtc::CopyOnWriteBuffer* packet,
const rtc::PacketTime& packet_time);
// TODO(zstein): packet can be const once the RtpTransport handles protection.
void OnPacketReceived(bool rtcp,
const rtc::CopyOnWriteBuffer& packet,
rtc::CopyOnWriteBuffer* packet,
const rtc::PacketTime& packet_time);
void ProcessPacket(bool rtcp,
const rtc::CopyOnWriteBuffer& packet,
@ -358,11 +360,6 @@ class BaseChannel : public rtc::MessageHandler,
void AddHandledPayloadType(int payload_type);
void UpdateRtpHeaderExtensionMap(
const RtpHeaderExtensions& header_extensions);
bool RegisterRtpDemuxerSink();
private:
void ConnectToRtpTransport();
void DisconnectFromRtpTransport();
@ -442,9 +439,6 @@ class BaseChannel : public rtc::MessageHandler,
// The cached encrypted header extension IDs.
rtc::Optional<std::vector<int>> cached_send_extension_ids_;
rtc::Optional<std::vector<int>> cached_recv_extension_ids_;
bool encryption_disabled_ = false;
webrtc::RtpDemuxerCriteria demuxer_criteria_;
};
// VoiceChannel is a specialization that adds support for early media, DTMF,

View File

@ -1609,6 +1609,10 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
EXPECT_TRUE(SendAccept());
EXPECT_EQ(rtcp_mux, !channel1_->NeedsRtcpTransport());
EXPECT_EQ(rtcp_mux, !channel2_->NeedsRtcpTransport());
EXPECT_TRUE(channel1_->HandlesPayloadType(pl_type1));
EXPECT_TRUE(channel2_->HandlesPayloadType(pl_type1));
EXPECT_FALSE(channel1_->HandlesPayloadType(pl_type2));
EXPECT_FALSE(channel2_->HandlesPayloadType(pl_type2));
// Both channels can receive pl_type1 only.
SendCustomRtp1(kSsrc1, ++sequence_number1_1, pl_type1);
@ -1619,15 +1623,13 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
EXPECT_TRUE(CheckNoRtp1());
EXPECT_TRUE(CheckNoRtp2());
EXPECT_TRUE(SendInitiate());
EXPECT_TRUE(SendAccept());
// RTCP test
SendCustomRtp1(kSsrc1, ++sequence_number1_1, pl_type2);
SendCustomRtp2(kSsrc2, ++sequence_number2_2, pl_type2);
WaitForThreads();
EXPECT_FALSE(CheckCustomRtp2(kSsrc1, sequence_number1_1, pl_type2));
EXPECT_FALSE(CheckCustomRtp1(kSsrc2, sequence_number2_2, pl_type2));
// RTCP test
SendCustomRtcp1(kSsrc1);
SendCustomRtcp2(kSsrc2);
WaitForThreads();

View File

@ -507,6 +507,7 @@ void ChannelManager::DestroyRtpDataChannel(RtpDataChannel* data_channel) {
if (it == data_channels_.end()) {
return;
}
data_channels_.erase(it);
}

View File

@ -195,14 +195,11 @@ class ChannelManagerTestWithRtpTransport
RTPTransportType type = GetParam();
switch (type) {
case RTPTransportType::kRtp:
return rtc::MakeUnique<webrtc::RtpTransport>(
/*rtcp_mux_required=*/true);
return CreatePlainRtpTransport();
case RTPTransportType::kSrtp:
return rtc::MakeUnique<webrtc::SrtpTransport>(
/*rtcp_mux_required=*/true);
return CreateSrtpTransport();
case RTPTransportType::kDtlsSrtp:
return rtc::MakeUnique<webrtc::DtlsSrtpTransport>(
/*rtcp_mux_required=*/true);
return CreateDtlsSrtpTransport();
}
return nullptr;
}
@ -227,6 +224,29 @@ class ChannelManagerTestWithRtpTransport
cm_->DestroyRtpDataChannel(rtp_data_channel);
cm_->Terminate();
}
private:
std::unique_ptr<webrtc::RtpTransportInternal> CreatePlainRtpTransport() {
return rtc::MakeUnique<webrtc::RtpTransport>(/*rtcp_mux_required=*/true);
}
std::unique_ptr<webrtc::RtpTransportInternal> CreateSrtpTransport() {
auto rtp_transport =
rtc::MakeUnique<webrtc::RtpTransport>(/*rtcp_mux_required=*/true);
auto srtp_transport =
rtc::MakeUnique<webrtc::SrtpTransport>(std::move(rtp_transport));
return srtp_transport;
}
std::unique_ptr<webrtc::RtpTransportInternal> CreateDtlsSrtpTransport() {
auto rtp_transport =
rtc::MakeUnique<webrtc::RtpTransport>(/*rtcp_mux_required=*/true);
auto srtp_transport =
rtc::MakeUnique<webrtc::SrtpTransport>(std::move(rtp_transport));
auto dtls_srtp_transport_ =
rtc::MakeUnique<webrtc::DtlsSrtpTransport>(std::move(srtp_transport));
return dtls_srtp_transport_;
}
};
TEST_P(ChannelManagerTestWithRtpTransport, CreateDestroyChannels) {

View File

@ -24,8 +24,22 @@ static const char kDtlsSrtpExporterLabel[] = "EXTRACTOR-dtls_srtp";
namespace webrtc {
DtlsSrtpTransport::DtlsSrtpTransport(bool rtcp_mux_enabled)
: SrtpTransport(rtcp_mux_enabled) {}
DtlsSrtpTransport::DtlsSrtpTransport(
std::unique_ptr<webrtc::SrtpTransport> srtp_transport)
: RtpTransportInternalAdapter(srtp_transport.get()) {
srtp_transport_ = std::move(srtp_transport);
RTC_DCHECK(srtp_transport_);
srtp_transport_->SignalPacketReceived.connect(
this, &DtlsSrtpTransport::OnPacketReceived);
srtp_transport_->SignalReadyToSend.connect(this,
&DtlsSrtpTransport::OnReadyToSend);
srtp_transport_->SignalNetworkRouteChanged.connect(
this, &DtlsSrtpTransport::OnNetworkRouteChanged);
srtp_transport_->SignalWritableState.connect(
this, &DtlsSrtpTransport::OnWritableState);
srtp_transport_->SignalSentPacket.connect(this,
&DtlsSrtpTransport::OnSentPacket);
}
void DtlsSrtpTransport::SetDtlsTransports(
cricket::DtlsTransportInternal* rtp_dtls_transport,
@ -40,7 +54,7 @@ void DtlsSrtpTransport::SetDtlsTransports(
// DtlsTransport changes and wait until the DTLS handshake is complete to set
// the newly negotiated parameters.
if (IsActive()) {
ResetParams();
srtp_transport_->ResetParams();
}
const std::string transport_name =
@ -66,7 +80,7 @@ void DtlsSrtpTransport::SetDtlsTransports(
}
void DtlsSrtpTransport::SetRtcpMuxEnabled(bool enable) {
SrtpTransport::SetRtcpMuxEnabled(enable);
srtp_transport_->SetRtcpMuxEnabled(enable);
if (enable) {
UpdateWritableStateAndMaybeSetupDtlsSrtp();
}
@ -114,9 +128,10 @@ bool DtlsSrtpTransport::IsDtlsConnected() {
}
bool DtlsSrtpTransport::IsDtlsWritable() {
auto rtp_packet_transport = srtp_transport_->rtp_packet_transport();
auto rtcp_packet_transport =
rtcp_mux_enabled() ? nullptr : rtcp_dtls_transport_;
return rtp_dtls_transport_ && rtp_dtls_transport_->writable() &&
rtcp_mux_enabled() ? nullptr : srtp_transport_->rtcp_packet_transport();
return rtp_packet_transport && rtp_packet_transport->writable() &&
(!rtcp_packet_transport || rtcp_packet_transport->writable());
}
@ -155,10 +170,11 @@ void DtlsSrtpTransport::SetupRtpDtlsSrtp() {
if (!ExtractParams(rtp_dtls_transport_, &selected_crypto_suite, &send_key,
&recv_key) ||
!SetRtpParams(selected_crypto_suite, &send_key[0],
static_cast<int>(send_key.size()), send_extension_ids,
selected_crypto_suite, &recv_key[0],
static_cast<int>(recv_key.size()), recv_extension_ids)) {
!srtp_transport_->SetRtpParams(
selected_crypto_suite, &send_key[0],
static_cast<int>(send_key.size()), send_extension_ids,
selected_crypto_suite, &recv_key[0],
static_cast<int>(recv_key.size()), recv_extension_ids)) {
SignalDtlsSrtpSetupFailure(this, /*rtcp=*/false);
RTC_LOG(LS_WARNING) << "DTLS-SRTP key installation for RTP failed";
}
@ -186,11 +202,11 @@ void DtlsSrtpTransport::SetupRtcpDtlsSrtp() {
rtc::ZeroOnFreeBuffer<unsigned char> rtcp_recv_key;
if (!ExtractParams(rtcp_dtls_transport_, &selected_crypto_suite,
&rtcp_send_key, &rtcp_recv_key) ||
!SetRtcpParams(selected_crypto_suite, &rtcp_send_key[0],
static_cast<int>(rtcp_send_key.size()), send_extension_ids,
selected_crypto_suite, &rtcp_recv_key[0],
static_cast<int>(rtcp_recv_key.size()),
recv_extension_ids)) {
!srtp_transport_->SetRtcpParams(
selected_crypto_suite, &rtcp_send_key[0],
static_cast<int>(rtcp_send_key.size()), send_extension_ids,
selected_crypto_suite, &rtcp_recv_key[0],
static_cast<int>(rtcp_recv_key.size()), recv_extension_ids)) {
SignalDtlsSrtpSetupFailure(this, /*rtcp=*/true);
RTC_LOG(LS_WARNING) << "DTLS-SRTP key installation for RTCP failed";
}
@ -313,20 +329,37 @@ void DtlsSrtpTransport::OnDtlsState(cricket::DtlsTransportInternal* transport,
transport == rtcp_dtls_transport_);
if (state != cricket::DTLS_TRANSPORT_CONNECTED) {
ResetParams();
srtp_transport_->ResetParams();
return;
}
MaybeSetupDtlsSrtp();
}
void DtlsSrtpTransport::OnWritableState(
rtc::PacketTransportInternal* packet_transport) {
bool writable = IsTransportWritable();
void DtlsSrtpTransport::OnWritableState(bool writable) {
SetWritable(writable);
if (writable) {
MaybeSetupDtlsSrtp();
}
}
void DtlsSrtpTransport::OnSentPacket(const rtc::SentPacket& sent_packet) {
SignalSentPacket(sent_packet);
}
void DtlsSrtpTransport::OnPacketReceived(bool rtcp,
rtc::CopyOnWriteBuffer* packet,
const rtc::PacketTime& packet_time) {
SignalPacketReceived(rtcp, packet, packet_time);
}
void DtlsSrtpTransport::OnReadyToSend(bool ready) {
SignalReadyToSend(ready);
}
void DtlsSrtpTransport::OnNetworkRouteChanged(
rtc::Optional<rtc::NetworkRoute> network_route) {
SignalNetworkRouteChanged(network_route);
}
} // namespace webrtc

View File

@ -16,17 +16,20 @@
#include <vector>
#include "p2p/base/dtlstransportinternal.h"
#include "pc/rtptransportinternaladapter.h"
#include "pc/srtptransport.h"
#include "rtc_base/buffer.h"
namespace webrtc {
// The subclass of SrtpTransport is used for DTLS-SRTP. When the DTLS handshake
// is finished, it extracts the keying materials from DtlsTransport and
// configures the SrtpSessions in the base class.
class DtlsSrtpTransport : public SrtpTransport {
// This class is intended to be used as an RtpTransport and it wraps both an
// SrtpTransport and DtlsTransports(RTP/RTCP). When the DTLS handshake is
// finished, it extracts the keying materials from DtlsTransport and sets them
// to SrtpTransport.
class DtlsSrtpTransport : public RtpTransportInternalAdapter {
public:
explicit DtlsSrtpTransport(bool rtcp_mux_enabled);
explicit DtlsSrtpTransport(
std::unique_ptr<webrtc::SrtpTransport> srtp_transport);
// Set P2P layer RTP/RTCP DtlsTransports. When using RTCP-muxing,
// |rtcp_dtls_transport| is null.
@ -42,6 +45,15 @@ class DtlsSrtpTransport : public SrtpTransport {
void UpdateRecvEncryptedHeaderExtensionIds(
const std::vector<int>& recv_extension_ids);
bool IsActive() { return srtp_transport_->IsActive(); }
// Cache RTP Absoulute SendTime extension header ID. This is only used when
// external authentication is enabled.
void CacheRtpAbsSendTimeHeaderExtension(int rtp_abs_sendtime_extn_id) {
srtp_transport_->CacheRtpAbsSendTimeHeaderExtension(
rtp_abs_sendtime_extn_id);
}
// TODO(zhihuang): Remove this when we remove RtpTransportAdapter.
RtpTransportAdapter* GetInternal() override { return nullptr; }
@ -71,11 +83,16 @@ class DtlsSrtpTransport : public SrtpTransport {
void OnDtlsState(cricket::DtlsTransportInternal* dtls_transport,
cricket::DtlsTransportState state);
// Override the RtpTransport::OnWritableState.
void OnWritableState(rtc::PacketTransportInternal* packet_transport) override;
void OnWritableState(bool writable);
void OnSentPacket(const rtc::SentPacket& sent_packet);
void OnPacketReceived(bool rtcp,
rtc::CopyOnWriteBuffer* packet,
const rtc::PacketTime& packet_time);
void OnReadyToSend(bool ready);
void OnNetworkRouteChanged(rtc::Optional<rtc::NetworkRoute> network_route);
bool writable_ = false;
std::unique_ptr<SrtpTransport> srtp_transport_;
// Owned by the TransportController.
cricket::DtlsTransportInternal* rtp_dtls_transport_ = nullptr;
cricket::DtlsTransportInternal* rtcp_dtls_transport_ = nullptr;

View File

@ -33,26 +33,50 @@ using webrtc::RtpTransport;
const int kRtpAuthTagLen = 10;
class TransportObserver : public sigslot::has_slots<> {
public:
void OnPacketReceived(bool rtcp,
rtc::CopyOnWriteBuffer* packet,
const rtc::PacketTime& packet_time) {
rtcp ? last_recv_rtcp_packet_ = *packet : last_recv_rtp_packet_ = *packet;
}
void OnReadyToSend(bool ready) { ready_to_send_ = ready; }
rtc::CopyOnWriteBuffer last_recv_rtp_packet() {
return last_recv_rtp_packet_;
}
rtc::CopyOnWriteBuffer last_recv_rtcp_packet() {
return last_recv_rtcp_packet_;
}
bool ready_to_send() { return ready_to_send_; }
private:
rtc::CopyOnWriteBuffer last_recv_rtp_packet_;
rtc::CopyOnWriteBuffer last_recv_rtcp_packet_;
bool ready_to_send_ = false;
};
class DtlsSrtpTransportTest : public testing::Test,
public sigslot::has_slots<> {
protected:
DtlsSrtpTransportTest() {}
~DtlsSrtpTransportTest() {
if (dtls_srtp_transport1_) {
dtls_srtp_transport1_->UnregisterRtpDemuxerSink(&transport_observer1_);
}
if (dtls_srtp_transport2_) {
dtls_srtp_transport2_->UnregisterRtpDemuxerSink(&transport_observer2_);
}
}
std::unique_ptr<DtlsSrtpTransport> MakeDtlsSrtpTransport(
FakeDtlsTransport* rtp_dtls,
FakeDtlsTransport* rtcp_dtls,
bool rtcp_mux_enabled) {
auto rtp_transport = rtc::MakeUnique<RtpTransport>(rtcp_mux_enabled);
rtp_transport->AddHandledPayloadType(0x00);
rtp_transport->AddHandledPayloadType(0xc9);
auto srtp_transport =
rtc::MakeUnique<SrtpTransport>(std::move(rtp_transport));
auto dtls_srtp_transport =
rtc::MakeUnique<DtlsSrtpTransport>(rtcp_mux_enabled);
rtc::MakeUnique<DtlsSrtpTransport>(std::move(srtp_transport));
dtls_srtp_transport->SetDtlsTransports(rtp_dtls, rtcp_dtls);
@ -69,24 +93,15 @@ class DtlsSrtpTransportTest : public testing::Test,
dtls_srtp_transport2_ =
MakeDtlsSrtpTransport(rtp_dtls2, rtcp_dtls2, rtcp_mux_enabled);
dtls_srtp_transport1_->SignalRtcpPacketReceived.connect(
&transport_observer1_,
&webrtc::TransportObserver::OnRtcpPacketReceived);
dtls_srtp_transport1_->SignalPacketReceived.connect(
&transport_observer1_, &TransportObserver::OnPacketReceived);
dtls_srtp_transport1_->SignalReadyToSend.connect(
&transport_observer1_, &webrtc::TransportObserver::OnReadyToSend);
&transport_observer1_, &TransportObserver::OnReadyToSend);
dtls_srtp_transport2_->SignalRtcpPacketReceived.connect(
&transport_observer2_,
&webrtc::TransportObserver::OnRtcpPacketReceived);
dtls_srtp_transport2_->SignalPacketReceived.connect(
&transport_observer2_, &TransportObserver::OnPacketReceived);
dtls_srtp_transport2_->SignalReadyToSend.connect(
&transport_observer2_, &webrtc::TransportObserver::OnReadyToSend);
webrtc::RtpDemuxerCriteria demuxer_criteria;
// 0x00 is the payload type used in kPcmuFrame.
demuxer_criteria.payload_types = {0x00};
dtls_srtp_transport1_->RegisterRtpDemuxerSink(demuxer_criteria,
&transport_observer1_);
dtls_srtp_transport2_->RegisterRtpDemuxerSink(demuxer_criteria,
&transport_observer2_);
&transport_observer2_, &TransportObserver::OnReadyToSend);
}
void CompleteDtlsHandshake(FakeDtlsTransport* fake_dtls1,
@ -236,8 +251,8 @@ class DtlsSrtpTransportTest : public testing::Test,
std::unique_ptr<DtlsSrtpTransport> dtls_srtp_transport1_;
std::unique_ptr<DtlsSrtpTransport> dtls_srtp_transport2_;
webrtc::TransportObserver transport_observer1_;
webrtc::TransportObserver transport_observer2_;
TransportObserver transport_observer1_;
TransportObserver transport_observer2_;
int sequence_number_ = 0;
};

View File

@ -43,8 +43,9 @@ class JsepTransport2Test : public testing::Test, public sigslot::has_slots<> {
const std::string& transport_name,
rtc::PacketTransportInternal* rtp_packet_transport,
rtc::PacketTransportInternal* rtcp_packet_transport) {
auto srtp_transport = rtc::MakeUnique<webrtc::SrtpTransport>(
rtcp_packet_transport == nullptr);
bool rtcp_mux_enabled = (rtcp_packet_transport == nullptr);
auto srtp_transport =
rtc::MakeUnique<webrtc::SrtpTransport>(rtcp_mux_enabled);
srtp_transport->SetRtpPacketTransport(rtp_packet_transport);
if (rtcp_packet_transport) {
@ -57,8 +58,11 @@ class JsepTransport2Test : public testing::Test, public sigslot::has_slots<> {
const std::string& transport_name,
cricket::DtlsTransportInternal* rtp_dtls_transport,
cricket::DtlsTransportInternal* rtcp_dtls_transport) {
auto dtls_srtp_transport = rtc::MakeUnique<webrtc::DtlsSrtpTransport>(
rtcp_dtls_transport == nullptr);
bool rtcp_mux_enabled = (rtcp_dtls_transport == nullptr);
auto srtp_transport =
rtc::MakeUnique<webrtc::SrtpTransport>(rtcp_mux_enabled);
auto dtls_srtp_transport =
rtc::MakeUnique<webrtc::DtlsSrtpTransport>(std::move(srtp_transport));
dtls_srtp_transport->SetDtlsTransports(rtp_dtls_transport,
rtcp_dtls_transport);

View File

@ -457,13 +457,16 @@ JsepTransportController::CreateDtlsSrtpTransport(
cricket::DtlsTransportInternal* rtp_dtls_transport,
cricket::DtlsTransportInternal* rtcp_dtls_transport) {
RTC_DCHECK(network_thread_->IsCurrent());
auto dtls_srtp_transport = rtc::MakeUnique<webrtc::DtlsSrtpTransport>(
rtcp_dtls_transport == nullptr);
bool rtcp_mux_enabled = rtcp_dtls_transport == nullptr;
auto srtp_transport =
rtc::MakeUnique<webrtc::SrtpTransport>(rtcp_mux_enabled);
if (config_.enable_external_auth) {
dtls_srtp_transport->EnableExternalAuth();
srtp_transport->EnableExternalAuth();
}
auto dtls_srtp_transport =
rtc::MakeUnique<webrtc::DtlsSrtpTransport>(std::move(srtp_transport));
dtls_srtp_transport->SetDtlsTransports(rtp_dtls_transport,
rtcp_dtls_transport);
return dtls_srtp_transport;

View File

@ -6195,9 +6195,12 @@ void PeerConnection::DestroyDataChannel() {
void PeerConnection::DestroyBaseChannel(cricket::BaseChannel* channel) {
RTC_DCHECK(channel);
RTC_DCHECK(channel->rtp_dtls_transport());
// Need to cache these before destroying the base channel so that we do not
// access uninitialized memory.
const std::string transport_name = channel->transport_name();
const std::string transport_name =
channel->rtp_dtls_transport()->transport_name();
const bool need_to_delete_rtcp = (channel->rtcp_dtls_transport() != nullptr);
switch (channel->media_type()) {

View File

@ -959,8 +959,8 @@ void RenameContent(cricket::SessionDescription* desc,
// Tests that an answer responds with the same MIDs as the offer.
TEST_P(PeerConnectionMediaTest, AnswerHasSameMidsAsOffer) {
const std::string kAudioMid = "notdefault1";
const std::string kVideoMid = "notdefault2";
const std::string kAudioMid = "not default1";
const std::string kVideoMid = "not default2";
auto caller = CreatePeerConnectionWithAudioVideo();
auto callee = CreatePeerConnectionWithAudioVideo();
@ -980,8 +980,8 @@ TEST_P(PeerConnectionMediaTest, AnswerHasSameMidsAsOffer) {
// Test that if the callee creates a re-offer, the MIDs are the same as the
// original offer.
TEST_P(PeerConnectionMediaTest, ReOfferHasSameMidsAsFirstOffer) {
const std::string kAudioMid = "notdefault1";
const std::string kVideoMid = "notdefault2";
const std::string kAudioMid = "not default1";
const std::string kVideoMid = "not default2";
auto caller = CreatePeerConnectionWithAudioVideo();
auto callee = CreatePeerConnectionWithAudioVideo();

View File

@ -10,10 +10,7 @@
#include "pc/rtptransport.h"
#include <utility>
#include "media/base/rtputils.h"
#include "modules/rtp_rtcp/source/rtp_packet_received.h"
#include "p2p/base/p2pconstants.h"
#include "p2p/base/packettransportinterface.h"
#include "rtc_base/checks.h"
@ -47,7 +44,7 @@ void RtpTransport::SetRtpPacketTransport(
new_packet_transport->SignalReadPacket.connect(this,
&RtpTransport::OnReadPacket);
new_packet_transport->SignalNetworkRouteChanged.connect(
this, &RtpTransport::OnNetworkRouteChanged);
this, &RtpTransport::OnNetworkRouteChange);
new_packet_transport->SignalWritableState.connect(
this, &RtpTransport::OnWritableState);
new_packet_transport->SignalSentPacket.connect(this,
@ -83,7 +80,7 @@ void RtpTransport::SetRtcpPacketTransport(
new_packet_transport->SignalReadPacket.connect(this,
&RtpTransport::OnReadPacket);
new_packet_transport->SignalNetworkRouteChanged.connect(
this, &RtpTransport::OnNetworkRouteChanged);
this, &RtpTransport::OnNetworkRouteChange);
new_packet_transport->SignalWritableState.connect(
this, &RtpTransport::OnWritableState);
new_packet_transport->SignalSentPacket.connect(this,
@ -137,27 +134,16 @@ bool RtpTransport::SendPacket(bool rtcp,
return true;
}
void RtpTransport::UpdateRtpHeaderExtensionMap(
const cricket::RtpHeaderExtensions& header_extensions) {
header_extension_map_ = RtpHeaderExtensionMap(header_extensions);
bool RtpTransport::HandlesPacket(const uint8_t* data, size_t len) {
return bundle_filter_.DemuxPacket(data, len);
}
bool RtpTransport::RegisterRtpDemuxerSink(const RtpDemuxerCriteria& criteria,
RtpPacketSinkInterface* sink) {
rtp_demuxer_.RemoveSink(sink);
if (!rtp_demuxer_.AddSink(criteria, sink)) {
RTC_LOG(LS_ERROR) << "Failed to register the sink for RTP demuxer.";
return false;
}
return true;
bool RtpTransport::HandlesPayloadType(int payload_type) const {
return bundle_filter_.FindPayloadType(payload_type);
}
bool RtpTransport::UnregisterRtpDemuxerSink(RtpPacketSinkInterface* sink) {
if (!rtp_demuxer_.RemoveSink(sink)) {
RTC_LOG(LS_ERROR) << "Failed to unregister the sink for RTP demuxer.";
return false;
}
return true;
void RtpTransport::AddHandledPayloadType(int payload_type) {
bundle_filter_.AddPayloadType(payload_type);
}
PacketTransportInterface* RtpTransport::GetRtpPacketTransport() const {
@ -194,26 +180,11 @@ RtpTransportParameters RtpTransport::GetParameters() const {
return parameters_;
}
void RtpTransport::DemuxPacket(rtc::CopyOnWriteBuffer* packet,
const rtc::PacketTime& time) {
webrtc::RtpPacketReceived parsed_packet(&header_extension_map_);
if (!parsed_packet.Parse(std::move(*packet))) {
RTC_LOG(LS_ERROR)
<< "Failed to parse the incoming RTP packet before demuxing. Drop it.";
return;
}
if (time.timestamp != -1) {
parsed_packet.set_arrival_time_ms((time.timestamp + 500) / 1000);
}
rtp_demuxer_.OnRtpPacket(parsed_packet);
}
RtpTransportAdapter* RtpTransport::GetInternal() {
return nullptr;
}
bool RtpTransport::IsTransportWritable() {
bool RtpTransport::IsRtpTransportWritable() {
auto rtcp_packet_transport =
rtcp_mux_enabled_ ? nullptr : rtcp_packet_transport_;
return rtp_packet_transport_ && rtp_packet_transport_->writable() &&
@ -224,7 +195,7 @@ void RtpTransport::OnReadyToSend(rtc::PacketTransportInternal* transport) {
SetReadyToSend(transport == rtcp_packet_transport_, true);
}
void RtpTransport::OnNetworkRouteChanged(
void RtpTransport::OnNetworkRouteChange(
rtc::Optional<rtc::NetworkRoute> network_route) {
SignalNetworkRouteChanged(network_route);
}
@ -233,7 +204,7 @@ void RtpTransport::OnWritableState(
rtc::PacketTransportInternal* packet_transport) {
RTC_DCHECK(packet_transport == rtp_packet_transport_ ||
packet_transport == rtcp_packet_transport_);
SignalWritableState(IsTransportWritable());
SignalWritableState(IsRtpTransportWritable());
}
void RtpTransport::OnSentPacket(rtc::PacketTransportInternal* packet_transport,
@ -243,44 +214,6 @@ void RtpTransport::OnSentPacket(rtc::PacketTransportInternal* packet_transport,
SignalSentPacket(sent_packet);
}
void RtpTransport::OnRtpPacketReceived(rtc::CopyOnWriteBuffer* packet,
const rtc::PacketTime& packet_time) {
DemuxPacket(packet, packet_time);
}
void RtpTransport::OnRtcpPacketReceived(rtc::CopyOnWriteBuffer* packet,
const rtc::PacketTime& packet_time) {
SignalRtcpPacketReceived(packet, packet_time);
}
void RtpTransport::OnReadPacket(rtc::PacketTransportInternal* transport,
const char* data,
size_t len,
const rtc::PacketTime& packet_time,
int flags) {
TRACE_EVENT0("webrtc", "RtpTransport::OnReadPacket");
// When using RTCP multiplexing we might get RTCP packets on the RTP
// transport. We check the RTP payload type to determine if it is RTCP.
bool rtcp = transport == rtcp_packet_transport() ||
cricket::IsRtcp(data, static_cast<int>(len));
rtc::CopyOnWriteBuffer packet(data, len);
// Protect ourselves against crazy data.
if (!cricket::IsValidRtpRtcpPacketSize(rtcp, packet.size())) {
RTC_LOG(LS_ERROR) << "Dropping incoming "
<< cricket::RtpRtcpStringLiteral(rtcp)
<< " packet: wrong size=" << packet.size();
return;
}
if (rtcp) {
OnRtcpPacketReceived(&packet, packet_time);
} else {
OnRtpPacketReceived(&packet, packet_time);
}
}
void RtpTransport::SetReadyToSend(bool rtcp, bool ready) {
if (rtcp) {
rtcp_ready_to_send_ = ready;
@ -300,4 +233,51 @@ void RtpTransport::MaybeSignalReadyToSend() {
}
}
// Check the RTP payload type. If 63 < payload type < 96, it's RTCP.
// For additional details, see http://tools.ietf.org/html/rfc5761.
bool IsRtcp(const char* data, int len) {
if (len < 2) {
return false;
}
char pt = data[1] & 0x7F;
return (63 < pt) && (pt < 96);
}
void RtpTransport::OnReadPacket(rtc::PacketTransportInternal* transport,
const char* data,
size_t len,
const rtc::PacketTime& packet_time,
int flags) {
TRACE_EVENT0("webrtc", "RtpTransport::OnReadPacket");
// When using RTCP multiplexing we might get RTCP packets on the RTP
// transport. We check the RTP payload type to determine if it is RTCP.
bool rtcp = transport == rtcp_packet_transport() ||
IsRtcp(data, static_cast<int>(len));
rtc::CopyOnWriteBuffer packet(data, len);
if (!WantsPacket(rtcp, &packet)) {
return;
}
// This mutates |packet| if it is protected.
SignalPacketReceived(rtcp, &packet, packet_time);
}
bool RtpTransport::WantsPacket(bool rtcp,
const rtc::CopyOnWriteBuffer* packet) {
// Protect ourselves against crazy data.
if (!packet || !cricket::IsValidRtpRtcpPacketSize(rtcp, packet->size())) {
RTC_LOG(LS_ERROR) << "Dropping incoming "
<< cricket::RtpRtcpStringLiteral(rtcp)
<< " packet: wrong size=" << packet->size();
return false;
}
if (rtcp) {
// Permit all (seemingly valid) RTCP packets.
return true;
}
// Check whether we handle this payload.
return HandlesPacket(packet->data(), packet->size());
}
} // namespace webrtc

View File

@ -13,8 +13,7 @@
#include <string>
#include "call/rtp_demuxer.h"
#include "modules/rtp_rtcp/include/rtp_header_extension_map.h"
#include "pc/bundlefilter.h"
#include "pc/rtptransportinternal.h"
#include "rtc_base/sigslot.h"
@ -67,13 +66,9 @@ class RtpTransport : public RtpTransportInternal {
const rtc::PacketOptions& options,
int flags) override;
void UpdateRtpHeaderExtensionMap(
const cricket::RtpHeaderExtensions& header_extensions) override;
bool HandlesPayloadType(int payload_type) const override;
bool RegisterRtpDemuxerSink(const RtpDemuxerCriteria& criteria,
RtpPacketSinkInterface* sink) override;
bool UnregisterRtpDemuxerSink(RtpPacketSinkInterface* sink) override;
void AddHandledPayloadType(int payload_type) override;
void SetMetricsObserver(
rtc::scoped_refptr<MetricsObserverInterface> metrics_observer) override {}
@ -82,35 +77,15 @@ class RtpTransport : public RtpTransportInternal {
// TODO(zstein): Remove this when we remove RtpTransportAdapter.
RtpTransportAdapter* GetInternal() override;
// These methods will be used in the subclasses.
void DemuxPacket(rtc::CopyOnWriteBuffer* packet, const rtc::PacketTime& time);
bool SendPacket(bool rtcp,
rtc::CopyOnWriteBuffer* packet,
const rtc::PacketOptions& options,
int flags);
bool IsTransportWritable();
// Overridden by SrtpTransport.
virtual void OnNetworkRouteChanged(
rtc::Optional<rtc::NetworkRoute> network_route);
virtual void OnRtpPacketReceived(rtc::CopyOnWriteBuffer* packet,
const rtc::PacketTime& packet_time);
virtual void OnRtcpPacketReceived(rtc::CopyOnWriteBuffer* packet,
const rtc::PacketTime& packet_time);
// Overridden by DtlsSrtpTransport.
virtual void OnWritableState(rtc::PacketTransportInternal* packet_transport);
private:
bool IsRtpTransportWritable();
bool HandlesPacket(const uint8_t* data, size_t len);
void OnReadyToSend(rtc::PacketTransportInternal* transport);
void OnNetworkRouteChange(rtc::Optional<rtc::NetworkRoute> network_route);
void OnWritableState(rtc::PacketTransportInternal* packet_transport);
void OnSentPacket(rtc::PacketTransportInternal* packet_transport,
const rtc::SentPacket& sent_packet);
void OnReadPacket(rtc::PacketTransportInternal* transport,
const char* data,
size_t len,
const rtc::PacketTime& packet_time,
int flags);
// Updates "ready to send" for an individual channel and fires
// SignalReadyToSend.
@ -118,17 +93,18 @@ class RtpTransport : public RtpTransportInternal {
void MaybeSignalReadyToSend();
// SRTP specific methods.
// TODO(zhihuang): Improve the inheritance model so that the RtpTransport
// doesn't need to implement SRTP specfic methods.
RTCError SetSrtpSendKey(const cricket::CryptoParams& params) override {
RTC_NOTREACHED();
return RTCError::OK();
}
RTCError SetSrtpReceiveKey(const cricket::CryptoParams& params) override {
RTC_NOTREACHED();
return RTCError::OK();
}
bool SendPacket(bool rtcp,
rtc::CopyOnWriteBuffer* packet,
const rtc::PacketOptions& options,
int flags);
void OnReadPacket(rtc::PacketTransportInternal* transport,
const char* data,
size_t len,
const rtc::PacketTime& packet_time,
int flags);
bool WantsPacket(bool rtcp, const rtc::CopyOnWriteBuffer* packet);
bool rtcp_mux_enabled_;
@ -140,10 +116,8 @@ class RtpTransport : public RtpTransportInternal {
bool rtcp_ready_to_send_ = false;
RtpTransportParameters parameters_;
RtpDemuxer rtp_demuxer_;
// Used for identifying the MID for RtpDemuxer.
RtpHeaderExtensionMap header_extension_map_;
cricket::BundleFilter bundle_filter_;
};
} // namespace webrtc

View File

@ -197,37 +197,49 @@ TEST(RtpTransportTest, SetRtcpTransportWithNetworkRouteChanged) {
EXPECT_FALSE(observer.network_route());
}
class SignalCounter : public sigslot::has_slots<> {
public:
explicit SignalCounter(RtpTransport* transport) {
transport->SignalReadyToSend.connect(this, &SignalCounter::OnReadyToSend);
}
int count() const { return count_; }
void OnReadyToSend(bool ready) { ++count_; }
private:
int count_ = 0;
};
TEST(RtpTransportTest, ChangingReadyToSendStateOnlySignalsWhenChanged) {
RtpTransport transport(kMuxEnabled);
TransportObserver observer(&transport);
SignalCounter observer(&transport);
rtc::FakePacketTransport fake_rtp("fake_rtp");
fake_rtp.SetWritable(true);
// State changes, so we should signal.
transport.SetRtpPacketTransport(&fake_rtp);
EXPECT_EQ(observer.ready_to_send_signal_count(), 1);
EXPECT_EQ(observer.count(), 1);
// State does not change, so we should not signal.
transport.SetRtpPacketTransport(&fake_rtp);
EXPECT_EQ(observer.ready_to_send_signal_count(), 1);
EXPECT_EQ(observer.count(), 1);
// State does not change, so we should not signal.
transport.SetRtcpMuxEnabled(true);
EXPECT_EQ(observer.ready_to_send_signal_count(), 1);
EXPECT_EQ(observer.count(), 1);
// State changes, so we should signal.
transport.SetRtcpMuxEnabled(false);
EXPECT_EQ(observer.ready_to_send_signal_count(), 2);
EXPECT_EQ(observer.count(), 2);
}
// Test that SignalPacketReceived fires with rtcp=true when a RTCP packet is
// received.
TEST(RtpTransportTest, SignalDemuxedRtcp) {
RtpTransport transport(kMuxDisabled);
SignalPacketReceivedCounter observer(&transport);
rtc::FakePacketTransport fake_rtp("fake_rtp");
fake_rtp.SetDestination(&fake_rtp, true);
transport.SetRtpPacketTransport(&fake_rtp);
TransportObserver observer(&transport);
// An rtcp packet.
const char data[] = {0, 73, 0, 0};
@ -247,15 +259,11 @@ static const int kRtpLen = 12;
// handled payload type is received.
TEST(RtpTransportTest, SignalHandledRtpPayloadType) {
RtpTransport transport(kMuxDisabled);
SignalPacketReceivedCounter observer(&transport);
rtc::FakePacketTransport fake_rtp("fake_rtp");
fake_rtp.SetDestination(&fake_rtp, true);
// Disable the encryption to allow raw RTP data.
transport.SetRtpPacketTransport(&fake_rtp);
TransportObserver observer(&transport);
RtpDemuxerCriteria demuxer_criteria;
// Add a handled payload type.
demuxer_criteria.payload_types = {0x11};
transport.RegisterRtpDemuxerSink(demuxer_criteria, &observer);
transport.AddHandledPayloadType(0x11);
// An rtp packet.
const rtc::PacketOptions options;
@ -264,22 +272,16 @@ TEST(RtpTransportTest, SignalHandledRtpPayloadType) {
fake_rtp.SendPacket(rtp_data.data<char>(), kRtpLen, options, flags);
EXPECT_EQ(1, observer.rtp_count());
EXPECT_EQ(0, observer.rtcp_count());
// Remove the sink before destroying the transport.
transport.UnregisterRtpDemuxerSink(&observer);
}
// Test that SignalPacketReceived does not fire when a RTP packet with an
// unhandled payload type is received.
TEST(RtpTransportTest, DontSignalUnhandledRtpPayloadType) {
RtpTransport transport(kMuxDisabled);
SignalPacketReceivedCounter observer(&transport);
rtc::FakePacketTransport fake_rtp("fake_rtp");
fake_rtp.SetDestination(&fake_rtp, true);
transport.SetRtpPacketTransport(&fake_rtp);
TransportObserver observer(&transport);
RtpDemuxerCriteria demuxer_criteria;
// Add an unhandled payload type.
demuxer_criteria.payload_types = {0x12};
transport.RegisterRtpDemuxerSink(demuxer_criteria, &observer);
const rtc::PacketOptions options;
const int flags = 0;
@ -287,8 +289,6 @@ TEST(RtpTransportTest, DontSignalUnhandledRtpPayloadType) {
fake_rtp.SendPacket(rtp_data.data<char>(), kRtpLen, options, flags);
EXPECT_EQ(0, observer.rtp_count());
EXPECT_EQ(0, observer.rtcp_count());
// Remove the sink before destroying the transport.
transport.UnregisterRtpDemuxerSink(&observer);
}
} // namespace webrtc

View File

@ -13,11 +13,9 @@
#include <string>
#include "api/ortc/srtptransportinterface.h"
#include "api/ortc/rtptransportinterface.h"
#include "api/umametrics.h"
#include "call/rtp_demuxer.h"
#include "p2p/base/icetransportinternal.h"
#include "pc/sessiondescription.h"
#include "rtc_base/networkroute.h"
#include "rtc_base/sigslot.h"
@ -29,11 +27,11 @@ struct PacketTime;
namespace webrtc {
// This represents the internal interface beneath SrtpTransportInterface;
// This represents the internal interface beneath RtpTransportInterface;
// it is not accessible to API consumers but is accessible to internal classes
// in order to send and receive RTP and RTCP packets belonging to a single RTP
// session. Additional convenience and configuration methods are also provided.
class RtpTransportInternal : public SrtpTransportInterface,
class RtpTransportInternal : public RtpTransportInterface,
public sigslot::has_slots<> {
public:
virtual void SetRtcpMuxEnabled(bool enable) = 0;
@ -54,11 +52,11 @@ class RtpTransportInternal : public SrtpTransportInterface,
// than just "writable"; it means the last send didn't return ENOTCONN.
sigslot::signal1<bool> SignalReadyToSend;
// Called whenever an RTCP packet is received. There is no equivalent signal
// for RTP packets because they would be forwarded to the BaseChannel through
// the RtpDemuxer callback.
sigslot::signal2<rtc::CopyOnWriteBuffer*, const rtc::PacketTime&>
SignalRtcpPacketReceived;
// TODO(zstein): Consider having two signals - RtpPacketReceived and
// RtcpPacketReceived.
// The first argument is true for RTCP packets and false for RTP packets.
sigslot::signal3<bool, rtc::CopyOnWriteBuffer*, const rtc::PacketTime&>
SignalPacketReceived;
// Called whenever the network route of the P2P layer transport changes.
// The argument is an optional network route.
@ -82,22 +80,12 @@ class RtpTransportInternal : public SrtpTransportInterface,
const rtc::PacketOptions& options,
int flags) = 0;
// This method updates the RTP header extension map so that the RTP transport
// can parse the received packets and identify the MID. This is called by the
// BaseChannel when setting the content description.
//
// Note: This doesn't take the BUNDLE case in account meaning the RTP header
// extension maps are not merged when BUNDLE is enabled. This is fine because
// the ID for MID should be consistent among all the RTP transports.
virtual void UpdateRtpHeaderExtensionMap(
const cricket::RtpHeaderExtensions& header_extensions) = 0;
virtual bool HandlesPayloadType(int payload_type) const = 0;
virtual void AddHandledPayloadType(int payload_type) = 0;
virtual void SetMetricsObserver(
rtc::scoped_refptr<MetricsObserverInterface> metrics_observer) = 0;
virtual bool RegisterRtpDemuxerSink(const RtpDemuxerCriteria& criteria,
RtpPacketSinkInterface* sink) = 0;
virtual bool UnregisterRtpDemuxerSink(RtpPacketSinkInterface* sink) = 0;
};
} // namespace webrtc

View File

@ -67,22 +67,12 @@ class RtpTransportInternalAdapter : public RtpTransportInternal {
return transport_->SendRtcpPacket(packet, options, flags);
}
void UpdateRtpHeaderExtensionMap(
const cricket::RtpHeaderExtensions& header_extensions) override {
transport_->UpdateRtpHeaderExtensionMap(header_extensions);
bool HandlesPayloadType(int payload_type) const override {
return transport_->HandlesPayloadType(payload_type);
}
void RegisterRtpDemuxerSink(const RtpDemuxerCriteria& criteria,
RtpPacketSinkInterface* sink) override {
transport_->RegisterRtpDemuxerSink(criteria, sink);
}
void UnregisterRtpDemuxerSink(RtpPacketSinkInterface* sink) override {
transport_->UnregisterRtpDemuxerSink(sink);
}
void SetEncryptionDisabled(bool encryption_disabled) override {
transport_->SetEncryptionDisabled(encryption_disabled);
void AddHandledPayloadType(int payload_type) override {
return transport_->AddHandledPayloadType(payload_type);
}
// RtpTransportInterface overrides.

View File

@ -11,67 +11,32 @@
#ifndef PC_RTPTRANSPORTTESTUTIL_H_
#define PC_RTPTRANSPORTTESTUTIL_H_
#include "call/rtp_packet_sink_interface.h"
#include "modules/rtp_rtcp/source/rtp_packet_received.h"
#include "pc/rtptransportinternal.h"
#include "rtc_base/sigslot.h"
namespace webrtc {
// Used to handle the signals when the RtpTransport receives an RTP/RTCP packet.
// Used in Rtp/Srtp/DtlsTransport unit tests.
class TransportObserver : public RtpPacketSinkInterface,
public sigslot::has_slots<> {
class SignalPacketReceivedCounter : public sigslot::has_slots<> {
public:
TransportObserver() {}
explicit TransportObserver(RtpTransportInternal* rtp_transport) {
rtp_transport->SignalRtcpPacketReceived.connect(
this, &TransportObserver::OnRtcpPacketReceived);
rtp_transport->SignalReadyToSend.connect(this,
&TransportObserver::OnReadyToSend);
explicit SignalPacketReceivedCounter(RtpTransportInternal* transport) {
transport->SignalPacketReceived.connect(
this, &SignalPacketReceivedCounter::OnPacketReceived);
}
// RtpPacketInterface override.
void OnRtpPacket(const RtpPacketReceived& packet) override {
rtp_count_++;
last_recv_rtp_packet_ = packet.Buffer();
}
void OnRtcpPacketReceived(rtc::CopyOnWriteBuffer* packet,
const rtc::PacketTime& packet_time) {
RTC_LOG(LS_INFO) << "Received an RTCP packet.";
rtcp_count_++;
last_recv_rtcp_packet_ = *packet;
}
int rtp_count() const { return rtp_count_; }
int rtcp_count() const { return rtcp_count_; }
rtc::CopyOnWriteBuffer last_recv_rtp_packet() {
return last_recv_rtp_packet_;
}
rtc::CopyOnWriteBuffer last_recv_rtcp_packet() {
return last_recv_rtcp_packet_;
}
void OnReadyToSend(bool ready) {
ready_to_send_signal_count_++;
ready_to_send_ = ready;
}
bool ready_to_send() { return ready_to_send_; }
int ready_to_send_signal_count() { return ready_to_send_signal_count_; }
int rtp_count() const { return rtp_count_; }
private:
bool ready_to_send_ = false;
int rtp_count_ = 0;
void OnPacketReceived(bool rtcp,
rtc::CopyOnWriteBuffer*,
const rtc::PacketTime&) {
if (rtcp) {
++rtcp_count_;
} else {
++rtp_count_;
}
}
int rtcp_count_ = 0;
int ready_to_send_signal_count_ = 0;
rtc::CopyOnWriteBuffer last_recv_rtp_packet_;
rtc::CopyOnWriteBuffer last_recv_rtcp_packet_;
int rtp_count_ = 0;
};
} // namespace webrtc

View File

@ -25,133 +25,155 @@
namespace webrtc {
SrtpTransport::SrtpTransport(bool rtcp_mux_enabled)
: RtpTransport(rtcp_mux_enabled) {}
: RtpTransportInternalAdapter(new RtpTransport(rtcp_mux_enabled)) {
// Own the raw pointer |transport| from the base class.
rtp_transport_.reset(transport_);
RTC_DCHECK(rtp_transport_);
ConnectToRtpTransport();
}
SrtpTransport::SrtpTransport(
std::unique_ptr<RtpTransportInternal> rtp_transport)
: RtpTransportInternalAdapter(rtp_transport.get()),
rtp_transport_(std::move(rtp_transport)) {
RTC_DCHECK(rtp_transport_);
ConnectToRtpTransport();
}
void SrtpTransport::ConnectToRtpTransport() {
rtp_transport_->SignalPacketReceived.connect(
this, &SrtpTransport::OnPacketReceived);
rtp_transport_->SignalReadyToSend.connect(this,
&SrtpTransport::OnReadyToSend);
rtp_transport_->SignalNetworkRouteChanged.connect(
this, &SrtpTransport::OnNetworkRouteChanged);
rtp_transport_->SignalWritableState.connect(this,
&SrtpTransport::OnWritableState);
rtp_transport_->SignalSentPacket.connect(this, &SrtpTransport::OnSentPacket);
}
bool SrtpTransport::SendRtpPacket(rtc::CopyOnWriteBuffer* packet,
const rtc::PacketOptions& options,
int flags) {
return SendPacket(false, packet, options, flags);
}
bool SrtpTransport::SendRtcpPacket(rtc::CopyOnWriteBuffer* packet,
const rtc::PacketOptions& options,
int flags) {
return SendPacket(true, packet, options, flags);
}
bool SrtpTransport::SendPacket(bool rtcp,
rtc::CopyOnWriteBuffer* packet,
const rtc::PacketOptions& options,
int flags) {
if (!IsActive()) {
RTC_LOG(LS_ERROR)
<< "Failed to send the packet because SRTP transport is inactive.";
return false;
}
rtc::PacketOptions updated_options = options;
rtc::CopyOnWriteBuffer cp = *packet;
TRACE_EVENT0("webrtc", "SRTP Encode");
bool res;
uint8_t* data = packet->data();
int len = static_cast<int>(packet->size());
if (!rtcp) {
// If ENABLE_EXTERNAL_AUTH flag is on then packet authentication is not done
// inside libsrtp for a RTP packet. A external HMAC module will be writing
// a fake HMAC value. This is ONLY done for a RTP packet.
// Socket layer will update rtp sendtime extension header if present in
// packet with current time before updating the HMAC.
#if !defined(ENABLE_EXTERNAL_AUTH)
res = ProtectRtp(data, len, static_cast<int>(packet->capacity()), &len);
#else
if (!IsExternalAuthActive()) {
res = ProtectRtp(data, len, static_cast<int>(packet->capacity()), &len);
} else {
updated_options.packet_time_params.rtp_sendtime_extension_id =
rtp_abs_sendtime_extn_id_;
res = ProtectRtp(data, len, static_cast<int>(packet->capacity()), &len,
&updated_options.packet_time_params.srtp_packet_index);
// If protection succeeds, let's get auth params from srtp.
if (res) {
uint8_t* auth_key = NULL;
int key_len;
res = GetRtpAuthParams(
&auth_key, &key_len,
&updated_options.packet_time_params.srtp_auth_tag_len);
#else
if (!IsExternalAuthActive()) {
res = ProtectRtp(data, len, static_cast<int>(packet->capacity()), &len);
} else {
updated_options.packet_time_params.rtp_sendtime_extension_id =
rtp_abs_sendtime_extn_id_;
res = ProtectRtp(data, len, static_cast<int>(packet->capacity()), &len,
&updated_options.packet_time_params.srtp_packet_index);
// If protection succeeds, let's get auth params from srtp.
if (res) {
updated_options.packet_time_params.srtp_auth_key.resize(key_len);
updated_options.packet_time_params.srtp_auth_key.assign(
auth_key, auth_key + key_len);
uint8_t* auth_key = NULL;
int key_len;
res = GetRtpAuthParams(
&auth_key, &key_len,
&updated_options.packet_time_params.srtp_auth_tag_len);
if (res) {
updated_options.packet_time_params.srtp_auth_key.resize(key_len);
updated_options.packet_time_params.srtp_auth_key.assign(
auth_key, auth_key + key_len);
}
}
}
}
#endif
if (!res) {
int seq_num = -1;
uint32_t ssrc = 0;
cricket::GetRtpSeqNum(data, len, &seq_num);
cricket::GetRtpSsrc(data, len, &ssrc);
RTC_LOG(LS_ERROR) << "Failed to protect RTP packet: size=" << len
<< ", seqnum=" << seq_num << ", SSRC=" << ssrc;
return false;
if (!res) {
int seq_num = -1;
uint32_t ssrc = 0;
cricket::GetRtpSeqNum(data, len, &seq_num);
cricket::GetRtpSsrc(data, len, &ssrc);
RTC_LOG(LS_ERROR) << "Failed to protect RTP packet: size=" << len
<< ", seqnum=" << seq_num << ", SSRC=" << ssrc;
return false;
}
} else {
res = ProtectRtcp(data, len, static_cast<int>(packet->capacity()), &len);
if (!res) {
int type = -1;
cricket::GetRtcpType(data, len, &type);
RTC_LOG(LS_ERROR) << "Failed to protect RTCP packet: size=" << len
<< ", type=" << type;
return false;
}
}
// Update the length of the packet now that we've added the auth tag.
packet->SetSize(len);
return SendPacket(/*rtcp=*/false, packet, updated_options, flags);
return rtcp ? rtp_transport_->SendRtcpPacket(packet, updated_options, flags)
: rtp_transport_->SendRtpPacket(packet, updated_options, flags);
}
bool SrtpTransport::SendRtcpPacket(rtc::CopyOnWriteBuffer* packet,
const rtc::PacketOptions& options,
int flags) {
if (!IsActive()) {
RTC_LOG(LS_ERROR)
<< "Failed to send the packet because SRTP transport is inactive.";
return false;
}
TRACE_EVENT0("webrtc", "SRTP Encode");
uint8_t* data = packet->data();
int len = static_cast<int>(packet->size());
if (!ProtectRtcp(data, len, static_cast<int>(packet->capacity()), &len)) {
int type = -1;
cricket::GetRtcpType(data, len, &type);
RTC_LOG(LS_ERROR) << "Failed to protect RTCP packet: size=" << len
<< ", type=" << type;
return false;
}
// Update the length of the packet now that we've added the auth tag.
packet->SetSize(len);
return SendPacket(/*rtcp=*/true, packet, options, flags);
}
void SrtpTransport::OnRtpPacketReceived(rtc::CopyOnWriteBuffer* packet,
const rtc::PacketTime& packet_time) {
void SrtpTransport::OnPacketReceived(bool rtcp,
rtc::CopyOnWriteBuffer* packet,
const rtc::PacketTime& packet_time) {
if (!IsActive()) {
RTC_LOG(LS_WARNING)
<< "Inactive SRTP transport received an RTP packet. Drop it.";
<< "Inactive SRTP transport received a packet. Drop it.";
return;
}
TRACE_EVENT0("webrtc", "SRTP Decode");
char* data = packet->data<char>();
int len = static_cast<int>(packet->size());
if (!UnprotectRtp(data, len, &len)) {
int seq_num = -1;
uint32_t ssrc = 0;
cricket::GetRtpSeqNum(data, len, &seq_num);
cricket::GetRtpSsrc(data, len, &ssrc);
RTC_LOG(LS_ERROR) << "Failed to unprotect RTP packet: size=" << len
<< ", seqnum=" << seq_num << ", SSRC=" << ssrc;
return;
bool res;
if (!rtcp) {
res = UnprotectRtp(data, len, &len);
if (!res) {
int seq_num = -1;
uint32_t ssrc = 0;
cricket::GetRtpSeqNum(data, len, &seq_num);
cricket::GetRtpSsrc(data, len, &ssrc);
RTC_LOG(LS_ERROR) << "Failed to unprotect RTP packet: size=" << len
<< ", seqnum=" << seq_num << ", SSRC=" << ssrc;
return;
}
} else {
res = UnprotectRtcp(data, len, &len);
if (!res) {
int type = -1;
cricket::GetRtcpType(data, len, &type);
RTC_LOG(LS_ERROR) << "Failed to unprotect RTCP packet: size=" << len
<< ", type=" << type;
return;
}
}
packet->SetSize(len);
DemuxPacket(packet, packet_time);
}
void SrtpTransport::OnRtcpPacketReceived(rtc::CopyOnWriteBuffer* packet,
const rtc::PacketTime& packet_time) {
if (!IsActive()) {
RTC_LOG(LS_WARNING)
<< "Inactive SRTP transport received an RTCP packet. Drop it.";
return;
}
TRACE_EVENT0("webrtc", "SRTP Decode");
char* data = packet->data<char>();
int len = static_cast<int>(packet->size());
if (!UnprotectRtcp(data, len, &len)) {
int type = -1;
cricket::GetRtcpType(data, len, &type);
RTC_LOG(LS_ERROR) << "Failed to unprotect RTCP packet: size=" << len
<< ", type=" << type;
return;
}
packet->SetSize(len);
SignalRtcpPacketReceived(packet, packet_time);
SignalPacketReceived(rtcp, packet, packet_time);
}
void SrtpTransport::OnNetworkRouteChanged(
@ -392,6 +414,7 @@ void SrtpTransport::SetMetricsObserver(
if (recv_rtcp_session_) {
recv_rtcp_session_->SetMetricsObserver(metrics_observer_);
}
rtp_transport_->SetMetricsObserver(metrics_observer);
}
} // namespace webrtc

View File

@ -17,20 +17,21 @@
#include <vector>
#include "p2p/base/icetransportinternal.h"
#include "pc/rtptransport.h"
#include "pc/rtptransportinternaladapter.h"
#include "pc/srtpfilter.h"
#include "pc/srtpsession.h"
#include "rtc_base/checks.h"
namespace webrtc {
// This subclass of the RtpTransport is used for SRTP which is reponsible for
// protecting/unprotecting the packets. It provides interfaces to set the crypto
// parameters for the SrtpSession underneath.
class SrtpTransport : public RtpTransport {
// This class will eventually be a wrapper around RtpTransportInternal
// that protects and unprotects sent and received RTP packets.
class SrtpTransport : public RtpTransportInternalAdapter {
public:
explicit SrtpTransport(bool rtcp_mux_enabled);
explicit SrtpTransport(std::unique_ptr<RtpTransportInternal> rtp_transport);
bool SendRtpPacket(rtc::CopyOnWriteBuffer* packet,
const rtc::PacketOptions& options,
int flags) override;
@ -39,16 +40,6 @@ class SrtpTransport : public RtpTransport {
const rtc::PacketOptions& options,
int flags) override;
// SrtpTransportInterface override.
// TODO(zhihuang): Implement these methods and replace the RtpTransportAdapter
// object.
RTCError SetSrtpSendKey(const cricket::CryptoParams& params) override {
return RTCError::OK();
}
RTCError SetSrtpReceiveKey(const cricket::CryptoParams& params) override {
return RTCError::OK();
}
// The transport becomes active if the send_session_ and recv_session_ are
// created.
bool IsActive() const;
@ -114,12 +105,22 @@ class SrtpTransport : public RtpTransport {
void ConnectToRtpTransport();
void CreateSrtpSessions();
void OnRtpPacketReceived(rtc::CopyOnWriteBuffer* packet,
const rtc::PacketTime& packet_time) override;
void OnRtcpPacketReceived(rtc::CopyOnWriteBuffer* packet,
const rtc::PacketTime& packet_time) override;
void OnNetworkRouteChanged(
rtc::Optional<rtc::NetworkRoute> network_route) override;
bool SendPacket(bool rtcp,
rtc::CopyOnWriteBuffer* packet,
const rtc::PacketOptions& options,
int flags);
void OnPacketReceived(bool rtcp,
rtc::CopyOnWriteBuffer* packet,
const rtc::PacketTime& packet_time);
void OnReadyToSend(bool ready) { SignalReadyToSend(ready); }
void OnNetworkRouteChanged(rtc::Optional<rtc::NetworkRoute> network_route);
void OnWritableState(bool writable) { SignalWritableState(writable); }
void OnSentPacket(const rtc::SentPacket& sent_packet) {
SignalSentPacket(sent_packet);
}
bool ProtectRtp(void* data, int in_len, int max_len, int* out_len);
@ -138,6 +139,7 @@ class SrtpTransport : public RtpTransport {
bool UnprotectRtcp(void* data, int in_len, int* out_len);
const std::string content_name_;
std::unique_ptr<RtpTransportInternal> rtp_transport_;
std::unique_ptr<cricket::SrtpSession> send_session_;
std::unique_ptr<cricket::SrtpSession> recv_session_;

View File

@ -42,6 +42,8 @@ class SrtpTransportTest : public testing::Test, public sigslot::has_slots<> {
protected:
SrtpTransportTest() {
bool rtcp_mux_enabled = true;
auto rtp_transport1 = rtc::MakeUnique<RtpTransport>(rtcp_mux_enabled);
auto rtp_transport2 = rtc::MakeUnique<RtpTransport>(rtcp_mux_enabled);
rtp_packet_transport1_ =
rtc::MakeUnique<rtc::FakePacketTransport>("fake_packet_transport1");
@ -52,32 +54,38 @@ class SrtpTransportTest : public testing::Test, public sigslot::has_slots<> {
rtp_packet_transport1_->SetDestination(rtp_packet_transport2_.get(),
asymmetric);
srtp_transport1_ = rtc::MakeUnique<SrtpTransport>(rtcp_mux_enabled);
srtp_transport2_ = rtc::MakeUnique<SrtpTransport>(rtcp_mux_enabled);
rtp_transport1->SetRtpPacketTransport(rtp_packet_transport1_.get());
rtp_transport2->SetRtpPacketTransport(rtp_packet_transport2_.get());
srtp_transport1_->SetRtpPacketTransport(rtp_packet_transport1_.get());
srtp_transport2_->SetRtpPacketTransport(rtp_packet_transport2_.get());
// Add payload type for RTP packet and RTCP packet.
rtp_transport1->AddHandledPayloadType(0x00);
rtp_transport2->AddHandledPayloadType(0x00);
rtp_transport1->AddHandledPayloadType(0xc9);
rtp_transport2->AddHandledPayloadType(0xc9);
srtp_transport1_->SignalRtcpPacketReceived.connect(
&rtp_sink1_, &TransportObserver::OnRtcpPacketReceived);
srtp_transport2_->SignalRtcpPacketReceived.connect(
&rtp_sink2_, &TransportObserver::OnRtcpPacketReceived);
srtp_transport1_ =
rtc::MakeUnique<SrtpTransport>(std::move(rtp_transport1));
srtp_transport2_ =
rtc::MakeUnique<SrtpTransport>(std::move(rtp_transport2));
RtpDemuxerCriteria demuxer_criteria;
// 0x00 is the payload type used in kPcmuFrame.
demuxer_criteria.payload_types = {0x00};
srtp_transport1_->RegisterRtpDemuxerSink(demuxer_criteria, &rtp_sink1_);
srtp_transport2_->RegisterRtpDemuxerSink(demuxer_criteria, &rtp_sink2_);
srtp_transport1_->SignalPacketReceived.connect(
this, &SrtpTransportTest::OnPacketReceived1);
srtp_transport2_->SignalPacketReceived.connect(
this, &SrtpTransportTest::OnPacketReceived2);
}
~SrtpTransportTest() {
if (srtp_transport1_) {
srtp_transport1_->UnregisterRtpDemuxerSink(&rtp_sink1_);
}
if (srtp_transport2_) {
srtp_transport2_->UnregisterRtpDemuxerSink(&rtp_sink2_);
}
void OnPacketReceived1(bool rtcp,
rtc::CopyOnWriteBuffer* packet,
const rtc::PacketTime& packet_time) {
RTC_LOG(LS_INFO) << "SrtpTransport1 Received a packet.";
last_recv_packet1_ = *packet;
}
void OnPacketReceived2(bool rtcp,
rtc::CopyOnWriteBuffer* packet,
const rtc::PacketTime& packet_time) {
RTC_LOG(LS_INFO) << "SrtpTransport2 Received a packet.";
last_recv_packet2_ = *packet;
}
// With external auth enabled, SRTP doesn't write the auth tag and
@ -134,9 +142,9 @@ class SrtpTransportTest : public testing::Test, public sigslot::has_slots<> {
if (srtp_transport1_->IsExternalAuthActive()) {
TestRtpAuthParams(srtp_transport1_.get(), cipher_suite_name);
} else {
ASSERT_TRUE(rtp_sink2_.last_recv_rtp_packet().data());
EXPECT_EQ(0, memcmp(rtp_sink2_.last_recv_rtp_packet().data(),
original_rtp_data, rtp_len));
ASSERT_TRUE(last_recv_packet2_.data());
EXPECT_EQ(0,
memcmp(last_recv_packet2_.data(), original_rtp_data, rtp_len));
// Get the encrypted packet from underneath packet transport and verify
// the data is actually encrypted.
auto fake_rtp_packet_transport = static_cast<rtc::FakePacketTransport*>(
@ -151,9 +159,9 @@ class SrtpTransportTest : public testing::Test, public sigslot::has_slots<> {
if (srtp_transport2_->IsExternalAuthActive()) {
TestRtpAuthParams(srtp_transport2_.get(), cipher_suite_name);
} else {
ASSERT_TRUE(rtp_sink1_.last_recv_rtp_packet().data());
EXPECT_EQ(0, memcmp(rtp_sink1_.last_recv_rtp_packet().data(),
original_rtp_data, rtp_len));
ASSERT_TRUE(last_recv_packet1_.data());
EXPECT_EQ(0,
memcmp(last_recv_packet1_.data(), original_rtp_data, rtp_len));
auto fake_rtp_packet_transport = static_cast<rtc::FakePacketTransport*>(
srtp_transport2_->rtp_packet_transport());
EXPECT_NE(0, memcmp(fake_rtp_packet_transport->last_sent_packet()->data(),
@ -162,12 +170,12 @@ class SrtpTransportTest : public testing::Test, public sigslot::has_slots<> {
}
void TestSendRecvRtcpPacket(const std::string& cipher_suite_name) {
size_t rtcp_len = sizeof(::kRtcpReport);
size_t rtcp_len = sizeof(kRtcpReport);
size_t packet_size =
rtcp_len + 4 + rtc::rtcp_auth_tag_len(cipher_suite_name);
rtc::Buffer rtcp_packet_buffer(packet_size);
char* rtcp_packet_data = rtcp_packet_buffer.data<char>();
memcpy(rtcp_packet_data, ::kRtcpReport, rtcp_len);
memcpy(rtcp_packet_data, kRtcpReport, rtcp_len);
rtc::CopyOnWriteBuffer rtcp_packet1to2(rtcp_packet_data, rtcp_len,
packet_size);
@ -179,9 +187,8 @@ class SrtpTransportTest : public testing::Test, public sigslot::has_slots<> {
// that the packet can be successfully received and decrypted.
ASSERT_TRUE(srtp_transport1_->SendRtcpPacket(&rtcp_packet1to2, options,
cricket::PF_SRTP_BYPASS));
ASSERT_TRUE(rtp_sink2_.last_recv_rtcp_packet().data());
EXPECT_EQ(0, memcmp(rtp_sink2_.last_recv_rtcp_packet().data(),
rtcp_packet_data, rtcp_len));
ASSERT_TRUE(last_recv_packet2_.data());
EXPECT_EQ(0, memcmp(last_recv_packet2_.data(), rtcp_packet_data, rtcp_len));
// Get the encrypted packet from underneath packet transport and verify the
// data is actually encrypted.
auto fake_rtp_packet_transport = static_cast<rtc::FakePacketTransport*>(
@ -192,9 +199,8 @@ class SrtpTransportTest : public testing::Test, public sigslot::has_slots<> {
// Do the same thing in the opposite direction;
ASSERT_TRUE(srtp_transport2_->SendRtcpPacket(&rtcp_packet2to1, options,
cricket::PF_SRTP_BYPASS));
ASSERT_TRUE(rtp_sink1_.last_recv_rtcp_packet().data());
EXPECT_EQ(0, memcmp(rtp_sink1_.last_recv_rtcp_packet().data(),
rtcp_packet_data, rtcp_len));
ASSERT_TRUE(last_recv_packet1_.data());
EXPECT_EQ(0, memcmp(last_recv_packet1_.data(), rtcp_packet_data, rtcp_len));
fake_rtp_packet_transport = static_cast<rtc::FakePacketTransport*>(
srtp_transport2_->rtp_packet_transport());
EXPECT_NE(0, memcmp(fake_rtp_packet_transport->last_sent_packet()->data(),
@ -261,9 +267,8 @@ class SrtpTransportTest : public testing::Test, public sigslot::has_slots<> {
// that the packet can be successfully received and decrypted.
ASSERT_TRUE(srtp_transport1_->SendRtpPacket(&rtp_packet1to2, options,
cricket::PF_SRTP_BYPASS));
ASSERT_TRUE(rtp_sink2_.last_recv_rtp_packet().data());
EXPECT_EQ(0, memcmp(rtp_sink2_.last_recv_rtp_packet().data(),
original_rtp_data, rtp_len));
ASSERT_TRUE(last_recv_packet2_.data());
EXPECT_EQ(0, memcmp(last_recv_packet2_.data(), original_rtp_data, rtp_len));
// Get the encrypted packet from underneath packet transport and verify the
// data and header extension are actually encrypted.
auto fake_rtp_packet_transport = static_cast<rtc::FakePacketTransport*>(
@ -279,9 +284,8 @@ class SrtpTransportTest : public testing::Test, public sigslot::has_slots<> {
// Do the same thing in the opposite direction;
ASSERT_TRUE(srtp_transport2_->SendRtpPacket(&rtp_packet2to1, options,
cricket::PF_SRTP_BYPASS));
ASSERT_TRUE(rtp_sink1_.last_recv_rtp_packet().data());
EXPECT_EQ(0, memcmp(rtp_sink1_.last_recv_rtp_packet().data(),
original_rtp_data, rtp_len));
ASSERT_TRUE(last_recv_packet1_.data());
EXPECT_EQ(0, memcmp(last_recv_packet1_.data(), original_rtp_data, rtp_len));
fake_rtp_packet_transport = static_cast<rtc::FakePacketTransport*>(
srtp_transport2_->rtp_packet_transport());
EXPECT_NE(0, memcmp(fake_rtp_packet_transport->last_sent_packet()->data(),
@ -324,9 +328,8 @@ class SrtpTransportTest : public testing::Test, public sigslot::has_slots<> {
std::unique_ptr<rtc::FakePacketTransport> rtp_packet_transport1_;
std::unique_ptr<rtc::FakePacketTransport> rtp_packet_transport2_;
TransportObserver rtp_sink1_;
TransportObserver rtp_sink2_;
rtc::CopyOnWriteBuffer last_recv_packet1_;
rtc::CopyOnWriteBuffer last_recv_packet2_;
int sequence_number_ = 0;
};

View File

@ -458,12 +458,16 @@ webrtc::DtlsSrtpTransport* TransportController::CreateDtlsSrtpTransport(
return existing_rtp_transport->dtls_srtp_transport;
}
auto new_dtls_srtp_transport =
rtc::MakeUnique<webrtc::DtlsSrtpTransport>(rtcp_mux_enabled);
auto new_srtp_transport =
rtc::MakeUnique<webrtc::SrtpTransport>(rtcp_mux_enabled);
#if defined(ENABLE_EXTERNAL_AUTH)
new_dtls_srtp_transport->EnableExternalAuth();
new_srtp_transport->EnableExternalAuth();
#endif
auto new_dtls_srtp_transport =
rtc::MakeUnique<webrtc::DtlsSrtpTransport>(std::move(new_srtp_transport));
auto rtp_dtls_transport = CreateDtlsTransport_n(
transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
auto rtcp_dtls_transport =