Add a ParseHeader method to RtcpPacket, for parsing common RTCP header.

Also refactor TransportFeedback to use this.

BUG=

Review URL: https://codereview.webrtc.org/1307663004

Cr-Commit-Position: refs/heads/master@{#9935}
This commit is contained in:
sprang
2015-09-14 12:50:39 -07:00
committed by Commit bot
parent 1cb121dea4
commit 73a93e8257
6 changed files with 249 additions and 169 deletions

View File

@ -14,6 +14,10 @@
#include <math.h> // ceil
#include <string.h> // memcpy
#include "webrtc/base/checks.h"
#include "webrtc/base/logging.h"
#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
namespace webrtc {
namespace RTCPUtility {
@ -155,43 +159,40 @@ RTCPUtility::RTCPParserV2::IterateTopLevel()
{
for (;;)
{
RTCPCommonHeader header;
RtcpCommonHeader header;
if (_ptrRTCPDataEnd <= _ptrRTCPData)
return;
const bool success = RTCPParseCommonHeader(_ptrRTCPData,
_ptrRTCPDataEnd,
header);
if (!success)
{
if (!RtcpParseCommonHeader(_ptrRTCPData, _ptrRTCPDataEnd - _ptrRTCPData,
&header)) {
return;
}
_ptrRTCPBlockEnd = _ptrRTCPData + header.LengthInOctets;
_ptrRTCPBlockEnd = _ptrRTCPData + header.BlockSize();
if (_ptrRTCPBlockEnd > _ptrRTCPDataEnd)
{
// Bad block!
return;
}
switch (header.PT)
{
switch (header.packet_type) {
case PT_SR:
{
// number of Report blocks
_numberOfBlocks = header.IC;
_numberOfBlocks = header.count_or_format;
ParseSR();
return;
}
case PT_RR:
{
// number of Report blocks
_numberOfBlocks = header.IC;
_numberOfBlocks = header.count_or_format;
ParseRR();
return;
}
case PT_SDES:
{
// number of SDES blocks
_numberOfBlocks = header.IC;
_numberOfBlocks = header.count_or_format;
const bool ok = ParseSDES();
if (!ok)
{
@ -202,7 +203,7 @@ RTCPUtility::RTCPParserV2::IterateTopLevel()
}
case PT_BYE:
{
_numberOfBlocks = header.IC;
_numberOfBlocks = header.count_or_format;
const bool ok = ParseBYE();
if (!ok)
{
@ -214,7 +215,7 @@ RTCPUtility::RTCPParserV2::IterateTopLevel()
case PT_IJ:
{
// number of Report blocks
_numberOfBlocks = header.IC;
_numberOfBlocks = header.count_or_format;
ParseIJ();
return;
}
@ -410,20 +411,16 @@ RTCPUtility::RTCPParserV2::IterateAppItem()
void
RTCPUtility::RTCPParserV2::Validate()
{
if (_ptrRTCPData == NULL)
{
return; // NOT VALID
}
if (_ptrRTCPData == nullptr)
return; // NOT VALID
RTCPCommonHeader header;
const bool success = RTCPParseCommonHeader(_ptrRTCPDataBegin,
_ptrRTCPDataEnd,
header);
RtcpCommonHeader header;
if (_ptrRTCPDataEnd <= _ptrRTCPDataBegin)
return; // NOT VALID
if (!success)
{
return; // NOT VALID!
}
if (!RtcpParseCommonHeader(_ptrRTCPDataBegin,
_ptrRTCPDataEnd - _ptrRTCPDataBegin, &header))
return; // NOT VALID!
// * if (!reducedSize) : first packet must be RR or SR.
//
@ -437,8 +434,7 @@ RTCPUtility::RTCPParserV2::Validate()
if (!_RTCPReducedSizeEnable)
{
if ((header.PT != PT_SR) && (header.PT != PT_RR))
{
if ((header.packet_type != PT_SR) && (header.packet_type != PT_RR)) {
return; // NOT VALID
}
}
@ -458,48 +454,74 @@ RTCPUtility::RTCPParserV2::EndCurrentBlock()
_ptrRTCPData = _ptrRTCPBlockEnd;
}
bool
RTCPUtility::RTCPParseCommonHeader( const uint8_t* ptrDataBegin,
const uint8_t* ptrDataEnd,
RTCPCommonHeader& parsedHeader)
{
if (!ptrDataBegin || !ptrDataEnd)
{
return false;
// 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| IC | PT | length |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//
// Common header for all RTCP packets, 4 octets.
bool RTCPUtility::RtcpParseCommonHeader(const uint8_t* packet,
size_t size_bytes,
RtcpCommonHeader* parsed_header) {
DCHECK(parsed_header != nullptr);
if (size_bytes < RtcpCommonHeader::kHeaderSizeBytes) {
LOG(LS_WARNING) << "Too little data (" << size_bytes << " byte"
<< (size_bytes != 1 ? "s" : "")
<< ") remaining in buffer to parse RTCP header (4 bytes).";
return false;
}
const uint8_t kRtcpVersion = 2;
uint8_t version = packet[0] >> 6;
if (version != kRtcpVersion) {
LOG(LS_WARNING) << "Invalid RTCP header: Version must be "
<< static_cast<int>(kRtcpVersion) << " but was "
<< static_cast<int>(version);
return false;
}
bool has_padding = (packet[0] & 0x20) != 0;
uint8_t format = packet[0] & 0x1F;
uint8_t packet_type = packet[1];
size_t packet_size_words =
ByteReader<uint16_t>::ReadBigEndian(&packet[2]) + 1;
if (size_bytes < packet_size_words * 4) {
LOG(LS_WARNING) << "Buffer too small (" << size_bytes
<< " bytes) to fit an RtcpPacket of " << packet_size_words
<< " 32bit words.";
return false;
}
size_t payload_size = packet_size_words * 4;
size_t padding_bytes = 0;
if (has_padding) {
if (payload_size <= RtcpCommonHeader::kHeaderSizeBytes) {
LOG(LS_WARNING) << "Invalid RTCP header: Padding bit set but 0 payload "
"size specified.";
return false;
}
// 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| IC | PT | length |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//
// Common header for all RTCP packets, 4 octets.
if ((ptrDataEnd - ptrDataBegin) < 4)
{
return false;
padding_bytes = packet[payload_size - 1];
if (RtcpCommonHeader::kHeaderSizeBytes + padding_bytes > payload_size) {
LOG(LS_WARNING) << "Invalid RTCP header: Too many padding bytes ("
<< padding_bytes << ") for a packet size of "
<< payload_size << "bytes.";
return false;
}
payload_size -= padding_bytes;
}
payload_size -= RtcpCommonHeader::kHeaderSizeBytes;
parsedHeader.V = ptrDataBegin[0] >> 6;
parsedHeader.P = ((ptrDataBegin[0] & 0x20) == 0) ? false : true;
parsedHeader.IC = ptrDataBegin[0] & 0x1f;
parsedHeader.PT = ptrDataBegin[1];
parsed_header->version = kRtcpVersion;
parsed_header->count_or_format = format;
parsed_header->packet_type = packet_type;
parsed_header->payload_size_bytes = payload_size;
parsed_header->padding_bytes = padding_bytes;
parsedHeader.LengthInOctets = (ptrDataBegin[2] << 8) + ptrDataBegin[3] + 1;
parsedHeader.LengthInOctets *= 4;
if(parsedHeader.LengthInOctets == 0)
{
return false;
}
// Check if RTP version field == 2
if (parsedHeader.V != 2)
{
return false;
}
return true;
return true;
}
bool
@ -1137,10 +1159,9 @@ bool RTCPUtility::RTCPParserV2::ParseXrUnsupportedBlockType(
return false;
}
bool
RTCPUtility::RTCPParserV2::ParseFBCommon(const RTCPCommonHeader& header)
{
assert((header.PT == PT_RTPFB) || (header.PT == PT_PSFB)); // Parser logic check
bool RTCPUtility::RTCPParserV2::ParseFBCommon(const RtcpCommonHeader& header) {
assert((header.packet_type == PT_RTPFB) ||
(header.packet_type == PT_PSFB)); // Parser logic check
const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
@ -1162,12 +1183,10 @@ RTCPUtility::RTCPParserV2::ParseFBCommon(const RTCPCommonHeader& header)
mediaSSRC += *_ptrRTCPData++ << 8;
mediaSSRC += *_ptrRTCPData++;
if (header.PT == PT_RTPFB)
{
if (header.packet_type == PT_RTPFB) {
// Transport layer feedback
switch (header.IC)
{
switch (header.count_or_format) {
case 1:
{
// NACK
@ -1222,12 +1241,9 @@ RTCPUtility::RTCPParserV2::ParseFBCommon(const RTCPCommonHeader& header)
}
EndCurrentBlock();
return false;
}
else if (header.PT == PT_PSFB)
{
} else if (header.packet_type == PT_PSFB) {
// Payload specific feedback
switch (header.IC)
{
switch (header.count_or_format) {
case 1:
// PLI
_packetType = RTCPPacketTypes::kPsfbPli;
@ -1579,9 +1595,7 @@ RTCPUtility::RTCPParserV2::ParseFIRItem()
return true;
}
bool
RTCPUtility::RTCPParserV2::ParseAPP( const RTCPCommonHeader& header)
{
bool RTCPUtility::RTCPParserV2::ParseAPP(const RtcpCommonHeader& header) {
ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
if (length < 12) // 4 * 3, RFC 3550 6.7 APP: Application-Defined RTCP Packet
@ -1606,7 +1620,7 @@ RTCPUtility::RTCPParserV2::ParseAPP( const RTCPCommonHeader& header)
_packetType = RTCPPacketTypes::kApp;
_packet.APP.SubType = header.IC;
_packet.APP.SubType = header.count_or_format;
_packet.APP.Name = name;
_state = ParseState::State_AppItem;
@ -1651,37 +1665,31 @@ RTCPUtility::RTCPPacketIterator::RTCPPacketIterator(uint8_t* rtcpData,
RTCPUtility::RTCPPacketIterator::~RTCPPacketIterator() {
}
const RTCPUtility::RTCPCommonHeader*
RTCPUtility::RTCPPacketIterator::Begin()
{
const RTCPUtility::RtcpCommonHeader* RTCPUtility::RTCPPacketIterator::Begin() {
_ptrBlock = _ptrBegin;
return Iterate();
}
const RTCPUtility::RTCPCommonHeader*
RTCPUtility::RTCPPacketIterator::Iterate()
{
const bool success = RTCPParseCommonHeader(_ptrBlock, _ptrEnd, _header);
if (!success)
{
_ptrBlock = NULL;
return NULL;
}
_ptrBlock += _header.LengthInOctets;
const RTCPUtility::RtcpCommonHeader*
RTCPUtility::RTCPPacketIterator::Iterate() {
if ((_ptrEnd <= _ptrBlock) ||
!RtcpParseCommonHeader(_ptrBlock, _ptrEnd - _ptrBlock, &_header)) {
_ptrBlock = nullptr;
return nullptr;
}
_ptrBlock += _header.BlockSize();
if (_ptrBlock > _ptrEnd)
{
_ptrBlock = NULL;
return NULL;
}
if (_ptrBlock > _ptrEnd) {
_ptrBlock = nullptr;
return nullptr;
}
return &_header;
return &_header;
}
const RTCPUtility::RTCPCommonHeader*
RTCPUtility::RTCPPacketIterator::Current()
{
const RTCPUtility::RtcpCommonHeader*
RTCPUtility::RTCPPacketIterator::Current() {
if (!_ptrBlock)
{
return NULL;