Exemplo n.º 1
0
        public RtcpHeader(Common.MemorySegment memory, bool shouldDispose = true)//, int additionalOffset = 0)
            : base(shouldDispose)
        {
            First16Bits = new Media.RFC3550.CommonHeaderBits(memory);//, additionalOffset);

            SegmentToLast6Bytes = new Common.MemorySegment(memory.Array, memory.Offset + RFC3550.CommonHeaderBits.Size, Binary.Clamp(memory.Count - RFC3550.CommonHeaderBits.Size, 0, 6));
        }
Exemplo n.º 2
0
        protected override void Dispose(bool disposing)
        {
            if (false.Equals(disposing) || false.Equals(ShouldDispose))
            {
                return;
            }

            base.Dispose(ShouldDispose);

            if (false.Equals(IsDisposed))
            {
                return;
            }

            if (false.Equals(Common.IDisposedExtensions.IsNullOrDisposed(First16Bits)))
            {
                //Dispose the instance
                First16Bits.Dispose();

                //Remove the reference to the CommonHeaderBits instance
                First16Bits = null;
            }

            if (false.Equals(Common.IDisposedExtensions.IsNullOrDisposed(SegmentToLast6Bytes)))
            {
                //Invalidate the pointer
                SegmentToLast6Bytes.Dispose();

                SegmentToLast6Bytes = null;
            }

            //Remove the reference to the allocated array.
            Last6Bytes = null;
        }
Exemplo n.º 3
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);
                }
            }
        }
Exemplo n.º 4
0
        public RtcpHeader(RtcpHeader other, bool shouldDispose = true)
            : base(shouldDispose)
        {
            First16Bits = new RFC3550.CommonHeaderBits(other.First16Bits, shouldDispose);

            SegmentToLast6Bytes = new Common.MemorySegment(other.SegmentToLast6Bytes, shouldDispose);
        }
Exemplo n.º 5
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);
                }
            }
        }
Exemplo n.º 6
0
        public RtpHeader(Common.MemorySegment memory, bool shouldDispose = true)
            : base(shouldDispose)
        {
            First16Bits = new Media.RFC3550.CommonHeaderBits(memory);

            SegmentToLast10Bytes = new Common.MemorySegment(memory.Array, memory.Offset + RFC3550.CommonHeaderBits.Size, Binary.Clamp(memory.Count - RFC3550.CommonHeaderBits.Size, 0, 10));
        }
Exemplo n.º 7
0
        public override void Dispose()
        {
            if (IsDisposed)
            {
                return;
            }

            base.Dispose();

            if (ShouldDispose)
            {
                //Call dispose
                First16Bits.Dispose();

                //Remove the reference to the CommonHeaderBits instance
                First16Bits = null;

                //Invalidate the pointer
                PointerToLast10Bytes.Dispose();
                PointerToLast10Bytes = null;

                //Remove the reference to the allocated array.
                Last10Bytes = null;
            }
        }
Exemplo n.º 8
0
        public RtcpHeader(Common.MemorySegment memory, int additionalOffset = 0)
        {
            if (Math.Abs(memory.Count - additionalOffset) < RtcpHeader.Length)
            {
                throw new ArgumentException("memory must contain at least 4 elements", "memory");
            }

            First16Bits = new Media.RFC3550.CommonHeaderBits(memory, additionalOffset);

            //das infamous clamp max min
            PointerToLast6Bytes = new Common.MemorySegment(memory.Array, memory.Offset + additionalOffset + RFC3550.CommonHeaderBits.Size, Math.Max(Math.Min(memory.Count - additionalOffset - RFC3550.CommonHeaderBits.Size, 6), RtcpHeader.Length));
        }
Exemplo n.º 9
0
        /// <summary>
        /// Reads an instance of the RtpHeader class and copies 12 octets which make up the RtpHeader.
        /// </summary>
        /// <param name="octets">A reference to a byte array which contains at least 12 octets to copy.</param>
        public RtpHeader(byte[] octets, int offset = 0)
        {
            //If the octets reference is null throw an exception
            if (octets == null)
            {
                throw new ArgumentNullException("octets");
            }

            //Determine the length of the array
            int octetsLength = octets.Length;

            //Check range
            if (offset > octetsLength)
            {
                throw new ArgumentOutOfRangeException("offset", "Cannot be greater than the length of octets");
            }

            //Check for the amount of octets required to build a RtpHeader given by the delination of the offset
            //if (octetsLength == 0 || octetsLength - offset < Length) throw new ArgumentException("octets must contain at least 12 elements given the deleniation of the offset parameter.", "octets");
            if (octetsLength == 0)
            {
                throw new ArgumentException("octets must contain at least 1 element given the deleniation of the offset parameter.", "octets");
            }

            bool hasMoreThanOnebyte = octetsLength > 1;

            if (hasMoreThanOnebyte)
            {
                //Read a managed representation of the first two octets which are stored in Big ByteOrder / Network Byte Order
                First16Bits = new Media.RFC3550.CommonHeaderBits(octets[offset + 0], octets[offset + 1]);

                //Allocate space for the other 10 octets
                Last10Bytes = hasMoreThanOnebyte ? new byte[10] : Media.Common.MemorySegment.EmptyBytes;

                //Copy the remaining bytes of the header which consist of the
                //SequenceNumber (2 octets / U16)
                //Timestamp (4 octets / U32)
                //SSRC (4 octets / U32)
                Array.Copy(octets, offset + 2, Last10Bytes, 0, Math.Min(10, octetsLength - 2));
            }
            else
            {
                //Read a managed representation of the first two octets which are stored in Big ByteOrder / Network Byte Order
                First16Bits = new Media.RFC3550.CommonHeaderBits(octets[offset + 0], default(byte));

                //Allocate space for the other 10 octets
                Last10Bytes = Media.Common.MemorySegment.EmptyBytes;
            }

            PointerToLast10Bytes = new MemorySegment(Last10Bytes, 0, Last10Bytes.Length);
        }
Exemplo n.º 10
0
        public RtcpHeader(int version, int payloadType, bool padding, int blockCount)
        {
            First16Bits = new Media.RFC3550.CommonHeaderBits(version, padding, false, false, payloadType, (byte)blockCount);

            Last6Bytes = new byte[6];

            PointerToLast6Bytes = new Common.MemorySegment(Last6Bytes, 0, 6);

            //The default value must be set into the LengthInWords field otherwise it will reflect 0
            if (blockCount == 0)
            {
                LengthInWordsMinusOne = RtcpHeader.MaximumLengthInWords;                 // ushort (0 - 1)
            }
        }
Exemplo n.º 11
0
        public RtpHeader(int version, bool padding, bool extension)
        {
            First16Bits = new Media.RFC3550.CommonHeaderBits(version, padding, extension);

            //Allocate space for the other 10 octets
            Last10Bytes = new byte[10];

            PointerToLast10Bytes = new Common.MemorySegment(Last10Bytes, 0, 10);

            Version = version;

            Padding = padding;

            Extension = extension;
        }
Exemplo n.º 12
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 RtpHeader(RtpHeader other, bool reference)
 {
     if (reference)
     {
         First16Bits          = other.First16Bits;
         Last10Bytes          = other.Last10Bytes;
         PointerToLast10Bytes = other.PointerToLast10Bytes;
     }
     else
     {
         First16Bits          = new Media.RFC3550.CommonHeaderBits(other.First16Bits);
         Last10Bytes          = new byte[10];
         PointerToLast10Bytes = new Common.MemorySegment(Last10Bytes, 0, 10);
         other.Last10Bytes.CopyTo(Last10Bytes, 0);
     }
 }
