コード例 #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();
            }
        }
コード例 #2
0
        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));
            }
        }
コード例 #3
0
        public void ProcessTransferred(Int64 transferred, SequenceRangeCollection ranges, int quotaRemaining)
        {
            if (transferred < 0)
            {
                throw Fx.AssertAndThrow("Argument transferred must be a valid sequence number or 0 for protocol messages.");
            }

            bool invalidAck;

            // ignored, TransmissionStrategy is being used to keep track of what must be re-sent.
            // In the Request-Reply case this state may not align with acks.
            bool inconsistentAck;

            this.strategy.ProcessAcknowledgement(ranges, out invalidAck, out inconsistentAck);
            invalidAck = (invalidAck || ((transferred != 0) && !ranges.Contains(transferred)));

            if (!invalidAck)
            {
                if ((transferred > 0) && this.strategy.ProcessTransferred(transferred, quotaRemaining))
                {
                    ActionItem.Schedule(sendRetries, this);
                }
                else
                {
                    this.OnTransferComplete();
                }
            }
            else
            {
                WsrmFault fault = new InvalidAcknowledgementFault(this.id, ranges);
                RaiseFault(fault.CreateException(), fault);
            }
        }
コード例 #4
0
 public WsrmAcknowledgmentHeader(ReliableMessagingVersion reliableMessagingVersion, UniqueId sequenceID, SequenceRangeCollection ranges, bool final, int bufferRemaining) : base(reliableMessagingVersion)
 {
     this.sequenceID      = sequenceID;
     this.ranges          = ranges;
     this.final           = final;
     this.bufferRemaining = bufferRemaining;
 }
コード例 #5
0
        public void ProcessTransferred(long transferred, SequenceRangeCollection ranges, int quotaRemaining)
        {
            bool flag;
            bool flag2;

            if (transferred < 0L)
            {
                throw Fx.AssertAndThrow("Argument transferred must be a valid sequence number or 0 for protocol messages.");
            }
            this.strategy.ProcessAcknowledgement(ranges, out flag, out flag2);
            if (!flag && ((transferred == 0L) || ranges.Contains(transferred)))
            {
                if ((transferred > 0L) && this.strategy.ProcessTransferred(transferred, quotaRemaining))
                {
                    ActionItem.Schedule(sendRetries, this);
                }
                else
                {
                    this.OnTransferComplete();
                }
            }
            else
            {
                WsrmFault fault = new InvalidAcknowledgementFault(this.id, ranges);
                this.RaiseFault(fault.CreateException(), fault);
            }
        }
コード例 #6
0
        // Called for Duplex and Output
        public bool ProcessTransferred(SequenceRangeCollection ranges, int quotaRemaining)
        {
            if (ranges.Count == 0)
            {
                return(false);
            }

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

                bool send = false;

                for (int rangeIndex = 0; rangeIndex < ranges.Count; rangeIndex++)
                {
                    if (ProcessTransferred(ranges[rangeIndex], quotaRemaining))
                    {
                        send = true;
                    }
                }

                return(send);
            }
        }
コード例 #7
0
 private WsrmAcknowledgmentInfo(UniqueId sequenceID, SequenceRangeCollection ranges, bool final, int bufferRemaining, MessageHeaderInfo header) : base(header)
 {
     this.sequenceID      = sequenceID;
     this.ranges          = ranges;
     this.final           = final;
     this.bufferRemaining = bufferRemaining;
 }
コード例 #8
0
        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));
        }
コード例 #9
0
 public static bool CanMerge(long sequenceNumber, SequenceRangeCollection ranges)
 {
     if (ranges.Count < ReliableMessagingConstants.MaxSequenceRanges)
     {
         return(true);
     }
     ranges = ranges.MergeWith(sequenceNumber);
     return(ranges.Count <= ReliableMessagingConstants.MaxSequenceRanges);
 }
コード例 #10
0
        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;
        }
