< Summary - CoreWCF Coverage — PR #1766

Information
Class: CoreWCF.Channels.XmlObjectSerializerBodyWriter
Assembly: CoreWCF.Primitives
File(s): /home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/Channels/Message.cs
Line coverage
100%
Covered lines: 9
Uncovered lines: 0
Coverable lines: 9
Total lines: 2262
Line coverage: 100%
Branch coverage
N/A
Covered branches: 0
Total branches: 0
Branch coverage: N/A
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.ctor(...)100%11100%
OnWriteBodyContents(...)100%11100%

File(s)

/home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/Channels/Message.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System;
 5using System.Collections.Generic;
 6using System.Globalization;
 7using System.IO;
 8using System.Runtime.Serialization;
 9using System.Threading.Tasks;
 10using System.Xml;
 11using CoreWCF.Diagnostics;
 12using CoreWCF.Dispatcher;
 13using CoreWCF.Runtime;
 14using CoreWCF.Xml;
 15
 16namespace CoreWCF.Channels
 17{
 18    public abstract class Message : System.IDisposable
 19    {
 20        //SeekableMessageNavigator messageNavigator;
 21        internal const int InitialBufferSize = 1024;
 22
 23        public abstract MessageHeaders Headers { get; } // must never return null
 24
 25        protected bool IsDisposed
 26        {
 27            get { return State == MessageState.Closed; }
 28        }
 29
 30        public virtual bool IsFault
 31        {
 32            get
 33            {
 34                if (IsDisposed)
 35                {
 36                    throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
 37                }
 38
 39                return false;
 40            }
 41        }
 42
 43        public virtual bool IsEmpty
 44        {
 45            get
 46            {
 47                if (IsDisposed)
 48                {
 49                    throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
 50                }
 51
 52                return false;
 53            }
 54        }
 55
 56        public abstract MessageProperties Properties { get; }
 57
 58        public abstract MessageVersion Version { get; } // must never return null
 59
 60        public virtual RecycledMessageState RecycledMessageState
 61        {
 62            get { return null; }
 63        }
 64
 65        public MessageState State { get; private set; }
 66
 67        internal void BodyToString(XmlDictionaryWriter writer)
 68        {
 69            OnBodyToString(writer);
 70        }
 71
 72        public void Close()
 73        {
 74            if (State != MessageState.Closed)
 75            {
 76                State = MessageState.Closed;
 77                OnClose();
 78                //if (DiagnosticUtility.ShouldTraceVerbose)
 79                //{
 80                //    TraceUtility.TraceEvent(TraceEventType.Verbose, TraceCode.MessageClosed,
 81                //        SR.TraceCodeMessageClosed, this);
 82                //}
 83            }
 84            else
 85            {
 86                //if (DiagnosticUtility.ShouldTraceVerbose)
 87                //{
 88                //    TraceUtility.TraceEvent(TraceEventType.Verbose, TraceCode.MessageClosedAgain,
 89                //        SR.TraceCodeMessageClosedAgain, this);
 90                //}
 91            }
 92        }
 93
 94        public MessageBuffer CreateBufferedCopy(int maxBufferSize)
 95        {
 96            if (maxBufferSize < 0)
 97            {
 98                throw TraceUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(maxBufferSize), maxBufferSize
 99                                                    SRCommon.ValueMustBeNonNegative), this);
 100            }
 101
 102            switch (State)
 103            {
 104                case MessageState.Created:
 105                    State = MessageState.Copied;
 106                    //if (DiagnosticUtility.ShouldTraceVerbose)
 107                    //{
 108                    //    TraceUtility.TraceEvent(TraceEventType.Verbose, TraceCode.MessageCopied,
 109                    //        SR.TraceCodeMessageCopied, this, this);
 110                    //}
 111                    break;
 112                case MessageState.Closed:
 113                    throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
 114                case MessageState.Copied:
 115                    throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.MessageHasBeenCopied), this);
 116                case MessageState.Read:
 117                    throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.MessageHasBeenRead), this);
 118                case MessageState.Written:
 119                    throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.MessageHasBeenWritten), this);
 120                default:
 121                    Fx.Assert(SR.InvalidMessageState);
 122                    throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.InvalidMessageState), this);
 123            }
 124            return OnCreateBufferedCopy(maxBufferSize);
 125        }
 126
 127        internal static Type GetObjectType(object value)
 128        {
 129            return (value == null) ? typeof(object) : value.GetType();
 130        }
 131
 132        public static Message CreateMessage(MessageVersion version, string action, object body)
 133        {
 134            return CreateMessage(version, action, body, DataContractSerializerDefaults.CreateSerializer(GetObjectType(bo
 135        }
 136
 137        public static Message CreateMessage(MessageVersion version, string action, object body, XmlObjectSerializer seri
 138        {
 139            if (version == null)
 140            {
 141                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(version));
 142            }
 143
 144            if (serializer == null)
 145            {
 146                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(serializer));
 147            }
 148
 149            return new BodyWriterMessage(version, action, new XmlObjectSerializerBodyWriter(body, serializer));
 150        }
 151
 152        public static Message CreateMessage(MessageVersion version, string action, XmlReader body)
 153        {
 154            return CreateMessage(version, action, XmlDictionaryReader.CreateDictionaryReader(body));
 155        }
 156
 157        public static Message CreateMessage(MessageVersion version, string action, XmlDictionaryReader body)
 158        {
 159            if (body == null)
 160            {
 161                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(body));
 162            }
 163
 164            if (version == null)
 165            {
 166                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(version));
 167            }
 168
 169            return CreateMessage(version, action, new XmlReaderBodyWriter(body, version.Envelope));
 170        }
 171
 172        public static Message CreateMessage(MessageVersion version, string action, BodyWriter body)
 173        {
 174            if (version == null)
 175            {
 176                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(version));
 177            }
 178
 179            if (body == null)
 180            {
 181                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(body));
 182            }
 183
 184            return new BodyWriterMessage(version, action, body);
 185        }
 186
 187        internal static Message CreateMessage(MessageVersion version, ActionHeader actionHeader, BodyWriter body)
 188        {
 189            if (version == null)
 190            {
 191                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(version));
 192            }
 193
 194            if (body == null)
 195            {
 196                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(body));
 197            }
 198
 199            return new BodyWriterMessage(version, actionHeader, body);
 200        }
 201
 202        public static Message CreateMessage(MessageVersion version, string action)
 203        {
 204            if (version == null)
 205            {
 206                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(version));
 207            }
 208
 209            return new BodyWriterMessage(version, action, EmptyBodyWriter.Value);
 210        }
 211
 212        //static internal Message CreateMessage(MessageVersion version, ActionHeader actionHeader)
 213        //{
 214        //    if (version == null)
 215        //        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("version"));
 216        //    return new BodyWriterMessage(version, actionHeader, EmptyBodyWriter.Value);
 217        //}
 218
 219        public static Message CreateMessage(XmlReader envelopeReader, int maxSizeOfHeaders, MessageVersion version)
 220        {
 221            return CreateMessage(XmlDictionaryReader.CreateDictionaryReader(envelopeReader), maxSizeOfHeaders, version);
 222        }
 223
 224        public static Message CreateMessage(XmlDictionaryReader envelopeReader, int maxSizeOfHeaders, MessageVersion ver
 225        {
 226            if (envelopeReader == null)
 227            {
 228                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(envelopeReader));
 229            }
 230
 231            if (version == null)
 232            {
 233                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(version));
 234            }
 235
 236            Message message = new StreamedMessage(envelopeReader, maxSizeOfHeaders, version);
 237            return message;
 238        }
 239
 240        internal static Message CreateMessage(MessageVersion version, FaultCode faultCode, string reason, string action)
 241        {
 242            if (version == null)
 243            {
 244                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(version));
 245            }
 246
 247            if (faultCode == null)
 248            {
 249                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(faultCode));
 250            }
 251
 252            if (reason == null)
 253            {
 254                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(reason));
 255            }
 256
 257            return CreateMessage(version, MessageFault.CreateFault(faultCode, reason), action);
 258        }
 259
 260        //public static Message CreateMessage(MessageVersion version, FaultCode faultCode, string reason, object detail,
 261        //{
 262        //    if (version == null)
 263        //        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("version"));
 264        //    if (faultCode == null)
 265        //        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("faultCode"));
 266        //    if (reason == null)
 267        //        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("reason"));
 268
 269        //    return CreateMessage(version, MessageFault.CreateFault(faultCode, new FaultReason(reason), detail), action
 270        //}
 271
 272        // TODO: This method SHOULD be made public in the contract as without it, you can't create a Message from a Mess
 273        public static Message CreateMessage(MessageVersion version, MessageFault fault, string action)
 274        {
 275            if (fault == null)
 276            {
 277                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(fault));
 278            }
 279
 280            if (version == null)
 281            {
 282                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(version));
 283            }
 284
 285            return new BodyWriterMessage(version, action, new FaultBodyWriter(fault, version.Envelope));
 286        }
 287
 288        internal Exception CreateMessageDisposedException()
 289        {
 290            return new ObjectDisposedException("", SR.MessageClosed);
 291        }
 292
 293        void IDisposable.Dispose()
 294        {
 295            Close();
 296        }
 297
 298        public T GetBody<T>()
 299        {
 300            XmlDictionaryReader reader = GetReaderAtBodyContents();   // This call will change the message state to Read
 301            return OnGetBody<T>(reader);
 302        }
 303
 304        protected virtual T OnGetBody<T>(XmlDictionaryReader reader)
 305        {
 306            return GetBodyCore<T>(reader, DataContractSerializerDefaults.CreateSerializer(typeof(T), int.MaxValue/*maxIt
 307        }
 308
 309        public T GetBody<T>(XmlObjectSerializer serializer)
 310        {
 311            if (serializer == null)
 312            {
 313                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(serializer));
 314            }
 315
 316            return GetBodyCore<T>(GetReaderAtBodyContents(), serializer);
 317        }
 318
 319        private T GetBodyCore<T>(XmlDictionaryReader reader, XmlObjectSerializer serializer)
 320        {
 321            T value;
 322            using (reader)
 323            {
 324                value = (T)serializer.ReadObject(reader);
 325                ReadFromBodyContentsToEnd(reader);
 326            }
 327            return value;
 328        }
 329
 330        public virtual XmlDictionaryReader GetReaderAtHeader()
 331        {
 332            XmlBuffer buffer = new XmlBuffer(int.MaxValue);
 333            XmlDictionaryWriter writer = buffer.OpenSection(XmlDictionaryReaderQuotas.Max);
 334            WriteStartEnvelope(writer);
 335            MessageHeaders headers = Headers;
 336            for (int i = 0; i < headers.Count; i++)
 337            {
 338                headers.WriteHeader(i, writer);
 339            }
 340
 341            writer.WriteEndElement();
 342            writer.WriteEndElement();
 343            buffer.CloseSection();
 344            buffer.Close();
 345            XmlDictionaryReader reader = buffer.GetReader(0);
 346            reader.ReadStartElement();
 347            reader.MoveToStartElement();
 348            return reader;
 349        }
 350
 351        public XmlDictionaryReader GetReaderAtBodyContents()
 352        {
 353            EnsureReadMessageState();
 354            if (IsEmpty)
 355            {
 356                throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.MessageIsEmpty), this);
 357            }
 358
 359            return OnGetReaderAtBodyContents();
 360        }
 361
 362        internal void EnsureReadMessageState()
 363        {
 364            switch (State)
 365            {
 366                case MessageState.Created:
 367                    State = MessageState.Read;
 368                    //if (DiagnosticUtility.ShouldTraceVerbose)
 369                    //{
 370                    //    TraceUtility.TraceEvent(TraceEventType.Verbose, TraceCode.MessageRead, SR.Format(SR.TraceCodeM
 371                    //}
 372                    break;
 373                case MessageState.Copied:
 374                    throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.MessageHasBeenCopied), this);
 375                case MessageState.Read:
 376                    throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.MessageHasBeenRead), this);
 377                case MessageState.Written:
 378                    throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.MessageHasBeenWritten), this);
 379                case MessageState.Closed:
 380                    throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
 381                default:
 382                    Fx.Assert(SR.InvalidMessageState);
 383                    throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.InvalidMessageState), this);
 384            }
 385        }
 386
 387        //internal SeekableMessageNavigator GetNavigator(bool navigateBody, int maxNodes)
 388        //{
 389        //    if (IsDisposed)
 390        //        throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
 391        //    if (null == this.messageNavigator)
 392        //    {
 393        //        this.messageNavigator = new SeekableMessageNavigator(this, maxNodes, XmlSpace.Default, navigateBody, f
 394        //    }
 395        //    else
 396        //    {
 397        //        this.messageNavigator.ForkNodeCount(maxNodes);
 398        //    }
 399
 400        //    return this.messageNavigator;
 401        //}
 402
 403        internal void InitializeReply(Message request)
 404        {
 405            UniqueId requestMessageID = request.Headers.MessageId;
 406            Headers.RelatesTo = requestMessageID ?? throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR
 407        }
 408
 409        internal static bool IsFaultStartElement(XmlDictionaryReader reader, EnvelopeVersion version)
 410        {
 411            return reader.IsStartElement(XD.MessageDictionary.Fault, version.DictionaryNamespace);
 412        }
 413
 414        protected virtual void OnBodyToString(XmlDictionaryWriter writer)
 415        {
 416            writer.WriteString(SR.MessageBodyIsUnknown);
 417        }
 418
 419        protected virtual MessageBuffer OnCreateBufferedCopy(int maxBufferSize)
 420        {
 421            return OnCreateBufferedCopy(maxBufferSize, XmlDictionaryReaderQuotas.Max);
 422        }
 423
 424        public MessageBuffer OnCreateBufferedCopy(int maxBufferSize, XmlDictionaryReaderQuotas quotas)
 425        {
 426            XmlBuffer msgBuffer = new XmlBuffer(maxBufferSize);
 427            XmlDictionaryWriter writer = msgBuffer.OpenSection(quotas);
 428            OnWriteMessage(writer);
 429            msgBuffer.CloseSection();
 430            msgBuffer.Close();
 431            return new DefaultMessageBuffer(this, msgBuffer);
 432        }
 433
 434        protected virtual void OnClose()
 435        {
 436        }
 437
 438        protected virtual XmlDictionaryReader OnGetReaderAtBodyContents()
 439        {
 440            XmlBuffer bodyBuffer = new XmlBuffer(int.MaxValue);
 441            XmlDictionaryWriter writer = bodyBuffer.OpenSection(XmlDictionaryReaderQuotas.Max);
 442            if (Version.Envelope != EnvelopeVersion.None)
 443            {
 444                OnWriteStartEnvelope(writer);
 445                OnWriteStartBody(writer);
 446            }
 447            OnWriteBodyContents(writer);
 448            if (Version.Envelope != EnvelopeVersion.None)
 449            {
 450                writer.WriteEndElement();
 451                writer.WriteEndElement();
 452            }
 453            bodyBuffer.CloseSection();
 454            bodyBuffer.Close();
 455            XmlDictionaryReader reader = bodyBuffer.GetReader(0);
 456            if (Version.Envelope != EnvelopeVersion.None)
 457            {
 458                reader.ReadStartElement();
 459                reader.ReadStartElement();
 460            }
 461            reader.MoveToContent();
 462            return reader;
 463        }
 464
 465        protected virtual void OnWriteStartBody(XmlDictionaryWriter writer)
 466        {
 467            MessageDictionary messageDictionary = XD.MessageDictionary;
 468            writer.WriteStartElement(messageDictionary.Prefix.Value, messageDictionary.Body, Version.Envelope.Dictionary
 469        }
 470
 471        public void WriteBodyContents(XmlDictionaryWriter writer)
 472        {
 473            EnsureWriteMessageState(writer);
 474            OnWriteBodyContents(writer);
 475        }
 476
 477        public Task WriteBodyContentsAsync(XmlDictionaryWriter writer)
 478        {
 479            EnsureWriteMessageState(writer);
 480            return OnWriteBodyContentsAsync(writer);
 481        }
 482
 483        //public IAsyncResult BeginWriteBodyContents(XmlDictionaryWriter writer, AsyncCallback callback, object state)
 484        //{
 485        //    EnsureWriteMessageState(writer);
 486        //    return this.OnBeginWriteBodyContents(writer, callback, state);
 487        //}
 488
 489        //public void EndWriteBodyContents(IAsyncResult result)
 490        //{
 491        //    this.OnEndWriteBodyContents(result);
 492        //}
 493
 494        protected abstract void OnWriteBodyContents(XmlDictionaryWriter writer);
 495
 496        internal virtual Task OnWriteBodyContentsAsync(XmlDictionaryWriter writer)
 497        {
 498            OnWriteBodyContents(writer);
 499            return Task.CompletedTask;
 500        }
 501
 502        //protected virtual IAsyncResult OnBeginWriteBodyContents(XmlDictionaryWriter writer, AsyncCallback callback, ob
 503        //{
 504        //    return new OnWriteBodyContentsAsyncResult(writer, this, callback, state);
 505        //}
 506
 507        //protected virtual void OnEndWriteBodyContents(IAsyncResult result)
 508        //{
 509        //    OnWriteBodyContentsAsyncResult.End(result);
 510        //}
 511
 512        public void WriteStartEnvelope(XmlDictionaryWriter writer)
 513        {
 514            if (writer == null)
 515            {
 516                throw TraceUtility.ThrowHelperError(new ArgumentNullException(nameof(writer)), this);
 517            }
 518
 519            OnWriteStartEnvelope(writer);
 520        }
 521
 522        protected virtual void OnWriteStartEnvelope(XmlDictionaryWriter writer)
 523        {
 524            EnvelopeVersion envelopeVersion = Version.Envelope;
 525            if (envelopeVersion != EnvelopeVersion.None)
 526            {
 527                MessageDictionary messageDictionary = XD.MessageDictionary;
 528                writer.WriteStartElement(messageDictionary.Prefix.Value, messageDictionary.Envelope, envelopeVersion.Dic
 529                WriteSharedHeaderPrefixes(writer);
 530            }
 531        }
 532
 533        protected virtual void OnWriteStartHeaders(XmlDictionaryWriter writer)
 534        {
 535            EnvelopeVersion envelopeVersion = Version.Envelope;
 536            if (envelopeVersion != EnvelopeVersion.None)
 537            {
 538                MessageDictionary messageDictionary = XD.MessageDictionary;
 539                writer.WriteStartElement(messageDictionary.Prefix.Value, messageDictionary.Header, envelopeVersion.Dicti
 540            }
 541        }
 542
 543        public override string ToString()
 544        {
 545            if (IsDisposed)
 546            {
 547                return base.ToString();
 548            }
 549
 550            StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture);
 551            EncodingFallbackAwareXmlTextWriter textWriter = new EncodingFallbackAwareXmlTextWriter(stringWriter)
 552            {
 553                Formatting = Formatting.Indented
 554            };
 555            XmlDictionaryWriter writer = XmlDictionaryWriter.CreateDictionaryWriter(textWriter);
 556            try
 557            {
 558                ToString(writer);
 559                writer.Flush();
 560                return stringWriter.ToString();
 561            }
 562            catch (XmlException e)
 563            {
 564                return SR.Format(SR.MessageBodyToStringError, e.GetType().ToString(), e.Message);
 565            }
 566        }
 567
 568        internal void ToString(XmlDictionaryWriter writer)
 569        {
 570            if (IsDisposed)
 571            {
 572                throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
 573            }
 574
 575            if (Version.Envelope != EnvelopeVersion.None)
 576            {
 577                WriteStartEnvelope(writer);
 578                WriteStartHeaders(writer);
 579                MessageHeaders headers = Headers;
 580                for (int i = 0; i < headers.Count; i++)
 581                {
 582                    headers.WriteHeader(i, writer);
 583                }
 584
 585                writer.WriteEndElement();
 586                MessageDictionary messageDictionary = XD.MessageDictionary;
 587                WriteStartBody(writer);
 588            }
 589
 590            BodyToString(writer);
 591
 592            if (Version.Envelope != EnvelopeVersion.None)
 593            {
 594                writer.WriteEndElement();
 595                writer.WriteEndElement();
 596            }
 597        }
 598
 599        public string GetBodyAttribute(string localName, string ns)
 600        {
 601            if (localName == null)
 602            {
 603                throw TraceUtility.ThrowHelperError(new ArgumentNullException(nameof(localName)), this);
 604            }
 605
 606            if (ns == null)
 607            {
 608                throw TraceUtility.ThrowHelperError(new ArgumentNullException(nameof(ns)), this);
 609            }
 610
 611            switch (State)
 612            {
 613                case MessageState.Created:
 614                    break;
 615                case MessageState.Copied:
 616                    throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.MessageHasBeenCopied), this);
 617                case MessageState.Read:
 618                    throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.MessageHasBeenRead), this);
 619                case MessageState.Written:
 620                    throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.MessageHasBeenWritten), this);
 621                case MessageState.Closed:
 622                    throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
 623                default:
 624                    Fx.Assert(SR.InvalidMessageState);
 625                    throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.InvalidMessageState), this);
 626            }
 627            return OnGetBodyAttribute(localName, ns);
 628        }
 629
 630        protected virtual string OnGetBodyAttribute(string localName, string ns)
 631        {
 632            return null;
 633        }
 634
 635        internal void ReadFromBodyContentsToEnd(XmlDictionaryReader reader)
 636        {
 637            ReadFromBodyContentsToEnd(reader, Version.Envelope);
 638        }
 639
 640        private static void ReadFromBodyContentsToEnd(XmlDictionaryReader reader, EnvelopeVersion envelopeVersion)
 641        {
 642            if (envelopeVersion != EnvelopeVersion.None)
 643            {
 644                reader.ReadEndElement(); // </Body>
 645                reader.ReadEndElement(); // </Envelope>
 646            }
 647            reader.MoveToContent();
 648        }
 649
 650        internal static bool ReadStartBody(XmlDictionaryReader reader, EnvelopeVersion envelopeVersion, out bool isFault
 651        {
 652            if (reader.IsEmptyElement)
 653            {
 654                reader.Read();
 655                isEmpty = true;
 656                isFault = false;
 657                reader.ReadEndElement();
 658                return false;
 659            }
 660            else
 661            {
 662                reader.Read();
 663                if (reader.NodeType != XmlNodeType.Element)
 664                {
 665                    reader.MoveToContent();
 666                }
 667
 668                if (reader.NodeType == XmlNodeType.Element)
 669                {
 670                    isFault = IsFaultStartElement(reader, envelopeVersion);
 671                    isEmpty = false;
 672                }
 673                else if (reader.NodeType == XmlNodeType.EndElement)
 674                {
 675                    isEmpty = true;
 676                    isFault = false;
 677                    ReadFromBodyContentsToEnd(reader, envelopeVersion);
 678                    return false;
 679                }
 680                else
 681                {
 682                    isEmpty = false;
 683                    isFault = false;
 684                }
 685
 686                return true;
 687            }
 688        }
 689
 690        public void WriteBody(XmlWriter writer)
 691        {
 692            WriteBody(XmlDictionaryWriter.CreateDictionaryWriter(writer));
 693        }
 694
 695        public void WriteBody(XmlDictionaryWriter writer)
 696        {
 697            WriteStartBody(writer);
 698            WriteBodyContents(writer);
 699            writer.WriteEndElement();
 700        }
 701
 702        public void WriteStartBody(XmlWriter writer)
 703        {
 704            WriteStartBody(XmlDictionaryWriter.CreateDictionaryWriter(writer));
 705        }
 706
 707        public void WriteStartBody(XmlDictionaryWriter writer)
 708        {
 709            if (writer == null)
 710            {
 711                throw TraceUtility.ThrowHelperError(new ArgumentNullException(nameof(writer)), this);
 712            }
 713
 714            OnWriteStartBody(writer);
 715        }
 716
 717        internal void WriteStartHeaders(XmlDictionaryWriter writer)
 718        {
 719            OnWriteStartHeaders(writer);
 720        }
 721
 722        public void WriteMessage(XmlWriter writer)
 723        {
 724            WriteMessage(XmlDictionaryWriter.CreateDictionaryWriter(writer));
 725        }
 726
 727        public void WriteMessage(XmlDictionaryWriter writer)
 728        {
 729            EnsureWriteMessageState(writer);
 730            OnWriteMessage(writer);
 731        }
 732
 733        public virtual Task WriteMessageAsync(XmlWriter writer)
 734        {
 735            WriteMessage(writer);
 736            return TaskHelpers.CompletedTask();
 737        }
 738
 739        public virtual async Task WriteMessageAsync(XmlDictionaryWriter writer)
 740        {
 741            EnsureWriteMessageState(writer);
 742            await OnWriteMessageAsync(writer);
 743        }
 744
 745        public virtual async Task OnWriteMessageAsync(XmlDictionaryWriter writer)
 746        {
 747            WriteMessagePreamble(writer);
 748            // We should call OnWriteBodyContentsAsync instead of WriteBodyContentsAsync here,
 749            // otherwise EnsureWriteMessageState would get called twice. Also see OnWriteMessage()
 750            // for the example.
 751            await OnWriteBodyContentsAsync(writer);
 752            if (writer.SupportsAsync())
 753            {
 754                await WriteMessagePostambleAsync(writer);
 755            }
 756            else
 757            {
 758                WriteMessagePostamble(writer);
 759            }
 760        }
 761
 762        private void EnsureWriteMessageState(XmlDictionaryWriter writer)
 763        {
 764            if (writer == null)
 765            {
 766                throw TraceUtility.ThrowHelperError(new ArgumentNullException(nameof(writer)), this);
 767            }
 768
 769            switch (State)
 770            {
 771                case MessageState.Created:
 772                    State = MessageState.Written;
 773                    //if (DiagnosticUtility.ShouldTraceVerbose)
 774                    //{
 775                    //    TraceUtility.TraceEvent(TraceEventType.Verbose, TraceCode.MessageWritten, SR.TraceCodeMessageW
 776                    //}
 777                    break;
 778                case MessageState.Copied:
 779                    throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.MessageHasBeenCopied), this);
 780                case MessageState.Read:
 781                    throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.MessageHasBeenRead), this);
 782                case MessageState.Written:
 783                    throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.MessageHasBeenWritten), this);
 784                case MessageState.Closed:
 785                    throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
 786                default:
 787                    Fx.Assert(SR.InvalidMessageState);
 788                    throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.InvalidMessageState), this);
 789            }
 790        }
 791
 792        //public IAsyncResult BeginWriteMessage(XmlDictionaryWriter writer, AsyncCallback callback, object state)
 793        //{
 794        //    EnsureWriteMessageState(writer);
 795        //    return OnBeginWriteMessage(writer, callback, state);
 796        //}
 797
 798        //public void EndWriteMessage(IAsyncResult result)
 799        //{
 800        //    OnEndWriteMessage(result);
 801        //}
 802
 803        protected virtual void OnWriteMessage(XmlDictionaryWriter writer)
 804        {
 805            WriteMessagePreamble(writer);
 806            OnWriteBodyContents(writer);
 807            WriteMessagePostamble(writer);
 808        }
 809
 810        internal void WriteMessagePreamble(XmlDictionaryWriter writer)
 811        {
 812            if (Version.Envelope != EnvelopeVersion.None)
 813            {
 814                OnWriteStartEnvelope(writer);
 815
 816                MessageHeaders headers = Headers;
 817                int headersCount = headers.Count;
 818                if (headersCount > 0)
 819                {
 820                    OnWriteStartHeaders(writer);
 821                    for (int i = 0; i < headersCount; i++)
 822                    {
 823                        headers.WriteHeader(i, writer);
 824                    }
 825                    writer.WriteEndElement();
 826                }
 827
 828                OnWriteStartBody(writer);
 829            }
 830        }
 831
 832        internal void WriteMessagePostamble(XmlDictionaryWriter writer)
 833        {
 834            if (Version.Envelope != EnvelopeVersion.None)
 835            {
 836                writer.WriteEndElement();
 837                writer.WriteEndElement();
 838            }
 839        }
 840
 841        internal async Task WriteMessagePostambleAsync(XmlDictionaryWriter writer)
 842        {
 843            if (Version.Envelope != EnvelopeVersion.None)
 844            {
 845                await writer.WriteEndElementAsync();
 846                await writer.WriteEndElementAsync();
 847            }
 848        }
 849
 850        private void WriteSharedHeaderPrefixes(XmlDictionaryWriter writer)
 851        {
 852            MessageHeaders headers = Headers;
 853            int count = headers.Count;
 854            int prefixesWritten = 0;
 855            for (int i = 0; i < count; i++)
 856            {
 857                if (Version.Addressing == AddressingVersion.None && headers[i].Namespace == AddressingVersion.None.Names
 858                {
 859                    continue;
 860                }
 861
 862                if (headers[i] is IMessageHeaderWithSharedNamespace headerWithSharedNamespace)
 863                {
 864                    XmlDictionaryString prefix = headerWithSharedNamespace.SharedPrefix;
 865                    string prefixString = prefix.Value;
 866                    if (!((prefixString.Length == 1)))
 867                    {
 868                        Fx.Assert("Message.WriteSharedHeaderPrefixes: (prefixString.Length == 1) -- IMessageHeaderWithSh
 869                        throw TraceUtility.ThrowHelperError(new InvalidOperationException(string.Format(CultureInfo.Inva
 870                    }
 871
 872                    int prefixIndex = prefixString[0] - 'a';
 873                    if (!((prefixIndex >= 0 && prefixIndex < 26)))
 874                    {
 875                        Fx.Assert("Message.WriteSharedHeaderPrefixes: (prefixIndex >= 0 && prefixIndex < 26) -- IMessage
 876                        throw TraceUtility.ThrowHelperError(new InvalidOperationException(string.Format(CultureInfo.Inva
 877                    }
 878                    int prefixBit = 1 << prefixIndex;
 879                    if ((prefixesWritten & prefixBit) == 0)
 880                    {
 881                        writer.WriteXmlnsAttribute(prefixString, headerWithSharedNamespace.SharedNamespace);
 882                        prefixesWritten |= prefixBit;
 883                    }
 884                }
 885            }
 886        }
 887    }
 888
 889    internal class EmptyBodyWriter : BodyWriter
 890    {
 891        private static EmptyBodyWriter s_value;
 892
 893        private EmptyBodyWriter()
 894            : base(true)
 895        {
 896        }
 897
 898        public static EmptyBodyWriter Value
 899        {
 900            get
 901            {
 902                if (s_value == null)
 903                {
 904                    s_value = new EmptyBodyWriter();
 905                }
 906
 907                return s_value;
 908            }
 909        }
 910
 911        internal override bool IsEmpty
 912        {
 913            get { return true; }
 914        }
 915
 916        protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
 917        {
 918        }
 919    }
 920
 921    internal class FaultBodyWriter : BodyWriter
 922    {
 923        private readonly MessageFault _fault;
 924        private readonly EnvelopeVersion _version;
 925
 926        public FaultBodyWriter(MessageFault fault, EnvelopeVersion version)
 927            : base(true)
 928        {
 929            _fault = fault;
 930            _version = version;
 931        }
 932
 933        internal override bool IsFault
 934        {
 935            get { return true; }
 936        }
 937
 938        protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
 939        {
 940            _fault.WriteTo(writer, _version);
 941        }
 942    }
 943
 944    internal class XmlObjectSerializerBodyWriter : BodyWriter
 945    {
 946        private readonly object _body;
 947        private readonly XmlObjectSerializer _serializer;
 948
 949        public XmlObjectSerializerBodyWriter(object body, XmlObjectSerializer serializer)
 356950            : base(true)
 951        {
 356952            _body = body;
 356953            _serializer = serializer;
 356954        }
 955
 956        private object ThisLock
 957        {
 356958            get { return this; }
 959        }
 960
 961        protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
 962        {
 356963            lock (ThisLock)
 964            {
 356965                _serializer.WriteObject(writer, _body);
 356966            }
 356967        }
 968    }
 969
 970    internal class XmlReaderBodyWriter : BodyWriter
 971    {
 972        private readonly XmlDictionaryReader _reader;
 973        private readonly bool _isFault;
 974
 975        public XmlReaderBodyWriter(XmlDictionaryReader reader, EnvelopeVersion version)
 976            : base(false)
 977        {
 978            _reader = reader;
 979            if (reader.MoveToContent() != XmlNodeType.Element)
 980            {
 981                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.InvalidReaderPosition
 982            }
 983
 984            _isFault = Message.IsFaultStartElement(reader, version);
 985        }
 986
 987        internal override bool IsFault
 988        {
 989            get
 990            {
 991                return _isFault;
 992            }
 993        }
 994
 995        protected override BodyWriter OnCreateBufferedCopy(int maxBufferSize)
 996        {
 997            return OnCreateBufferedCopy(maxBufferSize, _reader.Quotas);
 998        }
 999
 1000        protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
 1001        {
 1002            using (_reader)
 1003            {
 1004                XmlNodeType type = _reader.MoveToContent();
 1005                while (!_reader.EOF && type != XmlNodeType.EndElement)
 1006                {
 1007                    if (type != XmlNodeType.Element)
 1008                    {
 1009                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.InvalidReader
 1010                    }
 1011
 1012                    writer.WriteNode(_reader, false);
 1013
 1014                    type = _reader.MoveToContent();
 1015                }
 1016            }
 1017        }
 1018    }
 1019
 1020    internal class BodyWriterMessage : Message
 1021    {
 1022        private MessageProperties _properties;
 1023        private readonly MessageHeaders _headers;
 1024
 1025        private BodyWriterMessage(BodyWriter bodyWriter)
 1026        {
 1027            BodyWriter = bodyWriter;
 1028        }
 1029
 1030        public BodyWriterMessage(MessageVersion version, string action, BodyWriter bodyWriter)
 1031            : this(bodyWriter)
 1032        {
 1033            _headers = new MessageHeaders(version)
 1034            {
 1035                Action = action
 1036            };
 1037        }
 1038
 1039        public BodyWriterMessage(MessageVersion version, ActionHeader actionHeader, BodyWriter bodyWriter)
 1040            : this(bodyWriter)
 1041        {
 1042            _headers = new MessageHeaders(version);
 1043            _headers.SetActionHeader(actionHeader);
 1044        }
 1045
 1046        public BodyWriterMessage(MessageHeaders headers, KeyValuePair<string, object>[] properties, BodyWriter bodyWrite
 1047            : this(bodyWriter)
 1048        {
 1049            _headers = new MessageHeaders(headers);
 1050            _properties = new MessageProperties(properties);
 1051        }
 1052
 1053        public override bool IsFault
 1054        {
 1055            get
 1056            {
 1057                if (IsDisposed)
 1058                {
 1059                    throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
 1060                }
 1061
 1062                return BodyWriter.IsFault;
 1063            }
 1064        }
 1065
 1066        public override bool IsEmpty
 1067        {
 1068            get
 1069            {
 1070                if (IsDisposed)
 1071                {
 1072                    throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
 1073                }
 1074
 1075                return BodyWriter.IsEmpty;
 1076            }
 1077        }
 1078
 1079        public override MessageHeaders Headers
 1080        {
 1081            get
 1082            {
 1083                if (IsDisposed)
 1084                {
 1085                    throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
 1086                }
 1087
 1088                return _headers;
 1089            }
 1090        }
 1091
 1092        public override MessageProperties Properties
 1093        {
 1094            get
 1095            {
 1096                if (IsDisposed)
 1097                {
 1098                    throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
 1099                }
 1100
 1101                if (_properties == null)
 1102                {
 1103                    _properties = new MessageProperties();
 1104                }
 1105
 1106                return _properties;
 1107            }
 1108        }
 1109
 1110        public override MessageVersion Version
 1111        {
 1112            get
 1113            {
 1114                if (IsDisposed)
 1115                {
 1116                    throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
 1117                }
 1118
 1119                return _headers.MessageVersion;
 1120            }
 1121        }
 1122
 1123        protected override MessageBuffer OnCreateBufferedCopy(int maxBufferSize)
 1124        {
 1125            BodyWriter bufferedBodyWriter;
 1126            if (BodyWriter.IsBuffered)
 1127            {
 1128                bufferedBodyWriter = BodyWriter;
 1129            }
 1130            else
 1131            {
 1132                bufferedBodyWriter = BodyWriter.CreateBufferedCopy(maxBufferSize);
 1133            }
 1134            KeyValuePair<string, object>[] properties = new KeyValuePair<string, object>[Properties.Count];
 1135            ((ICollection<KeyValuePair<string, object>>)Properties).CopyTo(properties, 0);
 1136            return new BodyWriterMessageBuffer(_headers, properties, bufferedBodyWriter);
 1137        }
 1138
 1139        protected override void OnClose()
 1140        {
 1141            Exception ex = null;
 1142            try
 1143            {
 1144                base.OnClose();
 1145            }
 1146            catch (Exception e)
 1147            {
 1148                if (Fx.IsFatal(e))
 1149                {
 1150                    throw;
 1151                }
 1152
 1153                ex = e;
 1154            }
 1155
 1156            try
 1157            {
 1158                if (_properties != null)
 1159                {
 1160                    _properties.Dispose();
 1161                }
 1162            }
 1163            catch (Exception e)
 1164            {
 1165                if (Fx.IsFatal(e))
 1166                {
 1167                    throw;
 1168                }
 1169
 1170                if (ex == null)
 1171                {
 1172                    ex = e;
 1173                }
 1174            }
 1175
 1176            if (ex != null)
 1177            {
 1178                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(ex);
 1179            }
 1180
 1181            BodyWriter = null;
 1182        }
 1183
 1184        protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
 1185        {
 1186            BodyWriter.WriteBodyContents(writer);
 1187        }
 1188
 1189        public override async Task OnWriteMessageAsync(XmlDictionaryWriter writer)
 1190        {
 1191            WriteMessagePreamble(writer);
 1192            await OnWriteBodyContentsAsync(writer);
 1193
 1194            if (writer.SupportsAsync())
 1195            {
 1196                await WriteMessagePostambleAsync(writer);
 1197            }
 1198            else
 1199            {
 1200                WriteMessagePostamble(writer);
 1201            }
 1202        }
 1203
 1204        internal override Task OnWriteBodyContentsAsync(XmlDictionaryWriter writer)
 1205        {
 1206            return BodyWriter.WriteBodyContentsAsync(writer);
 1207        }
 1208
 1209        protected override void OnBodyToString(XmlDictionaryWriter writer)
 1210        {
 1211            if (BodyWriter.IsBuffered)
 1212            {
 1213                BodyWriter.WriteBodyContents(writer);
 1214            }
 1215            else
 1216            {
 1217                writer.WriteString(SR.MessageBodyIsStream);
 1218            }
 1219        }
 1220
 1221        protected internal BodyWriter BodyWriter { get; private set; }
 1222    }
 1223
 1224    internal abstract class ReceivedMessage : Message
 1225    {
 1226        private bool _isFault;
 1227        private bool _isEmpty;
 1228
 1229        public override bool IsEmpty
 1230        {
 1231            get { return _isEmpty; }
 1232        }
 1233
 1234        public override bool IsFault
 1235        {
 1236            get { return _isFault; }
 1237        }
 1238
 1239        protected static bool HasHeaderElement(XmlDictionaryReader reader, EnvelopeVersion envelopeVersion)
 1240        {
 1241            return reader.IsStartElement(XD.MessageDictionary.Header, envelopeVersion.DictionaryNamespace);
 1242        }
 1243
 1244        protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
 1245        {
 1246            if (!_isEmpty)
 1247            {
 1248                using (XmlDictionaryReader bodyReader = OnGetReaderAtBodyContents())
 1249                {
 1250                    if (bodyReader.ReadState == ReadState.Error || bodyReader.ReadState == ReadState.Closed)
 1251                    {
 1252                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Forma
 1253                    }
 1254
 1255                    while (bodyReader.NodeType != XmlNodeType.EndElement && !bodyReader.EOF)
 1256                    {
 1257                        writer.WriteNode(bodyReader, false);
 1258                    }
 1259
 1260                    ReadFromBodyContentsToEnd(bodyReader);
 1261                }
 1262            }
 1263        }
 1264
 1265        protected bool ReadStartBody(XmlDictionaryReader reader)
 1266        {
 1267            return ReadStartBody(reader, Version.Envelope, out _isFault, out _isEmpty);
 1268        }
 1269
 1270        protected static EnvelopeVersion ReadStartEnvelope(XmlDictionaryReader reader)
 1271        {
 1272            EnvelopeVersion envelopeVersion;
 1273
 1274            if (reader.IsStartElement(XD.MessageDictionary.Envelope, XD.Message12Dictionary.Namespace))
 1275            {
 1276                envelopeVersion = EnvelopeVersion.Soap12;
 1277            }
 1278            else if (reader.IsStartElement(XD.MessageDictionary.Envelope, XD.Message11Dictionary.Namespace))
 1279            {
 1280                envelopeVersion = EnvelopeVersion.Soap11;
 1281            }
 1282            else
 1283            {
 1284                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(SR.MessageVersionUn
 1285            }
 1286
 1287            if (reader.IsEmptyElement)
 1288            {
 1289                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(SR.MessageBodyMissi
 1290            }
 1291
 1292            reader.Read();
 1293            return envelopeVersion;
 1294        }
 1295
 1296        protected static void VerifyStartBody(XmlDictionaryReader reader, EnvelopeVersion version)
 1297        {
 1298            if (!reader.IsStartElement(XD.MessageDictionary.Body, version.DictionaryNamespace))
 1299            {
 1300                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(SR.MessageBodyMissi
 1301            }
 1302        }
 1303    }
 1304
 1305    internal sealed class StreamedMessage : ReceivedMessage
 1306    {
 1307        private readonly MessageHeaders _headers;
 1308        private readonly XmlAttributeHolder[] _envelopeAttributes;
 1309        private readonly XmlAttributeHolder[] _headerAttributes;
 1310        private readonly XmlAttributeHolder[] _bodyAttributes;
 1311        private readonly string _envelopePrefix;
 1312        private readonly string _headerPrefix;
 1313        private readonly string _bodyPrefix;
 1314        private readonly MessageProperties _properties;
 1315        private XmlDictionaryReader _reader;
 1316        private readonly XmlDictionaryReaderQuotas _quotas;
 1317
 1318        public StreamedMessage(XmlDictionaryReader reader, int maxSizeOfHeaders, MessageVersion desiredVersion)
 1319        {
 1320            _properties = new MessageProperties();
 1321            if (reader.NodeType != XmlNodeType.Element)
 1322            {
 1323                reader.MoveToContent();
 1324            }
 1325
 1326            if (desiredVersion.Envelope == EnvelopeVersion.None)
 1327            {
 1328                _reader = reader;
 1329                _headerAttributes = XmlAttributeHolder.emptyArray;
 1330                _headers = new MessageHeaders(desiredVersion);
 1331            }
 1332            else
 1333            {
 1334                _envelopeAttributes = XmlAttributeHolder.ReadAttributes(reader, ref maxSizeOfHeaders);
 1335                _envelopePrefix = reader.Prefix;
 1336                EnvelopeVersion envelopeVersion = ReadStartEnvelope(reader);
 1337                if (desiredVersion.Envelope != envelopeVersion)
 1338                {
 1339                    Exception versionMismatchException = new ArgumentException(SR.Format(SR.EncoderEnvelopeVersionMismat
 1340                    throw TraceUtility.ThrowHelperError(
 1341                        new CommunicationException(versionMismatchException.Message, versionMismatchException),
 1342                        this);
 1343                }
 1344
 1345                if (HasHeaderElement(reader, envelopeVersion))
 1346                {
 1347                    _headerPrefix = reader.Prefix;
 1348                    _headerAttributes = XmlAttributeHolder.ReadAttributes(reader, ref maxSizeOfHeaders);
 1349                    _headers = new MessageHeaders(desiredVersion, reader, _envelopeAttributes, _headerAttributes, ref ma
 1350                }
 1351                else
 1352                {
 1353                    _headerAttributes = XmlAttributeHolder.emptyArray;
 1354                    _headers = new MessageHeaders(desiredVersion);
 1355                }
 1356
 1357                if (reader.NodeType != XmlNodeType.Element)
 1358                {
 1359                    reader.MoveToContent();
 1360                }
 1361
 1362                _bodyPrefix = reader.Prefix;
 1363                VerifyStartBody(reader, envelopeVersion);
 1364                _bodyAttributes = XmlAttributeHolder.ReadAttributes(reader, ref maxSizeOfHeaders);
 1365                if (ReadStartBody(reader))
 1366                {
 1367                    _reader = reader;
 1368                }
 1369                else
 1370                {
 1371                    _quotas = new XmlDictionaryReaderQuotas();
 1372                    reader.Quotas.CopyTo(_quotas);
 1373                    reader.Dispose();
 1374                }
 1375            }
 1376        }
 1377
 1378        public override MessageHeaders Headers
 1379        {
 1380            get
 1381            {
 1382                if (IsDisposed)
 1383                {
 1384                    throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
 1385                }
 1386
 1387                return _headers;
 1388            }
 1389        }
 1390
 1391        public override MessageVersion Version
 1392        {
 1393            get
 1394            {
 1395                return _headers.MessageVersion;
 1396            }
 1397        }
 1398
 1399        public override MessageProperties Properties
 1400        {
 1401            get
 1402            {
 1403                return _properties;
 1404            }
 1405        }
 1406
 1407        protected override void OnBodyToString(XmlDictionaryWriter writer)
 1408        {
 1409            writer.WriteString(SR.MessageBodyIsStream);
 1410        }
 1411
 1412        protected override void OnClose()
 1413        {
 1414            Exception ex = null;
 1415            try
 1416            {
 1417                base.OnClose();
 1418            }
 1419            catch (Exception e)
 1420            {
 1421                if (Fx.IsFatal(e))
 1422                {
 1423                    throw;
 1424                }
 1425
 1426                ex = e;
 1427            }
 1428
 1429            try
 1430            {
 1431                _properties.Dispose();
 1432            }
 1433            catch (Exception e)
 1434            {
 1435                if (Fx.IsFatal(e))
 1436                {
 1437                    throw;
 1438                }
 1439
 1440                if (ex == null)
 1441                {
 1442                    ex = e;
 1443                }
 1444            }
 1445
 1446            try
 1447            {
 1448                if (_reader != null)
 1449                {
 1450                    _reader.Dispose();
 1451                }
 1452            }
 1453            catch (Exception e)
 1454            {
 1455                if (Fx.IsFatal(e))
 1456                {
 1457                    throw;
 1458                }
 1459
 1460                if (ex == null)
 1461                {
 1462                    ex = e;
 1463                }
 1464            }
 1465
 1466            if (ex != null)
 1467            {
 1468                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(ex);
 1469            }
 1470        }
 1471
 1472        protected override XmlDictionaryReader OnGetReaderAtBodyContents()
 1473        {
 1474            XmlDictionaryReader reader = _reader;
 1475            _reader = null;
 1476            return reader;
 1477        }
 1478
 1479        protected override MessageBuffer OnCreateBufferedCopy(int maxBufferSize)
 1480        {
 1481            if (_reader != null)
 1482            {
 1483                return OnCreateBufferedCopy(maxBufferSize, _reader.Quotas);
 1484            }
 1485
 1486            return OnCreateBufferedCopy(maxBufferSize, _quotas);
 1487        }
 1488
 1489        protected override void OnWriteStartBody(XmlDictionaryWriter writer)
 1490        {
 1491            writer.WriteStartElement(_bodyPrefix, MessageStrings.Body, Version.Envelope.Namespace);
 1492            XmlAttributeHolder.WriteAttributes(_bodyAttributes, writer);
 1493        }
 1494
 1495        protected override void OnWriteStartEnvelope(XmlDictionaryWriter writer)
 1496        {
 1497            EnvelopeVersion envelopeVersion = Version.Envelope;
 1498            writer.WriteStartElement(_envelopePrefix, MessageStrings.Envelope, envelopeVersion.Namespace);
 1499            XmlAttributeHolder.WriteAttributes(_envelopeAttributes, writer);
 1500        }
 1501
 1502        protected override void OnWriteStartHeaders(XmlDictionaryWriter writer)
 1503        {
 1504            EnvelopeVersion envelopeVersion = Version.Envelope;
 1505            writer.WriteStartElement(_headerPrefix, MessageStrings.Header, envelopeVersion.Namespace);
 1506            XmlAttributeHolder.WriteAttributes(_headerAttributes, writer);
 1507        }
 1508
 1509        protected override string OnGetBodyAttribute(string localName, string ns)
 1510        {
 1511            return XmlAttributeHolder.GetAttribute(_bodyAttributes, localName, ns);
 1512        }
 1513    }
 1514
 1515    public interface IBufferedMessageData
 1516    {
 1517        MessageEncoder MessageEncoder { get; }
 1518        ArraySegment<byte> Buffer { get; }
 1519        XmlDictionaryReaderQuotas Quotas { get; }
 1520        void Close();
 1521        void EnableMultipleUsers();
 1522        XmlDictionaryReader GetMessageReader();
 1523        void Open();
 1524        void ReturnMessageState(RecycledMessageState messageState);
 1525        RecycledMessageState TakeMessageState();
 1526    }
 1527
 1528    internal sealed class BufferedMessage : ReceivedMessage
 1529    {
 1530        private readonly MessageHeaders _headers;
 1531        private readonly MessageProperties _properties;
 1532        private RecycledMessageState _recycledMessageState;
 1533        private XmlDictionaryReader _reader;
 1534        private readonly XmlAttributeHolder[] _bodyAttributes;
 1535
 1536        public BufferedMessage(IBufferedMessageData messageData, RecycledMessageState recycledMessageState)
 1537            : this(messageData, recycledMessageState, null, false)
 1538        {
 1539        }
 1540
 1541        public BufferedMessage(IBufferedMessageData messageData, RecycledMessageState recycledMessageState, bool[] under
 1542        {
 1543            //bool throwing = true;
 1544            //try
 1545            //{
 1546            _recycledMessageState = recycledMessageState;
 1547            MessageData = messageData;
 1548            _properties = recycledMessageState.TakeProperties();
 1549            if (_properties == null)
 1550            {
 1551                _properties = new MessageProperties();
 1552            }
 1553
 1554            XmlDictionaryReader reader = messageData.GetMessageReader();
 1555            MessageVersion desiredVersion = messageData.MessageEncoder.MessageVersion;
 1556
 1557            if (desiredVersion.Envelope == EnvelopeVersion.None)
 1558            {
 1559                _reader = reader;
 1560                _headers = new MessageHeaders(desiredVersion);
 1561            }
 1562            else
 1563            {
 1564                EnvelopeVersion envelopeVersion = ReadStartEnvelope(reader);
 1565                if (desiredVersion.Envelope != envelopeVersion)
 1566                {
 1567                    Exception versionMismatchException = new ArgumentException(SR.Format(SR.EncoderEnvelopeVersionMismat
 1568                    throw TraceUtility.ThrowHelperError(
 1569                        new CommunicationException(versionMismatchException.Message, versionMismatchException),
 1570                        this);
 1571                }
 1572
 1573                if (HasHeaderElement(reader, envelopeVersion))
 1574                {
 1575                    _headers = recycledMessageState.TakeHeaders();
 1576                    if (_headers == null)
 1577                    {
 1578                        _headers = new MessageHeaders(desiredVersion, reader, messageData, recycledMessageState, underst
 1579                    }
 1580                    else
 1581                    {
 1582                        _headers.Init(desiredVersion, reader, messageData, recycledMessageState, understoodHeaders, unde
 1583                    }
 1584                }
 1585                else
 1586                {
 1587                    _headers = new MessageHeaders(desiredVersion);
 1588                }
 1589
 1590                VerifyStartBody(reader, envelopeVersion);
 1591
 1592                int maxSizeOfAttributes = int.MaxValue;
 1593                _bodyAttributes = XmlAttributeHolder.ReadAttributes(reader, ref maxSizeOfAttributes);
 1594                if (maxSizeOfAttributes < int.MaxValue - 4096)
 1595                {
 1596                    _bodyAttributes = null;
 1597                }
 1598
 1599                if (ReadStartBody(reader))
 1600                {
 1601                    _reader = reader;
 1602                }
 1603                else
 1604                {
 1605                    reader.Dispose();
 1606                }
 1607            }
 1608            //throwing = false;
 1609            //}
 1610            //finally
 1611            //{
 1612            //    if (throwing && MessageLogger.LoggingEnabled)
 1613            //    {
 1614            //        MessageLogger.LogMessage(messageData.Buffer, MessageLoggingSource.Malformed);
 1615            //    }
 1616            //}
 1617        }
 1618
 1619        public override MessageHeaders Headers
 1620        {
 1621            get
 1622            {
 1623                if (IsDisposed)
 1624                {
 1625                    throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
 1626                }
 1627
 1628                return _headers;
 1629            }
 1630        }
 1631
 1632        internal IBufferedMessageData MessageData { get; private set; }
 1633
 1634        public override MessageProperties Properties
 1635        {
 1636            get
 1637            {
 1638                if (IsDisposed)
 1639                {
 1640                    throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
 1641                }
 1642
 1643                return _properties;
 1644            }
 1645        }
 1646
 1647        public override RecycledMessageState RecycledMessageState
 1648        {
 1649            get { return _recycledMessageState; }
 1650        }
 1651
 1652        public override MessageVersion Version
 1653        {
 1654            get
 1655            {
 1656                return _headers.MessageVersion;
 1657            }
 1658        }
 1659
 1660        protected override XmlDictionaryReader OnGetReaderAtBodyContents()
 1661        {
 1662            XmlDictionaryReader reader = _reader;
 1663            _reader = null;
 1664            return reader;
 1665        }
 1666
 1667        public override XmlDictionaryReader GetReaderAtHeader()
 1668        {
 1669            if (!_headers.ContainsOnlyBufferedMessageHeaders)
 1670            {
 1671                return base.GetReaderAtHeader();
 1672            }
 1673
 1674            XmlDictionaryReader reader = MessageData.GetMessageReader();
 1675            if (reader.NodeType != XmlNodeType.Element)
 1676            {
 1677                reader.MoveToContent();
 1678            }
 1679
 1680            reader.Read();
 1681            if (HasHeaderElement(reader, _headers.MessageVersion.Envelope))
 1682            {
 1683                return reader;
 1684            }
 1685
 1686            return base.GetReaderAtHeader();
 1687        }
 1688
 1689        public XmlDictionaryReader GetBufferedReaderAtBody()
 1690        {
 1691            XmlDictionaryReader reader = MessageData.GetMessageReader();
 1692            if (reader.NodeType != XmlNodeType.Element)
 1693            {
 1694                reader.MoveToContent();
 1695            }
 1696
 1697            if (Version.Envelope != EnvelopeVersion.None)
 1698            {
 1699                reader.Read();
 1700                if (HasHeaderElement(reader, _headers.MessageVersion.Envelope))
 1701                {
 1702                    reader.Skip();
 1703                }
 1704
 1705                if (reader.NodeType != XmlNodeType.Element)
 1706                {
 1707                    reader.MoveToContent();
 1708                }
 1709            }
 1710            return reader;
 1711        }
 1712
 1713        public XmlDictionaryReader GetMessageReader()
 1714        {
 1715            return MessageData.GetMessageReader();
 1716        }
 1717
 1718        protected override void OnBodyToString(XmlDictionaryWriter writer)
 1719        {
 1720            using (XmlDictionaryReader reader = GetBufferedReaderAtBody())
 1721            {
 1722                if (Version == MessageVersion.None)
 1723                {
 1724                    writer.WriteNode(reader, false);
 1725                }
 1726                else
 1727                {
 1728                    if (!reader.IsEmptyElement)
 1729                    {
 1730                        reader.ReadStartElement();
 1731                        while (reader.NodeType != XmlNodeType.EndElement)
 1732                        {
 1733                            writer.WriteNode(reader, false);
 1734                        }
 1735                    }
 1736                }
 1737            }
 1738        }
 1739
 1740        protected override void OnClose()
 1741        {
 1742            Exception ex = null;
 1743            try
 1744            {
 1745                base.OnClose();
 1746            }
 1747            catch (Exception e)
 1748            {
 1749                if (Fx.IsFatal(e))
 1750                {
 1751                    throw;
 1752                }
 1753
 1754                ex = e;
 1755            }
 1756
 1757            try
 1758            {
 1759                _properties.Dispose();
 1760            }
 1761            catch (Exception e)
 1762            {
 1763                if (Fx.IsFatal(e))
 1764                {
 1765                    throw;
 1766                }
 1767
 1768                if (ex == null)
 1769                {
 1770                    ex = e;
 1771                }
 1772            }
 1773
 1774            try
 1775            {
 1776                if (_reader != null)
 1777                {
 1778                    _reader.Dispose();
 1779                }
 1780            }
 1781            catch (Exception e)
 1782            {
 1783                if (Fx.IsFatal(e))
 1784                {
 1785                    throw;
 1786                }
 1787
 1788                if (ex == null)
 1789                {
 1790                    ex = e;
 1791                }
 1792            }
 1793
 1794            try
 1795            {
 1796                _recycledMessageState.ReturnHeaders(_headers);
 1797                _recycledMessageState.ReturnProperties(_properties);
 1798                MessageData.ReturnMessageState(_recycledMessageState);
 1799                _recycledMessageState = null;
 1800                MessageData.Close();
 1801                MessageData = null;
 1802            }
 1803            catch (Exception e)
 1804            {
 1805                if (Fx.IsFatal(e))
 1806                {
 1807                    throw;
 1808                }
 1809
 1810                if (ex == null)
 1811                {
 1812                    ex = e;
 1813                }
 1814            }
 1815
 1816            if (ex != null)
 1817            {
 1818                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(ex);
 1819            }
 1820        }
 1821
 1822        protected override void OnWriteStartEnvelope(XmlDictionaryWriter writer)
 1823        {
 1824            using (XmlDictionaryReader reader = GetMessageReader())
 1825            {
 1826                reader.MoveToContent();
 1827                EnvelopeVersion envelopeVersion = Version.Envelope;
 1828                writer.WriteStartElement(reader.Prefix, MessageStrings.Envelope, envelopeVersion.Namespace);
 1829                writer.WriteAttributes(reader, false);
 1830            }
 1831        }
 1832
 1833        protected override void OnWriteStartHeaders(XmlDictionaryWriter writer)
 1834        {
 1835            using (XmlDictionaryReader reader = GetMessageReader())
 1836            {
 1837                reader.MoveToContent();
 1838                EnvelopeVersion envelopeVersion = Version.Envelope;
 1839                reader.Read();
 1840                if (HasHeaderElement(reader, envelopeVersion))
 1841                {
 1842                    writer.WriteStartElement(reader.Prefix, MessageStrings.Header, envelopeVersion.Namespace);
 1843                    writer.WriteAttributes(reader, false);
 1844                }
 1845                else
 1846                {
 1847                    writer.WriteStartElement(MessageStrings.Prefix, MessageStrings.Header, envelopeVersion.Namespace);
 1848                }
 1849            }
 1850        }
 1851
 1852        protected override void OnWriteStartBody(XmlDictionaryWriter writer)
 1853        {
 1854            using (XmlDictionaryReader reader = GetBufferedReaderAtBody())
 1855            {
 1856                writer.WriteStartElement(reader.Prefix, MessageStrings.Body, Version.Envelope.Namespace);
 1857                writer.WriteAttributes(reader, false);
 1858            }
 1859        }
 1860
 1861        protected override MessageBuffer OnCreateBufferedCopy(int maxBufferSize)
 1862        {
 1863            if (_headers.ContainsOnlyBufferedMessageHeaders)
 1864            {
 1865                KeyValuePair<string, object>[] properties = new KeyValuePair<string, object>[Properties.Count];
 1866                ((ICollection<KeyValuePair<string, object>>)Properties).CopyTo(properties, 0);
 1867                MessageData.EnableMultipleUsers();
 1868                bool[] understoodHeaders = null;
 1869                if (_headers.HasMustUnderstandBeenModified)
 1870                {
 1871                    understoodHeaders = new bool[_headers.Count];
 1872                    for (int i = 0; i < _headers.Count; i++)
 1873                    {
 1874                        understoodHeaders[i] = _headers.IsUnderstood(i);
 1875                    }
 1876                }
 1877                return new BufferedMessageBuffer(MessageData, properties, understoodHeaders, _headers.HasMustUnderstandB
 1878            }
 1879            else
 1880            {
 1881                if (_reader != null)
 1882                {
 1883                    return OnCreateBufferedCopy(maxBufferSize, _reader.Quotas);
 1884                }
 1885
 1886                return OnCreateBufferedCopy(maxBufferSize, XmlDictionaryReaderQuotas.Max);
 1887            }
 1888        }
 1889
 1890        protected override string OnGetBodyAttribute(string localName, string ns)
 1891        {
 1892            if (_bodyAttributes != null)
 1893            {
 1894                return XmlAttributeHolder.GetAttribute(_bodyAttributes, localName, ns);
 1895            }
 1896
 1897            using (XmlDictionaryReader reader = GetBufferedReaderAtBody())
 1898            {
 1899                return reader.GetAttribute(localName, ns);
 1900            }
 1901        }
 1902    }
 1903
 1904    internal struct XmlAttributeHolder
 1905    {
 1906        public static XmlAttributeHolder[] emptyArray = Array.Empty<XmlAttributeHolder>();
 1907
 1908        public XmlAttributeHolder(string prefix, string localName, string ns, string value)
 1909        {
 1910            Prefix = prefix;
 1911            LocalName = localName;
 1912            NamespaceUri = ns;
 1913            Value = value;
 1914        }
 1915
 1916        public string Prefix { get; }
 1917
 1918        public string NamespaceUri { get; }
 1919
 1920        public string LocalName { get; }
 1921
 1922        public string Value { get; }
 1923
 1924        public void WriteTo(XmlWriter writer)
 1925        {
 1926            writer.WriteStartAttribute(Prefix, LocalName, NamespaceUri);
 1927            writer.WriteString(Value);
 1928            writer.WriteEndAttribute();
 1929        }
 1930
 1931        public static void WriteAttributes(XmlAttributeHolder[] attributes, XmlWriter writer)
 1932        {
 1933            for (int i = 0; i < attributes.Length; i++)
 1934            {
 1935                attributes[i].WriteTo(writer);
 1936            }
 1937        }
 1938
 1939        public static XmlAttributeHolder[] ReadAttributes(XmlDictionaryReader reader)
 1940        {
 1941            int maxSizeOfHeaders = int.MaxValue;
 1942            return ReadAttributes(reader, ref maxSizeOfHeaders);
 1943        }
 1944
 1945        public static XmlAttributeHolder[] ReadAttributes(XmlDictionaryReader reader, ref int maxSizeOfHeaders)
 1946        {
 1947            if (reader.AttributeCount == 0)
 1948            {
 1949                return emptyArray;
 1950            }
 1951
 1952            XmlAttributeHolder[] attributes = new XmlAttributeHolder[reader.AttributeCount];
 1953            reader.MoveToFirstAttribute();
 1954            for (int i = 0; i < attributes.Length; i++)
 1955            {
 1956                string ns = reader.NamespaceURI;
 1957                string localName = reader.LocalName;
 1958                string prefix = reader.Prefix;
 1959                string value = string.Empty;
 1960                while (reader.ReadAttributeValue())
 1961                {
 1962                    if (value.Length == 0)
 1963                    {
 1964                        value = reader.Value;
 1965                    }
 1966                    else
 1967                    {
 1968                        value += reader.Value;
 1969                    }
 1970                }
 1971                Deduct(prefix, ref maxSizeOfHeaders);
 1972                Deduct(localName, ref maxSizeOfHeaders);
 1973                Deduct(ns, ref maxSizeOfHeaders);
 1974                Deduct(value, ref maxSizeOfHeaders);
 1975                attributes[i] = new XmlAttributeHolder(prefix, localName, ns, value);
 1976                reader.MoveToNextAttribute();
 1977            }
 1978            reader.MoveToElement();
 1979            return attributes;
 1980        }
 1981
 1982        private static void Deduct(string s, ref int maxSizeOfHeaders)
 1983        {
 1984            int byteCount = s.Length * sizeof(char);
 1985            if (byteCount > maxSizeOfHeaders)
 1986            {
 1987                string message = SRCommon.XmlBufferQuotaExceeded;
 1988                Exception inner = new QuotaExceededException(message);
 1989                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(message, inner));
 1990            }
 1991            maxSizeOfHeaders -= byteCount;
 1992        }
 1993
 1994        public static string GetAttribute(XmlAttributeHolder[] attributes, string localName, string ns)
 1995        {
 1996            for (int i = 0; i < attributes.Length; i++)
 1997            {
 1998                if (attributes[i].LocalName == localName && attributes[i].NamespaceUri == ns)
 1999                {
 2000                    return attributes[i].Value;
 2001                }
 2002            }
 2003
 2004            return null;
 2005        }
 2006    }
 2007
 2008    public class RecycledMessageState
 2009    {
 2010        private MessageHeaders _recycledHeaders;
 2011        private MessageProperties _recycledProperties;
 2012        private UriCache _uriCache;
 2013        private HeaderInfoCache _headerInfoCache;
 2014
 2015        public HeaderInfoCache HeaderInfoCache
 2016        {
 2017            get
 2018            {
 2019                if (_headerInfoCache == null)
 2020                {
 2021                    _headerInfoCache = new HeaderInfoCache();
 2022                }
 2023                return _headerInfoCache;
 2024            }
 2025        }
 2026
 2027        public UriCache UriCache
 2028        {
 2029            get
 2030            {
 2031                if (_uriCache == null)
 2032                {
 2033                    _uriCache = new UriCache();
 2034                }
 2035
 2036                return _uriCache;
 2037            }
 2038        }
 2039
 2040        public MessageProperties TakeProperties()
 2041        {
 2042            MessageProperties taken = _recycledProperties;
 2043            _recycledProperties = null;
 2044            return taken;
 2045        }
 2046
 2047        public void ReturnProperties(MessageProperties properties)
 2048        {
 2049            if (properties.CanRecycle)
 2050            {
 2051                properties.Recycle();
 2052                _recycledProperties = properties;
 2053            }
 2054        }
 2055
 2056        public MessageHeaders TakeHeaders()
 2057        {
 2058            MessageHeaders taken = _recycledHeaders;
 2059            _recycledHeaders = null;
 2060            return taken;
 2061        }
 2062
 2063        public void ReturnHeaders(MessageHeaders headers)
 2064        {
 2065            if (headers.CanRecycle)
 2066            {
 2067                headers.Recycle(HeaderInfoCache);
 2068                _recycledHeaders = headers;
 2069            }
 2070        }
 2071    }
 2072
 2073    public class HeaderInfoCache
 2074    {
 2075        private const int maxHeaderInfos = 4;
 2076        private HeaderInfo[] _headerInfos;
 2077        private int _index;
 2078
 2079        public MessageHeaderInfo TakeHeaderInfo(XmlDictionaryReader reader, string actor, bool mustUnderstand, bool rela
 2080        {
 2081            if (_headerInfos != null)
 2082            {
 2083                int i = _index;
 2084                for (; ; )
 2085                {
 2086                    HeaderInfo headerInfo = _headerInfos[i];
 2087                    if (headerInfo != null)
 2088                    {
 2089                        if (headerInfo.Matches(reader, actor, mustUnderstand, relay, isRefParam))
 2090                        {
 2091                            _headerInfos[i] = null;
 2092                            _index = (i + 1) % maxHeaderInfos;
 2093                            return headerInfo;
 2094                        }
 2095                    }
 2096                    i = (i + 1) % maxHeaderInfos;
 2097                    if (i == _index)
 2098                    {
 2099                        break;
 2100                    }
 2101                }
 2102            }
 2103
 2104            return new HeaderInfo(reader, actor, mustUnderstand, relay, isRefParam);
 2105        }
 2106
 2107        public void ReturnHeaderInfo(MessageHeaderInfo headerInfo)
 2108        {
 2109            if (headerInfo is HeaderInfo headerInfoToReturn)
 2110            {
 2111                if (_headerInfos == null)
 2112                {
 2113                    _headerInfos = new HeaderInfo[maxHeaderInfos];
 2114                }
 2115                int i = _index;
 2116                for (; ; )
 2117                {
 2118                    if (_headerInfos[i] == null)
 2119                    {
 2120                        break;
 2121                    }
 2122                    i = (i + 1) % maxHeaderInfos;
 2123                    if (i == _index)
 2124                    {
 2125                        break;
 2126                    }
 2127                }
 2128                _headerInfos[i] = headerInfoToReturn;
 2129                _index = (i + 1) % maxHeaderInfos;
 2130            }
 2131        }
 2132
 2133        public class HeaderInfo : MessageHeaderInfo
 2134        {
 2135            private readonly string _name;
 2136            private readonly string _ns;
 2137            private readonly string _actor;
 2138            private readonly bool _isReferenceParameter;
 2139            private readonly bool _mustUnderstand;
 2140            private readonly bool _relay;
 2141
 2142            public HeaderInfo(XmlDictionaryReader reader, string actor, bool mustUnderstand, bool relay, bool isReferenc
 2143            {
 2144                _actor = actor;
 2145                _mustUnderstand = mustUnderstand;
 2146                _relay = relay;
 2147                _isReferenceParameter = isReferenceParameter;
 2148                _name = reader.LocalName;
 2149                _ns = reader.NamespaceURI;
 2150            }
 2151
 2152            public override string Name
 2153            {
 2154                get { return _name; }
 2155            }
 2156
 2157            public override string Namespace
 2158            {
 2159                get { return _ns; }
 2160            }
 2161
 2162            public override bool IsReferenceParameter
 2163            {
 2164                get { return _isReferenceParameter; }
 2165            }
 2166
 2167            public override string Actor
 2168            {
 2169                get { return _actor; }
 2170            }
 2171
 2172            public override bool MustUnderstand
 2173            {
 2174                get { return _mustUnderstand; }
 2175            }
 2176
 2177            public override bool Relay
 2178            {
 2179                get { return _relay; }
 2180            }
 2181
 2182            public bool Matches(XmlDictionaryReader reader, string actor, bool mustUnderstand, bool relay, bool isRefPar
 2183            {
 2184                return reader.IsStartElement(_name, _ns) &&
 2185                    _actor == actor && _mustUnderstand == mustUnderstand && _relay == relay && _isReferenceParameter == 
 2186            }
 2187        }
 2188    }
 2189
 2190    public class UriCache
 2191    {
 2192        private const int MaxKeyLength = 128;
 2193        private const int MaxEntries = 8;
 2194        private readonly Entry[] _entries;
 2195        private int _count;
 2196
 2197        public UriCache()
 2198        {
 2199            _entries = new Entry[MaxEntries];
 2200        }
 2201
 2202        public Uri CreateUri(string uriString)
 2203        {
 2204            Uri uri = Get(uriString);
 2205            if (uri == null)
 2206            {
 2207                uri = new Uri(uriString);
 2208                Set(uriString, uri);
 2209            }
 2210            return uri;
 2211        }
 2212
 2213        private Uri Get(string key)
 2214        {
 2215            if (key.Length > MaxKeyLength)
 2216            {
 2217                return null;
 2218            }
 2219
 2220            for (int i = _count - 1; i >= 0; i--)
 2221            {
 2222                if (_entries[i].Key == key)
 2223                {
 2224                    return _entries[i].Value;
 2225                }
 2226            }
 2227
 2228            return null;
 2229        }
 2230
 2231        private void Set(string key, Uri value)
 2232        {
 2233            if (key.Length > MaxKeyLength)
 2234            {
 2235                return;
 2236            }
 2237
 2238            if (_count < _entries.Length)
 2239            {
 2240                _entries[_count++] = new Entry(key, value);
 2241            }
 2242            else
 2243            {
 2244                Array.Copy(_entries, 1, _entries, 0, _entries.Length - 1);
 2245                _entries[_count - 1] = new Entry(key, value);
 2246            }
 2247        }
 2248
 2249        private struct Entry
 2250        {
 2251            public Entry(string key, Uri value)
 2252            {
 2253                Key = key;
 2254                Value = value;
 2255            }
 2256
 2257            public string Key { get; }
 2258
 2259            public Uri Value { get; }
 2260        }
 2261    }
 2262}