Exemple #1
0
        public RtcpHeader(RtcpHeader other, bool shouldDispose = true)
            : base(shouldDispose)
        {
            First16Bits = new RFC3550.CommonHeaderBits(other.First16Bits, shouldDispose);

            SegmentToLast6Bytes = new Common.MemorySegment(other.SegmentToLast6Bytes, shouldDispose);
        }
Exemple #2
0
        /// <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);
                }
            }
        }
Exemple #3
0
        /// <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;
            }
        }
Exemple #4
0
        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);
 }
Exemple #9
0
        /// <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;
        }
Exemple #10
0
        /// <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;
        }
Exemple #11
0
        //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);
        }
Exemple #13
0
        /// <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;
        }
Exemple #14
0
 public RtcpReport(RtcpHeader header, Common.MemorySegment payload, bool shouldDispose = true)
     : base(header, payload, shouldDispose)
 {
 }
Exemple #15
0
 public RtcpReport(RtcpHeader header, IEnumerable <byte> payload, bool shouldDispose = true)
     : base(header, payload, shouldDispose)
 {
 }
Exemple #16
0
 internal static void CheckHeaderAndPayloadType(int payloadType, RtcpHeader header)
 {
     CheckHeaderAndPayloadType(ref payloadType, header);
 }
Exemple #17
0
 /// <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)
 {
 }
Exemple #18
0
 /// <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)
 {
 }
Exemple #19
0
 /// <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)
 {
 }
Exemple #20
0
 /// <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)
 {
 }
Exemple #21
0
 public bool Equals(RtcpHeader other)
 {
     return(other.First16Bits.Equals(First16Bits)
            &&
            other.SendersSynchronizationSourceIdentifier.Equals(SendersSynchronizationSourceIdentifier));
 }
Exemple #22
0
 /// <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)
 {
 }