1/*
2 *  Copyright (c) 2014 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
12#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_H_
13#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_H_
14
15#include <map>
16#include <string>
17#include <vector>
18
19#include "webrtc/base/scoped_ptr.h"
20#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
21#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/dlrr.h"
22#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/report_block.h"
23#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/rrtr.h"
24#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/voip_metric.h"
25#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
26#include "webrtc/typedefs.h"
27
28namespace webrtc {
29namespace rtcp {
30
31static const int kCommonFbFmtLength = 12;
32static const int kReportBlockLength = 24;
33
34class RawPacket;
35
36// Class for building RTCP packets.
37//
38//  Example:
39//  ReportBlock report_block;
40//  report_block.To(234)
41//  report_block.FractionLost(10);
42//
43//  ReceiverReport rr;
44//  rr.From(123);
45//  rr.WithReportBlock(&report_block)
46//
47//  Fir fir;
48//  fir.From(123);
49//  fir.To(234)
50//  fir.WithCommandSeqNum(123);
51//
52//  size_t length = 0;                     // Builds an intra frame request
53//  uint8_t packet[kPacketSize];           // with sequence number 123.
54//  fir.Build(packet, &length, kPacketSize);
55//
56//  RawPacket packet = fir.Build();        // Returns a RawPacket holding
57//                                         // the built rtcp packet.
58//
59//  rr.Append(&fir)                        // Builds a compound RTCP packet with
60//  RawPacket packet = rr.Build();         // a receiver report, report block
61//                                         // and fir message.
62
63class RtcpPacket {
64 public:
65  virtual ~RtcpPacket() {}
66
67  void Append(RtcpPacket* packet);
68
69  // Callback used to signal that an RTCP packet is ready. Note that this may
70  // not contain all data in this RtcpPacket; if a packet cannot fit in
71  // max_length bytes, it will be fragmented and multiple calls to this
72  // callback will be made.
73  class PacketReadyCallback {
74   public:
75    PacketReadyCallback() {}
76    virtual ~PacketReadyCallback() {}
77
78    virtual void OnPacketReady(uint8_t* data, size_t length) = 0;
79  };
80
81  // Convenience method mostly used for test. Max length of IP_PACKET_SIZE is
82  // used, will cause assertion error if fragmentation occurs.
83  rtc::scoped_ptr<RawPacket> Build() const;
84
85  // Returns true if all calls to Create succeeded. A buffer of size
86  // IP_PACKET_SIZE will be allocated and reused between calls to callback.
87  bool Build(PacketReadyCallback* callback) const;
88
89  // Returns true if all calls to Create succeeded. Provided buffer reference
90  // will be used for all calls to callback.
91  bool BuildExternalBuffer(uint8_t* buffer,
92                           size_t max_length,
93                           PacketReadyCallback* callback) const;
94
95  // Size of this packet in bytes (including headers, excluding nested packets).
96  virtual size_t BlockLength() const = 0;
97
98 protected:
99  RtcpPacket() {}
100
101  virtual bool Create(uint8_t* packet,
102                      size_t* index,
103                      size_t max_length,
104                      PacketReadyCallback* callback) const = 0;
105
106  static void CreateHeader(uint8_t count_or_format,
107                           uint8_t packet_type,
108                           size_t block_length,  // Size in 32bit words - 1.
109                           uint8_t* buffer,
110                           size_t* pos);
111
112  bool OnBufferFull(uint8_t* packet,
113                    size_t* index,
114                    RtcpPacket::PacketReadyCallback* callback) const;
115
116  size_t HeaderLength() const;
117
118  static const size_t kHeaderLength = 4;
119  std::vector<RtcpPacket*> appended_packets_;
120
121 private:
122  bool CreateAndAddAppended(uint8_t* packet,
123                            size_t* index,
124                            size_t max_length,
125                            PacketReadyCallback* callback) const;
126};
127
128// TODO(sprang): Move RtcpPacket subclasses out to separate files.
129
130// RTCP sender report (RFC 3550).
131//
132//   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
133//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
134//  |V=2|P|    RC   |   PT=SR=200   |             length            |
135//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
136//  |                         SSRC of sender                        |
137//  +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
138//  |              NTP timestamp, most significant word             |
139//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
140//  |             NTP timestamp, least significant word             |
141//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
142//  |                         RTP timestamp                         |
143//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
144//  |                     sender's packet count                     |
145//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
146//  |                      sender's octet count                     |
147//  +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
148//  |                         report block(s)                       |
149//  |                            ....                               |
150
151class SenderReport : public RtcpPacket {
152 public:
153  SenderReport() : RtcpPacket() {
154    memset(&sr_, 0, sizeof(sr_));
155  }
156
157  virtual ~SenderReport() {}
158
159  void From(uint32_t ssrc) {
160    sr_.SenderSSRC = ssrc;
161  }
162  void WithNtpSec(uint32_t sec) {
163    sr_.NTPMostSignificant = sec;
164  }
165  void WithNtpFrac(uint32_t frac) {
166    sr_.NTPLeastSignificant = frac;
167  }
168  void WithRtpTimestamp(uint32_t rtp_timestamp) {
169    sr_.RTPTimestamp = rtp_timestamp;
170  }
171  void WithPacketCount(uint32_t packet_count) {
172    sr_.SenderPacketCount = packet_count;
173  }
174  void WithOctetCount(uint32_t octet_count) {
175    sr_.SenderOctetCount = octet_count;
176  }
177  bool WithReportBlock(const ReportBlock& block);
178
179 protected:
180  bool Create(uint8_t* packet,
181              size_t* index,
182              size_t max_length,
183              RtcpPacket::PacketReadyCallback* callback) const override;
184
185 private:
186  static const int kMaxNumberOfReportBlocks = 0x1f;
187
188  size_t BlockLength() const {
189    const size_t kSrHeaderLength = 8;
190    const size_t kSenderInfoLength = 20;
191    return kSrHeaderLength + kSenderInfoLength +
192           report_blocks_.size() * kReportBlockLength;
193  }
194
195  RTCPUtility::RTCPPacketSR sr_;
196  std::vector<ReportBlock> report_blocks_;
197
198  RTC_DISALLOW_COPY_AND_ASSIGN(SenderReport);
199};
200
201// Source Description (SDES) (RFC 3550).
202//
203//         0                   1                   2                   3
204//         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
205//        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
206// header |V=2|P|    SC   |  PT=SDES=202  |             length            |
207//        +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
208// chunk  |                          SSRC/CSRC_1                          |
209//   1    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
210//        |                           SDES items                          |
211//        |                              ...                              |
212//        +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
213// chunk  |                          SSRC/CSRC_2                          |
214//   2    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
215//        |                           SDES items                          |
216//        |                              ...                              |
217//        +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
218//
219// Canonical End-Point Identifier SDES Item (CNAME)
220//
221//    0                   1                   2                   3
222//    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
223//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
224//   |    CNAME=1    |     length    | user and domain name        ...
225//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
226
227class Sdes : public RtcpPacket {
228 public:
229  Sdes() : RtcpPacket() {}
230
231  virtual ~Sdes() {}
232
233  bool WithCName(uint32_t ssrc, const std::string& cname);
234
235  struct Chunk {
236    uint32_t ssrc;
237    std::string name;
238    int null_octets;
239  };
240
241 protected:
242  bool Create(uint8_t* packet,
243              size_t* index,
244              size_t max_length,
245              RtcpPacket::PacketReadyCallback* callback) const override;
246
247 private:
248  static const int kMaxNumberOfChunks = 0x1f;
249
250  size_t BlockLength() const;
251
252  std::vector<Chunk> chunks_;
253
254  RTC_DISALLOW_COPY_AND_ASSIGN(Sdes);
255};
256
257// Reference picture selection indication (RPSI) (RFC 4585).
258//
259// FCI:
260//
261//    0                   1                   2                   3
262//    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
263//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
264//   |      PB       |0| Payload Type|    Native RPSI bit string     |
265//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
266//   |   defined per codec          ...                | Padding (0) |
267//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
268
269class Rpsi : public RtcpPacket {
270 public:
271  Rpsi()
272      : RtcpPacket(),
273        padding_bytes_(0) {
274    memset(&rpsi_, 0, sizeof(rpsi_));
275  }
276
277  virtual ~Rpsi() {}
278
279  void From(uint32_t ssrc) {
280    rpsi_.SenderSSRC = ssrc;
281  }
282  void To(uint32_t ssrc) {
283    rpsi_.MediaSSRC = ssrc;
284  }
285  void WithPayloadType(uint8_t payload) {
286    assert(payload <= 0x7f);
287    rpsi_.PayloadType = payload;
288  }
289  void WithPictureId(uint64_t picture_id);
290
291 protected:
292  bool Create(uint8_t* packet,
293              size_t* index,
294              size_t max_length,
295              RtcpPacket::PacketReadyCallback* callback) const override;
296
297 private:
298  size_t BlockLength() const {
299    size_t fci_length = 2 + (rpsi_.NumberOfValidBits / 8) + padding_bytes_;
300    return kCommonFbFmtLength + fci_length;
301  }
302
303  uint8_t padding_bytes_;
304  RTCPUtility::RTCPPacketPSFBRPSI rpsi_;
305
306  RTC_DISALLOW_COPY_AND_ASSIGN(Rpsi);
307};
308
309// Full intra request (FIR) (RFC 5104).
310//
311// FCI:
312//
313//    0                   1                   2                   3
314//    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
315//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
316//   |                              SSRC                             |
317//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
318//   | Seq nr.       |    Reserved                                   |
319//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
320
321class Fir : public RtcpPacket {
322 public:
323  Fir() : RtcpPacket() {
324    memset(&fir_, 0, sizeof(fir_));
325    memset(&fir_item_, 0, sizeof(fir_item_));
326  }
327
328  virtual ~Fir() {}
329
330  void From(uint32_t ssrc) {
331    fir_.SenderSSRC = ssrc;
332  }
333  void To(uint32_t ssrc) {
334    fir_item_.SSRC = ssrc;
335  }
336  void WithCommandSeqNum(uint8_t seq_num) {
337    fir_item_.CommandSequenceNumber = seq_num;
338  }
339
340 protected:
341  bool Create(uint8_t* packet,
342              size_t* index,
343              size_t max_length,
344              RtcpPacket::PacketReadyCallback* callback) const override;
345
346 private:
347  size_t BlockLength() const {
348    const size_t kFciLength = 8;
349    return kCommonFbFmtLength + kFciLength;
350  }
351
352  RTCPUtility::RTCPPacketPSFBFIR fir_;
353  RTCPUtility::RTCPPacketPSFBFIRItem fir_item_;
354};
355
356// Receiver Estimated Max Bitrate (REMB) (draft-alvestrand-rmcat-remb).
357//
358//    0                   1                   2                   3
359//    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
360//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
361//   |V=2|P| FMT=15  |   PT=206      |             length            |
362//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
363//   |                  SSRC of packet sender                        |
364//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
365//   |                  SSRC of media source                         |
366//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
367//   |  Unique identifier 'R' 'E' 'M' 'B'                            |
368//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
369//   |  Num SSRC     | BR Exp    |  BR Mantissa                      |
370//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
371//   |   SSRC feedback                                               |
372//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
373//   |  ...
374
375class Remb : public RtcpPacket {
376 public:
377  Remb() : RtcpPacket() {
378    memset(&remb_, 0, sizeof(remb_));
379    memset(&remb_item_, 0, sizeof(remb_item_));
380  }
381
382  virtual ~Remb() {}
383
384  void From(uint32_t ssrc) {
385    remb_.SenderSSRC = ssrc;
386  }
387  void AppliesTo(uint32_t ssrc);
388
389  void WithBitrateBps(uint32_t bitrate_bps) {
390    remb_item_.BitRate = bitrate_bps;
391  }
392
393 protected:
394  bool Create(uint8_t* packet,
395              size_t* index,
396              size_t max_length,
397              RtcpPacket::PacketReadyCallback* callback) const override;
398
399 private:
400  static const int kMaxNumberOfSsrcs = 0xff;
401
402  size_t BlockLength() const {
403    return (remb_item_.NumberOfSSRCs + 5) * 4;
404  }
405
406  RTCPUtility::RTCPPacketPSFBAPP remb_;
407  RTCPUtility::RTCPPacketPSFBREMBItem remb_item_;
408
409  RTC_DISALLOW_COPY_AND_ASSIGN(Remb);
410};
411
412// From RFC 3611: RTP Control Protocol Extended Reports (RTCP XR).
413//
414// Format for XR packets:
415//
416//   0                   1                   2                   3
417//   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
418//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
419//  |V=2|P|reserved |   PT=XR=207   |             length            |
420//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
421//  |                              SSRC                             |
422//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
423//  :                         report blocks                         :
424//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
425
426class Xr : public RtcpPacket {
427 public:
428  typedef std::vector<RTCPUtility::RTCPPacketXRDLRRReportBlockItem> DlrrBlock;
429  Xr() : RtcpPacket() {
430    memset(&xr_header_, 0, sizeof(xr_header_));
431  }
432
433  virtual ~Xr() {}
434
435  void From(uint32_t ssrc) {
436    xr_header_.OriginatorSSRC = ssrc;
437  }
438
439  // Max 50 items of each of {Rrtr, Dlrr, VoipMetric} allowed per Xr.
440  bool WithRrtr(Rrtr* rrtr);
441  bool WithDlrr(Dlrr* dlrr);
442  bool WithVoipMetric(VoipMetric* voip_metric);
443
444 protected:
445  bool Create(uint8_t* packet,
446              size_t* index,
447              size_t max_length,
448              RtcpPacket::PacketReadyCallback* callback) const override;
449
450 private:
451  static const int kMaxNumberOfRrtrBlocks = 50;
452  static const int kMaxNumberOfDlrrBlocks = 50;
453  static const int kMaxNumberOfVoipMetricBlocks = 50;
454
455  size_t BlockLength() const {
456    const size_t kXrHeaderLength = 8;
457    return kXrHeaderLength + RrtrLength() + DlrrLength() + VoipMetricLength();
458  }
459
460  size_t RrtrLength() const { return Rrtr::kLength * rrtr_blocks_.size(); }
461
462  size_t DlrrLength() const;
463
464  size_t VoipMetricLength() const {
465    return VoipMetric::kLength * voip_metric_blocks_.size();
466  }
467
468  RTCPUtility::RTCPPacketXR xr_header_;
469  std::vector<Rrtr> rrtr_blocks_;
470  std::vector<Dlrr> dlrr_blocks_;
471  std::vector<VoipMetric> voip_metric_blocks_;
472
473  RTC_DISALLOW_COPY_AND_ASSIGN(Xr);
474};
475
476// Class holding a RTCP packet.
477//
478// Takes a built rtcp packet.
479//  RawPacket raw_packet(buffer, length);
480//
481// To access the raw packet:
482//  raw_packet.Buffer();         - pointer to the raw packet
483//  raw_packet.BufferLength();   - the length of the raw packet
484
485class RawPacket {
486 public:
487  explicit RawPacket(size_t buffer_length);
488  RawPacket(const uint8_t* packet, size_t packet_length);
489
490  const uint8_t* Buffer() const;
491  uint8_t* MutableBuffer();
492  size_t BufferLength() const;
493  size_t Length() const;
494  void SetLength(size_t length);
495
496 private:
497  const size_t buffer_length_;
498  size_t length_;
499  rtc::scoped_ptr<uint8_t[]> buffer_;
500};
501
502}  // namespace rtcp
503}  // namespace webrtc
504#endif  // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_H_
505