Exemple #1
0
        internal static void WriteAckRanges(XmlDictionaryWriter writer, ReliableMessagingVersion reliableMessagingVersion, UniqueId sequenceId, SequenceRangeCollection ranges)
        {
            WsrmFeb2005Dictionary dictionary   = XD.WsrmFeb2005Dictionary;
            XmlDictionaryString   namespaceUri = WsrmIndex.GetNamespace(reliableMessagingVersion);

            writer.WriteStartElement(dictionary.Identifier, namespaceUri);
            writer.WriteValue(sequenceId);
            writer.WriteEndElement();
            if (ranges.Count == 0)
            {
                if (reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessagingFebruary2005)
                {
                    ranges = ranges.MergeWith((long)0L);
                }
                else if (reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessaging11)
                {
                    writer.WriteStartElement(DXD.Wsrm11Dictionary.None, namespaceUri);
                    writer.WriteEndElement();
                }
            }
            for (int i = 0; i < ranges.Count; i++)
            {
                writer.WriteStartElement(dictionary.AcknowledgementRange, namespaceUri);
                writer.WriteStartAttribute(dictionary.Lower, null);
                SequenceRange range = ranges[i];
                writer.WriteValue(range.Lower);
                writer.WriteEndAttribute();
                writer.WriteStartAttribute(dictionary.Upper, null);
                SequenceRange range2 = ranges[i];
                writer.WriteValue(range2.Upper);
                writer.WriteEndAttribute();
                writer.WriteEndElement();
            }
        }
Exemple #2
0
 public bool IsValid(long sequenceNumber, bool isLast)
 {
     if (this.reliableMessagingVersion == System.ServiceModel.ReliableMessagingVersion.WSReliableMessagingFebruary2005)
     {
         if (isLast)
         {
             if (this.last != 0L)
             {
                 return(sequenceNumber == this.last);
             }
             if (this.ranges.Count > 0)
             {
                 SequenceRange range = this.ranges[this.ranges.Count - 1];
                 return(sequenceNumber > range.Upper);
             }
             return(true);
         }
         if (this.last > 0L)
         {
             return(sequenceNumber < this.last);
         }
     }
     else if (this.isLastKnown)
     {
         return(this.ranges.Contains(sequenceNumber));
     }
     return(true);
 }
        public static WsrmFault ValidateFinalAck(ChannelReliableSession session, WsrmMessageInfo info, long last)
        {
            WsrmAcknowledgmentInfo acknowledgementInfo = info.AcknowledgementInfo;
            WsrmFault fault = ValidateFinalAckExists(session, acknowledgementInfo);

            if (fault != null)
            {
                return(fault);
            }
            SequenceRangeCollection ranges = acknowledgementInfo.Ranges;

            if (last == 0L)
            {
                if (ranges.Count == 0)
                {
                    return(null);
                }
            }
            else if (ranges.Count == 1)
            {
                SequenceRange range = ranges[0];
                if (range.Lower == 1L)
                {
                    SequenceRange range2 = ranges[0];
                    if (range2.Upper == last)
                    {
                        return(null);
                    }
                }
            }
            return(new InvalidAcknowledgementFault(session.OutputID, acknowledgementInfo.Ranges));
        }
            public override bool Contains(Int64 number)
            {
                if (this.ranges.Length == 0)
                {
                    return(false);
                }
                else if (this.ranges.Length == 1)
                {
                    return(this.ranges[0].Contains(number));
                }

                SequenceRange searchFor   = new SequenceRange(number);
                int           searchValue = Array.BinarySearch(this.ranges, searchFor, lowerComparer);

                if (searchValue >= 0)
                {
                    return(true);
                }

                searchValue = ~searchValue;

                if (searchValue == 0)
                {
                    return(false);
                }

                return(this.ranges[searchValue - 1].Upper >= number);
            }
        public bool IsFinalAckConsistent(SequenceRangeCollection ranges)
        {
            lock (this.ThisLock)
            {
                SequenceRange range2;
                if (this.closed)
                {
                    return(true);
                }
                if ((this.windowStart == 1L) && (this.window.Count == 0))
                {
                    return(ranges.Count == 0);
                }
                if (ranges.Count != 0)
                {
                    SequenceRange range = ranges[0];
                    if (range.Lower == 1L)
                    {
                        goto Label_005F;
                    }
                }
                return(false);

Label_005F:
                range2 = ranges[0];
                return(range2.Upper >= (this.windowStart - 1L));
            }
        }
        public void ProcessAcknowledgement(SequenceRangeCollection ranges, out bool invalidAck, out bool inconsistentAck)
        {
            invalidAck      = false;
            inconsistentAck = false;
            bool flag  = false;
            bool flag2 = false;

            lock (this.ThisLock)
            {
                if (this.closed)
                {
                    return;
                }
                long num              = (this.windowStart + this.window.Count) - 1L;
                long num2             = this.windowStart - 1L;
                int  transferredCount = this.window.TransferredCount;
                for (int i = 0; i < ranges.Count; i++)
                {
                    SequenceRange range = ranges[i];
                    if (range.Upper > num)
                    {
                        invalidAck = true;
                        return;
                    }
                    if (((range.Lower > 1L) && (range.Lower <= num2)) || (range.Upper < num2))
                    {
                        flag2 = true;
                    }
                    if (range.Upper >= this.windowStart)
                    {
                        if (range.Lower <= this.windowStart)
                        {
                            flag = true;
                        }
                        if (!flag)
                        {
                            int beginIndex = (int)(range.Lower - this.windowStart);
                            int endIndex   = (range.Upper > num) ? (this.window.Count - 1) : ((int)(range.Upper - this.windowStart));
                            flag = this.window.GetTransferredInRangeCount(beginIndex, endIndex) < ((endIndex - beginIndex) + 1);
                        }
                        if ((transferredCount > 0) && !flag2)
                        {
                            int num7 = (range.Lower < this.windowStart) ? ((int)0L) : ((int)(range.Lower - this.windowStart));
                            int num8 = (range.Upper > num) ? (this.window.Count - 1) : ((int)(range.Upper - this.windowStart));
                            transferredCount -= this.window.GetTransferredInRangeCount(num7, num8);
                        }
                    }
                }
                if (transferredCount > 0)
                {
                    flag2 = true;
                }
            }
            inconsistentAck = flag2 && flag;
        }
        public override string ToString()
        {
            StringBuilder builder = new StringBuilder();

            for (int i = 0; i < Count; i++)
            {
                SequenceRange range = this[i];
                if (i > 0)
                {
                    builder.Append(',');
                }
                builder.Append(range.Lower);
                builder.Append('-');
                builder.Append(range.Upper);
            }
            return(builder.ToString());
        }
