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