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