Exemple #8
0
        public bool SetCloseSequenceLast(long last)
        {
            bool flag;

            WsrmUtilities.AssertWsrm11(this.reliableMessagingVersion);
            if ((last < 1L) || (this.ranges.Count == 0))
            {
                flag = true;
            }
            else
            {
                SequenceRange range = this.ranges[this.ranges.Count - 1];
                flag = last >= range.Upper;
            }
            if (flag)
            {
                this.isSequenceClosed = true;
                this.SetLast(last);
            }
            return(flag);
        }
Exemple #9
0
 public override SequenceRangeCollection MergeWith(SequenceRange newRange)
 {
     if (newRange.Lower == (this.range.Upper + 1L))
     {
         return(new SequenceRangeCollection.SingleItemRangeCollection(this.range.Lower, newRange.Upper));
     }
     if (this.range.Contains(newRange))
     {
         return(this);
     }
     if (newRange.Contains(this.range))
     {
         return(new SequenceRangeCollection.SingleItemRangeCollection(newRange));
     }
     if (newRange.Upper == (this.range.Lower - 1L))
     {
         return(new SequenceRangeCollection.SingleItemRangeCollection(newRange.Lower, this.range.Upper));
     }
     SequenceRange[] sortedRanges = new SequenceRange[] { this.range };
     return(SequenceRangeCollection.GeneralMerge(sortedRanges, newRange));
 }
 public override SequenceRangeCollection MergeWith(SequenceRange newRange)
 {
     if (newRange.Lower == this.range.Upper + 1)
     {
         return(new SingleItemRangeCollection(range.Lower, newRange.Upper));
     }
     else if (this.range.Contains(newRange))
     {
         return(this);
     }
     else if (newRange.Contains(this.range))
     {
         return(new SingleItemRangeCollection(newRange));
     }
     else if (newRange.Upper == this.range.Lower - 1)
     {
         return(new SingleItemRangeCollection(newRange.Lower, this.range.Upper));
     }
     else
     {
         return(GeneralMerge(new SequenceRange[] { this.range }, newRange));
     }
 }