Exemplo n.º 13
0
 public RtpHeader(RtpHeader other, bool reference, bool shouldDispose = true)
     : base(shouldDispose)
 {
     if (reference)
     {
         First16Bits          = other.First16Bits;
         Last10Bytes          = other.Last10Bytes;
         SegmentToLast10Bytes = other.SegmentToLast10Bytes;
     }
     else
     {
         First16Bits          = new Media.RFC3550.CommonHeaderBits(other.First16Bits);
         Last10Bytes          = new byte[10];
         SegmentToLast10Bytes = new Common.MemorySegment(Last10Bytes, 0, 10);
         other.Last10Bytes.CopyTo(Last10Bytes, 0);
     }
 }
Exemplo n.º 14
0
        public RtcpHeader(byte[] octets, int offset = 0, bool shouldDispose = true)
            : base(shouldDispose)
        {
            //If the octets reference is null throw an exception
            if (octets == null)
            {
                throw new ArgumentNullException("octets");
            }

            //Determine the length of the array
            int octetsLength = octets.Length, availableOctets = octetsLength - offset;

            //Check range
            if (offset > octetsLength)
            {
                throw new ArgumentOutOfRangeException("offset", "Cannot be greater than the length of octets");
            }

            //Check for the amount of octets required to build a RtcpHeader given by the delination of the offset
            if (octetsLength == 0 || availableOctets < RtcpHeader.Length)
            {
                throw new ArgumentException("octets must contain at least 4 elements given the deleniation of the offset parameter.", "octets");
            }

            //Read a managed representation of the first two octets which are stored in Big ByteOrder / Network Byte Order
            First16Bits = new Media.RFC3550.CommonHeaderBits(octets, offset);

            //Allocate space for the other 6 octets which consist of the
            //LengthInWordsMinusOne (16 bits)
            //SynchronizationSourceIdentifier (32 bits)
            // 48 Bits = 6 bytes
            Last6Bytes = new byte[6];
            //Copy the remaining bytes of the header which consist of the aformentioned properties

            //If the LengthInWords is FFFF then this is extreanous and probably belongs to any padding...

            Array.Copy(octets, offset + RFC3550.CommonHeaderBits.Size, Last6Bytes, 0, Binary.Min(6, availableOctets - RFC3550.CommonHeaderBits.Size));

            //Make a pointer to the last 6 bytes
            SegmentToLast6Bytes = new Common.MemorySegment(Last6Bytes, 0, 6);
        }
Exemplo n.º 15
0
        public RtpHeader(byte[] octets, int offset = 0, bool shouldDispose = true)
            : base(shouldDispose)
        {
            //Determine the length of the array
            long octetsLength;

            //If the octets reference is null throw an exception
            if (Common.Extensions.Array.ArrayExtensions.IsNullOrEmpty(octets, out octetsLength))
            {
                throw new ArgumentException("octets must not be null and must contain at least 1 element given the deleniation of the offset parameter.", "octets");
            }

            //Check range
            if (offset > octetsLength)
            {
                throw new ArgumentOutOfRangeException("offset", "Cannot be greater than the length of octets");
            }

            //Todo, should not matter since this header instance would be allowed to be modified, saving the allocation here is not necessary.
            //The check is only relevent because octets my have less than 2 bytes which cannot be handled without exception in the CommonHeaderBits
            //Read a managed representation of the first two octets which are stored in Big ByteOrder / Network Byte Order
            First16Bits = octetsLength == 1 ? new Media.RFC3550.CommonHeaderBits(octets[offset], default(byte)) : new Media.RFC3550.CommonHeaderBits(octets, offset);

            //Allocate space for the other 10 octets
            Last10Bytes = new byte[10];

            //If there are octets for those bytes in the source array
            if (octetsLength > 2)
            {
                //Copy the remaining bytes of the header which consist of the
                //SequenceNumber (2 octets / U16)
                //Timestamp (4 octets / U32)
                //SSRC (4 octets / U32)
                Array.Copy(octets, offset + 2, Last10Bytes, 0, Math.Min(10, octetsLength - 2));
            }

            //Assign the segment
            SegmentToLast10Bytes = new MemorySegment(Last10Bytes, 0, Last10Bytes.Length);
        }
