|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Runtime;
using System.Runtime.Serialization;
using System.ServiceModel.Dispatcher;
using System.Threading;
using System.Xml;
namespace System.ServiceModel.Channels
{
public sealed class MessageHeaders : IEnumerable<MessageHeaderInfo>
{
private int _headerCount;
private Header[] _headers;
private IBufferedMessageData _bufferedMessageData;
private UnderstoodHeaders _understoodHeaders;
private const int InitialHeaderCount = 4;
private const int MaxRecycledArrayLength = 8;
private static XmlDictionaryString[] s_localNames;
internal const string WildcardAction = "*";
// The highest node and attribute counts reached by the BVTs were 1829 and 667 respectively.
private const int MaxBufferedHeaderNodes = 4096;
private const int MaxBufferedHeaderAttributes = 2048;
private int _nodeCount = 0;
private int _attrCount = 0;
private bool _understoodHeadersModified;
public MessageHeaders(MessageVersion version, int initialSize)
{
Init(version, initialSize);
}
public MessageHeaders(MessageVersion version)
: this(version, InitialHeaderCount)
{
}
internal MessageHeaders(MessageVersion version, XmlDictionaryReader reader, XmlAttributeHolder[] envelopeAttributes, XmlAttributeHolder[] headerAttributes, ref int maxSizeOfHeaders)
: this(version)
{
if (maxSizeOfHeaders < 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
new ArgumentOutOfRangeException(nameof(maxSizeOfHeaders), maxSizeOfHeaders,
SRP.ValueMustBeNonNegative));
}
if (version == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(version)));
}
if (reader == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(reader)));
}
if (reader.IsEmptyElement)
{
reader.Read();
return;
}
XmlBuffer xmlBuffer = null;
EnvelopeVersion envelopeVersion = version.Envelope;
reader.ReadStartElement(XD.MessageDictionary.Header, envelopeVersion.DictionaryNamespace);
while (reader.IsStartElement())
{
if (xmlBuffer == null)
{
xmlBuffer = new XmlBuffer(maxSizeOfHeaders);
}
BufferedHeader bufferedHeader = new BufferedHeader(version, xmlBuffer, reader, envelopeAttributes, headerAttributes);
HeaderProcessing processing = bufferedHeader.MustUnderstand ? HeaderProcessing.MustUnderstand : 0;
HeaderKind kind = GetHeaderKind(bufferedHeader);
if (kind != HeaderKind.Unknown)
{
processing |= HeaderProcessing.Understood;
MessageHeaders.TraceUnderstood(bufferedHeader);
}
Header newHeader = new Header(kind, bufferedHeader, processing);
AddHeader(newHeader);
}
if (xmlBuffer != null)
{
xmlBuffer.Close();
maxSizeOfHeaders -= xmlBuffer.BufferSize;
}
reader.ReadEndElement();
CollectionVersion = 0;
}
internal MessageHeaders(MessageVersion version, XmlDictionaryReader reader, IBufferedMessageData bufferedMessageData, RecycledMessageState recycledMessageState, bool[] understoodHeaders, bool understoodHeadersModified)
{
_headers = new Header[InitialHeaderCount];
Init(version, reader, bufferedMessageData, recycledMessageState, understoodHeaders, understoodHeadersModified);
}
internal MessageHeaders(MessageVersion version, MessageHeaders headers, IBufferedMessageData bufferedMessageData)
{
MessageVersion = version;
_bufferedMessageData = bufferedMessageData;
_headerCount = headers._headerCount;
_headers = new Header[_headerCount];
Array.Copy(headers._headers, _headers, _headerCount);
CollectionVersion = 0;
}
public MessageHeaders(MessageHeaders collection)
{
if (collection == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(collection));
}
Init(collection.MessageVersion, collection._headers.Length);
CopyHeadersFrom(collection);
CollectionVersion = 0;
}
public string Action
{
get
{
int index = FindHeaderProperty(HeaderKind.Action);
if (index < 0)
{
return null;
}
ActionHeader actionHeader = _headers[index].HeaderInfo as ActionHeader;
if (actionHeader != null)
{
return actionHeader.Action;
}
using (XmlDictionaryReader reader = GetReaderAtHeader(index))
{
return ActionHeader.ReadHeaderValue(reader, MessageVersion.Addressing);
}
}
set
{
if (value != null)
{
SetActionHeader(ActionHeader.Create(value, MessageVersion.Addressing));
}
else
{
SetHeaderProperty(HeaderKind.Action, null);
}
}
}
internal bool CanRecycle
{
get { return _headers.Length <= MaxRecycledArrayLength; }
}
internal bool ContainsOnlyBufferedMessageHeaders
{
get { return (_bufferedMessageData != null && CollectionVersion == 0); }
}
internal int CollectionVersion { get; private set; }
public int Count
{
get { return _headerCount; }
}
public EndpointAddress FaultTo
{
get
{
int index = FindHeaderProperty(HeaderKind.FaultTo);
if (index < 0)
{
return null;
}
FaultToHeader faultToHeader = _headers[index].HeaderInfo as FaultToHeader;
if (faultToHeader != null)
{
return faultToHeader.FaultTo;
}
using (XmlDictionaryReader reader = GetReaderAtHeader(index))
{
return FaultToHeader.ReadHeaderValue(reader, MessageVersion.Addressing);
}
}
set
{
if (value != null)
{
SetFaultToHeader(FaultToHeader.Create(value, MessageVersion.Addressing));
}
else
{
SetHeaderProperty(HeaderKind.FaultTo, null);
}
}
}
public EndpointAddress From
{
get
{
int index = FindHeaderProperty(HeaderKind.From);
if (index < 0)
{
return null;
}
FromHeader fromHeader = _headers[index].HeaderInfo as FromHeader;
if (fromHeader != null)
{
return fromHeader.From;
}
using (XmlDictionaryReader reader = GetReaderAtHeader(index))
{
return FromHeader.ReadHeaderValue(reader, MessageVersion.Addressing);
}
}
set
{
if (value != null)
{
SetFromHeader(FromHeader.Create(value, MessageVersion.Addressing));
}
else
{
SetHeaderProperty(HeaderKind.From, null);
}
}
}
internal bool HasMustUnderstandBeenModified
{
get
{
if (_understoodHeaders != null)
{
return _understoodHeaders.Modified;
}
else
{
return _understoodHeadersModified;
}
}
}
public UniqueId MessageId
{
get
{
int index = FindHeaderProperty(HeaderKind.MessageId);
if (index < 0)
{
return null;
}
MessageIDHeader messageIDHeader = _headers[index].HeaderInfo as MessageIDHeader;
if (messageIDHeader != null)
{
return messageIDHeader.MessageId;
}
using (XmlDictionaryReader reader = GetReaderAtHeader(index))
{
return MessageIDHeader.ReadHeaderValue(reader, MessageVersion.Addressing);
}
}
set
{
if (value != null)
{
SetMessageIDHeader(MessageIDHeader.Create(value, MessageVersion.Addressing));
}
else
{
SetHeaderProperty(HeaderKind.MessageId, null);
}
}
}
public MessageVersion MessageVersion { get; private set; }
public UniqueId RelatesTo
{
get
{
return GetRelatesTo(RelatesToHeader.ReplyRelationshipType);
}
set
{
SetRelatesTo(RelatesToHeader.ReplyRelationshipType, value);
}
}
public EndpointAddress ReplyTo
{
get
{
int index = FindHeaderProperty(HeaderKind.ReplyTo);
if (index < 0)
{
return null;
}
ReplyToHeader replyToHeader = _headers[index].HeaderInfo as ReplyToHeader;
if (replyToHeader != null)
{
return replyToHeader.ReplyTo;
}
using (XmlDictionaryReader reader = GetReaderAtHeader(index))
{
return ReplyToHeader.ReadHeaderValue(reader, MessageVersion.Addressing);
}
}
set
{
if (value != null)
{
SetReplyToHeader(ReplyToHeader.Create(value, MessageVersion.Addressing));
}
else
{
SetHeaderProperty(HeaderKind.ReplyTo, null);
}
}
}
public Uri To
{
get
{
int index = FindHeaderProperty(HeaderKind.To);
if (index < 0)
{
return null;
}
ToHeader toHeader = _headers[index].HeaderInfo as ToHeader;
if (toHeader != null)
{
return toHeader.To;
}
using (XmlDictionaryReader reader = GetReaderAtHeader(index))
{
return ToHeader.ReadHeaderValue(reader, MessageVersion.Addressing);
}
}
set
{
if (value != null)
{
SetToHeader(ToHeader.Create(value, MessageVersion.Addressing));
}
else
{
SetHeaderProperty(HeaderKind.To, null);
}
}
}
public UnderstoodHeaders UnderstoodHeaders
{
get
{
if (_understoodHeaders == null)
{
_understoodHeaders = new UnderstoodHeaders(this, _understoodHeadersModified);
}
return _understoodHeaders;
}
}
public MessageHeaderInfo this[int index]
{
get
{
if (index < 0 || index >= _headerCount)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
new ArgumentOutOfRangeException(nameof(index), index,
SRP.Format(SRP.ValueMustBeInRange, 0, _headerCount)));
}
return _headers[index].HeaderInfo;
}
}
public void Add(MessageHeader header)
{
Insert(_headerCount, header);
}
internal void AddActionHeader(ActionHeader actionHeader)
{
Insert(_headerCount, actionHeader, HeaderKind.Action);
}
internal void AddMessageIDHeader(MessageIDHeader messageIDHeader)
{
Insert(_headerCount, messageIDHeader, HeaderKind.MessageId);
}
internal void AddRelatesToHeader(RelatesToHeader relatesToHeader)
{
Insert(_headerCount, relatesToHeader, HeaderKind.RelatesTo);
}
internal void AddReplyToHeader(ReplyToHeader replyToHeader)
{
Insert(_headerCount, replyToHeader, HeaderKind.ReplyTo);
}
internal void AddToHeader(ToHeader toHeader)
{
Insert(_headerCount, toHeader, HeaderKind.To);
}
private void Add(MessageHeader header, HeaderKind kind)
{
Insert(_headerCount, header, kind);
}
private void AddHeader(Header header)
{
InsertHeader(_headerCount, header);
}
internal void AddUnderstood(int i)
{
_headers[i].HeaderProcessing |= HeaderProcessing.Understood;
MessageHeaders.TraceUnderstood(_headers[i].HeaderInfo);
}
internal void AddUnderstood(MessageHeaderInfo headerInfo)
{
if (headerInfo == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(headerInfo)));
}
for (int i = 0; i < _headerCount; i++)
{
if ((object)_headers[i].HeaderInfo == (object)headerInfo)
{
if ((_headers[i].HeaderProcessing & HeaderProcessing.Understood) != 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(
SRP.Format(SRP.HeaderAlreadyUnderstood, headerInfo.Name, headerInfo.Namespace), "headerInfo"));
}
AddUnderstood(i);
}
}
}
private void CaptureBufferedHeaders()
{
CaptureBufferedHeaders(-1);
}
private void CaptureBufferedHeaders(int exceptIndex)
{
using (XmlDictionaryReader reader = GetBufferedMessageHeaderReaderAtHeaderContents(_bufferedMessageData))
{
for (int i = 0; i < _headerCount; i++)
{
if (reader.NodeType != XmlNodeType.Element)
{
if (reader.MoveToContent() != XmlNodeType.Element)
{
break;
}
}
Header header = _headers[i];
if (i == exceptIndex || header.HeaderType != HeaderType.BufferedMessageHeader)
{
reader.Skip();
}
else
{
_headers[i] = new Header(header.HeaderKind, CaptureBufferedHeader(reader,
header.HeaderInfo), header.HeaderProcessing);
}
}
}
_bufferedMessageData = null;
}
private BufferedHeader CaptureBufferedHeader(XmlDictionaryReader reader, MessageHeaderInfo headerInfo)
{
XmlBuffer buffer = new XmlBuffer(int.MaxValue);
XmlDictionaryWriter writer = buffer.OpenSection(_bufferedMessageData.Quotas);
writer.WriteNode(reader, false);
buffer.CloseSection();
buffer.Close();
return new BufferedHeader(MessageVersion, buffer, 0, headerInfo);
}
private BufferedHeader CaptureBufferedHeader(IBufferedMessageData bufferedMessageData, MessageHeaderInfo headerInfo, int bufferedMessageHeaderIndex)
{
XmlBuffer buffer = new XmlBuffer(int.MaxValue);
XmlDictionaryWriter writer = buffer.OpenSection(bufferedMessageData.Quotas);
WriteBufferedMessageHeader(bufferedMessageData, bufferedMessageHeaderIndex, writer);
buffer.CloseSection();
buffer.Close();
return new BufferedHeader(MessageVersion, buffer, 0, headerInfo);
}
private BufferedHeader CaptureWriteableHeader(MessageHeader writeableHeader)
{
XmlBuffer buffer = new XmlBuffer(int.MaxValue);
XmlDictionaryWriter writer = buffer.OpenSection(XmlDictionaryReaderQuotas.Max);
writeableHeader.WriteHeader(writer, MessageVersion);
buffer.CloseSection();
buffer.Close();
return new BufferedHeader(MessageVersion, buffer, 0, writeableHeader);
}
public void Clear()
{
for (int i = 0; i < _headerCount; i++)
{
_headers[i] = new Header();
}
_headerCount = 0;
CollectionVersion++;
_bufferedMessageData = null;
}
public void CopyHeaderFrom(Message message, int headerIndex)
{
if (message == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(message)));
}
CopyHeaderFrom(message.Headers, headerIndex);
}
public void CopyHeaderFrom(MessageHeaders collection, int headerIndex)
{
if (collection == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(collection));
}
if (collection.MessageVersion != MessageVersion)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SRP.Format(SRP.MessageHeaderVersionMismatch, collection.MessageVersion.ToString(), MessageVersion.ToString()), "collection"));
}
if (headerIndex < 0 || headerIndex >= collection._headerCount)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
new ArgumentOutOfRangeException(nameof(headerIndex), headerIndex,
SRP.Format(SRP.ValueMustBeInRange, 0, collection._headerCount)));
}
Header header = collection._headers[headerIndex];
HeaderProcessing processing = header.HeaderInfo.MustUnderstand ? HeaderProcessing.MustUnderstand : 0;
if ((header.HeaderProcessing & HeaderProcessing.Understood) != 0 || header.HeaderKind != HeaderKind.Unknown)
{
processing |= HeaderProcessing.Understood;
}
switch (header.HeaderType)
{
case HeaderType.BufferedMessageHeader:
AddHeader(new Header(header.HeaderKind, collection.CaptureBufferedHeader(collection._bufferedMessageData,
header.HeaderInfo, headerIndex), processing));
break;
case HeaderType.ReadableHeader:
AddHeader(new Header(header.HeaderKind, header.ReadableHeader, processing));
break;
case HeaderType.WriteableHeader:
AddHeader(new Header(header.HeaderKind, header.MessageHeader, processing));
break;
default:
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SRP.Format(SRP.InvalidEnumValue, header.HeaderType)));
}
}
public void CopyHeadersFrom(Message message)
{
if (message == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(message)));
}
CopyHeadersFrom(message.Headers);
}
public void CopyHeadersFrom(MessageHeaders collection)
{
if (collection == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(collection)));
}
for (int i = 0; i < collection._headerCount; i++)
{
CopyHeaderFrom(collection, i);
}
}
public void CopyTo(MessageHeaderInfo[] array, int index)
{
if (array == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(array));
}
if (index < 0 || (index + _headerCount) > array.Length)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
new ArgumentOutOfRangeException(nameof(index), index,
SRP.Format(SRP.ValueMustBeInRange, 0, array.Length - _headerCount)));
}
for (int i = 0; i < _headerCount; i++)
{
array[i + index] = _headers[i].HeaderInfo;
}
}
private Exception CreateDuplicateHeaderException(HeaderKind kind)
{
string name;
switch (kind)
{
case HeaderKind.Action:
name = AddressingStrings.Action;
break;
case HeaderKind.FaultTo:
name = AddressingStrings.FaultTo;
break;
case HeaderKind.From:
name = AddressingStrings.From;
break;
case HeaderKind.MessageId:
name = AddressingStrings.MessageId;
break;
case HeaderKind.ReplyTo:
name = AddressingStrings.ReplyTo;
break;
case HeaderKind.To:
name = AddressingStrings.To;
break;
default:
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SRP.Format(SRP.InvalidEnumValue, kind)));
}
return new MessageHeaderException(
SRP.Format(SRP.MultipleMessageHeaders, name, MessageVersion.Addressing.Namespace),
name,
MessageVersion.Addressing.Namespace,
true);
}
public int FindHeader(string name, string ns)
{
if (name == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(name)));
}
if (ns == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(ns)));
}
if (ns == MessageVersion.Addressing.Namespace)
{
return FindAddressingHeader(name, ns);
}
else
{
return FindNonAddressingHeader(name, ns, MessageVersion.Envelope.UltimateDestinationActorValues);
}
}
private int FindAddressingHeader(string name, string ns)
{
int foundAt = -1;
for (int i = 0; i < _headerCount; i++)
{
if (_headers[i].HeaderKind != HeaderKind.Unknown)
{
MessageHeaderInfo info = _headers[i].HeaderInfo;
if (info.Name == name && info.Namespace == ns)
{
if (foundAt >= 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
new MessageHeaderException(SRP.Format(SRP.MultipleMessageHeaders, name, ns), name, ns, true));
}
foundAt = i;
}
}
}
return foundAt;
}
private int FindNonAddressingHeader(string name, string ns, string[] actors)
{
int foundAt = -1;
for (int i = 0; i < _headerCount; i++)
{
if (_headers[i].HeaderKind == HeaderKind.Unknown)
{
MessageHeaderInfo info = _headers[i].HeaderInfo;
if (info.Name == name && info.Namespace == ns)
{
for (int j = 0; j < actors.Length; j++)
{
if (actors[j] == info.Actor)
{
if (foundAt >= 0)
{
if (actors.Length == 1)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageHeaderException(SRP.Format(SRP.MultipleMessageHeadersWithActor, name, ns, actors[0]), name, ns, true));
}
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageHeaderException(SRP.Format(SRP.MultipleMessageHeaders, name, ns), name, ns, true));
}
foundAt = i;
}
}
}
}
}
return foundAt;
}
public int FindHeader(string name, string ns, params string[] actors)
{
if (name == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(name)));
}
if (ns == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(ns)));
}
if (actors == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(actors)));
}
int foundAt = -1;
for (int i = 0; i < _headerCount; i++)
{
MessageHeaderInfo info = _headers[i].HeaderInfo;
if (info.Name == name && info.Namespace == ns)
{
for (int j = 0; j < actors.Length; j++)
{
if (actors[j] == info.Actor)
{
if (foundAt >= 0)
{
if (actors.Length == 1)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageHeaderException(SRP.Format(SRP.MultipleMessageHeadersWithActor, name, ns, actors[0]), name, ns, true));
}
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageHeaderException(SRP.Format(SRP.MultipleMessageHeaders, name, ns), name, ns, true));
}
foundAt = i;
}
}
}
}
return foundAt;
}
private int FindHeaderProperty(HeaderKind kind)
{
int index = -1;
for (int i = 0; i < _headerCount; i++)
{
if (_headers[i].HeaderKind == kind)
{
if (index >= 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateDuplicateHeaderException(kind));
}
index = i;
}
}
return index;
}
private int FindRelatesTo(Uri relationshipType, out UniqueId messageId)
{
UniqueId foundValue = null;
int foundIndex = -1;
for (int i = 0; i < _headerCount; i++)
{
if (_headers[i].HeaderKind == HeaderKind.RelatesTo)
{
Uri tempRelationship;
UniqueId tempValue;
GetRelatesToValues(i, out tempRelationship, out tempValue);
if (relationshipType == tempRelationship)
{
if (foundValue != null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
new MessageHeaderException(
SRP.Format(SRP.MultipleRelatesToHeaders, relationshipType.AbsoluteUri),
AddressingStrings.RelatesTo,
MessageVersion.Addressing.Namespace,
true));
}
foundValue = tempValue;
foundIndex = i;
}
}
}
messageId = foundValue;
return foundIndex;
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public IEnumerator<MessageHeaderInfo> GetEnumerator()
{
MessageHeaderInfo[] headers = new MessageHeaderInfo[_headerCount];
CopyTo(headers, 0);
return GetEnumerator(headers);
}
private IEnumerator<MessageHeaderInfo> GetEnumerator(MessageHeaderInfo[] headers)
{
IList<MessageHeaderInfo> list = new ReadOnlyCollection<MessageHeaderInfo>(headers);
return list.GetEnumerator();
}
internal IEnumerator<MessageHeaderInfo> GetUnderstoodEnumerator()
{
List<MessageHeaderInfo> understoodHeaders = new List<MessageHeaderInfo>();
for (int i = 0; i < _headerCount; i++)
{
if ((_headers[i].HeaderProcessing & HeaderProcessing.Understood) != 0)
{
understoodHeaders.Add(_headers[i].HeaderInfo);
}
}
return understoodHeaders.GetEnumerator();
}
private static XmlDictionaryReader GetBufferedMessageHeaderReaderAtHeaderContents(IBufferedMessageData bufferedMessageData)
{
XmlDictionaryReader reader = bufferedMessageData.GetMessageReader();
if (reader.NodeType == XmlNodeType.Element)
{
reader.Read();
}
else
{
reader.ReadStartElement();
}
if (reader.NodeType == XmlNodeType.Element)
{
reader.Read();
}
else
{
reader.ReadStartElement();
}
return reader;
}
private XmlDictionaryReader GetBufferedMessageHeaderReader(IBufferedMessageData bufferedMessageData, int bufferedMessageHeaderIndex)
{
// Check if we need to change representations
if (_nodeCount > MaxBufferedHeaderNodes || _attrCount > MaxBufferedHeaderAttributes)
{
CaptureBufferedHeaders();
return _headers[bufferedMessageHeaderIndex].ReadableHeader.GetHeaderReader();
}
XmlDictionaryReader reader = GetBufferedMessageHeaderReaderAtHeaderContents(bufferedMessageData);
for (; ; )
{
if (reader.NodeType != XmlNodeType.Element)
{
reader.MoveToContent();
}
if (bufferedMessageHeaderIndex == 0)
{
break;
}
Skip(reader);
bufferedMessageHeaderIndex--;
}
return reader;
}
private void Skip(XmlDictionaryReader reader)
{
if (reader.MoveToContent() == XmlNodeType.Element && !reader.IsEmptyElement)
{
int depth = reader.Depth;
do
{
_attrCount += reader.AttributeCount;
_nodeCount++;
} while (reader.Read() && depth < reader.Depth);
// consume end tag
if (reader.NodeType == XmlNodeType.EndElement)
{
_nodeCount++;
reader.Read();
}
}
else
{
_attrCount += reader.AttributeCount;
_nodeCount++;
reader.Read();
}
}
public T GetHeader<T>(string name, string ns)
{
return GetHeader<T>(name, ns, DataContractSerializerDefaults.CreateSerializer(typeof(T), name, ns, int.MaxValue/*maxItems*/));
}
public T GetHeader<T>(string name, string ns, params string[] actors)
{
int index = FindHeader(name, ns, actors);
if (index < 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageHeaderException(SRP.Format(SRP.HeaderNotFound, name, ns), name, ns));
}
return GetHeader<T>(index);
}
public T GetHeader<T>(string name, string ns, XmlObjectSerializer serializer)
{
if (serializer == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(serializer)));
}
int index = FindHeader(name, ns);
if (index < 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageHeaderException(SRP.Format(SRP.HeaderNotFound, name, ns), name, ns));
}
return GetHeader<T>(index, serializer);
}
public T GetHeader<T>(int index)
{
if (index < 0 || index >= _headerCount)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
new ArgumentOutOfRangeException(nameof(index), index,
SRP.Format(SRP.ValueMustBeInRange, 0, _headerCount)));
}
MessageHeaderInfo headerInfo = _headers[index].HeaderInfo;
return GetHeader<T>(index, DataContractSerializerDefaults.CreateSerializer(typeof(T), headerInfo.Name, headerInfo.Namespace, int.MaxValue/*maxItems*/));
}
public T GetHeader<T>(int index, XmlObjectSerializer serializer)
{
if (serializer == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(serializer)));
}
using (XmlDictionaryReader reader = GetReaderAtHeader(index))
{
return (T)serializer.ReadObject(reader);
}
}
private HeaderKind GetHeaderKind(MessageHeaderInfo headerInfo)
{
HeaderKind headerKind = HeaderKind.Unknown;
if (headerInfo.Namespace == MessageVersion.Addressing.Namespace)
{
if (MessageVersion.Envelope.IsUltimateDestinationActor(headerInfo.Actor))
{
string name = headerInfo.Name;
if (name.Length > 0)
{
switch (name[0])
{
case 'A':
if (name == AddressingStrings.Action)
{
headerKind = HeaderKind.Action;
}
break;
case 'F':
if (name == AddressingStrings.From)
{
headerKind = HeaderKind.From;
}
else if (name == AddressingStrings.FaultTo)
{
headerKind = HeaderKind.FaultTo;
}
break;
case 'M':
if (name == AddressingStrings.MessageId)
{
headerKind = HeaderKind.MessageId;
}
break;
case 'R':
if (name == AddressingStrings.ReplyTo)
{
headerKind = HeaderKind.ReplyTo;
}
else if (name == AddressingStrings.RelatesTo)
{
headerKind = HeaderKind.RelatesTo;
}
break;
case 'T':
if (name == AddressingStrings.To)
{
headerKind = HeaderKind.To;
}
break;
}
}
}
}
ValidateHeaderKind(headerKind);
return headerKind;
}
private void ValidateHeaderKind(HeaderKind headerKind)
{
if (MessageVersion.Envelope == EnvelopeVersion.None)
{
if (headerKind != HeaderKind.Action && headerKind != HeaderKind.To)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
new InvalidOperationException(SRP.Format(SRP.HeadersCannotBeAddedToEnvelopeVersion, MessageVersion.Envelope)));
}
}
if (MessageVersion.Addressing == AddressingVersion.None)
{
if (headerKind != HeaderKind.Unknown && headerKind != HeaderKind.Action && headerKind != HeaderKind.To)
{
string message = SRP.Format(SRP.AddressingHeadersCannotBeAddedToAddressingVersion, MessageVersion.Addressing);
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
new InvalidOperationException(message, new ProtocolException(message)));
}
}
}
public XmlDictionaryReader GetReaderAtHeader(int headerIndex)
{
if (headerIndex < 0 || headerIndex >= _headerCount)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
new ArgumentOutOfRangeException(nameof(headerIndex), headerIndex,
SRP.Format(SRP.ValueMustBeInRange, 0, _headerCount)));
}
switch (_headers[headerIndex].HeaderType)
{
case HeaderType.ReadableHeader:
return _headers[headerIndex].ReadableHeader.GetHeaderReader();
case HeaderType.WriteableHeader:
MessageHeader writeableHeader = _headers[headerIndex].MessageHeader;
BufferedHeader bufferedHeader = CaptureWriteableHeader(writeableHeader);
_headers[headerIndex] = new Header(_headers[headerIndex].HeaderKind, bufferedHeader, _headers[headerIndex].HeaderProcessing);
CollectionVersion++;
return bufferedHeader.GetHeaderReader();
case HeaderType.BufferedMessageHeader:
return GetBufferedMessageHeaderReader(_bufferedMessageData, headerIndex);
default:
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SRP.Format(SRP.InvalidEnumValue, _headers[headerIndex].HeaderType)));
}
}
internal UniqueId GetRelatesTo(Uri relationshipType)
{
if (relationshipType == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(relationshipType)));
}
UniqueId messageId;
FindRelatesTo(relationshipType, out messageId);
return messageId;
}
private void GetRelatesToValues(int index, out Uri relationshipType, out UniqueId messageId)
{
RelatesToHeader relatesToHeader = _headers[index].HeaderInfo as RelatesToHeader;
if (relatesToHeader != null)
{
relationshipType = relatesToHeader.RelationshipType;
messageId = relatesToHeader.UniqueId;
}
else
{
using (XmlDictionaryReader reader = GetReaderAtHeader(index))
{
RelatesToHeader.ReadHeaderValue(reader, MessageVersion.Addressing, out relationshipType, out messageId);
}
}
}
internal string[] GetHeaderAttributes(string localName, string ns)
{
string[] attrs = null;
if (ContainsOnlyBufferedMessageHeaders)
{
XmlDictionaryReader reader = _bufferedMessageData.GetMessageReader();
reader.ReadStartElement(); // Envelope
reader.ReadStartElement(); // Header
for (int index = 0; reader.IsStartElement(); index++)
{
string value = reader.GetAttribute(localName, ns);
if (value != null)
{
if (attrs == null)
{
attrs = new string[_headerCount];
}
attrs[index] = value;
}
if (index == _headerCount - 1)
{
break;
}
reader.Skip();
}
reader.Dispose();
}
else
{
for (int index = 0; index < _headerCount; index++)
{
if (_headers[index].HeaderType != HeaderType.WriteableHeader)
{
using (XmlDictionaryReader reader = GetReaderAtHeader(index))
{
string value = reader.GetAttribute(localName, ns);
if (value != null)
{
if (attrs == null)
{
attrs = new string[_headerCount];
}
attrs[index] = value;
}
}
}
}
}
return attrs;
}
internal MessageHeader GetMessageHeader(int index)
{
if (index < 0 || index >= _headerCount)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
new ArgumentOutOfRangeException(nameof(index), index,
SRP.Format(SRP.ValueMustBeInRange, 0, _headerCount)));
}
MessageHeader messageHeader;
switch (_headers[index].HeaderType)
{
case HeaderType.WriteableHeader:
case HeaderType.ReadableHeader:
return _headers[index].MessageHeader;
case HeaderType.BufferedMessageHeader:
messageHeader = CaptureBufferedHeader(_bufferedMessageData, _headers[index].HeaderInfo, index);
_headers[index] = new Header(_headers[index].HeaderKind, messageHeader, _headers[index].HeaderProcessing);
CollectionVersion++;
return messageHeader;
default:
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SRP.Format(SRP.InvalidEnumValue, _headers[index].HeaderType)));
}
}
internal Collection<MessageHeaderInfo> GetHeadersNotUnderstood()
{
Collection<MessageHeaderInfo> notUnderstoodHeaders = null;
for (int headerIndex = 0; headerIndex < _headerCount; headerIndex++)
{
if (_headers[headerIndex].HeaderProcessing == HeaderProcessing.MustUnderstand)
{
if (notUnderstoodHeaders == null)
{
notUnderstoodHeaders = new Collection<MessageHeaderInfo>();
}
MessageHeaderInfo headerInfo = _headers[headerIndex].HeaderInfo;
notUnderstoodHeaders.Add(headerInfo);
}
}
return notUnderstoodHeaders;
}
public bool HaveMandatoryHeadersBeenUnderstood()
{
return HaveMandatoryHeadersBeenUnderstood(MessageVersion.Envelope.MustUnderstandActorValues);
}
public bool HaveMandatoryHeadersBeenUnderstood(params string[] actors)
{
if (actors == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(actors)));
}
for (int headerIndex = 0; headerIndex < _headerCount; headerIndex++)
{
if (_headers[headerIndex].HeaderProcessing == HeaderProcessing.MustUnderstand)
{
for (int actorIndex = 0; actorIndex < actors.Length; ++actorIndex)
{
if (_headers[headerIndex].HeaderInfo.Actor == actors[actorIndex])
{
return false;
}
}
}
}
return true;
}
internal void Init(MessageVersion version, int initialSize)
{
_nodeCount = 0;
_attrCount = 0;
if (initialSize < 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
new ArgumentOutOfRangeException(nameof(initialSize), initialSize,
SRP.ValueMustBeNonNegative));
}
MessageVersion = version ?? throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(version));
_headers = new Header[initialSize];
}
internal void Init(MessageVersion version)
{
_nodeCount = 0;
_attrCount = 0;
MessageVersion = version;
CollectionVersion = 0;
}
internal void Init(MessageVersion version, XmlDictionaryReader reader, IBufferedMessageData bufferedMessageData, RecycledMessageState recycledMessageState, bool[] understoodHeaders, bool understoodHeadersModified)
{
_nodeCount = 0;
_attrCount = 0;
MessageVersion = version;
_bufferedMessageData = bufferedMessageData;
if (version.Envelope != EnvelopeVersion.None)
{
_understoodHeadersModified = (understoodHeaders != null) && understoodHeadersModified;
if (reader.IsEmptyElement)
{
reader.Read();
return;
}
EnvelopeVersion envelopeVersion = version.Envelope;
Fx.Assert(reader.IsStartElement(XD.MessageDictionary.Header, envelopeVersion.DictionaryNamespace), "");
reader.ReadStartElement();
AddressingDictionary dictionary = XD.AddressingDictionary;
if (s_localNames == null)
{
XmlDictionaryString[] strings = new XmlDictionaryString[7];
strings[(int)HeaderKind.To] = dictionary.To;
strings[(int)HeaderKind.Action] = dictionary.Action;
strings[(int)HeaderKind.MessageId] = dictionary.MessageId;
strings[(int)HeaderKind.RelatesTo] = dictionary.RelatesTo;
strings[(int)HeaderKind.ReplyTo] = dictionary.ReplyTo;
strings[(int)HeaderKind.From] = dictionary.From;
strings[(int)HeaderKind.FaultTo] = dictionary.FaultTo;
Interlocked.MemoryBarrier();
s_localNames = strings;
}
int i = 0;
while (reader.IsStartElement())
{
ReadBufferedHeader(reader, recycledMessageState, s_localNames, (understoodHeaders == null) ? false : understoodHeaders[i++]);
}
reader.ReadEndElement();
}
CollectionVersion = 0;
}
public void Insert(int headerIndex, MessageHeader header)
{
if (header == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(header)));
}
if (!header.IsMessageVersionSupported(MessageVersion))
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SRP.Format(SRP.MessageHeaderVersionNotSupported,
header.GetType().FullName, MessageVersion.Envelope.ToString()), "header"));
}
Insert(headerIndex, header, GetHeaderKind(header));
}
private void Insert(int headerIndex, MessageHeader header, HeaderKind kind)
{
ReadableMessageHeader readableMessageHeader = header as ReadableMessageHeader;
HeaderProcessing processing = header.MustUnderstand ? HeaderProcessing.MustUnderstand : 0;
if (kind != HeaderKind.Unknown)
{
processing |= HeaderProcessing.Understood;
}
if (readableMessageHeader != null)
{
InsertHeader(headerIndex, new Header(kind, readableMessageHeader, processing));
}
else
{
InsertHeader(headerIndex, new Header(kind, header, processing));
}
}
private void InsertHeader(int headerIndex, Header header)
{
ValidateHeaderKind(header.HeaderKind);
if (headerIndex < 0 || headerIndex > _headerCount)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
new ArgumentOutOfRangeException(nameof(headerIndex), headerIndex,
SRP.Format(SRP.ValueMustBeInRange, 0, _headerCount)));
}
if (_headerCount == _headers.Length)
{
if (_headers.Length == 0)
{
_headers = new Header[1];
}
else
{
Header[] newHeaders = new Header[_headers.Length * 2];
_headers.CopyTo(newHeaders, 0);
_headers = newHeaders;
}
}
if (headerIndex < _headerCount)
{
if (_bufferedMessageData != null)
{
for (int i = headerIndex; i < _headerCount; i++)
{
if (_headers[i].HeaderType == HeaderType.BufferedMessageHeader)
{
CaptureBufferedHeaders();
break;
}
}
}
Array.Copy(_headers, headerIndex, _headers, headerIndex + 1, _headerCount - headerIndex);
}
_headers[headerIndex] = header;
_headerCount++;
CollectionVersion++;
}
internal bool IsUnderstood(int i)
{
return (_headers[i].HeaderProcessing & HeaderProcessing.Understood) != 0;
}
internal bool IsUnderstood(MessageHeaderInfo headerInfo)
{
if (headerInfo == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(headerInfo)));
}
for (int i = 0; i < _headerCount; i++)
{
if ((object)_headers[i].HeaderInfo == (object)headerInfo)
{
if (IsUnderstood(i))
{
return true;
}
}
}
return false;
}
private void ReadBufferedHeader(XmlDictionaryReader reader, RecycledMessageState recycledMessageState, XmlDictionaryString[] localNames, bool understood)
{
string actor;
bool mustUnderstand;
bool relay;
bool isRefParam;
if (MessageVersion.Addressing == AddressingVersion.None && reader.NamespaceURI == AddressingVersion.None.Namespace)
{
string message = SRP.Format(SRP.AddressingHeadersCannotBeAddedToAddressingVersion, MessageVersion.Addressing);
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
new InvalidOperationException(message, new ProtocolException(message)));
}
MessageHeader.GetHeaderAttributes(reader, MessageVersion, out actor, out mustUnderstand, out relay, out isRefParam);
HeaderKind kind = HeaderKind.Unknown;
MessageHeaderInfo info = null;
if (MessageVersion.Envelope.IsUltimateDestinationActor(actor))
{
Fx.Assert(MessageVersion.Addressing.DictionaryNamespace != null, "non-None Addressing requires a non-null DictionaryNamespace");
kind = (HeaderKind)reader.IndexOfLocalName(localNames, MessageVersion.Addressing.DictionaryNamespace);
switch (kind)
{
case HeaderKind.To:
info = ToHeader.ReadHeader(reader, MessageVersion.Addressing, recycledMessageState.UriCache, actor, mustUnderstand, relay);
break;
case HeaderKind.Action:
info = ActionHeader.ReadHeader(reader, MessageVersion.Addressing, actor, mustUnderstand, relay);
break;
case HeaderKind.MessageId:
info = MessageIDHeader.ReadHeader(reader, MessageVersion.Addressing, actor, mustUnderstand, relay);
break;
case HeaderKind.RelatesTo:
info = RelatesToHeader.ReadHeader(reader, MessageVersion.Addressing, actor, mustUnderstand, relay);
break;
case HeaderKind.ReplyTo:
info = ReplyToHeader.ReadHeader(reader, MessageVersion.Addressing, actor, mustUnderstand, relay);
break;
case HeaderKind.From:
info = FromHeader.ReadHeader(reader, MessageVersion.Addressing, actor, mustUnderstand, relay);
break;
case HeaderKind.FaultTo:
info = FaultToHeader.ReadHeader(reader, MessageVersion.Addressing, actor, mustUnderstand, relay);
break;
default:
kind = HeaderKind.Unknown;
break;
}
}
if (info == null)
{
info = recycledMessageState.HeaderInfoCache.TakeHeaderInfo(reader, actor, mustUnderstand, relay, isRefParam);
reader.Skip();
}
HeaderProcessing processing = mustUnderstand ? HeaderProcessing.MustUnderstand : 0;
if (kind != HeaderKind.Unknown || understood)
{
processing |= HeaderProcessing.Understood;
MessageHeaders.TraceUnderstood(info);
}
AddHeader(new Header(kind, info, processing));
}
internal void Recycle(HeaderInfoCache headerInfoCache)
{
for (int i = 0; i < _headerCount; i++)
{
if (_headers[i].HeaderKind == HeaderKind.Unknown)
{
headerInfoCache.ReturnHeaderInfo(_headers[i].HeaderInfo);
}
}
Clear();
CollectionVersion = 0;
if (_understoodHeaders != null)
{
_understoodHeaders.Modified = false;
}
}
internal void RemoveUnderstood(MessageHeaderInfo headerInfo)
{
if (headerInfo == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(headerInfo)));
}
for (int i = 0; i < _headerCount; i++)
{
if ((object)_headers[i].HeaderInfo == (object)headerInfo)
{
if ((_headers[i].HeaderProcessing & HeaderProcessing.Understood) == 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(
SRP.Format(SRP.HeaderAlreadyNotUnderstood, headerInfo.Name, headerInfo.Namespace), "headerInfo"));
}
_headers[i].HeaderProcessing &= ~HeaderProcessing.Understood;
}
}
}
public void RemoveAll(string name, string ns)
{
if (name == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(name)));
}
if (ns == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(ns)));
}
for (int i = _headerCount - 1; i >= 0; i--)
{
MessageHeaderInfo info = _headers[i].HeaderInfo;
if (info.Name == name && info.Namespace == ns)
{
RemoveAt(i);
}
}
}
public void RemoveAt(int headerIndex)
{
if (headerIndex < 0 || headerIndex >= _headerCount)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
new ArgumentOutOfRangeException(nameof(headerIndex), headerIndex,
SRP.Format(SRP.ValueMustBeInRange, 0, _headerCount)));
}
if (_bufferedMessageData != null && _headers[headerIndex].HeaderType == HeaderType.BufferedMessageHeader)
{
CaptureBufferedHeaders(headerIndex);
}
Array.Copy(_headers, headerIndex + 1, _headers, headerIndex, _headerCount - headerIndex - 1);
_headers[--_headerCount] = new Header();
CollectionVersion++;
}
internal void ReplaceAt(int headerIndex, MessageHeader header)
{
if (headerIndex < 0 || headerIndex >= _headerCount)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
new ArgumentOutOfRangeException(nameof(headerIndex), headerIndex,
SRP.Format(SRP.ValueMustBeInRange, 0, _headerCount)));
}
if (header == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(header));
}
ReplaceAt(headerIndex, header, GetHeaderKind(header));
}
private void ReplaceAt(int headerIndex, MessageHeader header, HeaderKind kind)
{
HeaderProcessing processing = header.MustUnderstand ? HeaderProcessing.MustUnderstand : 0;
if (kind != HeaderKind.Unknown)
{
processing |= HeaderProcessing.Understood;
}
ReadableMessageHeader readableMessageHeader = header as ReadableMessageHeader;
if (readableMessageHeader != null)
{
_headers[headerIndex] = new Header(kind, readableMessageHeader, processing);
}
else
{
_headers[headerIndex] = new Header(kind, header, processing);
}
CollectionVersion++;
}
public void SetAction(XmlDictionaryString action)
{
if (action == null)
{
SetHeaderProperty(HeaderKind.Action, null);
}
else
{
SetActionHeader(ActionHeader.Create(action, MessageVersion.Addressing));
}
}
internal void SetActionHeader(ActionHeader actionHeader)
{
SetHeaderProperty(HeaderKind.Action, actionHeader);
}
internal void SetFaultToHeader(FaultToHeader faultToHeader)
{
SetHeaderProperty(HeaderKind.FaultTo, faultToHeader);
}
internal void SetFromHeader(FromHeader fromHeader)
{
SetHeaderProperty(HeaderKind.From, fromHeader);
}
internal void SetMessageIDHeader(MessageIDHeader messageIDHeader)
{
SetHeaderProperty(HeaderKind.MessageId, messageIDHeader);
}
internal void SetRelatesTo(Uri relationshipType, UniqueId messageId)
{
if (relationshipType == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(relationshipType));
}
RelatesToHeader relatesToHeader;
if (!object.ReferenceEquals(messageId, null))
{
relatesToHeader = RelatesToHeader.Create(messageId, MessageVersion.Addressing, relationshipType);
}
else
{
relatesToHeader = null;
}
SetRelatesTo(RelatesToHeader.ReplyRelationshipType, relatesToHeader);
}
private void SetRelatesTo(Uri relationshipType, RelatesToHeader relatesToHeader)
{
UniqueId previousUniqueId;
int index = FindRelatesTo(relationshipType, out previousUniqueId);
if (index >= 0)
{
if (relatesToHeader == null)
{
RemoveAt(index);
}
else
{
ReplaceAt(index, relatesToHeader, HeaderKind.RelatesTo);
}
}
else if (relatesToHeader != null)
{
Add(relatesToHeader, HeaderKind.RelatesTo);
}
}
internal void SetReplyToHeader(ReplyToHeader replyToHeader)
{
SetHeaderProperty(HeaderKind.ReplyTo, replyToHeader);
}
internal void SetToHeader(ToHeader toHeader)
{
SetHeaderProperty(HeaderKind.To, toHeader);
}
private void SetHeaderProperty(HeaderKind kind, MessageHeader header)
{
int index = FindHeaderProperty(kind);
if (index >= 0)
{
if (header == null)
{
RemoveAt(index);
}
else
{
ReplaceAt(index, header, kind);
}
}
else if (header != null)
{
Add(header, kind);
}
}
public void WriteHeader(int headerIndex, XmlWriter writer)
{
WriteHeader(headerIndex, XmlDictionaryWriter.CreateDictionaryWriter(writer));
}
public void WriteHeader(int headerIndex, XmlDictionaryWriter writer)
{
WriteStartHeader(headerIndex, writer);
WriteHeaderContents(headerIndex, writer);
writer.WriteEndElement();
}
public void WriteStartHeader(int headerIndex, XmlWriter writer)
{
WriteStartHeader(headerIndex, XmlDictionaryWriter.CreateDictionaryWriter(writer));
}
public void WriteStartHeader(int headerIndex, XmlDictionaryWriter writer)
{
if (writer == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(writer));
}
if (headerIndex < 0 || headerIndex >= _headerCount)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
new ArgumentOutOfRangeException(nameof(headerIndex), headerIndex,
SRP.Format(SRP.ValueMustBeInRange, 0, _headerCount)));
}
switch (_headers[headerIndex].HeaderType)
{
case HeaderType.ReadableHeader:
case HeaderType.WriteableHeader:
_headers[headerIndex].MessageHeader.WriteStartHeader(writer, MessageVersion);
break;
case HeaderType.BufferedMessageHeader:
WriteStartBufferedMessageHeader(_bufferedMessageData, headerIndex, writer);
break;
default:
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SRP.Format(SRP.InvalidEnumValue, _headers[headerIndex].HeaderType)));
}
}
public void WriteHeaderContents(int headerIndex, XmlWriter writer)
{
WriteHeaderContents(headerIndex, XmlDictionaryWriter.CreateDictionaryWriter(writer));
}
public void WriteHeaderContents(int headerIndex, XmlDictionaryWriter writer)
{
if (writer == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(writer));
}
if (headerIndex < 0 || headerIndex >= _headerCount)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
new ArgumentOutOfRangeException(nameof(headerIndex), headerIndex,
SRP.Format(SRP.ValueMustBeInRange, 0, _headerCount)));
}
switch (_headers[headerIndex].HeaderType)
{
case HeaderType.ReadableHeader:
case HeaderType.WriteableHeader:
_headers[headerIndex].MessageHeader.WriteHeaderContents(writer, MessageVersion);
break;
case HeaderType.BufferedMessageHeader:
WriteBufferedMessageHeaderContents(_bufferedMessageData, headerIndex, writer);
break;
default:
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SRP.Format(SRP.InvalidEnumValue, _headers[headerIndex].HeaderType)));
}
}
private static void TraceUnderstood(MessageHeaderInfo info)
{
}
private void WriteBufferedMessageHeader(IBufferedMessageData bufferedMessageData, int bufferedMessageHeaderIndex, XmlWriter writer)
{
using (XmlReader reader = GetBufferedMessageHeaderReader(bufferedMessageData, bufferedMessageHeaderIndex))
{
writer.WriteNode(reader, false);
}
}
private void WriteStartBufferedMessageHeader(IBufferedMessageData bufferedMessageData, int bufferedMessageHeaderIndex, XmlWriter writer)
{
using (XmlReader reader = GetBufferedMessageHeaderReader(bufferedMessageData, bufferedMessageHeaderIndex))
{
writer.WriteStartElement(reader.Prefix, reader.LocalName, reader.NamespaceURI);
writer.WriteAttributes(reader, false);
}
}
private void WriteBufferedMessageHeaderContents(IBufferedMessageData bufferedMessageData, int bufferedMessageHeaderIndex, XmlWriter writer)
{
using (XmlReader reader = GetBufferedMessageHeaderReader(bufferedMessageData, bufferedMessageHeaderIndex))
{
if (!reader.IsEmptyElement)
{
reader.ReadStartElement();
while (reader.NodeType != XmlNodeType.EndElement)
{
writer.WriteNode(reader, false);
}
reader.ReadEndElement();
}
}
}
internal enum HeaderType : byte
{
Invalid,
ReadableHeader,
BufferedMessageHeader,
WriteableHeader
}
internal enum HeaderKind : byte
{
Action,
FaultTo,
From,
MessageId,
ReplyTo,
RelatesTo,
To,
Unknown,
}
[Flags]
internal enum HeaderProcessing : byte
{
MustUnderstand = 0x1,
Understood = 0x2,
}
internal struct Header
{
private MessageHeaderInfo _info;
public Header(HeaderKind kind, MessageHeaderInfo info, HeaderProcessing processing)
{
HeaderKind = kind;
HeaderType = HeaderType.BufferedMessageHeader;
_info = info;
HeaderProcessing = processing;
}
public Header(HeaderKind kind, ReadableMessageHeader readableHeader, HeaderProcessing processing)
{
HeaderKind = kind;
HeaderType = HeaderType.ReadableHeader;
_info = readableHeader;
HeaderProcessing = processing;
}
public Header(HeaderKind kind, MessageHeader header, HeaderProcessing processing)
{
HeaderKind = kind;
HeaderType = HeaderType.WriteableHeader;
_info = header;
HeaderProcessing = processing;
}
public HeaderType HeaderType { get; }
public HeaderKind HeaderKind { get; }
public MessageHeaderInfo HeaderInfo
{
get { return _info; }
}
public MessageHeader MessageHeader
{
get
{
Fx.Assert(HeaderType == HeaderType.WriteableHeader || HeaderType == HeaderType.ReadableHeader, "");
return (MessageHeader)_info;
}
}
public HeaderProcessing HeaderProcessing { get; set; }
public ReadableMessageHeader ReadableHeader
{
get
{
Fx.Assert(HeaderType == HeaderType.ReadableHeader, "");
return (ReadableMessageHeader)_info;
}
}
}
}
}
|