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/source/byte_io.h"
17
18 namespace webrtc {
19
NullObjectRtpData()20 RtpData* NullObjectRtpData() {
21 static NullRtpData null_rtp_data;
22 return &null_rtp_data;
23 }
24
NullObjectRtpFeedback()25 RtpFeedback* NullObjectRtpFeedback() {
26 static NullRtpFeedback null_rtp_feedback;
27 return &null_rtp_feedback;
28 }
29
NullObjectRtpAudioFeedback()30 RtpAudioFeedback* NullObjectRtpAudioFeedback() {
31 static NullRtpAudioFeedback null_rtp_audio_feedback;
32 return &null_rtp_audio_feedback;
33 }
34
NullObjectReceiveStatistics()35 ReceiveStatistics* NullObjectReceiveStatistics() {
36 static NullReceiveStatistics null_receive_statistics;
37 return &null_receive_statistics;
38 }
39
40 namespace RtpUtility {
41
42 enum {
43 kRtcpExpectedVersion = 2,
44 kRtcpMinHeaderLength = 4,
45 kRtcpMinParseLength = 8,
46
47 kRtpExpectedVersion = 2,
48 kRtpMinParseLength = 12
49 };
50
51 /*
52 * Misc utility routines
53 */
54
55 #if defined(_WIN32)
StringCompare(const char * str1,const char * str2,const uint32_t length)56 bool StringCompare(const char* str1, const char* str2,
57 const uint32_t length) {
58 return _strnicmp(str1, str2, length) == 0;
59 }
60 #elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
StringCompare(const char * str1,const char * str2,const uint32_t length)61 bool StringCompare(const char* str1, const char* str2,
62 const uint32_t length) {
63 return strncasecmp(str1, str2, length) == 0;
64 }
65 #endif
66
Word32Align(size_t size)67 size_t Word32Align(size_t size) {
68 uint32_t remainder = size % 4;
69 if (remainder != 0)
70 return size + 4 - remainder;
71 return size;
72 }
73
RtpHeaderParser(const uint8_t * rtpData,const size_t rtpDataLength)74 RtpHeaderParser::RtpHeaderParser(const uint8_t* rtpData,
75 const size_t rtpDataLength)
76 : _ptrRTPDataBegin(rtpData),
77 _ptrRTPDataEnd(rtpData ? (rtpData + rtpDataLength) : NULL) {
78 }
79
~RtpHeaderParser()80 RtpHeaderParser::~RtpHeaderParser() {
81 }
82
RTCP() const83 bool RtpHeaderParser::RTCP() const {
84 // 72 to 76 is reserved for RTP
85 // 77 to 79 is not reserver but they are not assigned we will block them
86 // for RTCP 200 SR == marker bit + 72
87 // for RTCP 204 APP == marker bit + 76
88 /*
89 * RTCP
90 *
91 * FIR full INTRA-frame request 192 [RFC2032] supported
92 * NACK negative acknowledgement 193 [RFC2032]
93 * IJ Extended inter-arrival jitter report 195 [RFC-ietf-avt-rtp-toff
94 * set-07.txt] http://tools.ietf.org/html/draft-ietf-avt-rtp-toffset-07
95 * SR sender report 200 [RFC3551] supported
96 * RR receiver report 201 [RFC3551] supported
97 * SDES source description 202 [RFC3551] supported
98 * BYE goodbye 203 [RFC3551] supported
99 * APP application-defined 204 [RFC3551] ignored
100 * RTPFB Transport layer FB message 205 [RFC4585] supported
101 * PSFB Payload-specific FB message 206 [RFC4585] supported
102 * XR extended report 207 [RFC3611] supported
103 */
104
105 /* 205 RFC 5104
106 * FMT 1 NACK supported
107 * FMT 2 reserved
108 * FMT 3 TMMBR supported
109 * FMT 4 TMMBN supported
110 */
111
112 /* 206 RFC 5104
113 * FMT 1: Picture Loss Indication (PLI) supported
114 * FMT 2: Slice Lost Indication (SLI)
115 * FMT 3: Reference Picture Selection Indication (RPSI)
116 * FMT 4: Full Intra Request (FIR) Command supported
117 * FMT 5: Temporal-Spatial Trade-off Request (TSTR)
118 * FMT 6: Temporal-Spatial Trade-off Notification (TSTN)
119 * FMT 7: Video Back Channel Message (VBCM)
120 * FMT 15: Application layer FB message
121 */
122
123 const ptrdiff_t length = _ptrRTPDataEnd - _ptrRTPDataBegin;
124 if (length < kRtcpMinHeaderLength) {
125 return false;
126 }
127
128 const uint8_t V = _ptrRTPDataBegin[0] >> 6;
129 if (V != kRtcpExpectedVersion) {
130 return false;
131 }
132
133 const uint8_t payloadType = _ptrRTPDataBegin[1];
134 switch (payloadType) {
135 case 192:
136 return true;
137 case 193:
138 // not supported
139 // pass through and check for a potential RTP packet
140 return false;
141 case 195:
142 case 200:
143 case 201:
144 case 202:
145 case 203:
146 case 204:
147 case 205:
148 case 206:
149 case 207:
150 return true;
151 default:
152 return false;
153 }
154 }
155
ParseRtcp(RTPHeader * header) const156 bool RtpHeaderParser::ParseRtcp(RTPHeader* header) const {
157 assert(header != NULL);
158
159 const ptrdiff_t length = _ptrRTPDataEnd - _ptrRTPDataBegin;
160 if (length < kRtcpMinParseLength) {
161 return false;
162 }
163
164 const uint8_t V = _ptrRTPDataBegin[0] >> 6;
165 if (V != kRtcpExpectedVersion) {
166 return false;
167 }
168
169 const uint8_t PT = _ptrRTPDataBegin[1];
170 const size_t len = (_ptrRTPDataBegin[2] << 8) + _ptrRTPDataBegin[3];
171 const uint8_t* ptr = &_ptrRTPDataBegin[4];
172
173 uint32_t SSRC = ByteReader<uint32_t>::ReadBigEndian(ptr);
174 ptr += 4;
175
176 header->payloadType = PT;
177 header->ssrc = SSRC;
178 header->headerLength = 4 + (len << 2);
179
180 return true;
181 }
182
Parse(RTPHeader * header,RtpHeaderExtensionMap * ptrExtensionMap) const183 bool RtpHeaderParser::Parse(RTPHeader* header,
184 RtpHeaderExtensionMap* ptrExtensionMap) 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 const size_t CSRCocts = CC * 4;
217
218 if ((ptr + CSRCocts) > _ptrRTPDataEnd) {
219 return false;
220 }
221
222 header->markerBit = M;
223 header->payloadType = PT;
224 header->sequenceNumber = sequenceNumber;
225 header->timestamp = RTPTimestamp;
226 header->ssrc = SSRC;
227 header->numCSRCs = CC;
228 header->paddingLength = P ? *(_ptrRTPDataEnd - 1) : 0;
229
230 for (uint8_t i = 0; i < CC; ++i) {
231 uint32_t CSRC = ByteReader<uint32_t>::ReadBigEndian(ptr);
232 ptr += 4;
233 header->arrOfCSRCs[i] = CSRC;
234 }
235
236 header->headerLength = 12 + CSRCocts;
237
238 // If in effect, MAY be omitted for those packets for which the offset
239 // is zero.
240 header->extension.hasTransmissionTimeOffset = false;
241 header->extension.transmissionTimeOffset = 0;
242
243 // May not be present in packet.
244 header->extension.hasAbsoluteSendTime = false;
245 header->extension.absoluteSendTime = 0;
246
247 // May not be present in packet.
248 header->extension.hasAudioLevel = false;
249 header->extension.voiceActivity = false;
250 header->extension.audioLevel = 0;
251
252 // May not be present in packet.
253 header->extension.hasVideoRotation = false;
254 header->extension.videoRotation = 0;
255
256 if (X) {
257 /* RTP header extension, RFC 3550.
258 0 1 2 3
259 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
260 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
261 | defined by profile | length |
262 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
263 | header extension |
264 | .... |
265 */
266 const ptrdiff_t remain = _ptrRTPDataEnd - ptr;
267 if (remain < 4) {
268 return false;
269 }
270
271 header->headerLength += 4;
272
273 uint16_t definedByProfile = ByteReader<uint16_t>::ReadBigEndian(ptr);
274 ptr += 2;
275
276 // in 32 bit words
277 size_t XLen = ByteReader<uint16_t>::ReadBigEndian(ptr);
278 ptr += 2;
279 XLen *= 4; // in bytes
280
281 if (static_cast<size_t>(remain) < (4 + XLen)) {
282 return false;
283 }
284 if (definedByProfile == kRtpOneByteHeaderExtensionId) {
285 const uint8_t* ptrRTPDataExtensionEnd = ptr + XLen;
286 ParseOneByteExtensionHeader(header,
287 ptrExtensionMap,
288 ptrRTPDataExtensionEnd,
289 ptr);
290 }
291 header->headerLength += XLen;
292 }
293 if (header->headerLength + header->paddingLength >
294 static_cast<size_t>(length))
295 return false;
296 return true;
297 }
298
ParseOneByteExtensionHeader(RTPHeader * header,const RtpHeaderExtensionMap * ptrExtensionMap,const uint8_t * ptrRTPDataExtensionEnd,const uint8_t * ptr) const299 void RtpHeaderParser::ParseOneByteExtensionHeader(
300 RTPHeader* header,
301 const RtpHeaderExtensionMap* ptrExtensionMap,
302 const uint8_t* ptrRTPDataExtensionEnd,
303 const uint8_t* ptr) const {
304 if (!ptrExtensionMap) {
305 return;
306 }
307
308 while (ptrRTPDataExtensionEnd - ptr > 0) {
309 // 0
310 // 0 1 2 3 4 5 6 7
311 // +-+-+-+-+-+-+-+-+
312 // | ID | len |
313 // +-+-+-+-+-+-+-+-+
314
315 // Note that 'len' is the header extension element length, which is the
316 // number of bytes - 1.
317 const int id = (*ptr & 0xf0) >> 4;
318 const int len = (*ptr & 0x0f);
319 ptr++;
320
321 if (id == 15) {
322 LOG(LS_WARNING)
323 << "RTP extension header 15 encountered. Terminate parsing.";
324 return;
325 }
326
327 RTPExtensionType type;
328 if (ptrExtensionMap->GetType(id, &type) != 0) {
329 // If we encounter an unknown extension, just skip over it.
330 LOG(LS_WARNING) << "Failed to find extension id: " << id;
331 } else {
332 switch (type) {
333 case kRtpExtensionTransmissionTimeOffset: {
334 if (len != 2) {
335 LOG(LS_WARNING) << "Incorrect transmission time offset len: "
336 << len;
337 return;
338 }
339 // 0 1 2 3
340 // 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
341 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
342 // | ID | len=2 | transmission offset |
343 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
344
345 header->extension.transmissionTimeOffset =
346 ByteReader<int32_t, 3>::ReadBigEndian(ptr);
347 header->extension.hasTransmissionTimeOffset = true;
348 break;
349 }
350 case kRtpExtensionAudioLevel: {
351 if (len != 0) {
352 LOG(LS_WARNING) << "Incorrect audio level len: " << len;
353 return;
354 }
355 // 0 1
356 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
357 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
358 // | ID | len=0 |V| level |
359 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
360 //
361 header->extension.audioLevel = ptr[0] & 0x7f;
362 header->extension.voiceActivity = (ptr[0] & 0x80) != 0;
363 header->extension.hasAudioLevel = true;
364 break;
365 }
366 case kRtpExtensionAbsoluteSendTime: {
367 if (len != 2) {
368 LOG(LS_WARNING) << "Incorrect absolute send time len: " << len;
369 return;
370 }
371 // 0 1 2 3
372 // 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
373 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
374 // | ID | len=2 | absolute send time |
375 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
376
377 header->extension.absoluteSendTime =
378 ByteReader<uint32_t, 3>::ReadBigEndian(ptr);
379 header->extension.hasAbsoluteSendTime = true;
380 break;
381 }
382 case kRtpExtensionVideoRotation: {
383 if (len != 0) {
384 LOG(LS_WARNING)
385 << "Incorrect coordination of video coordination len: " << len;
386 return;
387 }
388 // 0 1
389 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
390 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
391 // | ID | len=0 |0 0 0 0 C F R R|
392 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
393 header->extension.hasVideoRotation = true;
394 header->extension.videoRotation = ptr[0];
395 break;
396 }
397 case kRtpExtensionTransportSequenceNumber: {
398 if (len != 1) {
399 LOG(LS_WARNING) << "Incorrect transport sequence number len: "
400 << len;
401 return;
402 }
403 // 0 1 2
404 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
405 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
406 // | ID | L=1 |transport wide sequence number |
407 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
408
409 uint16_t sequence_number = ptr[0] << 8;
410 sequence_number += ptr[1];
411 header->extension.transportSequenceNumber = sequence_number;
412 header->extension.hasTransportSequenceNumber = true;
413 break;
414 }
415 default: {
416 LOG(LS_WARNING) << "Extension type not implemented: " << type;
417 return;
418 }
419 }
420 }
421 ptr += (len + 1);
422 uint8_t num_bytes = ParsePaddingBytes(ptrRTPDataExtensionEnd, ptr);
423 ptr += num_bytes;
424 }
425 }
426
ParsePaddingBytes(const uint8_t * ptrRTPDataExtensionEnd,const uint8_t * ptr) const427 uint8_t RtpHeaderParser::ParsePaddingBytes(
428 const uint8_t* ptrRTPDataExtensionEnd,
429 const uint8_t* ptr) const {
430 uint8_t num_zero_bytes = 0;
431 while (ptrRTPDataExtensionEnd - ptr > 0) {
432 if (*ptr != 0) {
433 return num_zero_bytes;
434 }
435 ptr++;
436 num_zero_bytes++;
437 }
438 return num_zero_bytes;
439 }
440 } // namespace RtpUtility
441 } // namespace webrtc
442