/// <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) }); }
/// <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) }); }