Exemple #11
0
            public override bool Contains(long number)
            {
                if (this.ranges.Length == 0)
                {
                    return(false);
                }
                if (this.ranges.Length == 1)
                {
                    return(this.ranges[0].Contains(number));
                }
                SequenceRange range = new SequenceRange(number);
                int           num   = Array.BinarySearch <SequenceRange>(this.ranges, range, SequenceRangeCollection.lowerComparer);

                if (num >= 0)
                {
                    return(true);
                }
                num = ~num;
                if (num == 0)
                {
                    return(false);
                }
                return(this.ranges[num - 1].Upper >= number);
            }
 public SingleItemRangeCollection(Int64 lower, Int64 upper)
 {
     this.range = new SequenceRange(lower, upper);
 }
 public SingleItemRangeCollection(SequenceRange range)
 {
     this.range = range;
 }
 public override SequenceRangeCollection MergeWith(SequenceRange newRange)
 {
     return(GeneralMerge(this.ranges, newRange));
 }
 public override SequenceRangeCollection MergeWith(SequenceRange range)
 {
     return(new SingleItemRangeCollection(range));
 }
 public override SequenceRangeCollection MergeWith(SequenceRange range) => new SingleItemRangeCollection(range);
        // It is necessary that ProcessAcknowledgement be called prior, as
        // this method does not check for valid ack ranges.
        // This method returns true if the calling method should start sending retries
        // obtained from GetMessageInfoForRetry.
        private bool ProcessTransferred(SequenceRange range, int quotaRemaining)
        {
            if (range.Upper < _windowStart)
            {
                if (range.Upper == _windowStart - 1 && (quotaRemaining != -1) && quotaRemaining > QuotaRemaining)
                {
                    QuotaRemaining = quotaRemaining - Math.Min(_windowSize, _window.Count);
                }

                return(false);
            }
            else if (range.Lower <= _windowStart)
            {
                bool send = false;

                _retryTimer.Cancel();

                long slide = range.Upper - _windowStart + 1;

                // For Request Reply: Requests are transferred 1 at a time, (i.e. when the reply comes back).
                // The TransmissionStrategy only removes messages if the window start is removed.
                // Because of this, RequestReply messages transferred out of order will cause many, many retries.
                // To avoid extraneous retries we mark each message transferred, and we remove our virtual slide.
                if (slide == 1)
                {
                    for (int i = 1; i < _window.Count; i++)
                    {
                        if (_window.GetTransferred(i))
                        {
                            slide++;
                        }
                        else
                        {
                            break;
                        }
                    }
                }

                long now          = Now;
                long oldWindowEnd = _windowStart + _windowSize;

                for (int i = 0; i < (int)slide; i++)
                {
                    UpdateStats(now, _window.GetLastAttemptTime(i));
                }

                if (quotaRemaining != -1)
                {
                    int inFlightAfterAck = Math.Min(_windowSize, _window.Count) - (int)slide;
                    QuotaRemaining = quotaRemaining - Math.Max(0, inFlightAfterAck);
                }

                _window.Remove((int)slide);

                _windowStart += slide;

                int sendBeginIndex = 0;

                if (_windowSize <= _slowStartThreshold)
                {
                    _windowSize = Math.Min(_maxWindowSize, Math.Min(_slowStartThreshold + 1, _windowSize + (int)slide));

                    if (!_startup)
                    {
                        sendBeginIndex = 0;
                    }
                    else
                    {
                        sendBeginIndex = Math.Max(0, (int)oldWindowEnd - (int)_windowStart);
                    }
                }
                else
                {
                    _congestionControlModeAcks += (int)slide;

                    // EXPERIMENTAL, needs optimizing ///
                    int segmentSize = Math.Max(1, (_lossWindowSize - _slowStartThreshold) / 8);
                    int windowGrowthAckThreshold = ((_windowSize - _slowStartThreshold) * _windowSize) / segmentSize;

                    if (_congestionControlModeAcks > windowGrowthAckThreshold)
                    {
                        _congestionControlModeAcks = 0;
                        _windowSize = Math.Min(_maxWindowSize, _windowSize + 1);
                    }

                    sendBeginIndex = Math.Max(0, (int)oldWindowEnd - (int)_windowStart);
                }

                int sendEndIndex = Math.Min(_windowSize, _window.Count);

                if (sendBeginIndex < sendEndIndex)
                {
                    send = (_retransmissionWindow.Count == 0);

                    for (int i = sendBeginIndex; i < _windowSize && i < _window.Count; i++)
                    {
                        long sequenceNumber = _windowStart + i;

                        if (!_window.GetTransferred(i) && !_retransmissionWindow.Contains(sequenceNumber))
                        {
                            _window.RecordRetry(i, Now);
                            _retransmissionWindow.Add(sequenceNumber);
                        }
                    }
                }

                if (_window.Count > 0)
                {
                    _retryTimer.Set(Timeout);
                }

                return(send);
            }
            else
            {
                for (long i = range.Lower; i <= range.Upper; i++)
                {
                    _window.SetTransferred((int)(i - _windowStart));
                }
            }

            return(false);
        }
 public bool Contains(SequenceRange range)
 {
     return ((range.Lower >= this.lower) && (range.Upper <= this.upper));
 }
