rtp_utils.cc (14537B)
1 /* 2 * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. 3 * 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 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "media/base/rtp_utils.h" 12 13 #include <cstdint> 14 #include <cstring> 15 #include <vector> 16 17 // PacketTimeUpdateParams is defined in asyncpacketsocket.h. 18 // TODO(sergeyu): Find more appropriate place for PacketTimeUpdateParams. 19 #include "absl/strings/string_view.h" 20 #include "api/array_view.h" 21 #include "media/base/turn_utils.h" 22 #include "modules/rtp_rtcp/source/rtp_util.h" 23 #include "rtc_base/async_packet_socket.h" 24 #include "rtc_base/byte_order.h" 25 #include "rtc_base/checks.h" 26 #include "rtc_base/message_digest.h" 27 28 namespace webrtc { 29 30 static const size_t kRtcpPayloadTypeOffset = 1; 31 static const size_t kRtpExtensionHeaderLen = 4; 32 static const size_t kAbsSendTimeExtensionLen = 3; 33 static const size_t kOneByteExtensionHeaderLen = 1; 34 static const size_t kTwoByteExtensionHeaderLen = 2; 35 36 namespace { 37 38 // Fake auth tag written by the sender when external authentication is enabled. 39 // HMAC in packet will be compared against this value before updating packet 40 // with actual HMAC value. 41 const uint8_t kFakeAuthTag[10] = {0xba, 0xdd, 0xba, 0xdd, 0xba, 42 0xdd, 0xba, 0xdd, 0xba, 0xdd}; 43 44 void UpdateAbsSendTimeExtensionValue(uint8_t* extension_data, 45 size_t length, 46 uint64_t time_us) { 47 // Absolute send time in RTP streams. 48 // 49 // The absolute send time is signaled to the receiver in-band using the 50 // general mechanism for RTP header extensions [RFC5285]. The payload 51 // of this extension (the transmitted value) is a 24-bit unsigned integer 52 // containing the sender's current time in seconds as a fixed point number 53 // with 18 bits fractional part. 54 // 55 // The form of the absolute send time extension block: 56 // 57 // 0 1 2 3 58 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 59 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 60 // | ID | len=2 | absolute send time | 61 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 62 if (length != kAbsSendTimeExtensionLen) { 63 RTC_DCHECK_NOTREACHED(); 64 return; 65 } 66 67 // Convert microseconds to a 6.18 fixed point value in seconds. 68 uint32_t send_time = ((time_us << 18) / 1000000) & 0x00FFFFFF; 69 extension_data[0] = static_cast<uint8_t>(send_time >> 16); 70 extension_data[1] = static_cast<uint8_t>(send_time >> 8); 71 extension_data[2] = static_cast<uint8_t>(send_time); 72 } 73 74 // Assumes `length` is actual packet length + tag length. Updates HMAC at end of 75 // the RTP packet. 76 void UpdateRtpAuthTag(ArrayView<uint8_t> rtp, 77 const PacketTimeUpdateParams& packet_time_params) { 78 // If there is no key, return. 79 if (packet_time_params.srtp_auth_key.empty()) { 80 return; 81 } 82 83 size_t tag_length = packet_time_params.srtp_auth_tag_len; 84 85 // ROC (rollover counter) is at the beginning of the auth tag. 86 const size_t kRocLength = 4; 87 if (tag_length < kRocLength || tag_length > rtp.size()) { 88 RTC_DCHECK_NOTREACHED(); 89 return; 90 } 91 92 uint8_t* auth_tag = rtp.data() + (rtp.size() - tag_length); 93 94 // We should have a fake HMAC value @ auth_tag. 95 RTC_DCHECK_EQ(0, memcmp(auth_tag, kFakeAuthTag, tag_length)); 96 97 // Copy ROC after end of rtp packet. 98 memcpy(auth_tag, &packet_time_params.srtp_packet_index, kRocLength); 99 // Authentication of a RTP packet will have RTP packet + ROC size. 100 size_t auth_required_length = rtp.size() - tag_length + kRocLength; 101 102 uint8_t output[64]; 103 size_t result = 104 ComputeHmac(DIGEST_SHA_1, &packet_time_params.srtp_auth_key[0], 105 packet_time_params.srtp_auth_key.size(), rtp.data(), 106 auth_required_length, output, sizeof(output)); 107 108 if (result < tag_length) { 109 RTC_DCHECK_NOTREACHED(); 110 return; 111 } 112 113 // Copy HMAC from output to packet. This is required as auth tag length 114 // may not be equal to the actual HMAC length. 115 memcpy(auth_tag, output, tag_length); 116 } 117 118 bool GetUint8(const void* data, size_t offset, int* value) { 119 if (!data || !value) { 120 return false; 121 } 122 *value = *(static_cast<const uint8_t*>(data) + offset); 123 return true; 124 } 125 126 } // namespace 127 128 bool GetRtcpType(const void* data, size_t len, int* value) { 129 if (len < kMinRtcpPacketLen) { 130 return false; 131 } 132 return GetUint8(data, kRtcpPayloadTypeOffset, value); 133 } 134 135 // This method returns SSRC first of RTCP packet, except if packet is SDES. 136 // TODO(mallinath) - Fully implement RFC 5506. This standard doesn't restrict 137 // to send non-compound packets only to feedback messages. 138 bool GetRtcpSsrc(const void* data, size_t len, uint32_t* value) { 139 // Packet should be at least of 8 bytes, to get SSRC from a RTCP packet. 140 if (!data || len < kMinRtcpPacketLen + 4 || !value) 141 return false; 142 int pl_type; 143 if (!GetRtcpType(data, len, &pl_type)) 144 return false; 145 // SDES packet parsing is not supported. 146 if (pl_type == kRtcpTypeSDES) 147 return false; 148 *value = GetBE32(static_cast<const uint8_t*>(data) + 4); 149 return true; 150 } 151 152 bool IsValidRtpPayloadType(int payload_type) { 153 return payload_type >= 0 && payload_type <= 127; 154 } 155 156 bool IsValidRtpPacketSize(RtpPacketType packet_type, size_t size) { 157 RTC_DCHECK_NE(RtpPacketType::kUnknown, packet_type); 158 size_t min_packet_length = packet_type == RtpPacketType::kRtcp 159 ? kMinRtcpPacketLen 160 : kMinRtpPacketLen; 161 return size >= min_packet_length && size <= kMaxRtpPacketLen; 162 } 163 164 absl::string_view RtpPacketTypeToString(RtpPacketType packet_type) { 165 switch (packet_type) { 166 case RtpPacketType::kRtp: 167 return "RTP"; 168 case RtpPacketType::kRtcp: 169 return "RTCP"; 170 case RtpPacketType::kUnknown: 171 return "Unknown"; 172 } 173 RTC_CHECK_NOTREACHED(); 174 } 175 176 RtpPacketType InferRtpPacketType(ArrayView<const uint8_t> packet) { 177 if (IsRtcpPacket(packet)) { 178 return RtpPacketType::kRtcp; 179 } 180 if (IsRtpPacket(packet)) { 181 return RtpPacketType::kRtp; 182 } 183 return RtpPacketType::kUnknown; 184 } 185 186 bool ValidateRtpHeader(ArrayView<const uint8_t> rtp, size_t* header_length) { 187 size_t length = rtp.size(); 188 if (header_length) { 189 *header_length = 0; 190 } 191 192 if (length < kMinRtpPacketLen) { 193 return false; 194 } 195 196 size_t cc_count = rtp[0] & 0x0F; 197 size_t header_length_without_extension = kMinRtpPacketLen + 4 * cc_count; 198 if (header_length_without_extension > length) { 199 return false; 200 } 201 202 // If extension bit is not set, we are done with header processing, as input 203 // length is verified above. 204 if (!(rtp[0] & 0x10)) { 205 if (header_length) 206 *header_length = header_length_without_extension; 207 208 return true; 209 } 210 211 if (header_length_without_extension + kRtpExtensionHeaderLen > length) { 212 return false; 213 } 214 215 // Getting extension profile length. 216 // Length is in 32 bit words. 217 uint16_t extension_length_in_32bits = 218 GetBE16(&rtp[header_length_without_extension + 2]); 219 size_t extension_length = extension_length_in_32bits * 4; 220 221 size_t rtp_header_length = extension_length + 222 header_length_without_extension + 223 kRtpExtensionHeaderLen; 224 225 // Verify input length against total header size. 226 if (rtp_header_length > length) { 227 return false; 228 } 229 230 if (header_length) { 231 *header_length = rtp_header_length; 232 } 233 return true; 234 } 235 236 // ValidateRtpHeader() must be called before this method to make sure, we have 237 // a sane rtp packet. 238 bool UpdateRtpAbsSendTimeExtension(ArrayView<uint8_t> packet, 239 int extension_id, 240 uint64_t time_us) { 241 // 0 1 2 3 242 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 243 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 244 // |V=2|P|X| CC |M| PT | sequence number | 245 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 246 // | timestamp | 247 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 248 // | synchronization source (SSRC) identifier | 249 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 250 // | contributing source (CSRC) identifiers | 251 // | .... | 252 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 253 254 // Return if extension bit is not set. 255 if (!(packet[0] & 0x10)) { 256 return true; 257 } 258 259 size_t cc_count = packet[0] & 0x0F; 260 size_t header_length_without_extension = kMinRtpPacketLen + 4 * cc_count; 261 262 uint8_t* rtp = packet.data(); 263 rtp += header_length_without_extension; 264 265 // Getting extension profile ID and length. 266 uint16_t profile_id = GetBE16(rtp); 267 // Length is in 32 bit words. 268 uint16_t extension_length_in_32bits = GetBE16(rtp + 2); 269 size_t extension_length = extension_length_in_32bits * 4; 270 271 rtp += kRtpExtensionHeaderLen; // Moving past extension header. 272 273 constexpr uint16_t kOneByteExtensionProfileId = 0xBEDE; 274 constexpr uint16_t kTwoByteExtensionProfileId = 0x1000; 275 276 bool found = false; 277 if (profile_id == kOneByteExtensionProfileId || 278 profile_id == kTwoByteExtensionProfileId) { 279 // OneByte extension header 280 // 0 281 // 0 1 2 3 4 5 6 7 282 // +-+-+-+-+-+-+-+-+ 283 // | ID |length | 284 // +-+-+-+-+-+-+-+-+ 285 286 // 0 1 2 3 287 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 288 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 289 // | 0xBE | 0xDE | length=3 | 290 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 291 // | ID | L=0 | data | ID | L=1 | data... 292 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 293 // ...data | 0 (pad) | 0 (pad) | ID | L=3 | 294 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 295 // | data | 296 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 297 298 // TwoByte extension header 299 // 0 300 // 0 1 2 3 4 5 6 7 301 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 302 // | ID | length | 303 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 304 305 // 0 1 2 3 306 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 307 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 308 // | 0x10 | 0x00 | length=3 | 309 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 310 // | ID | L=1 | data | ID | 311 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 312 // | L=2 | data | 0 (pad) | 313 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 314 // | ID | L=2 | data | 315 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 316 317 size_t extension_header_length = profile_id == kOneByteExtensionProfileId 318 ? kOneByteExtensionHeaderLen 319 : kTwoByteExtensionHeaderLen; 320 321 const uint8_t* extension_start = rtp; 322 const uint8_t* extension_end = extension_start + extension_length; 323 324 // rtp + 1 since the minimum size per header extension is two bytes for both 325 // one- and two-byte header extensions. 326 while (rtp + 1 < extension_end) { 327 // See RFC8285 Section 4.2-4.3 for more information about one- and 328 // two-byte header extensions. 329 const int id = 330 profile_id == kOneByteExtensionProfileId ? (*rtp & 0xF0) >> 4 : *rtp; 331 const size_t length = profile_id == kOneByteExtensionProfileId 332 ? (*rtp & 0x0F) + 1 333 : *(rtp + 1); 334 if (rtp + extension_header_length + length > extension_end) { 335 return false; 336 } 337 if (id == extension_id) { 338 UpdateAbsSendTimeExtensionValue(rtp + extension_header_length, length, 339 time_us); 340 found = true; 341 break; 342 } 343 rtp += extension_header_length + length; 344 // Counting padding bytes. 345 while ((rtp < extension_end) && (*rtp == 0)) { 346 ++rtp; 347 } 348 } 349 } 350 return found; 351 } 352 353 bool ApplyPacketOptions(ArrayView<uint8_t> data, 354 const PacketTimeUpdateParams& packet_time_params, 355 uint64_t time_us) { 356 RTC_DCHECK(!data.empty()); 357 358 // if there is no valid `rtp_sendtime_extension_id` and `srtp_auth_key` in 359 // PacketOptions, nothing to be updated in this packet. 360 if (packet_time_params.rtp_sendtime_extension_id == -1 && 361 packet_time_params.srtp_auth_key.empty()) { 362 return true; 363 } 364 365 // If there is a srtp auth key present then the packet must be an RTP packet. 366 // RTP packet may have been wrapped in a TURN Channel Data or TURN send 367 // indication. 368 size_t rtp_start_pos; 369 size_t rtp_length; 370 if (!UnwrapTurnPacket(data.data(), data.size(), &rtp_start_pos, 371 &rtp_length)) { 372 RTC_DCHECK_NOTREACHED(); 373 return false; 374 } 375 376 // Making sure we have a valid RTP packet at the end. 377 auto packet = data.subview(rtp_start_pos, rtp_length); 378 if (!IsRtpPacket(packet) || !ValidateRtpHeader(packet, nullptr)) { 379 RTC_DCHECK_NOTREACHED(); 380 return false; 381 } 382 383 // If packet option has non default value (-1) for sendtime extension id, 384 // then we should parse the rtp packet to update the timestamp. Otherwise 385 // just calculate HMAC and update packet with it. 386 if (packet_time_params.rtp_sendtime_extension_id != -1) { 387 UpdateRtpAbsSendTimeExtension( 388 packet, packet_time_params.rtp_sendtime_extension_id, time_us); 389 } 390 391 UpdateRtpAuthTag(packet, packet_time_params); 392 return true; 393 } 394 395 } // namespace webrtc