OLD | NEW |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |