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(); } }
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 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); } }
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; }
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); } }
// 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); } }
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; }
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 static bool CanMerge(long sequenceNumber, SequenceRangeCollection ranges) { if (ranges.Count < ReliableMessagingConstants.MaxSequenceRanges) { return(true); } ranges = ranges.MergeWith(sequenceNumber); return(ranges.Count <= ReliableMessagingConstants.MaxSequenceRanges); }
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 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); }
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 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); } }
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); } }
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)); } }
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" }))); } }
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(); } } } } }
public void SetFinalAck(SequenceRangeCollection finalRanges) { this.finalRanges = finalRanges; }
public bool IsFinalAckConsistent(SequenceRangeCollection ranges) { return(this.strategy.IsFinalAckConsistent(ranges)); }
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)); }
public override SequenceRangeCollection MergeWith(SequenceRange newRange) { return(SequenceRangeCollection.GeneralMerge(this.ranges, newRange)); }
public InvalidAcknowledgementFault(UniqueId sequenceID, SequenceRangeCollection ranges) : base(true, WsrmFeb2005Strings.InvalidAcknowledgement, SR.GetString(SR.InvalidAcknowledgementFaultReason), SR.GetString(SR.InvalidAcknowledgementReceived), sequenceID, true, false) { this.ranges = ranges; }
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(); } }
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); }