public RtcpHeader(RtcpHeader other, bool reference, bool shouldDispose = true) : base(shouldDispose) { if (reference) { First16Bits = other.First16Bits; Last6Bytes = other.Last6Bytes; SegmentToLast6Bytes = other.SegmentToLast6Bytes; } else { First16Bits = new RFC3550.CommonHeaderBits(other.First16Bits, false, shouldDispose); Last6Bytes = new byte[6]; SegmentToLast6Bytes = new MemorySegment(Last6Bytes, 0, 6, shouldDispose); if (other.Last6Bytes != null) { other.Last6Bytes.CopyTo(Last6Bytes, 0); } else { System.Array.Copy(other.SegmentToLast6Bytes.Array, other.SegmentToLast6Bytes.Offset, Last6Bytes, 0, 6); } } }
public RtcpHeader(RtcpHeader other, bool shouldDispose = true) : base(shouldDispose) { First16Bits = new RFC3550.CommonHeaderBits(other.First16Bits, shouldDispose); SegmentToLast6Bytes = new MemorySegment(other.SegmentToLast6Bytes, shouldDispose); }
/// <summary> /// Constructs a new SendersReport from the given <see cref="RtcpHeader"/> and payload. /// Changes to the header are immediately reflected in this instance. /// Changes to the payload are not immediately reflected in this instance. /// </summary> /// <param name="header">The header</param> /// <param name="payload">The payload</param> public ReceiversReport(RtcpHeader header, System.Collections.Generic.IEnumerable <byte> payload, bool shouldDispose = true) : base(header, payload, shouldDispose) { if (Header.PayloadType != PayloadType) { throw new ArgumentException("Header.PayloadType is not equal to the expected type of 201.", "reference"); } }
/// <summary> /// Constructs a new SendersReport from the given <see cref="RtcpHeader"/> and payload. /// Changes to the header and payload are immediately reflected in this instance. /// </summary> /// <param name="header"></param> /// <param name="payload"></param> public ReceiversReport(RtcpHeader header, MemorySegment payload, bool shouldDipose = true) : base(header, payload, shouldDipose) { if (Header.PayloadType != PayloadType) { throw new ArgumentException("Header.PayloadType is not equal to the expected type of 201.", "reference"); } }
/// <summary> /// Constructs a new ApplicationSpecificReport from the given <see cref="RtcpHeader"/> and payload. /// Changes to the header are immediately reflected in this instance. /// Changes to the payload are not immediately reflected in this instance. /// </summary> /// <param name="header">The header</param> /// <param name="payload">The payload</param> public ApplicationSpecificReport(RtcpHeader header, IEnumerable <byte> payload, bool shouldDispose = true) : base(header, payload, shouldDispose) { if (Header.PayloadType != PayloadType) { throw new ArgumentException("Header.PayloadType is not equal to the expected type of 204.", "reference"); } }
public RtcpPacket(RtcpHeader header, IEnumerable <byte> octets, bool shouldDispose = true) : base(shouldDispose) { //Should probably keep header and just assign octets... //The reason why this doesn't happen is that the amount of bytes to take from octets can only be determined from the header... //The instance owns the header m_OwnsHeader = shouldDispose; //Reference the header Header = header; //Project the sequence m_OwnedOctets = octets.ToArray(); //Determine the amount of bytes in the header and packet int headerLength = RtcpHeader.Length, packetLength = Header.LengthInWordsMinusOne; //packetLength contains the LengthInWordsMinusOne switch (header.LengthInWordsMinusOne) { case ushort.MaxValue: // FFFF + 1 = 0 //case ushort.MinValue:// 0 + 1 = 1 * 4 = 4, header only.??? { Payload = MemorySegment.Empty; m_OwnedOctets = Payload.Array; return; } default: { //Header has another word headerLength = Header.Size; //Binary.BytesPerLong; //Packet length is given by the LengthInWordsMinusOne + 1 * 4 //packetLength = ((ushort)((packetLength + 1) * 4)); //The header was consumed and the packet cannot be less than 0 bytes or more than the buffer's length - offset in parsing. //packetLength = Binary.Clamp(packetLength - headerLength, 0, m_OwnedOctets.Length - headerLength); packetLength = m_OwnedOctets.Length - headerLength; //If there are no bytes then just handle as would for 0xFFFF if (packetLength <= 0) { goto case ushort.MaxValue; } //Assign the payload Payload = new MemorySegment(m_OwnedOctets, shouldDispose); return; } } }
/// <summary> /// Constructs a new GoodbyeReport from the given <see cref="RtcpHeader"/> and payload. /// Changes to the header and payload are immediately reflected in this instance. /// </summary> /// <param name="header"></param> /// <param name="payload"></param> public GoodbyeReport(RtcpHeader header, MemorySegment payload, bool shouldDipose = true) : base(header, payload, shouldDipose) { if (Header.PayloadType != PayloadType) { throw new ArgumentException("Header.PayloadType is not equal to the expected type of 203.", "reference"); } //RtcpReportExtensions.VerifyPayloadType(this); }
public RtcpPacket(int version, int payloadType, int padding, int ssrc, int blockCount, int lengthInWords, int blockSize, int extensionSize, bool shouldDispose = true) : base(shouldDispose) { //If the padding is greater than allow throw an overflow exception if (padding < 0 || padding > byte.MaxValue) { Binary.CreateOverflowException("padding", padding, byte.MinValue.ToString(), byte.MaxValue.ToString()); } extensionSize = Binary.MachineWordsToBytes(Binary.BytesToMachineWords(extensionSize)); //Calulcate the size of the Payload Segment, padding SHOULD be included here although this is not enforced. int payloadSize = (blockSize * blockCount) + extensionSize; //Octet alignment should always be respected when creating the payload, this will avoid a few uncecessary resizes. int nullOctetsRequired = (extensionSize & 0x03); //262136 is really the maximum number of bytes which can appear in the payload... payloadSize += nullOctetsRequired + padding; int octetsLength = payloadSize + Binary.BytesPerLong; //Allocate an array of byte equal to the size required m_OwnedOctets = new byte[octetsLength]; //Header = new RtcpHeader(version, payloadType, padding > 0, blockCount, ssrc, lengthInWords); Header = new RtcpHeader(new MemorySegment(m_OwnedOctets, 0, Binary.BytesPerLong)) { Version = version, PayloadType = payloadType, Padding = padding > 0, BlockCount = blockCount, LengthInWordsMinusOne = lengthInWords, SendersSynchronizationSourceIdentifier = ssrc }; m_OwnsHeader = true; //int headerSize = Header.Size; //Segment the array to allow property access. Payload = new MemorySegment(m_OwnedOctets, Binary.BytesPerLong, payloadSize); //, Binary.Max(0, payloadSize - Header.Size)); //If there was padding determine where to put it. if (padding > 0) { m_OwnedOctets[Binary.Min(octetsLength - 1, Binary.BytesPerLong + (Payload.Offset + Payload.Count - 1))] = (byte)padding; } }
public RtcpPacket(byte[] buffer, int offset, int count, bool shouldDispose = true) : base(shouldDispose) { //The instance owns the header m_OwnsHeader = shouldDispose; //Create the header Header = new RtcpHeader(buffer, offset, shouldDispose); //Calulate how many bytes the header used int headerSize = Header.Size; //Remove that many bytes from the count. //count -= headerSize; //packetLength contains the LengthInWordsMinusOne switch (count) { //case ushort.MaxValue: // FFFF + 1 = 0 case ushort.MinValue: // 0 + 1 = 1 * 4 = 4, header only.??? { Payload = new MemorySegment(0, shouldDispose); m_OwnedOctets = Payload.Array; return; } default: { //only take up to the length of the packet or what remains available to copy. int remains = count - headerSize; //If there are no bytes then just handle as would for 0xFFFF if (remains <= 0) { goto case ushort.MinValue; } //Make the array m_OwnedOctets = new byte[remains]; //Copy it System.Array.Copy(buffer, offset + headerSize, m_OwnedOctets, 0, remains); //Assign the payload Payload = new MemorySegment(m_OwnedOctets, 0, Binary.Clamp(0, Binary.MachineWordsToBytes(Header.LengthInWordsMinusOne + 1) - headerSize, remains), shouldDispose); return; } } }
//Should be extensions because it makes intellisense weird for all derived types. /// <summary> /// Throws an <see cref="ArgumentException"/> if the given header is null or disposed or does not have the given payloadType. /// </summary> /// <param name="payloadType"></param> /// <param name="header"></param> internal static void CheckHeaderAndPayloadType(ref int payloadType, RtcpHeader header) { if (IDisposedExtensions.IsNullOrDisposed(header)) { throw new ArgumentException("header IsNullOrDisposed"); } int headerPayloadType = header.PayloadType; if (headerPayloadType != payloadType) { throw new ArgumentException(string.Format("Header.PayloadType is not equal to the expected type of {0}, found {1}.", payloadType, headerPayloadType), "header"); } }
public RtcpPacket(RtcpHeader header, MemorySegment payload, bool shouldDispose = true) : base(shouldDispose) { if (header == null) { throw new ArgumentNullException("header"); } //The instance owns the header m_OwnsHeader = shouldDispose; Header = header; Payload = payload; }
public bool Equals(RtcpHeader other) { return(other.First16Bits.Equals(First16Bits) && other.SendersSynchronizationSourceIdentifier.Equals(SendersSynchronizationSourceIdentifier)); }
/// <summary> /// Parses all RtcpPackets contained in the array using the given paramters. /// </summary> /// <param name="array">The array to parse packets from.</param> /// <param name="offset">The index to start parsing</param> /// <param name="count">The amount of bytes to use in parsing</param> /// <param name="version">The optional <see cref="RtcpPacket.Version"/>version of the packets</param> /// <param name="payloadType">The optional <see cref="RtcpPacket.PayloadType"/> of all packets</param> /// <param name="ssrc">The optional <see cref="RtcpPacket.SynchronizationSourceIdentifier"/> of all packets</param> /// <returns>A pointer to each packet found</returns> public static IEnumerable <RtcpPacket> GetPackets(byte[] array, int offset, int count, int version = 2, //Todo, should possibly be Enumerable int?payloadType = null, //Todo, should be Enumerable int?ssrc = null, //Todo, should be Enumerable bool shouldDispose = true) { //array.GetLowerBound(0) for VB, UpperBound(0) is then the index of the last element int lowerBound = 0, upperBound = array.Length; if (offset < lowerBound || offset > upperBound) { throw new ArgumentOutOfRangeException("index", "Must refer to an accessible position in the given array"); } if (count <= lowerBound) { yield break; } if (count > upperBound) { throw new ArgumentOutOfRangeException("count", "Must refer to an accessible position in the given array"); } //Would overflow the array if (count + offset > upperBound) { throw new ArgumentOutOfRangeException("index", "Count must refer to an accessible position in the given array when deleniated by index"); } int remains = count; //While a 32 bit value remains to be read in the vector while (remains >= RtcpHeader.Length) { //Get the header of the packet to verify if it is wanted or not using (var header = new RtcpHeader(new MemorySegment(array, offset, remains, shouldDispose), shouldDispose)) { //Determine how long the header was int headerSize = header.Size; //Determine the amount of bytes in the packet NOT INCLUDING the RtcpHeader (Which may be 0 or 65535) //16384 is the maximum value which should occupy the LengthInWordsMinusOne in a single IP RTCP packet //Values over this such as 65535 will be truncated to 0 when added with 1 when the result type is not bound to ushort //When LengthInWordsMinusOne == 0 this means there should only be the header, 0 + 1 = 1 * 4 = 4 int lengthInBytes = headerSize > remains ? 0 : Binary.MachineWordsToBytes((ushort)(header.LengthInWordsMinusOne + 1)); //Create a packet using the existing header and the bytes left in the packet using (RtcpPacket newPacket = new RtcpPacket(header, lengthInBytes == 0 ? MemorySegment.Empty : new MemorySegment(array, offset + headerSize, Binary.Clamp(lengthInBytes - headerSize, 0, remains - headerSize)), shouldDispose)) { lengthInBytes = headerSize + newPacket.Payload.Count; remains -= lengthInBytes; offset += lengthInBytes; //Check for the optional parameters before returning the packet if (payloadType.HasValue && payloadType.Value != header.PayloadType || // Check for the given payloadType if provided ssrc.HasValue && ssrc.Value != header.SendersSynchronizationSourceIdentifier) //Check for the given ssrc if provided { //Skip the packet continue; } //Yield the packet, disposed afterwards yield return(newPacket); } } } //Done parsing yield break; }
internal static void CheckHeaderAndPayloadType(int payloadType, RtcpHeader header) { CheckHeaderAndPayloadType(ref payloadType, header); }
public RtcpReport(RtcpHeader header, MemorySegment payload, bool shouldDispose = true) : base(header, payload, shouldDispose) { }
public RtcpReport(RtcpHeader header, IEnumerable <byte> payload, bool shouldDispose = true) : base(header, payload, shouldDispose) { }