Chromium Code Reviews| Index: webrtc/modules/rtp_rtcp/source/rtcp_utility.cc |
| diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_utility.cc b/webrtc/modules/rtp_rtcp/source/rtcp_utility.cc |
| index 4e37cf3716d916c7ecb1bfd6185b1790dfa15f5f..29b82009d8ea607c468dd2375630c37796e4baa9 100644 |
| --- a/webrtc/modules/rtp_rtcp/source/rtcp_utility.cc |
| +++ b/webrtc/modules/rtp_rtcp/source/rtcp_utility.cc |
| @@ -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; |
| - |
| - const bool success = RTCPParseCommonHeader(_ptrRTCPData, |
| - _ptrRTCPDataEnd, |
| - header); |
| + RtcpCommonHeader header; |
| + if (_ptrRTCPDataEnd <= _ptrRTCPData) |
| + return; |
| - 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,69 @@ 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. |
| +// 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); |
| + const size_t kHeaderLength = 4; |
|
åsapersson
2015/09/10 13:27:33
use define in RtcpCommonHeader?
sprang_webrtc
2015/09/11 13:03:19
Done.
|
| + if (size_bytes < kHeaderLength) { |
| + LOG(LS_WARNING) << "Too little data (" << size_bytes << " byte" |
| + << (size_bytes != 1 ? "s" : "") |
| + << ") remaining in buffer to parse RTCP header (4 bytes)."; |
| + return false; |
| + } |
| - if ((ptrDataEnd - ptrDataBegin) < 4) |
| - { |
| - 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; |
| + } |
| - parsedHeader.V = ptrDataBegin[0] >> 6; |
| - parsedHeader.P = ((ptrDataBegin[0] & 0x20) == 0) ? false : true; |
| - parsedHeader.IC = ptrDataBegin[0] & 0x1f; |
| - parsedHeader.PT = ptrDataBegin[1]; |
| + 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; |
| - parsedHeader.LengthInOctets = (ptrDataBegin[2] << 8) + ptrDataBegin[3] + 1; |
| - parsedHeader.LengthInOctets *= 4; |
| + 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; |
| + } |
| - if(parsedHeader.LengthInOctets == 0) |
| - { |
| - return false; |
| - } |
| - // Check if RTP version field == 2 |
| - if (parsedHeader.V != 2) |
| - { |
| - return false; |
| + size_t payload_size = packet_size_words * 4; |
| + size_t padding_bytes = 0; |
| + if (has_padding) { |
| + padding_bytes = packet[payload_size - 1]; |
|
åsapersson
2015/09/10 13:27:33
if size_bytes is 4 and packet_size_words is 1 (len
sprang_webrtc
2015/09/11 13:03:19
Done.
Good catch!
|
| + if (kHeaderLength + 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 -= kHeaderLength; |
| - return true; |
| + 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; |
| + |
| + return true; |
| } |
| bool |
| @@ -1137,10 +1154,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 +1178,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 +1236,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 +1590,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 +1615,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 +1660,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; |