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 TEST_RTCP_PACKET_PARSER_H_
13 #define TEST_RTCP_PACKET_PARSER_H_
14 
15 #include <stddef.h>
16 #include <stdint.h>
17 
18 #include "api/array_view.h"
19 #include "modules/rtp_rtcp/source/rtcp_packet/app.h"
20 #include "modules/rtp_rtcp/source/rtcp_packet/bye.h"
21 #include "modules/rtp_rtcp/source/rtcp_packet/common_header.h"
22 #include "modules/rtp_rtcp/source/rtcp_packet/extended_jitter_report.h"
23 #include "modules/rtp_rtcp/source/rtcp_packet/extended_reports.h"
24 #include "modules/rtp_rtcp/source/rtcp_packet/fir.h"
25 #include "modules/rtp_rtcp/source/rtcp_packet/loss_notification.h"
26 #include "modules/rtp_rtcp/source/rtcp_packet/nack.h"
27 #include "modules/rtp_rtcp/source/rtcp_packet/pli.h"
28 #include "modules/rtp_rtcp/source/rtcp_packet/rapid_resync_request.h"
29 #include "modules/rtp_rtcp/source/rtcp_packet/receiver_report.h"
30 #include "modules/rtp_rtcp/source/rtcp_packet/remb.h"
31 #include "modules/rtp_rtcp/source/rtcp_packet/sdes.h"
32 #include "modules/rtp_rtcp/source/rtcp_packet/sender_report.h"
33 #include "modules/rtp_rtcp/source/rtcp_packet/tmmbn.h"
34 #include "modules/rtp_rtcp/source/rtcp_packet/tmmbr.h"
35 #include "modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
36 #include "rtc_base/checks.h"
37 
38 namespace webrtc {
39 namespace test {
40 // Parse RTCP packet of given type. Assumes RTCP header is valid and that there
41 // is excatly one packet of correct type in the buffer.
42 template <typename Packet>
ParseSinglePacket(const uint8_t * buffer,size_t size,Packet * packet)43 bool ParseSinglePacket(const uint8_t* buffer, size_t size, Packet* packet) {
44   rtcp::CommonHeader header;
45   RTC_CHECK(header.Parse(buffer, size));
46   RTC_CHECK_EQ(size, header.NextPacket() - buffer);
47   return packet->Parse(header);
48 }
49 // Same function, but takes raw buffer as single argument instead of pair.
50 template <typename Packet>
ParseSinglePacket(rtc::ArrayView<const uint8_t> buffer,Packet * packet)51 bool ParseSinglePacket(rtc::ArrayView<const uint8_t> buffer, Packet* packet) {
52   return ParseSinglePacket(buffer.data(), buffer.size(), packet);
53 }
54 
55 class RtcpPacketParser {
56  public:
57   // Keeps last parsed packet, count number of parsed packets of given type.
58   template <typename TypedRtcpPacket>
59   class PacketCounter : public TypedRtcpPacket {
60    public:
num_packets()61     int num_packets() const { return num_packets_; }
Parse(const rtcp::CommonHeader & header)62     void Parse(const rtcp::CommonHeader& header) {
63       if (TypedRtcpPacket::Parse(header))
64         ++num_packets_;
65     }
Parse(const rtcp::CommonHeader & header,uint32_t * sender_ssrc)66     bool Parse(const rtcp::CommonHeader& header, uint32_t* sender_ssrc) {
67       const bool result = TypedRtcpPacket::Parse(header);
68       if (result) {
69         ++num_packets_;
70         if (*sender_ssrc == 0)  // Use first sender ssrc in compound packet.
71           *sender_ssrc = TypedRtcpPacket::sender_ssrc();
72       }
73       return result;
74     }
75 
76    private:
77     int num_packets_ = 0;
78   };
79 
80   RtcpPacketParser();
81   ~RtcpPacketParser();
82 
83   bool Parse(const void* packet, size_t packet_len);
84 
app()85   PacketCounter<rtcp::App>* app() { return &app_; }
bye()86   PacketCounter<rtcp::Bye>* bye() { return &bye_; }
ij()87   PacketCounter<rtcp::ExtendedJitterReport>* ij() { return &ij_; }
xr()88   PacketCounter<rtcp::ExtendedReports>* xr() { return &xr_; }
fir()89   PacketCounter<rtcp::Fir>* fir() { return &fir_; }
nack()90   PacketCounter<rtcp::Nack>* nack() { return &nack_; }
pli()91   PacketCounter<rtcp::Pli>* pli() { return &pli_; }
rrr()92   PacketCounter<rtcp::RapidResyncRequest>* rrr() { return &rrr_; }
receiver_report()93   PacketCounter<rtcp::ReceiverReport>* receiver_report() {
94     return &receiver_report_;
95   }
loss_notification()96   PacketCounter<rtcp::LossNotification>* loss_notification() {
97     return &loss_notification_;
98   }
remb()99   PacketCounter<rtcp::Remb>* remb() { return &remb_; }
sdes()100   PacketCounter<rtcp::Sdes>* sdes() { return &sdes_; }
sender_report()101   PacketCounter<rtcp::SenderReport>* sender_report() { return &sender_report_; }
tmmbn()102   PacketCounter<rtcp::Tmmbn>* tmmbn() { return &tmmbn_; }
tmmbr()103   PacketCounter<rtcp::Tmmbr>* tmmbr() { return &tmmbr_; }
transport_feedback()104   PacketCounter<rtcp::TransportFeedback>* transport_feedback() {
105     return &transport_feedback_;
106   }
sender_ssrc()107   uint32_t sender_ssrc() const { return sender_ssrc_; }
processed_rtcp_packets()108   size_t processed_rtcp_packets() const { return processed_rtcp_packets_; }
109 
110  private:
111   PacketCounter<rtcp::App> app_;
112   PacketCounter<rtcp::Bye> bye_;
113   PacketCounter<rtcp::ExtendedJitterReport> ij_;
114   PacketCounter<rtcp::ExtendedReports> xr_;
115   PacketCounter<rtcp::Fir> fir_;
116   PacketCounter<rtcp::Nack> nack_;
117   PacketCounter<rtcp::Pli> pli_;
118   PacketCounter<rtcp::RapidResyncRequest> rrr_;
119   PacketCounter<rtcp::ReceiverReport> receiver_report_;
120   PacketCounter<rtcp::LossNotification> loss_notification_;
121   PacketCounter<rtcp::Remb> remb_;
122   PacketCounter<rtcp::Sdes> sdes_;
123   PacketCounter<rtcp::SenderReport> sender_report_;
124   PacketCounter<rtcp::Tmmbn> tmmbn_;
125   PacketCounter<rtcp::Tmmbr> tmmbr_;
126   PacketCounter<rtcp::TransportFeedback> transport_feedback_;
127   uint32_t sender_ssrc_ = 0;
128   size_t processed_rtcp_packets_ = 0;
129 };
130 
131 }  // namespace test
132 }  // namespace webrtc
133 #endif  // TEST_RTCP_PACKET_PARSER_H_
134