Example #1
0
        /// <summary>
        /// Handles sending out fragments based on the messages in the queue.
        /// </summary>
        private void UpdateSend()
        {
            // Update existing active messages before doing anything else; if we
            // send something for an existing active message then we don't go
            // any further.
            if (this.UpdateSendActiveMessages())
            {
                return;
            }

            // Re-evaluate the active messages to find and finalize any that
            // have been full acknowledged.
            this.CheckForFullAcknowledgement();

            // If we get to here, then there were no active message that had
            // sends pending, so rather than wasting a cycle doing nothing, we
            // start sending out the next message by bringing a queued message
            // into the active list.

            // Make sure there are messages in the queue; if there aren't any
            // then we have nothing left to do.
            if (this.m_QueuedMessages.Count == 0)
            {
                return;
            }

            // Dequeue the next message.
            var packet = this.m_QueuedMessages.Dequeue();

            // Create the new send state that we're going to use to track this message.
            var sendState = new MxReliabilitySendState();

            // Assign the send state a unique send message ID and then increment our counter.
            sendState.CurrentSendMessageID = this.m_CurrentSendMessageIDCounter++;

            // Assign the send state the packet data.
            sendState.CurrentSendMessage = packet;

            // Fragment the packet up into (SafeFragmentSize - DataOffset) byte chunks.
            var fragments = new List <Fragment>();
            var total     = 0;

            for (var i = 0; i < packet.Length; i += SafeFragmentSize - DataOffset)
            {
                total += 1;
            }

            if (total >= byte.MaxValue)
            {
                throw new OverflowException(
                          "The input data was " + packet.Length
                          + " bytes in length which is larger than the maximum " + ((SafeFragmentSize - DataOffset) * (byte.MaxValue - 1))
                          + " bytes.");
            }

            var inc = 0;

            for (var i = 0; i < packet.Length; i += SafeFragmentSize - DataOffset)
            {
                var length         = Math.Min(SafeFragmentSize - DataOffset, packet.Length - i);
                var fragment       = new byte[length + DataOffset];
                var messageIDBytes = BitConverter.GetBytes(sendState.CurrentSendMessageID);
                var lengthBytes    = BitConverter.GetBytes((UInt16)length);

                fragment[0] = messageIDBytes[0];
                fragment[1] = messageIDBytes[1];
                fragment[2] = messageIDBytes[2];
                fragment[3] = messageIDBytes[3];
                fragment[4] = lengthBytes[0];
                fragment[5] = lengthBytes[1];
                fragment[6] = (byte)inc;
                fragment[7] = (byte)total;
                for (var idx = 0; idx < length; idx++)
                {
                    fragment[idx + DataOffset] = packet[i + idx];
                }

                fragments.Add(new Fragment(fragment, FragmentStatus.WaitingOnSend));
                inc++;
            }

            sendState.CurrentSendFragments = fragments;

            // Add the new send state to the end of the list of active messages.
            this.m_ActiveMessages.Add(sendState);

            // Call UpdateSendActiveMessages again so that the new message gets queued
            // this step.
            this.UpdateSendActiveMessages();

            // Fire the progress event which is now an aggregate of all messages
            // that are waiting to be sent.
            this.OnFragmentReceived(
                new MxReliabilityTransmitEventArgs
            {
                Client           = this.m_Client,
                CurrentFragments = this.m_ActiveMessages.SelectMany(x => x.CurrentSendFragments).Count(x => x.Status == FragmentStatus.Acknowledged),
                TotalFragments   = this.m_ActiveMessages.SelectMany(x => x.CurrentSendFragments).Count(),
                IsSending        = true,
                TotalSize        = this.m_ActiveMessages.Sum(x => x.CurrentSendMessage.Length)
            });
        }
Example #2
0
        /// <summary>
        /// Handles sending out fragments based on the messages in the queue.
        /// </summary>
        private void UpdateSend()
        {
            // Update existing active messages before doing anything else; if we
            // send something for an existing active message then we don't go
            // any further.
            if (this.UpdateSendActiveMessages())
            {
                return;
            }

            // Re-evaluate the active messages to find and finalize any that
            // have been full acknowledged.
            this.CheckForFullAcknowledgement();

            // If we get to here, then there were no active message that had
            // sends pending, so rather than wasting a cycle doing nothing, we
            // start sending out the next message by bringing a queued message
            // into the active list.

            // Make sure there are messages in the queue; if there aren't any
            // then we have nothing left to do.
            if (this.m_QueuedMessages.Count == 0)
            {
                return;
            }

            // Dequeue the next message.
            var packet = this.m_QueuedMessages.Dequeue();
            
            // Create the new send state that we're going to use to track this message.
            var sendState = new MxReliabilitySendState();

            // Assign the send state a unique send message ID and then increment our counter.
            sendState.CurrentSendMessageID = this.m_CurrentSendMessageIDCounter++;

            // Assign the send state the packet data.
            sendState.CurrentSendMessage = packet;

            // Fragment the packet up into (SafeFragmentSize - DataOffset) byte chunks.
            var fragments = new List<Fragment>();
            var total = 0;
            for (var i = 0; i < packet.Length; i += SafeFragmentSize - DataOffset)
            {
                total += 1;
            }

            if (total >= byte.MaxValue)
            {
                throw new OverflowException(
                    "The input data was " + packet.Length
                    + " bytes in length which is larger than the maximum " + ((SafeFragmentSize - DataOffset) * (byte.MaxValue - 1))
                    + " bytes.");
            }

            var inc = 0;
            for (var i = 0; i < packet.Length; i += SafeFragmentSize - DataOffset)
            {
                var length = Math.Min(SafeFragmentSize - DataOffset, packet.Length - i);
                var fragment = new byte[length + DataOffset];
                var messageIDBytes = BitConverter.GetBytes(sendState.CurrentSendMessageID);
                var lengthBytes = BitConverter.GetBytes((UInt16)length);

                fragment[0] = messageIDBytes[0];
                fragment[1] = messageIDBytes[1];
                fragment[2] = messageIDBytes[2];
                fragment[3] = messageIDBytes[3];
                fragment[4] = lengthBytes[0];
                fragment[5] = lengthBytes[1];
                fragment[6] = (byte)inc;
                fragment[7] = (byte)total;
                for (var idx = 0; idx < length; idx++)
                {
                    fragment[idx + DataOffset] = packet[i + idx];
                }

                fragments.Add(new Fragment(fragment, FragmentStatus.WaitingOnSend));
                inc++;
            }

            sendState.CurrentSendFragments = fragments;

            // Add the new send state to the end of the list of active messages.
            this.m_ActiveMessages.Add(sendState);

            // Call UpdateSendActiveMessages again so that the new message gets queued
            // this step.
            this.UpdateSendActiveMessages();

            // Fire the progress event which is now an aggregate of all messages
            // that are waiting to be sent.
            this.OnFragmentReceived(
                new MxReliabilityTransmitEventArgs
                {
                    Client = this.m_Client, 
                    CurrentFragments = this.m_ActiveMessages.SelectMany(x => x.CurrentSendFragments).Count(x => x.Status == FragmentStatus.Acknowledged), 
                    TotalFragments = this.m_ActiveMessages.SelectMany(x => x.CurrentSendFragments).Count(), 
                    IsSending = true,
                    TotalSize = this.m_ActiveMessages.Sum(x => x.CurrentSendMessage.Length)
                });
        }