Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(199)

Side by Side Diff: webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.cc

Issue 1307663004: Add a ParseHeader method to RtcpPacket, for parsing common RTCP header. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Merged RtcpPacket header parsing with RTCPUtility Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h" 11 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
12 12
13 #include "webrtc/base/checks.h" 13 #include "webrtc/base/checks.h"
14 #include "webrtc/base/logging.h" 14 #include "webrtc/base/logging.h"
15 #include "webrtc/modules/rtp_rtcp/source/byte_io.h" 15 #include "webrtc/modules/rtp_rtcp/source/byte_io.h"
16 #include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
16 17
17 namespace webrtc { 18 namespace webrtc {
18 namespace rtcp { 19 namespace rtcp {
19 20
20 // Header size: 21 // Header size:
21 // * 12 bytes Common Packet Format for RTCP Feedback Messages 22 // * 12 bytes Common Packet Format for RTCP Feedback Messages
22 // * 8 bytes FeedbackPacket header 23 // * 8 bytes FeedbackPacket header
23 static const uint32_t kHeaderSizeBytes = 12 + 8; 24 static const uint32_t kHeaderSizeBytes = 12 + 8;
24 static const uint32_t kChunkSizeBytes = 2; 25 static const uint32_t kChunkSizeBytes = 2;
25 static const uint32_t kOneBitVectorCapacity = 14; 26 static const uint32_t kOneBitVectorCapacity = 14;
(...skipping 626 matching lines...) Expand 10 before | Expand all | Expand 10 after
652 size_t length) { 653 size_t length) {
653 rtc::scoped_ptr<TransportFeedback> packet(new TransportFeedback()); 654 rtc::scoped_ptr<TransportFeedback> packet(new TransportFeedback());
654 655
655 if (length < kMinSizeBytes) { 656 if (length < kMinSizeBytes) {
656 LOG(LS_WARNING) << "Buffer too small (" << length 657 LOG(LS_WARNING) << "Buffer too small (" << length
657 << " bytes) to fit a " 658 << " bytes) to fit a "
658 "FeedbackPacket. Minimum size = " << kMinSizeBytes; 659 "FeedbackPacket. Minimum size = " << kMinSizeBytes;
659 return nullptr; 660 return nullptr;
660 } 661 }
661 662
662 size_t packet_size_words = 663 RTCPUtility::RtcpCommonHeader header;
663 ByteReader<uint16_t>::ReadBigEndian(&buffer[2]) + 1; 664 if (!RtcpParseCommonHeader(buffer, 0, length, &header))
664 if (length < packet_size_words * 4) { 665 return nullptr;
665 LOG(LS_WARNING) << "Buffer too small (" << length 666
666 << " bytes) to fit a FeedbackPacket of " 667 if (header.count_or_format != kFeedbackMessageType) {
667 << packet_size_words << " 32bit words."; 668 LOG(LS_WARNING) << "Invalid RTCP header: FMT must be "
669 << kFeedbackMessageType << " but was "
670 << header.count_or_format;
668 return nullptr; 671 return nullptr;
669 } 672 }
670 673
671 // TODO(sprang): Break this out and generalize when implementing parsing of 674 if (header.packet_type != kPayloadType) {
672 // other RtcpPacket subclasses. 675 LOG(LS_WARNING) << "Invalid RTCP header: PT must be " << kPayloadType
673 676 << " but was " << header.packet_type;
674 const uint8_t kRtcpVersion = 2;
675 uint8_t version = buffer[0] >> 6;
676 if (version != kRtcpVersion) {
677 LOG(LS_WARNING) << "Invalid RTCP header: Version must be " << kRtcpVersion
678 << " but was " << version;
679 return nullptr; 677 return nullptr;
680 } 678 }
681 679
682 bool has_padding = (buffer[0] & 0x20) != 0;
683
684 uint8_t format = buffer[0] & 0x1F;
685 if (format != kFeedbackMessageType) {
686 LOG(LS_WARNING) << "Invalid RTCP header: FMT must be "
687 << kFeedbackMessageType << " but was " << format;
688 return nullptr;
689 }
690
691 uint8_t payload_type = buffer[1];
692 if (payload_type != kPayloadType) {
693 LOG(LS_WARNING) << "Invalid RTCP header: PT must be " << kPayloadType
694 << " but was " << payload_type;
695 return nullptr;
696 }
697
698 size_t payload_size = packet_size_words * 4;
699 if (has_padding) {
700 uint8_t padding_bytes = buffer[payload_size - 1];
701 if (payload_size < kMinSizeBytes + padding_bytes) {
702 LOG(LS_WARNING) << "Invalid RTCP header: Too many padding bytes ("
703 << padding_bytes << ") for a packet size of "
704 << payload_size << "bytes.";
705 return nullptr;
706 }
707 payload_size -= padding_bytes;
708 }
709
710 packet->packet_sender_ssrc_ = ByteReader<uint32_t>::ReadBigEndian(&buffer[4]); 680 packet->packet_sender_ssrc_ = ByteReader<uint32_t>::ReadBigEndian(&buffer[4]);
711 packet->media_source_ssrc_ = ByteReader<uint32_t>::ReadBigEndian(&buffer[8]); 681 packet->media_source_ssrc_ = ByteReader<uint32_t>::ReadBigEndian(&buffer[8]);
712 packet->base_seq_ = ByteReader<uint16_t>::ReadBigEndian(&buffer[12]); 682 packet->base_seq_ = ByteReader<uint16_t>::ReadBigEndian(&buffer[12]);
713 uint16_t num_packets = ByteReader<uint16_t>::ReadBigEndian(&buffer[14]); 683 uint16_t num_packets = ByteReader<uint16_t>::ReadBigEndian(&buffer[14]);
714 packet->base_time_ = ByteReader<int32_t, 3>::ReadBigEndian(&buffer[16]); 684 packet->base_time_ = ByteReader<int32_t, 3>::ReadBigEndian(&buffer[16]);
715 packet->feedback_seq_ = buffer[19]; 685 packet->feedback_seq_ = buffer[19];
716 size_t index = 20; 686 size_t index = 20;
687 const size_t end_index = kHeaderLength + header.payload_size_bytes;
717 688
718 if (num_packets == 0) { 689 if (num_packets == 0) {
719 LOG(LS_WARNING) << "Empty feedback messages not allowed."; 690 LOG(LS_WARNING) << "Empty feedback messages not allowed.";
720 return nullptr; 691 return nullptr;
721 } 692 }
722 packet->last_seq_ = packet->base_seq_ + num_packets - 1; 693 packet->last_seq_ = packet->base_seq_ + num_packets - 1;
723 694
724 size_t packets_read = 0; 695 size_t packets_read = 0;
725 while (packets_read < num_packets) { 696 while (packets_read < num_packets) {
726 if (index + 2 > payload_size) { 697 if (index + 2 > end_index) {
727 LOG(LS_WARNING) << "Buffer overflow while parsing packet."; 698 LOG(LS_WARNING) << "Buffer overflow while parsing packet.";
728 return nullptr; 699 return nullptr;
729 } 700 }
730 701
731 PacketStatusChunk* chunk = 702 PacketStatusChunk* chunk =
732 ParseChunk(&buffer[index], num_packets - packets_read); 703 ParseChunk(&buffer[index], num_packets - packets_read);
733 if (chunk == nullptr) 704 if (chunk == nullptr)
734 return nullptr; 705 return nullptr;
735 706
736 index += 2; 707 index += 2;
737 packet->status_chunks_.push_back(chunk); 708 packet->status_chunks_.push_back(chunk);
738 packets_read += chunk->NumSymbols(); 709 packets_read += chunk->NumSymbols();
739 } 710 }
740 711
741 std::vector<StatusSymbol> symbols = packet->GetStatusVector(); 712 std::vector<StatusSymbol> symbols = packet->GetStatusVector();
742 713
743 DCHECK_EQ(num_packets, symbols.size()); 714 DCHECK_EQ(num_packets, symbols.size());
744 715
745 for (StatusSymbol symbol : symbols) { 716 for (StatusSymbol symbol : symbols) {
746 switch (symbol) { 717 switch (symbol) {
747 case StatusSymbol::kReceivedSmallDelta: 718 case StatusSymbol::kReceivedSmallDelta:
748 if (index + 1 > payload_size) { 719 if (index + 1 > end_index) {
749 LOG(LS_WARNING) << "Buffer overflow while parsing packet."; 720 LOG(LS_WARNING) << "Buffer overflow while parsing packet.";
750 return nullptr; 721 return nullptr;
751 } 722 }
752 packet->receive_deltas_.push_back(buffer[index]); 723 packet->receive_deltas_.push_back(buffer[index]);
753 ++index; 724 ++index;
754 break; 725 break;
755 case StatusSymbol::kReceivedLargeDelta: 726 case StatusSymbol::kReceivedLargeDelta:
756 if (index + 2 > payload_size) { 727 if (index + 2 > end_index) {
757 LOG(LS_WARNING) << "Buffer overflow while parsing packet."; 728 LOG(LS_WARNING) << "Buffer overflow while parsing packet.";
758 return nullptr; 729 return nullptr;
759 } 730 }
760 packet->receive_deltas_.push_back( 731 packet->receive_deltas_.push_back(
761 ByteReader<int16_t>::ReadBigEndian(&buffer[index])); 732 ByteReader<int16_t>::ReadBigEndian(&buffer[index]));
762 index += 2; 733 index += 2;
763 break; 734 break;
764 default: 735 default:
765 continue; 736 continue;
766 } 737 }
767 } 738 }
768 739
769 DCHECK_GE(index, payload_size - 3); 740 DCHECK_GE(index, end_index - 3);
770 DCHECK_LE(index, payload_size); 741 DCHECK_LE(index, end_index);
771 742
772 return packet; 743 return packet;
773 } 744 }
774 745
775 PacketStatusChunk* TransportFeedback::ParseChunk(const uint8_t* buffer, 746 PacketStatusChunk* TransportFeedback::ParseChunk(const uint8_t* buffer,
776 size_t max_size) { 747 size_t max_size) {
777 if (buffer[0] & 0x80) { 748 if (buffer[0] & 0x80) {
778 // First bit set => vector chunk. 749 // First bit set => vector chunk.
779 std::deque<StatusSymbol> symbols; 750 std::deque<StatusSymbol> symbols;
780 if (buffer[0] & 0x40) { 751 if (buffer[0] & 0x40) {
(...skipping 12 matching lines...) Expand all
793 "RLE block of size " << rle_chunk->NumSymbols() 764 "RLE block of size " << rle_chunk->NumSymbols()
794 << " but only " << max_size << " left to read."; 765 << " but only " << max_size << " left to read.";
795 delete rle_chunk; 766 delete rle_chunk;
796 return nullptr; 767 return nullptr;
797 } 768 }
798 return rle_chunk; 769 return rle_chunk;
799 } 770 }
800 771
801 } // namespace rtcp 772 } // namespace rtcp
802 } // namespace webrtc 773 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698