コード例 #11
0
 public void Merge(long sequenceNumber, bool isLast)
 {
     this.ranges = this.ranges.MergeWith(sequenceNumber);
     if (isLast)
     {
         this.last = sequenceNumber;
     }
     if (this.AllAdded)
     {
         this.shutdownWaitObject.Set();
     }
 }
 public ReliableRequestSessionChannel(ChannelManagerBase factory, IReliableFactorySettings settings, IClientReliableChannelBinder binder, FaultHelper faultHelper, LateBoundChannelParameterCollection channelParameters, UniqueId inputID) : base(factory, binder.RemoteAddress, binder.Via, true)
 {
     this.ranges   = SequenceRangeCollection.Empty;
     this.settings = settings;
     this.binder   = binder;
     this.session  = new ClientReliableSession(this, settings, binder, faultHelper, inputID);
     this.session.PollingCallback             = new ClientReliableSession.PollingHandler(this.PollingCallback);
     this.session.UnblockChannelCloseCallback = new ChannelReliableSession.UnblockChannelCloseHandler(this.UnblockClose);
     if (this.settings.ReliableMessagingVersion == ReliableMessagingVersion.WSReliableMessagingFebruary2005)
     {
         this.shutdownHandle = new InterruptibleWaitObject(false);
     }
     else
     {
         this.replyAckConsistencyGuard = new Guard(0x7fffffff);
     }
     this.binder.Faulted     += new BinderExceptionHandler(this.OnBinderFaulted);
     this.binder.OnException += new BinderExceptionHandler(this.OnBinderException);
     this.channelParameters   = channelParameters;
     channelParameters.SetChannel(this);
 }
コード例 #13
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));
 }
コード例 #14
0
        public void ProcessTransferred(SequenceRangeCollection ranges, int quotaRemaining)
        {
            bool flag;
            bool flag2;

            this.strategy.ProcessAcknowledgement(ranges, out flag, out flag2);
            if (!flag && !flag2)
            {
                if (this.strategy.ProcessTransferred(ranges, quotaRemaining))
                {
                    ActionItem.Schedule(sendRetries, this);
                }
                else
                {
                    this.OnTransferComplete();
                }
            }
            else
            {
                WsrmFault fault = new InvalidAcknowledgementFault(this.id, ranges);
                this.RaiseFault(fault.CreateException(), fault);
            }
        }
コード例 #15
0
 public bool ProcessTransferred(SequenceRangeCollection ranges, int quotaRemaining)
 {
     if (ranges.Count == 0)
     {
         return(false);
     }
     lock (this.ThisLock)
     {
         if (this.closed)
         {
             return(false);
         }
         bool flag = false;
         for (int i = 0; i < ranges.Count; i++)
         {
             if (this.ProcessTransferred(ranges[i], quotaRemaining))
             {
                 flag = true;
             }
         }
         return(flag);
     }
 }
コード例 #16
0
        public bool IsFinalAckConsistent(SequenceRangeCollection ranges)
        {
            lock (ThisLock)
            {
                if (_closed)
                {
                    return(true);
                }

                // Nothing sent, ensure ack is empty.
                if ((_windowStart == 1) && (_window.Count == 0))
                {
                    return(ranges.Count == 0);
                }

                // Ack is empty or first range is invalid.
                if (ranges.Count == 0 || ranges[0].Lower != 1)
                {
                    return(false);
                }

                return(ranges[0].Upper >= (_windowStart - 1));
            }
        }
