< Summary - CoreWCF Coverage — PR #1766

Information
Class: CoreWCF.Channels.BinaryMessageEncoderFactory
Assembly: CoreWCF.Primitives
File(s): /home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/Channels/BinaryMessageEncoderFactory.cs
Line coverage
82%
Covered lines: 281
Uncovered lines: 58
Coverable lines: 339
Total lines: 1772
Line coverage: 82.8%
Branch coverage
75%
Covered branches: 120
Total branches: 160
Branch coverage: 75%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.ctor(...)100%22100%
CreateSessionEncoder()100%11100%
TakeStreamedWriter(...)100%11100%
ReturnStreamedWriter(...)100%11100%
TakeBufferedWriter()100%66100%
ReturnMessageWriter(...)100%11100%
TakeStreamedReader(...)100%11100%
ReturnStreamedReader(...)100%110%
TakeBufferedData(...)100%66100%
ReturnBufferedData(...)100%110%
.ctor(...)100%11100%
SetMessageEncoder(...)100%11100%
TakeXmlReader()100%11100%
ReturnXmlReader(...)100%110%
OnClosed()100%110%
.ctor(...)100%11100%
.ctor(...)100%11100%
TakeXmlWriter(...)100%11100%
ReturnXmlWriter(...)100%22100%
.ctor(...)100%1010100%
AddSessionInformationToMessage(...)80%101080.64%
ExtractSessionInformationFromMessage(...)62.5%161680%
ReadMessage(...)92.85%141488%
ReadMessageAsync(...)75%4490%
WriteMessage(...)75%202074.19%
WriteMessageAsync()75%8887.5%
IsContentTypeSupported(...)8.33%121230%
SetSessionContentType(...)75%4466.66%
AddCompressedMessageProperties(...)100%11100%
ContentTypeEqualsOrStartsWith(...)50%22100%
CheckContentType(...)68.75%161671.42%
CheckCompressedWrite(...)87.5%161690.9%
.ctor(...)100%11100%
TryAdd(...)62.5%8862.5%
GetNewStrings()100%11100%
ClearNewStrings()100%11100%

File(s)

