/// <summary> /// Converts a generic RtcpPacket into a specific RtcpPacket type and forwards it to the /// appropriate method to be processed /// </summary> /// <param name="packet">Generic RtcpPacket</param> /// <param name="ipAddress">IPAddress packet was received from</param> private void ProcessPacket(RtcpPacket packet, IPAddress ipAddress) { switch(packet.PacketType) { case (byte)Rtcp.PacketType.SR: { ProcessSRPacket(new SrPacket(packet), ipAddress); break; } case (byte)Rtcp.PacketType.RR: { ProcessRRPacket(new RrPacket(packet), ipAddress); break; } case (byte)Rtcp.PacketType.SDES: { ProcessSDESPacket(new SdesPacket(packet), ipAddress); break; } case (byte)Rtcp.PacketType.BYE: { ProcessBYEPacket(new ByePacket(packet), ipAddress); break; } case (byte)Rtcp.PacketType.APP: { ProcessAPPPacket(new AppPacket(packet)); break; } default: { eventLog.WriteEntry("Received an unhandled Rtcp type, " + packet.ToString(), EventLogEntryType.Warning, (int)RtpEL.ID.UnhandledRtcpType); break; } } }
internal void AddPacket(RtcpPacket packet) { packet.WriteToBuffer(buffer); }
/// <summary> /// Called immediately after the buffer is populated by the network listener /// It parses RtcpPackets and rigorously validates them /// </summary> internal void ParseBuffer() { // See if the packet ends on a 32 bit boundary as it should if(buffer.Length % 4 != 0) { throw new CompoundPacketException("Compound packets must end on a 32 bit boundary"); } // Parse all data in the buffer while(buffer.Length > 0) { // Retrieve the next packet from the buffer // RTCP Version will be validated by RtcpHeader in the generic RtcpPacket RtcpPacket packet = new RtcpPacket(buffer); // Check a couple of facts if the padding bit is set if(packet.Padding == true) { // Can't be set on the first packet if(packets.Count == 0) { throw new CompoundPacketException("You can't set the padding bit on the first packet"); } else { // There must be as many padding octets as the the last octet claims int octets = 0; byte octet = 0; while(buffer.Length > 0) { octet = buffer.NextByte(); octets++; } // Last octet contains the count of padding octets if(octet != octets) { throw new CompoundPacketException(string.Format( "There is a discrepancy between the number of padding bytes - " + "actual: {0}, expected: {1}", octets, octet)); } } } packets.Enqueue(packet); } // It must be a compound packet if(packets.Count <= 1) { throw new CompoundPacketException(string.Format( "A compound RTCP packet must contain more than 1 packet, actual count: {0}", packets.Count)); } // First packet must be an SR or RR byte pt = ((RtcpPacket)packets.Peek()).PacketType; if((pt != (byte)Rtcp.PacketType.SR) && (pt != (byte)Rtcp.PacketType.RR)) { throw new CompoundPacketException(string.Format( "The first packet in a compound RTCP packet must be an SR: {0} or RR: {1}, " + "actual: {2}", (byte)Rtcp.PacketType.SR, (byte)Rtcp.PacketType.RR, pt)); } }
/// <summary> /// Construct a ReceiverReport packet from an existing RtcpPacket /// </summary> /// <param name="packet">Packet to process</param> public RrPacket(RtcpPacket packet) : base(Rtcp.PacketType.RR) { ProcessPacket(packet); }
/// <summary> /// Construct a SenderReport packet from an existing RtcpPacket /// </summary> /// <param name="packet">Packet to process</param> public SrPacket(RtcpPacket packet) : base(Rtcp.PacketType.SR) { sr = new SenderReport(); ProcessPacket(packet); }
/// <summary> /// Construct an APP packet from an existing RtcpPacket /// </summary> /// <param name="packet">Packet to process</param> public AppPacket(RtcpPacket packet) : base(Rtcp.PacketType.APP) { ProcessPacket(packet); }
/// <summary> /// Constructor used to process an existing BYE packet /// </summary> public ByePacket(RtcpPacket packet) : base(Rtcp.PacketType.BYE) { ProcessPacket(packet); }
/// <summary> /// Construct an SDES packet from an existing RtcpPacket /// </summary> public SdesPacket(RtcpPacket packet) : base(Rtcp.PacketType.SDES) { ProcessPacket(packet); }
/// <summary> /// Converts packet's data into derived class member data /// </summary> /// <param name="packet"></param> protected void ProcessPacket(RtcpPacket packet) { ValidatePacketType(Header.PacketType, packet.Header.PacketType); // Store the header header = packet.Header; // Do the real work ReadDataFromBuffer(packet.buffer); // Leave the buffer 32 bit aligned RemovePadding(packet.buffer); }
/// <summary> /// Called immediately after the buffer is populated by the network listener /// It parses RtcpPackets and rigorously validates them /// </summary> public void ParseBuffer() { // See if the packet ends on a 32 bit boundary as it should if(buffer.Length % 4 != 0) { throw new CompoundPacketException(Strings.CompoundPacketsMustEndOnBoundary); } // Parse all data in the buffer while(buffer.Length > 0) { // Retrieve the next packet from the buffer // RTCP Version will be validated by RtcpHeader in the generic RtcpPacket RtcpPacket packet = new RtcpPacket(buffer); // Check a couple of facts if the padding bit is set if(packet.Padding == true) { // Can't be set on the first packet if(packets.Count == 0) { throw new CompoundPacketException(Strings.YouCantSetThePaddingBit); } else { // There must be as many padding octets as the the last octet claims int octets = 0; byte octet = 0; while(buffer.Length > 0) { octet = buffer.NextByte(); octets++; } // Last octet contains the count of padding octets if(octet != octets) { throw new CompoundPacketException(string.Format(CultureInfo.CurrentCulture, Strings.PaddingBytesDiscrepancy, octets, octet)); } } } packets.Enqueue(packet); } // It must be a compound packet if(packets.Count <= 1) { throw new CompoundPacketException(string.Format(CultureInfo.CurrentCulture, Strings.MustContainMoreThan1Packet, packets.Count)); } // First packet must be an SR or RR byte pt = ((RtcpPacket)packets.Peek()).PacketType; if((pt != (byte)Rtcp.PacketType.SR) && (pt != (byte)Rtcp.PacketType.RR)) { throw new CompoundPacketException(string.Format(CultureInfo.CurrentCulture, Strings.FirstPacketMustBeSROrRR, (byte)Rtcp.PacketType.SR, (byte)Rtcp.PacketType.RR, pt)); } }