コード例 #17
0
        internal static void ReadAck(ReliableMessagingVersion reliableMessagingVersion, XmlDictionaryReader reader, out UniqueId sequenceId, out SequenceRangeCollection rangeCollection, out bool final)
        {
            WsrmFeb2005Dictionary dictionary   = XD.WsrmFeb2005Dictionary;
            XmlDictionaryString   namespaceUri = WsrmIndex.GetNamespace(reliableMessagingVersion);

            reader.ReadStartElement(dictionary.SequenceAcknowledgement, namespaceUri);
            reader.ReadStartElement(dictionary.Identifier, namespaceUri);
            sequenceId = reader.ReadContentAsUniqueId();
            reader.ReadEndElement();
            bool allowZero = reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessagingFebruary2005;

            rangeCollection = SequenceRangeCollection.Empty;
            while (reader.IsStartElement(dictionary.AcknowledgementRange, namespaceUri))
            {
                reader.MoveToAttribute("Lower");
                long lower = WsrmUtilities.ReadSequenceNumber(reader, allowZero);
                reader.MoveToAttribute("Upper");
                long upper = WsrmUtilities.ReadSequenceNumber(reader, allowZero);
                if ((((lower < 0L) || (lower > upper)) || (((reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessagingFebruary2005) && (lower == 0L)) && (upper > 0L))) || ((reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessaging11) && (lower == 0L)))
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(System.ServiceModel.SR.GetString("InvalidSequenceRange", new object[] { lower, upper })));
                }
                rangeCollection = rangeCollection.MergeWith(new SequenceRange(lower, upper));
                reader.MoveToElement();
                WsrmUtilities.ReadEmptyElement(reader);
            }
            bool flag2 = rangeCollection.Count > 0;

            final = false;
            if (reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessaging11)
            {
                Wsrm11Dictionary dictionary2 = DXD.Wsrm11Dictionary;
                if (reader.IsStartElement(dictionary2.None, namespaceUri))
                {
                    if (flag2)
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(System.ServiceModel.SR.GetString("UnexpectedXmlChildNode", new object[] { reader.Name, reader.NodeType, dictionary.SequenceAcknowledgement })));
                    }
                    WsrmUtilities.ReadEmptyElement(reader);
                    flag2 = true;
                }
                if (reader.IsStartElement(dictionary2.Final, namespaceUri))
                {
                    if (!flag2)
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(System.ServiceModel.SR.GetString("UnexpectedXmlChildNode", new object[] { reader.Name, reader.NodeType, dictionary.SequenceAcknowledgement })));
                    }
                    WsrmUtilities.ReadEmptyElement(reader);
                    final = true;
                }
            }
            bool flag4 = false;

            while (reader.IsStartElement(dictionary.Nack, namespaceUri))
            {
                if (flag2)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(System.ServiceModel.SR.GetString("UnexpectedXmlChildNode", new object[] { reader.Name, reader.NodeType, "Body" })));
                }
                reader.ReadStartElement();
                WsrmUtilities.ReadSequenceNumber(reader, true);
                reader.ReadEndElement();
                flag4 = true;
            }
            if (!flag2 && !flag4)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(System.ServiceModel.SR.GetString("UnexpectedXmlChildNode", new object[] { reader.Name, reader.NodeType, "Body" })));
            }
        }
