Parse next RTCP XR report block after an unsupported block type.

R=stefan@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/2649004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@5114 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
asapersson@webrtc.org 2013-11-12 08:08:26 +00:00
parent 3e427263ee
commit 38599510df
3 changed files with 167 additions and 108 deletions

View File

@ -162,6 +162,17 @@ class PacketBuilder {
}
}
void AddXrUnknownBlock() {
Add8(6); // Block type.
Add8(0); // Reserved.
Add16(9); // Length.
Add32(0); // Receiver SSRC.
Add64(0, 0); // Remaining fields (RFC 3611) are set to zero.
Add64(0, 0);
Add64(0, 0);
Add64(0, 0);
}
void AddXrVoipBlock(uint32_t remote_ssrc, uint8_t loss) {
Add8(7); // Block type.
Add8(0); // Reserved.
@ -452,6 +463,27 @@ TEST_F(RtcpReceiverTest, InjectXrPacketWithMultipleReportBlocks) {
EXPECT_TRUE(rtcp_packet_info_.xr_dlrr_item);
}
TEST_F(RtcpReceiverTest, InjectXrPacketWithUnknownReportBlock) {
const uint8_t kLossRate = 123;
const uint32_t kSourceSsrc = 0x123456;
std::set<uint32_t> ssrcs;
ssrcs.insert(kSourceSsrc);
rtcp_receiver_->SetSsrcs(kSourceSsrc, ssrcs);
std::vector<uint32_t> remote_ssrcs;
remote_ssrcs.push_back(kSourceSsrc);
PacketBuilder p;
p.AddXrHeader(0x2345);
p.AddXrVoipBlock(kSourceSsrc, kLossRate);
p.AddXrUnknownBlock();
p.AddXrReceiverReferenceTimeBlock(0x10203, 0x40506);
EXPECT_EQ(0, InjectRtcpPacket(p.packet(), p.length()));
EXPECT_EQ(static_cast<unsigned int>(kRtcpXrReceiverReferenceTime +
kRtcpXrVoipMetric),
rtcp_packet_info_.rtcpPacketTypeFlags);
}
TEST(RtcpUtilityTest, MidNtp) {
const uint32_t kNtpSec = 0x12345678;
const uint32_t kNtpFrac = 0x23456789;

View File

@ -224,7 +224,7 @@ RTCPUtility::RTCPParserV2::IterateTopLevel()
}
case PT_XR:
{
const bool ok = ParseXR();
const bool ok = ParseXr();
if (!ok)
{
// Nothing supported found, continue to next block!
@ -243,7 +243,7 @@ RTCPUtility::RTCPParserV2::IterateTopLevel()
void
RTCPUtility::RTCPParserV2::IterateXrItem()
{
const bool success = ParseXRItem();
const bool success = ParseXrItem();
if (!success)
{
Iterate();
@ -253,7 +253,7 @@ RTCPUtility::RTCPParserV2::IterateXrItem()
void
RTCPUtility::RTCPParserV2::IterateXrDlrrItem()
{
const bool success = ParseXRDLRRReportBlockItem();
const bool success = ParseXrDlrrItem();
if (!success)
{
Iterate();
@ -851,7 +851,7 @@ RTCPUtility::RTCPParserV2::ParseBYEItem()
return true;
}
/*
0 1 2 3
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|V=2|P|reserved | PT=XR=207 | length |
@ -861,7 +861,7 @@ RTCPUtility::RTCPParserV2::ParseBYEItem()
: report blocks :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
bool RTCPUtility::RTCPParserV2::ParseXR()
bool RTCPUtility::RTCPParserV2::ParseXr()
{
const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
if (length < 8)
@ -882,55 +882,47 @@ bool RTCPUtility::RTCPParserV2::ParseXR()
return true;
}
/*
/* Extended report block format (RFC 3611).
BT: block type.
block length: length of report block in 32-bits words minus one (including
the header).
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| BT | type-specific | block length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
: type-specific block contents :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
bool
RTCPUtility::RTCPParserV2::ParseXRItem()
{
bool RTCPUtility::RTCPParserV2::ParseXrItem() {
const int kBlockHeaderLengthInBytes = 4;
const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
if (length < 4) {
if (length < kBlockHeaderLengthInBytes) {
_state = State_TopLevel;
EndCurrentBlock();
return false;
}
uint8_t blockType = *_ptrRTCPData++;
uint8_t block_type = *_ptrRTCPData++;
_ptrRTCPData++; // Ignore reserved.
uint16_t blockLength = *_ptrRTCPData++ << 8;
blockLength = *_ptrRTCPData++;
uint16_t block_length_in_4bytes = *_ptrRTCPData++ << 8;
block_length_in_4bytes += *_ptrRTCPData++;
if (blockType == 4 && blockLength == 2)
{
return ParseXRReceiverReferenceTimeItem();
switch (block_type) {
case kBtReceiverReferenceTime:
return ParseXrReceiverReferenceTimeItem(block_length_in_4bytes);
case kBtDlrr:
return ParseXrDlrr(block_length_in_4bytes);
case kBtVoipMetric:
return ParseXrVoipMetricItem(block_length_in_4bytes);
default:
return ParseXrUnsupportedBlockType(block_length_in_4bytes);
}
else if (blockType == 5 && (blockLength % 3) == 0)
{
_packetType = kRtcpXrDlrrReportBlockCode;
_state = State_XR_DLLRItem;
_numberOfBlocks = blockLength / 3;
return true;
}
else if (blockType == 7 && blockLength == 8)
{
return ParseXRVOIPMetricItem();
}
// Not supported.
_state = State_TopLevel;
EndCurrentBlock();
return false;
}
/* 0 1 2 3
/* Receiver Reference Time Report Block.
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| BT=4 | reserved | block length = 2 |
@ -940,37 +932,35 @@ RTCPUtility::RTCPParserV2::ParseXRItem()
| NTP timestamp, least significant word |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
bool RTCPUtility::RTCPParserV2::ParseXRReceiverReferenceTimeItem() {
bool RTCPUtility::RTCPParserV2::ParseXrReceiverReferenceTimeItem(
int block_length_4bytes) {
const int kBlockLengthIn4Bytes = 2;
const int kBlockLengthInBytes = kBlockLengthIn4Bytes * 4;
const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
if (length < 8) {
if (block_length_4bytes != kBlockLengthIn4Bytes ||
length < kBlockLengthInBytes) {
_state = State_TopLevel;
EndCurrentBlock();
return false;
}
_packet.XRReceiverReferenceTimeItem.NTPMostSignificant =
*_ptrRTCPData++ << 24;
_packet.XRReceiverReferenceTimeItem.NTPMostSignificant +=
*_ptrRTCPData++ << 16;
_packet.XRReceiverReferenceTimeItem.NTPMostSignificant +=
*_ptrRTCPData++ << 8;
_packet.XRReceiverReferenceTimeItem.NTPMostSignificant += *_ptrRTCPData++;
_packet.XRReceiverReferenceTimeItem.NTPMostSignificant = *_ptrRTCPData++<<24;
_packet.XRReceiverReferenceTimeItem.NTPMostSignificant+= *_ptrRTCPData++<<16;
_packet.XRReceiverReferenceTimeItem.NTPMostSignificant+= *_ptrRTCPData++<<8;
_packet.XRReceiverReferenceTimeItem.NTPMostSignificant+= *_ptrRTCPData++;
_packet.XRReceiverReferenceTimeItem.NTPLeastSignificant =
*_ptrRTCPData++ << 24;
_packet.XRReceiverReferenceTimeItem.NTPLeastSignificant +=
*_ptrRTCPData++ << 16;
_packet.XRReceiverReferenceTimeItem.NTPLeastSignificant +=
*_ptrRTCPData++ << 8;
_packet.XRReceiverReferenceTimeItem.NTPLeastSignificant += *_ptrRTCPData++;
_packet.XRReceiverReferenceTimeItem.NTPLeastSignificant = *_ptrRTCPData++<<24;
_packet.XRReceiverReferenceTimeItem.NTPLeastSignificant+= *_ptrRTCPData++<<16;
_packet.XRReceiverReferenceTimeItem.NTPLeastSignificant+= *_ptrRTCPData++<<8;
_packet.XRReceiverReferenceTimeItem.NTPLeastSignificant+= *_ptrRTCPData++;
_packetType = kRtcpXrReceiverReferenceTimeCode;
_state = State_XRItem;
return true;
}
/* 0 1 2 3
/* DLRR Report Block.
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| BT=5 | reserved | block length |
@ -986,14 +976,28 @@ bool RTCPUtility::RTCPParserV2::ParseXRReceiverReferenceTimeItem() {
: ... : 2
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
*/
bool RTCPUtility::RTCPParserV2::ParseXrDlrr(int block_length_4bytes) {
const int kSubBlockLengthIn4Bytes = 3;
if (block_length_4bytes < 0 ||
(block_length_4bytes % kSubBlockLengthIn4Bytes) != 0) {
_state = State_TopLevel;
EndCurrentBlock();
return false;
}
_packetType = kRtcpXrDlrrReportBlockCode;
_state = State_XR_DLLRItem;
_numberOfBlocks = block_length_4bytes / kSubBlockLengthIn4Bytes;
return true;
}
bool RTCPUtility::RTCPParserV2::ParseXRDLRRReportBlockItem() {
const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
bool RTCPUtility::RTCPParserV2::ParseXrDlrrItem() {
if (_numberOfBlocks == 0) {
_state = State_XRItem;
return false;
}
if (length < 12) {
const int kSubBlockLengthInBytes = 12;
const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
if (length < kSubBlockLengthInBytes) {
_state = State_TopLevel;
EndCurrentBlock();
return false;
@ -1019,8 +1023,8 @@ bool RTCPUtility::RTCPParserV2::ParseXRDLRRReportBlockItem() {
_state = State_XR_DLLRItem;
return true;
}
/*
0 1 2 3
/* VoIP Metrics Report Block.
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| BT=7 | reserved | block length = 8 |
@ -1043,63 +1047,77 @@ bool RTCPUtility::RTCPParserV2::ParseXRDLRRReportBlockItem() {
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
bool
RTCPUtility::RTCPParserV2::ParseXRVOIPMetricItem()
{
const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
bool RTCPUtility::RTCPParserV2::ParseXrVoipMetricItem(int block_length_4bytes) {
const int kBlockLengthIn4Bytes = 8;
const int kBlockLengthInBytes = kBlockLengthIn4Bytes * 4;
const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
if (block_length_4bytes != kBlockLengthIn4Bytes ||
length < kBlockLengthInBytes) {
_state = State_TopLevel;
EndCurrentBlock();
return false;
}
if (length < 28)
{
_state = State_TopLevel;
EndCurrentBlock();
return false;
}
_packetType = kRtcpXrVoipMetricCode;
_packet.XRVOIPMetricItem.SSRC = *_ptrRTCPData++ << 24;
_packet.XRVOIPMetricItem.SSRC += *_ptrRTCPData++ << 16;
_packet.XRVOIPMetricItem.SSRC += *_ptrRTCPData++ << 8;
_packet.XRVOIPMetricItem.SSRC += *_ptrRTCPData++;
_packet.XRVOIPMetricItem.SSRC = *_ptrRTCPData++ << 24;
_packet.XRVOIPMetricItem.SSRC += *_ptrRTCPData++ << 16;
_packet.XRVOIPMetricItem.SSRC += *_ptrRTCPData++ << 8;
_packet.XRVOIPMetricItem.SSRC += *_ptrRTCPData++;
_packet.XRVOIPMetricItem.lossRate = *_ptrRTCPData++;
_packet.XRVOIPMetricItem.discardRate = *_ptrRTCPData++;
_packet.XRVOIPMetricItem.burstDensity = *_ptrRTCPData++;
_packet.XRVOIPMetricItem.gapDensity = *_ptrRTCPData++;
_packet.XRVOIPMetricItem.lossRate = *_ptrRTCPData++;
_packet.XRVOIPMetricItem.discardRate = *_ptrRTCPData++;
_packet.XRVOIPMetricItem.burstDensity = *_ptrRTCPData++;
_packet.XRVOIPMetricItem.gapDensity = *_ptrRTCPData++;
_packet.XRVOIPMetricItem.burstDuration = *_ptrRTCPData++ << 8;
_packet.XRVOIPMetricItem.burstDuration += *_ptrRTCPData++;
_packet.XRVOIPMetricItem.burstDuration = *_ptrRTCPData++ << 8;
_packet.XRVOIPMetricItem.burstDuration += *_ptrRTCPData++;
_packet.XRVOIPMetricItem.gapDuration = *_ptrRTCPData++ << 8;
_packet.XRVOIPMetricItem.gapDuration += *_ptrRTCPData++;
_packet.XRVOIPMetricItem.gapDuration = *_ptrRTCPData++ << 8;
_packet.XRVOIPMetricItem.gapDuration += *_ptrRTCPData++;
_packet.XRVOIPMetricItem.roundTripDelay = *_ptrRTCPData++ << 8;
_packet.XRVOIPMetricItem.roundTripDelay += *_ptrRTCPData++;
_packet.XRVOIPMetricItem.roundTripDelay = *_ptrRTCPData++ << 8;
_packet.XRVOIPMetricItem.roundTripDelay += *_ptrRTCPData++;
_packet.XRVOIPMetricItem.endSystemDelay = *_ptrRTCPData++ << 8;
_packet.XRVOIPMetricItem.endSystemDelay += *_ptrRTCPData++;
_packet.XRVOIPMetricItem.endSystemDelay = *_ptrRTCPData++ << 8;
_packet.XRVOIPMetricItem.endSystemDelay += *_ptrRTCPData++;
_packet.XRVOIPMetricItem.signalLevel = *_ptrRTCPData++;
_packet.XRVOIPMetricItem.noiseLevel = *_ptrRTCPData++;
_packet.XRVOIPMetricItem.RERL = *_ptrRTCPData++;
_packet.XRVOIPMetricItem.Gmin = *_ptrRTCPData++;
_packet.XRVOIPMetricItem.Rfactor = *_ptrRTCPData++;
_packet.XRVOIPMetricItem.extRfactor = *_ptrRTCPData++;
_packet.XRVOIPMetricItem.MOSLQ = *_ptrRTCPData++;
_packet.XRVOIPMetricItem.MOSCQ = *_ptrRTCPData++;
_packet.XRVOIPMetricItem.RXconfig = *_ptrRTCPData++;
_ptrRTCPData++; // skip reserved
_packet.XRVOIPMetricItem.signalLevel = *_ptrRTCPData++;
_packet.XRVOIPMetricItem.noiseLevel = *_ptrRTCPData++;
_packet.XRVOIPMetricItem.RERL = *_ptrRTCPData++;
_packet.XRVOIPMetricItem.Gmin = *_ptrRTCPData++;
_packet.XRVOIPMetricItem.Rfactor = *_ptrRTCPData++;
_packet.XRVOIPMetricItem.extRfactor = *_ptrRTCPData++;
_packet.XRVOIPMetricItem.MOSLQ = *_ptrRTCPData++;
_packet.XRVOIPMetricItem.MOSCQ = *_ptrRTCPData++;
_packet.XRVOIPMetricItem.RXconfig = *_ptrRTCPData++;
_ptrRTCPData++; // skip reserved
_packet.XRVOIPMetricItem.JBnominal = *_ptrRTCPData++ << 8;
_packet.XRVOIPMetricItem.JBnominal += *_ptrRTCPData++;
_packet.XRVOIPMetricItem.JBnominal = *_ptrRTCPData++ << 8;
_packet.XRVOIPMetricItem.JBnominal += *_ptrRTCPData++;
_packet.XRVOIPMetricItem.JBmax = *_ptrRTCPData++ << 8;
_packet.XRVOIPMetricItem.JBmax += *_ptrRTCPData++;
_packet.XRVOIPMetricItem.JBmax = *_ptrRTCPData++ << 8;
_packet.XRVOIPMetricItem.JBmax += *_ptrRTCPData++;
_packet.XRVOIPMetricItem.JBabsMax = *_ptrRTCPData++ << 8;
_packet.XRVOIPMetricItem.JBabsMax += *_ptrRTCPData++;
_packet.XRVOIPMetricItem.JBabsMax = *_ptrRTCPData++ << 8;
_packet.XRVOIPMetricItem.JBabsMax += *_ptrRTCPData++;
_packetType = kRtcpXrVoipMetricCode;
_state = State_XRItem;
return true;
}
_state = State_XRItem;
return true;
bool RTCPUtility::RTCPParserV2::ParseXrUnsupportedBlockType(
int block_length_4bytes) {
const int32_t kBlockLengthInBytes = block_length_4bytes * 4;
const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
if (length < kBlockLengthInBytes) {
_state = State_TopLevel;
EndCurrentBlock();
return false;
}
// Skip block.
_ptrRTCPData += kBlockLengthInBytes;
_state = State_XRItem;
return false;
}
bool

View File

@ -335,6 +335,13 @@ namespace RTCPUtility {
PT_XR = 207
};
// Extended report blocks, RFC 3611.
enum RtcpXrBlockType {
kBtReceiverReferenceTime = 4,
kBtDlrr = 5,
kBtVoipMetric = 7
};
bool RTCPParseCommonHeader( const uint8_t* ptrDataBegin,
const uint8_t* ptrDataEnd,
RTCPCommonHeader& parsedHeader);
@ -413,11 +420,13 @@ namespace RTCPUtility {
bool ParseIJ();
bool ParseIJItem();
bool ParseXR();
bool ParseXRItem();
bool ParseXRReceiverReferenceTimeItem();
bool ParseXRDLRRReportBlockItem();
bool ParseXRVOIPMetricItem();
bool ParseXr();
bool ParseXrItem();
bool ParseXrReceiverReferenceTimeItem(int block_length_4bytes);
bool ParseXrDlrr(int block_length_4bytes);
bool ParseXrDlrrItem();
bool ParseXrVoipMetricItem(int block_length_4bytes);
bool ParseXrUnsupportedBlockType(int block_length_4bytes);
bool ParseFBCommon(const RTCPCommonHeader& header);
bool ParseNACKItem();