Example #1
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 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);
                }
            }
        }
Example #2
0
        public RtcpHeader(RtcpHeader other, bool shouldDispose = true)
            : base(shouldDispose)
        {
            First16Bits = new RFC3550.CommonHeaderBits(other.First16Bits, shouldDispose);

            SegmentToLast6Bytes = new MemorySegment(other.SegmentToLast6Bytes, shouldDispose);
        }
Example #3
0
 /// <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");
     }
 }
Example #4
0
 /// <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");
     }
 }
Example #5
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, 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");
     }
 }
Example #6
0
        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;
            }
            }
        }
Example #7
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, 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);
 }
Example #8
0
        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;
            }
        }
Example #9
0
        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;
            }
            }
        }
Example #10
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 (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");
            }
        }
Example #11
0
        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;
        }
Example #12
0
 public bool Equals(RtcpHeader other)
 {
     return(other.First16Bits.Equals(First16Bits)
            &&
            other.SendersSynchronizationSourceIdentifier.Equals(SendersSynchronizationSourceIdentifier));
 }
Example #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,    //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;
        }
Example #14
0
 internal static void CheckHeaderAndPayloadType(int payloadType, RtcpHeader header)
 {
     CheckHeaderAndPayloadType(ref payloadType, header);
 }
Example #15
0
 public RtcpReport(RtcpHeader header, MemorySegment payload, bool shouldDispose = true)
     : base(header, payload, shouldDispose)
 {
 }
Example #16
0
 public RtcpReport(RtcpHeader header, IEnumerable <byte> payload, bool shouldDispose = true)
     : base(header, payload, shouldDispose)
 {
 }