コード例 #18
0
        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;
        }
 public InvalidAcknowledgementFault(UniqueId sequenceID, SequenceRangeCollection ranges) : base(true, "InvalidAcknowledgement", System.ServiceModel.SR.GetString("InvalidAcknowledgementFaultReason"), System.ServiceModel.SR.GetString("InvalidAcknowledgementReceived"), sequenceID, true, false)
 {
     this.ranges = ranges;
 }
        private void ProcessReply(Message reply, IReliableRequest request, long requestSequenceNumber)
        {
            WsrmMessageInfo info = WsrmMessageInfo.Get(this.settings.MessageVersion, this.settings.ReliableMessagingVersion, this.binder.Channel, this.binder.GetInnerSession(), reply);

            if (this.session.ProcessInfo(info, null) && this.session.VerifyDuplexProtocolElements(info, null))
            {
                bool flag = this.settings.ReliableMessagingVersion == ReliableMessagingVersion.WSReliableMessaging11;
                if (info.WsrmHeaderFault != null)
                {
                    info.Message.Close();
                    if (!(info.WsrmHeaderFault is UnknownSequenceFault))
                    {
                        throw Fx.AssertAndThrow("Fault must be UnknownSequence fault.");
                    }
                    if (this.terminateRequestor == null)
                    {
                        throw Fx.AssertAndThrow("If we start getting UnknownSequence, terminateRequestor cannot be null.");
                    }
                    this.terminateRequestor.SetInfo(info);
                }
                else if (info.AcknowledgementInfo == null)
                {
                    WsrmFault fault = SequenceTerminatedFault.CreateProtocolFault(this.session.InputID, System.ServiceModel.SR.GetString("SequenceTerminatedReplyMissingAcknowledgement"), System.ServiceModel.SR.GetString("ReplyMissingAcknowledgement"));
                    info.Message.Close();
                    this.session.OnLocalFault(fault.CreateException(), fault, null);
                }
                else if (flag && (info.TerminateSequenceInfo != null))
                {
                    UniqueId  sequenceID = (info.TerminateSequenceInfo.Identifier == this.session.OutputID) ? this.session.InputID : this.session.OutputID;
                    WsrmFault fault2     = SequenceTerminatedFault.CreateProtocolFault(sequenceID, System.ServiceModel.SR.GetString("SequenceTerminatedUnsupportedTerminateSequence"), System.ServiceModel.SR.GetString("UnsupportedTerminateSequenceExceptionString"));
                    info.Message.Close();
                    this.session.OnLocalFault(fault2.CreateException(), fault2, null);
                }
                else if (flag && info.AcknowledgementInfo.Final)
                {
                    info.Message.Close();
                    if (this.closeRequestor == null)
                    {
                        string    exceptionMessage = System.ServiceModel.SR.GetString("UnsupportedCloseExceptionString");
                        string    faultReason      = System.ServiceModel.SR.GetString("SequenceTerminatedUnsupportedClose");
                        WsrmFault fault3           = SequenceTerminatedFault.CreateProtocolFault(this.session.OutputID, faultReason, exceptionMessage);
                        this.session.OnLocalFault(fault3.CreateException(), fault3, null);
                    }
                    else
                    {
                        WsrmFault fault4 = WsrmUtilities.ValidateFinalAck(this.session, info, this.connection.Last);
                        if (fault4 == null)
                        {
                            this.closeRequestor.SetInfo(info);
                        }
                        else
                        {
                            this.session.OnLocalFault(fault4.CreateException(), fault4, null);
                        }
                    }
                }
                else
                {
                    int quotaRemaining = -1;
                    if (this.settings.FlowControlEnabled)
                    {
                        quotaRemaining = info.AcknowledgementInfo.BufferRemaining;
                    }
                    if ((info.SequencedMessageInfo != null) && !ReliableInputConnection.CanMerge(info.SequencedMessageInfo.SequenceNumber, this.ranges))
                    {
                        info.Message.Close();
                    }
                    else
                    {
                        bool flag2 = (this.replyAckConsistencyGuard != null) ? this.replyAckConsistencyGuard.Enter() : false;
                        try
                        {
                            this.connection.ProcessTransferred(requestSequenceNumber, info.AcknowledgementInfo.Ranges, quotaRemaining);
                            this.session.OnRemoteActivity(this.connection.Strategy.QuotaRemaining == 0);
                            if (info.SequencedMessageInfo != null)
                            {
                                lock (base.ThisLock)
                                {
                                    this.ranges = this.ranges.MergeWith(info.SequencedMessageInfo.SequenceNumber);
                                }
                            }
                        }
                        finally
                        {
                            if (flag2)
                            {
                                this.replyAckConsistencyGuard.Exit();
                            }
                        }
                        if (request != null)
                        {
                            if (WsrmUtilities.IsWsrmAction(this.settings.ReliableMessagingVersion, info.Action))
                            {
                                info.Message.Close();
                                request.Set(null);
                            }
                            else
                            {
                                request.Set(info.Message);
                            }
                        }
                        if ((this.shutdownHandle != null) && this.connection.CheckForTermination())
                        {
                            this.shutdownHandle.Set();
                        }
                        if (request != null)
                        {
                            request.Complete();
                        }
                    }
                }
            }
        }
コード例 #21
0
 public void SetFinalAck(SequenceRangeCollection finalRanges)
 {
     this.finalRanges = finalRanges;
 }
