Delete RtcpDemuxer as unused

Bug: None
Change-Id: I17b30af3fef6c165bf951cb58eef11cc9c37aa39
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/178396
Reviewed-by: Sebastian Jansson <srte@webrtc.org>
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#31676}
This commit is contained in:
Danil Chapovalov
2020-06-30 17:51:55 +02:00
committed by Commit Bot
parent a5a4be1118
commit c1b271264a
11 changed files with 36 additions and 1038 deletions

View File

@ -81,7 +81,6 @@ rtc_library("rtp_interfaces") {
# client code gets updated.
visibility = [ "*" ]
sources = [
"rtcp_packet_sink_interface.h",
"rtp_config.cc",
"rtp_config.h",
"rtp_packet_sink_interface.h",
@ -111,12 +110,8 @@ rtc_library("rtp_interfaces") {
rtc_library("rtp_receiver") {
visibility = [ "*" ]
sources = [
"rtcp_demuxer.cc",
"rtcp_demuxer.h",
"rtp_demuxer.cc",
"rtp_demuxer.h",
"rtp_rtcp_demuxer_helper.cc",
"rtp_rtcp_demuxer_helper.h",
"rtp_stream_receiver_controller.cc",
"rtp_stream_receiver_controller.h",
"rtx_receive_stream.cc",
@ -387,11 +382,9 @@ if (rtc_include_tests) {
"call_unittest.cc",
"flexfec_receive_stream_unittest.cc",
"receive_time_calculator_unittest.cc",
"rtcp_demuxer_unittest.cc",
"rtp_bitrate_configurator_unittest.cc",
"rtp_demuxer_unittest.cc",
"rtp_payload_params_unittest.cc",
"rtp_rtcp_demuxer_helper_unittest.cc",
"rtp_video_sender_unittest.cc",
"rtx_receive_stream_unittest.cc",
]

View File

@ -1,107 +0,0 @@
/*
* Copyright (c) 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 "call/rtcp_demuxer.h"
#include <stddef.h>
#include <algorithm>
#include <utility>
#include "absl/types/optional.h"
#include "api/rtp_headers.h"
#include "call/rtcp_packet_sink_interface.h"
#include "call/rtp_rtcp_demuxer_helper.h"
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
#include "rtc_base/checks.h"
namespace webrtc {
RtcpDemuxer::RtcpDemuxer() = default;
RtcpDemuxer::~RtcpDemuxer() {
RTC_DCHECK(ssrc_sinks_.empty());
RTC_DCHECK(rsid_sinks_.empty());
RTC_DCHECK(broadcast_sinks_.empty());
}
void RtcpDemuxer::AddSink(uint32_t sender_ssrc, RtcpPacketSinkInterface* sink) {
RTC_DCHECK(sink);
RTC_DCHECK(!ContainerHasKey(broadcast_sinks_, sink));
RTC_DCHECK(!MultimapAssociationExists(ssrc_sinks_, sender_ssrc, sink));
ssrc_sinks_.emplace(sender_ssrc, sink);
}
void RtcpDemuxer::AddSink(const std::string& rsid,
RtcpPacketSinkInterface* sink) {
RTC_DCHECK(IsLegalRsidName(rsid));
RTC_DCHECK(sink);
RTC_DCHECK(!ContainerHasKey(broadcast_sinks_, sink));
RTC_DCHECK(!MultimapAssociationExists(rsid_sinks_, rsid, sink));
rsid_sinks_.emplace(rsid, sink);
}
void RtcpDemuxer::AddBroadcastSink(RtcpPacketSinkInterface* sink) {
RTC_DCHECK(sink);
RTC_DCHECK(!MultimapHasValue(ssrc_sinks_, sink));
RTC_DCHECK(!MultimapHasValue(rsid_sinks_, sink));
RTC_DCHECK(!ContainerHasKey(broadcast_sinks_, sink));
broadcast_sinks_.push_back(sink);
}
void RtcpDemuxer::RemoveSink(const RtcpPacketSinkInterface* sink) {
RTC_DCHECK(sink);
size_t removal_count = RemoveFromMultimapByValue(&ssrc_sinks_, sink) +
RemoveFromMultimapByValue(&rsid_sinks_, sink);
RTC_DCHECK_GT(removal_count, 0);
}
void RtcpDemuxer::RemoveBroadcastSink(const RtcpPacketSinkInterface* sink) {
RTC_DCHECK(sink);
auto it = std::find(broadcast_sinks_.begin(), broadcast_sinks_.end(), sink);
RTC_DCHECK(it != broadcast_sinks_.end());
broadcast_sinks_.erase(it);
}
void RtcpDemuxer::OnRtcpPacket(rtc::ArrayView<const uint8_t> packet) {
// Perform sender-SSRC-based demuxing for packets with a sender-SSRC.
absl::optional<uint32_t> sender_ssrc = ParseRtcpPacketSenderSsrc(packet);
if (sender_ssrc) {
auto it_range = ssrc_sinks_.equal_range(*sender_ssrc);
for (auto it = it_range.first; it != it_range.second; ++it) {
it->second->OnRtcpPacket(packet);
}
}
// All packets, even those without a sender-SSRC, are broadcast to sinks
// which listen to broadcasts.
for (RtcpPacketSinkInterface* sink : broadcast_sinks_) {
sink->OnRtcpPacket(packet);
}
}
void RtcpDemuxer::OnSsrcBoundToRsid(const std::string& rsid, uint32_t ssrc) {
// Record the new SSRC association for all of the sinks that were associated
// with the RSID.
auto it_range = rsid_sinks_.equal_range(rsid);
for (auto it = it_range.first; it != it_range.second; ++it) {
RtcpPacketSinkInterface* sink = it->second;
// Watch out for pre-existing SSRC-based associations.
if (!MultimapAssociationExists(ssrc_sinks_, ssrc, sink)) {
AddSink(ssrc, sink);
}
}
// RSIDs are uniquely associated with SSRCs; no need to keep in memory
// the RSID-to-sink association of resolved RSIDs.
rsid_sinks_.erase(it_range.first, it_range.second);
}
} // namespace webrtc

View File

@ -1,84 +0,0 @@
/*
* Copyright (c) 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.
*/
#ifndef CALL_RTCP_DEMUXER_H_
#define CALL_RTCP_DEMUXER_H_
#include <map>
#include <string>
#include <vector>
#include "api/array_view.h"
#include "call/ssrc_binding_observer.h"
namespace webrtc {
class RtcpPacketSinkInterface;
// This class represents the RTCP demuxing, for a single RTP session (i.e., one
// SSRC space, see RFC 7656). It isn't thread aware, leaving responsibility of
// multithreading issues to the user of this class.
class RtcpDemuxer : public SsrcBindingObserver {
public:
RtcpDemuxer();
~RtcpDemuxer() override;
// Registers a sink. The sink will be notified of incoming RTCP packets with
// that sender-SSRC. The same sink can be registered for multiple SSRCs, and
// the same SSRC can have multiple sinks. Null pointer is not allowed.
// Sinks may be associated with both an SSRC and an RSID.
// Sinks may be registered as SSRC/RSID-specific or broadcast, but not both.
void AddSink(uint32_t sender_ssrc, RtcpPacketSinkInterface* sink);
// Registers a sink. Once the RSID is resolved to an SSRC, the sink will be
// notified of all RTCP packets with that sender-SSRC.
// The same sink can be registered for multiple RSIDs, and
// the same RSID can have multiple sinks. Null pointer is not allowed.
// Sinks may be associated with both an SSRC and an RSID.
// Sinks may be registered as SSRC/RSID-specific or broadcast, but not both.
void AddSink(const std::string& rsid, RtcpPacketSinkInterface* sink);
// Registers a sink. The sink will be notified of any incoming RTCP packet.
// Null pointer is not allowed.
// Sinks may be registered as SSRC/RSID-specific or broadcast, but not both.
void AddBroadcastSink(RtcpPacketSinkInterface* sink);
// Undo previous AddSink() calls with the given sink.
void RemoveSink(const RtcpPacketSinkInterface* sink);
// Undo AddBroadcastSink().
void RemoveBroadcastSink(const RtcpPacketSinkInterface* sink);
// Process a new RTCP packet and forward it to the appropriate sinks.
void OnRtcpPacket(rtc::ArrayView<const uint8_t> packet);
// Implement SsrcBindingObserver - become notified whenever RSIDs resolve to
// an SSRC.
void OnSsrcBoundToRsid(const std::string& rsid, uint32_t ssrc) override;
// TODO(eladalon): Add the ability to resolve RSIDs and inform observers,
// like in the RtpDemuxer case, once the relevant standard is finalized.
private:
// Records the association SSRCs to sinks.
std::multimap<uint32_t, RtcpPacketSinkInterface*> ssrc_sinks_;
// Records the association RSIDs to sinks.
std::multimap<std::string, RtcpPacketSinkInterface*> rsid_sinks_;
// Sinks which will receive notifications of all incoming RTCP packets.
// Additional/removal of sinks is expected to be significantly less frequent
// than RTCP message reception; container chosen for iteration performance.
std::vector<RtcpPacketSinkInterface*> broadcast_sinks_;
};
} // namespace webrtc
#endif // CALL_RTCP_DEMUXER_H_

View File

@ -1,507 +0,0 @@
/*
* Copyright (c) 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 "call/rtcp_demuxer.h"
#include <stddef.h>
#include <set>
#include "api/rtp_headers.h"
#include "call/rtcp_packet_sink_interface.h"
#include "modules/rtp_rtcp/source/rtcp_packet/bye.h"
#include "modules/rtp_rtcp/source/rtp_header_extensions.h"
#include "rtc_base/arraysize.h"
#include "rtc_base/buffer.h"
#include "rtc_base/checks.h"
#include "test/gmock.h"
#include "test/gtest.h"
namespace webrtc {
namespace {
using ::testing::_;
using ::testing::AtLeast;
using ::testing::ElementsAreArray;
using ::testing::InSequence;
using ::testing::Matcher;
using ::testing::NiceMock;
class MockRtcpPacketSink : public RtcpPacketSinkInterface {
public:
MOCK_METHOD(void, OnRtcpPacket, (rtc::ArrayView<const uint8_t>), (override));
};
class RtcpDemuxerTest : public ::testing::Test {
protected:
~RtcpDemuxerTest() {
for (auto* sink : sinks_to_tear_down_) {
demuxer_.RemoveSink(sink);
}
for (auto* sink : broadcast_sinks_to_tear_down_) {
demuxer_.RemoveBroadcastSink(sink);
}
}
void AddSsrcSink(uint32_t ssrc, RtcpPacketSinkInterface* sink) {
demuxer_.AddSink(ssrc, sink);
sinks_to_tear_down_.insert(sink);
}
void AddRsidSink(const std::string& rsid, RtcpPacketSinkInterface* sink) {
demuxer_.AddSink(rsid, sink);
sinks_to_tear_down_.insert(sink);
}
void RemoveSink(RtcpPacketSinkInterface* sink) {
sinks_to_tear_down_.erase(sink);
demuxer_.RemoveSink(sink);
}
void AddBroadcastSink(RtcpPacketSinkInterface* sink) {
demuxer_.AddBroadcastSink(sink);
broadcast_sinks_to_tear_down_.insert(sink);
}
void RemoveBroadcastSink(RtcpPacketSinkInterface* sink) {
broadcast_sinks_to_tear_down_.erase(sink);
demuxer_.RemoveBroadcastSink(sink);
}
RtcpDemuxer demuxer_;
std::set<RtcpPacketSinkInterface*> sinks_to_tear_down_;
std::set<RtcpPacketSinkInterface*> broadcast_sinks_to_tear_down_;
};
class RtcpDemuxerDeathTest : public RtcpDemuxerTest {};
// Produces a packet buffer representing an RTCP packet with a given SSRC,
// as it would look when sent over the wire.
// |distinguishing_string| allows different RTCP packets with the same SSRC
// to be distinguished. How this is set into the actual packet is
// unimportant, and depends on which RTCP message we choose to use.
rtc::Buffer CreateRtcpPacket(uint32_t ssrc,
const std::string& distinguishing_string = "") {
rtcp::Bye packet;
packet.SetSenderSsrc(ssrc);
if (distinguishing_string != "") {
// Actual way we use |distinguishing_string| is unimportant, so long
// as it ends up in the packet.
packet.SetReason(distinguishing_string);
}
return packet.Build();
}
static Matcher<rtc::ArrayView<const uint8_t>> SamePacketAs(
const rtc::Buffer& other) {
return ElementsAreArray(other.cbegin(), other.cend());
}
} // namespace
TEST_F(RtcpDemuxerTest, OnRtcpPacketCalledOnCorrectSinkBySsrc) {
constexpr uint32_t ssrcs[] = {101, 202, 303};
MockRtcpPacketSink sinks[arraysize(ssrcs)];
for (size_t i = 0; i < arraysize(ssrcs); i++) {
AddSsrcSink(ssrcs[i], &sinks[i]);
}
for (size_t i = 0; i < arraysize(ssrcs); i++) {
auto packet = CreateRtcpPacket(ssrcs[i]);
EXPECT_CALL(sinks[i], OnRtcpPacket(SamePacketAs(packet))).Times(1);
demuxer_.OnRtcpPacket(packet);
}
}
TEST_F(RtcpDemuxerTest, OnRtcpPacketCalledOnResolvedRsidSink) {
// Set up some RSID sinks.
const std::string rsids[] = {"a", "b", "c"};
MockRtcpPacketSink sinks[arraysize(rsids)];
for (size_t i = 0; i < arraysize(rsids); i++) {
AddRsidSink(rsids[i], &sinks[i]);
}
// Only resolve one of the sinks.
constexpr size_t resolved_sink_index = 0;
constexpr uint32_t ssrc = 345;
demuxer_.OnSsrcBoundToRsid(rsids[resolved_sink_index], ssrc);
// The resolved sink gets notifications of RTCP messages with its SSRC.
auto packet = CreateRtcpPacket(ssrc);
EXPECT_CALL(sinks[resolved_sink_index], OnRtcpPacket(SamePacketAs(packet)))
.Times(1);
// RTCP received; expected calls triggered.
demuxer_.OnRtcpPacket(packet);
}
TEST_F(RtcpDemuxerTest,
SingleCallbackAfterResolutionOfAnRsidToAlreadyRegisteredSsrc) {
// Associate a sink with an SSRC.
MockRtcpPacketSink sink;
constexpr uint32_t ssrc = 999;
AddSsrcSink(ssrc, &sink);
// Associate the same sink with an RSID.
const std::string rsid = "r";
AddRsidSink(rsid, &sink);
// Resolve the RSID to the aforementioned SSRC.
demuxer_.OnSsrcBoundToRsid(rsid, ssrc);
// OnRtcpPacket still called only a single time for messages with this SSRC.
auto packet = CreateRtcpPacket(ssrc);
EXPECT_CALL(sink, OnRtcpPacket(SamePacketAs(packet))).Times(1);
demuxer_.OnRtcpPacket(packet);
}
TEST_F(RtcpDemuxerTest,
OnRtcpPacketCalledOnAllBroadcastSinksForAllRtcpPackets) {
MockRtcpPacketSink sinks[3];
for (MockRtcpPacketSink& sink : sinks) {
AddBroadcastSink(&sink);
}
constexpr uint32_t ssrc = 747;
auto packet = CreateRtcpPacket(ssrc);
for (MockRtcpPacketSink& sink : sinks) {
EXPECT_CALL(sink, OnRtcpPacket(SamePacketAs(packet))).Times(1);
}
// RTCP received; expected calls triggered.
demuxer_.OnRtcpPacket(packet);
}
TEST_F(RtcpDemuxerTest, PacketsDeliveredInRightOrderToNonBroadcastSink) {
constexpr uint32_t ssrc = 101;
MockRtcpPacketSink sink;
AddSsrcSink(ssrc, &sink);
std::vector<rtc::Buffer> packets;
for (size_t i = 0; i < 5; i++) {
packets.push_back(CreateRtcpPacket(ssrc, std::to_string(i)));
}
InSequence sequence;
for (const auto& packet : packets) {
EXPECT_CALL(sink, OnRtcpPacket(SamePacketAs(packet))).Times(1);
}
for (const auto& packet : packets) {
demuxer_.OnRtcpPacket(packet);
}
}
TEST_F(RtcpDemuxerTest, PacketsDeliveredInRightOrderToBroadcastSink) {
MockRtcpPacketSink sink;
AddBroadcastSink(&sink);
std::vector<rtc::Buffer> packets;
for (size_t i = 0; i < 5; i++) {
constexpr uint32_t ssrc = 101;
packets.push_back(CreateRtcpPacket(ssrc, std::to_string(i)));
}
InSequence sequence;
for (const auto& packet : packets) {
EXPECT_CALL(sink, OnRtcpPacket(SamePacketAs(packet))).Times(1);
}
for (const auto& packet : packets) {
demuxer_.OnRtcpPacket(packet);
}
}
TEST_F(RtcpDemuxerTest, MultipleSinksMappedToSameSsrc) {
MockRtcpPacketSink sinks[3];
constexpr uint32_t ssrc = 404;
for (auto& sink : sinks) {
AddSsrcSink(ssrc, &sink);
}
// Reception of an RTCP packet associated with the shared SSRC triggers the
// callback on all of the sinks associated with it.
auto packet = CreateRtcpPacket(ssrc);
for (auto& sink : sinks) {
EXPECT_CALL(sink, OnRtcpPacket(SamePacketAs(packet)));
}
demuxer_.OnRtcpPacket(packet);
}
TEST_F(RtcpDemuxerTest, SinkMappedToMultipleSsrcs) {
constexpr uint32_t ssrcs[] = {404, 505, 606};
MockRtcpPacketSink sink;
for (uint32_t ssrc : ssrcs) {
AddSsrcSink(ssrc, &sink);
}
// The sink which is associated with multiple SSRCs gets the callback
// triggered for each of those SSRCs.
for (uint32_t ssrc : ssrcs) {
auto packet = CreateRtcpPacket(ssrc);
EXPECT_CALL(sink, OnRtcpPacket(SamePacketAs(packet)));
demuxer_.OnRtcpPacket(packet);
}
}
TEST_F(RtcpDemuxerTest, MultipleRsidsOnSameSink) {
// Sink associated with multiple sinks.
MockRtcpPacketSink sink;
const std::string rsids[] = {"a", "b", "c"};
for (const auto& rsid : rsids) {
AddRsidSink(rsid, &sink);
}
// RSIDs resolved to SSRCs.
uint32_t ssrcs[arraysize(rsids)];
for (size_t i = 0; i < arraysize(rsids); i++) {
ssrcs[i] = 1000 + static_cast<uint32_t>(i);
demuxer_.OnSsrcBoundToRsid(rsids[i], ssrcs[i]);
}
// Set up packets to match those RSIDs/SSRCs.
std::vector<rtc::Buffer> packets;
for (size_t i = 0; i < arraysize(rsids); i++) {
packets.push_back(CreateRtcpPacket(ssrcs[i]));
}
// The sink expects to receive all of the packets.
for (const auto& packet : packets) {
EXPECT_CALL(sink, OnRtcpPacket(SamePacketAs(packet))).Times(1);
}
// Packet demuxed correctly; OnRtcpPacket() triggered on sink.
for (const auto& packet : packets) {
demuxer_.OnRtcpPacket(packet);
}
}
TEST_F(RtcpDemuxerTest, RsidUsedByMultipleSinks) {
MockRtcpPacketSink sinks[3];
const std::string shared_rsid = "a";
for (MockRtcpPacketSink& sink : sinks) {
AddRsidSink(shared_rsid, &sink);
}
constexpr uint32_t shared_ssrc = 888;
demuxer_.OnSsrcBoundToRsid(shared_rsid, shared_ssrc);
auto packet = CreateRtcpPacket(shared_ssrc);
for (MockRtcpPacketSink& sink : sinks) {
EXPECT_CALL(sink, OnRtcpPacket(SamePacketAs(packet))).Times(1);
}
demuxer_.OnRtcpPacket(packet);
}
TEST_F(RtcpDemuxerTest, NoCallbackOnSsrcSinkRemovedBeforeFirstPacket) {
constexpr uint32_t ssrc = 404;
MockRtcpPacketSink sink;
AddSsrcSink(ssrc, &sink);
RemoveSink(&sink);
// The removed sink does not get callbacks.
auto packet = CreateRtcpPacket(ssrc);
EXPECT_CALL(sink, OnRtcpPacket(_)).Times(0); // Not called.
demuxer_.OnRtcpPacket(packet);
}
TEST_F(RtcpDemuxerTest, NoCallbackOnSsrcSinkRemovedAfterFirstPacket) {
constexpr uint32_t ssrc = 404;
NiceMock<MockRtcpPacketSink> sink;
AddSsrcSink(ssrc, &sink);
auto before_packet = CreateRtcpPacket(ssrc);
demuxer_.OnRtcpPacket(before_packet);
RemoveSink(&sink);
// The removed sink does not get callbacks.
auto after_packet = CreateRtcpPacket(ssrc);
EXPECT_CALL(sink, OnRtcpPacket(_)).Times(0); // Not called.
demuxer_.OnRtcpPacket(after_packet);
}
TEST_F(RtcpDemuxerTest, NoCallbackOnRsidSinkRemovedBeforeRsidResolution) {
const std::string rsid = "a";
constexpr uint32_t ssrc = 404;
MockRtcpPacketSink sink;
AddRsidSink(rsid, &sink);
// Removal before resolution.
RemoveSink(&sink);
demuxer_.OnSsrcBoundToRsid(rsid, ssrc);
// The removed sink does not get callbacks.
auto packet = CreateRtcpPacket(ssrc);
EXPECT_CALL(sink, OnRtcpPacket(_)).Times(0); // Not called.
demuxer_.OnRtcpPacket(packet);
}
TEST_F(RtcpDemuxerTest, NoCallbackOnRsidSinkRemovedAfterRsidResolution) {
const std::string rsid = "a";
constexpr uint32_t ssrc = 404;
MockRtcpPacketSink sink;
AddRsidSink(rsid, &sink);
// Removal after resolution.
demuxer_.OnSsrcBoundToRsid(rsid, ssrc);
RemoveSink(&sink);
// The removed sink does not get callbacks.
auto packet = CreateRtcpPacket(ssrc);
EXPECT_CALL(sink, OnRtcpPacket(_)).Times(0); // Not called.
demuxer_.OnRtcpPacket(packet);
}
TEST_F(RtcpDemuxerTest, NoCallbackOnBroadcastSinkRemovedBeforeFirstPacket) {
MockRtcpPacketSink sink;
AddBroadcastSink(&sink);
RemoveBroadcastSink(&sink);
// The removed sink does not get callbacks.
constexpr uint32_t ssrc = 404;
auto packet = CreateRtcpPacket(ssrc);
EXPECT_CALL(sink, OnRtcpPacket(_)).Times(0); // Not called.
demuxer_.OnRtcpPacket(packet);
}
TEST_F(RtcpDemuxerTest, NoCallbackOnBroadcastSinkRemovedAfterFirstPacket) {
NiceMock<MockRtcpPacketSink> sink;
AddBroadcastSink(&sink);
constexpr uint32_t ssrc = 404;
auto before_packet = CreateRtcpPacket(ssrc);
demuxer_.OnRtcpPacket(before_packet);
RemoveBroadcastSink(&sink);
// The removed sink does not get callbacks.
auto after_packet = CreateRtcpPacket(ssrc);
EXPECT_CALL(sink, OnRtcpPacket(_)).Times(0); // Not called.
demuxer_.OnRtcpPacket(after_packet);
}
// The RSID to SSRC mapping should be one-to-one. If we end up receiving
// two (or more) packets with the same SSRC, but different RSIDs, we guarantee
// remembering the first one; no guarantees are made about further associations.
TEST_F(RtcpDemuxerTest, FirstResolutionOfRsidNotForgotten) {
MockRtcpPacketSink sink;
const std::string rsid = "a";
AddRsidSink(rsid, &sink);
constexpr uint32_t ssrc_a = 111; // First resolution - guaranteed effective.
demuxer_.OnSsrcBoundToRsid(rsid, ssrc_a);
constexpr uint32_t ssrc_b = 222; // Second resolution - no guarantees.
demuxer_.OnSsrcBoundToRsid(rsid, ssrc_b);
auto packet_a = CreateRtcpPacket(ssrc_a);
EXPECT_CALL(sink, OnRtcpPacket(SamePacketAs(packet_a))).Times(1);
demuxer_.OnRtcpPacket(packet_a);
auto packet_b = CreateRtcpPacket(ssrc_b);
EXPECT_CALL(sink, OnRtcpPacket(SamePacketAs(packet_b))).Times(AtLeast(0));
demuxer_.OnRtcpPacket(packet_b);
}
#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
TEST_F(RtcpDemuxerDeathTest, RepeatedSsrcToSinkAssociationsDisallowed) {
MockRtcpPacketSink sink;
constexpr uint32_t ssrc = 101;
AddSsrcSink(ssrc, &sink);
EXPECT_DEATH(AddSsrcSink(ssrc, &sink), "");
}
TEST_F(RtcpDemuxerDeathTest, RepeatedRsidToSinkAssociationsDisallowed) {
MockRtcpPacketSink sink;
const std::string rsid = "z";
AddRsidSink(rsid, &sink);
EXPECT_DEATH(AddRsidSink(rsid, &sink), "");
}
TEST_F(RtcpDemuxerDeathTest, RepeatedBroadcastSinkRegistrationDisallowed) {
MockRtcpPacketSink sink;
AddBroadcastSink(&sink);
EXPECT_DEATH(AddBroadcastSink(&sink), "");
}
TEST_F(RtcpDemuxerDeathTest, SsrcSinkCannotAlsoBeRegisteredAsBroadcast) {
MockRtcpPacketSink sink;
constexpr uint32_t ssrc = 101;
AddSsrcSink(ssrc, &sink);
EXPECT_DEATH(AddBroadcastSink(&sink), "");
}
TEST_F(RtcpDemuxerDeathTest, RsidSinkCannotAlsoBeRegisteredAsBroadcast) {
MockRtcpPacketSink sink;
const std::string rsid = "z";
AddRsidSink(rsid, &sink);
EXPECT_DEATH(AddBroadcastSink(&sink), "");
}
TEST_F(RtcpDemuxerDeathTest, BroadcastSinkCannotAlsoBeRegisteredAsSsrcSink) {
MockRtcpPacketSink sink;
AddBroadcastSink(&sink);
constexpr uint32_t ssrc = 101;
EXPECT_DEATH(AddSsrcSink(ssrc, &sink), "");
}
TEST_F(RtcpDemuxerDeathTest, BroadcastSinkCannotAlsoBeRegisteredAsRsidSink) {
MockRtcpPacketSink sink;
AddBroadcastSink(&sink);
const std::string rsid = "j";
EXPECT_DEATH(AddRsidSink(rsid, &sink), "");
}
TEST_F(RtcpDemuxerDeathTest, MayNotCallRemoveSinkOnNeverAddedSink) {
MockRtcpPacketSink sink;
EXPECT_DEATH(RemoveSink(&sink), "");
}
TEST_F(RtcpDemuxerDeathTest, MayNotCallRemoveBroadcastSinkOnNeverAddedSink) {
MockRtcpPacketSink sink;
EXPECT_DEATH(RemoveBroadcastSink(&sink), "");
}
TEST_F(RtcpDemuxerDeathTest, RsidMustBeNonEmpty) {
MockRtcpPacketSink sink;
EXPECT_DEATH(AddRsidSink("", &sink), "");
}
TEST_F(RtcpDemuxerDeathTest, RsidMustBeAlphaNumeric) {
MockRtcpPacketSink sink;
EXPECT_DEATH(AddRsidSink("a_3", &sink), "");
}
TEST_F(RtcpDemuxerDeathTest, RsidMustNotExceedMaximumLength) {
MockRtcpPacketSink sink;
std::string rsid(BaseRtpStringExtension::kMaxValueSizeBytes + 1, 'a');
EXPECT_DEATH(AddRsidSink(rsid, &sink), "");
}
#endif
} // namespace webrtc

View File

@ -1,29 +0,0 @@
/*
* Copyright (c) 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.
*/
#ifndef CALL_RTCP_PACKET_SINK_INTERFACE_H_
#define CALL_RTCP_PACKET_SINK_INTERFACE_H_
#include "api/array_view.h"
namespace webrtc {
// This class represents a receiver of unparsed RTCP packets.
// TODO(eladalon): Replace this by demuxing over parsed rather than raw data.
// Whether this should be over an entire RTCP packet, or over RTCP blocks,
// is still under discussion.
class RtcpPacketSinkInterface {
public:
virtual ~RtcpPacketSinkInterface() = default;
virtual void OnRtcpPacket(rtc::ArrayView<const uint8_t> packet) = 0;
};
} // namespace webrtc
#endif // CALL_RTCP_PACKET_SINK_INTERFACE_H_

View File

@ -11,7 +11,6 @@
#include "call/rtp_demuxer.h"
#include "call/rtp_packet_sink_interface.h"
#include "call/rtp_rtcp_demuxer_helper.h"
#include "call/ssrc_binding_observer.h"
#include "modules/rtp_rtcp/source/rtp_header_extensions.h"
#include "modules/rtp_rtcp/source/rtp_packet_received.h"
@ -20,6 +19,42 @@
#include "rtc_base/strings/string_builder.h"
namespace webrtc {
namespace {
template <typename Container, typename Value>
size_t RemoveFromMultimapByValue(Container* multimap, const Value& value) {
size_t count = 0;
for (auto it = multimap->begin(); it != multimap->end();) {
if (it->second == value) {
it = multimap->erase(it);
++count;
} else {
++it;
}
}
return count;
}
template <typename Map, typename Value>
size_t RemoveFromMapByValue(Map* map, const Value& value) {
size_t count = 0;
for (auto it = map->begin(); it != map->end();) {
if (it->second == value) {
it = map->erase(it);
++count;
} else {
++it;
}
}
return count;
}
template <typename Container, typename Key>
bool ContainerHasKey(const Container& c, const Key& k) {
return std::find(c.cbegin(), c.cend(), k) != c.cend();
}
} // namespace
RtpDemuxerCriteria::RtpDemuxerCriteria() = default;
RtpDemuxerCriteria::~RtpDemuxerCriteria() = default;

View File

@ -1,55 +0,0 @@
/*
* Copyright (c) 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 "call/rtp_rtcp_demuxer_helper.h"
#include "modules/rtp_rtcp/source/byte_io.h"
#include "modules/rtp_rtcp/source/rtcp_packet/bye.h"
#include "modules/rtp_rtcp/source/rtcp_packet/common_header.h"
#include "modules/rtp_rtcp/source/rtcp_packet/extended_reports.h"
#include "modules/rtp_rtcp/source/rtcp_packet/psfb.h"
#include "modules/rtp_rtcp/source/rtcp_packet/receiver_report.h"
#include "modules/rtp_rtcp/source/rtcp_packet/rtpfb.h"
#include "modules/rtp_rtcp/source/rtcp_packet/sender_report.h"
namespace webrtc {
absl::optional<uint32_t> ParseRtcpPacketSenderSsrc(
rtc::ArrayView<const uint8_t> packet) {
rtcp::CommonHeader header;
for (const uint8_t* next_packet = packet.begin(); next_packet < packet.end();
next_packet = header.NextPacket()) {
if (!header.Parse(next_packet, packet.end() - next_packet)) {
return absl::nullopt;
}
switch (header.type()) {
case rtcp::Bye::kPacketType:
case rtcp::ExtendedReports::kPacketType:
case rtcp::Psfb::kPacketType:
case rtcp::ReceiverReport::kPacketType:
case rtcp::Rtpfb::kPacketType:
case rtcp::SenderReport::kPacketType: {
// Sender SSRC at the beginning of the RTCP payload.
if (header.payload_size_bytes() >= sizeof(uint32_t)) {
const uint32_t ssrc_sender =
ByteReader<uint32_t>::ReadBigEndian(header.payload());
return ssrc_sender;
} else {
return absl::nullopt;
}
}
}
}
return absl::nullopt;
}
} // namespace webrtc

View File

@ -1,96 +0,0 @@
/*
* Copyright (c) 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.
*/
#ifndef CALL_RTP_RTCP_DEMUXER_HELPER_H_
#define CALL_RTP_RTCP_DEMUXER_HELPER_H_
#include <stddef.h>
#include <stdint.h>
#include "absl/types/optional.h"
#include "api/array_view.h"
namespace webrtc {
// TODO(eladalon): Remove this in the next CL.
template <typename Container>
bool MultimapAssociationExists(const Container& multimap,
const typename Container::key_type& key,
const typename Container::mapped_type& val) {
auto it_range = multimap.equal_range(key);
using Reference = typename Container::const_reference;
return std::any_of(it_range.first, it_range.second,
[val](Reference elem) { return elem.second == val; });
}
template <typename Container, typename Value>
size_t RemoveFromMultimapByValue(Container* multimap, const Value& value) {
size_t count = 0;
for (auto it = multimap->begin(); it != multimap->end();) {
if (it->second == value) {
it = multimap->erase(it);
++count;
} else {
++it;
}
}
return count;
}
template <typename Map, typename Value>
size_t RemoveFromMapByValue(Map* map, const Value& value) {
size_t count = 0;
for (auto it = map->begin(); it != map->end();) {
if (it->second == value) {
it = map->erase(it);
++count;
} else {
++it;
}
}
return count;
}
template <typename Container, typename Key>
bool ContainerHasKey(const Container& c, const Key& k) {
return std::find(c.cbegin(), c.cend(), k) != c.cend();
}
// TODO(eladalon): Remove this in the next CL.
template <typename Container>
bool MultimapHasValue(const Container& c,
const typename Container::mapped_type& v) {
auto predicate = [v](const typename Container::value_type& it) {
return it.second == v;
};
return std::any_of(c.cbegin(), c.cend(), predicate);
}
template <typename Map>
bool MapHasValue(const Map& map, const typename Map::mapped_type& value) {
auto predicate = [value](const typename Map::value_type& it) {
return it.second == value;
};
return std::any_of(map.cbegin(), map.cend(), predicate);
}
template <typename Container>
bool MultimapHasKey(const Container& c,
const typename Container::key_type& key) {
auto it_range = c.equal_range(key);
return it_range.first != it_range.second;
}
absl::optional<uint32_t> ParseRtcpPacketSenderSsrc(
rtc::ArrayView<const uint8_t> packet);
} // namespace webrtc
#endif // CALL_RTP_RTCP_DEMUXER_HELPER_H_

View File

@ -1,120 +0,0 @@
/*
* Copyright (c) 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 "call/rtp_rtcp_demuxer_helper.h"
#include <string.h>
#include <cstdio>
#include "modules/rtp_rtcp/source/rtcp_packet/bye.h"
#include "modules/rtp_rtcp/source/rtcp_packet/extended_jitter_report.h"
#include "modules/rtp_rtcp/source/rtcp_packet/extended_reports.h"
#include "modules/rtp_rtcp/source/rtcp_packet/pli.h"
#include "modules/rtp_rtcp/source/rtcp_packet/rapid_resync_request.h"
#include "modules/rtp_rtcp/source/rtcp_packet/receiver_report.h"
#include "modules/rtp_rtcp/source/rtcp_packet/sender_report.h"
#include "rtc_base/arraysize.h"
#include "rtc_base/buffer.h"
#include "test/gtest.h"
namespace webrtc {
namespace {
constexpr uint32_t kSsrc = 8374;
} // namespace
TEST(RtpRtcpDemuxerHelperTest, ParseRtcpPacketSenderSsrc_ByePacket) {
webrtc::rtcp::Bye rtcp_packet;
rtcp_packet.SetSenderSsrc(kSsrc);
rtc::Buffer raw_packet = rtcp_packet.Build();
absl::optional<uint32_t> ssrc = ParseRtcpPacketSenderSsrc(raw_packet);
EXPECT_EQ(ssrc, kSsrc);
}
TEST(RtpRtcpDemuxerHelperTest,
ParseRtcpPacketSenderSsrc_ExtendedReportsPacket) {
webrtc::rtcp::ExtendedReports rtcp_packet;
rtcp_packet.SetSenderSsrc(kSsrc);
rtc::Buffer raw_packet = rtcp_packet.Build();
absl::optional<uint32_t> ssrc = ParseRtcpPacketSenderSsrc(raw_packet);
EXPECT_EQ(ssrc, kSsrc);
}
TEST(RtpRtcpDemuxerHelperTest, ParseRtcpPacketSenderSsrc_PsfbPacket) {
webrtc::rtcp::Pli rtcp_packet; // Psfb is abstract; use a subclass.
rtcp_packet.SetSenderSsrc(kSsrc);
rtc::Buffer raw_packet = rtcp_packet.Build();
absl::optional<uint32_t> ssrc = ParseRtcpPacketSenderSsrc(raw_packet);
EXPECT_EQ(ssrc, kSsrc);
}
TEST(RtpRtcpDemuxerHelperTest, ParseRtcpPacketSenderSsrc_ReceiverReportPacket) {
webrtc::rtcp::ReceiverReport rtcp_packet;
rtcp_packet.SetSenderSsrc(kSsrc);
rtc::Buffer raw_packet = rtcp_packet.Build();
absl::optional<uint32_t> ssrc = ParseRtcpPacketSenderSsrc(raw_packet);
EXPECT_EQ(ssrc, kSsrc);
}
TEST(RtpRtcpDemuxerHelperTest, ParseRtcpPacketSenderSsrc_RtpfbPacket) {
// Rtpfb is abstract; use a subclass.
webrtc::rtcp::RapidResyncRequest rtcp_packet;
rtcp_packet.SetSenderSsrc(kSsrc);
rtc::Buffer raw_packet = rtcp_packet.Build();
absl::optional<uint32_t> ssrc = ParseRtcpPacketSenderSsrc(raw_packet);
EXPECT_EQ(ssrc, kSsrc);
}
TEST(RtpRtcpDemuxerHelperTest, ParseRtcpPacketSenderSsrc_SenderReportPacket) {
webrtc::rtcp::SenderReport rtcp_packet;
rtcp_packet.SetSenderSsrc(kSsrc);
rtc::Buffer raw_packet = rtcp_packet.Build();
absl::optional<uint32_t> ssrc = ParseRtcpPacketSenderSsrc(raw_packet);
EXPECT_EQ(ssrc, kSsrc);
}
TEST(RtpRtcpDemuxerHelperTest, ParseRtcpPacketSenderSsrc_MalformedRtcpPacket) {
uint8_t garbage[100];
memset(&garbage[0], 0, arraysize(garbage));
absl::optional<uint32_t> ssrc = ParseRtcpPacketSenderSsrc(garbage);
EXPECT_FALSE(ssrc);
}
TEST(RtpRtcpDemuxerHelperTest,
ParseRtcpPacketSenderSsrc_RtcpMessageWithoutSenderSsrc) {
webrtc::rtcp::ExtendedJitterReport rtcp_packet; // Has no sender SSRC.
rtc::Buffer raw_packet = rtcp_packet.Build();
absl::optional<uint32_t> ssrc = ParseRtcpPacketSenderSsrc(raw_packet);
EXPECT_FALSE(ssrc);
}
TEST(RtpRtcpDemuxerHelperTest, ParseRtcpPacketSenderSsrc_TruncatedRtcpMessage) {
webrtc::rtcp::Bye rtcp_packet;
rtcp_packet.SetSenderSsrc(kSsrc);
rtc::Buffer raw_packet = rtcp_packet.Build();
constexpr size_t rtcp_length_bytes = 8;
ASSERT_EQ(rtcp_length_bytes, raw_packet.size());
absl::optional<uint32_t> ssrc = ParseRtcpPacketSenderSsrc(
rtc::ArrayView<const uint8_t>(raw_packet.data(), rtcp_length_bytes - 1));
EXPECT_FALSE(ssrc);
}
} // namespace webrtc

View File

@ -584,15 +584,6 @@ webrtc_fuzzer_test("string_to_number_fuzzer") {
seed_corpus = "corpora/string_to_number-corpus"
}
webrtc_fuzzer_test("rtp_rtcp_demuxer_helper_fuzzer") {
sources = [ "rtp_rtcp_demuxer_helper_fuzzer.cc" ]
deps = [
"../../api:array_view",
"../../call:rtp_receiver",
]
seed_corpus = "corpora/rtcp-corpus"
}
webrtc_fuzzer_test("sctp_utils_fuzzer") {
sources = [ "sctp_utils_fuzzer.cc" ]
deps = [

View File

@ -1,23 +0,0 @@
/*
* Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <stddef.h>
#include <stdint.h>
#include "api/array_view.h"
#include "call/rtp_rtcp_demuxer_helper.h"
namespace webrtc {
void FuzzOneInput(const uint8_t* data, size_t size) {
ParseRtcpPacketSenderSsrc(rtc::MakeArrayView(data, size));
}
} // namespace webrtc