Exemplo n.º 16
0
        /// <summary>
        /// Parses the data in the buffer for valid Rtcp and Rtcp packet instances.
        /// </summary>
        /// <param name="memory">The memory to parse</param>
        /// <param name="from">The socket which received the data into memory and may be used for packet completion.</param>
        protected internal virtual void ParseAndCompleteData(Common.MemorySegment memory, bool parseRtcp = true, bool parseRtp = true, int? remaining = null)
        {
            if (memory == null || memory.IsDisposed || memory.Count == 0) return;

            //handle demultiplex scenarios e.g. RFC5761
            if (parseRtcp == parseRtp && memory.Count > RFC3550.CommonHeaderBits.Size)
            {
                //Double Negitive, Demux based on PayloadType? RFC5761?

                //Distinguishable RTP and RTCP Packets
                //http://tools.ietf.org/search/rfc5761#section-4

                //Observation 1) Rtp packets can only have a PayloadType from 64-95
                //However Rtcp Packets may also use PayloadTypes 72- 76.. (Reduced size...)

                //Observation 2) Rtcp Packets defined in RFC3550 Start at 200 (SR -> Goodbye) 204,
                // 209 - 223 is cited in the above as well as below
                //RTCP packet types in the ranges 1-191 and 224-254 SHOULD only be used when other values have been exhausted.

                using (Media.RFC3550.CommonHeaderBits header = new Media.RFC3550.CommonHeaderBits(memory))
                {
                    //Just use the payload type to avoid confusion, payload types for Rtcp and Rtp cannot and should not overlap
                    parseRtcp = !(parseRtp = GetContextByPayloadType(header.RtpPayloadType) != null);

                    //Could also lookup the ssrc
                }
            }

            //Cache start, count and index
            int offset = memory.Offset, count = memory.Count, index = 0,
                //Calulcate remaining
            mRemaining = remaining ?? count - index;

            //If there is nothing left to parse then return
            if (count <= 0) return;

            //If rtcp should be parsed
            if (parseRtcp && mRemaining >= RtcpHeader.Length)
            {
                //Copy valid RtcpPackets out of the buffer now, if any packet is not complete it will be completed only if required.
                foreach (RtcpPacket rtcp in RtcpPacket.GetPackets(memory.Array, offset + index, mRemaining))
                {
                    //Raise an event for each packet.
                    //OnRtcpPacketReceieved(rtcp);
                    HandleIncomingRtcpPacket(this, rtcp);

                    //Move the offset the length of the packet parsed
                    index += rtcp.Length;

                    mRemaining -= rtcp.Length;
                }
            }

            //If rtp is parsed
            if (parseRtp && mRemaining >= RtpHeader.Length)
            {
                using (var subMemory = new Common.MemorySegment(memory.Array, offset + index, mRemaining))
                {
                    using (RtpPacket rtp = new RtpPacket(subMemory))
                    {
                        Console.WriteLine(rtp.SequenceNumber+"===================");
                        //Raise the event
                        HandleIncomingRtpPacket(this, rtp);

                        //Move the index past the length of the packet
                        index += rtp.Length;

                        //Calculate the amount of octets remaining in the segment.
                        mRemaining -= rtp.Length;
                    }
                }
            }

            //If not all data was consumed
            if (mRemaining > 0)
            {
                Media.Common.ILoggingExtensions.Log(Logger, ToString() + "@ParseAndCompleteData - Remaining= " + mRemaining);

                //Only handle when not in TCP?
                //OnInterleavedData(memory.Array, offset + index, mRemaining);
            }

            return;
        }
