• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <string.h>
14 
15 #include <vector>
16 
17 // PacketTimeUpdateParams is defined in asyncpacketsocket.h.
18 // TODO(sergeyu): Find more appropriate place for PacketTimeUpdateParams.
19 #include "media/base/turn_utils.h"
20 #include "rtc_base/async_packet_socket.h"
21 #include "rtc_base/byte_order.h"
22 #include "rtc_base/checks.h"
23 #include "rtc_base/message_digest.h"
24 
25 namespace cricket {
26 
27 static const uint8_t kRtpVersion = 2;
28 static const size_t kRtpFlagsOffset = 0;
29 static const size_t kRtpPayloadTypeOffset = 1;
30 static const size_t kRtpSeqNumOffset = 2;
31 static const size_t kRtpTimestampOffset = 4;
32 static const size_t kRtpSsrcOffset = 8;
33 static const size_t kRtcpPayloadTypeOffset = 1;
34 static const size_t kRtpExtensionHeaderLen = 4;
35 static const size_t kAbsSendTimeExtensionLen = 3;
36 static const size_t kOneByteExtensionHeaderLen = 1;
37 static const size_t kTwoByteExtensionHeaderLen = 2;
38 
39 namespace {
40 
41 // Fake auth tag written by the sender when external authentication is enabled.
42 // HMAC in packet will be compared against this value before updating packet
43 // with actual HMAC value.
44 static const uint8_t kFakeAuthTag[10] = {0xba, 0xdd, 0xba, 0xdd, 0xba,
45                                          0xdd, 0xba, 0xdd, 0xba, 0xdd};
46 
UpdateAbsSendTimeExtensionValue(uint8_t * extension_data,size_t length,uint64_t time_us)47 void UpdateAbsSendTimeExtensionValue(uint8_t* extension_data,
48                                      size_t length,
49                                      uint64_t time_us) {
50   // Absolute send time in RTP streams.
51   //
52   // The absolute send time is signaled to the receiver in-band using the
53   // general mechanism for RTP header extensions [RFC5285]. The payload
54   // of this extension (the transmitted value) is a 24-bit unsigned integer
55   // containing the sender's current time in seconds as a fixed point number
56   // with 18 bits fractional part.
57   //
58   // The form of the absolute send time extension block:
59   //
60   //    0                   1                   2                   3
61   //    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
62   //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
63   //   |  ID   | len=2 |              absolute send time               |
64   //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
65   if (length != kAbsSendTimeExtensionLen) {
66     RTC_NOTREACHED();
67     return;
68   }
69 
70   // Convert microseconds to a 6.18 fixed point value in seconds.
71   uint32_t send_time = ((time_us << 18) / 1000000) & 0x00FFFFFF;
72   extension_data[0] = static_cast<uint8_t>(send_time >> 16);
73   extension_data[1] = static_cast<uint8_t>(send_time >> 8);
74   extension_data[2] = static_cast<uint8_t>(send_time);
75 }
76 
77 // Assumes |length| is actual packet length + tag length. Updates HMAC at end of
78 // the RTP packet.
UpdateRtpAuthTag(uint8_t * rtp,size_t length,const rtc::PacketTimeUpdateParams & packet_time_params)79 void UpdateRtpAuthTag(uint8_t* rtp,
80                       size_t length,
81                       const rtc::PacketTimeUpdateParams& packet_time_params) {
82   // If there is no key, return.
83   if (packet_time_params.srtp_auth_key.empty()) {
84     return;
85   }
86 
87   size_t tag_length = packet_time_params.srtp_auth_tag_len;
88 
89   // ROC (rollover counter) is at the beginning of the auth tag.
90   const size_t kRocLength = 4;
91   if (tag_length < kRocLength || tag_length > length) {
92     RTC_NOTREACHED();
93     return;
94   }
95 
96   uint8_t* auth_tag = rtp + (length - tag_length);
97 
98   // We should have a fake HMAC value @ auth_tag.
99   RTC_DCHECK_EQ(0, memcmp(auth_tag, kFakeAuthTag, tag_length));
100 
101   // Copy ROC after end of rtp packet.
102   memcpy(auth_tag, &packet_time_params.srtp_packet_index, kRocLength);
103   // Authentication of a RTP packet will have RTP packet + ROC size.
104   size_t auth_required_length = length - tag_length + kRocLength;
105 
106   uint8_t output[64];
107   size_t result =
108       rtc::ComputeHmac(rtc::DIGEST_SHA_1, &packet_time_params.srtp_auth_key[0],
109                        packet_time_params.srtp_auth_key.size(), rtp,
110                        auth_required_length, output, sizeof(output));
111 
112   if (result < tag_length) {
113     RTC_NOTREACHED();
114     return;
115   }
116 
117   // Copy HMAC from output to packet. This is required as auth tag length
118   // may not be equal to the actual HMAC length.
119   memcpy(auth_tag, output, tag_length);
120 }
121 
122 }  // namespace
123 
GetUint8(const void * data,size_t offset,int * value)124 bool GetUint8(const void* data, size_t offset, int* value) {
125   if (!data || !value) {
126     return false;
127   }
128   *value = *(static_cast<const uint8_t*>(data) + offset);
129   return true;
130 }
131 
GetUint16(const void * data,size_t offset,int * value)132 bool GetUint16(const void* data, size_t offset, int* value) {
133   if (!data || !value) {
134     return false;
135   }
136   *value = static_cast<int>(
137       rtc::GetBE16(static_cast<const uint8_t*>(data) + offset));
138   return true;
139 }
140 
GetUint32(const void * data,size_t offset,uint32_t * value)141 bool GetUint32(const void* data, size_t offset, uint32_t* value) {
142   if (!data || !value) {
143     return false;
144   }
145   *value = rtc::GetBE32(static_cast<const uint8_t*>(data) + offset);
146   return true;
147 }
148 
SetUint8(void * data,size_t offset,uint8_t value)149 bool SetUint8(void* data, size_t offset, uint8_t value) {
150   if (!data) {
151     return false;
152   }
153   rtc::Set8(data, offset, value);
154   return true;
155 }
156 
SetUint16(void * data,size_t offset,uint16_t value)157 bool SetUint16(void* data, size_t offset, uint16_t value) {
158   if (!data) {
159     return false;
160   }
161   rtc::SetBE16(static_cast<uint8_t*>(data) + offset, value);
162   return true;
163 }
164 
SetUint32(void * data,size_t offset,uint32_t value)165 bool SetUint32(void* data, size_t offset, uint32_t value) {
166   if (!data) {
167     return false;
168   }
169   rtc::SetBE32(static_cast<uint8_t*>(data) + offset, value);
170   return true;
171 }
172 
GetRtpFlags(const void * data,size_t len,int * value)173 bool GetRtpFlags(const void* data, size_t len, int* value) {
174   if (len < kMinRtpPacketLen) {
175     return false;
176   }
177   return GetUint8(data, kRtpFlagsOffset, value);
178 }
179 
GetRtpPayloadType(const void * data,size_t len,int * value)180 bool GetRtpPayloadType(const void* data, size_t len, int* value) {
181   if (len < kMinRtpPacketLen) {
182     return false;
183   }
184   if (!GetUint8(data, kRtpPayloadTypeOffset, value)) {
185     return false;
186   }
187   *value &= 0x7F;
188   return true;
189 }
190 
GetRtpSeqNum(const void * data,size_t len,int * value)191 bool GetRtpSeqNum(const void* data, size_t len, int* value) {
192   if (len < kMinRtpPacketLen) {
193     return false;
194   }
195   return GetUint16(data, kRtpSeqNumOffset, value);
196 }
197 
GetRtpTimestamp(const void * data,size_t len,uint32_t * value)198 bool GetRtpTimestamp(const void* data, size_t len, uint32_t* value) {
199   if (len < kMinRtpPacketLen) {
200     return false;
201   }
202   return GetUint32(data, kRtpTimestampOffset, value);
203 }
204 
GetRtpSsrc(const void * data,size_t len,uint32_t * value)205 bool GetRtpSsrc(const void* data, size_t len, uint32_t* value) {
206   if (len < kMinRtpPacketLen) {
207     return false;
208   }
209   return GetUint32(data, kRtpSsrcOffset, value);
210 }
211 
GetRtpHeaderLen(const void * data,size_t len,size_t * value)212 bool GetRtpHeaderLen(const void* data, size_t len, size_t* value) {
213   if (!data || len < kMinRtpPacketLen || !value)
214     return false;
215   const uint8_t* header = static_cast<const uint8_t*>(data);
216   // Get base header size + length of CSRCs (not counting extension yet).
217   size_t header_size = kMinRtpPacketLen + (header[0] & 0xF) * sizeof(uint32_t);
218   if (len < header_size)
219     return false;
220   // If there's an extension, read and add in the extension size.
221   if (header[0] & 0x10) {
222     if (len < header_size + sizeof(uint32_t))
223       return false;
224     header_size +=
225         ((rtc::GetBE16(header + header_size + 2) + 1) * sizeof(uint32_t));
226     if (len < header_size)
227       return false;
228   }
229   *value = header_size;
230   return true;
231 }
232 
GetRtpHeader(const void * data,size_t len,RtpHeader * header)233 bool GetRtpHeader(const void* data, size_t len, RtpHeader* header) {
234   return (GetRtpPayloadType(data, len, &(header->payload_type)) &&
235           GetRtpSeqNum(data, len, &(header->seq_num)) &&
236           GetRtpTimestamp(data, len, &(header->timestamp)) &&
237           GetRtpSsrc(data, len, &(header->ssrc)));
238 }
239 
GetRtcpType(const void * data,size_t len,int * value)240 bool GetRtcpType(const void* data, size_t len, int* value) {
241   if (len < kMinRtcpPacketLen) {
242     return false;
243   }
244   return GetUint8(data, kRtcpPayloadTypeOffset, value);
245 }
246 
247 // This method returns SSRC first of RTCP packet, except if packet is SDES.
248 // TODO(mallinath) - Fully implement RFC 5506. This standard doesn't restrict
249 // to send non-compound packets only to feedback messages.
GetRtcpSsrc(const void * data,size_t len,uint32_t * value)250 bool GetRtcpSsrc(const void* data, size_t len, uint32_t* value) {
251   // Packet should be at least of 8 bytes, to get SSRC from a RTCP packet.
252   if (!data || len < kMinRtcpPacketLen + 4 || !value)
253     return false;
254   int pl_type;
255   if (!GetRtcpType(data, len, &pl_type))
256     return false;
257   // SDES packet parsing is not supported.
258   if (pl_type == kRtcpTypeSDES)
259     return false;
260   *value = rtc::GetBE32(static_cast<const uint8_t*>(data) + 4);
261   return true;
262 }
263 
SetRtpSsrc(void * data,size_t len,uint32_t value)264 bool SetRtpSsrc(void* data, size_t len, uint32_t value) {
265   return SetUint32(data, kRtpSsrcOffset, value);
266 }
267 
268 // Assumes version 2, no padding, no extensions, no csrcs.
SetRtpHeader(void * data,size_t len,const RtpHeader & header)269 bool SetRtpHeader(void* data, size_t len, const RtpHeader& header) {
270   if (!IsValidRtpPayloadType(header.payload_type) || header.seq_num < 0 ||
271       header.seq_num > static_cast<int>(UINT16_MAX)) {
272     return false;
273   }
274   return (SetUint8(data, kRtpFlagsOffset, kRtpVersion << 6) &&
275           SetUint8(data, kRtpPayloadTypeOffset, header.payload_type & 0x7F) &&
276           SetUint16(data, kRtpSeqNumOffset,
277                     static_cast<uint16_t>(header.seq_num)) &&
278           SetUint32(data, kRtpTimestampOffset, header.timestamp) &&
279           SetRtpSsrc(data, len, header.ssrc));
280 }
281 
HasCorrectRtpVersion(rtc::ArrayView<const uint8_t> packet)282 static bool HasCorrectRtpVersion(rtc::ArrayView<const uint8_t> packet) {
283   return packet.data()[0] >> 6 == kRtpVersion;
284 }
285 
IsRtpPacket(rtc::ArrayView<const char> packet)286 bool IsRtpPacket(rtc::ArrayView<const char> packet) {
287   return packet.size() >= kMinRtpPacketLen &&
288          HasCorrectRtpVersion(
289              rtc::reinterpret_array_view<const uint8_t>(packet));
290 }
291 
292 // Check the RTP payload type. If 63 < payload type < 96, it's RTCP.
293 // For additional details, see http://tools.ietf.org/html/rfc5761.
IsRtcpPacket(rtc::ArrayView<const char> packet)294 bool IsRtcpPacket(rtc::ArrayView<const char> packet) {
295   if (packet.size() < kMinRtcpPacketLen ||
296       !HasCorrectRtpVersion(
297           rtc::reinterpret_array_view<const uint8_t>(packet))) {
298     return false;
299   }
300 
301   char pt = packet[1] & 0x7F;
302   return (63 < pt) && (pt < 96);
303 }
304 
IsValidRtpPayloadType(int payload_type)305 bool IsValidRtpPayloadType(int payload_type) {
306   return payload_type >= 0 && payload_type <= 127;
307 }
308 
IsValidRtpPacketSize(RtpPacketType packet_type,size_t size)309 bool IsValidRtpPacketSize(RtpPacketType packet_type, size_t size) {
310   RTC_DCHECK_NE(RtpPacketType::kUnknown, packet_type);
311   size_t min_packet_length = packet_type == RtpPacketType::kRtcp
312                                  ? kMinRtcpPacketLen
313                                  : kMinRtpPacketLen;
314   return size >= min_packet_length && size <= kMaxRtpPacketLen;
315 }
316 
RtpPacketTypeToString(RtpPacketType packet_type)317 absl::string_view RtpPacketTypeToString(RtpPacketType packet_type) {
318   switch (packet_type) {
319     case RtpPacketType::kRtp:
320       return "RTP";
321     case RtpPacketType::kRtcp:
322       return "RTCP";
323     case RtpPacketType::kUnknown:
324       return "Unknown";
325   }
326 }
327 
InferRtpPacketType(rtc::ArrayView<const char> packet)328 RtpPacketType InferRtpPacketType(rtc::ArrayView<const char> packet) {
329   // RTCP packets are RTP packets so must check that first.
330   if (IsRtcpPacket(packet)) {
331     return RtpPacketType::kRtcp;
332   }
333   if (IsRtpPacket(packet)) {
334     return RtpPacketType::kRtp;
335   }
336   return RtpPacketType::kUnknown;
337 }
338 
ValidateRtpHeader(const uint8_t * rtp,size_t length,size_t * header_length)339 bool ValidateRtpHeader(const uint8_t* rtp,
340                        size_t length,
341                        size_t* header_length) {
342   if (header_length) {
343     *header_length = 0;
344   }
345 
346   if (length < kMinRtpPacketLen) {
347     return false;
348   }
349 
350   size_t cc_count = rtp[0] & 0x0F;
351   size_t header_length_without_extension = kMinRtpPacketLen + 4 * cc_count;
352   if (header_length_without_extension > length) {
353     return false;
354   }
355 
356   // If extension bit is not set, we are done with header processing, as input
357   // length is verified above.
358   if (!(rtp[0] & 0x10)) {
359     if (header_length)
360       *header_length = header_length_without_extension;
361 
362     return true;
363   }
364 
365   rtp += header_length_without_extension;
366 
367   if (header_length_without_extension + kRtpExtensionHeaderLen > length) {
368     return false;
369   }
370 
371   // Getting extension profile length.
372   // Length is in 32 bit words.
373   uint16_t extension_length_in_32bits = rtc::GetBE16(rtp + 2);
374   size_t extension_length = extension_length_in_32bits * 4;
375 
376   size_t rtp_header_length = extension_length +
377                              header_length_without_extension +
378                              kRtpExtensionHeaderLen;
379 
380   // Verify input length against total header size.
381   if (rtp_header_length > length) {
382     return false;
383   }
384 
385   if (header_length) {
386     *header_length = rtp_header_length;
387   }
388   return true;
389 }
390 
391 // ValidateRtpHeader() must be called before this method to make sure, we have
392 // a sane rtp packet.
UpdateRtpAbsSendTimeExtension(uint8_t * rtp,size_t length,int extension_id,uint64_t time_us)393 bool UpdateRtpAbsSendTimeExtension(uint8_t* rtp,
394                                    size_t length,
395                                    int extension_id,
396                                    uint64_t time_us) {
397   //  0                   1                   2                   3
398   //  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
399   // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
400   // |V=2|P|X|  CC   |M|     PT      |       sequence number         |
401   // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
402   // |                           timestamp                           |
403   // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
404   // |           synchronization source (SSRC) identifier            |
405   // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
406   // |            contributing source (CSRC) identifiers             |
407   // |                             ....                              |
408   // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
409 
410   // Return if extension bit is not set.
411   if (!(rtp[0] & 0x10)) {
412     return true;
413   }
414 
415   size_t cc_count = rtp[0] & 0x0F;
416   size_t header_length_without_extension = kMinRtpPacketLen + 4 * cc_count;
417 
418   rtp += header_length_without_extension;
419 
420   // Getting extension profile ID and length.
421   uint16_t profile_id = rtc::GetBE16(rtp);
422   // Length is in 32 bit words.
423   uint16_t extension_length_in_32bits = rtc::GetBE16(rtp + 2);
424   size_t extension_length = extension_length_in_32bits * 4;
425 
426   rtp += kRtpExtensionHeaderLen;  // Moving past extension header.
427 
428   constexpr uint16_t kOneByteExtensionProfileId = 0xBEDE;
429   constexpr uint16_t kTwoByteExtensionProfileId = 0x1000;
430 
431   bool found = false;
432   if (profile_id == kOneByteExtensionProfileId ||
433       profile_id == kTwoByteExtensionProfileId) {
434     // OneByte extension header
435     //  0
436     //  0 1 2 3 4 5 6 7
437     // +-+-+-+-+-+-+-+-+
438     // |  ID   |length |
439     // +-+-+-+-+-+-+-+-+
440 
441     //  0                   1                   2                   3
442     //  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
443     // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
444     // |       0xBE    |    0xDE       |           length=3            |
445     // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
446     // |  ID   | L=0   |     data      |  ID   |  L=1  |   data...
447     // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
448     //       ...data   |    0 (pad)    |    0 (pad)    |  ID   | L=3   |
449     // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
450     // |                          data                                 |
451     // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
452 
453     // TwoByte extension header
454     //  0
455     //  0 1 2 3 4 5 6 7
456     // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
457     // |      ID       |    length     |
458     // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
459 
460     //  0                   1                   2                   3
461     //  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
462     // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
463     // |     0x10      |     0x00      |           length=3            |
464     // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
465     // |      ID       |      L=1      |     data      |      ID       |
466     // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
467     // |      L=2      |             data              |    0 (pad)    |
468     // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
469     // |      ID       |      L=2      |             data              |
470     // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
471 
472     size_t extension_header_length = profile_id == kOneByteExtensionProfileId
473                                          ? kOneByteExtensionHeaderLen
474                                          : kTwoByteExtensionHeaderLen;
475 
476     const uint8_t* extension_start = rtp;
477     const uint8_t* extension_end = extension_start + extension_length;
478 
479     // rtp + 1 since the minimum size per header extension is two bytes for both
480     // one- and two-byte header extensions.
481     while (rtp + 1 < extension_end) {
482       // See RFC8285 Section 4.2-4.3 for more information about one- and
483       // two-byte header extensions.
484       const int id =
485           profile_id == kOneByteExtensionProfileId ? (*rtp & 0xF0) >> 4 : *rtp;
486       const size_t length = profile_id == kOneByteExtensionProfileId
487                                 ? (*rtp & 0x0F) + 1
488                                 : *(rtp + 1);
489       if (rtp + extension_header_length + length > extension_end) {
490         return false;
491       }
492       if (id == extension_id) {
493         UpdateAbsSendTimeExtensionValue(rtp + extension_header_length, length,
494                                         time_us);
495         found = true;
496         break;
497       }
498       rtp += extension_header_length + length;
499       // Counting padding bytes.
500       while ((rtp < extension_end) && (*rtp == 0)) {
501         ++rtp;
502       }
503     }
504   }
505   return found;
506 }
507 
ApplyPacketOptions(uint8_t * data,size_t length,const rtc::PacketTimeUpdateParams & packet_time_params,uint64_t time_us)508 bool ApplyPacketOptions(uint8_t* data,
509                         size_t length,
510                         const rtc::PacketTimeUpdateParams& packet_time_params,
511                         uint64_t time_us) {
512   RTC_DCHECK(data);
513   RTC_DCHECK(length);
514 
515   // if there is no valid |rtp_sendtime_extension_id| and |srtp_auth_key| in
516   // PacketOptions, nothing to be updated in this packet.
517   if (packet_time_params.rtp_sendtime_extension_id == -1 &&
518       packet_time_params.srtp_auth_key.empty()) {
519     return true;
520   }
521 
522   // If there is a srtp auth key present then the packet must be an RTP packet.
523   // RTP packet may have been wrapped in a TURN Channel Data or TURN send
524   // indication.
525   size_t rtp_start_pos;
526   size_t rtp_length;
527   if (!UnwrapTurnPacket(data, length, &rtp_start_pos, &rtp_length)) {
528     RTC_NOTREACHED();
529     return false;
530   }
531 
532   // Making sure we have a valid RTP packet at the end.
533   auto packet = rtc::MakeArrayView(data + rtp_start_pos, rtp_length);
534   if (!IsRtpPacket(rtc::reinterpret_array_view<const char>(packet)) ||
535       !ValidateRtpHeader(data + rtp_start_pos, rtp_length, nullptr)) {
536     RTC_NOTREACHED();
537     return false;
538   }
539 
540   uint8_t* start = data + rtp_start_pos;
541   // If packet option has non default value (-1) for sendtime extension id,
542   // then we should parse the rtp packet to update the timestamp. Otherwise
543   // just calculate HMAC and update packet with it.
544   if (packet_time_params.rtp_sendtime_extension_id != -1) {
545     UpdateRtpAbsSendTimeExtension(start, rtp_length,
546                                   packet_time_params.rtp_sendtime_extension_id,
547                                   time_us);
548   }
549 
550   UpdateRtpAuthTag(start, rtp_length, packet_time_params);
551   return true;
552 }
553 
554 }  // namespace cricket
555