Exemple #19
0
 public bool Contains(SequenceRange range)
 {
     return(range.Lower >= this.lower && range.Upper <= this.upper);
 }
Exemple #20
0
        private static SequenceRangeCollection GeneralMerge(SequenceRange[] sortedRanges, SequenceRange range)
        {
            int num;
            int num2;

            if (sortedRanges.Length == 0)
            {
                return(new SingleItemRangeCollection(range));
            }
            if (sortedRanges.Length == 1)
            {
                if (range.Lower == sortedRanges[0].Upper)
                {
                    num = 0;
                }
                else if (range.Lower < sortedRanges[0].Upper)
                {
                    num = -1;
                }
                else
                {
                    num = -2;
                }
            }
            else
            {
                num = Array.BinarySearch <SequenceRange>(sortedRanges, new SequenceRange(range.Lower), upperComparer);
            }
            if (num < 0)
            {
                num = ~num;
                if ((num > 0) && (sortedRanges[num - 1].Upper == (range.Lower - 1L)))
                {
                    num--;
                }
                if (num == sortedRanges.Length)
                {
                    SequenceRange[] rangeArray = new SequenceRange[sortedRanges.Length + 1];
                    Array.Copy(sortedRanges, rangeArray, sortedRanges.Length);
                    rangeArray[sortedRanges.Length] = range;
                    return(GeneralCreate(rangeArray));
                }
            }
            if (sortedRanges.Length == 1)
            {
                if (range.Upper == sortedRanges[0].Lower)
                {
                    num2 = 0;
                }
                else if (range.Upper < sortedRanges[0].Lower)
                {
                    num2 = -1;
                }
                else
                {
                    num2 = -2;
                }
            }
            else
            {
                num2 = Array.BinarySearch <SequenceRange>(sortedRanges, new SequenceRange(range.Upper), lowerComparer);
            }
            if (num2 < 0)
            {
                num2 = ~num2;
                if (num2 > 0)
                {
                    if ((num2 == sortedRanges.Length) || (sortedRanges[num2].Lower != (range.Upper + 1L)))
                    {
                        num2--;
                    }
                }
                else if (sortedRanges[0].Lower > (range.Upper + 1L))
                {
                    SequenceRange[] rangeArray2 = new SequenceRange[sortedRanges.Length + 1];
                    Array.Copy(sortedRanges, 0, rangeArray2, 1, sortedRanges.Length);
                    rangeArray2[0] = range;
                    return(GeneralCreate(rangeArray2));
                }
            }
            long lower = (range.Lower < sortedRanges[num].Lower) ? range.Lower : sortedRanges[num].Lower;
            long upper = (range.Upper > sortedRanges[num2].Upper) ? range.Upper : sortedRanges[num2].Upper;
            int  num5  = (num2 - num) + 1;
            int  num6  = (sortedRanges.Length - num5) + 1;

            if (num6 == 1)
            {
                return(new SingleItemRangeCollection(lower, upper));
            }
            SequenceRange[] destinationArray = new SequenceRange[num6];
            Array.Copy(sortedRanges, destinationArray, num);
            destinationArray[num] = new SequenceRange(lower, upper);
            Array.Copy(sortedRanges, (int)(num2 + 1), destinationArray, (int)(num + 1), (int)((sortedRanges.Length - num2) - 1));
            return(GeneralCreate(destinationArray));
        }
