1 /*
2  *  Copyright (c) 2012 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 "modules/rtp_rtcp/source/rtp_utility.h"
12 
13 #include "modules/rtp_rtcp/include/rtp_cvo.h"
14 #include "modules/rtp_rtcp/source/byte_io.h"
15 #include "modules/rtp_rtcp/source/rtp_header_extensions.h"
16 #include "rtc_base/logging.h"
17 
18 namespace webrtc {
19 
NullObjectRtpFeedback()20 RtpFeedback* NullObjectRtpFeedback() {
21   static NullRtpFeedback null_rtp_feedback;
22   return &null_rtp_feedback;
23 }
24 
25 namespace RtpUtility {
26 
27 enum {
28   kRtcpExpectedVersion = 2,
29   kRtcpMinHeaderLength = 4,
30   kRtcpMinParseLength = 8,
31 
32   kRtpExpectedVersion = 2,
33   kRtpMinParseLength = 12
34 };
35 
36 /*
37  * Misc utility routines
38  */
39 
40 #if defined(_WIN32)
StringCompare(const char * str1,const char * str2,const uint32_t length)41 bool StringCompare(const char* str1, const char* str2,
42                    const uint32_t length) {
43   return _strnicmp(str1, str2, length) == 0;
44 }
45 #elif defined(WEBRTC_LINUX) || defined(WEBRTC_BSD) || defined(WEBRTC_MAC)
StringCompare(const char * str1,const char * str2,const uint32_t length)46 bool StringCompare(const char* str1, const char* str2,
47                    const uint32_t length) {
48   return strncasecmp(str1, str2, length) == 0;
49 }
50 #endif
51 
Word32Align(size_t size)52 size_t Word32Align(size_t size) {
53   uint32_t remainder = size % 4;
54   if (remainder != 0)
55     return size + 4 - remainder;
56   return size;
57 }
58 
RtpHeaderParser(const uint8_t * rtpData,const size_t rtpDataLength)59 RtpHeaderParser::RtpHeaderParser(const uint8_t* rtpData,
60                                  const size_t rtpDataLength)
61     : _ptrRTPDataBegin(rtpData),
62       _ptrRTPDataEnd(rtpData ? (rtpData + rtpDataLength) : NULL) {
63 }
64 
~RtpHeaderParser()65 RtpHeaderParser::~RtpHeaderParser() {
66 }
67 
RTCP() const68 bool RtpHeaderParser::RTCP() const {
69   // 72 to 76 is reserved for RTP
70   // 77 to 79 is not reserver but  they are not assigned we will block them
71   // for RTCP 200 SR  == marker bit + 72
72   // for RTCP 204 APP == marker bit + 76
73   /*
74   *       RTCP
75   *
76   * FIR      full INTRA-frame request             192     [RFC2032]   supported
77   * NACK     negative acknowledgement             193     [RFC2032]
78   * IJ       Extended inter-arrival jitter report 195     [RFC-ietf-avt-rtp-toff
79   * set-07.txt] http://tools.ietf.org/html/draft-ietf-avt-rtp-toffset-07
80   * SR       sender report                        200     [RFC3551]   supported
81   * RR       receiver report                      201     [RFC3551]   supported
82   * SDES     source description                   202     [RFC3551]   supported
83   * BYE      goodbye                              203     [RFC3551]   supported
84   * APP      application-defined                  204     [RFC3551]   ignored
85   * RTPFB    Transport layer FB message           205     [RFC4585]   supported
86   * PSFB     Payload-specific FB message          206     [RFC4585]   supported
87   * XR       extended report                      207     [RFC3611]   supported
88   */
89 
90   /* 205       RFC 5104
91    * FMT 1      NACK       supported
92    * FMT 2      reserved
93    * FMT 3      TMMBR      supported
94    * FMT 4      TMMBN      supported
95    */
96 
97   /* 206      RFC 5104
98   * FMT 1:     Picture Loss Indication (PLI)                      supported
99   * FMT 2:     Slice Lost Indication (SLI)
100   * FMT 3:     Reference Picture Selection Indication (RPSI)
101   * FMT 4:     Full Intra Request (FIR) Command                   supported
102   * FMT 5:     Temporal-Spatial Trade-off Request (TSTR)
103   * FMT 6:     Temporal-Spatial Trade-off Notification (TSTN)
104   * FMT 7:     Video Back Channel Message (VBCM)
105   * FMT 15:    Application layer FB message
106   */
107 
108   const ptrdiff_t length = _ptrRTPDataEnd - _ptrRTPDataBegin;
109   if (length < kRtcpMinHeaderLength) {
110     return false;
111   }
112 
113   const uint8_t V = _ptrRTPDataBegin[0] >> 6;
114   if (V != kRtcpExpectedVersion) {
115     return false;
116   }
117 
118   const uint8_t payloadType = _ptrRTPDataBegin[1];
119   switch (payloadType) {
120     case 192:
121       return true;
122     case 193:
123       // not supported
124       // pass through and check for a potential RTP packet
125       return false;
126     case 195:
127     case 200:
128     case 201:
129     case 202:
130     case 203:
131     case 204:
132     case 205:
133     case 206:
134     case 207:
135       return true;
136     default:
137       return false;
138   }
139 }
140 
ParseRtcp(RTPHeader * header) const141 bool RtpHeaderParser::ParseRtcp(RTPHeader* header) const {
142   assert(header != NULL);
143 
144   const ptrdiff_t length = _ptrRTPDataEnd - _ptrRTPDataBegin;
145   if (length < kRtcpMinParseLength) {
146     return false;
147   }
148 
149   const uint8_t V = _ptrRTPDataBegin[0] >> 6;
150   if (V != kRtcpExpectedVersion) {
151     return false;
152   }
153 
154   const uint8_t PT = _ptrRTPDataBegin[1];
155   const size_t len = (_ptrRTPDataBegin[2] << 8) + _ptrRTPDataBegin[3];
156   const uint8_t* ptr = &_ptrRTPDataBegin[4];
157 
158   uint32_t SSRC = ByteReader<uint32_t>::ReadBigEndian(ptr);
159   ptr += 4;
160 
161   header->payloadType  = PT;
162   header->ssrc         = SSRC;
163   header->headerLength = 4 + (len << 2);
164   if (header->headerLength > static_cast<size_t>(length)) {
165     return false;
166   }
167 
168   return true;
169 }
170 
Parse(RTPHeader * header,RtpHeaderExtensionMap * ptrExtensionMap,bool secured) const171 bool RtpHeaderParser::Parse(RTPHeader* header,
172                             RtpHeaderExtensionMap* ptrExtensionMap,
173                             bool secured) const {
174   const ptrdiff_t length = _ptrRTPDataEnd - _ptrRTPDataBegin;
175   if (length < kRtpMinParseLength) {
176     return false;
177   }
178 
179   // Version
180   const uint8_t V  = _ptrRTPDataBegin[0] >> 6;
181   // Padding
182   const bool          P  = ((_ptrRTPDataBegin[0] & 0x20) == 0) ? false : true;
183   // eXtension
184   const bool          X  = ((_ptrRTPDataBegin[0] & 0x10) == 0) ? false : true;
185   const uint8_t CC = _ptrRTPDataBegin[0] & 0x0f;
186   const bool          M  = ((_ptrRTPDataBegin[1] & 0x80) == 0) ? false : true;
187 
188   const uint8_t PT = _ptrRTPDataBegin[1] & 0x7f;
189 
190   const uint16_t sequenceNumber = (_ptrRTPDataBegin[2] << 8) +
191       _ptrRTPDataBegin[3];
192 
193   const uint8_t* ptr = &_ptrRTPDataBegin[4];
194 
195   uint32_t RTPTimestamp = ByteReader<uint32_t>::ReadBigEndian(ptr);
196   ptr += 4;
197 
198   uint32_t SSRC = ByteReader<uint32_t>::ReadBigEndian(ptr);
199   ptr += 4;
200 
201   if (V != kRtpExpectedVersion) {
202     return false;
203   }
204 
205   header->markerBit      = M;
206   header->payloadType    = PT;
207   header->sequenceNumber = sequenceNumber;
208   header->timestamp      = RTPTimestamp;
209   header->ssrc           = SSRC;
210   header->numCSRCs       = CC;
211   header->paddingLength  = P ? *(_ptrRTPDataEnd - 1) : 0;
212 
213   // 12 == sizeof(RFC rtp header) == kRtpMinParseLength, each CSRC=4 bytes
214   header->headerLength   = 12 + (CC * 4);
215   // not a full validation, just safety against underflow.  Padding must
216   // start after the header.  We can have 0 payload bytes left, note.
217   if (!secured &&
218       (header->paddingLength + header->headerLength > (size_t) length)) {
219     return false;
220   }
221 
222   for (uint8_t i = 0; i < CC; ++i) {
223     uint32_t CSRC = ByteReader<uint32_t>::ReadBigEndian(ptr);
224     ptr += 4;
225     header->arrOfCSRCs[i] = CSRC;
226   }
227   assert((ptr - _ptrRTPDataBegin) == (ptrdiff_t) header->headerLength);
228 
229   // If in effect, MAY be omitted for those packets for which the offset
230   // is zero.
231   header->extension.hasTransmissionTimeOffset = false;
232   header->extension.transmissionTimeOffset = 0;
233 
234   // May not be present in packet.
235   header->extension.hasAbsoluteSendTime = false;
236   header->extension.absoluteSendTime = 0;
237 
238   // May not be present in packet.
239   header->extension.hasAudioLevel = false;
240   header->extension.voiceActivity = false;
241   header->extension.audioLevel = 0;
242 
243   // May not be present in packet.
244   header->extension.hasVideoRotation = false;
245   header->extension.videoRotation = kVideoRotation_0;
246 
247   // May not be present in packet.
248   header->extension.playout_delay.min_ms = -1;
249   header->extension.playout_delay.max_ms = -1;
250 
251   // May not be present in packet.
252   header->extension.hasVideoContentType = false;
253   header->extension.videoContentType = VideoContentType::UNSPECIFIED;
254 
255   header->extension.has_video_timing = false;
256   header->extension.video_timing = {0u, 0u, 0u, 0u, 0u, 0u, false};
257 
258   if (X) {
259     /* RTP header extension, RFC 3550.
260      0                   1                   2                   3
261      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
262     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
263     |      defined by profile       |           length              |
264     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
265     |                        header extension                       |
266     |                             ....                              |
267     */
268     // earlier test ensures we have at least paddingLength bytes left
269     const ptrdiff_t remain = (_ptrRTPDataEnd - ptr) - header->paddingLength;
270     if (remain < 4) { // minimum header extension length = 32 bits
271       return false;
272     }
273 
274     header->headerLength += 4;
275 
276     uint16_t definedByProfile = ByteReader<uint16_t>::ReadBigEndian(ptr);
277     ptr += 2;
278 
279     // in 32 bit words
280     size_t XLen = ByteReader<uint16_t>::ReadBigEndian(ptr);
281     ptr += 2;
282     XLen *= 4;  // in bytes
283 
284     if (static_cast<size_t>(remain) < (4 + XLen)) {
285       return false;
286     }
287     static constexpr uint16_t kRtpOneByteHeaderExtensionId = 0xBEDE;
288     if (definedByProfile == kRtpOneByteHeaderExtensionId) {
289       const uint8_t* ptrRTPDataExtensionEnd = ptr + XLen;
290       ParseOneByteExtensionHeader(header,
291                                   ptrExtensionMap,
292                                   ptrRTPDataExtensionEnd,
293                                   ptr);
294     }
295     header->headerLength += XLen;
296   }
297   if (header->headerLength + header->paddingLength >
298       static_cast<size_t>(length))
299     return false;
300   return true;
301 }
302 
ParseOneByteExtensionHeader(RTPHeader * header,const RtpHeaderExtensionMap * ptrExtensionMap,const uint8_t * ptrRTPDataExtensionEnd,const uint8_t * ptr) const303 void RtpHeaderParser::ParseOneByteExtensionHeader(
304     RTPHeader* header,
305     const RtpHeaderExtensionMap* ptrExtensionMap,
306     const uint8_t* ptrRTPDataExtensionEnd,
307     const uint8_t* ptr) const {
308   if (!ptrExtensionMap) {
309     return;
310   }
311 
312   while (ptrRTPDataExtensionEnd - ptr > 0) {
313     //  0
314     //  0 1 2 3 4 5 6 7
315     // +-+-+-+-+-+-+-+-+
316     // |  ID   |  len  |
317     // +-+-+-+-+-+-+-+-+
318 
319     // Note that 'len' is the header extension element length, which is the
320     // number of bytes - 1.
321     const int id = (*ptr & 0xf0) >> 4;
322     const int len = (*ptr & 0x0f);
323     if (ptr + len + 1 > ptrRTPDataExtensionEnd) {
324       RTC_LOG(LS_WARNING)
325           << "RTP extension header length out of bounds. Terminate parsing.";
326       return;
327     }
328     ptr++;
329 
330     if (id == 0) {
331       // Padding byte, skip ignoring len.
332       continue;
333     }
334 
335     if (id == 15) {
336       RTC_LOG(LS_VERBOSE)
337           << "RTP extension header 15 encountered. Terminate parsing.";
338       return;
339     }
340 
341     if (ptrRTPDataExtensionEnd - ptr < (len + 1)) {
342       RTC_LOG(LS_WARNING) << "Incorrect one-byte extension len: " << (len + 1)
343                           << ", bytes left in buffer: "
344                           << (ptrRTPDataExtensionEnd - ptr);
345       return;
346     }
347 
348     RTPExtensionType type = ptrExtensionMap->GetType(id);
349     if (type == RtpHeaderExtensionMap::kInvalidType) {
350       // If we encounter an unknown extension, just skip over it.
351       // Mozilla - we reuse the parse for demux, without registering extensions.
352       // Reduce log-spam by switching to VERBOSE
353       RTC_LOG(LS_VERBOSE) << "Failed to find extension id: " << id;
354     } else {
355       switch (type) {
356         case kRtpExtensionTransmissionTimeOffset: {
357           if (len != 2) {
358             RTC_LOG(LS_WARNING)
359                 << "Incorrect transmission time offset len: " << len;
360             return;
361           }
362           //  0                   1                   2                   3
363           //  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
364           // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
365           // |  ID   | len=2 |              transmission offset              |
366           // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
367 
368           header->extension.transmissionTimeOffset =
369               ByteReader<int32_t, 3>::ReadBigEndian(ptr);
370           header->extension.hasTransmissionTimeOffset = true;
371           break;
372         }
373         case kRtpExtensionAudioLevel: {
374           if (len != 0) {
375             RTC_LOG(LS_WARNING) << "Incorrect audio level len: " << len;
376             return;
377           }
378           //  0                   1
379           //  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
380           // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
381           // |  ID   | len=0 |V|   level     |
382           // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
383           //
384           header->extension.audioLevel = ptr[0] & 0x7f;
385           header->extension.voiceActivity = (ptr[0] & 0x80) != 0;
386           header->extension.hasAudioLevel = true;
387           break;
388         }
389         case kRtpExtensionAbsoluteSendTime: {
390           if (len != 2) {
391             RTC_LOG(LS_WARNING) << "Incorrect absolute send time len: " << len;
392             return;
393           }
394           //  0                   1                   2                   3
395           //  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
396           // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
397           // |  ID   | len=2 |              absolute send time               |
398           // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
399 
400           header->extension.absoluteSendTime =
401               ByteReader<uint32_t, 3>::ReadBigEndian(ptr);
402           header->extension.hasAbsoluteSendTime = true;
403           break;
404         }
405         case kRtpExtensionVideoRotation: {
406           if (len != 0) {
407             RTC_LOG(LS_WARNING)
408                 << "Incorrect coordination of video coordination len: " << len;
409             return;
410           }
411           //  0                   1
412           //  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
413           // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
414           // |  ID   | len=0 |0 0 0 0 C F R R|
415           // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
416           header->extension.hasVideoRotation = true;
417           header->extension.videoRotation =
418               ConvertCVOByteToVideoRotation(ptr[0]);
419           break;
420         }
421         case kRtpExtensionTransportSequenceNumber: {
422           if (len != 1) {
423             RTC_LOG(LS_WARNING)
424                 << "Incorrect transport sequence number len: " << len;
425             return;
426           }
427           //   0                   1                   2
428           //   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
429           //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
430           //  |  ID   | L=1   |transport wide sequence number |
431           //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
432 
433           uint16_t sequence_number = ptr[0] << 8;
434           sequence_number += ptr[1];
435           header->extension.transportSequenceNumber = sequence_number;
436           header->extension.hasTransportSequenceNumber = true;
437           break;
438         }
439         case kRtpExtensionPlayoutDelay: {
440           if (len != 2) {
441             RTC_LOG(LS_WARNING) << "Incorrect playout delay len: " << len;
442             return;
443           }
444           //   0                   1                   2                   3
445           //   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
446           //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
447           //  |  ID   | len=2 |   MIN delay           |   MAX delay           |
448           //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
449 
450           int min_playout_delay = (ptr[0] << 4) | ((ptr[1] >> 4) & 0xf);
451           int max_playout_delay = ((ptr[1] & 0xf) << 8) | ptr[2];
452           header->extension.playout_delay.min_ms =
453               min_playout_delay * PlayoutDelayLimits::kGranularityMs;
454           header->extension.playout_delay.max_ms =
455               max_playout_delay * PlayoutDelayLimits::kGranularityMs;
456           break;
457         }
458         case kRtpExtensionVideoContentType: {
459           if (len != 0) {
460             RTC_LOG(LS_WARNING) << "Incorrect video content type len: " << len;
461             return;
462           }
463           //    0                   1
464           //    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
465           //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
466           //   |  ID   | len=0 | Content type  |
467           //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
468 
469           if (videocontenttypehelpers::IsValidContentType(ptr[0])) {
470             header->extension.hasVideoContentType = true;
471             header->extension.videoContentType =
472                 static_cast<VideoContentType>(ptr[0]);
473           }
474           break;
475         }
476         case kRtpExtensionVideoTiming: {
477           if (len != VideoTimingExtension::kValueSizeBytes - 1) {
478             RTC_LOG(LS_WARNING) << "Incorrect video timing len: " << len;
479             return;
480           }
481           header->extension.has_video_timing = true;
482           VideoTimingExtension::Parse(rtc::MakeArrayView(ptr, len + 1),
483                                       &header->extension.video_timing);
484           break;
485         }
486         case kRtpExtensionRtpStreamId: {
487           header->extension.stream_id.Set(rtc::MakeArrayView(ptr, len + 1));
488           break;
489         }
490         case kRtpExtensionRepairedRtpStreamId: {
491           header->extension.repaired_stream_id.Set(
492               rtc::MakeArrayView(ptr, len + 1));
493           break;
494         }
495         case kRtpExtensionMid: {
496           header->extension.mid.Set(rtc::MakeArrayView(ptr, len + 1));
497           break;
498         }
499         case kRtpExtensionCsrcAudioLevel: {
500           auto& levels = header->extension.csrcAudioLevels;
501           levels.numAudioLevels = static_cast<uint8_t>(len + 1);
502           if (levels.numAudioLevels > kRtpCsrcSize)  {
503             RTC_LOG(LS_WARNING) << "Incorrect number of CSRC audio levels: " <<
504                                    levels.numAudioLevels;
505             levels.numAudioLevels = 0;
506             return;
507           }
508           for (uint8_t i = 0; i < levels.numAudioLevels; i++) {
509             levels.arrOfAudioLevels[i] = ptr[i] & 0x7f;
510           }
511           break;
512         }
513         case kRtpExtensionNone:
514         case kRtpExtensionNumberOfExtensions: {
515           RTC_NOTREACHED() << "Invalid extension type: " << type;
516           return;
517         }
518       }
519     }
520     ptr += (len + 1);
521   }
522 }
523 
524 }  // namespace RtpUtility
525 }  // namespace webrtc
526