/// <summary>
 /// Constructs a new PayloadSpecificFeedbackReport 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 PayloadSpecificFeedbackReport(RtcpHeader header, System.Collections.Generic.IEnumerable <byte> payload, bool shouldDispose = true)
     : base(header, payload, shouldDispose)
 {
     if (Header.PayloadType != PayloadType)
     {
         throw new System.ArgumentException("Header.PayloadType is not equal to the expected type of 206.", "reference");
     }
 }
 /// <summary>
 /// Constructs a new PayloadSpecificFeedbackReport 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 PayloadSpecificFeedbackReport(RtcpHeader header, Common.MemorySegment payload, bool shouldDipose = true)
     : base(header, payload, shouldDipose)
 {
     if (Header.PayloadType != PayloadType)
     {
         throw new System.ArgumentException("Header.PayloadType is not equal to the expected type of 206.", "reference");
     }
 }
 /// <summary>
 /// Constructs a new TransportLayerFeedbackReport 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 TransportLayerFeedbackReport(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 205.", "reference");
     }
 }
示例#4
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");
            }
        }
示例#5
0
 internal static void CheckHeaderAndPayloadType(int payloadType, RtcpHeader header)
 {
     CheckHeaderAndPayloadType(ref payloadType, header);
 }
示例#6
0
 public RtcpReport(RtcpHeader header, Common.MemorySegment payload, bool shouldDispose = true)
     : base(header, payload, shouldDispose)
 {
 }
示例#7
0
 public RtcpReport(RtcpHeader header, IEnumerable <byte> payload, bool shouldDispose = true)
     : base(header, payload, shouldDispose)
 {
 }
示例#8
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;
        }
示例#9
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;
        }
示例#10
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;
        }
示例#11
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;
        }
示例#12
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)
 {
 }
示例#13
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;
        }