mediapacket.cpp (3681B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "mediapacket.h" 8 9 #include <cstring> 10 11 #include "ipc/IPCMessageUtils.h" 12 13 namespace mozilla { 14 15 void MediaPacket::Copy(const uint8_t* data, size_t len, size_t capacity) { 16 if (capacity < len) { 17 capacity = len; 18 } 19 data_.reset(new uint8_t[capacity]); 20 len_ = len; 21 capacity_ = capacity; 22 memcpy(data_.get(), data, len); 23 } 24 25 MediaPacket::MediaPacket(const MediaPacket& orig) 26 : sdp_level_(orig.sdp_level_), type_(orig.type_) { 27 Copy(orig.data_.get(), orig.len_, orig.capacity_); 28 } 29 30 MediaPacket MediaPacket::Clone() const { return MediaPacket(*this); } 31 32 void MediaPacket::Serialize(IPC::MessageWriter* aWriter) const { 33 aWriter->WriteUInt32(len_); 34 aWriter->WriteUInt32(capacity_); 35 if (len_) { 36 aWriter->WriteBytes(data_.get(), len_); 37 } 38 aWriter->WriteUInt32(encrypted_len_); 39 if (encrypted_len_) { 40 aWriter->WriteBytes(encrypted_data_.get(), encrypted_len_); 41 } 42 aWriter->WriteInt32(sdp_level_.isSome() ? *sdp_level_ : -1); 43 aWriter->WriteInt32(type_); 44 } 45 46 bool MediaPacket::Deserialize(IPC::MessageReader* aReader) { 47 Reset(); 48 uint32_t len; 49 if (!aReader->ReadUInt32(&len)) { 50 return false; 51 } 52 uint32_t capacity; 53 if (!aReader->ReadUInt32(&capacity)) { 54 return false; 55 } 56 if (len) { 57 MOZ_RELEASE_ASSERT(capacity >= len); 58 UniquePtr<uint8_t[]> data(new uint8_t[capacity]); 59 if (!aReader->ReadBytesInto(data.get(), len)) { 60 return false; 61 } 62 data_ = std::move(data); 63 len_ = len; 64 capacity_ = capacity; 65 } 66 67 if (!aReader->ReadUInt32(&len)) { 68 return false; 69 } 70 if (len) { 71 UniquePtr<uint8_t[]> data(new uint8_t[len]); 72 if (!aReader->ReadBytesInto(data.get(), len)) { 73 return false; 74 } 75 encrypted_data_ = std::move(data); 76 encrypted_len_ = len; 77 } 78 79 int32_t sdp_level; 80 if (!aReader->ReadInt32(&sdp_level)) { 81 return false; 82 } 83 84 if (sdp_level >= 0) { 85 sdp_level_ = Some(sdp_level); 86 } 87 88 int32_t type; 89 if (!aReader->ReadInt32(&type)) { 90 return false; 91 } 92 type_ = static_cast<Type>(type); 93 return true; 94 } 95 96 static bool IsRtp(const uint8_t* data, size_t len) { 97 if (len < 2) return false; 98 99 // Check if this is a RTCP packet. Logic based on the types listed in 100 // media/webrtc/trunk/src/modules/rtp_rtcp/source/rtp_utility.cc 101 102 // Anything outside this range is RTP. 103 if ((data[1] < 192) || (data[1] > 207)) return true; 104 105 if (data[1] == 192) // FIR 106 return false; 107 108 if (data[1] == 193) // NACK, but could also be RTP. This makes us sad 109 return true; // but it's how webrtc.org behaves. 110 111 if (data[1] == 194) return true; 112 113 if (data[1] == 195) // IJ. 114 return false; 115 116 if ((data[1] > 195) && (data[1] < 200)) // the > 195 is redundant 117 return true; 118 119 if ((data[1] >= 200) && (data[1] <= 207)) // SR, RR, SDES, BYE, 120 return false; // APP, RTPFB, PSFB, XR 121 122 MOZ_ASSERT(false); // Not reached, belt and suspenders. 123 return true; 124 } 125 126 void MediaPacket::Categorize() { 127 SetType(MediaPacket::UNCLASSIFIED); 128 129 if (!data_ || len_ < 4) { 130 return; 131 } 132 133 if (data_[0] >= 20 && data_[0] <= 63) { 134 // DTLS per RFC 7983 135 SetType(MediaPacket::DTLS); 136 } else if (data_[0] > 127 && data_[0] < 192) { 137 // RTP/RTCP per RFC 7983 138 if (IsRtp(data_.get(), len_)) { 139 SetType(MediaPacket::SRTP); 140 } else { 141 SetType(MediaPacket::SRTCP); 142 } 143 } 144 } 145 } // namespace mozilla