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(); } } } } }
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(); } }
public static WsrmMessageInfo Get(MessageVersion messageVersion, ReliableMessagingVersion reliableMessagingVersion, IChannel channel, ISession session, System.ServiceModel.Channels.Message message, bool csrOnly) { WsrmMessageInfo info = new WsrmMessageInfo { message = message }; bool isFault = true; try { isFault = message.IsFault; MessageHeaders headers = message.Headers; string action = headers.Action; info.action = action; bool flag2 = false; bool flag3 = reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessagingFebruary2005; bool flag4 = reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessaging11; bool flag5 = false; if (action == WsrmIndex.GetCreateSequenceResponseActionString(reliableMessagingVersion)) { info.createSequenceResponseInfo = System.ServiceModel.Channels.CreateSequenceResponseInfo.ReadMessage(messageVersion, reliableMessagingVersion, message, headers); ValidateMustUnderstand(messageVersion, message); return(info); } if (csrOnly) { return(info); } if (action == WsrmIndex.GetTerminateSequenceActionString(reliableMessagingVersion)) { info.terminateSequenceInfo = System.ServiceModel.Channels.TerminateSequenceInfo.ReadMessage(messageVersion, reliableMessagingVersion, message, headers); flag2 = true; } else if (action == WsrmIndex.GetCreateSequenceActionString(reliableMessagingVersion)) { info.createSequenceInfo = System.ServiceModel.Channels.CreateSequenceInfo.ReadMessage(messageVersion, reliableMessagingVersion, session as ISecureConversationSession, message, headers); if (flag3) { ValidateMustUnderstand(messageVersion, message); return(info); } flag5 = true; } else if (flag4) { if (action == "http://docs.oasis-open.org/ws-rx/wsrm/200702/CloseSequence") { info.closeSequenceInfo = System.ServiceModel.Channels.CloseSequenceInfo.ReadMessage(messageVersion, message, headers); flag2 = true; } else if (action == "http://docs.oasis-open.org/ws-rx/wsrm/200702/CloseSequenceResponse") { info.closeSequenceResponseInfo = System.ServiceModel.Channels.CloseSequenceResponseInfo.ReadMessage(messageVersion, message, headers); flag2 = true; } else if (action == WsrmIndex.GetTerminateSequenceResponseActionString(reliableMessagingVersion)) { info.terminateSequenceResponseInfo = System.ServiceModel.Channels.TerminateSequenceResponseInfo.ReadMessage(messageVersion, message, headers); flag2 = true; } } string namespaceString = WsrmIndex.GetNamespaceString(reliableMessagingVersion); bool flag6 = messageVersion.Envelope == EnvelopeVersion.Soap11; bool flag7 = false; int num = -1; int headerIndex = -1; int num3 = -1; int num4 = -1; int num5 = -1; int num6 = -1; int index = -1; int num8 = -1; int num9 = -1; for (int i = 0; i < headers.Count; i++) { MessageHeaderInfo info2 = headers[i]; if (messageVersion.Envelope.IsUltimateDestinationActor(info2.Actor) && (info2.Namespace == namespaceString)) { bool flag8 = true; if (flag5) { if (flag4 && (info2.Name == "UsesSequenceSSL")) { if (num8 != -1) { num = i; break; } num8 = i; } else if (flag4 && (info2.Name == "UsesSequenceSTR")) { if (num9 != -1) { num = i; break; } num9 = i; } else { flag8 = false; } } else if (info2.Name == "Sequence") { if (headerIndex != -1) { num = i; break; } headerIndex = i; } else if (info2.Name == "SequenceAcknowledgement") { if (num3 != -1) { num = i; break; } num3 = i; } else if (info2.Name == "AckRequested") { if (num4 != -1) { num = i; break; } num4 = i; } else if (flag6 && (info2.Name == "SequenceFault")) { if (index != -1) { num = i; break; } index = i; } else { flag8 = false; } if (flag8) { if (i > num5) { num5 = i; } if (num6 == -1) { num6 = i; } } } } if (num != -1) { Collection <MessageHeaderInfo> notUnderstoodHeaders = new Collection <MessageHeaderInfo> { headers[num] }; throw System.ServiceModel.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MustUnderstandSoapException(notUnderstoodHeaders, messageVersion.Envelope)); } if (num5 > -1) { BufferedMessage message2 = message as BufferedMessage; if ((message2 != null) && message2.Headers.ContainsOnlyBufferedMessageHeaders) { flag7 = true; using (XmlDictionaryReader reader = headers.GetReaderAtHeader(num6)) { for (int j = num6; j <= num5; j++) { MessageHeaderInfo header = headers[j]; if (flag5) { if (flag4 && (j == num8)) { info.usesSequenceSSLInfo = WsrmUsesSequenceSSLInfo.ReadHeader(reader, header); headers.UnderstoodHeaders.Add(header); } else if (flag4 && (j == num9)) { info.usesSequenceSTRInfo = WsrmUsesSequenceSTRInfo.ReadHeader(reader, header); headers.UnderstoodHeaders.Add(header); } else { reader.Skip(); } } else if (j == headerIndex) { info.sequencedMessageInfo = WsrmSequencedMessageInfo.ReadHeader(reliableMessagingVersion, reader, header); headers.UnderstoodHeaders.Add(header); } else if (j == num3) { info.acknowledgementInfo = WsrmAcknowledgmentInfo.ReadHeader(reliableMessagingVersion, reader, header); headers.UnderstoodHeaders.Add(header); } else if (j == num4) { info.ackRequestedInfo = WsrmAckRequestedInfo.ReadHeader(reliableMessagingVersion, reader, header); headers.UnderstoodHeaders.Add(header); } else { reader.Skip(); } } } } } if ((num5 > -1) && !flag7) { flag7 = true; if (flag5) { if (num8 != -1) { using (XmlDictionaryReader reader2 = headers.GetReaderAtHeader(num8)) { MessageHeaderInfo info4 = headers[num8]; info.usesSequenceSSLInfo = WsrmUsesSequenceSSLInfo.ReadHeader(reader2, info4); headers.UnderstoodHeaders.Add(info4); } } if (num9 == -1) { goto Label_05CB; } using (XmlDictionaryReader reader3 = headers.GetReaderAtHeader(num9)) { MessageHeaderInfo info5 = headers[num9]; info.usesSequenceSTRInfo = WsrmUsesSequenceSTRInfo.ReadHeader(reader3, info5); headers.UnderstoodHeaders.Add(info5); goto Label_05CB; } } if (headerIndex != -1) { using (XmlDictionaryReader reader4 = headers.GetReaderAtHeader(headerIndex)) { MessageHeaderInfo info6 = headers[headerIndex]; info.sequencedMessageInfo = WsrmSequencedMessageInfo.ReadHeader(reliableMessagingVersion, reader4, info6); headers.UnderstoodHeaders.Add(info6); } } if (num3 != -1) { using (XmlDictionaryReader reader5 = headers.GetReaderAtHeader(num3)) { MessageHeaderInfo info7 = headers[num3]; info.acknowledgementInfo = WsrmAcknowledgmentInfo.ReadHeader(reliableMessagingVersion, reader5, info7); headers.UnderstoodHeaders.Add(info7); } } if (num4 != -1) { using (XmlDictionaryReader reader6 = headers.GetReaderAtHeader(num4)) { MessageHeaderInfo info8 = headers[num4]; info.ackRequestedInfo = WsrmAckRequestedInfo.ReadHeader(reliableMessagingVersion, reader6, info8); headers.UnderstoodHeaders.Add(info8); } } } Label_05CB: if (flag5) { System.ServiceModel.Channels.CreateSequenceInfo.ValidateCreateSequenceHeaders(messageVersion, session as ISecureConversationSession, info); ValidateMustUnderstand(messageVersion, message); return(info); } if ((info.sequencedMessageInfo == null) && (info.action == null)) { if (flag3) { throw System.ServiceModel.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageHeaderException(System.ServiceModel.SR.GetString("NoActionNoSequenceHeaderReason"), messageVersion.Addressing.Namespace, "Action", false)); } throw System.ServiceModel.DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateWsrmRequiredException(messageVersion)); } if ((info.sequencedMessageInfo == null) && message.IsFault) { System.ServiceModel.Channels.WsrmHeaderFault fault; info.faultInfo = System.ServiceModel.Channels.MessageFault.CreateFault(message, 0x10000); if (flag6) { if (System.ServiceModel.Channels.WsrmHeaderFault.TryCreateFault11(reliableMessagingVersion, message, info.faultInfo, index, out fault)) { info.faultInfo = fault; info.faultException = WsrmFault.CreateException(fault); } } else if (System.ServiceModel.Channels.WsrmHeaderFault.TryCreateFault12(reliableMessagingVersion, message, info.faultInfo, out fault)) { info.faultInfo = fault; info.faultException = WsrmFault.CreateException(fault); } if (fault == null) { FaultConverter property = channel.GetProperty <FaultConverter>(); if (property == null) { property = FaultConverter.GetDefaultFaultConverter(messageVersion); } if (!property.TryCreateException(message, info.faultInfo, out info.faultException)) { info.faultException = new ProtocolException(System.ServiceModel.SR.GetString("UnrecognizedFaultReceived", new object[] { info.faultInfo.Code.Namespace, info.faultInfo.Code.Name, System.ServiceModel.FaultException.GetSafeReasonText(info.faultInfo) })); } } flag2 = true; } if (!flag7 && !flag2) { if (flag3) { throw System.ServiceModel.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ActionNotSupportedException(System.ServiceModel.SR.GetString("NonWsrmFeb2005ActionNotSupported", new object[] { action }))); } throw System.ServiceModel.DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateWsrmRequiredException(messageVersion)); } if (!flag2 && !WsrmUtilities.IsWsrmAction(reliableMessagingVersion, action)) { return(info); } ValidateMustUnderstand(messageVersion, message); } catch (InternalFaultException exception) { if (System.ServiceModel.DiagnosticUtility.ShouldTraceInformation) { System.ServiceModel.DiagnosticUtility.ExceptionUtility.TraceHandledException(exception, TraceEventType.Information); } info.FaultReply = exception.FaultReply; info.faultException = exception.InnerException; } catch (CommunicationException exception2) { if (System.ServiceModel.DiagnosticUtility.ShouldTraceInformation) { System.ServiceModel.DiagnosticUtility.ExceptionUtility.TraceHandledException(exception2, TraceEventType.Information); } if (isFault) { info.parsingException = exception2; return(info); } FaultConverter defaultFaultConverter = channel.GetProperty <FaultConverter>(); if (defaultFaultConverter == null) { defaultFaultConverter = FaultConverter.GetDefaultFaultConverter(messageVersion); } if (defaultFaultConverter.TryCreateFaultMessage(exception2, out info.faultReply)) { info.faultException = new ProtocolException(System.ServiceModel.SR.GetString("MessageExceptionOccurred"), exception2); return(info); } info.parsingException = new ProtocolException(System.ServiceModel.SR.GetString("MessageExceptionOccurred"), exception2); } catch (XmlException exception3) { if (System.ServiceModel.DiagnosticUtility.ShouldTraceInformation) { System.ServiceModel.DiagnosticUtility.ExceptionUtility.TraceHandledException(exception3, TraceEventType.Information); } info.parsingException = new ProtocolException(System.ServiceModel.SR.GetString("MessageExceptionOccurred"), exception3); } return(info); }