* Copyright 2017 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/dtls_srtp_transport.h"
#include <string.h>
#include <cstdint>
#include <memory>
#include "call/rtp_demuxer.h"
#include "media/base/fake_rtp.h"
#include "p2p/base/dtls_transport_internal.h"
#include "p2p/base/fake_dtls_transport.h"
#include "p2p/base/fake_ice_transport.h"
#include "p2p/base/p2p_constants.h"
#include "pc/rtp_transport.h"
#include "pc/test/rtp_transport_test_util.h"
#include "rtc_base/async_packet_socket.h"
#include "rtc_base/byte_order.h"
#include "rtc_base/containers/flat_set.h"
#include "rtc_base/copy_on_write_buffer.h"
#include "rtc_base/rtc_certificate.h"
#include "rtc_base/ssl_identity.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
#include "test/gtest.h"
#include "test/scoped_key_value_config.h"
using cricket::FakeDtlsTransport;
using cricket::FakeIceTransport;
using webrtc::DtlsSrtpTransport;
using webrtc::RtpTransport;
using webrtc::SrtpTransport;
const int kRtpAuthTagLen = 10;
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 dtls_srtp_transport =
std::make_unique<DtlsSrtpTransport>(rtcp_mux_enabled, field_trials_);
dtls_srtp_transport->SetDtlsTransports(rtp_dtls, rtcp_dtls);
return dtls_srtp_transport;
}
void MakeDtlsSrtpTransports(FakeDtlsTransport* rtp_dtls1,
FakeDtlsTransport* rtcp_dtls1,
FakeDtlsTransport* rtp_dtls2,
FakeDtlsTransport* rtcp_dtls2,
bool rtcp_mux_enabled) {
dtls_srtp_transport1_ =
MakeDtlsSrtpTransport(rtp_dtls1, rtcp_dtls1, rtcp_mux_enabled);
dtls_srtp_transport2_ =
MakeDtlsSrtpTransport(rtp_dtls2, rtcp_dtls2, rtcp_mux_enabled);
dtls_srtp_transport1_->SubscribeRtcpPacketReceived(
&transport_observer1_,
[this](rtc::CopyOnWriteBuffer* buffer, int64_t packet_time_ms) {
transport_observer1_.OnRtcpPacketReceived(buffer, packet_time_ms);
});
dtls_srtp_transport1_->SubscribeReadyToSend(
&transport_observer1_,
[this](bool ready) { transport_observer1_.OnReadyToSend(ready); });
dtls_srtp_transport2_->SubscribeRtcpPacketReceived(
&transport_observer2_,
[this](rtc::CopyOnWriteBuffer* buffer, int64_t packet_time_ms) {
transport_observer2_.OnRtcpPacketReceived(buffer, packet_time_ms);
});
dtls_srtp_transport2_->SubscribeReadyToSend(
&transport_observer2_,
[this](bool ready) { transport_observer2_.OnReadyToSend(ready); });
webrtc::RtpDemuxerCriteria demuxer_criteria;
demuxer_criteria.payload_types() = {0x00};
dtls_srtp_transport1_->RegisterRtpDemuxerSink(demuxer_criteria,
&transport_observer1_);
dtls_srtp_transport2_->RegisterRtpDemuxerSink(demuxer_criteria,
&transport_observer2_);
}
void CompleteDtlsHandshake(FakeDtlsTransport* fake_dtls1,
FakeDtlsTransport* fake_dtls2) {
auto cert1 = rtc::RTCCertificate::Create(
rtc::SSLIdentity::Create("session1", rtc::KT_DEFAULT));
fake_dtls1->SetLocalCertificate(cert1);
auto cert2 = rtc::RTCCertificate::Create(
rtc::SSLIdentity::Create("session1", rtc::KT_DEFAULT));
fake_dtls2->SetLocalCertificate(cert2);
fake_dtls1->SetDestination(fake_dtls2);
}
void SendRecvRtpPackets() {
ASSERT_TRUE(dtls_srtp_transport1_);
ASSERT_TRUE(dtls_srtp_transport2_);
ASSERT_TRUE(dtls_srtp_transport1_->IsSrtpActive());
ASSERT_TRUE(dtls_srtp_transport2_->IsSrtpActive());
size_t rtp_len = sizeof(kPcmuFrame);
size_t packet_size = rtp_len + kRtpAuthTagLen;
rtc::Buffer rtp_packet_buffer(packet_size);
char* rtp_packet_data = rtp_packet_buffer.data<char>();
memcpy(rtp_packet_data, kPcmuFrame, rtp_len);
rtc::SetBE16(reinterpret_cast<uint8_t*>(rtp_packet_data) + 2,
++sequence_number_);
rtc::CopyOnWriteBuffer rtp_packet1to2(rtp_packet_data, rtp_len,
packet_size);
rtc::CopyOnWriteBuffer rtp_packet2to1(rtp_packet_data, rtp_len,
packet_size);
rtc::PacketOptions options;
int prev_received_packets = transport_observer2_.rtp_count();
ASSERT_TRUE(dtls_srtp_transport1_->SendRtpPacket(&rtp_packet1to2, options,
cricket::PF_SRTP_BYPASS));
ASSERT_TRUE(transport_observer2_.last_recv_rtp_packet().data());
EXPECT_EQ(0, memcmp(transport_observer2_.last_recv_rtp_packet().data(),
kPcmuFrame, rtp_len));
EXPECT_EQ(prev_received_packets + 1, transport_observer2_.rtp_count());
prev_received_packets = transport_observer1_.rtp_count();
ASSERT_TRUE(dtls_srtp_transport2_->SendRtpPacket(&rtp_packet2to1, options,
cricket::PF_SRTP_BYPASS));
ASSERT_TRUE(transport_observer1_.last_recv_rtp_packet().data());
EXPECT_EQ(0, memcmp(transport_observer1_.last_recv_rtp_packet().data(),
kPcmuFrame, rtp_len));
EXPECT_EQ(prev_received_packets + 1, transport_observer1_.rtp_count());
}
void SendRecvRtcpPackets() {
size_t rtcp_len = sizeof(kRtcpReport);
size_t packet_size = rtcp_len + 4 + kRtpAuthTagLen;
rtc::Buffer rtcp_packet_buffer(packet_size);
rtc::CopyOnWriteBuffer rtcp_packet1to2(kRtcpReport, rtcp_len, packet_size);
rtc::CopyOnWriteBuffer rtcp_packet2to1(kRtcpReport, rtcp_len, packet_size);
rtc::PacketOptions options;
int prev_received_packets = transport_observer2_.rtcp_count();
ASSERT_TRUE(dtls_srtp_transport1_->SendRtcpPacket(&rtcp_packet1to2, options,
cricket::PF_SRTP_BYPASS));
ASSERT_TRUE(transport_observer2_.last_recv_rtcp_packet().data());
EXPECT_EQ(0, memcmp(transport_observer2_.last_recv_rtcp_packet().data(),
kRtcpReport, rtcp_len));
EXPECT_EQ(prev_received_packets + 1, transport_observer2_.rtcp_count());
prev_received_packets = transport_observer1_.rtcp_count();
ASSERT_TRUE(dtls_srtp_transport2_->SendRtcpPacket(&rtcp_packet2to1, options,
cricket::PF_SRTP_BYPASS));
ASSERT_TRUE(transport_observer1_.last_recv_rtcp_packet().data());
EXPECT_EQ(0, memcmp(transport_observer1_.last_recv_rtcp_packet().data(),
kRtcpReport, rtcp_len));
EXPECT_EQ(prev_received_packets + 1, transport_observer1_.rtcp_count());
}
void SendRecvRtpPacketsWithHeaderExtension(
const std::vector<int>& encrypted_header_ids) {
ASSERT_TRUE(dtls_srtp_transport1_);
ASSERT_TRUE(dtls_srtp_transport2_);
ASSERT_TRUE(dtls_srtp_transport1_->IsSrtpActive());
ASSERT_TRUE(dtls_srtp_transport2_->IsSrtpActive());
size_t rtp_len = sizeof(kPcmuFrameWithExtensions);
size_t packet_size = rtp_len + kRtpAuthTagLen;
rtc::Buffer rtp_packet_buffer(packet_size);
char* rtp_packet_data = rtp_packet_buffer.data<char>();
memcpy(rtp_packet_data, kPcmuFrameWithExtensions, rtp_len);
rtc::SetBE16(reinterpret_cast<uint8_t*>(rtp_packet_data) + 2,
++sequence_number_);
rtc::CopyOnWriteBuffer rtp_packet1to2(rtp_packet_data, rtp_len,
packet_size);
rtc::CopyOnWriteBuffer rtp_packet2to1(rtp_packet_data, rtp_len,
packet_size);
char original_rtp_data[sizeof(kPcmuFrameWithExtensions)];
memcpy(original_rtp_data, rtp_packet_data, rtp_len);
rtc::PacketOptions options;
ASSERT_TRUE(dtls_srtp_transport1_->SendRtpPacket(&rtp_packet1to2, options,
cricket::PF_SRTP_BYPASS));
ASSERT_TRUE(transport_observer2_.last_recv_rtp_packet().data());
EXPECT_EQ(0, memcmp(transport_observer2_.last_recv_rtp_packet().data(),
original_rtp_data, rtp_len));
auto fake_dtls_transport = static_cast<FakeDtlsTransport*>(
dtls_srtp_transport1_->rtp_packet_transport());
auto fake_ice_transport =
static_cast<FakeIceTransport*>(fake_dtls_transport->ice_transport());
EXPECT_NE(0, memcmp(fake_ice_transport->last_sent_packet().data(),
original_rtp_data, rtp_len));
CompareHeaderExtensions(reinterpret_cast<const char*>(
fake_ice_transport->last_sent_packet().data()),
fake_ice_transport->last_sent_packet().size(),
original_rtp_data, rtp_len, encrypted_header_ids,
false);
ASSERT_TRUE(dtls_srtp_transport2_->SendRtpPacket(&rtp_packet2to1, options,
cricket::PF_SRTP_BYPASS));
ASSERT_TRUE(transport_observer1_.last_recv_rtp_packet().data());
EXPECT_EQ(0, memcmp(transport_observer1_.last_recv_rtp_packet().data(),
original_rtp_data, rtp_len));
fake_dtls_transport = static_cast<FakeDtlsTransport*>(
dtls_srtp_transport2_->rtp_packet_transport());
fake_ice_transport =
static_cast<FakeIceTransport*>(fake_dtls_transport->ice_transport());
EXPECT_NE(0, memcmp(fake_ice_transport->last_sent_packet().data(),
original_rtp_data, rtp_len));
CompareHeaderExtensions(reinterpret_cast<const char*>(
fake_ice_transport->last_sent_packet().data()),
fake_ice_transport->last_sent_packet().size(),
original_rtp_data, rtp_len, encrypted_header_ids,
false);
}
void SendRecvPackets() {
SendRecvRtpPackets();
SendRecvRtcpPackets();
}
rtc::AutoThread main_thread_;
std::unique_ptr<DtlsSrtpTransport> dtls_srtp_transport1_;
std::unique_ptr<DtlsSrtpTransport> dtls_srtp_transport2_;
webrtc::TransportObserver transport_observer1_;
webrtc::TransportObserver transport_observer2_;
int sequence_number_ = 0;
webrtc::test::ScopedKeyValueConfig field_trials_;
};
TEST_F(DtlsSrtpTransportTest, SetTransportsAfterHandshakeCompleteWithRtcpMux) {
auto rtp_dtls1 = std::make_unique<FakeDtlsTransport>(
"video", cricket::ICE_CANDIDATE_COMPONENT_RTP);
auto rtp_dtls2 = std::make_unique<FakeDtlsTransport>(
"video", cricket::ICE_CANDIDATE_COMPONENT_RTP);
MakeDtlsSrtpTransports(rtp_dtls1.get(), nullptr, rtp_dtls2.get(), nullptr,
true);
auto rtp_dtls3 = std::make_unique<FakeDtlsTransport>(
"audio", cricket::ICE_CANDIDATE_COMPONENT_RTP);
auto rtp_dtls4 = std::make_unique<FakeDtlsTransport>(
"audio", cricket::ICE_CANDIDATE_COMPONENT_RTP);
CompleteDtlsHandshake(rtp_dtls3.get(), rtp_dtls4.get());
dtls_srtp_transport1_->SetDtlsTransports(rtp_dtls3.get(), nullptr);
dtls_srtp_transport2_->SetDtlsTransports(rtp_dtls4.get(), nullptr);
SendRecvPackets();
}
TEST_F(DtlsSrtpTransportTest,
SetTransportsAfterHandshakeCompleteWithoutRtcpMux) {
auto rtp_dtls1 = std::make_unique<FakeDtlsTransport>(
"video", cricket::ICE_CANDIDATE_COMPONENT_RTP);
auto rtcp_dtls1 = std::make_unique<FakeDtlsTransport>(
"video", cricket::ICE_CANDIDATE_COMPONENT_RTCP);
auto rtp_dtls2 = std::make_unique<FakeDtlsTransport>(
"video", cricket::ICE_CANDIDATE_COMPONENT_RTP);
auto rtcp_dtls2 = std::make_unique<FakeDtlsTransport>(
"video", cricket::ICE_CANDIDATE_COMPONENT_RTCP);
MakeDtlsSrtpTransports(rtp_dtls1.get(), rtcp_dtls1.get(), rtp_dtls2.get(),
rtcp_dtls2.get(), false);
auto rtp_dtls3 = std::make_unique<FakeDtlsTransport>(
"audio", cricket::ICE_CANDIDATE_COMPONENT_RTP);
auto rtcp_dtls3 = std::make_unique<FakeDtlsTransport>(
"audio", cricket::ICE_CANDIDATE_COMPONENT_RTCP);
auto rtp_dtls4 = std::make_unique<FakeDtlsTransport>(
"audio", cricket::ICE_CANDIDATE_COMPONENT_RTP);
auto rtcp_dtls4 = std::make_unique<FakeDtlsTransport>(
"audio", cricket::ICE_CANDIDATE_COMPONENT_RTCP);
CompleteDtlsHandshake(rtp_dtls3.get(), rtp_dtls4.get());
CompleteDtlsHandshake(rtcp_dtls3.get(), rtcp_dtls4.get());
dtls_srtp_transport1_->SetDtlsTransports(rtp_dtls3.get(), rtcp_dtls3.get());
dtls_srtp_transport2_->SetDtlsTransports(rtp_dtls4.get(), rtcp_dtls4.get());
SendRecvPackets();
}
TEST_F(DtlsSrtpTransportTest, SetTransportsBeforeHandshakeCompleteWithRtcpMux) {
auto rtp_dtls1 = std::make_unique<FakeDtlsTransport>(
"audio", cricket::ICE_CANDIDATE_COMPONENT_RTP);
auto rtcp_dtls1 = std::make_unique<FakeDtlsTransport>(
"audio", cricket::ICE_CANDIDATE_COMPONENT_RTCP);
auto rtp_dtls2 = std::make_unique<FakeDtlsTransport>(
"audio", cricket::ICE_CANDIDATE_COMPONENT_RTP);
auto rtcp_dtls2 = std::make_unique<FakeDtlsTransport>(
"audio", cricket::ICE_CANDIDATE_COMPONENT_RTCP);
MakeDtlsSrtpTransports(rtp_dtls1.get(), rtcp_dtls1.get(), rtp_dtls2.get(),
rtcp_dtls2.get(),
false);
dtls_srtp_transport1_->SetRtcpMuxEnabled(true);
dtls_srtp_transport2_->SetRtcpMuxEnabled(true);
CompleteDtlsHandshake(rtp_dtls1.get(), rtp_dtls2.get());
SendRecvPackets();
}
TEST_F(DtlsSrtpTransportTest,
SetTransportsBeforeHandshakeCompleteWithoutRtcpMux) {
auto rtp_dtls1 = std::make_unique<FakeDtlsTransport>(
"audio", cricket::ICE_CANDIDATE_COMPONENT_RTP);
auto rtcp_dtls1 = std::make_unique<FakeDtlsTransport>(
"audio", cricket::ICE_CANDIDATE_COMPONENT_RTCP);
auto rtp_dtls2 = std::make_unique<FakeDtlsTransport>(
"audio", cricket::ICE_CANDIDATE_COMPONENT_RTP);
auto rtcp_dtls2 = std::make_unique<FakeDtlsTransport>(
"audio", cricket::ICE_CANDIDATE_COMPONENT_RTCP);
MakeDtlsSrtpTransports(rtp_dtls1.get(), rtcp_dtls1.get(), rtp_dtls2.get(),
rtcp_dtls2.get(), false);
CompleteDtlsHandshake(rtp_dtls1.get(), rtp_dtls2.get());
EXPECT_FALSE(dtls_srtp_transport1_->IsSrtpActive());
EXPECT_FALSE(dtls_srtp_transport2_->IsSrtpActive());
CompleteDtlsHandshake(rtcp_dtls1.get(), rtcp_dtls2.get());
SendRecvPackets();
}
TEST_F(DtlsSrtpTransportTest, DtlsSrtpResetAfterDtlsTransportChange) {
auto rtp_dtls1 = std::make_unique<FakeDtlsTransport>(
"audio", cricket::ICE_CANDIDATE_COMPONENT_RTP);
auto rtp_dtls2 = std::make_unique<FakeDtlsTransport>(
"audio", cricket::ICE_CANDIDATE_COMPONENT_RTP);
MakeDtlsSrtpTransports(rtp_dtls1.get(), nullptr, rtp_dtls2.get(), nullptr,
true);
CompleteDtlsHandshake(rtp_dtls1.get(), rtp_dtls2.get());
EXPECT_TRUE(dtls_srtp_transport1_->IsSrtpActive());
EXPECT_TRUE(dtls_srtp_transport2_->IsSrtpActive());
auto rtp_dtls3 = std::make_unique<FakeDtlsTransport>(
"audio", cricket::ICE_CANDIDATE_COMPONENT_RTP);
auto rtp_dtls4 = std::make_unique<FakeDtlsTransport>(
"audio", cricket::ICE_CANDIDATE_COMPONENT_RTP);
dtls_srtp_transport1_->SetDtlsTransports(rtp_dtls3.get(), nullptr);
dtls_srtp_transport2_->SetDtlsTransports(rtp_dtls4.get(), nullptr);
EXPECT_FALSE(dtls_srtp_transport1_->IsSrtpActive());
EXPECT_FALSE(dtls_srtp_transport2_->IsSrtpActive());
CompleteDtlsHandshake(rtp_dtls3.get(), rtp_dtls4.get());
SendRecvPackets();
}
TEST_F(DtlsSrtpTransportTest,
RtcpMuxEnabledAfterRtpTransportHandshakeComplete) {
auto rtp_dtls1 = std::make_unique<FakeDtlsTransport>(
"audio", cricket::ICE_CANDIDATE_COMPONENT_RTP);
auto rtcp_dtls1 = std::make_unique<FakeDtlsTransport>(
"audio", cricket::ICE_CANDIDATE_COMPONENT_RTCP);
auto rtp_dtls2 = std::make_unique<FakeDtlsTransport>(
"audio", cricket::ICE_CANDIDATE_COMPONENT_RTP);
auto rtcp_dtls2 = std::make_unique<FakeDtlsTransport>(
"audio", cricket::ICE_CANDIDATE_COMPONENT_RTCP);
MakeDtlsSrtpTransports(rtp_dtls1.get(), rtcp_dtls1.get(), rtp_dtls2.get(),
rtcp_dtls2.get(), false);
CompleteDtlsHandshake(rtp_dtls1.get(), rtp_dtls2.get());
EXPECT_FALSE(dtls_srtp_transport1_->IsSrtpActive());
EXPECT_FALSE(dtls_srtp_transport2_->IsSrtpActive());
dtls_srtp_transport1_->SetRtcpMuxEnabled(true);
dtls_srtp_transport2_->SetRtcpMuxEnabled(true);
SendRecvPackets();
}
TEST_F(DtlsSrtpTransportTest, EncryptedHeaderExtensionIdUpdated) {
auto rtp_dtls1 = std::make_unique<FakeDtlsTransport>(
"audio", cricket::ICE_CANDIDATE_COMPONENT_RTP);
auto rtp_dtls2 = std::make_unique<FakeDtlsTransport>(
"audio", cricket::ICE_CANDIDATE_COMPONENT_RTP);
MakeDtlsSrtpTransports(rtp_dtls1.get(), nullptr, rtp_dtls2.get(), nullptr,
true);
CompleteDtlsHandshake(rtp_dtls1.get(), rtp_dtls2.get());
std::vector<int> encrypted_headers;
encrypted_headers.push_back(kHeaderExtensionIDs[0]);
encrypted_headers.push_back(kHeaderExtensionIDs[1]);
dtls_srtp_transport1_->UpdateSendEncryptedHeaderExtensionIds(
encrypted_headers);
dtls_srtp_transport1_->UpdateRecvEncryptedHeaderExtensionIds(
encrypted_headers);
dtls_srtp_transport2_->UpdateSendEncryptedHeaderExtensionIds(
encrypted_headers);
dtls_srtp_transport2_->UpdateRecvEncryptedHeaderExtensionIds(
encrypted_headers);
}
TEST_F(DtlsSrtpTransportTest, SignalReadyToSendFiredWithRtcpMux) {
auto rtp_dtls1 = std::make_unique<FakeDtlsTransport>(
"audio", cricket::ICE_CANDIDATE_COMPONENT_RTP);
auto rtp_dtls2 = std::make_unique<FakeDtlsTransport>(
"audio", cricket::ICE_CANDIDATE_COMPONENT_RTP);
MakeDtlsSrtpTransports(rtp_dtls1.get(), nullptr, rtp_dtls2.get(), nullptr,
true);
rtp_dtls1->SetDestination(rtp_dtls2.get());
EXPECT_TRUE(transport_observer1_.ready_to_send());
EXPECT_TRUE(transport_observer2_.ready_to_send());
}
TEST_F(DtlsSrtpTransportTest, SignalReadyToSendFiredWithoutRtcpMux) {
auto rtp_dtls1 = std::make_unique<FakeDtlsTransport>(
"audio", cricket::ICE_CANDIDATE_COMPONENT_RTP);
auto rtcp_dtls1 = std::make_unique<FakeDtlsTransport>(
"audio", cricket::ICE_CANDIDATE_COMPONENT_RTCP);
auto rtp_dtls2 = std::make_unique<FakeDtlsTransport>(
"audio", cricket::ICE_CANDIDATE_COMPONENT_RTP);
auto rtcp_dtls2 = std::make_unique<FakeDtlsTransport>(
"audio", cricket::ICE_CANDIDATE_COMPONENT_RTCP);
MakeDtlsSrtpTransports(rtp_dtls1.get(), rtcp_dtls1.get(), rtp_dtls2.get(),
rtcp_dtls2.get(), false);
rtp_dtls1->SetDestination(rtp_dtls2.get());
EXPECT_FALSE(transport_observer1_.ready_to_send());
EXPECT_FALSE(transport_observer2_.ready_to_send());
rtcp_dtls1->SetDestination(rtcp_dtls2.get());
EXPECT_TRUE(transport_observer1_.ready_to_send());
EXPECT_TRUE(transport_observer2_.ready_to_send());
}
TEST_F(DtlsSrtpTransportTest, SrtpSessionNotResetWhenRtcpTransportRemoved) {
auto rtp_dtls1 = std::make_unique<FakeDtlsTransport>(
"audio", cricket::ICE_CANDIDATE_COMPONENT_RTP);
auto rtcp_dtls1 = std::make_unique<FakeDtlsTransport>(
"audio", cricket::ICE_CANDIDATE_COMPONENT_RTCP);
auto rtp_dtls2 = std::make_unique<FakeDtlsTransport>(
"audio", cricket::ICE_CANDIDATE_COMPONENT_RTP);
auto rtcp_dtls2 = std::make_unique<FakeDtlsTransport>(
"audio", cricket::ICE_CANDIDATE_COMPONENT_RTCP);
MakeDtlsSrtpTransports(rtp_dtls1.get(), rtcp_dtls1.get(), rtp_dtls2.get(),
rtcp_dtls2.get(), true);
CompleteDtlsHandshake(rtp_dtls1.get(), rtp_dtls2.get());
CompleteDtlsHandshake(rtcp_dtls1.get(), rtcp_dtls2.get());
SendRecvRtcpPackets();
dtls_srtp_transport1_->SetDtlsTransports(rtp_dtls1.get(), nullptr);
SendRecvRtcpPackets();
}
TEST_F(DtlsSrtpTransportTest, ActivelyResetSrtpParams) {
auto rtp_dtls1 = std::make_unique<FakeDtlsTransport>(
"audio", cricket::ICE_CANDIDATE_COMPONENT_RTP);
auto rtcp_dtls1 = std::make_unique<FakeDtlsTransport>(
"audio", cricket::ICE_CANDIDATE_COMPONENT_RTCP);
auto rtp_dtls2 = std::make_unique<FakeDtlsTransport>(
"audio", cricket::ICE_CANDIDATE_COMPONENT_RTP);
auto rtcp_dtls2 = std::make_unique<FakeDtlsTransport>(
"audio", cricket::ICE_CANDIDATE_COMPONENT_RTCP);
MakeDtlsSrtpTransports(rtp_dtls1.get(), rtcp_dtls1.get(), rtp_dtls2.get(),
rtcp_dtls2.get(), true);
CompleteDtlsHandshake(rtp_dtls1.get(), rtp_dtls2.get());
CompleteDtlsHandshake(rtcp_dtls1.get(), rtcp_dtls2.get());
SendRecvRtcpPackets();
dtls_srtp_transport1_->SetActiveResetSrtpParams(true);
dtls_srtp_transport1_->SetDtlsTransports(rtp_dtls1.get(), nullptr);
dtls_srtp_transport2_->SetDtlsTransports(rtp_dtls2.get(), nullptr);
size_t rtcp_len = sizeof(kRtcpReport);
size_t packet_size = rtcp_len + 4 + kRtpAuthTagLen;
rtc::Buffer rtcp_packet_buffer(packet_size);
rtc::CopyOnWriteBuffer rtcp_packet(kRtcpReport, rtcp_len, packet_size);
int prev_received_packets = transport_observer2_.rtcp_count();
ASSERT_TRUE(dtls_srtp_transport1_->SendRtcpPacket(
&rtcp_packet, rtc::PacketOptions(), cricket::PF_SRTP_BYPASS));
EXPECT_EQ(prev_received_packets, transport_observer2_.rtcp_count());
dtls_srtp_transport2_->SetActiveResetSrtpParams(true);
dtls_srtp_transport1_->SetDtlsTransports(rtp_dtls1.get(), nullptr);
dtls_srtp_transport2_->SetDtlsTransports(rtp_dtls2.get(), nullptr);
SendRecvRtcpPackets();
}