コード例 #22
0
 public bool IsFinalAckConsistent(SequenceRangeCollection ranges)
 {
     return(this.strategy.IsFinalAckConsistent(ranges));
 }
コード例 #23
0
 internal static void AddAcknowledgementHeader(ReliableMessagingVersion reliableMessagingVersion, Message message, UniqueId id, SequenceRangeCollection ranges, bool final, int bufferRemaining)
 {
     message.Headers.Insert(0, new WsrmAcknowledgmentHeader(reliableMessagingVersion, id, ranges, final, bufferRemaining));
 }
コード例 #24
0
 public override SequenceRangeCollection MergeWith(SequenceRange newRange)
 {
     return(SequenceRangeCollection.GeneralMerge(this.ranges, newRange));
 }
コード例 #25
0
 public InvalidAcknowledgementFault(UniqueId sequenceID, SequenceRangeCollection ranges)
     : base(true, WsrmFeb2005Strings.InvalidAcknowledgement, SR.GetString(SR.InvalidAcknowledgementFaultReason),
            SR.GetString(SR.InvalidAcknowledgementReceived), sequenceID, true, false)
 {
     this.ranges = ranges;
 }
コード例 #26
0
 internal static void AddAcknowledgementHeader(ReliableMessagingVersion reliableMessagingVersion, Message message, UniqueId id, SequenceRangeCollection ranges, bool final)
 {
     AddAcknowledgementHeader(reliableMessagingVersion, message, id, ranges, final, -1);
 }
        void ProcessReply(Message reply, IReliableRequest request, Int64 requestSequenceNumber)
        {
            WsrmMessageInfo messageInfo = WsrmMessageInfo.Get(this.settings.MessageVersion,
                                                              this.settings.ReliableMessagingVersion, this.binder.Channel, this.binder.GetInnerSession(), reply);

            if (!this.session.ProcessInfo(messageInfo, null))
            {
                return;
            }

            if (!this.session.VerifyDuplexProtocolElements(messageInfo, null))
            {
                return;
            }

            bool wsrm11 = this.settings.ReliableMessagingVersion == ReliableMessagingVersion.WSReliableMessaging11;

            if (messageInfo.WsrmHeaderFault != null)
            {
                // Close message now, going to stop processing in all cases.
                messageInfo.Message.Close();

                if (!(messageInfo.WsrmHeaderFault is UnknownSequenceFault))
                {
                    throw Fx.AssertAndThrow("Fault must be UnknownSequence fault.");
                }

                if (this.terminateRequestor == null)
                {
                    throw Fx.AssertAndThrow("If we start getting UnknownSequence, terminateRequestor cannot be null.");
                }

                this.terminateRequestor.SetInfo(messageInfo);

                return;
            }

            if (messageInfo.AcknowledgementInfo == null)
            {
                WsrmFault fault = SequenceTerminatedFault.CreateProtocolFault(this.session.InputID,
                                                                              SR.GetString(SR.SequenceTerminatedReplyMissingAcknowledgement),
                                                                              SR.GetString(SR.ReplyMissingAcknowledgement));
                messageInfo.Message.Close();
                this.session.OnLocalFault(fault.CreateException(), fault, null);
                return;
            }

            if (wsrm11 && (messageInfo.TerminateSequenceInfo != null))
            {
                UniqueId faultId = (messageInfo.TerminateSequenceInfo.Identifier == this.session.OutputID)
                    ? this.session.InputID
                    : this.session.OutputID;

                WsrmFault fault = SequenceTerminatedFault.CreateProtocolFault(faultId,
                                                                              SR.GetString(SR.SequenceTerminatedUnsupportedTerminateSequence),
                                                                              SR.GetString(SR.UnsupportedTerminateSequenceExceptionString));
                messageInfo.Message.Close();
                this.session.OnLocalFault(fault.CreateException(), fault, null);
                return;
            }
            else if (wsrm11 && messageInfo.AcknowledgementInfo.Final)
            {
                // Close message now, going to stop processing in all cases.
                messageInfo.Message.Close();

                if (this.closeRequestor == null)
                {
                    // Remote endpoint signaled Close, this is not allowed so we fault.
                    string exceptionString = SR.GetString(SR.UnsupportedCloseExceptionString);
                    string faultString     = SR.GetString(SR.SequenceTerminatedUnsupportedClose);

                    WsrmFault fault = SequenceTerminatedFault.CreateProtocolFault(this.session.OutputID, faultString,
                                                                                  exceptionString);
                    this.session.OnLocalFault(fault.CreateException(), fault, null);
                }
                else
                {
                    WsrmFault fault = WsrmUtilities.ValidateFinalAck(this.session, messageInfo, this.connection.Last);

                    if (fault == null)
                    {
                        // Received valid final ack after sending Close, inform the close thread.
                        this.closeRequestor.SetInfo(messageInfo);
                    }
                    else
                    {
                        // Received invalid final ack after sending Close, fault.
                        this.session.OnLocalFault(fault.CreateException(), fault, null);
                    }
                }

                return;
            }

            int bufferRemaining = -1;

            if (this.settings.FlowControlEnabled)
            {
                bufferRemaining = messageInfo.AcknowledgementInfo.BufferRemaining;
            }

            // We accept no more than MaxSequenceRanges ranges to limit the serialized ack size and
            // the amount of memory taken up by the ack ranges. Since request reply uses the presence of
            // a reply as an acknowledgement we cannot call ProcessTransferred (which stops retrying the
            // request) if we intend to drop the message. This means the limit is not strict since we do
            // not check for the limit and merge the ranges atomically. The limit + the number of
            // concurrent threads is a sufficient mitigation.
            if ((messageInfo.SequencedMessageInfo != null) &&
                !ReliableInputConnection.CanMerge(messageInfo.SequencedMessageInfo.SequenceNumber, this.ranges))
            {
                messageInfo.Message.Close();
                return;
            }

            bool exitGuard = this.replyAckConsistencyGuard != null?this.replyAckConsistencyGuard.Enter() : false;

            try
            {
                this.connection.ProcessTransferred(requestSequenceNumber,
                                                   messageInfo.AcknowledgementInfo.Ranges, bufferRemaining);

                this.session.OnRemoteActivity(this.connection.Strategy.QuotaRemaining == 0);

                if (messageInfo.SequencedMessageInfo != null)
                {
                    lock (this.ThisLock)
                    {
                        this.ranges = this.ranges.MergeWith(messageInfo.SequencedMessageInfo.SequenceNumber);
                    }
                }
            }
            finally
            {
                if (exitGuard)
                {
                    this.replyAckConsistencyGuard.Exit();
                }
            }

            if (request != null)
            {
                if (WsrmUtilities.IsWsrmAction(this.settings.ReliableMessagingVersion, messageInfo.Action))
                {
                    messageInfo.Message.Close();
                    request.Set(null);
                }
                else
                {
                    request.Set(messageInfo.Message);
                }
            }

            // The termination mechanism in the TerminateSequence fails with RequestReply.
            // Since the ack ranges are updated after ProcessTransferred is called and
            // ProcessTransferred potentially signals the Termination process, this channel
            // winds up sending a message with the ack for last message missing.
            // Thus we send the termination after we update the ranges.

            if ((this.shutdownHandle != null) && this.connection.CheckForTermination())
            {
                this.shutdownHandle.Set();
            }

            if (request != null)
            {
                request.Complete();
            }
        }
コード例 #28
0
        internal static Message CreateAcknowledgmentMessage(MessageVersion version, ReliableMessagingVersion reliableMessagingVersion, UniqueId id, SequenceRangeCollection ranges, bool final, int bufferRemaining)
        {
            Message message = Message.CreateMessage(version, WsrmIndex.GetSequenceAcknowledgementActionHeader(version.Addressing, reliableMessagingVersion));

            AddAcknowledgementHeader(reliableMessagingVersion, message, id, ranges, final, bufferRemaining);
            message.Properties.AllowOutputBatching = false;
            return(message);
        }