e79aa3c0ed
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
1845 lines
65 KiB
C#
1845 lines
65 KiB
C#
//----------------------------------------------------------------------------
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//----------------------------------------------------------------------------
|
|
namespace System.ServiceModel.Channels
|
|
{
|
|
using System;
|
|
using System.Collections.ObjectModel;
|
|
using System.Diagnostics;
|
|
using System.Runtime;
|
|
using System.Runtime.Serialization;
|
|
using System.ServiceModel;
|
|
using System.ServiceModel.Security;
|
|
using System.Xml;
|
|
|
|
sealed class WsrmMessageInfo
|
|
{
|
|
WsrmAcknowledgmentInfo acknowledgementInfo;
|
|
WsrmAckRequestedInfo ackRequestedInfo;
|
|
string action;
|
|
CloseSequenceInfo closeSequenceInfo;
|
|
CloseSequenceResponseInfo closeSequenceResponseInfo;
|
|
CreateSequenceInfo createSequenceInfo;
|
|
CreateSequenceResponseInfo createSequenceResponseInfo;
|
|
Exception faultException;
|
|
MessageFault faultInfo;
|
|
Message faultReply;
|
|
Message message;
|
|
Exception parsingException;
|
|
WsrmSequencedMessageInfo sequencedMessageInfo;
|
|
TerminateSequenceInfo terminateSequenceInfo;
|
|
TerminateSequenceResponseInfo terminateSequenceResponseInfo;
|
|
WsrmUsesSequenceSSLInfo usesSequenceSSLInfo;
|
|
WsrmUsesSequenceSTRInfo usesSequenceSTRInfo;
|
|
|
|
public WsrmMessageInfo()
|
|
{
|
|
}
|
|
|
|
public WsrmAcknowledgmentInfo AcknowledgementInfo
|
|
{
|
|
get
|
|
{
|
|
return acknowledgementInfo;
|
|
}
|
|
}
|
|
|
|
public WsrmAckRequestedInfo AckRequestedInfo
|
|
{
|
|
get
|
|
{
|
|
return this.ackRequestedInfo;
|
|
}
|
|
}
|
|
|
|
public string Action
|
|
{
|
|
get
|
|
{
|
|
return this.action;
|
|
}
|
|
}
|
|
|
|
public CloseSequenceInfo CloseSequenceInfo
|
|
{
|
|
get
|
|
{
|
|
return this.closeSequenceInfo;
|
|
}
|
|
}
|
|
|
|
public CloseSequenceResponseInfo CloseSequenceResponseInfo
|
|
{
|
|
get
|
|
{
|
|
return this.closeSequenceResponseInfo;
|
|
}
|
|
}
|
|
|
|
public CreateSequenceInfo CreateSequenceInfo
|
|
{
|
|
get
|
|
{
|
|
return this.createSequenceInfo;
|
|
}
|
|
}
|
|
|
|
public CreateSequenceResponseInfo CreateSequenceResponseInfo
|
|
{
|
|
get
|
|
{
|
|
return this.createSequenceResponseInfo;
|
|
}
|
|
}
|
|
|
|
public Exception FaultException
|
|
{
|
|
get
|
|
{
|
|
return this.faultException;
|
|
}
|
|
set
|
|
{
|
|
if (this.faultException != null)
|
|
{
|
|
throw Fx.AssertAndThrow("FaultException can only be set once.");
|
|
}
|
|
|
|
this.faultException = value;
|
|
}
|
|
}
|
|
|
|
public MessageFault FaultInfo
|
|
{
|
|
get
|
|
{
|
|
return this.faultInfo;
|
|
}
|
|
}
|
|
|
|
public Message FaultReply
|
|
{
|
|
get
|
|
{
|
|
return this.faultReply;
|
|
}
|
|
set
|
|
{
|
|
if (this.faultReply != null)
|
|
{
|
|
throw Fx.AssertAndThrow("FaultReply can only be set once.");
|
|
}
|
|
|
|
this.faultReply = value;
|
|
}
|
|
}
|
|
|
|
public Message Message
|
|
{
|
|
get
|
|
{
|
|
return this.message;
|
|
}
|
|
}
|
|
|
|
public MessageFault MessageFault
|
|
{
|
|
get
|
|
{
|
|
return this.faultInfo;
|
|
}
|
|
}
|
|
|
|
public Exception ParsingException
|
|
{
|
|
get
|
|
{
|
|
return this.parsingException;
|
|
}
|
|
}
|
|
|
|
public WsrmSequencedMessageInfo SequencedMessageInfo
|
|
{
|
|
get
|
|
{
|
|
return sequencedMessageInfo;
|
|
}
|
|
}
|
|
|
|
public TerminateSequenceInfo TerminateSequenceInfo
|
|
{
|
|
get
|
|
{
|
|
return terminateSequenceInfo;
|
|
}
|
|
}
|
|
|
|
public TerminateSequenceResponseInfo TerminateSequenceResponseInfo
|
|
{
|
|
get
|
|
{
|
|
return terminateSequenceResponseInfo;
|
|
}
|
|
}
|
|
|
|
public WsrmUsesSequenceSSLInfo UsesSequenceSSLInfo
|
|
{
|
|
get
|
|
{
|
|
return usesSequenceSSLInfo;
|
|
}
|
|
}
|
|
|
|
public WsrmUsesSequenceSTRInfo UsesSequenceSTRInfo
|
|
{
|
|
get
|
|
{
|
|
return usesSequenceSTRInfo;
|
|
}
|
|
}
|
|
|
|
public WsrmHeaderFault WsrmHeaderFault
|
|
{
|
|
get
|
|
{
|
|
return this.faultInfo as WsrmHeaderFault;
|
|
}
|
|
}
|
|
|
|
public static Exception CreateInternalFaultException(Message faultReply, string message, Exception inner)
|
|
{
|
|
return new InternalFaultException(faultReply, SR.GetString(SR.WsrmMessageProcessingError, message), inner);
|
|
}
|
|
|
|
static Exception CreateWsrmRequiredException(MessageVersion messageVersion)
|
|
{
|
|
string exceptionReason = SR.GetString(SR.WsrmRequiredExceptionString);
|
|
string faultReason = SR.GetString(SR.WsrmRequiredFaultString);
|
|
Message faultReply = new WsrmRequiredFault(faultReason).CreateMessage(messageVersion,
|
|
ReliableMessagingVersion.WSReliableMessaging11);
|
|
return CreateInternalFaultException(faultReply, exceptionReason, new ProtocolException(exceptionReason));
|
|
}
|
|
|
|
// Caller should check these things:
|
|
// FaultReply and FaultException, FaultInfo and FaultException or ParsingException
|
|
public static WsrmMessageInfo Get(MessageVersion messageVersion,
|
|
ReliableMessagingVersion reliableMessagingVersion, IChannel channel, ISession session, Message message)
|
|
{
|
|
return Get(messageVersion, reliableMessagingVersion, channel, session, message, false);
|
|
}
|
|
|
|
public static WsrmMessageInfo Get(MessageVersion messageVersion,
|
|
ReliableMessagingVersion reliableMessagingVersion, IChannel channel, ISession session, Message message,
|
|
bool csrOnly)
|
|
{
|
|
WsrmMessageInfo messageInfo = new WsrmMessageInfo();
|
|
messageInfo.message = message;
|
|
bool isFault = true;
|
|
|
|
try
|
|
{
|
|
isFault = message.IsFault;
|
|
MessageHeaders headers = message.Headers;
|
|
string action = headers.Action;
|
|
messageInfo.action = action;
|
|
bool foundAction = false;
|
|
bool wsrmFeb2005 = reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessagingFebruary2005;
|
|
bool wsrm11 = reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessaging11;
|
|
bool csOnly = false;
|
|
|
|
if (action == WsrmIndex.GetCreateSequenceResponseActionString(reliableMessagingVersion))
|
|
{
|
|
messageInfo.createSequenceResponseInfo = CreateSequenceResponseInfo.ReadMessage(messageVersion,
|
|
reliableMessagingVersion, message, headers);
|
|
ValidateMustUnderstand(messageVersion, message);
|
|
return messageInfo;
|
|
}
|
|
|
|
if (csrOnly)
|
|
return messageInfo;
|
|
|
|
if (action == WsrmIndex.GetTerminateSequenceActionString(reliableMessagingVersion))
|
|
{
|
|
messageInfo.terminateSequenceInfo = TerminateSequenceInfo.ReadMessage(messageVersion,
|
|
reliableMessagingVersion, message, headers);
|
|
foundAction = true;
|
|
}
|
|
else if (action == WsrmIndex.GetCreateSequenceActionString(reliableMessagingVersion))
|
|
{
|
|
messageInfo.createSequenceInfo = CreateSequenceInfo.ReadMessage(messageVersion,
|
|
reliableMessagingVersion, session as ISecureConversationSession, message, headers);
|
|
|
|
if (wsrmFeb2005)
|
|
{
|
|
ValidateMustUnderstand(messageVersion, message);
|
|
return messageInfo;
|
|
}
|
|
|
|
csOnly = true;
|
|
}
|
|
else if (wsrm11)
|
|
{
|
|
if (action == Wsrm11Strings.CloseSequenceAction)
|
|
{
|
|
messageInfo.closeSequenceInfo = CloseSequenceInfo.ReadMessage(messageVersion, message,
|
|
headers);
|
|
foundAction = true;
|
|
}
|
|
else if (action == Wsrm11Strings.CloseSequenceResponseAction)
|
|
{
|
|
messageInfo.closeSequenceResponseInfo = CloseSequenceResponseInfo.ReadMessage(messageVersion,
|
|
message, headers);
|
|
foundAction = true;
|
|
}
|
|
else if (action == WsrmIndex.GetTerminateSequenceResponseActionString(reliableMessagingVersion))
|
|
{
|
|
messageInfo.terminateSequenceResponseInfo = TerminateSequenceResponseInfo.ReadMessage(messageVersion,
|
|
message, headers);
|
|
foundAction = true;
|
|
}
|
|
}
|
|
|
|
string wsrmNs = WsrmIndex.GetNamespaceString(reliableMessagingVersion);
|
|
bool soap11 = messageVersion.Envelope == EnvelopeVersion.Soap11;
|
|
bool foundHeader = false;
|
|
int foundTooManyIndex = -1;
|
|
int sequenceIndex = -1;
|
|
int ackIndex = -1;
|
|
int ackRequestedIndex = -1;
|
|
int maxIndex = -1;
|
|
int minIndex = -1;
|
|
int sequenceFaultIndex = -1;
|
|
int usesSequenceSSLIndex = -1;
|
|
int usesSequenceSTRIndex = -1;
|
|
|
|
for (int index = 0; index < headers.Count; index++)
|
|
{
|
|
MessageHeaderInfo header = headers[index];
|
|
|
|
if (!messageVersion.Envelope.IsUltimateDestinationActor(header.Actor))
|
|
continue;
|
|
|
|
if (header.Namespace == wsrmNs)
|
|
{
|
|
bool setIndex = true;
|
|
|
|
if (csOnly)
|
|
{
|
|
if (wsrm11 && (header.Name == Wsrm11Strings.UsesSequenceSSL))
|
|
{
|
|
if (usesSequenceSSLIndex != -1)
|
|
{
|
|
foundTooManyIndex = index;
|
|
break;
|
|
}
|
|
usesSequenceSSLIndex = index;
|
|
}
|
|
else if (wsrm11 && (header.Name == Wsrm11Strings.UsesSequenceSTR))
|
|
{
|
|
if (usesSequenceSTRIndex != -1)
|
|
{
|
|
foundTooManyIndex = index;
|
|
break;
|
|
}
|
|
usesSequenceSTRIndex = index;
|
|
}
|
|
else
|
|
{
|
|
setIndex = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (header.Name == WsrmFeb2005Strings.Sequence)
|
|
{
|
|
if (sequenceIndex != -1)
|
|
{
|
|
foundTooManyIndex = index;
|
|
break;
|
|
}
|
|
sequenceIndex = index;
|
|
}
|
|
else if (header.Name == WsrmFeb2005Strings.SequenceAcknowledgement)
|
|
{
|
|
if (ackIndex != -1)
|
|
{
|
|
foundTooManyIndex = index;
|
|
break;
|
|
}
|
|
ackIndex = index;
|
|
}
|
|
else if (header.Name == WsrmFeb2005Strings.AckRequested)
|
|
{
|
|
if (ackRequestedIndex != -1)
|
|
{
|
|
foundTooManyIndex = index;
|
|
break;
|
|
}
|
|
ackRequestedIndex = index;
|
|
}
|
|
else if (soap11 && (header.Name == WsrmFeb2005Strings.SequenceFault))
|
|
{
|
|
if (sequenceFaultIndex != -1)
|
|
{
|
|
foundTooManyIndex = index;
|
|
break;
|
|
}
|
|
sequenceFaultIndex = index;
|
|
}
|
|
else
|
|
{
|
|
setIndex = false;
|
|
}
|
|
}
|
|
|
|
if (setIndex)
|
|
{
|
|
if (index > maxIndex)
|
|
maxIndex = index;
|
|
|
|
if (minIndex == -1)
|
|
minIndex = index;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (foundTooManyIndex != -1)
|
|
{
|
|
Collection<MessageHeaderInfo> notUnderstoodHeaders = new Collection<MessageHeaderInfo>();
|
|
notUnderstoodHeaders.Add(headers[foundTooManyIndex]);
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
|
new MustUnderstandSoapException(notUnderstoodHeaders, messageVersion.Envelope));
|
|
}
|
|
|
|
if (maxIndex > -1)
|
|
{
|
|
BufferedMessage bufferedMessage = message as BufferedMessage;
|
|
|
|
if (bufferedMessage != null && bufferedMessage.Headers.ContainsOnlyBufferedMessageHeaders)
|
|
{
|
|
foundHeader = true;
|
|
|
|
using (XmlDictionaryReader reader = headers.GetReaderAtHeader(minIndex))
|
|
{
|
|
for (int index = minIndex; index <= maxIndex; index++)
|
|
{
|
|
MessageHeaderInfo header = headers[index];
|
|
|
|
if (csOnly)
|
|
{
|
|
if (wsrm11 && (index == usesSequenceSSLIndex))
|
|
{
|
|
messageInfo.usesSequenceSSLInfo = WsrmUsesSequenceSSLInfo.ReadHeader(
|
|
reader, header);
|
|
headers.UnderstoodHeaders.Add(header);
|
|
}
|
|
else if (wsrm11 && (index == usesSequenceSTRIndex))
|
|
{
|
|
messageInfo.usesSequenceSTRInfo = WsrmUsesSequenceSTRInfo.ReadHeader(
|
|
reader, header);
|
|
headers.UnderstoodHeaders.Add(header);
|
|
}
|
|
else
|
|
{
|
|
reader.Skip();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (index == sequenceIndex)
|
|
{
|
|
messageInfo.sequencedMessageInfo = WsrmSequencedMessageInfo.ReadHeader(
|
|
reliableMessagingVersion, reader, header);
|
|
headers.UnderstoodHeaders.Add(header);
|
|
}
|
|
else if (index == ackIndex)
|
|
{
|
|
messageInfo.acknowledgementInfo = WsrmAcknowledgmentInfo.ReadHeader(
|
|
reliableMessagingVersion, reader, header);
|
|
headers.UnderstoodHeaders.Add(header);
|
|
}
|
|
else if (index == ackRequestedIndex)
|
|
{
|
|
messageInfo.ackRequestedInfo = WsrmAckRequestedInfo.ReadHeader(
|
|
reliableMessagingVersion, reader, header);
|
|
headers.UnderstoodHeaders.Add(header);
|
|
}
|
|
else
|
|
{
|
|
reader.Skip();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (maxIndex > -1 && !foundHeader)
|
|
{
|
|
foundHeader = true;
|
|
|
|
if (csOnly)
|
|
{
|
|
if (usesSequenceSSLIndex != -1)
|
|
{
|
|
using (XmlDictionaryReader reader = headers.GetReaderAtHeader(usesSequenceSSLIndex))
|
|
{
|
|
MessageHeaderInfo header = headers[usesSequenceSSLIndex];
|
|
messageInfo.usesSequenceSSLInfo = WsrmUsesSequenceSSLInfo.ReadHeader(
|
|
reader, header);
|
|
headers.UnderstoodHeaders.Add(header);
|
|
}
|
|
}
|
|
|
|
if (usesSequenceSTRIndex != -1)
|
|
{
|
|
using (XmlDictionaryReader reader = headers.GetReaderAtHeader(usesSequenceSTRIndex))
|
|
{
|
|
MessageHeaderInfo header = headers[usesSequenceSTRIndex];
|
|
messageInfo.usesSequenceSTRInfo = WsrmUsesSequenceSTRInfo.ReadHeader(
|
|
reader, header);
|
|
headers.UnderstoodHeaders.Add(header);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (sequenceIndex != -1)
|
|
{
|
|
using (XmlDictionaryReader reader = headers.GetReaderAtHeader(sequenceIndex))
|
|
{
|
|
MessageHeaderInfo header = headers[sequenceIndex];
|
|
|
|
messageInfo.sequencedMessageInfo = WsrmSequencedMessageInfo.ReadHeader(
|
|
reliableMessagingVersion, reader, header);
|
|
headers.UnderstoodHeaders.Add(header);
|
|
}
|
|
}
|
|
|
|
if (ackIndex != -1)
|
|
{
|
|
using (XmlDictionaryReader reader = headers.GetReaderAtHeader(ackIndex))
|
|
{
|
|
MessageHeaderInfo header = headers[ackIndex];
|
|
messageInfo.acknowledgementInfo = WsrmAcknowledgmentInfo.ReadHeader(
|
|
reliableMessagingVersion, reader, header);
|
|
headers.UnderstoodHeaders.Add(header);
|
|
}
|
|
}
|
|
|
|
if (ackRequestedIndex != -1)
|
|
{
|
|
using (XmlDictionaryReader reader = headers.GetReaderAtHeader(ackRequestedIndex))
|
|
{
|
|
MessageHeaderInfo header = headers[ackRequestedIndex];
|
|
messageInfo.ackRequestedInfo = WsrmAckRequestedInfo.ReadHeader(reliableMessagingVersion,
|
|
reader, header);
|
|
headers.UnderstoodHeaders.Add(header);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (csOnly)
|
|
{
|
|
CreateSequenceInfo.ValidateCreateSequenceHeaders(messageVersion,
|
|
session as ISecureConversationSession, messageInfo);
|
|
ValidateMustUnderstand(messageVersion, message);
|
|
return messageInfo;
|
|
}
|
|
|
|
if (messageInfo.sequencedMessageInfo == null && messageInfo.action == null)
|
|
{
|
|
if (wsrmFeb2005)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageHeaderException(SR.GetString(SR.NoActionNoSequenceHeaderReason), messageVersion.Addressing.Namespace, AddressingStrings.Action, false));
|
|
}
|
|
else
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
|
CreateWsrmRequiredException(messageVersion));
|
|
}
|
|
}
|
|
|
|
if (messageInfo.sequencedMessageInfo == null && message.IsFault)
|
|
{
|
|
messageInfo.faultInfo = MessageFault.CreateFault(message, TransportDefaults.MaxRMFaultSize);
|
|
WsrmHeaderFault wsrmFault;
|
|
|
|
if (soap11)
|
|
{
|
|
if (WsrmHeaderFault.TryCreateFault11(reliableMessagingVersion, message, messageInfo.faultInfo, sequenceFaultIndex, out wsrmFault))
|
|
{
|
|
messageInfo.faultInfo = wsrmFault;
|
|
messageInfo.faultException = WsrmHeaderFault.CreateException(wsrmFault);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (WsrmHeaderFault.TryCreateFault12(reliableMessagingVersion, message, messageInfo.faultInfo, out wsrmFault))
|
|
{
|
|
messageInfo.faultInfo = wsrmFault;
|
|
messageInfo.faultException = WsrmHeaderFault.CreateException(wsrmFault);
|
|
}
|
|
}
|
|
|
|
// Not a wsrm fault, maybe it is another fault we should understand (i.e. addressing or soap fault).
|
|
if (wsrmFault == null)
|
|
{
|
|
FaultConverter faultConverter = channel.GetProperty<FaultConverter>();
|
|
|
|
if (faultConverter == null)
|
|
{
|
|
faultConverter = FaultConverter.GetDefaultFaultConverter(messageVersion);
|
|
}
|
|
|
|
if (!faultConverter.TryCreateException(message, messageInfo.faultInfo, out messageInfo.faultException))
|
|
{
|
|
messageInfo.faultException = new ProtocolException(SR.GetString(SR.UnrecognizedFaultReceived, messageInfo.faultInfo.Code.Namespace, messageInfo.faultInfo.Code.Name, System.ServiceModel.FaultException.GetSafeReasonText(messageInfo.faultInfo)));
|
|
}
|
|
}
|
|
|
|
foundAction = true;
|
|
}
|
|
|
|
if (!foundHeader && !foundAction)
|
|
{
|
|
if (wsrmFeb2005)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
|
new ActionNotSupportedException(SR.GetString(SR.NonWsrmFeb2005ActionNotSupported, action)));
|
|
}
|
|
else
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
|
CreateWsrmRequiredException(messageVersion));
|
|
}
|
|
}
|
|
|
|
if (foundAction || WsrmUtilities.IsWsrmAction(reliableMessagingVersion, action))
|
|
{
|
|
ValidateMustUnderstand(messageVersion, message);
|
|
}
|
|
}
|
|
catch (InternalFaultException exception)
|
|
{
|
|
if (DiagnosticUtility.ShouldTraceInformation)
|
|
DiagnosticUtility.TraceHandledException(exception, TraceEventType.Information);
|
|
|
|
messageInfo.FaultReply = exception.FaultReply;
|
|
messageInfo.faultException = exception.InnerException;
|
|
}
|
|
catch (CommunicationException exception)
|
|
{
|
|
if (DiagnosticUtility.ShouldTraceInformation)
|
|
DiagnosticUtility.TraceHandledException(exception, TraceEventType.Information);
|
|
|
|
if (isFault)
|
|
{
|
|
messageInfo.parsingException = exception;
|
|
return messageInfo;
|
|
}
|
|
|
|
FaultConverter faultConverter = channel.GetProperty<FaultConverter>();
|
|
if (faultConverter == null)
|
|
faultConverter = FaultConverter.GetDefaultFaultConverter(messageVersion);
|
|
|
|
if (faultConverter.TryCreateFaultMessage(exception, out messageInfo.faultReply))
|
|
{
|
|
messageInfo.faultException = new ProtocolException(SR.GetString(SR.MessageExceptionOccurred), exception);
|
|
}
|
|
else
|
|
{
|
|
messageInfo.parsingException = new ProtocolException(SR.GetString(SR.MessageExceptionOccurred), exception);
|
|
}
|
|
}
|
|
catch (XmlException exception)
|
|
{
|
|
if (DiagnosticUtility.ShouldTraceInformation)
|
|
DiagnosticUtility.TraceHandledException(exception, TraceEventType.Information);
|
|
|
|
messageInfo.parsingException = new ProtocolException(SR.GetString(SR.MessageExceptionOccurred), exception);
|
|
}
|
|
|
|
return messageInfo;
|
|
}
|
|
|
|
static void ValidateMustUnderstand(MessageVersion version, Message message)
|
|
{
|
|
Collection<MessageHeaderInfo> notUnderstoodHeaders = message.Headers.GetHeadersNotUnderstood();
|
|
if ((notUnderstoodHeaders != null) && (notUnderstoodHeaders.Count > 0))
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
|
new MustUnderstandSoapException(notUnderstoodHeaders, version.Envelope));
|
|
}
|
|
}
|
|
|
|
[Serializable]
|
|
class InternalFaultException : ProtocolException
|
|
{
|
|
Message faultReply;
|
|
|
|
public InternalFaultException()
|
|
: base()
|
|
{
|
|
}
|
|
|
|
public InternalFaultException(Message faultReply, string message, Exception inner)
|
|
: base(message, inner)
|
|
{
|
|
this.faultReply = faultReply;
|
|
}
|
|
|
|
protected InternalFaultException(SerializationInfo info, StreamingContext context)
|
|
: base(info, context)
|
|
{
|
|
}
|
|
|
|
public Message FaultReply
|
|
{
|
|
get
|
|
{
|
|
return this.faultReply;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
sealed class CloseSequenceInfo : WsrmRequestInfo
|
|
{
|
|
UniqueId identifier;
|
|
Int64 lastMsgNumber;
|
|
|
|
public UniqueId Identifier
|
|
{
|
|
get
|
|
{
|
|
return this.identifier;
|
|
}
|
|
set
|
|
{
|
|
this.identifier = value;
|
|
}
|
|
}
|
|
|
|
public Int64 LastMsgNumber
|
|
{
|
|
get
|
|
{
|
|
return this.lastMsgNumber;
|
|
}
|
|
set
|
|
{
|
|
this.lastMsgNumber = value;
|
|
}
|
|
}
|
|
|
|
public override string RequestName
|
|
{
|
|
get
|
|
{
|
|
return Wsrm11Strings.CloseSequence;
|
|
}
|
|
}
|
|
|
|
public static CloseSequenceInfo ReadMessage(MessageVersion messageVersion, Message message,
|
|
MessageHeaders headers)
|
|
{
|
|
if (message.IsEmpty)
|
|
{
|
|
string reason = SR.GetString(SR.NonEmptyWsrmMessageIsEmpty, Wsrm11Strings.CloseSequenceAction);
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(reason));
|
|
}
|
|
|
|
CloseSequenceInfo info;
|
|
using (XmlDictionaryReader reader = message.GetReaderAtBodyContents())
|
|
{
|
|
info = CloseSequence.Create(reader);
|
|
message.ReadFromBodyContentsToEnd(reader);
|
|
}
|
|
|
|
info.SetMessageId(messageVersion, headers);
|
|
info.SetReplyTo(messageVersion, headers);
|
|
|
|
return info;
|
|
}
|
|
}
|
|
|
|
sealed class CloseSequenceResponseInfo
|
|
{
|
|
UniqueId identifier;
|
|
UniqueId relatesTo;
|
|
|
|
public UniqueId Identifier
|
|
{
|
|
get
|
|
{
|
|
return this.identifier;
|
|
}
|
|
set
|
|
{
|
|
this.identifier = value;
|
|
}
|
|
}
|
|
|
|
public UniqueId RelatesTo
|
|
{
|
|
get
|
|
{
|
|
return this.relatesTo;
|
|
}
|
|
set
|
|
{
|
|
this.relatesTo = value;
|
|
}
|
|
}
|
|
|
|
public static CloseSequenceResponseInfo ReadMessage(MessageVersion messageVersion, Message message,
|
|
MessageHeaders headers)
|
|
{
|
|
if (headers.RelatesTo == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
|
new MessageHeaderException(SR.GetString(SR.MissingRelatesToOnWsrmResponseReason,
|
|
DXD.Wsrm11Dictionary.CloseSequenceResponse), messageVersion.Addressing.Namespace,
|
|
AddressingStrings.RelatesTo, false));
|
|
}
|
|
|
|
if (message.IsEmpty)
|
|
{
|
|
string reason = SR.GetString(SR.NonEmptyWsrmMessageIsEmpty,
|
|
Wsrm11Strings.CloseSequenceResponseAction);
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(reason));
|
|
}
|
|
|
|
CloseSequenceResponseInfo info;
|
|
using (XmlDictionaryReader reader = message.GetReaderAtBodyContents())
|
|
{
|
|
info = CloseSequenceResponse.Create(reader);
|
|
message.ReadFromBodyContentsToEnd(reader);
|
|
}
|
|
|
|
info.relatesTo = headers.RelatesTo;
|
|
return info;
|
|
}
|
|
}
|
|
|
|
sealed class CreateSequenceInfo : WsrmRequestInfo
|
|
{
|
|
EndpointAddress acksTo = EndpointAddress.AnonymousAddress;
|
|
Nullable<TimeSpan> expires;
|
|
Nullable<TimeSpan> offerExpires;
|
|
UniqueId offerIdentifier;
|
|
Uri to;
|
|
|
|
public EndpointAddress AcksTo
|
|
{
|
|
get
|
|
{
|
|
return this.acksTo;
|
|
}
|
|
set
|
|
{
|
|
this.acksTo = value;
|
|
}
|
|
}
|
|
|
|
public Nullable<TimeSpan> Expires
|
|
{
|
|
get
|
|
{
|
|
return this.expires;
|
|
}
|
|
set
|
|
{
|
|
this.expires = value;
|
|
}
|
|
}
|
|
|
|
public Nullable<TimeSpan> OfferExpires
|
|
{
|
|
get
|
|
{
|
|
return this.offerExpires;
|
|
}
|
|
set
|
|
{
|
|
this.offerExpires = value;
|
|
}
|
|
}
|
|
|
|
public UniqueId OfferIdentifier
|
|
{
|
|
get
|
|
{
|
|
return this.offerIdentifier;
|
|
}
|
|
set
|
|
{
|
|
this.offerIdentifier = value;
|
|
}
|
|
}
|
|
|
|
public override string RequestName
|
|
{
|
|
get
|
|
{
|
|
return WsrmFeb2005Strings.CreateSequence;
|
|
}
|
|
}
|
|
|
|
public Uri To
|
|
{
|
|
get
|
|
{
|
|
return this.to;
|
|
}
|
|
}
|
|
|
|
public static CreateSequenceInfo ReadMessage(MessageVersion messageVersion,
|
|
ReliableMessagingVersion reliableMessagingVersion, ISecureConversationSession securitySession,
|
|
Message message, MessageHeaders headers)
|
|
{
|
|
if (message.IsEmpty)
|
|
{
|
|
string reason = SR.GetString(SR.NonEmptyWsrmMessageIsEmpty,
|
|
WsrmIndex.GetCreateSequenceActionString(reliableMessagingVersion));
|
|
Message faultReply = WsrmUtilities.CreateCSRefusedProtocolFault(messageVersion, reliableMessagingVersion, reason);
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(WsrmMessageInfo.CreateInternalFaultException(faultReply, reason, new ProtocolException(reason)));
|
|
}
|
|
|
|
CreateSequenceInfo info;
|
|
using (XmlDictionaryReader reader = message.GetReaderAtBodyContents())
|
|
{
|
|
info = CreateSequence.Create(messageVersion, reliableMessagingVersion, securitySession, reader);
|
|
message.ReadFromBodyContentsToEnd(reader);
|
|
}
|
|
|
|
info.SetMessageId(messageVersion, headers);
|
|
info.SetReplyTo(messageVersion, headers);
|
|
|
|
if (info.AcksTo.Uri != info.ReplyTo.Uri)
|
|
{
|
|
string reason = SR.GetString(SR.CSRefusedAcksToMustEqualReplyTo);
|
|
Message faultReply = WsrmUtilities.CreateCSRefusedProtocolFault(messageVersion, reliableMessagingVersion, reason);
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(WsrmMessageInfo.CreateInternalFaultException(faultReply, reason, new ProtocolException(reason)));
|
|
}
|
|
|
|
info.to = message.Headers.To;
|
|
if (info.to == null && messageVersion.Addressing == AddressingVersion.WSAddressing10)
|
|
info.to = messageVersion.Addressing.AnonymousUri;
|
|
|
|
return info;
|
|
}
|
|
|
|
public static void ValidateCreateSequenceHeaders(MessageVersion messageVersion,
|
|
ISecureConversationSession securitySession, WsrmMessageInfo info)
|
|
{
|
|
string reason = null;
|
|
|
|
if (info.UsesSequenceSSLInfo != null)
|
|
{
|
|
reason = SR.GetString(SR.CSRefusedSSLNotSupported);
|
|
}
|
|
else if ((info.UsesSequenceSTRInfo != null) && (securitySession == null))
|
|
{
|
|
reason = SR.GetString(SR.CSRefusedSTRNoWSSecurity);
|
|
}
|
|
else if ((info.UsesSequenceSTRInfo == null) && (securitySession != null))
|
|
{
|
|
reason = SR.GetString(SR.CSRefusedNoSTRWSSecurity);
|
|
}
|
|
|
|
if (reason != null)
|
|
{
|
|
Message faultReply = WsrmUtilities.CreateCSRefusedProtocolFault(messageVersion,
|
|
ReliableMessagingVersion.WSReliableMessaging11, reason);
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(WsrmMessageInfo.CreateInternalFaultException(faultReply, reason, new ProtocolException(reason)));
|
|
}
|
|
}
|
|
}
|
|
|
|
sealed class CreateSequenceResponseInfo
|
|
{
|
|
EndpointAddress acceptAcksTo;
|
|
UniqueId identifier;
|
|
UniqueId relatesTo;
|
|
|
|
public EndpointAddress AcceptAcksTo
|
|
{
|
|
get
|
|
{
|
|
return this.acceptAcksTo;
|
|
}
|
|
set
|
|
{
|
|
this.acceptAcksTo = value;
|
|
}
|
|
}
|
|
|
|
public UniqueId Identifier
|
|
{
|
|
get
|
|
{
|
|
return this.identifier;
|
|
}
|
|
set
|
|
{
|
|
this.identifier = value;
|
|
}
|
|
}
|
|
|
|
public UniqueId RelatesTo
|
|
{
|
|
get
|
|
{
|
|
return this.relatesTo;
|
|
}
|
|
set
|
|
{
|
|
this.relatesTo = value;
|
|
}
|
|
}
|
|
|
|
public static CreateSequenceResponseInfo ReadMessage(MessageVersion messageVersion,
|
|
ReliableMessagingVersion reliableMessagingVersion, Message message, MessageHeaders headers)
|
|
{
|
|
if (message.IsEmpty)
|
|
{
|
|
string reason = SR.GetString(SR.NonEmptyWsrmMessageIsEmpty,
|
|
WsrmIndex.GetCreateSequenceResponseActionString(reliableMessagingVersion));
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(reason));
|
|
}
|
|
|
|
if (headers.RelatesTo == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
|
new MessageHeaderException(SR.GetString(SR.MissingRelatesToOnWsrmResponseReason,
|
|
XD.WsrmFeb2005Dictionary.CreateSequenceResponse), messageVersion.Addressing.Namespace,
|
|
AddressingStrings.RelatesTo, false));
|
|
}
|
|
|
|
CreateSequenceResponseInfo info;
|
|
using (XmlDictionaryReader reader = message.GetReaderAtBodyContents())
|
|
{
|
|
info = CreateSequenceResponse.Create(messageVersion.Addressing, reliableMessagingVersion, reader);
|
|
message.ReadFromBodyContentsToEnd(reader);
|
|
}
|
|
|
|
info.RelatesTo = headers.RelatesTo;
|
|
return info;
|
|
}
|
|
}
|
|
|
|
sealed class TerminateSequenceInfo : WsrmRequestInfo
|
|
{
|
|
UniqueId identifier;
|
|
Int64 lastMsgNumber;
|
|
|
|
public UniqueId Identifier
|
|
{
|
|
get
|
|
{
|
|
return this.identifier;
|
|
}
|
|
set
|
|
{
|
|
this.identifier = value;
|
|
}
|
|
}
|
|
|
|
public Int64 LastMsgNumber
|
|
{
|
|
get
|
|
{
|
|
return this.lastMsgNumber;
|
|
}
|
|
set
|
|
{
|
|
this.lastMsgNumber = value;
|
|
}
|
|
}
|
|
|
|
public override string RequestName
|
|
{
|
|
get
|
|
{
|
|
return WsrmFeb2005Strings.TerminateSequence;
|
|
}
|
|
}
|
|
|
|
public static TerminateSequenceInfo ReadMessage(MessageVersion messageVersion,
|
|
ReliableMessagingVersion reliableMessagingVersion, Message message, MessageHeaders headers)
|
|
{
|
|
if (message.IsEmpty)
|
|
{
|
|
string reason = SR.GetString(SR.NonEmptyWsrmMessageIsEmpty,
|
|
WsrmIndex.GetTerminateSequenceActionString(reliableMessagingVersion));
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(reason));
|
|
}
|
|
|
|
TerminateSequenceInfo info;
|
|
using (XmlDictionaryReader reader = message.GetReaderAtBodyContents())
|
|
{
|
|
info = TerminateSequence.Create(reliableMessagingVersion, reader);
|
|
message.ReadFromBodyContentsToEnd(reader);
|
|
}
|
|
|
|
if (reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessaging11)
|
|
{
|
|
info.SetMessageId(messageVersion, headers);
|
|
info.SetReplyTo(messageVersion, headers);
|
|
}
|
|
|
|
return info;
|
|
}
|
|
}
|
|
|
|
sealed class TerminateSequenceResponseInfo
|
|
{
|
|
UniqueId identifier;
|
|
UniqueId relatesTo;
|
|
|
|
public UniqueId Identifier
|
|
{
|
|
get
|
|
{
|
|
return this.identifier;
|
|
}
|
|
set
|
|
{
|
|
this.identifier = value;
|
|
}
|
|
}
|
|
|
|
public UniqueId RelatesTo
|
|
{
|
|
get
|
|
{
|
|
return this.relatesTo;
|
|
}
|
|
set
|
|
{
|
|
this.relatesTo = value;
|
|
}
|
|
}
|
|
|
|
public static TerminateSequenceResponseInfo ReadMessage(MessageVersion messageVersion, Message message,
|
|
MessageHeaders headers)
|
|
{
|
|
if (headers.RelatesTo == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
|
new MessageHeaderException(SR.GetString(SR.MissingRelatesToOnWsrmResponseReason,
|
|
DXD.Wsrm11Dictionary.TerminateSequenceResponse), messageVersion.Addressing.Namespace,
|
|
AddressingStrings.RelatesTo, false));
|
|
}
|
|
|
|
if (message.IsEmpty)
|
|
{
|
|
string reason = SR.GetString(SR.NonEmptyWsrmMessageIsEmpty,
|
|
WsrmIndex.GetTerminateSequenceResponseActionString(ReliableMessagingVersion.WSReliableMessaging11));
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(reason));
|
|
}
|
|
|
|
TerminateSequenceResponseInfo info;
|
|
using (XmlDictionaryReader reader = message.GetReaderAtBodyContents())
|
|
{
|
|
info = TerminateSequenceResponse.Create(reader);
|
|
message.ReadFromBodyContentsToEnd(reader);
|
|
}
|
|
|
|
info.relatesTo = headers.RelatesTo;
|
|
return info;
|
|
}
|
|
}
|
|
|
|
internal abstract class WsrmMessageHeader : DictionaryHeader, IMessageHeaderWithSharedNamespace
|
|
{
|
|
ReliableMessagingVersion reliableMessagingVersion;
|
|
|
|
protected WsrmMessageHeader(ReliableMessagingVersion reliableMessagingVersion)
|
|
{
|
|
this.reliableMessagingVersion = reliableMessagingVersion;
|
|
}
|
|
|
|
XmlDictionaryString IMessageHeaderWithSharedNamespace.SharedPrefix
|
|
{
|
|
get { return XD.WsrmFeb2005Dictionary.Prefix; }
|
|
}
|
|
|
|
XmlDictionaryString IMessageHeaderWithSharedNamespace.SharedNamespace
|
|
{
|
|
get { return WsrmIndex.GetNamespace(this.reliableMessagingVersion); }
|
|
}
|
|
|
|
public override XmlDictionaryString DictionaryNamespace
|
|
{
|
|
get { return WsrmIndex.GetNamespace(this.reliableMessagingVersion); }
|
|
}
|
|
|
|
public override string Namespace
|
|
{
|
|
get { return WsrmIndex.GetNamespaceString(this.reliableMessagingVersion); }
|
|
}
|
|
|
|
protected ReliableMessagingVersion ReliableMessagingVersion
|
|
{
|
|
get { return this.reliableMessagingVersion; }
|
|
}
|
|
}
|
|
|
|
abstract class WsrmHeaderInfo
|
|
{
|
|
MessageHeaderInfo messageHeader;
|
|
|
|
protected WsrmHeaderInfo(MessageHeaderInfo messageHeader)
|
|
{
|
|
this.messageHeader = messageHeader;
|
|
}
|
|
|
|
public MessageHeaderInfo MessageHeader
|
|
{
|
|
get
|
|
{
|
|
return messageHeader;
|
|
}
|
|
}
|
|
}
|
|
|
|
abstract class WsrmRequestInfo
|
|
{
|
|
UniqueId messageId;
|
|
EndpointAddress replyTo;
|
|
|
|
protected WsrmRequestInfo()
|
|
{
|
|
}
|
|
|
|
public UniqueId MessageId
|
|
{
|
|
get
|
|
{
|
|
return this.messageId;
|
|
}
|
|
}
|
|
|
|
public EndpointAddress ReplyTo
|
|
{
|
|
get
|
|
{
|
|
return this.replyTo;
|
|
}
|
|
}
|
|
|
|
public abstract string RequestName
|
|
{
|
|
get;
|
|
}
|
|
|
|
protected void SetMessageId(MessageVersion messageVersion, MessageHeaders headers)
|
|
{
|
|
this.messageId = headers.MessageId;
|
|
|
|
if (this.messageId == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageHeaderException(
|
|
SR.GetString(SR.MissingMessageIdOnWsrmRequest, RequestName),
|
|
messageVersion.Addressing.Namespace,
|
|
AddressingStrings.MessageId,
|
|
false));
|
|
}
|
|
}
|
|
|
|
protected void SetReplyTo(MessageVersion messageVersion, MessageHeaders headers)
|
|
{
|
|
this.replyTo = headers.ReplyTo;
|
|
|
|
if (messageVersion.Addressing == AddressingVersion.WSAddressing10 && this.replyTo == null)
|
|
{
|
|
this.replyTo = EndpointAddress.AnonymousAddress;
|
|
}
|
|
|
|
if (this.replyTo == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageHeaderException(
|
|
SR.GetString(SR.MissingReplyToOnWsrmRequest, RequestName),
|
|
messageVersion.Addressing.Namespace,
|
|
AddressingStrings.ReplyTo,
|
|
false));
|
|
}
|
|
}
|
|
}
|
|
|
|
internal sealed class WsrmSequencedMessageInfo : WsrmHeaderInfo
|
|
{
|
|
UniqueId sequenceID;
|
|
Int64 sequenceNumber;
|
|
bool lastMessage;
|
|
|
|
WsrmSequencedMessageInfo(
|
|
UniqueId sequenceID,
|
|
Int64 sequenceNumber,
|
|
bool lastMessage,
|
|
MessageHeaderInfo header)
|
|
: base(header)
|
|
{
|
|
this.sequenceID = sequenceID;
|
|
this.sequenceNumber = sequenceNumber;
|
|
this.lastMessage = lastMessage;
|
|
}
|
|
|
|
public UniqueId SequenceID
|
|
{
|
|
get
|
|
{
|
|
return sequenceID;
|
|
}
|
|
}
|
|
|
|
public Int64 SequenceNumber
|
|
{
|
|
get
|
|
{
|
|
return sequenceNumber;
|
|
}
|
|
}
|
|
|
|
public bool LastMessage
|
|
{
|
|
get
|
|
{
|
|
return lastMessage;
|
|
}
|
|
}
|
|
|
|
public static WsrmSequencedMessageInfo ReadHeader(ReliableMessagingVersion reliableMessagingVersion,
|
|
XmlDictionaryReader reader, MessageHeaderInfo header)
|
|
{
|
|
WsrmFeb2005Dictionary wsrmFeb2005Dictionary = XD.WsrmFeb2005Dictionary;
|
|
XmlDictionaryString wsrmNs = WsrmIndex.GetNamespace(reliableMessagingVersion);
|
|
|
|
reader.ReadStartElement();
|
|
|
|
reader.ReadStartElement(wsrmFeb2005Dictionary.Identifier, wsrmNs);
|
|
UniqueId sequenceID = reader.ReadContentAsUniqueId();
|
|
reader.ReadEndElement();
|
|
|
|
reader.ReadStartElement(wsrmFeb2005Dictionary.MessageNumber, wsrmNs);
|
|
Int64 sequenceNumber = WsrmUtilities.ReadSequenceNumber(reader);
|
|
reader.ReadEndElement();
|
|
|
|
bool lastMessage = false;
|
|
|
|
if (reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessagingFebruary2005)
|
|
{
|
|
if (reader.IsStartElement(wsrmFeb2005Dictionary.LastMessage, wsrmNs))
|
|
{
|
|
WsrmUtilities.ReadEmptyElement(reader);
|
|
lastMessage = true;
|
|
}
|
|
}
|
|
|
|
while (reader.IsStartElement())
|
|
{
|
|
reader.Skip();
|
|
}
|
|
|
|
reader.ReadEndElement();
|
|
|
|
return new WsrmSequencedMessageInfo(sequenceID, sequenceNumber, lastMessage, header);
|
|
}
|
|
}
|
|
|
|
internal sealed class WsrmSequencedMessageHeader : WsrmMessageHeader
|
|
{
|
|
bool lastMessage;
|
|
UniqueId sequenceID;
|
|
Int64 sequenceNumber;
|
|
|
|
public WsrmSequencedMessageHeader(
|
|
ReliableMessagingVersion reliableMessagingVersion,
|
|
UniqueId sequenceID,
|
|
Int64 sequenceNumber,
|
|
bool lastMessage)
|
|
: base(reliableMessagingVersion)
|
|
{
|
|
this.sequenceID = sequenceID;
|
|
this.sequenceNumber = sequenceNumber;
|
|
this.lastMessage = lastMessage;
|
|
}
|
|
|
|
public override XmlDictionaryString DictionaryName
|
|
{
|
|
get { return XD.WsrmFeb2005Dictionary.Sequence; }
|
|
}
|
|
|
|
public override bool MustUnderstand
|
|
{
|
|
get { return true; }
|
|
}
|
|
|
|
protected override void OnWriteHeaderContents(XmlDictionaryWriter writer, MessageVersion messageVersion)
|
|
{
|
|
WsrmFeb2005Dictionary wsrmFeb2005Dictionary = XD.WsrmFeb2005Dictionary;
|
|
XmlDictionaryString wsrmNs = this.DictionaryNamespace;
|
|
|
|
writer.WriteStartElement(wsrmFeb2005Dictionary.Identifier, wsrmNs);
|
|
writer.WriteValue(this.sequenceID);
|
|
writer.WriteEndElement();
|
|
|
|
writer.WriteStartElement(wsrmFeb2005Dictionary.MessageNumber, wsrmNs);
|
|
writer.WriteValue(this.sequenceNumber);
|
|
writer.WriteEndElement();
|
|
|
|
if ((this.ReliableMessagingVersion == ReliableMessagingVersion.WSReliableMessagingFebruary2005)
|
|
&& lastMessage)
|
|
{
|
|
writer.WriteStartElement(wsrmFeb2005Dictionary.LastMessage, wsrmNs);
|
|
writer.WriteEndElement();
|
|
}
|
|
}
|
|
}
|
|
|
|
internal sealed class WsrmAcknowledgmentInfo : WsrmHeaderInfo
|
|
{
|
|
int bufferRemaining;
|
|
bool final;
|
|
SequenceRangeCollection ranges;
|
|
UniqueId sequenceID;
|
|
|
|
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 int BufferRemaining
|
|
{
|
|
get
|
|
{
|
|
return this.bufferRemaining;
|
|
}
|
|
}
|
|
|
|
public bool Final
|
|
{
|
|
get
|
|
{
|
|
return this.final;
|
|
}
|
|
}
|
|
|
|
public SequenceRangeCollection Ranges
|
|
{
|
|
get
|
|
{
|
|
return this.ranges;
|
|
}
|
|
}
|
|
|
|
public UniqueId SequenceID
|
|
{
|
|
get
|
|
{
|
|
return this.sequenceID;
|
|
}
|
|
}
|
|
|
|
// February 2005 - Reads Identifier, AcknowledgementRange, Nack
|
|
// 1.1 - Reads Identifier, AcknowledgementRange, None, Final, Nack
|
|
internal static void ReadAck(ReliableMessagingVersion reliableMessagingVersion,
|
|
XmlDictionaryReader reader, out UniqueId sequenceId, out SequenceRangeCollection rangeCollection,
|
|
out bool final)
|
|
{
|
|
WsrmFeb2005Dictionary wsrmFeb2005Dictionary = XD.WsrmFeb2005Dictionary;
|
|
XmlDictionaryString wsrmNs = WsrmIndex.GetNamespace(reliableMessagingVersion);
|
|
|
|
reader.ReadStartElement(wsrmFeb2005Dictionary.SequenceAcknowledgement, wsrmNs);
|
|
reader.ReadStartElement(wsrmFeb2005Dictionary.Identifier, wsrmNs);
|
|
sequenceId = reader.ReadContentAsUniqueId();
|
|
reader.ReadEndElement();
|
|
bool allowZero = reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessagingFebruary2005;
|
|
|
|
rangeCollection = SequenceRangeCollection.Empty;
|
|
while (reader.IsStartElement(wsrmFeb2005Dictionary.AcknowledgementRange, wsrmNs))
|
|
{
|
|
reader.MoveToAttribute(WsrmFeb2005Strings.Lower);
|
|
Int64 lower = WsrmUtilities.ReadSequenceNumber(reader, allowZero);
|
|
|
|
reader.MoveToAttribute(WsrmFeb2005Strings.Upper);
|
|
Int64 upper = WsrmUtilities.ReadSequenceNumber(reader, allowZero);
|
|
|
|
if (lower < 0 || lower > upper
|
|
|| ((reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessagingFebruary2005) && (lower == 0 && upper > 0))
|
|
|| ((reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessaging11) && (lower == 0)))
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
|
new XmlException(SR.GetString(SR.InvalidSequenceRange, lower, upper)));
|
|
}
|
|
|
|
rangeCollection = rangeCollection.MergeWith(new SequenceRange(lower, upper));
|
|
|
|
reader.MoveToElement();
|
|
|
|
WsrmUtilities.ReadEmptyElement(reader);
|
|
}
|
|
|
|
bool validAck = rangeCollection.Count > 0;
|
|
final = false;
|
|
bool wsrm11 = reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessaging11;
|
|
|
|
if (wsrm11)
|
|
{
|
|
Wsrm11Dictionary wsrm11Dictionary = DXD.Wsrm11Dictionary;
|
|
|
|
if (reader.IsStartElement(wsrm11Dictionary.None, wsrmNs))
|
|
{
|
|
if (validAck)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(
|
|
SR.GetString(SR.UnexpectedXmlChildNode, reader.Name, reader.NodeType,
|
|
wsrmFeb2005Dictionary.SequenceAcknowledgement)));
|
|
}
|
|
|
|
WsrmUtilities.ReadEmptyElement(reader);
|
|
validAck = true;
|
|
}
|
|
|
|
if (reader.IsStartElement(wsrm11Dictionary.Final, wsrmNs))
|
|
{
|
|
if (!validAck)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(
|
|
SR.GetString(SR.UnexpectedXmlChildNode, reader.Name, reader.NodeType,
|
|
wsrmFeb2005Dictionary.SequenceAcknowledgement)));
|
|
}
|
|
|
|
WsrmUtilities.ReadEmptyElement(reader);
|
|
final = true;
|
|
}
|
|
}
|
|
|
|
bool foundNack = false;
|
|
while (reader.IsStartElement(wsrmFeb2005Dictionary.Nack, wsrmNs))
|
|
{
|
|
if (validAck)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(
|
|
SR.GetString(SR.UnexpectedXmlChildNode, reader.Name, reader.NodeType,
|
|
MessageStrings.Body)));
|
|
}
|
|
|
|
reader.ReadStartElement();
|
|
WsrmUtilities.ReadSequenceNumber(reader, true);
|
|
reader.ReadEndElement();
|
|
foundNack = true;
|
|
}
|
|
|
|
if (!validAck && !foundNack)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(
|
|
SR.GetString(SR.UnexpectedXmlChildNode, reader.Name, reader.NodeType,
|
|
MessageStrings.Body)));
|
|
}
|
|
}
|
|
|
|
public static WsrmAcknowledgmentInfo ReadHeader(ReliableMessagingVersion reliableMessagingVersion,
|
|
XmlDictionaryReader reader, MessageHeaderInfo header)
|
|
{
|
|
WsrmFeb2005Dictionary wsrmFeb2005Dictionary = XD.WsrmFeb2005Dictionary;
|
|
XmlDictionaryString wsrmNs = WsrmIndex.GetNamespace(reliableMessagingVersion);
|
|
|
|
UniqueId sequenceID;
|
|
SequenceRangeCollection rangeCollection;
|
|
bool final;
|
|
ReadAck(reliableMessagingVersion, reader, out sequenceID, out rangeCollection, out final);
|
|
|
|
int bufferRemaining = -1;
|
|
|
|
// Parse the extensibility section.
|
|
while (reader.IsStartElement())
|
|
{
|
|
if (reader.IsStartElement(wsrmFeb2005Dictionary.BufferRemaining,
|
|
XD.WsrmFeb2005Dictionary.NETNamespace))
|
|
{
|
|
if (bufferRemaining != -1)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(
|
|
SR.GetString(SR.UnexpectedXmlChildNode, reader.Name, reader.NodeType,
|
|
MessageStrings.Body)));
|
|
}
|
|
|
|
reader.ReadStartElement();
|
|
bufferRemaining = reader.ReadContentAsInt();
|
|
reader.ReadEndElement();
|
|
|
|
if (bufferRemaining < 0)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(
|
|
SR.GetString(SR.InvalidBufferRemaining, bufferRemaining)));
|
|
}
|
|
|
|
// Found BufferRemaining, continue parsing.
|
|
continue;
|
|
}
|
|
|
|
if (reader.IsStartElement(wsrmFeb2005Dictionary.AcknowledgementRange, wsrmNs))
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(
|
|
SR.GetString(SR.UnexpectedXmlChildNode, reader.Name, reader.NodeType,
|
|
MessageStrings.Body)));
|
|
}
|
|
else if (reader.IsStartElement(wsrmFeb2005Dictionary.Nack, wsrmNs))
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(
|
|
SR.GetString(SR.UnexpectedXmlChildNode, reader.Name, reader.NodeType,
|
|
MessageStrings.Body)));
|
|
}
|
|
else if (reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessaging11)
|
|
{
|
|
Wsrm11Dictionary wsrm11Dictionary = DXD.Wsrm11Dictionary;
|
|
|
|
if (reader.IsStartElement(wsrm11Dictionary.None, wsrmNs)
|
|
|| reader.IsStartElement(wsrm11Dictionary.Final, wsrmNs))
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(
|
|
SR.GetString(SR.UnexpectedXmlChildNode, reader.Name, reader.NodeType,
|
|
wsrmFeb2005Dictionary.SequenceAcknowledgement)));
|
|
}
|
|
}
|
|
|
|
// Advance the reader in all cases.
|
|
reader.Skip();
|
|
}
|
|
|
|
reader.ReadEndElement();
|
|
|
|
return new WsrmAcknowledgmentInfo(sequenceID, rangeCollection, final, bufferRemaining, header);
|
|
}
|
|
}
|
|
|
|
internal sealed class WsrmAcknowledgmentHeader : WsrmMessageHeader
|
|
{
|
|
int bufferRemaining;
|
|
bool final;
|
|
SequenceRangeCollection ranges;
|
|
UniqueId sequenceID;
|
|
|
|
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 override XmlDictionaryString DictionaryName
|
|
{
|
|
get { return XD.WsrmFeb2005Dictionary.SequenceAcknowledgement; }
|
|
}
|
|
|
|
protected override void OnWriteHeaderContents(XmlDictionaryWriter writer, MessageVersion messageVersion)
|
|
{
|
|
WsrmFeb2005Dictionary wsrmFeb2005Dictionary = XD.WsrmFeb2005Dictionary;
|
|
XmlDictionaryString wsrmNs = this.DictionaryNamespace;
|
|
|
|
WriteAckRanges(writer, this.ReliableMessagingVersion, this.sequenceID, this.ranges);
|
|
|
|
if ((this.ReliableMessagingVersion == ReliableMessagingVersion.WSReliableMessaging11) && this.final)
|
|
{
|
|
writer.WriteStartElement(DXD.Wsrm11Dictionary.Final, wsrmNs);
|
|
writer.WriteEndElement();
|
|
}
|
|
|
|
if (this.bufferRemaining != -1)
|
|
{
|
|
writer.WriteStartElement(WsrmFeb2005Strings.NETPrefix, wsrmFeb2005Dictionary.BufferRemaining,
|
|
XD.WsrmFeb2005Dictionary.NETNamespace);
|
|
writer.WriteValue(this.bufferRemaining);
|
|
writer.WriteEndElement();
|
|
}
|
|
}
|
|
|
|
// February 2005 - Writes Identifier, AcknowledgementRange
|
|
// 1.1 - Writes Identifier, AcknowledgementRange | None
|
|
internal static void WriteAckRanges(XmlDictionaryWriter writer,
|
|
ReliableMessagingVersion reliableMessagingVersion, UniqueId sequenceId, SequenceRangeCollection ranges)
|
|
{
|
|
WsrmFeb2005Dictionary wsrmFeb2005Dictionary = XD.WsrmFeb2005Dictionary;
|
|
XmlDictionaryString wsrmNs = WsrmIndex.GetNamespace(reliableMessagingVersion);
|
|
|
|
writer.WriteStartElement(wsrmFeb2005Dictionary.Identifier, wsrmNs);
|
|
writer.WriteValue(sequenceId);
|
|
writer.WriteEndElement();
|
|
|
|
if (ranges.Count == 0)
|
|
{
|
|
if (reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessagingFebruary2005)
|
|
{
|
|
ranges = ranges.MergeWith(0);
|
|
}
|
|
else if (reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessaging11)
|
|
{
|
|
writer.WriteStartElement(DXD.Wsrm11Dictionary.None, wsrmNs);
|
|
writer.WriteEndElement();
|
|
}
|
|
}
|
|
|
|
for (int index = 0; index < ranges.Count; index++)
|
|
{
|
|
writer.WriteStartElement(wsrmFeb2005Dictionary.AcknowledgementRange, wsrmNs);
|
|
writer.WriteStartAttribute(wsrmFeb2005Dictionary.Lower, null);
|
|
writer.WriteValue(ranges[index].Lower);
|
|
writer.WriteEndAttribute();
|
|
writer.WriteStartAttribute(wsrmFeb2005Dictionary.Upper, null);
|
|
writer.WriteValue(ranges[index].Upper);
|
|
writer.WriteEndAttribute();
|
|
writer.WriteEndElement();
|
|
}
|
|
}
|
|
}
|
|
|
|
internal sealed class WsrmAckRequestedInfo : WsrmHeaderInfo
|
|
{
|
|
UniqueId sequenceID;
|
|
|
|
public WsrmAckRequestedInfo(UniqueId sequenceID, MessageHeaderInfo header)
|
|
: base(header)
|
|
{
|
|
this.sequenceID = sequenceID;
|
|
}
|
|
|
|
public UniqueId SequenceID
|
|
{
|
|
get
|
|
{
|
|
return this.sequenceID;
|
|
}
|
|
}
|
|
|
|
public static WsrmAckRequestedInfo ReadHeader(ReliableMessagingVersion reliableMessagingVersion,
|
|
XmlDictionaryReader reader, MessageHeaderInfo header)
|
|
{
|
|
WsrmFeb2005Dictionary wsrmFeb2005Dictionary = XD.WsrmFeb2005Dictionary;
|
|
XmlDictionaryString wsrmNs = WsrmIndex.GetNamespace(reliableMessagingVersion);
|
|
|
|
reader.ReadStartElement();
|
|
|
|
reader.ReadStartElement(wsrmFeb2005Dictionary.Identifier, wsrmNs);
|
|
UniqueId sequenceID = reader.ReadContentAsUniqueId();
|
|
reader.ReadEndElement();
|
|
|
|
if (reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessagingFebruary2005)
|
|
{
|
|
if (reader.IsStartElement(wsrmFeb2005Dictionary.MessageNumber, wsrmNs))
|
|
{
|
|
reader.ReadStartElement();
|
|
WsrmUtilities.ReadSequenceNumber(reader, true);
|
|
reader.ReadEndElement();
|
|
}
|
|
}
|
|
|
|
while (reader.IsStartElement())
|
|
{
|
|
reader.Skip();
|
|
}
|
|
|
|
reader.ReadEndElement();
|
|
|
|
return new WsrmAckRequestedInfo(sequenceID, header);
|
|
}
|
|
}
|
|
|
|
internal sealed class WsrmAckRequestedHeader : WsrmMessageHeader
|
|
{
|
|
UniqueId sequenceID;
|
|
|
|
public WsrmAckRequestedHeader(ReliableMessagingVersion reliableMessagingVersion, UniqueId sequenceID)
|
|
: base(reliableMessagingVersion)
|
|
{
|
|
this.sequenceID = sequenceID;
|
|
}
|
|
|
|
public override XmlDictionaryString DictionaryName
|
|
{
|
|
get { return XD.WsrmFeb2005Dictionary.AckRequested; }
|
|
}
|
|
|
|
protected override void OnWriteHeaderContents(XmlDictionaryWriter writer, MessageVersion messageVersion)
|
|
{
|
|
WsrmFeb2005Dictionary wsrmFeb2005Dictionary = XD.WsrmFeb2005Dictionary;
|
|
XmlDictionaryString wsrmNs = this.DictionaryNamespace;
|
|
|
|
writer.WriteStartElement(wsrmFeb2005Dictionary.Identifier, wsrmNs);
|
|
writer.WriteValue(this.sequenceID);
|
|
writer.WriteEndElement();
|
|
}
|
|
}
|
|
|
|
// We do not generate the UsesSequenceSSL header. Thus, there is an info, but no header.
|
|
internal sealed class WsrmUsesSequenceSSLInfo : WsrmHeaderInfo
|
|
{
|
|
WsrmUsesSequenceSSLInfo(MessageHeaderInfo header)
|
|
: base(header)
|
|
{
|
|
}
|
|
|
|
public static WsrmUsesSequenceSSLInfo ReadHeader(XmlDictionaryReader reader, MessageHeaderInfo header)
|
|
{
|
|
WsrmUtilities.ReadEmptyElement(reader);
|
|
return new WsrmUsesSequenceSSLInfo(header);
|
|
}
|
|
}
|
|
|
|
internal sealed class WsrmUsesSequenceSTRHeader : WsrmMessageHeader
|
|
{
|
|
public WsrmUsesSequenceSTRHeader()
|
|
: base(ReliableMessagingVersion.WSReliableMessaging11)
|
|
{
|
|
}
|
|
|
|
public override XmlDictionaryString DictionaryName
|
|
{
|
|
get { return DXD.Wsrm11Dictionary.UsesSequenceSTR; }
|
|
}
|
|
|
|
protected override void OnWriteHeaderContents(XmlDictionaryWriter writer, MessageVersion messageVersion)
|
|
{
|
|
}
|
|
|
|
public override bool MustUnderstand
|
|
{
|
|
get { return true; }
|
|
}
|
|
}
|
|
|
|
internal sealed class WsrmUsesSequenceSTRInfo : WsrmHeaderInfo
|
|
{
|
|
WsrmUsesSequenceSTRInfo(MessageHeaderInfo header)
|
|
: base(header)
|
|
{
|
|
}
|
|
|
|
public static WsrmUsesSequenceSTRInfo ReadHeader(XmlDictionaryReader reader, MessageHeaderInfo header)
|
|
{
|
|
WsrmUtilities.ReadEmptyElement(reader);
|
|
return new WsrmUsesSequenceSTRInfo(header);
|
|
}
|
|
}
|
|
}
|