/// <summary> /// Parses RTP compound packet. /// </summary> /// <param name="buffer">Data buffer..</param> /// <param name="count">Number of bytes in the <b>buffer</b>.</param> /// <returns>Returns parsed RTP packet.</returns> public static RTCP_CompoundPacket Parse(byte[] buffer, int count) { /* Compound packet stucture: * Encryption prefix * If and only if the compound packet is to be encrypted, it is prefixed by a * random 32-bit quantity redrawn for every compound packet transmitted. * * SR or RR * The first RTCP packet in the compound packet must always be a report * packet to facilitate header validation as described in Appendix A.2. * This is true even if no data has been sent nor received, in which case an * empty RR is sent, and even if the only other RTCP packet in the compound packet is a BYE. * * Additional RRs * If the number of sources for which reception statistics are being reported * exceeds 31, the number that will fit into one SR or RR packet, then additional * RR packets should follow the initial report packet. * * SDES * An SDES packet containing a CNAME item must be included in each compound RTCP packet. * Other source description items may optionally be included if required by a particular * application, subject to bandwidth constraints (see Section 6.2.2). * * BYE or APP * Other RTCP packet types, including those yet to be defined, may follow in any order, * except that BYE should be the last packet sent with a given SSRC/CSRC. * Packet types may appear more than once. */ int offset = 0; RTCP_CompoundPacket packet = new RTCP_CompoundPacket(); while (offset < count) { try{ packet.m_pPackets.Add(RTCP_Packet.Parse(buffer, ref offset)); } catch { // Skip invalid or unknown packets. } } return(packet); }
/// <summary> /// Validates RTCP compound packet. /// </summary> /// <exception cref="ArgumentException">Is raised when invalid RTCP compound packet.</exception> public void Validate() { /* RFC 3550 A.2 RTCP Header Validity Checks. * The following checks should be applied to RTCP packets. * * o RTP version field must equal 2. * * o The payload type field of the first RTCP packet in a compound * packet must be equal to SR or RR. * * o The padding bit (P) should be zero for the first packet of a * compound RTCP packet because padding should only be applied, if it * is needed, to the last packet. * * o The length fields of the individual RTCP packets must add up to * the overall length of the compound RTCP packet as received. This * is a fairly strong check. */ if (m_pPackets.Count == 0) { throw new ArgumentException("No RTCP packets."); } // Check version and padding. for (int i = 0; i < m_pPackets.Count; i++) { RTCP_Packet packet = m_pPackets[i]; if (packet.Version != 2) { throw new ArgumentException("RTP version field must equal 2."); } if (i < (m_pPackets.Count - 1) && packet.IsPadded) { throw new ArgumentException("Only the last packet in RTCP compound packet may be padded."); } } // The first RTCP packet in a compound packet must be equal to SR or RR. if (m_pPackets[0].Type != RTCP_PacketType.SR || m_pPackets[0].Type != RTCP_PacketType.RR) { throw new ArgumentException("The first RTCP packet in a compound packet must be equal to SR or RR."); } }