Exemplo n.º 17
0
        /// <summary>
        /// Used to handle Tcp framing
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="offset"></param>
        /// <param name="count"></param>
        /// <param name="socket"></param>
        /// <returns></returns>
        protected internal virtual int ProcessFrameData(byte[] buffer, int offset, int count, Socket socket)
        {
            if (count == 0) return 0;

            //If there is no buffer use our own buffer.
            if (buffer == null) buffer = m_Buffer.Array;

            //Determine which TransportContext will receive the data incoming
            TransportContext relevent = null;

            //The channel of the data
            byte frameChannel = 0;

            //Get the length of the given buffer (Should actually use m_Buffer.Count when using our own buffer)
            int bufferLength = buffer.Length,
                //The indicates length of the data
                frameLength = 0,
                //The amount of data remaining in the buffer
                remainingInBuffer = Media.Common.Extensions.Math.MathExtensions.Clamp(count, count, bufferLength - offset),
                //The amount of data received (which is already equal to what is remaining in the buffer)
                recievedTotal = remainingInBuffer;

            //Determine if Rtp or Rtcp is coming in or some other type (could be combined with expectRtcp and expectRtp == false)
            bool expectRtp = false, expectRtcp = false, incompatible = true, raisedEvent = false;

            //If anything remains on the socket the value will be calulcated.
            int remainingOnSocket = 0;

            //TODO handle receiving when no $ and Channel is presenent... e.g. RFC4571
            //Would only be 2 then...

            //if (GetContextBySocket(socket).MediaDescription.MediaProtocol.StartsWith("TCP", StringComparison.OrdinalIgnoreCase))
            //{
            //    //independent = true;
            //}

            int sessionRequired = InterleavedOverhead;

            //While not disposed and there is data remaining (within the buffer)
            while (false == IsDisposed &&
                remainingInBuffer > 0 &&
                offset >= m_Buffer.Offset)
            {
                //Assume not rtp or rtcp and that the data is compatible with the session
                expectRtp = expectRtcp = incompatible = false;

                //If a header can be read
                if (remainingInBuffer >= sessionRequired)
                {
                    //Determine if an event was raised each time there was at least the required amount of data.
                    raisedEvent = false;

                    //Parse the frameLength from the given buffer, take changes to the offset through the function.
                    frameLength = ReadApplicationLayerFraming(remainingInBuffer, out frameChannel, out relevent, ref offset, out raisedEvent, buffer);

                    //If a frame was found (Including the null packet)
                    if (frameLength >= 0)
                    {
                        //If there WAS a context
                        if (relevent != null)
                        {
                            //Verify minimum and maximum packet sizes allowed by context. (taking into account the amount of bytes in the ALF)
                            if (frameLength < relevent.MinimumPacketSize + sessionRequired ||
                                frameLength > relevent.MaximumPacketSize + sessionRequired)
                            {
                                //mark as incompatible
                                incompatible = true;

                                //ToDo
                                //Make CreateLogString function

                                Media.Common.ILoggingExtensions.Log(Logger, ToString() + "@ProcessFrameData - Irregular Packet of " + frameLength + " for Channel " + frameChannel + " remainingInBuffer=" + remainingInBuffer);

                                //jump
                                goto CheckPacketAttributes;
                            }

                            //TODO Independent framing... (e.g. no $)[ only 4 bytes not 6 ]
                            //If all that remains is the frame header then receive more data. 6 comes from (InterleavedOverhead + CommonHeaderBits.Size)
                            //We need more data to be able to verify the frame.
                            if (remainingInBuffer <= 6)
                            {
                                //Remove the context
                                relevent = null;

                                goto CheckRemainingData;

                                ////Only receive this many more bytes for now.
                                //remainingOnSocket = X - remainingInBuffer;

                                ////Receive the rest of the data indicated by frameLength. (Should probably only receive up to X more bytes then make another receive if needed)
                                //goto GetRemainingData;
                            }

                            //Use CommonHeaderBits on the data after the Interleaved Frame Header
                            using (var common = new Media.RFC3550.CommonHeaderBits(buffer[offset + sessionRequired], buffer[offset + sessionRequired + 1]))
                            {
                                //Check the version...
                                incompatible = common.Version != relevent.Version;

                                //If this is a valid context there must be at least a RtpHeader's worth of data in the buffer.
                                //If this was a RtcpPacket with only 4 bytes it wouldn't have a ssrc and wouldn't be valid to be sent.
                                if (false == incompatible &&
                                    (frameChannel == relevent.DataChannel &&
                                    remainingInBuffer <= Rtp.RtpHeader.Length + sessionRequired)
                                    ||
                                    (frameChannel == relevent.ControlChannel &&
                                    remainingInBuffer <= Rtcp.RtcpHeader.Length + sessionRequired))
                                {
                                    //Remove the context
                                    relevent = null;

                                    //Mark as incompatible
                                    incompatible = true;

                                    goto EndUsingHeader;

                                    ////Only receive this many more bytes for now.
                                    //remainingOnSocket = 16 - remainingInBuffer;

                                    ////Receive the rest of the data indicated by frameLength. (Should probably only receive up to 6 more bytes then make another receive if needed)
                                    //goto GetRemainingData;
                                }

                                //Perform a set of checks and set weather or not Rtp or Rtcp was expected.
                                if (false == incompatible)
                                {
                                    //Determine if the packet is Rtcp by looking at the found channel and the relvent control channel
                                    if (frameChannel == relevent.ControlChannel)
                                    {
                                        //Rtcp

                                        if (remainingInBuffer <= sessionRequired + Rtcp.RtcpHeader.Length)
                                        {
                                            //Remove the context
                                            relevent = null;

                                            goto CheckRemainingData;
                                        }

                                        //Store any rtcp length so we can verify its not 0 and then additionally ensure its value is not larger then the frameLength
                                        int rtcpLen;

                                        //use a rtcp header to extract the information in the packet
                                        using (Rtcp.RtcpHeader header = new RtcpHeader(buffer, offset + sessionRequired))
                                        {
                                            //Get the length in 'words' (by adding one)
                                            //A length of 0 means 1 word
                                            //A length of 65535 means only the header (no ssrc [or payload])
                                            ushort lengthInWordsPlusOne = (ushort)(header.LengthInWordsMinusOne + 1);

                                            //Convert to bytes
                                            rtcpLen = lengthInWordsPlusOne * 4;

                                            //Check that the supposed  amount of contained words is greater than or equal to the frame length conveyed by the application layer framing
                                            //it must also be larger than the buffer
                                            incompatible = rtcpLen > frameLength && rtcpLen > bufferLength;

                                            //if rtcpLen >= ushort.MaxValue the packet may possibly span multiple segments unless a large buffer is used.

                                            if (false == incompatible && //It was not already ruled incomaptible
                                                lengthInWordsPlusOne > 0 && //If there is supposed to be SSRC in the packet
                                                header.Size > Rtcp.RtcpHeader.Length && //The header ACTUALLY contains enough bytes to have a SSRC
                                                false == relevent.InDiscovery)//The remote context knowns the identity of the remote stream
                                            {
                                                //Determine if Rtcp is expected
                                                //Perform another lookup and check compatibility
                                                expectRtcp = !(incompatible = (GetContextBySourceId(header.SendersSynchronizationSourceIdentifier)) == null);
                                            }
                                        }
                                    }

                                    //May be mixing channels...
                                    if (false == expectRtcp)
                                    {
                                        //Rtp
                                        if (remainingInBuffer <= sessionRequired + Rtp.RtpHeader.Length)
                                        {
                                            //Remove the context
                                            relevent = null;

                                            goto CheckRemainingData;
                                        }

                                        //the context by payload type is null is not discovering the identity check the SSRC.
                                        if (GetContextByPayloadType(common.RtpPayloadType) == null && false == relevent.InDiscovery)
                                        {
                                            using (Rtp.RtpHeader header = new RtpHeader(buffer, offset + InterleavedOverhead))
                                            {
                                                //The context was obtained by the frameChannel
                                                //Use the SSRC to determine where it should be handled.
                                                //If there is no context the packet is incompatible
                                                expectRtp = !(incompatible = (GetContextBySourceId(header.SynchronizationSourceIdentifier)) == null);

                                                //(Could also check SequenceNumber to prevent duplicate packets from being processed.)

                                                ////Verify extensions (handled by ValidatePacket)
                                                //if (header.Extension)
                                                //{

                                                //}

                                            }
                                        }
                                        else incompatible = false;
                                    }
                                }
                            EndUsingHeader:
                                ;
                            }
                        }

                        //Log state.
                    //if (relevent == null) Media.Common.ILoggingExtensions.Log(Logger, InternalId + "-ProcessFrameData - No Context for Channel " + frameChannel + " frameLength=" + frameLength + " remainingInBuffer=" + remainingInBuffer);
                    //else Media.Common.ILoggingExtensions.Log(Logger, InternalId + "ProcessFrameData " + frameChannel + " frameLength=" + frameLength + " remainingInBuffer=" + remainingInBuffer);

                    CheckPacketAttributes:

                        if (incompatible)
                        {
                            //If there was a context then incrment for failed receptions
                            if (relevent != null)
                            {
                                if (expectRtp) ++relevent.m_FailedRtpReceptions;

                                if (expectRtcp) ++relevent.m_FailedRtcpReceptions;
                            }

                            Media.Common.ILoggingExtensions.Log(Logger, InternalId + "ProcessFrameData - Incompatible Packet frameLength=" + frameLength + " for Channel " + frameChannel + " remainingInBuffer=" + remainingInBuffer);
                        }
                        //If frameLength was 0 or the frame was larger than we can store then interleave the header for handling if required
                        //incompatible may not be true here.
                        else if (frameLength == 0 || frameLength > bufferLength)
                        {
                            //Could check incompatible to determine if to should move further.

                            //Just because there is no assoicated context on the client does not mean the packet is not useful elsewhere in Transport.

                            //TODO It may be possible to let the event reiever known how much is available here.
                            if (frameLength == 0)
                            {
                                Media.Common.ILoggingExtensions.Log(Logger, InternalId + "ProcessFrameData - Null Packet for Channel " + frameChannel + " remainingInBuffer=" + remainingInBuffer);
                            }
                            else //If there was a context then increment for failed receptions only for large packets
                            {
                                if (expectRtp) ++relevent.m_FailedRtpReceptions;

                                if (expectRtcp) ++relevent.m_FailedRtcpReceptions;

                                if (expectRtp || expectRtcp) Media.Common.ILoggingExtensions.Log(Logger, InternalId + "ProcessFrameData - Large Packet of " + frameLength + " for Channel " + frameChannel + " remainingInBuffer=" + remainingInBuffer);
                            }
                        }
                        else goto CheckRemainingData;

                        //The packet was incompatible or larger than the buffer

                        //Determine how much we can move
                        int toMove = Math.Min(remainingInBuffer, sessionRequired);

                        //TODO It may be possible to let the event reiever known how much is available here.

                        //Indicate what was received if not already done
                        if (false == raisedEvent) OnInterleavedData(buffer, offset, toMove);

                        //Move the offset
                        offset += toMove;

                        //Decrease by the length
                        remainingInBuffer -= toMove;

                        //Do another pass
                        continue;

                    }//else there was a frameLength of -1 this indicates there is not enough bytes for a header.
                }
                else//There is not enough data in the buffer as defined by sessionRequired.
                {
                    //unset the frameLength read
                    frameLength = -1;

                    //unset the context read
                    relevent = null;
                }

            //At this point there may be either less sessionRequired or not enough for a complete frame.
            CheckRemainingData:

                //See how many more bytes are required from the wire
                //If the frameLength is less than 0 AND there are less then are sessionRequired remaining in the buffer
                remainingOnSocket = frameLength < 0 && remainingInBuffer < sessionRequired ?
                    sessionRequired - remainingInBuffer //Receive enough to complete the header
                        : //Otherwise if the frameLength larger then what remains in the buffer allow for the buffer to be filled or nothing else remains.
                    frameLength > remainingInBuffer ? frameLength - remainingInBuffer : 0;

                //GetRemainingData:

                //If there is anymore data remaining on the wire
                if (remainingOnSocket > 0)
                {
                    //Align the buffer if anything remains on the socket.
                    Array.Copy(buffer, offset, buffer, m_Buffer.Offset, remainingInBuffer);

                    //Set the correct offset either way.
                    offset = m_Buffer.Offset + remainingInBuffer;

                    //Store the error if any
                    SocketError error = SocketError.SocketError;

                    //Get all the remaining data
                    while (false == IsDisposed && remainingOnSocket > 0)
                    {
                        //Recieve from the wire the amount of bytes required (up to the length of the buffer)
                        int recievedFromWire = socket == null ? 0 : Media.Common.Extensions.Socket.SocketExtensions.AlignedReceive(buffer, offset, remainingOnSocket, socket, out error);

                        //Check for an error and then the allowed continue condition
                        if (error != SocketError.Success && error != SocketError.TryAgain) break;

                        //If nothing was recieved try again.
                        if (recievedFromWire <= 0) continue;

                        //Decrease what is remaining from the wire by what was received
                        remainingOnSocket -= recievedFromWire;

                        //Move the offset
                        offset += recievedFromWire;

                        //Increment received
                        recievedTotal += recievedFromWire;

                        //Incrment remaining in buffer for what was recieved.
                        remainingInBuffer += recievedFromWire;
                    }

                    //If a socket error occured remove the context so no parsing occurs
                    if (error != SocketError.Success)
                    {
                        OnInterleavedData(buffer, offset - remainingInBuffer, remainingInBuffer);

                        return recievedTotal;
                    }

                    //Move back to where the frame started
                    offset -= remainingInBuffer;
                }

                //If there was data unrelated to a frame
                if (raisedEvent)
                {
                    if (relevent == null)
                    {
                        offset += frameLength;

                        remainingInBuffer -= frameLength;
                    }

                    continue;
                }
                else if (false == IsDisposed && frameLength > 0)
                {
                    //Parse the data in the buffer
                    using (var memory = new Common.MemorySegment(buffer, offset + InterleavedOverhead, frameLength - InterleavedOverhead))
                        ParseAndCompleteData(memory, expectRtcp, expectRtp, memory.Count);

                    //Decrease remaining in buffer
                    remainingInBuffer -= frameLength;

                    //Move the offset
                    offset += frameLength;

                    //Ensure large frames are completely received by receiving the rest of the frame now. (this only occurs for packets being skipped)
                    if (frameLength > bufferLength)
                    {
                        //Remove the context
                        relevent = null;

                        //Determine how much remains
                        remainingOnSocket = frameLength - bufferLength;

                        //If there is anything left
                        if (remainingOnSocket > 0)
                        {
                            //Set the new length of the frame based on the length of the buffer
                            frameLength -= bufferLength;

                            //Set what is remaining
                            remainingInBuffer = 0;

                            //Use all the buffer
                            offset = m_Buffer.Offset;

                            //go to receive it
                            goto CheckRemainingData;
                        }
                    }
                }
            }

            //Handle any data which remains if not already
            if (false == raisedEvent && remainingInBuffer > 0)
            {
                OnInterleavedData(buffer, offset, remainingInBuffer);
            }

            //Return the number of bytes recieved
            return recievedTotal;
        }