| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356 |
- //-----------------------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //-----------------------------------------------------------------------------
- namespace System.ServiceModel.Dispatcher
- {
- using System;
- using System.Collections.Generic;
- using System.Globalization;
- using System.Runtime;
- using System.ServiceModel;
- using System.ServiceModel.Channels;
- using System.Text;
- using System.Xml;
- using System.Xml.Schema;
- class EndpointAddressProcessor
- {
- internal static readonly QNameKeyComparer QNameComparer = new QNameKeyComparer();
- // QName Attributes
- internal static readonly string XsiNs = XmlSchema.InstanceNamespace;
- internal const string SerNs = "http://schemas.microsoft.com/2003/10/Serialization/";
- internal const string TypeLN = "type";
- internal const string ItemTypeLN = "ItemType";
- internal const string FactoryTypeLN = "FactoryType";
- // Pooling
- internal EndpointAddressProcessor next;
- StringBuilder builder;
- byte[] resultData;
- internal EndpointAddressProcessor(int length)
- {
- this.builder = new StringBuilder();
- this.resultData = new byte[length];
- }
- internal EndpointAddressProcessor Next
- {
- get
- {
- return this.next;
- }
- set
- {
- this.next = value;
- }
- }
- internal static string GetComparableForm(StringBuilder builder, XmlReader reader)
- {
- List<Attr> attrSet = new List<Attr>();
- int valueLength = -1;
- while (!reader.EOF)
- {
- XmlNodeType type = reader.MoveToContent();
- switch (type)
- {
- case XmlNodeType.Element:
- CompleteValue(builder, valueLength);
- valueLength = -1;
- builder.Append("<");
- AppendString(builder, reader.LocalName);
- builder.Append(":");
- AppendString(builder, reader.NamespaceURI);
- builder.Append(" ");
- // Scan attributes
- attrSet.Clear();
- if (reader.MoveToFirstAttribute())
- {
- do
- {
- // Ignore namespaces
- if (reader.Prefix == "xmlns" || reader.Name == "xmlns")
- {
- continue;
- }
- if (reader.LocalName == AddressingStrings.IsReferenceParameter && reader.NamespaceURI == Addressing10Strings.Namespace)
- {
- continue; // ignore IsReferenceParameter
- }
- string val = reader.Value;
- if ((reader.LocalName == TypeLN && reader.NamespaceURI == XsiNs) ||
- (reader.NamespaceURI == SerNs && (reader.LocalName == ItemTypeLN || reader.LocalName == FactoryTypeLN)))
- {
- string local, ns;
- XmlUtil.ParseQName(reader, val, out local, out ns);
- val = local + "^" + local.Length.ToString(CultureInfo.InvariantCulture) + ":" + ns + "^" + ns.Length.ToString(CultureInfo.InvariantCulture);
- }
- else if (reader.LocalName == XD.UtilityDictionary.IdAttribute.Value && reader.NamespaceURI == XD.UtilityDictionary.Namespace.Value)
- {
- // ignore wsu:Id attributes added by security to sign the header
- continue;
- }
- attrSet.Add(new Attr(reader.LocalName, reader.NamespaceURI, val));
- } while (reader.MoveToNextAttribute());
- }
- reader.MoveToElement();
- if (attrSet.Count > 0)
- {
- attrSet.Sort();
- for (int i = 0; i < attrSet.Count; ++i)
- {
- Attr a = attrSet[i];
- AppendString(builder, a.local);
- builder.Append(":");
- AppendString(builder, a.ns);
- builder.Append("=\"");
- AppendString(builder, a.val);
- builder.Append("\" ");
- }
- }
- if (reader.IsEmptyElement)
- builder.Append("></>"); // Should be the same as an empty tag.
- else
- builder.Append(">");
- break;
- case XmlNodeType.EndElement:
- CompleteValue(builder, valueLength);
- valueLength = -1;
- builder.Append("</>");
- break;
- // Need to escape CDATA values
- case XmlNodeType.CDATA:
- CompleteValue(builder, valueLength);
- valueLength = -1;
- builder.Append("<![CDATA[");
- AppendString(builder, reader.Value);
- builder.Append("]]>");
- break;
- case XmlNodeType.SignificantWhitespace:
- case XmlNodeType.Text:
- if (valueLength < 0)
- valueLength = builder.Length;
- builder.Append(reader.Value);
- break;
- default:
- // Do nothing
- break;
- }
- reader.Read();
- }
- return builder.ToString();
- }
- static void AppendString(StringBuilder builder, string s)
- {
- builder.Append(s);
- builder.Append("^");
- builder.Append(s.Length.ToString(CultureInfo.InvariantCulture));
- }
- static void CompleteValue(StringBuilder builder, int startLength)
- {
- if (startLength < 0)
- return;
- int len = builder.Length - startLength;
- builder.Append("^");
- builder.Append(len.ToString(CultureInfo.InvariantCulture));
- }
- internal void Clear(int length)
- {
- if (this.resultData.Length == length)
- {
- Array.Clear(this.resultData, 0, this.resultData.Length);
- }
- else
- {
- this.resultData = new byte[length];
- }
- }
- internal void ProcessHeaders(Message msg, Dictionary<QName, int> qnameLookup, Dictionary<string, HeaderBit[]> headerLookup)
- {
- string key;
- HeaderBit[] bits;
- QName qname;
- MessageHeaders headers = msg.Headers;
- for (int j = 0; j < headers.Count; ++j)
- {
- qname.name = headers[j].Name;
- qname.ns = headers[j].Namespace;
- if (headers.MessageVersion.Addressing == AddressingVersion.WSAddressing10
- && !headers[j].IsReferenceParameter)
- {
- continue;
- }
- if (qnameLookup.ContainsKey(qname))
- {
- builder.Remove(0, builder.Length);
- XmlReader reader = headers.GetReaderAtHeader(j).ReadSubtree();
- reader.Read(); // Needed after call to ReadSubtree
- key = GetComparableForm(builder, reader);
- if (headerLookup.TryGetValue(key, out bits))
- {
- SetBit(bits);
- }
- }
- }
- }
- internal void SetBit(HeaderBit[] bits)
- {
- if (bits.Length == 1)
- {
- this.resultData[bits[0].index] |= bits[0].mask;
- }
- else
- {
- byte[] results = this.resultData;
- for (int i = 0; i < bits.Length; ++i)
- {
- if ((results[bits[i].index] & bits[i].mask) == 0)
- {
- results[bits[i].index] |= bits[i].mask;
- break;
- }
- }
- }
- }
- internal bool TestExact(byte[] exact)
- {
- Fx.Assert(this.resultData.Length == exact.Length, "");
- byte[] results = this.resultData;
- for (int i = 0; i < exact.Length; ++i)
- {
- if (results[i] != exact[i])
- {
- return false;
- }
- }
- return true;
- }
- internal bool TestMask(byte[] mask)
- {
- if (mask == null)
- {
- return true;
- }
- byte[] results = this.resultData;
- for (int i = 0; i < mask.Length; ++i)
- {
- if ((results[i] & mask[i]) != mask[i])
- {
- return false;
- }
- }
- return true;
- }
- internal struct QName
- {
- internal string name;
- internal string ns;
- }
- internal class QNameKeyComparer : IComparer<QName>, IEqualityComparer<QName>
- {
- internal QNameKeyComparer()
- {
- }
- public int Compare(QName x, QName y)
- {
- int i = string.CompareOrdinal(x.name, y.name);
- if (i != 0)
- return i;
- return string.CompareOrdinal(x.ns, y.ns);
- }
- public bool Equals(QName x, QName y)
- {
- int i = string.CompareOrdinal(x.name, y.name);
- if (i != 0)
- return false;
- return string.CompareOrdinal(x.ns, y.ns) == 0;
- }
- public int GetHashCode(QName obj)
- {
- return obj.name.GetHashCode() ^ obj.ns.GetHashCode();
- }
- }
- internal struct HeaderBit
- {
- internal int index;
- internal byte mask;
- internal HeaderBit(int bitNum)
- {
- this.index = bitNum / 8;
- this.mask = (byte)(1 << (bitNum % 8));
- }
- internal void AddToMask(ref byte[] mask)
- {
- if (mask == null)
- {
- mask = new byte[this.index + 1];
- }
- else if (mask.Length <= this.index)
- {
- Array.Resize(ref mask, this.index + 1);
- }
- mask[this.index] |= this.mask;
- }
- }
- class Attr : IComparable<Attr>
- {
- internal string local;
- internal string ns;
- internal string val;
- string key;
- internal Attr(string l, string ns, string v)
- {
- this.local = l;
- this.ns = ns;
- this.val = v;
- this.key = ns + ":" + l;
- }
- public int CompareTo(Attr a)
- {
- return string.Compare(this.key, a.key, StringComparison.Ordinal);
- }
- }
- }
- }
|