public RtcpHeader(RtcpHeader other, bool shouldDispose = true) : base(shouldDispose) { First16Bits = new RFC3550.CommonHeaderBits(other.First16Bits, shouldDispose); SegmentToLast6Bytes = new Common.MemorySegment(other.SegmentToLast6Bytes, shouldDispose); }
/// <summary> /// Creates an exact copy of the RtpHeader from the given RtpHeader /// </summary> /// <param name="other">The RtpHeader to copy</param> /// <param name="reference">A value indicating if the RtpHeader given should be referenced or copied.</param> public RtcpHeader(RtcpHeader other, bool reference) { if (reference) { First16Bits = other.First16Bits; Last6Bytes = other.Last6Bytes; PointerToLast6Bytes = other.PointerToLast6Bytes; } else { First16Bits = new Media.RFC3550.CommonHeaderBits(other.First16Bits); Last6Bytes = new byte[6]; PointerToLast6Bytes = new Common.MemorySegment(Last6Bytes, 0, 6); if (other.Last6Bytes != null) { other.Last6Bytes.CopyTo(Last6Bytes, 0); } else { System.Array.Copy(other.PointerToLast6Bytes.Array, other.PointerToLast6Bytes.Offset, Last6Bytes, 0, 6); } } }
/// <summary> /// Creates a new RtcpPacket with the given paramters. /// Throws a <see cref="OverflowException"/> if padding is less than 0 or greater than byte.MaxValue. /// </summary> /// <param name="version">Sets <see cref="Version"/></param> /// <param name="payloadType">Sets <see cref="PayloadType"/></param> /// <param name="padding">The amount of padding octets if greater than 0</param> /// <param name="ssrc">Sets <see cref="SendersSyncrhonizationSourceIdentifier"/></param> /// <param name="blockCount">Sets <see cref="BlockCount"/> </param> /// <param name="lengthInWords">Sets <see cref="RtcpHeader.LengthInWordsMinusOne"/></param> public RtcpPacket(int version, int payloadType, int padding, int ssrc, int blockCount, int lengthInWords, int blockSize, int extensionSize) { //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()); } Header = new RtcpHeader(version, payloadType, padding > 0, blockCount, ssrc, lengthInWords); m_OwnsHeader = true; extensionSize = Binary.MachineWordsToBytes(Binary.BytesToMachineWords(extensionSize)); //Calulcate the size of the Payload Segment 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); payloadSize += nullOctetsRequired + padding; //Allocate an array of byte equal to the size required m_OwnedOctets = new byte[payloadSize]; //Segment the array to allow property access. Payload = new MemorySegment(m_OwnedOctets, 0, payloadSize); if (padding > 0) { m_OwnedOctets[payloadSize - 1] = (byte)padding; } }
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 Media.RFC3550.CommonHeaderBits(other.First16Bits, false, shouldDispose); Last6Bytes = new byte[6]; SegmentToLast6Bytes = new Common.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); } } }
/// <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 SendersReport(RtcpHeader header, Common.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 200.", "reference"); } }
/// <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 SendersReport(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 200.", "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"); } }
/// <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, Common.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); }
/// <summary> /// Creates a RtcpPacket instance from the given parameters by copying data. /// </summary> /// <param name="buffer">The buffer which contains the binary RtcpPacket to decode</param> /// <param name="offset">The offset to start decoding</param> public RtcpPacket(byte[] buffer, int offset, int count, bool shouldDispose = true) { //The instance owns the header ShouldDispose = m_OwnsHeader = shouldDispose; //Create the header Header = new RtcpHeader(buffer, offset); //Determine the amount of bytes in the header and packet int headerLength = RtcpHeader.Length, packetLength = Header.LengthInWordsMinusOne; switch (packetLength) { case ushort.MinValue: { Payload = Common.MemorySegment.Empty; if (false == Padding) { return; } break; } default: { //Header has another word headerLength = Binary.BytesPerLong; //Packet length is given by the LengthInWordsMinusOne + 1 * 4 packetLength = ((ushort)((packetLength + 1) * 4)); //If there is no data in the payload don't consume it if (packetLength < headerLength) { goto case ushort.MinValue; } break; } } //ssrc doesn't technically coun't //int nonHeaderBytes = packetLength - headerLength; //Project the octets in the sequence taking the minimum of the octets present and the octets required as indicated by the header. //m_OwnedOctets = buffer.Skip(offset + headerLength).Take(nonHeaderBytes < 0 ? buffer.Length + nonHeaderBytes : nonHeaderBytes).ToArray(); //The Payload property must be assigned otherwise the properties will not function in the instance. //Payload = new Common.MemorySegment(m_OwnedOctets, shouldDispose); Payload = new Common.MemorySegment(buffer, offset + headerLength, count - headerLength, shouldDispose); m_OwnedOctets = Payload.Array; }
/// <summary> /// Creates a RtcpPacket instance from an existing RtcpHeader and payload. /// Check the IsValid property to see if the RtcpPacket is well formed. /// </summary> /// <param name="header">The existing RtpHeader (which is now owned by this instance)</param> /// <param name="payload">The data contained in the payload</param> public RtcpPacket(RtcpHeader header, MemorySegment payload, bool shouldDispose = true) { if (header == null) { throw new ArgumentNullException("header"); } //The instance owns the header ShouldDispose = m_OwnsHeader = shouldDispose; Header = header; Payload = payload; }
//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 (Common.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 override bool Equals(object obj) { if (System.Object.ReferenceEquals(this, obj)) { return(true); } if (false == (obj is RtcpHeader)) { return(false); } RtcpHeader other = obj as RtcpHeader; return(other.First16Bits == First16Bits && other.SendersSynchronizationSourceIdentifier == 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, int?payloadType = null, int?ssrc = null) { //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"); } //While a 32 bit value remains to be read in the vector while (offset + RtcpHeader.Length < upperBound && count >= RtcpHeader.Length) { //Get the header of the packet to verify if it is wanted or not using (var header = new RtcpHeader(new Common.MemorySegment(array, offset, count))) { //Determine how long the header was int payloadOffset = header.Size; //Determine the amount of bytes in the packet NOT INCLUDING the RtcpHeader (Which may be 0) int lengthInBytes = Binary.MachineWordsToBytes(header.LengthInWordsMinusOne + 1); //((lengthInWords + 1) * 4) - payloadOffset; //Create a packet using the existing header and the bytes left in the packet using (RtcpPacket newPacket = new RtcpPacket(header, new MemorySegment(array, offset + payloadOffset, Binary.Min(lengthInBytes - payloadOffset, count - payloadOffset)))) { //Move the offset the length in bytes of the size of the last packet (including the header). offset += newPacket.Length; //Reduce the count count -= newPacket.Length; //Check for the optional parameters 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; }
public RtcpReport(RtcpHeader header, Common.MemorySegment payload, bool shouldDispose = true) : base(header, payload, shouldDispose) { }
public RtcpReport(RtcpHeader header, IEnumerable <byte> payload, bool shouldDispose = true) : base(header, payload, shouldDispose) { }
internal static void CheckHeaderAndPayloadType(int payloadType, RtcpHeader header) { CheckHeaderAndPayloadType(ref payloadType, header); }
/// <summary> /// Creates a RtcpPacket instance by projecting the given sequence to an array which is subsequently owned by the instance. /// The length of the sequence projected is determined by <paramref name="header"/>. /// Throws a ArgumentNullException if header is null /// </summary> /// <param name="header">The header to utilize. When Dispose is called this header will be diposed.</param> /// <param name="octets">The octets to project</param> public RtcpPacket(RtcpHeader header, IEnumerable <byte> octets, bool ownsHeader = true) : this(header.Concat(octets).ToArray(), 0, true) { }
/// <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, Common.MemorySegment payload, bool shouldDipose) : base(header, payload, shouldDipose) { }
/// <summary> /// Constructs a new GoodbyeReport 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 GoodbyeReport(RtcpHeader header, IEnumerable <byte> payload) : base(header, payload) { }
/// <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) : base(header, payload) { }
public bool Equals(RtcpHeader other) { return(other.First16Bits.Equals(First16Bits) && other.SendersSynchronizationSourceIdentifier.Equals(SendersSynchronizationSourceIdentifier)); }
/// <summary> /// Constructs a new ApplicationSpecificReport from the given <see cref="RtcpHeader"/> and payload. /// Changes to the header and payload are immediately reflected in this instance. /// </summary> /// <param name="header">The header</param> /// <param name="payload">The payload</param> public ApplicationSpecificReport(RtcpHeader header, Common.MemorySegment payload) : base(header, payload) { }