Exemple #21
0
 public SingleItemRangeCollection(long lower, long upper)
 {
     this.range = new SequenceRange(lower, upper);
 }
 public abstract SequenceRangeCollection MergeWith(SequenceRange range);
        static SequenceRangeCollection GeneralMerge(SequenceRange[] sortedRanges, SequenceRange range)
        {
            if (sortedRanges.Length == 0)
            {
                return(new SingleItemRangeCollection(range));
            }

            int lowerBound;

            if (sortedRanges.Length == 1)
            {
                // Avoid performance hit of binary search in single range case
                if (range.Lower == sortedRanges[0].Upper)
                {
                    lowerBound = 0;
                }
                else if (range.Lower < sortedRanges[0].Upper)
                {
                    lowerBound = ~0;
                }
                else
                {
                    lowerBound = ~1;
                }
            }
            else
            {
                lowerBound = Array.BinarySearch(sortedRanges, new SequenceRange(range.Lower), upperComparer);
            }

            if (lowerBound < 0)
            {
                lowerBound = ~lowerBound;

                if ((lowerBound > 0) && (sortedRanges[lowerBound - 1].Upper == range.Lower - 1))
                {
                    lowerBound--;
                }

                if (lowerBound == sortedRanges.Length)
                {
                    SequenceRange[] returnedRanges = new SequenceRange[sortedRanges.Length + 1];
                    Array.Copy(sortedRanges, returnedRanges, sortedRanges.Length);
                    returnedRanges[sortedRanges.Length] = range;
                    return(GeneralCreate(returnedRanges));
                }
            }

            int upperBound;

            if (sortedRanges.Length == 1)
            {
                // Avoid performance hit of binary search in single range case
                if (range.Upper == sortedRanges[0].Lower)
                {
                    upperBound = 0;
                }
                else if (range.Upper < sortedRanges[0].Lower)
                {
                    upperBound = ~0;
                }
                else
                {
                    upperBound = ~1;
                }
            }
            else
            {
                upperBound = Array.BinarySearch(sortedRanges, new SequenceRange(range.Upper), lowerComparer);
            }

            if (upperBound < 0)
            {
                upperBound = ~upperBound;

                if (upperBound > 0)
                {
                    if ((upperBound == sortedRanges.Length) || (sortedRanges[upperBound].Lower != range.Upper + 1))
                    {
                        upperBound--;
                    }
                }
                else if (sortedRanges[0].Lower > range.Upper + 1)
                {
                    SequenceRange[] returnedRanges = new SequenceRange[sortedRanges.Length + 1];
                    Array.Copy(sortedRanges, 0, returnedRanges, 1, sortedRanges.Length);
                    returnedRanges[0] = range;
                    return(GeneralCreate(returnedRanges));
                }
            }

            Int64 newLower = (range.Lower < sortedRanges[lowerBound].Lower) ? range.Lower : sortedRanges[lowerBound].Lower;
            Int64 newUpper = (range.Upper > sortedRanges[upperBound].Upper) ? range.Upper : sortedRanges[upperBound].Upper;

            int rangesRemoved   = upperBound - lowerBound + 1;
            int rangesRemaining = sortedRanges.Length - rangesRemoved + 1;

            if (rangesRemaining == 1)
            {
                return(new SingleItemRangeCollection(newLower, newUpper));
            }
            else
            {
                SequenceRange[] returnedRanges = new SequenceRange[rangesRemaining];
                Array.Copy(sortedRanges, returnedRanges, lowerBound);
                returnedRanges[lowerBound] = new SequenceRange(newLower, newUpper);
                Array.Copy(sortedRanges, upperBound + 1, returnedRanges, lowerBound + 1, sortedRanges.Length - upperBound - 1);
                return(GeneralCreate(returnedRanges));
            }
        }
 public override SequenceRangeCollection MergeWith(SequenceRange newRange) => GeneralMerge(_ranges, newRange);
        public void ProcessAcknowledgement(SequenceRangeCollection ranges, out bool invalidAck, out bool inconsistentAck)
        {
            invalidAck      = false;
            inconsistentAck = false;
            bool newAck = false;
            bool oldAck = false;

            lock (ThisLock)
            {
                if (_closed)
                {
                    return;
                }

                long lastMessageSent     = _windowStart + _window.Count - 1;
                long lastMessageAcked    = _windowStart - 1;
                int  transferredInWindow = _window.TransferredCount;

                for (int i = 0; i < ranges.Count; i++)
                {
                    SequenceRange range = ranges[i];

                    // Ack for a message not yet sent.
                    if (range.Upper > lastMessageSent)
                    {
                        invalidAck = true;
                        return;
                    }

                    if (((range.Lower > 1) && (range.Lower <= lastMessageAcked)) || (range.Upper < lastMessageAcked))
                    {
                        oldAck = true;
                    }

                    if (range.Upper >= _windowStart)
                    {
                        if (range.Lower <= _windowStart)
                        {
                            newAck = true;
                        }

                        if (!newAck)
                        {
                            int beginIndex = (int)(range.Lower - _windowStart);
                            int endIndex   = (int)((range.Upper > lastMessageSent) ? (_window.Count - 1) : (range.Upper - _windowStart));

                            newAck = _window.GetTransferredInRangeCount(beginIndex, endIndex) < (endIndex - beginIndex + 1);
                        }

                        if (transferredInWindow > 0 && !oldAck)
                        {
                            int beginIndex = (int)((range.Lower < _windowStart) ? 0 : (range.Lower - _windowStart));
                            int endIndex   = (int)((range.Upper > lastMessageSent) ? (_window.Count - 1) : (range.Upper - _windowStart));

                            transferredInWindow -= _window.GetTransferredInRangeCount(beginIndex, endIndex);
                        }
                    }
                }

                if (transferredInWindow > 0)
                {
                    oldAck = true;
                }
            }

            inconsistentAck = oldAck && newAck;
        }
        private bool ProcessTransferred(SequenceRange range, int quotaRemaining)
        {
            if (range.Upper < this.windowStart)
            {
                if (((range.Upper == (this.windowStart - 1L)) && (quotaRemaining != -1)) && (quotaRemaining > this.quotaRemaining))
                {
                    this.quotaRemaining = quotaRemaining - Math.Min(this.windowSize, this.window.Count);
                }
                return(false);
            }
            if (range.Lower > this.windowStart)
            {
                for (long j = range.Lower; j <= range.Upper; j += 1L)
                {
                    this.window.SetTransferred((int)(j - this.windowStart));
                }
                return(false);
            }
            bool flag = false;

            this.retryTimer.Cancel();
            long num = (range.Upper - this.windowStart) + 1L;

            if (num == 1L)
            {
                for (int k = 1; k < this.window.Count; k++)
                {
                    if (!this.window.GetTransferred(k))
                    {
                        break;
                    }
                    num += 1L;
                }
            }
            long now  = Now;
            long num4 = this.windowStart + this.windowSize;

            for (int i = 0; i < ((int)num); i++)
            {
                this.UpdateStats(now, this.window.GetLastAttemptTime(i));
            }
            if (quotaRemaining != -1)
            {
                int num6 = Math.Min(this.windowSize, this.window.Count) - ((int)num);
                this.quotaRemaining = quotaRemaining - Math.Max(0, num6);
            }
            this.window.Remove((int)num);
            this.windowStart += num;
            int num7 = 0;

            if (this.windowSize <= this.slowStartThreshold)
            {
                this.windowSize = Math.Min(this.maxWindowSize, Math.Min((int)(this.slowStartThreshold + 1), (int)(this.windowSize + ((int)num))));
                if (!this.startup)
                {
                    num7 = 0;
                }
                else
                {
                    num7 = Math.Max(0, ((int)num4) - ((int)this.windowStart));
                }
            }
            else
            {
                this.congestionControlModeAcks += (int)num;
                int num8 = Math.Max(1, (this.lossWindowSize - this.slowStartThreshold) / 8);
                int num9 = ((this.windowSize - this.slowStartThreshold) * this.windowSize) / num8;
                if (this.congestionControlModeAcks > num9)
                {
                    this.congestionControlModeAcks = 0;
                    this.windowSize = Math.Min(this.maxWindowSize, this.windowSize + 1);
                }
                num7 = Math.Max(0, ((int)num4) - ((int)this.windowStart));
            }
            int num10 = Math.Min(this.windowSize, this.window.Count);

            if (num7 < num10)
            {
                flag = this.retransmissionWindow.Count == 0;
                for (int m = num7; (m < this.windowSize) && (m < this.window.Count); m++)
                {
                    long item = this.windowStart + m;
                    if (!this.window.GetTransferred(m) && !this.retransmissionWindow.Contains(item))
                    {
                        this.window.RecordRetry(m, Now);
                        this.retransmissionWindow.Add(item);
                    }
                }
            }
            if (this.window.Count > 0)
            {
                this.retryTimer.Set(this.Timeout);
            }
            return(flag);
        }
 private bool ProcessTransferred(SequenceRange range, int quotaRemaining)
 {
     if (range.Upper < this.windowStart)
     {
         if (((range.Upper == (this.windowStart - 1L)) && (quotaRemaining != -1)) && (quotaRemaining > this.quotaRemaining))
         {
             this.quotaRemaining = quotaRemaining - Math.Min(this.windowSize, this.window.Count);
         }
         return false;
     }
     if (range.Lower > this.windowStart)
     {
         for (long j = range.Lower; j <= range.Upper; j += 1L)
         {
             this.window.SetTransferred((int) (j - this.windowStart));
         }
         return false;
     }
     bool flag = false;
     this.retryTimer.Cancel();
     long num = (range.Upper - this.windowStart) + 1L;
     if (num == 1L)
     {
         for (int k = 1; k < this.window.Count; k++)
         {
             if (!this.window.GetTransferred(k))
             {
                 break;
             }
             num += 1L;
         }
     }
     long now = Now;
     long num4 = this.windowStart + this.windowSize;
     for (int i = 0; i < ((int) num); i++)
     {
         this.UpdateStats(now, this.window.GetLastAttemptTime(i));
     }
     if (quotaRemaining != -1)
     {
         int num6 = Math.Min(this.windowSize, this.window.Count) - ((int) num);
         this.quotaRemaining = quotaRemaining - Math.Max(0, num6);
     }
     this.window.Remove((int) num);
     this.windowStart += num;
     int num7 = 0;
     if (this.windowSize <= this.slowStartThreshold)
     {
         this.windowSize = Math.Min(this.maxWindowSize, Math.Min((int) (this.slowStartThreshold + 1), (int) (this.windowSize + ((int) num))));
         if (!this.startup)
         {
             num7 = 0;
         }
         else
         {
             num7 = Math.Max(0, ((int) num4) - ((int) this.windowStart));
         }
     }
     else
     {
         this.congestionControlModeAcks += (int) num;
         int num8 = Math.Max(1, (this.lossWindowSize - this.slowStartThreshold) / 8);
         int num9 = ((this.windowSize - this.slowStartThreshold) * this.windowSize) / num8;
         if (this.congestionControlModeAcks > num9)
         {
             this.congestionControlModeAcks = 0;
             this.windowSize = Math.Min(this.maxWindowSize, this.windowSize + 1);
         }
         num7 = Math.Max(0, ((int) num4) - ((int) this.windowStart));
     }
     int num10 = Math.Min(this.windowSize, this.window.Count);
     if (num7 < num10)
     {
         flag = this.retransmissionWindow.Count == 0;
         for (int m = num7; (m < this.windowSize) && (m < this.window.Count); m++)
         {
             long item = this.windowStart + m;
             if (!this.window.GetTransferred(m) && !this.retransmissionWindow.Contains(item))
             {
                 this.window.RecordRetry(m, Now);
                 this.retransmissionWindow.Add(item);
             }
         }
     }
     if (this.window.Count > 0)
     {
         this.retryTimer.Set(this.Timeout);
     }
     return flag;
 }
        // It is necessary that ProcessAcknowledgement be called prior, as 
        // this method does not check for valid ack ranges.
        // This method returns true if the calling method should start sending retries 
        // obtained from GetMessageInfoForRetry.
        bool ProcessTransferred(SequenceRange range, int quotaRemaining)
        {
            if (range.Upper < this.windowStart)
            {
                if (range.Upper == this.windowStart - 1 && (quotaRemaining != -1) && quotaRemaining > this.quotaRemaining)
                    this.quotaRemaining = quotaRemaining - Math.Min(this.windowSize, this.window.Count);

                return false;
            }
            else if (range.Lower <= this.windowStart)
            {
                bool send = false;

                this.retryTimer.Cancel();

                Int64 slide = range.Upper - this.windowStart + 1;

                // For Request Reply: Requests are transferred 1 at a time, (i.e. when the reply comes back).
                // The TransmissionStrategy only removes messages if the window start is removed.
                // Because of this, RequestReply messages transferred out of order will cause many, many retries.
                // To avoid extraneous retries we mark each message transferred, and we remove our virtual slide.
                if (slide == 1)
                {
                    for (int i = 1; i < this.window.Count; i++)
                    {
                        if (this.window.GetTransferred(i))
                        {
                            slide++;
                        }
                        else
                        {
                            break;
                        }
                    }
                }

                Int64 now = Now;
                Int64 oldWindowEnd = this.windowStart + this.windowSize;

                for (int i = 0; i < (int)slide; i++)
                    UpdateStats(now, this.window.GetLastAttemptTime(i));

                if (quotaRemaining != -1)
                {
                    int inFlightAfterAck = Math.Min(this.windowSize, this.window.Count) - (int)slide;
                    this.quotaRemaining = quotaRemaining - Math.Max(0, inFlightAfterAck);
                }

                this.window.Remove((int)slide);

                this.windowStart += slide;

                int sendBeginIndex = 0;

                if (this.windowSize <= this.slowStartThreshold)
                {
                    this.windowSize = Math.Min(this.maxWindowSize, Math.Min(this.slowStartThreshold + 1, this.windowSize + (int)slide));

                    if (!startup)
                        sendBeginIndex = 0;
                    else
                        sendBeginIndex = Math.Max(0, (int)oldWindowEnd - (int)this.windowStart);
                }
                else
                {
                    this.congestionControlModeAcks += (int)slide;

                    // EXPERIMENTAL, needs optimizing ///
                    int segmentSize = Math.Max(1, (this.lossWindowSize - this.slowStartThreshold) / 8);
                    int windowGrowthAckThreshold = ((this.windowSize - this.slowStartThreshold) * this.windowSize) / segmentSize;

                    if (this.congestionControlModeAcks > windowGrowthAckThreshold)
                    {
                        this.congestionControlModeAcks = 0;
                        this.windowSize = Math.Min(this.maxWindowSize, this.windowSize + 1);
                    }

                    sendBeginIndex = Math.Max(0, (int)oldWindowEnd - (int)this.windowStart);
                }

                int sendEndIndex = Math.Min(this.windowSize, this.window.Count);

                if (sendBeginIndex < sendEndIndex)
                {
                    send = (this.retransmissionWindow.Count == 0);

                    for (int i = sendBeginIndex; i < this.windowSize && i < this.window.Count; i++)
                    {
                        Int64 sequenceNumber = this.windowStart + i;

                        if (!this.window.GetTransferred(i) && !this.retransmissionWindow.Contains(sequenceNumber))
                        {
                            this.window.RecordRetry(i, Now);
                            retransmissionWindow.Add(sequenceNumber);
                        }
                    }
                }

                if (window.Count > 0)
                {
                    this.retryTimer.Set(this.Timeout);
                }

                return send;
            }
            else
            {
                for (Int64 i = range.Lower; i <= range.Upper; i++)
                {
                    this.window.SetTransferred((int)(i - this.windowStart));
                }
            }

            return false;
        }