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

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: Addressed comments, rebase 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 629 matching lines...) Expand 10 before | Expand all | Expand 10 after
655 size_t length) { 656 size_t length) {
656 rtc::scoped_ptr<TransportFeedback> packet(new TransportFeedback()); 657 rtc::scoped_ptr<TransportFeedback> packet(new TransportFeedback());
657 658
658 if (length < kMinSizeBytes) { 659 if (length < kMinSizeBytes) {
659 LOG(LS_WARNING) << "Buffer too small (" << length 660 LOG(LS_WARNING) << "Buffer too small (" << length
660 << " bytes) to fit a " 661 << " bytes) to fit a "
661 "FeedbackPacket. Minimum size = " << kMinSizeBytes; 662 "FeedbackPacket. Minimum size = " << kMinSizeBytes;
662 return nullptr; 663 return nullptr;
663 } 664 }
664 665
665 size_t packet_size_words = 666 RTCPUtility::RtcpCommonHeader header;
666 ByteReader<uint16_t>::ReadBigEndian(&buffer[2]) + 1; 667 if (!RtcpParseCommonHeader(buffer, length, &header))
667 if (length < packet_size_words * 4) { 668 return nullptr;
668 LOG(LS_WARNING) << "Buffer too small (" << length 669
669 << " bytes) to fit a FeedbackPacket of " 670 if (header.count_or_format != kFeedbackMessageType) {
670 << packet_size_words << " 32bit words."; 671 LOG(LS_WARNING) << "Invalid RTCP header: FMT must be "
672 << kFeedbackMessageType << " but was "
673 << header.count_or_format;
671 return nullptr; 674 return nullptr;
672 } 675 }
673 676
674 // TODO(sprang): Break this out and generalize when implementing parsing of 677 if (header.packet_type != kPayloadType) {
675 // other RtcpPacket subclasses. 678 LOG(LS_WARNING) << "Invalid RTCP header: PT must be " << kPayloadType
676 679 << " but was " << header.packet_type;
677 const uint8_t kRtcpVersion = 2;
678 uint8_t version = buffer[0] >> 6;
679 if (version != kRtcpVersion) {
680 LOG(LS_WARNING) << "Invalid RTCP header: Version must be " << kRtcpVersion
681 << " but was " << version;
682 return nullptr; 680 return nullptr;
683 } 681 }
684 682
685 bool has_padding = (buffer[0] & 0x20) != 0;
686
687 uint8_t format = buffer[0] & 0x1F;
688 if (format != kFeedbackMessageType) {
689 LOG(LS_WARNING) << "Invalid RTCP header: FMT must be "
690 << kFeedbackMessageType << " but was " << format;
691 return nullptr;
692 }
693
694 uint8_t payload_type = buffer[1];
695 if (payload_type != kPayloadType) {
696 LOG(LS_WARNING) << "Invalid RTCP header: PT must be " << kPayloadType
697 << " but was " << payload_type;
698 return nullptr;
699 }
700
701 size_t payload_size = packet_size_words * 4;
702 if (has_padding) {
703 uint8_t padding_bytes = buffer[payload_size - 1];
704 if (payload_size < kMinSizeBytes + padding_bytes) {
705 LOG(LS_WARNING) << "Invalid RTCP header: Too many padding bytes ("
706 << padding_bytes << ") for a packet size of "
707 << payload_size << "bytes.";
708 return nullptr;
709 }
710 payload_size -= padding_bytes;
711 }
712
713 packet->packet_sender_ssrc_ = ByteReader<uint32_t>::ReadBigEndian(&buffer[4]); 683 packet->packet_sender_ssrc_ = ByteReader<uint32_t>::ReadBigEndian(&buffer[4]);
714 packet->media_source_ssrc_ = ByteReader<uint32_t>::ReadBigEndian(&buffer[8]); 684 packet->media_source_ssrc_ = ByteReader<uint32_t>::ReadBigEndian(&buffer[8]);
715 packet->base_seq_ = ByteReader<uint16_t>::ReadBigEndian(&buffer[12]); 685 packet->base_seq_ = ByteReader<uint16_t>::ReadBigEndian(&buffer[12]);
716 uint16_t num_packets = ByteReader<uint16_t>::ReadBigEndian(&buffer[14]); 686 uint16_t num_packets = ByteReader<uint16_t>::ReadBigEndian(&buffer[14]);
717 packet->base_time_ = ByteReader<int32_t, 3>::ReadBigEndian(&buffer[16]); 687 packet->base_time_ = ByteReader<int32_t, 3>::ReadBigEndian(&buffer[16]);
718 packet->feedback_seq_ = buffer[19]; 688 packet->feedback_seq_ = buffer[19];
719 size_t index = 20; 689 size_t index = 20;
690 const size_t end_index = kHeaderLength + header.payload_size_bytes;
720 691
721 if (num_packets == 0) { 692 if (num_packets == 0) {
722 LOG(LS_WARNING) << "Empty feedback messages not allowed."; 693 LOG(LS_WARNING) << "Empty feedback messages not allowed.";
723 return nullptr; 694 return nullptr;
724 } 695 }
725 packet->last_seq_ = packet->base_seq_ + num_packets - 1; 696 packet->last_seq_ = packet->base_seq_ + num_packets - 1;
726 697
727 size_t packets_read = 0; 698 size_t packets_read = 0;
728 while (packets_read < num_packets) { 699 while (packets_read < num_packets) {
729 if (index + 2 > payload_size) { 700 if (index + 2 > end_index) {
730 LOG(LS_WARNING) << "Buffer overflow while parsing packet."; 701 LOG(LS_WARNING) << "Buffer overflow while parsing packet.";
731 return nullptr; 702 return nullptr;
732 } 703 }
733 704
734 PacketStatusChunk* chunk = 705 PacketStatusChunk* chunk =
735 ParseChunk(&buffer[index], num_packets - packets_read); 706 ParseChunk(&buffer[index], num_packets - packets_read);
736 if (chunk == nullptr) 707 if (chunk == nullptr)
737 return nullptr; 708 return nullptr;
738 709
739 index += 2; 710 index += 2;
740 packet->status_chunks_.push_back(chunk); 711 packet->status_chunks_.push_back(chunk);
741 packets_read += chunk->NumSymbols(); 712 packets_read += chunk->NumSymbols();
742 } 713 }
743 714
744 std::vector<StatusSymbol> symbols = packet->GetStatusVector(); 715 std::vector<StatusSymbol> symbols = packet->GetStatusVector();
745 716
746 DCHECK_EQ(num_packets, symbols.size()); 717 DCHECK_EQ(num_packets, symbols.size());
747 718
748 for (StatusSymbol symbol : symbols) { 719 for (StatusSymbol symbol : symbols) {
749 switch (symbol) { 720 switch (symbol) {
750 case StatusSymbol::kReceivedSmallDelta: 721 case StatusSymbol::kReceivedSmallDelta:
751 if (index + 1 > payload_size) { 722 if (index + 1 > end_index) {
752 LOG(LS_WARNING) << "Buffer overflow while parsing packet."; 723 LOG(LS_WARNING) << "Buffer overflow while parsing packet.";
753 return nullptr; 724 return nullptr;
754 } 725 }
755 packet->receive_deltas_.push_back(buffer[index]); 726 packet->receive_deltas_.push_back(buffer[index]);
756 ++index; 727 ++index;
757 break; 728 break;
758 case StatusSymbol::kReceivedLargeDelta: 729 case StatusSymbol::kReceivedLargeDelta:
759 if (index + 2 > payload_size) { 730 if (index + 2 > end_index) {
760 LOG(LS_WARNING) << "Buffer overflow while parsing packet."; 731 LOG(LS_WARNING) << "Buffer overflow while parsing packet.";
761 return nullptr; 732 return nullptr;
762 } 733 }
763 packet->receive_deltas_.push_back( 734 packet->receive_deltas_.push_back(
764 ByteReader<int16_t>::ReadBigEndian(&buffer[index])); 735 ByteReader<int16_t>::ReadBigEndian(&buffer[index]));
765 index += 2; 736 index += 2;
766 break; 737 break;
767 default: 738 default:
768 continue; 739 continue;
769 } 740 }
770 } 741 }
771 742
772 DCHECK_GE(index, payload_size - 3); 743 DCHECK_GE(index, end_index - 3);
773 DCHECK_LE(index, payload_size); 744 DCHECK_LE(index, end_index);
774 745
775 return packet; 746 return packet;
776 } 747 }
777 748
778 PacketStatusChunk* TransportFeedback::ParseChunk(const uint8_t* buffer, 749 PacketStatusChunk* TransportFeedback::ParseChunk(const uint8_t* buffer,
779 size_t max_size) { 750 size_t max_size) {
780 if (buffer[0] & 0x80) { 751 if (buffer[0] & 0x80) {
781 // First bit set => vector chunk. 752 // First bit set => vector chunk.
782 std::deque<StatusSymbol> symbols; 753 std::deque<StatusSymbol> symbols;
783 if (buffer[0] & 0x40) { 754 if (buffer[0] & 0x40) {
(...skipping 12 matching lines...) Expand all
796 "RLE block of size " << rle_chunk->NumSymbols() 767 "RLE block of size " << rle_chunk->NumSymbols()
797 << " but only " << max_size << " left to read."; 768 << " but only " << max_size << " left to read.";
798 delete rle_chunk; 769 delete rle_chunk;
799 return nullptr; 770 return nullptr;
800 } 771 }
801 return rle_chunk; 772 return rle_chunk;
802 } 773 }
803 774
804 } // namespace rtcp 775 } // namespace rtcp
805 } // namespace webrtc 776 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/modules/rtp_rtcp/source/rtcp_packet.cc ('k') | webrtc/modules/rtp_rtcp/source/rtcp_utility.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698