862 lines
30 KiB
C#
862 lines
30 KiB
C#
|
//----------------------------------------------------------------------------
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
namespace System.ServiceModel.Channels
|
||
|
{
|
||
|
using System.Globalization;
|
||
|
using System.Runtime;
|
||
|
using System.ServiceModel;
|
||
|
using System.Xml;
|
||
|
|
||
|
abstract class WsrmFault : MessageFault
|
||
|
{
|
||
|
FaultCode code;
|
||
|
string exceptionMessage;
|
||
|
bool hasDetail;
|
||
|
bool isRemote;
|
||
|
FaultReason reason;
|
||
|
ReliableMessagingVersion reliableMessagingVersion;
|
||
|
string subcode;
|
||
|
|
||
|
// local
|
||
|
protected WsrmFault(bool isSenderFault, string subcode, string faultReason, string exceptionMessage)
|
||
|
{
|
||
|
if (isSenderFault)
|
||
|
{
|
||
|
this.code = new FaultCode("Sender", "");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
this.code = new FaultCode("Receiver", "");
|
||
|
}
|
||
|
|
||
|
this.subcode = subcode;
|
||
|
this.reason = new FaultReason(faultReason, CultureInfo.CurrentCulture);
|
||
|
this.exceptionMessage = exceptionMessage;
|
||
|
this.isRemote = false;
|
||
|
}
|
||
|
|
||
|
// remote
|
||
|
protected WsrmFault(FaultCode code, string subcode, FaultReason reason)
|
||
|
{
|
||
|
this.code = code;
|
||
|
this.subcode = subcode;
|
||
|
this.reason = reason;
|
||
|
this.isRemote = true;
|
||
|
}
|
||
|
|
||
|
public override FaultCode Code
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return this.code;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public override bool HasDetail
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
// The SOAP 1.1 requires body processing error information to be placed in a detail element
|
||
|
// and header processing error information to be placed in a soap fault header.
|
||
|
// Since wsrm header faults relate to header processing, the information in the detail is placed in a
|
||
|
// soap fault header in the SOAP 1.1 case. SOAP 1.2 is not so restrictive. Thus, this flag is set
|
||
|
// in CreateMessage if the SOAP version is 1.2.
|
||
|
return this.hasDetail;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public bool IsRemote
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return this.isRemote;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public override FaultReason Reason
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return this.reason;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public string Subcode
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return this.subcode;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public virtual CommunicationException CreateException()
|
||
|
{
|
||
|
string message;
|
||
|
|
||
|
if (this.IsRemote)
|
||
|
{
|
||
|
message = FaultException.GetSafeReasonText(this.reason);
|
||
|
message = SR.GetString(SR.WsrmFaultReceived, message);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (this.exceptionMessage == null)
|
||
|
{
|
||
|
throw Fx.AssertAndThrow("Exception message must not be accessed unless set.");
|
||
|
}
|
||
|
|
||
|
message = this.exceptionMessage;
|
||
|
}
|
||
|
|
||
|
if (this.code.IsSenderFault)
|
||
|
return new ProtocolException(message);
|
||
|
else
|
||
|
return new CommunicationException(message);
|
||
|
}
|
||
|
|
||
|
public static CommunicationException CreateException(WsrmFault fault)
|
||
|
{
|
||
|
return fault.CreateException();
|
||
|
}
|
||
|
|
||
|
public Message CreateMessage(MessageVersion messageVersion, ReliableMessagingVersion reliableMessagingVersion)
|
||
|
{
|
||
|
this.SetReliableMessagingVersion(reliableMessagingVersion);
|
||
|
string action = WsrmIndex.GetFaultActionString(messageVersion.Addressing, reliableMessagingVersion);
|
||
|
|
||
|
if (messageVersion.Envelope == EnvelopeVersion.Soap11)
|
||
|
{
|
||
|
this.code = this.Get11Code(this.code, this.subcode);
|
||
|
}
|
||
|
else if (messageVersion.Envelope == EnvelopeVersion.Soap12)
|
||
|
{
|
||
|
if (this.code.SubCode == null)
|
||
|
{
|
||
|
FaultCode subCode = new FaultCode(this.subcode,
|
||
|
WsrmIndex.GetNamespaceString(reliableMessagingVersion));
|
||
|
this.code = new FaultCode(this.code.Name, this.code.Namespace, subCode);
|
||
|
}
|
||
|
|
||
|
this.hasDetail = this.Get12HasDetail();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
throw Fx.AssertAndThrow("Unsupported MessageVersion.");
|
||
|
}
|
||
|
|
||
|
Message message = Message.CreateMessage(messageVersion, this, action);
|
||
|
this.OnFaultMessageCreated(messageVersion, message);
|
||
|
return message;
|
||
|
}
|
||
|
|
||
|
protected abstract FaultCode Get11Code(FaultCode code, string subcode);
|
||
|
protected abstract bool Get12HasDetail();
|
||
|
|
||
|
protected string GetExceptionMessage()
|
||
|
{
|
||
|
if (this.exceptionMessage == null)
|
||
|
{
|
||
|
throw Fx.AssertAndThrow("Exception message must not be accessed unless set.");
|
||
|
}
|
||
|
|
||
|
return this.exceptionMessage;
|
||
|
}
|
||
|
|
||
|
protected ReliableMessagingVersion GetReliableMessagingVersion()
|
||
|
{
|
||
|
if (this.reliableMessagingVersion == null)
|
||
|
{
|
||
|
throw Fx.AssertAndThrow("Reliable messaging version must not be accessed unless set.");
|
||
|
}
|
||
|
|
||
|
return this.reliableMessagingVersion;
|
||
|
}
|
||
|
|
||
|
protected abstract void OnFaultMessageCreated(MessageVersion version, Message message);
|
||
|
|
||
|
protected void SetReliableMessagingVersion(ReliableMessagingVersion reliableMessagingVersion)
|
||
|
{
|
||
|
if (reliableMessagingVersion == null)
|
||
|
{
|
||
|
throw Fx.AssertAndThrow("Reliable messaging version cannot be set to null.");
|
||
|
}
|
||
|
|
||
|
if (this.reliableMessagingVersion != null)
|
||
|
{
|
||
|
throw Fx.AssertAndThrow("Reliable messaging version must not be set twice.");
|
||
|
}
|
||
|
|
||
|
this.reliableMessagingVersion = reliableMessagingVersion;
|
||
|
}
|
||
|
|
||
|
internal void WriteDetail(XmlDictionaryWriter writer)
|
||
|
{
|
||
|
this.OnWriteDetailContents(writer);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
class WsrmRequiredFault : WsrmFault
|
||
|
{
|
||
|
// local
|
||
|
public WsrmRequiredFault(string faultReason)
|
||
|
: base(true, Wsrm11Strings.WsrmRequired, faultReason, null)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
protected override FaultCode Get11Code(FaultCode code, string subcode)
|
||
|
{
|
||
|
return new FaultCode(subcode, WsrmIndex.GetNamespaceString(this.GetReliableMessagingVersion()));
|
||
|
}
|
||
|
|
||
|
protected override bool Get12HasDetail()
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
protected override void OnFaultMessageCreated(MessageVersion version, Message message)
|
||
|
{
|
||
|
// do nothing
|
||
|
}
|
||
|
|
||
|
protected override void OnWriteDetailContents(XmlDictionaryWriter writer)
|
||
|
{
|
||
|
// do nothing
|
||
|
}
|
||
|
}
|
||
|
|
||
|
abstract class WsrmHeaderFault : WsrmFault
|
||
|
{
|
||
|
bool faultsInput;
|
||
|
bool faultsOutput;
|
||
|
UniqueId sequenceID;
|
||
|
string subcode;
|
||
|
|
||
|
// local
|
||
|
protected WsrmHeaderFault(bool isSenderFault, string subcode, string faultReason, string exceptionMessage,
|
||
|
UniqueId sequenceID, bool faultsInput, bool faultsOutput)
|
||
|
: base(isSenderFault, subcode, faultReason, exceptionMessage)
|
||
|
{
|
||
|
this.subcode = subcode;
|
||
|
this.sequenceID = sequenceID;
|
||
|
this.faultsInput = faultsInput;
|
||
|
this.faultsOutput = faultsOutput;
|
||
|
}
|
||
|
|
||
|
// remote
|
||
|
protected WsrmHeaderFault(FaultCode code, string subcode, FaultReason reason, XmlDictionaryReader detailReader,
|
||
|
ReliableMessagingVersion reliableMessagingVersion, bool faultsInput, bool faultsOutput)
|
||
|
: this(code, subcode, reason, faultsInput, faultsOutput)
|
||
|
{
|
||
|
this.sequenceID = ParseDetail(detailReader, reliableMessagingVersion);
|
||
|
}
|
||
|
|
||
|
// remote
|
||
|
protected WsrmHeaderFault(FaultCode code, string subcode, FaultReason reason, bool faultsInput,
|
||
|
bool faultsOutput)
|
||
|
: base(code, subcode, reason)
|
||
|
{
|
||
|
this.subcode = subcode;
|
||
|
this.faultsInput = faultsInput;
|
||
|
this.faultsOutput = faultsOutput;
|
||
|
}
|
||
|
|
||
|
public bool FaultsInput
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return this.faultsInput;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public bool FaultsOutput
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return this.faultsOutput;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public UniqueId SequenceID
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return this.sequenceID;
|
||
|
}
|
||
|
protected set
|
||
|
{
|
||
|
this.sequenceID = value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static WsrmHeaderFault CreateWsrmHeaderFault(ReliableMessagingVersion reliableMessagingVersion, FaultCode code,
|
||
|
string subcode, FaultReason reason, XmlDictionaryReader detailReader)
|
||
|
{
|
||
|
// Sender faults.
|
||
|
if (code.IsSenderFault)
|
||
|
{
|
||
|
if (subcode == WsrmFeb2005Strings.InvalidAcknowledgement)
|
||
|
{
|
||
|
return new InvalidAcknowledgementFault(code, reason, detailReader, reliableMessagingVersion);
|
||
|
}
|
||
|
else if (subcode == WsrmFeb2005Strings.MessageNumberRollover)
|
||
|
{
|
||
|
return new MessageNumberRolloverFault(code, reason, detailReader, reliableMessagingVersion);
|
||
|
}
|
||
|
else if (subcode == WsrmFeb2005Strings.UnknownSequence)
|
||
|
{
|
||
|
return new UnknownSequenceFault(code, reason, detailReader, reliableMessagingVersion);
|
||
|
}
|
||
|
else if (reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessagingFebruary2005)
|
||
|
{
|
||
|
if (subcode == WsrmFeb2005Strings.LastMessageNumberExceeded)
|
||
|
{
|
||
|
return new LastMessageNumberExceededFault(code, reason, detailReader, reliableMessagingVersion);
|
||
|
}
|
||
|
}
|
||
|
else if (reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessaging11)
|
||
|
{
|
||
|
if (subcode == Wsrm11Strings.SequenceClosed)
|
||
|
{
|
||
|
return new SequenceClosedFault(code, reason, detailReader, reliableMessagingVersion);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Sender or receiver faults.
|
||
|
if (code.IsSenderFault || code.IsReceiverFault)
|
||
|
{
|
||
|
return new SequenceTerminatedFault(code, reason, detailReader, reliableMessagingVersion);
|
||
|
}
|
||
|
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
protected override FaultCode Get11Code(FaultCode code, string subcode)
|
||
|
{
|
||
|
return code;
|
||
|
}
|
||
|
|
||
|
protected override bool Get12HasDetail()
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
static void LookupDetailInformation(ReliableMessagingVersion reliableMessagingVersion, string subcode,
|
||
|
out string detailName, out string detailNamespace)
|
||
|
{
|
||
|
detailName = null;
|
||
|
detailNamespace = null;
|
||
|
string wsrmNs = WsrmIndex.GetNamespaceString(reliableMessagingVersion);
|
||
|
bool wsrmFeb2005 = reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessagingFebruary2005;
|
||
|
bool wsrm11 = reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessaging11;
|
||
|
|
||
|
if (subcode == WsrmFeb2005Strings.InvalidAcknowledgement)
|
||
|
{
|
||
|
detailName = WsrmFeb2005Strings.SequenceAcknowledgement;
|
||
|
detailNamespace = wsrmNs;
|
||
|
}
|
||
|
else if ((subcode == WsrmFeb2005Strings.MessageNumberRollover)
|
||
|
|| (subcode == WsrmFeb2005Strings.SequenceTerminated)
|
||
|
|| (subcode == WsrmFeb2005Strings.UnknownSequence)
|
||
|
|| (wsrmFeb2005 && (subcode == WsrmFeb2005Strings.LastMessageNumberExceeded))
|
||
|
|| (wsrm11 && (subcode == Wsrm11Strings.SequenceClosed)))
|
||
|
{
|
||
|
detailName = WsrmFeb2005Strings.Identifier;
|
||
|
detailNamespace = wsrmNs;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
detailName = null;
|
||
|
detailNamespace = null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected override void OnFaultMessageCreated(MessageVersion version, Message message)
|
||
|
{
|
||
|
if (version.Envelope == EnvelopeVersion.Soap11)
|
||
|
{
|
||
|
WsrmSequenceFaultHeader header = new WsrmSequenceFaultHeader(this.GetReliableMessagingVersion(), this);
|
||
|
message.Headers.Add(header);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected override void OnWriteDetailContents(XmlDictionaryWriter writer)
|
||
|
{
|
||
|
WsrmUtilities.WriteIdentifier(writer, this.GetReliableMessagingVersion(), this.sequenceID);
|
||
|
}
|
||
|
|
||
|
static UniqueId ParseDetail(XmlDictionaryReader reader, ReliableMessagingVersion reliableMessagingVersion)
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
return WsrmUtilities.ReadIdentifier(reader, reliableMessagingVersion);
|
||
|
}
|
||
|
finally
|
||
|
{
|
||
|
reader.Close();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static bool TryCreateFault11(ReliableMessagingVersion reliableMessagingVersion, Message message,
|
||
|
MessageFault fault, int index, out WsrmHeaderFault wsrmFault)
|
||
|
{
|
||
|
if (index == -1)
|
||
|
{
|
||
|
wsrmFault = null;
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// All wsrm header faults must be sender or receiver faults.
|
||
|
if (!fault.Code.IsSenderFault && !fault.Code.IsReceiverFault)
|
||
|
{
|
||
|
wsrmFault = null;
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
string subcodeName = WsrmSequenceFaultHeader.GetSubcode(message.Headers.GetReaderAtHeader(index),
|
||
|
reliableMessagingVersion);
|
||
|
|
||
|
if (subcodeName == null)
|
||
|
{
|
||
|
wsrmFault = null;
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
string detailName;
|
||
|
string detailNamespace;
|
||
|
|
||
|
LookupDetailInformation(reliableMessagingVersion, subcodeName, out detailName, out detailNamespace);
|
||
|
|
||
|
XmlDictionaryReader detailReader = WsrmSequenceFaultHeader.GetReaderAtDetailContents(detailName,
|
||
|
detailNamespace, message.Headers.GetReaderAtHeader(index), reliableMessagingVersion);
|
||
|
|
||
|
if (detailReader == null)
|
||
|
{
|
||
|
wsrmFault = null;
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
wsrmFault = CreateWsrmHeaderFault(reliableMessagingVersion, fault.Code, subcodeName, fault.Reason,
|
||
|
detailReader);
|
||
|
if (wsrmFault != null)
|
||
|
{
|
||
|
message.Headers.UnderstoodHeaders.Add(message.Headers[index]);
|
||
|
return true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static bool TryCreateFault12(ReliableMessagingVersion reliableMessagingVersion, Message message,
|
||
|
MessageFault fault, out WsrmHeaderFault wsrmFault)
|
||
|
{
|
||
|
// All wsrm header faults must be sender or receiver faults.
|
||
|
if (!fault.Code.IsSenderFault && !fault.Code.IsReceiverFault)
|
||
|
{
|
||
|
wsrmFault = null;
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
if ((fault.Code.SubCode == null)
|
||
|
|| (fault.Code.SubCode.Namespace != WsrmIndex.GetNamespaceString(reliableMessagingVersion)) || !fault.HasDetail)
|
||
|
{
|
||
|
wsrmFault = null;
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
string subcodeName = fault.Code.SubCode.Name;
|
||
|
XmlDictionaryReader detailReader = fault.GetReaderAtDetailContents();
|
||
|
wsrmFault = CreateWsrmHeaderFault(reliableMessagingVersion, fault.Code, subcodeName, fault.Reason,
|
||
|
detailReader);
|
||
|
|
||
|
return (wsrmFault != null);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
sealed class InvalidAcknowledgementFault : WsrmHeaderFault
|
||
|
{
|
||
|
SequenceRangeCollection ranges;
|
||
|
|
||
|
public InvalidAcknowledgementFault(UniqueId sequenceID, SequenceRangeCollection ranges)
|
||
|
: base(true, WsrmFeb2005Strings.InvalidAcknowledgement, SR.GetString(SR.InvalidAcknowledgementFaultReason),
|
||
|
SR.GetString(SR.InvalidAcknowledgementReceived), sequenceID, true, false)
|
||
|
{
|
||
|
this.ranges = ranges;
|
||
|
}
|
||
|
|
||
|
public InvalidAcknowledgementFault(FaultCode code, FaultReason reason,
|
||
|
XmlDictionaryReader detailReader, ReliableMessagingVersion reliableMessagingVersion)
|
||
|
: base(code, WsrmFeb2005Strings.InvalidAcknowledgement, reason, true, false)
|
||
|
{
|
||
|
UniqueId sequenceId;
|
||
|
bool final;
|
||
|
|
||
|
WsrmAcknowledgmentInfo.ReadAck(reliableMessagingVersion, detailReader, out sequenceId, out this.ranges,
|
||
|
out final);
|
||
|
|
||
|
this.SequenceID = sequenceId;
|
||
|
|
||
|
while (detailReader.IsStartElement())
|
||
|
{
|
||
|
detailReader.Skip();
|
||
|
}
|
||
|
|
||
|
detailReader.ReadEndElement();
|
||
|
}
|
||
|
|
||
|
protected override void OnWriteDetailContents(XmlDictionaryWriter writer)
|
||
|
{
|
||
|
WsrmFeb2005Dictionary wsrmFeb2005Dictionary = XD.WsrmFeb2005Dictionary;
|
||
|
ReliableMessagingVersion reliableMessagingVersion = this.GetReliableMessagingVersion();
|
||
|
XmlDictionaryString wsrmNs = WsrmIndex.GetNamespace(reliableMessagingVersion);
|
||
|
|
||
|
writer.WriteStartElement(wsrmFeb2005Dictionary.SequenceAcknowledgement, wsrmNs);
|
||
|
WsrmAcknowledgmentHeader.WriteAckRanges(writer, reliableMessagingVersion, this.SequenceID, this.ranges);
|
||
|
writer.WriteEndElement();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
sealed class LastMessageNumberExceededFault : WsrmHeaderFault
|
||
|
{
|
||
|
public LastMessageNumberExceededFault(UniqueId sequenceID)
|
||
|
: base(true, WsrmFeb2005Strings.LastMessageNumberExceeded, SR.GetString(SR.LastMessageNumberExceededFaultReason),
|
||
|
SR.GetString(SR.LastMessageNumberExceeded), sequenceID, false, true)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
public LastMessageNumberExceededFault(FaultCode code, FaultReason reason,
|
||
|
XmlDictionaryReader detailReader, ReliableMessagingVersion reliableMessagingVersion)
|
||
|
: base(code, WsrmFeb2005Strings.LastMessageNumberExceeded, reason, detailReader, reliableMessagingVersion, false,
|
||
|
true)
|
||
|
{
|
||
|
}
|
||
|
}
|
||
|
|
||
|
sealed class MessageNumberRolloverFault : WsrmHeaderFault
|
||
|
{
|
||
|
public MessageNumberRolloverFault(UniqueId sequenceID)
|
||
|
: base(true, WsrmFeb2005Strings.MessageNumberRollover, SR.GetString(SR.MessageNumberRolloverFaultReason),
|
||
|
SR.GetString(SR.MessageNumberRollover), sequenceID, true, true)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
public MessageNumberRolloverFault(FaultCode code, FaultReason reason, XmlDictionaryReader detailReader,
|
||
|
ReliableMessagingVersion reliableMessagingVersion)
|
||
|
: base(code, WsrmFeb2005Strings.MessageNumberRollover, reason, true, true)
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
this.SequenceID = WsrmUtilities.ReadIdentifier(detailReader, reliableMessagingVersion);
|
||
|
|
||
|
if (reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessaging11)
|
||
|
{
|
||
|
detailReader.ReadStartElement(DXD.Wsrm11Dictionary.MaxMessageNumber,
|
||
|
WsrmIndex.GetNamespace(reliableMessagingVersion));
|
||
|
|
||
|
string maxMessageNumberString = detailReader.ReadContentAsString();
|
||
|
ulong maxMessageNumber;
|
||
|
if (!UInt64.TryParse(maxMessageNumberString, out maxMessageNumber)
|
||
|
|| (maxMessageNumber <= 0))
|
||
|
{
|
||
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(
|
||
|
SR.GetString(SR.InvalidSequenceNumber, maxMessageNumber)));
|
||
|
}
|
||
|
// otherwise ignore value
|
||
|
|
||
|
detailReader.ReadEndElement();
|
||
|
}
|
||
|
}
|
||
|
finally
|
||
|
{
|
||
|
detailReader.Close();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected override void OnWriteDetailContents(XmlDictionaryWriter writer)
|
||
|
{
|
||
|
ReliableMessagingVersion reliableMessagingVersion = this.GetReliableMessagingVersion();
|
||
|
WsrmUtilities.WriteIdentifier(writer, reliableMessagingVersion, this.SequenceID);
|
||
|
|
||
|
if (reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessaging11)
|
||
|
{
|
||
|
writer.WriteStartElement(WsrmFeb2005Strings.Prefix, DXD.Wsrm11Dictionary.MaxMessageNumber,
|
||
|
WsrmIndex.GetNamespace(reliableMessagingVersion));
|
||
|
writer.WriteValue(Int64.MaxValue);
|
||
|
writer.WriteEndElement();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
sealed class SequenceClosedFault : WsrmHeaderFault
|
||
|
{
|
||
|
public SequenceClosedFault(UniqueId sequenceID)
|
||
|
: base(true, Wsrm11Strings.SequenceClosed, SR.GetString(SR.SequenceClosedFaultString),
|
||
|
null, sequenceID, false, true)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
public SequenceClosedFault(FaultCode code, FaultReason reason, XmlDictionaryReader detailReader,
|
||
|
ReliableMessagingVersion reliableMessagingVersion)
|
||
|
: base(code, Wsrm11Strings.SequenceClosed, reason, detailReader, reliableMessagingVersion, false, true)
|
||
|
{
|
||
|
}
|
||
|
}
|
||
|
|
||
|
sealed class SequenceTerminatedFault : WsrmHeaderFault
|
||
|
{
|
||
|
SequenceTerminatedFault(bool isSenderFault, UniqueId sequenceID, string faultReason, string exceptionMessage)
|
||
|
: base(isSenderFault, WsrmFeb2005Strings.SequenceTerminated, faultReason, exceptionMessage, sequenceID, true, true)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
public SequenceTerminatedFault(FaultCode code, FaultReason reason, XmlDictionaryReader detailReader,
|
||
|
ReliableMessagingVersion reliableMessagingVersion)
|
||
|
: base(code, WsrmFeb2005Strings.SequenceTerminated, reason, detailReader, reliableMessagingVersion, true, true)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
public static WsrmFault CreateCommunicationFault(UniqueId sequenceID, string faultReason,
|
||
|
string exceptionMessage)
|
||
|
{
|
||
|
return new SequenceTerminatedFault(false, sequenceID, faultReason, exceptionMessage);
|
||
|
}
|
||
|
|
||
|
public static WsrmFault CreateMaxRetryCountExceededFault(UniqueId sequenceId)
|
||
|
{
|
||
|
return CreateCommunicationFault(sequenceId, SR.GetString(SR.SequenceTerminatedMaximumRetryCountExceeded), null);
|
||
|
}
|
||
|
|
||
|
public static WsrmFault CreateProtocolFault(UniqueId sequenceID, string faultReason,
|
||
|
string exceptionMessage)
|
||
|
{
|
||
|
return new SequenceTerminatedFault(true, sequenceID, faultReason, exceptionMessage);
|
||
|
}
|
||
|
|
||
|
public static WsrmFault CreateQuotaExceededFault(UniqueId sequenceID)
|
||
|
{
|
||
|
return CreateProtocolFault(sequenceID, SR.GetString(SR.SequenceTerminatedQuotaExceededException), null);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
sealed class UnknownSequenceFault : WsrmHeaderFault
|
||
|
{
|
||
|
public UnknownSequenceFault(UniqueId sequenceID)
|
||
|
: base(true, WsrmFeb2005Strings.UnknownSequence, SR.GetString(SR.UnknownSequenceFaultReason),
|
||
|
SR.GetString(SR.UnknownSequenceMessageReceived), sequenceID, true, true)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
public UnknownSequenceFault(FaultCode code, FaultReason reason, XmlDictionaryReader detailReader,
|
||
|
ReliableMessagingVersion reliableMessagingVersion)
|
||
|
: base(code, WsrmFeb2005Strings.UnknownSequence, reason, detailReader, reliableMessagingVersion, true, true)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
public override CommunicationException CreateException()
|
||
|
{
|
||
|
string message;
|
||
|
|
||
|
if (this.IsRemote)
|
||
|
{
|
||
|
message = FaultException.GetSafeReasonText(this.Reason);
|
||
|
message = SR.GetString(SR.UnknownSequenceFaultReceived, message);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
message = this.GetExceptionMessage();
|
||
|
}
|
||
|
|
||
|
return new CommunicationException(message);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
class WsrmSequenceFaultHeader : WsrmMessageHeader
|
||
|
{
|
||
|
WsrmFault fault;
|
||
|
|
||
|
public WsrmSequenceFaultHeader(ReliableMessagingVersion reliableMessagingVersion, WsrmFault fault)
|
||
|
: base(reliableMessagingVersion)
|
||
|
{
|
||
|
this.fault = fault;
|
||
|
}
|
||
|
|
||
|
public WsrmFault Fault
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return this.fault;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public override XmlDictionaryString DictionaryName
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return XD.WsrmFeb2005Dictionary.SequenceFault;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public string Subcode
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return this.fault.Subcode;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static XmlDictionaryReader GetReaderAtDetailContents(string detailName, string detailNamespace,
|
||
|
XmlDictionaryReader headerReader, ReliableMessagingVersion reliableMessagingVersion)
|
||
|
{
|
||
|
if (reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessagingFebruary2005)
|
||
|
{
|
||
|
return GetReaderAtDetailContentsFeb2005(detailName, detailNamespace, headerReader);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return GetReaderAtDetailContents11(detailName, detailNamespace, headerReader);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static XmlDictionaryReader GetReaderAtDetailContents11(string detailName, string detailNamespace,
|
||
|
XmlDictionaryReader headerReader)
|
||
|
{
|
||
|
XmlDictionaryString wsrmNs = DXD.Wsrm11Dictionary.Namespace;
|
||
|
headerReader.ReadFullStartElement(XD.WsrmFeb2005Dictionary.SequenceFault, wsrmNs);
|
||
|
headerReader.Skip();
|
||
|
headerReader.ReadFullStartElement(XD.Message12Dictionary.FaultDetail, wsrmNs);
|
||
|
|
||
|
if ((headerReader.NodeType != XmlNodeType.Element)
|
||
|
|| (headerReader.NamespaceURI != detailNamespace)
|
||
|
|| (headerReader.LocalName != detailName))
|
||
|
{
|
||
|
headerReader.Close();
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
return headerReader;
|
||
|
}
|
||
|
|
||
|
public static XmlDictionaryReader GetReaderAtDetailContentsFeb2005(string detailName, string detailNamespace,
|
||
|
XmlDictionaryReader headerReader)
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
WsrmFeb2005Dictionary wsrmFeb2005Dictionary = XD.WsrmFeb2005Dictionary;
|
||
|
XmlDictionaryString wsrmNs = wsrmFeb2005Dictionary.Namespace;
|
||
|
XmlBuffer buffer = null;
|
||
|
int index = 0;
|
||
|
int depth = headerReader.Depth;
|
||
|
headerReader.ReadFullStartElement(wsrmFeb2005Dictionary.SequenceFault, wsrmNs);
|
||
|
|
||
|
while (headerReader.Depth > depth)
|
||
|
{
|
||
|
if ((headerReader.NodeType == XmlNodeType.Element)
|
||
|
&& (headerReader.NamespaceURI == detailNamespace)
|
||
|
&& (headerReader.LocalName == detailName))
|
||
|
{
|
||
|
if (buffer != null)
|
||
|
{
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
buffer = new XmlBuffer(int.MaxValue);
|
||
|
|
||
|
try
|
||
|
{
|
||
|
index = buffer.SectionCount;
|
||
|
XmlDictionaryWriter writer = buffer.OpenSection(headerReader.Quotas);
|
||
|
// WriteNode moves the reader to the next sibling.
|
||
|
writer.WriteNode(headerReader, false);
|
||
|
}
|
||
|
finally
|
||
|
{
|
||
|
buffer.CloseSection();
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (headerReader.Depth == depth)
|
||
|
break;
|
||
|
|
||
|
headerReader.Read();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Ensure at least one detail is found;
|
||
|
if (buffer == null)
|
||
|
{
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
// Close causes a state change. It moves the buffer from Created to Reading.
|
||
|
buffer.Close();
|
||
|
XmlDictionaryReader detailReader = buffer.GetReader(index);
|
||
|
return detailReader;
|
||
|
}
|
||
|
finally
|
||
|
{
|
||
|
headerReader.Close();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static string GetSubcode(XmlDictionaryReader headerReader,
|
||
|
ReliableMessagingVersion reliableMessagingVersion)
|
||
|
{
|
||
|
string subCode = null;
|
||
|
|
||
|
try
|
||
|
{
|
||
|
WsrmFeb2005Dictionary wsrmFeb2005Dictionary = XD.WsrmFeb2005Dictionary;
|
||
|
XmlDictionaryString wsrmNs = WsrmIndex.GetNamespace(reliableMessagingVersion);
|
||
|
string ns;
|
||
|
|
||
|
headerReader.ReadStartElement(wsrmFeb2005Dictionary.SequenceFault, wsrmNs);
|
||
|
headerReader.ReadStartElement(wsrmFeb2005Dictionary.FaultCode, wsrmNs);
|
||
|
XmlUtil.ReadContentAsQName(headerReader, out subCode, out ns);
|
||
|
|
||
|
if (ns != WsrmIndex.GetNamespaceString(reliableMessagingVersion))
|
||
|
subCode = null;
|
||
|
|
||
|
headerReader.ReadEndElement();
|
||
|
|
||
|
while (headerReader.IsStartElement())
|
||
|
headerReader.Skip();
|
||
|
|
||
|
headerReader.ReadEndElement();
|
||
|
}
|
||
|
finally
|
||
|
{
|
||
|
headerReader.Close();
|
||
|
}
|
||
|
|
||
|
return subCode;
|
||
|
}
|
||
|
|
||
|
protected override void OnWriteHeaderContents(XmlDictionaryWriter writer, MessageVersion messageVersion)
|
||
|
{
|
||
|
writer.WriteStartElement(WsrmFeb2005Strings.Prefix, WsrmFeb2005Strings.FaultCode, this.Namespace);
|
||
|
writer.WriteXmlnsAttribute(null, this.Namespace);
|
||
|
writer.WriteQualifiedName(this.Subcode, this.Namespace);
|
||
|
writer.WriteEndElement();
|
||
|
|
||
|
bool wsrm11 = this.ReliableMessagingVersion == ReliableMessagingVersion.WSReliableMessaging11;
|
||
|
|
||
|
if (wsrm11)
|
||
|
{
|
||
|
writer.WriteStartElement(WsrmFeb2005Strings.Prefix, XD.Message12Dictionary.FaultDetail, this.DictionaryNamespace);
|
||
|
}
|
||
|
|
||
|
this.fault.WriteDetail(writer);
|
||
|
|
||
|
if (wsrm11)
|
||
|
{
|
||
|
writer.WriteEndElement();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|