/home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/Channels/BinaryMessageEncoderFactory.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.IO;
 7using System.Text;
 8using System.Threading.Tasks;
 9using System.Xml;
 10using CoreWCF.Runtime;
 11using CoreWCF.Xml;
 12
 13namespace CoreWCF.Channels
 14{
 15    internal class BinaryMessageEncoderFactory : MessageEncoderFactory
 16    {
 17        private const int maxPooledXmlReaderPerMessage = 2;
 18        private readonly BinaryMessageEncoder _messageEncoder;
 19        private readonly MessageVersion _messageVersion;
 20
 21        // Double-checked locking pattern requires volatile for read/write synchronization
 22        //volatile SynchronizedPool<XmlDictionaryWriter> streamedWriterPool;
 23        //volatile SynchronizedPool<XmlDictionaryReader> streamedReaderPool;
 24        private volatile SynchronizedPool<BinaryBufferedMessageData> _bufferedDataPool;
 25        private volatile SynchronizedPool<BinaryBufferedMessageWriter> _bufferedWriterPool;
 26        private volatile SynchronizedPool<RecycledMessageState> _recycledStatePool;
 27        private readonly OnXmlDictionaryReaderClose _onStreamedReaderClose;
 28        private readonly XmlDictionaryReaderQuotas _bufferedReadReaderQuotas;
 29        private readonly BinaryVersion _binaryVersion;
 30
 35531        public BinaryMessageEncoderFactory(MessageVersion messageVersion, int maxReadPoolSize, int maxWritePoolSize, int
 35532            XmlDictionaryReaderQuotas readerQuotas, long maxReceivedMessageSize, BinaryVersion version, CompressionForma
 33        {
 35534            _messageVersion = messageVersion;
 35535            MaxReadPoolSize = maxReadPoolSize;
 35536            MaxWritePoolSize = maxWritePoolSize;
 35537            MaxSessionSize = maxSessionSize;
 35538            ThisLock = new object();
 35539            _onStreamedReaderClose = new OnXmlDictionaryReaderClose(ReturnStreamedReader);
 35540            ReaderQuotas = new XmlDictionaryReaderQuotas();
 35541            if (readerQuotas != null)
 42            {
 35543                readerQuotas.CopyTo(ReaderQuotas);
 44            }
 45
 35546            _bufferedReadReaderQuotas = EncoderHelpers.GetBufferedReadQuotas(ReaderQuotas);
 35547            MaxReceivedMessageSize = maxReceivedMessageSize;
 48
 35549            _binaryVersion = version;
 35550            CompressionFormat = compressionFormat;
 35551            _messageEncoder = new BinaryMessageEncoder(this, false, 0);
 35552        }
 53
 54        public static IXmlDictionary XmlDictionary
 55        {
 056            get { return XD.Dictionary; }
 57        }
 58
 59        public override MessageEncoder Encoder
 60        {
 61            get
 62            {
 17463                return _messageEncoder;
 64            }
 65        }
 66
 67        public override MessageVersion MessageVersion
 68        {
 30369            get { return _messageVersion; }
 70        }
 71
 1772        public int MaxWritePoolSize { get; }
 73
 76574        public XmlDictionaryReaderQuotas ReaderQuotas { get; }
 75
 12676        public int MaxReadPoolSize { get; }
 77
 13478        public int MaxSessionSize { get; }
 79
 126380        public CompressionFormat CompressionFormat { get; }
 81
 82        private long MaxReceivedMessageSize
 83        {
 48984            get;
 35585            set;
 86        }
 87
 14388        private object ThisLock { get; }
 89
 90        private SynchronizedPool<RecycledMessageState> RecycledStatePool
 91        {
 92            get
 93            {
 9194                if (_recycledStatePool == null)
 95                {
 6396                    lock (ThisLock)
 97                    {
 6398                        if (_recycledStatePool == null)
 99                        {
 100                            //running = true;
 63101                            _recycledStatePool = new SynchronizedPool<RecycledMessageState>(MaxReadPoolSize);
 102                        }
 63103                    }
 104                }
 91105                return _recycledStatePool;
 106            }
 107        }
 108
 109        public override MessageEncoder CreateSessionEncoder()
 110        {
 134111            return new BinaryMessageEncoder(this, true, MaxSessionSize);
 112        }
 113
 114        private XmlDictionaryWriter TakeStreamedWriter(Stream stream)
 115        {
 47116            return XmlDictionaryWriter.CreateBinaryWriter(stream, _binaryVersion.Dictionary, null, false);
 117            // TODO: Revert once IXmlBinaryWriterInitializer is available
 118            //if (streamedWriterPool == null)
 119            //{
 120            //    lock (ThisLock)
 121            //    {
 122            //        if (streamedWriterPool == null)
 123            //        {
 124            //            //running = true;
 125            //            streamedWriterPool = new SynchronizedPool<XmlDictionaryWriter>(maxWritePoolSize);
 126            //        }
 127            //    }
 128            //}
 129            //XmlDictionaryWriter xmlWriter = streamedWriterPool.Take();
 130            //if (xmlWriter == null)
 131            //{
 132            //    xmlWriter = XmlDictionaryWriter.CreateBinaryWriter(stream, binaryVersion.Dictionary, null, false);
 133            //}
 134            //else
 135            //{
 136            //    ((IXmlBinaryWriterInitializer)xmlWriter).SetOutput(stream, binaryVersion.Dictionary, null, false);
 137            //}
 138            //return xmlWriter;
 139        }
 140
 141        private void ReturnStreamedWriter(XmlDictionaryWriter xmlWriter)
 142        {
 47143            xmlWriter.Dispose();
 144            //streamedWriterPool.Return(xmlWriter);
 47145        }
 146
 147        private BinaryBufferedMessageWriter TakeBufferedWriter()
 148        {
 17149            if (_bufferedWriterPool == null)
 150            {
 17151                lock (ThisLock)
 152                {
 17153                    if (_bufferedWriterPool == null)
 154                    {
 155                        //running = true;
 17156                        _bufferedWriterPool = new SynchronizedPool<BinaryBufferedMessageWriter>(MaxWritePoolSize);
 157                    }
 17158                }
 159            }
 160
 17161            BinaryBufferedMessageWriter messageWriter = _bufferedWriterPool.Take();
 17162            if (messageWriter == null)
 163            {
 17164                messageWriter = new BinaryBufferedMessageWriter(_binaryVersion.Dictionary);
 165            }
 17166            return messageWriter;
 167        }
 168
 169        private void ReturnMessageWriter(BinaryBufferedMessageWriter messageWriter)
 170        {
 17171            _bufferedWriterPool.Return(messageWriter);
 17172        }
 173
 174        private XmlDictionaryReader TakeStreamedReader(Stream stream)
 175        {
 55176            return XmlDictionaryReader.CreateBinaryReader(stream,
 55177                _binaryVersion.Dictionary,
 55178                ReaderQuotas,
 55179                null);
 180            // TODO: Revert once IXmlBinaryReaderInitializer is available
 181            //if (streamedReaderPool == null)
 182            //{
 183            //    lock (ThisLock)
 184            //    {
 185            //        if (streamedReaderPool == null)
 186            //        {
 187            //            //running = true;
 188            //            streamedReaderPool = new SynchronizedPool<XmlDictionaryReader>(maxReadPoolSize);
 189            //        }
 190            //    }
 191            //}
 192
 193            //XmlDictionaryReader xmlReader = streamedReaderPool.Take();
 194            //if (xmlReader == null)
 195            //{
 196            //    xmlReader = XmlDictionaryReader.CreateBinaryReader(stream,
 197            //        binaryVersion.Dictionary,
 198            //        readerQuotas,
 199            //        null,
 200            //        onStreamedReaderClose);
 201            //    if (TD.ReadPoolMissIsEnabled())
 202            //    {
 203            //        TD.ReadPoolMiss(xmlReader.GetType().Name);
 204            //    }
 205            //}
 206            //else
 207            //{
 208            //    ((IXmlBinaryReaderInitializer)xmlReader).SetInput(stream,
 209            //        binaryVersion.Dictionary,
 210            //        readerQuotas,
 211            //        null,
 212            //        onStreamedReaderClose);
 213            //}
 214
 215            //return xmlReader;
 216        }
 217
 218        private void ReturnStreamedReader(XmlDictionaryReader xmlReader)
 219        {
 220            //streamedReaderPool.Return(xmlReader);
 0221        }
 222
 223        private BinaryBufferedMessageData TakeBufferedData(BinaryMessageEncoder messageEncoder)
 224        {
 91225            if (_bufferedDataPool == null)
 226            {
 63227                lock (ThisLock)
 228                {
 63229                    if (_bufferedDataPool == null)
 230                    {
 231                        //running = true;
 63232                        _bufferedDataPool = new SynchronizedPool<BinaryBufferedMessageData>(MaxReadPoolSize);
 233                    }
 63234                }
 235            }
 91236            BinaryBufferedMessageData messageData = _bufferedDataPool.Take();
 91237            if (messageData == null)
 238            {
 91239                messageData = new BinaryBufferedMessageData(this, maxPooledXmlReaderPerMessage);
 240            }
 91241            messageData.SetMessageEncoder(messageEncoder);
 91242            return messageData;
 243        }
 244
 245        private void ReturnBufferedData(BinaryBufferedMessageData messageData)
 246        {
 0247            messageData.SetMessageEncoder(null);
 0248            _bufferedDataPool.Return(messageData);
 0249        }
 250
 251        private class BinaryBufferedMessageData : BufferedMessageData
 252        {
 253            private readonly BinaryMessageEncoderFactory _factory;
 254            private BinaryMessageEncoder _messageEncoder;
 255            private readonly Pool<XmlDictionaryReader> _readerPool;
 256            private readonly OnXmlDictionaryReaderClose _onClose;
 257
 258            public BinaryBufferedMessageData(BinaryMessageEncoderFactory factory, int maxPoolSize)
 91259                : base(factory.RecycledStatePool)
 260            {
 91261                _factory = factory;
 91262                _readerPool = new Pool<XmlDictionaryReader>(maxPoolSize);
 91263                _onClose = new OnXmlDictionaryReaderClose(OnXmlReaderClosed);
 91264            }
 265
 266            public override MessageEncoder MessageEncoder
 267            {
 23268                get { return _messageEncoder; }
 269            }
 270
 271            public override XmlDictionaryReaderQuotas Quotas
 272            {
 0273                get { return _factory.ReaderQuotas; }
 274            }
 275
 276            public void SetMessageEncoder(BinaryMessageEncoder messageEncoder)
 277            {
 91278                _messageEncoder = messageEncoder;
 91279            }
 280
 281            protected override XmlDictionaryReader TakeXmlReader()
 282            {
 145283                ArraySegment<byte> buffer = Buffer;
 284
 145285                return XmlDictionaryReader.CreateBinaryReader(buffer.Array, buffer.Offset, buffer.Count,
 145286                                        _factory._binaryVersion.Dictionary,
 145287                                        _factory._bufferedReadReaderQuotas,
 145288                                        _messageEncoder.ReaderSession);
 289                // TODO: Revert once IXmlBinaryReaderInitializer is available
 290                //ArraySegment<byte> buffer = this.Buffer;
 291                //XmlDictionaryReader xmlReader = readerPool.Take();
 292
 293                //if (xmlReader != null)
 294                //{
 295                //    ((IXmlBinaryReaderInitializer)xmlReader).SetInput(buffer.Array, buffer.Offset, buffer.Count,
 296                //        factory.binaryVersion.Dictionary,
 297                //        factory.bufferedReadReaderQuotas,
 298                //        messageEncoder.ReaderSession,
 299                //        onClose);
 300                //}
 301                //else
 302                //{
 303                //    xmlReader = XmlDictionaryReader.CreateBinaryReader(buffer.Array, buffer.Offset, buffer.Count,
 304                //        factory.binaryVersion.Dictionary,
 305                //        factory.bufferedReadReaderQuotas,
 306                //        messageEncoder.ReaderSession,
 307                //        onClose);
 308                //    if (TD.ReadPoolMissIsEnabled())
 309                //    {
 310                //        TD.ReadPoolMiss(xmlReader.GetType().Name);
 311                //    }
 312                //}
 313
 314                //return xmlReader;
 315            }
 316
 317            protected override void ReturnXmlReader(XmlDictionaryReader reader)
 318            {
 0319                _readerPool.Return(reader);
 0320            }
 321
 322            protected override void OnClosed()
 323            {
 0324                _factory.ReturnBufferedData(this);
 0325            }
 326        }
 327
 328        private class BinaryBufferedMessageWriter : BufferedMessageWriter
 329        {
 330            private XmlDictionaryWriter _writer;
 331            private readonly IXmlDictionary _dictionary;
 332            private readonly XmlBinaryWriterSession _session;
 333
 17334            public BinaryBufferedMessageWriter(IXmlDictionary dictionary)
 335            {
 17336                _dictionary = dictionary;
 17337            }
 338
 68339            public BinaryBufferedMessageWriter(IXmlDictionary dictionary, XmlBinaryWriterSession session)
 340            {
 68341                _dictionary = dictionary;
 68342                _session = session;
 68343            }
 344
 345            protected override XmlDictionaryWriter TakeXmlWriter(Stream stream)
 346            {
 98347                return XmlDictionaryWriter.CreateBinaryWriter(stream, _dictionary, _session, false);
 348                // TODO: Revert once IXmlBinaryReaderInitializer is available
 349                //XmlDictionaryWriter returnedWriter = writer;
 350                //if (returnedWriter == null)
 351                //{
 352                //    returnedWriter = XmlDictionaryWriter.CreateBinaryWriter(stream, dictionary, session, false);
 353                //}
 354                //else
 355                //{
 356                //    writer = null;
 357                //    ((IXmlBinaryWriterInitializer)returnedWriter).SetOutput(stream, dictionary, session, false);
 358                //}
 359                //return returnedWriter;
 360            }
 361
 362            protected override void ReturnXmlWriter(XmlDictionaryWriter writer)
 363            {
 98364                writer.Dispose();
 365
 98366                if (_writer == null)
 367                {
 85368                    _writer = writer;
 369                }
 98370            }
 371        }
 372
 373        private class BinaryMessageEncoder : MessageEncoder, ICompressedMessageEncoder
 374        {
 375            private const string SupportedCompressionTypesMessageProperty = "BinaryMessageEncoder.SupportedCompressionTy
 376            private readonly BinaryMessageEncoderFactory _factory;
 377            private readonly bool _isSession;
 378            private XmlBinaryWriterSessionWithQuota _writerSession;
 379            private BinaryBufferedMessageWriter _sessionMessageWriter;
 380
 381            //XmlBinaryReaderSession readerSessionForLogging;
 382            //bool readerSessionForLoggingIsInvalid = false;
 383            //int writeIdCounter;
 384            private int _idCounter;
 385            private readonly int _maxSessionSize;
 386            private int _remainingReaderSessionSize;
 387            private bool _isReaderSessionInvalid;
 388            private MessagePatterns _messagePatterns;
 389            private readonly string _contentType;
 390            private readonly string _normalContentType;
 391            private readonly string _gzipCompressedContentType;
 392            private readonly string _deflateCompressedContentType;
 393            private CompressionFormat _sessionCompressionFormat;
 394            private readonly long _maxReceivedMessageSize;
 395
 489396            public BinaryMessageEncoder(BinaryMessageEncoderFactory factory, bool isSession, int maxSessionSize)
 397            {
 489398                _factory = factory;
 489399                _isSession = isSession;
 489400                _maxSessionSize = maxSessionSize;
 489401                _remainingReaderSessionSize = maxSessionSize;
 489402                _normalContentType = isSession ? factory._binaryVersion.SessionContentType : factory._binaryVersion.Cont
 489403                _gzipCompressedContentType = isSession ? BinaryVersion.GZipVersion1.SessionContentType : BinaryVersion.G
 489404                _deflateCompressedContentType = isSession ? BinaryVersion.DeflateVersion1.SessionContentType : BinaryVer
 489405                _sessionCompressionFormat = _factory.CompressionFormat;
 489406                _maxReceivedMessageSize = _factory.MaxReceivedMessageSize;
 407
 489408                switch (_factory.CompressionFormat)
 409                {
 410                    case CompressionFormat.Deflate:
 13411                        _contentType = _deflateCompressedContentType;
 13412                        break;
 413                    case CompressionFormat.GZip:
 13414                        _contentType = _gzipCompressedContentType;
 13415                        break;
 416                    default:
 463417                        _contentType = _normalContentType;
 418                        break;
 419                }
 463420            }
 421
 422            public override string ContentType
 423            {
 424                get
 425                {
 190426                    return _contentType;
 427                }
 428            }
 429
 430            public override MessageVersion MessageVersion
 431            {
 300432                get { return _factory._messageVersion; }
 433            }
 434
 435            public override string MediaType
 436            {
 70437                get { return _contentType; }
 438            }
 439
 690440            public XmlBinaryReaderSession ReaderSession { get; private set; }
 441
 442            public bool CompressionEnabled
 443            {
 258444                get { return _factory.CompressionFormat != CompressionFormat.None; }
 445            }
 446
 447            private ArraySegment<byte> AddSessionInformationToMessage(ArraySegment<byte> messageData, BufferManager buff
 448            {
 81449                int dictionarySize = 0;
 81450                byte[] buffer = messageData.Array;
 451
 81452                if (_writerSession.HasNewStrings)
 453                {
 68454                    IList<XmlDictionaryString> newStrings = _writerSession.GetNewStrings();
 666455                    for (int i = 0; i < newStrings.Count; i++)
 456                    {
 265457                        int utf8ValueSize = Encoding.UTF8.GetByteCount(newStrings[i].Value);
 265458                        dictionarySize += IntEncoder.GetEncodedSize(utf8ValueSize) + utf8ValueSize;
 459                    }
 460
 68461                    int messageSize = messageData.Offset + messageData.Count;
 68462                    int remainingMessageSize = maxMessageSize - messageSize;
 68463                    if (remainingMessageSize - dictionarySize < 0)
 464                    {
 0465                        string excMsg = SR.Format(SRCommon.MaxSentMessageSizeExceeded, maxMessageSize);
 0466                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new QuotaExceededException(excMsg));
 467                    }
 468
 68469                    int requiredBufferSize = messageData.Offset + messageData.Count + dictionarySize;
 68470                    if (buffer.Length < requiredBufferSize)
 471                    {
 0472                        byte[] newBuffer = bufferManager.TakeBuffer(requiredBufferSize);
 0473                        Buffer.BlockCopy(buffer, messageData.Offset, newBuffer, messageData.Offset, messageData.Count);
 0474                        bufferManager.ReturnBuffer(buffer);
 0475                        buffer = newBuffer;
 476                    }
 477
 68478                    Buffer.BlockCopy(buffer, messageData.Offset, buffer, messageData.Offset + dictionarySize, messageDat
 479
 68480                    int offset = messageData.Offset;
 666481                    for (int i = 0; i < newStrings.Count; i++)
 482                    {
 265483                        string newString = newStrings[i].Value;
 265484                        int utf8ValueSize = Encoding.UTF8.GetByteCount(newString);
 265485                        offset += IntEncoder.Encode(utf8ValueSize, buffer, offset);
 265486                        offset += Encoding.UTF8.GetBytes(newString, 0, newString.Length, buffer, offset);
 487                    }
 488
 68489                    _writerSession.ClearNewStrings();
 490                }
 491
 81492                int headerSize = IntEncoder.GetEncodedSize(dictionarySize);
 81493                int newOffset = messageData.Offset - headerSize;
 81494                int newSize = headerSize + messageData.Count + dictionarySize;
 81495                IntEncoder.Encode(dictionarySize, buffer, newOffset);
 81496                return new ArraySegment<byte>(buffer, newOffset, newSize);
 497            }
 498
 499            private ArraySegment<byte> ExtractSessionInformationFromMessage(ArraySegment<byte> messageData)
 500            {
 81501                if (_isReaderSessionInvalid)
 502                {
 0503                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataException(SR.BinaryEncoderS
 504                }
 505
 81506                byte[] buffer = messageData.Array;
 507                int dictionarySize;
 508                int headerSize;
 509                int newOffset;
 510                int newSize;
 81511                bool throwing = true;
 512                try
 513                {
 81514                    IntDecoder decoder = new IntDecoder();
 81515                    headerSize = decoder.Decode(buffer, messageData.Offset, messageData.Count);
 81516                    dictionarySize = decoder.Value;
 81517                    if (dictionarySize > messageData.Count)
 518                    {
 0519                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataException(SR.BinaryEnco
 520                    }
 81521                    newOffset = messageData.Offset + headerSize + dictionarySize;
 81522                    newSize = messageData.Count - headerSize - dictionarySize;
 81523                    if (newSize < 0)
 524                    {
 0525                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataException(SR.BinaryEnco
 526                    }
 81527                    if (dictionarySize > 0)
 528                    {
 79529                        if (dictionarySize > _remainingReaderSessionSize)
 530                        {
 0531                            string message = SR.Format(SR.BinaryEncoderSessionTooLarge, _maxSessionSize);
 0532                            Exception inner = new QuotaExceededException(message);
 0533                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(message
 534                        }
 535                        else
 536                        {
 79537                            _remainingReaderSessionSize -= dictionarySize;
 538                        }
 539
 79540                        int size = dictionarySize;
 79541                        int offset = messageData.Offset + headerSize;
 542
 407543                        while (size > 0)
 544                        {
 328545                            decoder.Reset();
 328546                            int bytesDecoded = decoder.Decode(buffer, offset, size);
 328547                            int utf8ValueSize = decoder.Value;
 328548                            offset += bytesDecoded;
 328549                            size -= bytesDecoded;
 328550                            if (utf8ValueSize > size)
 551                            {
 0552                                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataException(SR.Bi
 553                            }
 328554                            string value = Encoding.UTF8.GetString(buffer, offset, utf8ValueSize);
 328555                            offset += utf8ValueSize;
 328556                            size -= utf8ValueSize;
 328557                            ReaderSession.Add(_idCounter, value);
 328558                            _idCounter++;
 559                        }
 560                    }
 81561                    throwing = false;
 81562                }
 563                finally
 564                {
 81565                    if (throwing)
 566                    {
 0567                        _isReaderSessionInvalid = true;
 568                    }
 81569                }
 570
 81571                return new ArraySegment<byte>(buffer, newOffset, newSize);
 572            }
 573
 574            public override Message ReadMessage(ArraySegment<byte> buffer, BufferManager bufferManager, string contentTy
 575            {
 91576                if (bufferManager == null)
 577                {
 0578                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(bufferManager));
 579                }
 580
 91581                CompressionFormat compressionFormat = CheckContentType(contentType);
 582
 91583                if (compressionFormat != CompressionFormat.None)
 584                {
 6585                    MessageEncoderCompressionHandler.DecompressBuffer(ref buffer, bufferManager, compressionFormat, _max
 586                }
 587
 91588                if (_isSession)
 589                {
 81590                    if (ReaderSession == null)
 591                    {
 68592                        ReaderSession = new XmlBinaryReaderSession();
 68593                        _messagePatterns = new MessagePatterns(_factory._binaryVersion.Dictionary, ReaderSession, Messag
 594                    }
 595                    try
 596                    {
 81597                        buffer = ExtractSessionInformationFromMessage(buffer);
 81598                    }
 0599                    catch (InvalidDataException)
 600                    {
 601                        //MessageLogger.LogMessage(buffer, MessageLoggingSource.Malformed);
 0602                        throw;
 603                    }
 604                }
 91605                BinaryBufferedMessageData messageData = _factory.TakeBufferedData(this);
 606                Message message;
 91607                if (_messagePatterns != null)
 608                {
 81609                    message = _messagePatterns.TryCreateMessage(buffer.Array, buffer.Offset, buffer.Count, bufferManager
 610                }
 611                else
 612                {
 10613                    message = null;
 614                }
 91615                if (message == null)
 616                {
 23617                    messageData.Open(buffer, bufferManager);
 23618                    RecycledMessageState messageState = messageData.TakeMessageState();
 23619                    if (messageState == null)
 620                    {
 23621                        messageState = new RecycledMessageState();
 622                    }
 23623                    message = new BufferedMessage(messageData, messageState);
 624                }
 91625                message.Properties.Encoder = this;
 626
 91627                return message;
 628            }
 629
 630            public override Task<Message> ReadMessageAsync(Stream stream, int maxSizeOfHeaders, string contentType)
 631            {
 55632                if (stream == null)
 633                {
 0634                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(stream));
 635                }
 636
 55637                CompressionFormat compressionFormat = CheckContentType(contentType);
 638
 55639                if (compressionFormat != CompressionFormat.None)
 640                {
 12641                    stream = new MaxMessageSizeStream(
 12642                        MessageEncoderCompressionHandler.GetDecompressStream(stream, compressionFormat), _maxReceivedMes
 643                }
 644
 55645                XmlDictionaryReader reader = _factory.TakeStreamedReader(stream);
 55646                Message message = Message.CreateMessage(reader, maxSizeOfHeaders, _factory._messageVersion);
 55647                message.Properties.Encoder = this;
 648
 55649                return Task.FromResult(message);
 650            }
 651
 652            public override ArraySegment<byte> WriteMessage(Message message, int maxMessageSize, BufferManager bufferMan
 653            {
 98654                if (message == null)
 655                {
 0656                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(message));
 657                }
 658
 98659                if (bufferManager == null)
 660                {
 0661                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(bufferManager));
 662                }
 663
 98664                if (maxMessageSize < 0)
 665                {
 0666                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(max
 0667                        SRCommon.ValueMustBeNonNegative));
 668                }
 669
 98670                message.Properties.Encoder = this;
 671
 98672                if (_isSession)
 673                {
 81674                    if (_writerSession == null)
 675                    {
 68676                        _writerSession = new XmlBinaryWriterSessionWithQuota(_maxSessionSize);
 68677                        _sessionMessageWriter = new BinaryBufferedMessageWriter(_factory._binaryVersion.Dictionary, _wri
 678                    }
 81679                    messageOffset += IntEncoder.MaxEncodedSize;
 680                }
 681
 98682                if (messageOffset < 0)
 683                {
 0684                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(mes
 0685                        SRCommon.ValueMustBeNonNegative));
 686                }
 687
 98688                if (messageOffset > maxMessageSize)
 689                {
 0690                    string excMsg = SR.Format(SRCommon.MaxSentMessageSizeExceeded, maxMessageSize);
 691
 0692                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new QuotaExceededException(excMsg));
 693                }
 694
 98695                ThrowIfMismatchedMessageVersion(message);
 696                BinaryBufferedMessageWriter messageWriter;
 98697                if (_isSession)
 698                {
 81699                    messageWriter = _sessionMessageWriter;
 700                }
 701                else
 702                {
 17703                    messageWriter = _factory.TakeBufferedWriter();
 704                }
 98705                ArraySegment<byte> messageData = messageWriter.WriteMessage(message, bufferManager, messageOffset, maxMe
 706
 707                //this.readerSessionForLoggingIsInvalid = true;
 708
 98709                if (_isSession)
 710                {
 81711                    messageData = AddSessionInformationToMessage(messageData, bufferManager, maxMessageSize);
 712                }
 713                else
 714                {
 17715                    _factory.ReturnMessageWriter(messageWriter);
 716                }
 717
 98718                CompressionFormat compressionFormat = CheckCompressedWrite(message);
 98719                if (compressionFormat != CompressionFormat.None)
 720                {
 10721                    MessageEncoderCompressionHandler.CompressBuffer(ref messageData, bufferManager, compressionFormat);
 722                }
 723
 98724                return messageData;
 725            }
 726
 727            public override async Task WriteMessageAsync(Message message, Stream stream)
 728            {
 47729                if (message == null)
 730                {
 0731                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(message))
 732                }
 47733                if (stream == null)
 734                {
 0735                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(stream)))
 736                }
 737
 47738                CompressionFormat compressionFormat = CheckCompressedWrite(message);
 47739                if (compressionFormat != CompressionFormat.None)
 740                {
 8741                    stream = MessageEncoderCompressionHandler.GetCompressStream(stream, compressionFormat);
 742                }
 743
 47744                ThrowIfMismatchedMessageVersion(message);
 47745                message.Properties.Encoder = this;
 47746                XmlDictionaryWriter xmlWriter = _factory.TakeStreamedWriter(stream);
 47747                await message.WriteMessageAsync(xmlWriter);
 47748                xmlWriter.Flush();
 749
 47750                _factory.ReturnStreamedWriter(xmlWriter);
 47751                if (compressionFormat != CompressionFormat.None)
 752                {
 8753                    stream.Dispose();
 754                }
 47755            }
 756
 757            public override bool IsContentTypeSupported(string contentType)
 758            {
 70759                bool supported = true;
 70760                if (!base.IsContentTypeSupported(contentType))
 761                {
 0762                    if (CompressionEnabled)
 763                    {
 0764                        supported = (_factory.CompressionFormat == CompressionFormat.GZip &&
 0765                            IsContentTypeSupported(contentType, _gzipCompressedContentType, _gzipCompressedContentType))
 0766                            (_factory.CompressionFormat == CompressionFormat.Deflate &&
 0767                            IsContentTypeSupported(contentType, _deflateCompressedContentType, _deflateCompressedContent
 0768                            IsContentTypeSupported(contentType, _normalContentType, _normalContentType);
 769                    }
 770                    else
 771                    {
 0772                        supported = false;
 773                    }
 774                }
 70775                return supported;
 776            }
 777
 778            public void SetSessionContentType(string contentType)
 779            {
 4780                if (IsContentTypeSupported(contentType, _gzipCompressedContentType, _gzipCompressedContentType))
 781                {
 2782                    _sessionCompressionFormat = CompressionFormat.GZip;
 783                }
 2784                else if (IsContentTypeSupported(contentType, _deflateCompressedContentType, _deflateCompressedContentTyp
 785                {
 2786                    _sessionCompressionFormat = CompressionFormat.Deflate;
 787                }
 788                else
 789                {
 0790                    _sessionCompressionFormat = CompressionFormat.None;
 791                }
 0792            }
 793
 794            public void AddCompressedMessageProperties(Message message, string supportedCompressionTypes)
 795            {
 14796                message.Properties.Add(SupportedCompressionTypesMessageProperty, supportedCompressionTypes);
 14797            }
 798
 799            private static bool ContentTypeEqualsOrStartsWith(string contentType, string supportedContentType)
 800            {
 132801                return contentType == supportedContentType || contentType.StartsWith(supportedContentType, StringCompari
 802            }
 803
 804            private CompressionFormat CheckContentType(string contentType)
 805            {
 146806                CompressionFormat compressionFormat = CompressionFormat.None;
 146807                if (contentType == null)
 808                {
 14809                    compressionFormat = _sessionCompressionFormat;
 810                }
 811                else
 812                {
 132813                    if (!CompressionEnabled)
 814                    {
 114815                        if (!ContentTypeEqualsOrStartsWith(contentType, ContentType))
 816                        {
 0817                            throw Fx.Exception.AsError(new ProtocolException(SR.Format(SR.EncoderUnrecognizedContentType
 818                        }
 819                    }
 820                    else
 821                    {
 18822                        if (_factory.CompressionFormat == CompressionFormat.GZip && ContentTypeEqualsOrStartsWith(conten
 823                        {
 9824                            compressionFormat = CompressionFormat.GZip;
 825                        }
 9826                        else if (_factory.CompressionFormat == CompressionFormat.Deflate && ContentTypeEqualsOrStartsWit
 827                        {
 9828                            compressionFormat = CompressionFormat.Deflate;
 829                        }
 0830                        else if (ContentTypeEqualsOrStartsWith(contentType, _normalContentType))
 831                        {
 0832                            compressionFormat = CompressionFormat.None;
 833                        }
 834                        else
 835                        {
 0836                            throw Fx.Exception.AsError(new ProtocolException(SR.Format(SR.EncoderUnrecognizedContentType
 837                        }
 838                    }
 839                }
 840
 146841                return compressionFormat;
 842            }
 843
 844            private CompressionFormat CheckCompressedWrite(Message message)
 845            {
 145846                CompressionFormat compressionFormat = _sessionCompressionFormat;
 145847                if (compressionFormat != CompressionFormat.None && !_isSession)
 848                {
 14849                    if (message.Properties.TryGetValue<string>(SupportedCompressionTypesMessageProperty, out string acce
 14850                        acceptEncoding != null)
 851                    {
 14852                        acceptEncoding = acceptEncoding.ToLowerInvariant();
 14853                        if ((compressionFormat == CompressionFormat.GZip &&
 14854                            !acceptEncoding.Contains(MessageEncoderCompressionHandler.GZipContentEncoding)) ||
 14855                            (compressionFormat == CompressionFormat.Deflate &&
 14856                            !acceptEncoding.Contains(MessageEncoderCompressionHandler.DeflateContentEncoding)))
 857                        {
 0858                            compressionFormat = CompressionFormat.None;
 859                        }
 860                    }
 861                }
 145862                return compressionFormat;
 863            }
 864        }
 865
 866        private class XmlBinaryWriterSessionWithQuota : XmlBinaryWriterSession
 867        {
 868            private int _bytesRemaining;
 869            private List<XmlDictionaryString> _newStrings;
 870
 68871            public XmlBinaryWriterSessionWithQuota(int maxSessionSize)
 872            {
 68873                _bytesRemaining = maxSessionSize;
 68874            }
 875
 876            public bool HasNewStrings
 877            {
 81878                get { return _newStrings != null; }
 879            }
 880
 881            public override bool TryAdd(XmlDictionaryString s, out int key)
 882            {
 265883                if (_bytesRemaining == 0)
 884                {
 0885                    key = -1;
 0886                    return false;
 887                }
 888
 265889                int bytesRequired = Encoding.UTF8.GetByteCount(s.Value);
 265890                bytesRequired += IntEncoder.GetEncodedSize(bytesRequired);
 891
 265892                if (bytesRequired > _bytesRemaining)
 893                {
 0894                    key = -1;
 0895                    _bytesRemaining = 0;
 0896                    return false;
 897                }
 898
 265899                if (base.TryAdd(s, out key))
 900                {
 265901                    if (_newStrings == null)
 902                    {
 68903                        _newStrings = new List<XmlDictionaryString>();
 904                    }
 265905                    _newStrings.Add(s);
 265906                    _bytesRemaining -= bytesRequired;
 265907                    return true;
 908                }
 909                else
 910                {
 0911                    return false;
 912                }
 913            }
 914
 915            public IList<XmlDictionaryString> GetNewStrings()
 916            {
 68917                return _newStrings;
 918            }
 919
 920            public void ClearNewStrings()
 921            {
 68922                _newStrings = null;
 68923            }
 924        }
 925    }
 926
 927    internal class BinaryFormatBuilder
 928    {
 929        private readonly List<byte> _bytes;
 930
 931        public BinaryFormatBuilder()
 932        {
 933            _bytes = new List<byte>();
 934        }
 935
 936        public int Count
 937        {
 938            get { return _bytes.Count; }
 939        }
 940
 941        public void AppendPrefixDictionaryElement(char prefix, int key)
 942        {
 943            AppendNode(XmlBinaryNodeType.PrefixDictionaryElementA + GetPrefixOffset(prefix));
 944            AppendKey(key);
 945        }
 946
 947        public void AppendDictionaryXmlnsAttribute(char prefix, int key)
 948        {
 949            AppendNode(XmlBinaryNodeType.DictionaryXmlnsAttribute);
 950            AppendUtf8(prefix);
 951            AppendKey(key);
 952        }
 953
 954        public void AppendPrefixDictionaryAttribute(char prefix, int key, char value)
 955        {
 956            AppendNode(XmlBinaryNodeType.PrefixDictionaryAttributeA + GetPrefixOffset(prefix));
 957            AppendKey(key);
 958            if (value == '1')
 959            {
 960                AppendNode(XmlBinaryNodeType.OneText);
 961            }
 962            else
 963            {
 964                AppendNode(XmlBinaryNodeType.Chars8Text);
 965                AppendUtf8(value);
 966            }
 967        }
 968
 969        public void AppendDictionaryAttribute(char prefix, int key, char value)
 970        {
 971            AppendNode(XmlBinaryNodeType.DictionaryAttribute);
 972            AppendUtf8(prefix);
 973            AppendKey(key);
 974            AppendNode(XmlBinaryNodeType.Chars8Text);
 975            AppendUtf8(value);
 976        }
 977
 978        public void AppendDictionaryTextWithEndElement(int key)
 979        {
 980            AppendNode(XmlBinaryNodeType.DictionaryTextWithEndElement);
 981            AppendKey(key);
 982        }
 983
 984        public void AppendDictionaryTextWithEndElement()
 985        {
 986            AppendNode(XmlBinaryNodeType.DictionaryTextWithEndElement);
 987        }
 988
 989        public void AppendUniqueIDWithEndElement()
 990        {
 991            AppendNode(XmlBinaryNodeType.UniqueIdTextWithEndElement);
 992        }
 993
 994        public void AppendEndElement()
 995        {
 996            AppendNode(XmlBinaryNodeType.EndElement);
 997        }
 998
 999        private void AppendKey(int key)
 1000        {
 1001            if (key < 0 || key >= 0x4000)
 1002            {
 1003                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(key), k
 1004                    SR.Format(SR.ValueMustBeInRange, 0, 0x4000)));
 1005            }
 1006            if (key >= 0x80)
 1007            {
 1008                AppendByte((key & 0x7f) | 0x80);
 1009                AppendByte(key >> 7);
 1010            }
 1011            else
 1012            {
 1013                AppendByte(key);
 1014            }
 1015        }
 1016
 1017        private void AppendNode(XmlBinaryNodeType value)
 1018        {
 1019            AppendByte((int)value);
 1020        }
 1021
 1022        private void AppendByte(int value)
 1023        {
 1024            if (value < 0 || value > 0xFF)
 1025            {
 1026                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(value),
 1027                    SR.Format(SR.ValueMustBeInRange, 0, 0xFF)));
 1028            }
 1029            _bytes.Add((byte)value);
 1030        }
 1031
 1032        private void AppendUtf8(char value)
 1033        {
 1034            AppendByte(1);
 1035            AppendByte((int)value);
 1036        }
 1037
 1038        public int GetStaticKey(int value)
 1039        {
 1040            return value * 2;
 1041        }
 1042
 1043        public int GetSessionKey(int value)
 1044        {
 1045            return value * 2 + 1;
 1046        }
 1047
 1048        private int GetPrefixOffset(char prefix)
 1049        {
 1050            if (prefix < 'a' || prefix > 'z')
 1051            {
 1052                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(prefix)
 1053                    SR.Format(SR.ValueMustBeInRange, 'a', 'z')));
 1054            }
 1055            return prefix - 'a';
 1056        }
 1057
 1058        public byte[] ToByteArray()
 1059        {
 1060            byte[] array = _bytes.ToArray();
 1061            _bytes.Clear();
 1062            return array;
 1063        }
 1064    }
 1065
 1066    internal static class BinaryFormatParser
 1067    {
 1068        public static bool IsSessionKey(int value)
 1069        {
 1070            return (value & 1) != 0;
 1071        }
 1072
 1073        public static int GetSessionKey(int value)
 1074        {
 1075            return value / 2;
 1076        }
 1077
 1078        public static int GetStaticKey(int value)
 1079        {
 1080            return value / 2;
 1081        }
 1082
 1083        public static int ParseInt32(byte[] buffer, int offset, int size)
 1084        {
 1085            switch (size)
 1086            {
 1087                case 1:
 1088                    return buffer[offset];
 1089                case 2:
 1090                    return (buffer[offset] & 0x7f) + (buffer[offset + 1] << 7);
 1091                case 3:
 1092                    return (buffer[offset] & 0x7f) + ((buffer[offset + 1] & 0x7f) << 7) + (buffer[offset + 2] << 14);
 1093                case 4:
 1094                    return (buffer[offset] & 0x7f) + ((buffer[offset + 1] & 0x7f) << 7) + ((buffer[offset + 2] & 0x7f) <
 1095                default:
 1096                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(siz
 1097                        SR.Format(SR.ValueMustBeInRange, 1, 4)));
 1098            }
 1099        }
 1100
 1101        public static int ParseKey(byte[] buffer, int offset, int size)
 1102        {
 1103            return ParseInt32(buffer, offset, size);
 1104        }
 1105
 1106        public static unsafe UniqueId ParseUniqueID(byte[] buffer, int offset, int size)
 1107        {
 1108            return new UniqueId(buffer, offset);
 1109        }
 1110
 1111        public static int MatchBytes(byte[] buffer, int offset, int size, byte[] buffer2)
 1112        {
 1113            if (size < buffer2.Length)
 1114            {
 1115                return 0;
 1116            }
 1117            int j = offset;
 1118            for (int i = 0; i < buffer2.Length; i++, j++)
 1119            {
 1120                if (buffer2[i] != buffer[j])
 1121                {
 1122                    return 0;
 1123                }
 1124            }
 1125            return buffer2.Length;
 1126        }
 1127
 1128
 1129        public static bool MatchAttributeNode(byte[] buffer, int offset, int size)
 1130        {
 1131            const XmlBinaryNodeType minAttribute = XmlBinaryNodeType.ShortAttribute;
 1132            const XmlBinaryNodeType maxAttribute = XmlBinaryNodeType.DictionaryAttribute;
 1133            if (size < 1)
 1134            {
 1135                return false;
 1136            }
 1137            XmlBinaryNodeType nodeType = (XmlBinaryNodeType)buffer[offset];
 1138            return nodeType >= minAttribute && nodeType <= maxAttribute;
 1139        }
 1140
 1141        public static int MatchKey(byte[] buffer, int offset, int size)
 1142        {
 1143            return MatchInt32(buffer, offset, size);
 1144        }
 1145
 1146        public static int MatchInt32(byte[] buffer, int offset, int size)
 1147        {
 1148            if (size > 0)
 1149            {
 1150                if ((buffer[offset] & 0x80) == 0)
 1151                {
 1152                    return 1;
 1153                }
 1154            }
 1155            if (size > 1)
 1156            {
 1157                if ((buffer[offset + 1] & 0x80) == 0)
 1158                {
 1159                    return 2;
 1160                }
 1161            }
 1162            if (size > 2)
 1163            {
 1164                if ((buffer[offset + 2] & 0x80) == 0)
 1165                {
 1166                    return 3;
 1167                }
 1168            }
 1169            if (size > 3)
 1170            {
 1171                if ((buffer[offset + 3] & 0x80) == 0)
 1172                {
 1173                    return 4;
 1174                }
 1175            }
 1176
 1177            return 0;
 1178        }
 1179
 1180        public static int MatchUniqueID(byte[] buffer, int offset, int size)
 1181        {
 1182            if (size < 16)
 1183            {
 1184                return 0;
 1185            }
 1186            return 16;
 1187        }
 1188    }
 1189
 1190    internal class MessagePatterns
 1191    {
 1192        private static readonly byte[] s_commonFragment; // <Envelope><Headers><Action>
 1193        private static readonly byte[] s_requestFragment1; // </Action><MessageID>
 1194        private static readonly byte[] s_requestFragment2; // </MessageID><ReplyTo>...</ReplyTo><To>session-to-key</To><
 1195        private static readonly byte[] s_responseFragment1; // </Action><RelatesTo>
 1196        private static readonly byte[] s_responseFragment2; // </RelatesTo><To>static-anonymous-key</To></Headers><Body>
 1197        private static readonly byte[] s_bodyFragment; // <Envelope><Body>
 1198        private const int ToValueSessionKey = 1;
 1199        private readonly IXmlDictionary _dictionary;
 1200        private readonly XmlBinaryReaderSession _readerSession;
 1201        private ToHeader _toHeader;
 1202        private readonly MessageVersion _messageVersion;
 1203
 1204        static MessagePatterns()
 1205        {
 1206            BinaryFormatBuilder builder = new BinaryFormatBuilder();
 1207
 1208            MessageDictionary messageDictionary = XD.MessageDictionary;
 1209            Message12Dictionary message12Dictionary = XD.Message12Dictionary;
 1210            AddressingDictionary addressingDictionary = XD.AddressingDictionary;
 1211            Addressing10Dictionary addressing10Dictionary = XD.Addressing10Dictionary;
 1212
 1213            char messagePrefix = MessageStrings.Prefix[0];
 1214            char addressingPrefix = AddressingStrings.Prefix[0];
 1215
 1216            // <s:Envelope xmlns:s="soap-ns" xmlns="addressing-ns">
 1217            builder.AppendPrefixDictionaryElement(messagePrefix, builder.GetStaticKey(messageDictionary.Envelope.Key));
 1218            builder.AppendDictionaryXmlnsAttribute(messagePrefix, builder.GetStaticKey(message12Dictionary.Namespace.Key
 1219            builder.AppendDictionaryXmlnsAttribute(addressingPrefix, builder.GetStaticKey(addressing10Dictionary.Namespa
 1220
 1221            // <s:Header>
 1222            builder.AppendPrefixDictionaryElement(messagePrefix, builder.GetStaticKey(messageDictionary.Header.Key));
 1223
 1224            // <a:Action>...
 1225            builder.AppendPrefixDictionaryElement(addressingPrefix, builder.GetStaticKey(addressingDictionary.Action.Key
 1226            builder.AppendPrefixDictionaryAttribute(messagePrefix, builder.GetStaticKey(messageDictionary.MustUnderstand
 1227            builder.AppendDictionaryTextWithEndElement();
 1228            s_commonFragment = builder.ToByteArray();
 1229
 1230            // <a:MessageID>...
 1231            builder.AppendPrefixDictionaryElement(addressingPrefix, builder.GetStaticKey(addressingDictionary.MessageId.
 1232            builder.AppendUniqueIDWithEndElement();
 1233            s_requestFragment1 = builder.ToByteArray();
 1234
 1235            // <a:ReplyTo><a:Address>static-anonymous-key</a:Address></a:ReplyTo>
 1236            builder.AppendPrefixDictionaryElement(addressingPrefix, builder.GetStaticKey(addressingDictionary.ReplyTo.Ke
 1237            builder.AppendPrefixDictionaryElement(addressingPrefix, builder.GetStaticKey(addressingDictionary.Address.Ke
 1238            builder.AppendDictionaryTextWithEndElement(builder.GetStaticKey(addressing10Dictionary.Anonymous.Key));
 1239            builder.AppendEndElement();
 1240
 1241            // <a:To>session-to-key</a:To>
 1242            builder.AppendPrefixDictionaryElement(addressingPrefix, builder.GetStaticKey(addressingDictionary.To.Key));
 1243            builder.AppendPrefixDictionaryAttribute(messagePrefix, builder.GetStaticKey(messageDictionary.MustUnderstand
 1244            builder.AppendDictionaryTextWithEndElement(builder.GetSessionKey(ToValueSessionKey));
 1245
 1246            // </s:Header>
 1247            builder.AppendEndElement();
 1248
 1249            // <s:Body>
 1250            builder.AppendPrefixDictionaryElement(messagePrefix, builder.GetStaticKey(messageDictionary.Body.Key));
 1251            s_requestFragment2 = builder.ToByteArray();
 1252
 1253            // <a:RelatesTo>...
 1254            builder.AppendPrefixDictionaryElement(addressingPrefix, builder.GetStaticKey(addressingDictionary.RelatesTo.
 1255            builder.AppendUniqueIDWithEndElement();
 1256            s_responseFragment1 = builder.ToByteArray();
 1257
 1258            // <a:To>static-anonymous-key</a:To>
 1259            builder.AppendPrefixDictionaryElement(addressingPrefix, builder.GetStaticKey(addressingDictionary.To.Key));
 1260            builder.AppendPrefixDictionaryAttribute(messagePrefix, builder.GetStaticKey(messageDictionary.MustUnderstand
 1261            builder.AppendDictionaryTextWithEndElement(builder.GetStaticKey(addressing10Dictionary.Anonymous.Key));
 1262
 1263            // </s:Header>
 1264            builder.AppendEndElement();
 1265
 1266            // <s:Body>
 1267            builder.AppendPrefixDictionaryElement(messagePrefix, builder.GetStaticKey(messageDictionary.Body.Key));
 1268            s_responseFragment2 = builder.ToByteArray();
 1269
 1270            // <s:Envelope xmlns:s="soap-ns" xmlns="addressing-ns">
 1271            builder.AppendPrefixDictionaryElement(messagePrefix, builder.GetStaticKey(messageDictionary.Envelope.Key));
 1272            builder.AppendDictionaryXmlnsAttribute(messagePrefix, builder.GetStaticKey(message12Dictionary.Namespace.Key
 1273            builder.AppendDictionaryXmlnsAttribute(addressingPrefix, builder.GetStaticKey(addressing10Dictionary.Namespa
 1274
 1275            // <s:Body>
 1276            builder.AppendPrefixDictionaryElement(messagePrefix, builder.GetStaticKey(messageDictionary.Body.Key));
 1277            s_bodyFragment = builder.ToByteArray();
 1278        }
 1279
 1280        public MessagePatterns(IXmlDictionary dictionary, XmlBinaryReaderSession readerSession, MessageVersion messageVe
 1281        {
 1282            _dictionary = dictionary;
 1283            _readerSession = readerSession;
 1284            _messageVersion = messageVersion;
 1285        }
 1286
 1287        public Message TryCreateMessage(byte[] buffer, int offset, int size, BufferManager bufferManager, BufferedMessag
 1288        {
 1289            RelatesToHeader relatesToHeader;
 1290            MessageIDHeader messageIDHeader;
 1291            XmlDictionaryString toString;
 1292
 1293            int currentOffset = offset;
 1294            int remainingSize = size;
 1295
 1296            int bytesMatched = BinaryFormatParser.MatchBytes(buffer, currentOffset, remainingSize, s_commonFragment);
 1297            if (bytesMatched == 0)
 1298            {
 1299                return null;
 1300            }
 1301            currentOffset += bytesMatched;
 1302            remainingSize -= bytesMatched;
 1303
 1304            bytesMatched = BinaryFormatParser.MatchKey(buffer, currentOffset, remainingSize);
 1305            if (bytesMatched == 0)
 1306            {
 1307                return null;
 1308            }
 1309            int actionOffset = currentOffset;
 1310            int actionSize = bytesMatched;
 1311            currentOffset += bytesMatched;
 1312            remainingSize -= bytesMatched;
 1313
 1314            int totalBytesMatched;
 1315
 1316            bytesMatched = BinaryFormatParser.MatchBytes(buffer, currentOffset, remainingSize, s_requestFragment1);
 1317            if (bytesMatched != 0)
 1318            {
 1319                currentOffset += bytesMatched;
 1320                remainingSize -= bytesMatched;
 1321
 1322                bytesMatched = BinaryFormatParser.MatchUniqueID(buffer, currentOffset, remainingSize);
 1323                if (bytesMatched == 0)
 1324                {
 1325                    return null;
 1326                }
 1327                int messageIDOffset = currentOffset;
 1328                int messageIDSize = bytesMatched;
 1329                currentOffset += bytesMatched;
 1330                remainingSize -= bytesMatched;
 1331
 1332                bytesMatched = BinaryFormatParser.MatchBytes(buffer, currentOffset, remainingSize, s_requestFragment2);
 1333                if (bytesMatched == 0)
 1334                {
 1335                    return null;
 1336                }
 1337                currentOffset += bytesMatched;
 1338                remainingSize -= bytesMatched;
 1339
 1340                if (BinaryFormatParser.MatchAttributeNode(buffer, currentOffset, remainingSize))
 1341                {
 1342                    return null;
 1343                }
 1344
 1345                UniqueId messageId = BinaryFormatParser.ParseUniqueID(buffer, messageIDOffset, messageIDSize);
 1346                messageIDHeader = MessageIDHeader.Create(messageId, _messageVersion.Addressing);
 1347                relatesToHeader = null;
 1348
 1349                if (!_readerSession.TryLookup(ToValueSessionKey, out toString))
 1350                {
 1351                    return null;
 1352                }
 1353
 1354                totalBytesMatched = s_requestFragment1.Length + messageIDSize + s_requestFragment2.Length;
 1355            }
 1356            else
 1357            {
 1358                bytesMatched = BinaryFormatParser.MatchBytes(buffer, currentOffset, remainingSize, s_responseFragment1);
 1359
 1360                if (bytesMatched == 0)
 1361                {
 1362                    return null;
 1363                }
 1364
 1365                currentOffset += bytesMatched;
 1366                remainingSize -= bytesMatched;
 1367
 1368                bytesMatched = BinaryFormatParser.MatchUniqueID(buffer, currentOffset, remainingSize);
 1369                if (bytesMatched == 0)
 1370                {
 1371                    return null;
 1372                }
 1373                int messageIDOffset = currentOffset;
 1374                int messageIDSize = bytesMatched;
 1375                currentOffset += bytesMatched;
 1376                remainingSize -= bytesMatched;
 1377
 1378                bytesMatched = BinaryFormatParser.MatchBytes(buffer, currentOffset, remainingSize, s_responseFragment2);
 1379                if (bytesMatched == 0)
 1380                {
 1381                    return null;
 1382                }
 1383                currentOffset += bytesMatched;
 1384                remainingSize -= bytesMatched;
 1385
 1386                if (BinaryFormatParser.MatchAttributeNode(buffer, currentOffset, remainingSize))
 1387                {
 1388                    return null;
 1389                }
 1390
 1391                UniqueId messageId = BinaryFormatParser.ParseUniqueID(buffer, messageIDOffset, messageIDSize);
 1392                relatesToHeader = RelatesToHeader.Create(messageId, _messageVersion.Addressing);
 1393                messageIDHeader = null;
 1394                toString = XD.Addressing10Dictionary.Anonymous;
 1395
 1396                totalBytesMatched = s_responseFragment1.Length + messageIDSize + s_responseFragment2.Length;
 1397            }
 1398
 1399            totalBytesMatched += s_commonFragment.Length + actionSize;
 1400
 1401            int actionKey = BinaryFormatParser.ParseKey(buffer, actionOffset, actionSize);
 1402
 1403            if (!TryLookupKey(actionKey, out XmlDictionaryString actionString))
 1404            {
 1405                return null;
 1406            }
 1407
 1408            ActionHeader actionHeader = ActionHeader.Create(actionString, _messageVersion.Addressing);
 1409
 1410            if (_toHeader == null)
 1411            {
 1412                _toHeader = ToHeader.Create(new Uri(toString.Value), _messageVersion.Addressing);
 1413            }
 1414
 1415            int abandonedSize = totalBytesMatched - s_bodyFragment.Length;
 1416
 1417            offset += abandonedSize;
 1418            size -= abandonedSize;
 1419
 1420            Buffer.BlockCopy(s_bodyFragment, 0, buffer, offset, s_bodyFragment.Length);
 1421
 1422            messageData.Open(new ArraySegment<byte>(buffer, offset, size), bufferManager);
 1423
 1424            PatternMessage patternMessage = new PatternMessage(messageData, _messageVersion);
 1425
 1426            MessageHeaders headers = patternMessage.Headers;
 1427            headers.AddActionHeader(actionHeader);
 1428            if (messageIDHeader != null)
 1429            {
 1430                headers.AddMessageIDHeader(messageIDHeader);
 1431                headers.AddReplyToHeader(ReplyToHeader.AnonymousReplyTo10);
 1432            }
 1433            else
 1434            {
 1435                headers.AddRelatesToHeader(relatesToHeader);
 1436            }
 1437            headers.AddToHeader(_toHeader);
 1438
 1439            return patternMessage;
 1440        }
 1441
 1442        private bool TryLookupKey(int key, out XmlDictionaryString result)
 1443        {
 1444            if (BinaryFormatParser.IsSessionKey(key))
 1445            {
 1446                return _readerSession.TryLookup(BinaryFormatParser.GetSessionKey(key), out result);
 1447            }
 1448            else
 1449            {
 1450                return _dictionary.TryLookup(BinaryFormatParser.GetStaticKey(key), out result);
 1451            }
 1452        }
 1453
 1454        private sealed class PatternMessage : ReceivedMessage
 1455        {
 1456            private IBufferedMessageData _messageData;
 1457            private readonly MessageHeaders _headers;
 1458            private RecycledMessageState _recycledMessageState;
 1459            private readonly MessageProperties _properties;
 1460            private XmlDictionaryReader _reader;
 1461
 1462            public PatternMessage(IBufferedMessageData messageData, MessageVersion messageVersion)
 1463            {
 1464                _messageData = messageData;
 1465                _recycledMessageState = messageData.TakeMessageState();
 1466                if (_recycledMessageState == null)
 1467                {
 1468                    _recycledMessageState = new RecycledMessageState();
 1469                }
 1470                _properties = _recycledMessageState.TakeProperties();
 1471                if (_properties == null)
 1472                {
 1473                    _properties = new MessageProperties();
 1474                }
 1475                _headers = _recycledMessageState.TakeHeaders();
 1476                if (_headers == null)
 1477                {
 1478                    _headers = new MessageHeaders(messageVersion);
 1479                }
 1480                else
 1481                {
 1482                    _headers.Init(messageVersion);
 1483                }
 1484                XmlDictionaryReader reader = messageData.GetMessageReader();
 1485                reader.ReadStartElement();
 1486                VerifyStartBody(reader, messageVersion.Envelope);
 1487                ReadStartBody(reader);
 1488                _reader = reader;
 1489            }
 1490
 1491            public PatternMessage(IBufferedMessageData messageData, MessageVersion messageVersion,
 1492                KeyValuePair<string, object>[] properties, MessageHeaders headers)
 1493            {
 1494                _messageData = messageData;
 1495                _messageData.Open();
 1496                _recycledMessageState = _messageData.TakeMessageState();
 1497                if (_recycledMessageState == null)
 1498                {
 1499                    _recycledMessageState = new RecycledMessageState();
 1500                }
 1501
 1502                _properties = _recycledMessageState.TakeProperties();
 1503                if (_properties == null)
 1504                {
 1505                    _properties = new MessageProperties();
 1506                }
 1507                if (properties != null)
 1508                {
 1509                    _properties.CopyProperties(properties);
 1510                }
 1511
 1512                _headers = _recycledMessageState.TakeHeaders();
 1513                if (_headers == null)
 1514                {
 1515                    _headers = new MessageHeaders(messageVersion);
 1516                }
 1517                if (headers != null)
 1518                {
 1519                    _headers.CopyHeadersFrom(headers);
 1520                }
 1521
 1522                XmlDictionaryReader reader = messageData.GetMessageReader();
 1523                reader.ReadStartElement();
 1524                VerifyStartBody(reader, messageVersion.Envelope);
 1525                ReadStartBody(reader);
 1526                _reader = reader;
 1527            }
 1528
 1529
 1530            public override MessageHeaders Headers
 1531            {
 1532                get
 1533                {
 1534                    if (IsDisposed)
 1535                    {
 1536                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateMessageDisposedException());
 1537                    }
 1538                    return _headers;
 1539                }
 1540            }
 1541
 1542            public override MessageProperties Properties
 1543            {
 1544                get
 1545                {
 1546                    if (IsDisposed)
 1547                    {
 1548                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateMessageDisposedException());
 1549                    }
 1550                    return _properties;
 1551                }
 1552            }
 1553
 1554            public override MessageVersion Version
 1555            {
 1556                get
 1557                {
 1558                    if (IsDisposed)
 1559                    {
 1560                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateMessageDisposedException());
 1561                    }
 1562                    return _headers.MessageVersion;
 1563                }
 1564            }
 1565
 1566            public override RecycledMessageState RecycledMessageState
 1567            {
 1568                get { return _recycledMessageState; }
 1569            }
 1570
 1571            private XmlDictionaryReader GetBufferedReaderAtBody()
 1572            {
 1573                XmlDictionaryReader reader = _messageData.GetMessageReader();
 1574                reader.ReadStartElement();
 1575                reader.ReadStartElement();
 1576                return reader;
 1577            }
 1578
 1579            protected override void OnBodyToString(XmlDictionaryWriter writer)
 1580            {
 1581                using (XmlDictionaryReader reader = GetBufferedReaderAtBody())
 1582                {
 1583                    while (reader.NodeType != XmlNodeType.EndElement)
 1584                    {
 1585                        writer.WriteNode(reader, false);
 1586                    }
 1587                }
 1588            }
 1589
 1590            protected override void OnClose()
 1591            {
 1592                Exception ex = null;
 1593                try
 1594                {
 1595                    base.OnClose();
 1596                }
 1597                catch (Exception e)
 1598                {
 1599                    if (Fx.IsFatal(e))
 1600                    {
 1601                        throw;
 1602                    }
 1603                    ex = e;
 1604                }
 1605
 1606                try
 1607                {
 1608                    _properties.Dispose();
 1609                }
 1610                catch (Exception e)
 1611                {
 1612                    if (Fx.IsFatal(e))
 1613                    {
 1614                        throw;
 1615                    }
 1616                    if (ex == null)
 1617                    {
 1618                        ex = e;
 1619                    }
 1620                }
 1621
 1622                try
 1623                {
 1624                    if (_reader != null)
 1625                    {
 1626                        _reader.Dispose();
 1627                    }
 1628                }
 1629                catch (Exception e)
 1630                {
 1631                    if (Fx.IsFatal(e))
 1632                    {
 1633                        throw;
 1634                    }
 1635                    if (ex == null)
 1636                    {
 1637                        ex = e;
 1638                    }
 1639                }
 1640
 1641                try
 1642                {
 1643                    _recycledMessageState.ReturnHeaders(_headers);
 1644                    _recycledMessageState.ReturnProperties(_properties);
 1645                    _messageData.ReturnMessageState(_recycledMessageState);
 1646                    _recycledMessageState = null;
 1647                    _messageData.Close();
 1648                    _messageData = null;
 1649                }
 1650                catch (Exception e)
 1651                {
 1652                    if (Fx.IsFatal(e))
 1653                    {
 1654                        throw;
 1655                    }
 1656                    if (ex == null)
 1657                    {
 1658                        ex = e;
 1659                    }
 1660                }
 1661
 1662                if (ex != null)
 1663                {
 1664                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(ex);
 1665                }
 1666            }
 1667
 1668            protected override MessageBuffer OnCreateBufferedCopy(int maxBufferSize)
 1669            {
 1670                KeyValuePair<string, object>[] properties = new KeyValuePair<string, object>[Properties.Count];
 1671                ((ICollection<KeyValuePair<string, object>>)Properties).CopyTo(properties, 0);
 1672                _messageData.EnableMultipleUsers();
 1673                return new PatternMessageBuffer(_messageData, Version, properties, _headers);
 1674            }
 1675
 1676            protected override XmlDictionaryReader OnGetReaderAtBodyContents()
 1677            {
 1678                XmlDictionaryReader reader = _reader;
 1679                _reader = null;
 1680                return reader;
 1681            }
 1682
 1683            protected override string OnGetBodyAttribute(string localName, string ns)
 1684            {
 1685                return null;
 1686            }
 1687        }
 1688
 1689        private class PatternMessageBuffer : MessageBuffer
 1690        {
 1691            private bool _closed;
 1692            private MessageHeaders _headers;
 1693            private IBufferedMessageData _messageDataAtBody;
 1694            private MessageVersion _messageVersion;
 1695            private KeyValuePair<string, object>[] _properties;
 1696            private RecycledMessageState _recycledMessageState;
 1697
 1698            public PatternMessageBuffer(IBufferedMessageData messageDataAtBody, MessageVersion messageVersion,
 1699                KeyValuePair<string, object>[] properties, MessageHeaders headers)
 1700            {
 1701                _messageDataAtBody = messageDataAtBody;
 1702                _messageDataAtBody.Open();
 1703
 1704                _recycledMessageState = _messageDataAtBody.TakeMessageState();
 1705                if (_recycledMessageState == null)
 1706                {
 1707                    _recycledMessageState = new RecycledMessageState();
 1708                }
 1709
 1710                _headers = _recycledMessageState.TakeHeaders();
 1711                if (_headers == null)
 1712                {
 1713                    _headers = new MessageHeaders(messageVersion);
 1714                }
 1715                _headers.CopyHeadersFrom(headers);
 1716                _properties = properties;
 1717                _messageVersion = messageVersion;
 1718            }
 1719
 1720            public override int BufferSize
 1721            {
 1722                get
 1723                {
 1724                    lock (ThisLock)
 1725                    {
 1726                        if (_closed)
 1727                        {
 1728                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateBufferDisposedException());
 1729                        }
 1730
 1731                        return _messageDataAtBody.Buffer.Count;
 1732                    }
 1733                }
 1734            }
 1735
 1736            private object ThisLock { get; } = new object();
 1737
 1738            public override void Close()
 1739            {
 1740                lock (ThisLock)
 1741                {
 1742                    if (!_closed)
 1743                    {
 1744                        _closed = true;
 1745                        _recycledMessageState.ReturnHeaders(_headers);
 1746                        _messageDataAtBody.ReturnMessageState(_recycledMessageState);
 1747                        _messageDataAtBody.Close();
 1748                        _recycledMessageState = null;
 1749                        _messageDataAtBody = null;
 1750                        _properties = null;
 1751                        _messageVersion = null;
 1752                        _headers = null;
 1753                    }
 1754                }
 1755            }
 1756
 1757            public override Message CreateMessage()
 1758            {
 1759                lock (ThisLock)
 1760                {
 1761                    if (_closed)
 1762                    {
 1763                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateBufferDisposedException());
 1764                    }
 1765
 1766                    return new PatternMessage(_messageDataAtBody, _messageVersion, _properties,
 1767                        _headers);
 1768                }
 1769            }
 1770        }
 1771    }
 1772}

Methods/Properties

.ctor(CoreWCF.Channels.MessageVersion,System.Int32,System.Int32,System.Int32,System.Xml.XmlDictionaryReaderQuotas,System.Int64,CoreWCF.Channels.BinaryVersion,CoreWCF.Channels.CompressionFormat)
XmlDictionary()
Encoder()
MessageVersion()
MaxWritePoolSize()
ReaderQuotas()
MaxReadPoolSize()
MaxSessionSize()
CompressionFormat()
MaxReceivedMessageSize()
MaxReceivedMessageSize(System.Int64)
ThisLock()
RecycledStatePool()
CreateSessionEncoder()
TakeStreamedWriter(System.IO.Stream)
ReturnStreamedWriter(System.Xml.XmlDictionaryWriter)
TakeBufferedWriter()
ReturnMessageWriter(CoreWCF.Channels.BinaryMessageEncoderFactory/BinaryBufferedMessageWriter)
TakeStreamedReader(System.IO.Stream)
ReturnStreamedReader(System.Xml.XmlDictionaryReader)
TakeBufferedData(CoreWCF.Channels.BinaryMessageEncoderFactory/BinaryMessageEncoder)
ReturnBufferedData(CoreWCF.Channels.BinaryMessageEncoderFactory/BinaryBufferedMessageData)
.ctor(CoreWCF.Channels.BinaryMessageEncoderFactory,System.Int32)
MessageEncoder()
Quotas()
SetMessageEncoder(CoreWCF.Channels.BinaryMessageEncoderFactory/BinaryMessageEncoder)
TakeXmlReader()
ReturnXmlReader(System.Xml.XmlDictionaryReader)
OnClosed()
.ctor(System.Xml.IXmlDictionary)
.ctor(System.Xml.IXmlDictionary,System.Xml.XmlBinaryWriterSession)
TakeXmlWriter(System.IO.Stream)
ReturnXmlWriter(System.Xml.XmlDictionaryWriter)
.ctor(CoreWCF.Channels.BinaryMessageEncoderFactory,System.Boolean,System.Int32)
ContentType()
MessageVersion()
MediaType()
ReaderSession()
CompressionEnabled()
AddSessionInformationToMessage(System.ArraySegment`1<System.Byte>,CoreWCF.Channels.BufferManager,System.Int32)
ExtractSessionInformationFromMessage(System.ArraySegment`1<System.Byte>)
ReadMessage(System.ArraySegment`1<System.Byte>,CoreWCF.Channels.BufferManager,System.String)
ReadMessageAsync(System.IO.Stream,System.Int32,System.String)
WriteMessage(CoreWCF.Channels.Message,System.Int32,CoreWCF.Channels.BufferManager,System.Int32)
WriteMessageAsync()
IsContentTypeSupported(System.String)
SetSessionContentType(System.String)
AddCompressedMessageProperties(CoreWCF.Channels.Message,System.String)
ContentTypeEqualsOrStartsWith(System.String,System.String)
CheckContentType(System.String)
CheckCompressedWrite(CoreWCF.Channels.Message)
.ctor(System.Int32)
HasNewStrings()
TryAdd(System.Xml.XmlDictionaryString,System.Int32&)
GetNewStrings()
ClearNewStrings()