< Summary - CoreWCF Coverage — PR #1766

Information
Class: CoreWCF.Channels.MtomMessageEncoder
Assembly: CoreWCF.Primitives
File(s): /home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/Channels/MtomMessageEncoder.cs
Line coverage
75%
Covered lines: 118
Uncovered lines: 39
Coverable lines: 157
Total lines: 708
Line coverage: 75.1%
Branch coverage
60%
Covered branches: 45
Total branches: 74
Branch coverage: 60.8%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.ctor(...)50%4488.23%
IsMTOMContentType(...)100%11100%
IsTextContentType(...)100%110%
IsContentTypeSupported(...)50%4466.66%
IsCharSetSupported(...)50%4466.66%
GenerateStartInfoString()100%22100%
ReadMessage(...)66.66%6684.61%
ReadMessageAsync(...)50%6675%
WriteMessage(...)100%11100%
GetContentType(...)100%11100%
FormatContentType(...)100%11100%
WriteMessageInternal(...)64.28%141475%
WriteMessageAsync(...)100%11100%
WriteMessageInternalAsync()66.66%121270%
CoreWCF.Runtime.Diagnostics.ITraceSourceStringProvider.GetSourceString()100%110%
.ctor(...)100%11100%
OnClosed()100%11100%
TakeXmlReader()41.66%121241.17%
ReturnXmlReader(...)100%22100%
.ctor(...)100%11100%
TakeXmlWriter(...)50%4462.5%
ReturnXmlWriter(...)100%22100%

File(s)

/home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/Channels/MtomMessageEncoder.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.Globalization;
 6using System.IO;
 7using System.Text;
 8using System.Threading.Tasks;
 9using System.Xml;
 10
 11using CoreWCF.Description;
 12using CoreWCF.Diagnostics;
 13using CoreWCF.Runtime;
 14using CoreWCF.Runtime.Diagnostics;
 15using CoreWCF.Xml;
 16
 17namespace CoreWCF.Channels
 18{
 19    internal class MtomMessageEncoderFactory : MessageEncoderFactory
 20    {
 21        private MessageVersion _messageVersion;
 22        private Encoding _writeEncoding;
 23        private int _maxReadPoolSize;
 24        private int _maxWritePoolSize;
 25        private int _maxBufferSize;
 26        private XmlDictionaryReaderQuotas _readerQuotas;
 27
 28        // Pools used by MtomMessageEncoder
 29        private const int MaxPooledXmlReadersPerMessage = 2;
 30        private object _thisLock;
 31        private OnXmlDictionaryReaderClose _onStreamedReaderClose;
 32        // Double-checked locking pattern requires volatile for read/write synchronization
 33        private volatile SynchronizedPool<XmlDictionaryWriter> _streamedWriterPool;
 34        private volatile SynchronizedPool<XmlDictionaryReader> _streamedReaderPool;
 35        private volatile SynchronizedPool<MtomMessageEncoder.MtomBufferedMessageData> _bufferedReaderPool;
 36        private volatile SynchronizedPool<MtomMessageEncoder.MtomBufferedMessageWriter> _bufferedWriterPool;
 37        private volatile SynchronizedPool<RecycledMessageState> _recycledStatePool;
 38
 39        public MtomMessageEncoderFactory(MessageVersion version, Encoding writeEncoding, int maxReadPoolSize, int maxWri
 40        {
 41            _messageVersion = version;
 42            _writeEncoding = writeEncoding;
 43            _maxReadPoolSize = maxReadPoolSize;
 44            _maxWritePoolSize = maxWritePoolSize;
 45            _maxBufferSize = maxBufferSize;
 46            _readerQuotas = quotas;
 47            _thisLock = new object();
 48            _onStreamedReaderClose = new OnXmlDictionaryReaderClose(ReturnStreamedReader);
 49            if (version.Envelope == EnvelopeVersion.Soap12)
 50            {
 51                ContentEncodingMap = TextMessageEncoderFactory.Soap12Content;
 52            }
 53            else if (version.Envelope == EnvelopeVersion.Soap11)
 54            {
 55                ContentEncodingMap = TextMessageEncoderFactory.Soap11Content;
 56            }
 57            else
 58            {
 59                Fx.Assert("Invalid MessageVersion");
 60                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(string.Format(Cu
 61            }
 62        }
 63
 64        public override MessageEncoder Encoder => new MtomMessageEncoder(_messageVersion, _writeEncoding, _maxReadPoolSi
 65
 66        public override MessageVersion MessageVersion => _messageVersion;
 67
 68        public int MaxWritePoolSize => _maxWritePoolSize;
 69
 70        public int MaxReadPoolSize => _maxReadPoolSize;
 71
 72        public XmlDictionaryReaderQuotas ReaderQuotas => _readerQuotas;
 73
 74        public int MaxBufferSize => _maxBufferSize;
 75
 76        internal ContentEncoding[] ContentEncodingMap { get; }
 77
 78        internal XmlDictionaryWriter TakeStreamedWriter(Stream stream, string startInfo, string boundary, string startUr
 79        {
 80            if (_streamedWriterPool == null)
 81            {
 82                lock (_thisLock)
 83                {
 84                    if (_streamedWriterPool == null)
 85                    {
 86                        _streamedWriterPool = new SynchronizedPool<XmlDictionaryWriter>(MaxWritePoolSize);
 87                    }
 88                }
 89            }
 90            XmlDictionaryWriter xmlWriter = _streamedWriterPool.Take();
 91            if (xmlWriter == null)
 92            {
 93                xmlWriter = XmlMtomWriter.Create(stream, _writeEncoding, int.MaxValue, startInfo, boundary, startUri, wr
 94                // if (WcfEventSource.Instance.WritePoolMissIsEnabled())
 95                // {
 96                //     WcfEventSource.Instance.WritePoolMiss(xmlWriter.GetType().Name);
 97                // }
 98            }
 99            else
 100            {
 101                ((IXmlMtomWriterInitializer)xmlWriter).SetOutput(stream, _writeEncoding, int.MaxValue, startInfo, bounda
 102            }
 103            return xmlWriter;
 104        }
 105
 106        internal void ReturnStreamedWriter(XmlDictionaryWriter xmlWriter)
 107        {
 108            xmlWriter.Close();
 109            _streamedWriterPool.Return(xmlWriter);
 110        }
 111
 112        internal MtomMessageEncoder.MtomBufferedMessageWriter TakeBufferedWriter(MtomMessageEncoder messageEncoder)
 113        {
 114            if (_bufferedWriterPool == null)
 115            {
 116                lock (_thisLock)
 117                {
 118                    if (_bufferedWriterPool == null)
 119                    {
 120                        _bufferedWriterPool = new SynchronizedPool<MtomMessageEncoder.MtomBufferedMessageWriter>(MaxWrit
 121                    }
 122                }
 123            }
 124
 125            MtomMessageEncoder.MtomBufferedMessageWriter messageWriter = _bufferedWriterPool.Take();
 126            if (messageWriter == null)
 127            {
 128                messageWriter = new MtomMessageEncoder.MtomBufferedMessageWriter(messageEncoder);
 129                // if (WcfEventSource.Instance.WritePoolMissIsEnabled())
 130                // {
 131                //     WcfEventSource.Instance.WritePoolMiss(messageWriter.GetType().Name);
 132                // }
 133            }
 134            return messageWriter;
 135        }
 136
 137        internal void ReturnMessageWriter(MtomMessageEncoder.MtomBufferedMessageWriter messageWriter)
 138        {
 139            _bufferedWriterPool.Return(messageWriter);
 140        }
 141
 142        internal MtomMessageEncoder.MtomBufferedMessageData TakeBufferedReader(MtomMessageEncoder messageEncoder)
 143        {
 144            if (_bufferedReaderPool == null)
 145            {
 146                lock (_thisLock)
 147                {
 148                    if (_bufferedReaderPool == null)
 149                    {
 150                        _bufferedReaderPool = new SynchronizedPool<MtomMessageEncoder.MtomBufferedMessageData>(MaxReadPo
 151                    }
 152                }
 153            }
 154            MtomMessageEncoder.MtomBufferedMessageData messageData = _bufferedReaderPool.Take();
 155            if (messageData == null)
 156            {
 157                messageData = new MtomMessageEncoder.MtomBufferedMessageData(messageEncoder, MaxPooledXmlReadersPerMessa
 158                // if (WcfEventSource.Instance.ReadPoolMissIsEnabled())
 159                // {
 160                //     WcfEventSource.Instance.ReadPoolMiss(messageData.GetType().Name);
 161                // }
 162            }
 163            return messageData;
 164        }
 165
 166        internal void ReturnBufferedData(MtomMessageEncoder.MtomBufferedMessageData messageData)
 167        {
 168            _bufferedReaderPool.Return(messageData);
 169        }
 170
 171        internal XmlReader TakeStreamedReader(Stream stream, string contentType, bool isMtomContentType)
 172        {
 173            if (_streamedReaderPool == null)
 174            {
 175                lock (_thisLock)
 176                {
 177                    if (_streamedReaderPool == null)
 178                    {
 179                        _streamedReaderPool = new SynchronizedPool<XmlDictionaryReader>(MaxReadPoolSize);
 180                    }
 181                }
 182            }
 183            XmlDictionaryReader xmlReader = _streamedReaderPool.Take();
 184            try
 185            {
 186                if (contentType == null || isMtomContentType)
 187                {
 188                    if (xmlReader != null && xmlReader is IXmlMtomReaderInitializer)
 189                    {
 190                        ((IXmlMtomReaderInitializer)xmlReader).SetInput(stream, MtomMessageEncoderFactory.GetSupportedEn
 191                    }
 192                    else
 193                    {
 194                        xmlReader = XmlMtomReader.Create(stream, MtomMessageEncoderFactory.GetSupportedEncodings(), cont
 195                        // if (WcfEventSource.Instance.ReadPoolMissIsEnabled())
 196                        // {
 197                        //     WcfEventSource.Instance.ReadPoolMiss(xmlReader.GetType().Name);
 198                        // }
 199                    }
 200                }
 201                else
 202                {
 203                    if (xmlReader != null && xmlReader is IXmlTextReaderInitializer)
 204                    {
 205                        ((IXmlTextReaderInitializer)xmlReader).SetInput(stream, TextMessageEncoderFactory.GetEncodingFro
 206                    }
 207                    else
 208                    {
 209                        xmlReader = XmlDictionaryReader.CreateTextReader(stream, TextMessageEncoderFactory.GetEncodingFr
 210                        // if (WcfEventSource.Instance.ReadPoolMissIsEnabled())
 211                        // {
 212                        //     WcfEventSource.Instance.ReadPoolMiss(xmlReader.GetType().Name);
 213                        // }
 214                    }
 215                }
 216            }
 217            catch (FormatException fe)
 218            {
 219                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(
 220                    SR.SFxErrorCreatingMtomReader, fe));
 221            }
 222            catch (XmlException xe)
 223            {
 224                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(
 225                    SR.SFxErrorCreatingMtomReader, xe));
 226            }
 227
 228            return xmlReader;
 229        }
 230
 231        internal void ReturnStreamedReader(XmlDictionaryReader xmlReader)
 232        {
 233            _streamedReaderPool.Return(xmlReader);
 234        }
 235
 236        internal SynchronizedPool<RecycledMessageState> RecycledStatePool
 237        {
 238            get
 239            {
 240                if (_recycledStatePool == null)
 241                {
 242                    lock (_thisLock)
 243                    {
 244                        if (_recycledStatePool == null)
 245                        {
 246                            _recycledStatePool = new SynchronizedPool<RecycledMessageState>(MaxReadPoolSize);
 247                        }
 248                    }
 249                }
 250                return _recycledStatePool;
 251            }
 252        }
 253
 254        public static Encoding[] GetSupportedEncodings()
 255        {
 256            Encoding[] supported = TextEncoderDefaults.SupportedEncodings;
 257            Encoding[] enc = new Encoding[supported.Length];
 258            Array.Copy(supported, enc, supported.Length);
 259            return enc;
 260        }
 261
 262    }
 263
 264    // Some notes:
 265    // The Encoding passed in is used for the SOAP envelope
 266    internal class MtomMessageEncoder : MessageEncoder, ITraceSourceStringProvider
 267    {
 268        private Encoding _writeEncoding;
 269        private string _contentType;
 270        private string _boundary;
 271        private MessageVersion _version;
 272        private static UriGenerator s_mimeBoundaryGenerator;
 273        private XmlDictionaryReaderQuotas _bufferedReadReaderQuotas;
 274
 275        private MtomMessageEncoderFactory _factory;
 276        private const string MtomMediaType = "multipart/related";
 277        private const string MtomContentType = MtomMediaType + "; type=\"application/xop+xml\"";
 278        private const string MtomStartUri = NamingHelper.DefaultNamespace + "0";
 279
 29280        public MtomMessageEncoder(MessageVersion version, Encoding writeEncoding, int maxReadPoolSize, int maxWritePoolS
 281        {
 29282            if (version == null)
 0283                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(version));
 29284            if (writeEncoding == null)
 0285                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(writeEncoding));
 286
 29287            _factory = factory;
 29288            TextEncoderDefaults.ValidateEncoding(writeEncoding);
 29289            _writeEncoding = writeEncoding;
 290
 29291            MaxReadPoolSize = maxReadPoolSize;
 29292            MaxWritePoolSize = maxWritePoolSize;
 293
 29294            ReaderQuotas = new XmlDictionaryReaderQuotas();
 29295            quotas.CopyTo(ReaderQuotas);
 296
 29297            _bufferedReadReaderQuotas = EncoderHelpers.GetBufferedReadQuotas(ReaderQuotas);
 29298            MaxBufferSize = maxBufferSize;
 29299            _version = version;
 29300            _contentType = GetContentType(out _boundary);
 29301        }
 302
 303        private static UriGenerator MimeBoundaryGenerator
 304        {
 305            get
 306            {
 29307                if (s_mimeBoundaryGenerator == null)
 1308                    s_mimeBoundaryGenerator = new UriGenerator("uuid", "+");
 29309                return s_mimeBoundaryGenerator;
 310            }
 311        }
 312
 38313        public override string ContentType => _contentType;
 314
 0315        public int MaxWritePoolSize { get; }
 316
 0317        public int MaxReadPoolSize { get; }
 318
 58319        public XmlDictionaryReaderQuotas ReaderQuotas { get; }
 320
 10321        public int MaxBufferSize { get; }
 322
 18323        public override string MediaType => MtomMediaType;
 324
 21325        public override MessageVersion MessageVersion => _version;
 326
 327        internal bool IsMTOMContentType(string contentType)
 328        {
 329            // check for MTOM contentType: multipart/related; type=\"application/xop+xml\"
 18330            return IsContentTypeSupported(contentType, ContentType, MediaType);
 331        }
 332
 333        internal bool IsTextContentType(string contentType)
 334        {
 335            // check for Text contentType: text/xml or application/soap+xml
 0336            string textMediaType = TextMessageEncoderFactory.GetMediaType(_version);
 0337            string textContentType = TextMessageEncoderFactory.GetContentType(textMediaType, _writeEncoding);
 0338            return IsContentTypeSupported(contentType, textContentType, textMediaType);
 339        }
 340
 341        public override bool IsContentTypeSupported(string contentType)
 342        {
 9343            if (contentType == null)
 0344                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(contentType))
 9345            return (IsMTOMContentType(contentType) || IsTextContentType(contentType));
 346        }
 347
 348        protected override bool IsCharSetSupported(string charSet)
 349        {
 18350            if (charSet == null || charSet.Length == 0)
 18351                return true;
 352
 353            Encoding tmp;
 0354            return TextEncoderDefaults.TryGetEncoding(charSet, out tmp);
 355        }
 356
 357        private string GenerateStartInfoString()
 358        {
 40359            return (_version.Envelope == EnvelopeVersion.Soap12) ? TextMessageEncoderFactory.Soap12MediaType : TextMessa
 360        }
 361
 362        public override Message ReadMessage(ArraySegment<byte> buffer, BufferManager bufferManager, string contentType)
 363        {
 10364            if (bufferManager == null)
 0365                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(bufferManager));
 366
 10367            if (contentType == ContentType)
 0368                contentType = null;
 369
 370            // if (WcfEventSource.Instance.MtomMessageDecodingStartIsEnabled())
 371            // {
 372            //     WcfEventSource.Instance.MtomMessageDecodingStart();
 373            // }
 374
 10375            MtomBufferedMessageData messageData = _factory.TakeBufferedReader(this);
 10376            messageData._contentType = contentType;
 10377            messageData.Open(buffer, bufferManager);
 10378            RecycledMessageState messageState = messageData.TakeMessageState();
 10379            if (messageState == null)
 10380                messageState = new RecycledMessageState();
 10381            Message message = new BufferedMessage(messageData, messageState);
 10382            message.Properties.Encoder = this;
 383            // if (MessageLogger.LogMessagesAtTransportLevel)
 384            //     MessageLogger.LogMessage(ref message, MessageLoggingSource.TransportReceive);
 385            //
 386            // if (WcfEventSource.Instance.MessageReadByEncoderIsEnabled() && buffer != null)
 387            // {
 388            //     WcfEventSource.Instance.MessageReadByEncoder(
 389            //         EventTraceActivityHelper.TryExtractActivity(message, true),
 390            //         buffer.Count,
 391            //         this);
 392            // }
 393
 10394            return message;
 395        }
 396
 397        public override Task<Message> ReadMessageAsync(Stream stream, int maxSizeOfHeaders, string contentType)
 398        {
 1399            if (stream == null)
 0400                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(stream)));
 401
 1402            if (contentType == ContentType)
 0403                contentType = null;
 404
 405            // if (WcfEventSource.Instance.MtomMessageDecodingStartIsEnabled())
 406            // {
 407            //     WcfEventSource.Instance.MtomMessageDecodingStart();
 408            // }
 409
 1410            XmlReader reader = _factory.TakeStreamedReader(stream, contentType, contentType == null || IsMTOMContentType
 1411            Message message = Message.CreateMessage(reader, maxSizeOfHeaders, _version);
 1412            message.Properties.Encoder = this;
 413
 414            // if (WcfEventSource.Instance.StreamedMessageReadByEncoderIsEnabled())
 415            // {
 416            //     WcfEventSource.Instance.StreamedMessageReadByEncoder(EventTraceActivityHelper.TryExtractActivity(mess
 417            // }
 418            //
 419            // if (MessageLogger.LogMessagesAtTransportLevel)
 420            //     MessageLogger.LogMessage(ref message, MessageLoggingSource.TransportReceive);
 1421            return Task.FromResult(message);
 422        }
 423
 424        public override ArraySegment<byte> WriteMessage(Message message, int maxMessageSize, BufferManager bufferManager
 425        {
 10426            return WriteMessageInternal(message, maxMessageSize, bufferManager, messageOffset, GenerateStartInfoString()
 427        }
 428
 429        // public override Task<ArraySegment<byte>> WriteMessageAsync(Message message, int maxMessageSize, BufferManager
 430        // {
 431        //     return Task.FromResult(WriteMessageInternal(message, maxMessageSize, bufferManager, messageOffset, Genera
 432        // }
 433
 434        private string GetContentType(out string boundary)
 435        {
 29436            string startInfo = GenerateStartInfoString();
 29437            boundary = MimeBoundaryGenerator.Next();
 438
 29439            return FormatContentType(boundary, startInfo);
 440        }
 441
 442        internal string FormatContentType(string boundary, string startInfo)
 443        {
 29444            return string.Format(CultureInfo.InvariantCulture,
 29445                "{0};start=\"<{1}>\";boundary=\"{2}\";start-info=\"{3}\"",
 29446                MtomContentType, MtomStartUri, boundary, startInfo);
 447        }
 448
 449        private ArraySegment<byte> WriteMessageInternal(Message message, int maxMessageSize, BufferManager bufferManager
 450        {
 10451            bool writeMessageHeaders = true;
 10452            if (message.Properties.TryGetValue("CoreWCF.Channel.MtomMessageEncoder.WriteMessageHeaders", out object bool
 453            {
 8454                writeMessageHeaders = (bool)boolAsObject;
 455            }
 456
 10457            if (message == null)
 0458                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(message));
 10459            if (bufferManager == null)
 0460                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(bufferManager));
 10461            if (maxMessageSize < 0)
 0462                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(maxMess
 0463                                                    SRCommon.ValueMustBeNonNegative));
 10464            if (messageOffset < 0 || messageOffset > maxMessageSize)
 0465                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(message
 0466                                                    SR.Format(SR.ValueMustBeInRange, 0, maxMessageSize)));
 10467            ThrowIfMismatchedMessageVersion(message);
 468
 469            // EventTraceActivity eventTraceActivity = null;
 470            // if (WcfEventSource.Instance.MtomMessageEncodingStartIsEnabled())
 471            // {
 472            //     eventTraceActivity = EventTraceActivityHelper.TryExtractActivity(message);
 473            //     WcfEventSource.Instance.MtomMessageEncodingStart(eventTraceActivity);
 474            // }
 475
 10476            message.Properties.Encoder = this;
 477
 10478            MtomBufferedMessageWriter messageWriter = _factory.TakeBufferedWriter(this);
 10479            messageWriter._startInfo = startInfo;
 10480            messageWriter._boundary = boundary;
 10481            messageWriter._startUri = startUri;
 10482            messageWriter._writeMessageHeaders = writeMessageHeaders;
 10483            messageWriter._maxSizeInBytes = maxMessageSize;
 10484            ArraySegment<byte> messageData = messageWriter.WriteMessage(message, bufferManager, messageOffset, maxMessag
 10485            _factory.ReturnMessageWriter(messageWriter);
 486
 487            // if (WcfEventSource.Instance.MessageWrittenByEncoderIsEnabled() && messageData != null)
 488            // {
 489            //     WcfEventSource.Instance.MessageWrittenByEncoder(
 490            //         eventTraceActivity ?? EventTraceActivityHelper.TryExtractActivity(message),
 491            //         messageData.Count,
 492            //         this);
 493            // }
 494            //
 495            // if (MessageLogger.LogMessagesAtTransportLevel)
 496            // {
 497            //     string contentType = null;
 498            //     if (boundary != null)
 499            //         contentType = FormatContentType(boundary, startInfo ?? GenerateStartInfoString());
 500            //
 501            //     XmlDictionaryReader xmlDictionaryReader = XmlMtomReader.Create(messageData.Array, messageData.Offset,
 502            //     MessageLogger.LogMessage(ref message, xmlDictionaryReader, MessageLoggingSource.TransportSend);
 503            // }
 504
 10505            return messageData;
 506        }
 507
 508        // public override void WriteMessage(Message message, Stream stream)
 509        // {
 510        //     WriteMessageAsync(message, stream).WaitForCompletionNoSpin();
 511        // }
 512
 513        public override Task WriteMessageAsync(Message message, Stream stream)
 514        {
 1515            return WriteMessageInternalAsync(message, stream, GenerateStartInfoString(), _boundary, MtomStartUri);
 516        }
 517
 518        // public override IAsyncResult BeginWriteMessage(Message message, Stream stream, AsyncCallback callback, object
 519        // {
 520        //     return WriteMessageAsync(message, stream).ToApm(callback, state);
 521        // }
 522        //
 523        // public override void EndWriteMessage(IAsyncResult result)
 524        // {
 525        //     result.ToApmEnd();
 526        // }
 527
 528        private async Task WriteMessageInternalAsync(Message message, Stream stream, string startInfo, string boundary, 
 529        {
 1530            bool writeMessageHeaders = true;
 1531            if (message.Properties.TryGetValue("CoreWCF.Channel.MtomMessageEncoder.WriteMessageHeaders", out object bool
 532            {
 1533                writeMessageHeaders = (bool)boolAsObject;
 534            }
 535
 1536            if (message == null)
 0537                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(message)));
 1538            if (stream == null)
 0539                throw TraceUtility.ThrowHelperError(new ArgumentNullException(nameof(stream)), message);
 1540            ThrowIfMismatchedMessageVersion(message);
 541
 542            // EventTraceActivity eventTraceActivity = null;
 543            // if (WcfEventSource.Instance.MtomMessageEncodingStartIsEnabled())
 544            // {
 545            //     eventTraceActivity = EventTraceActivityHelper.TryExtractActivity(message);
 546            //     WcfEventSource.Instance.MtomMessageEncodingStart(eventTraceActivity);
 547            // }
 548
 1549            message.Properties.Encoder = this;
 550            // if (MessageLogger.LogMessagesAtTransportLevel)
 551            //     MessageLogger.LogMessage(ref message, MessageLoggingSource.TransportSend);
 1552            XmlDictionaryWriter xmlWriter = _factory.TakeStreamedWriter(stream, startInfo, boundary, startUri, writeMess
 1553            if (_writeEncoding.WebName == "utf-8")
 554            {
 1555                await message.WriteMessageAsync(xmlWriter);
 556            }
 557            else
 558            {
 0559                await xmlWriter.WriteStartDocumentAsync();
 0560                await message.WriteMessageAsync(xmlWriter);
 0561                await xmlWriter.WriteEndDocumentAsync();
 562            }
 563
 1564            if (xmlWriter.SupportsAsync())
 565            {
 1566                await xmlWriter.FlushAsync();
 567            }
 568            else
 569            {
 0570                xmlWriter.Flush();
 571            }
 1572            _factory.ReturnStreamedWriter(xmlWriter);
 573
 574            // if (WcfEventSource.Instance.StreamedMessageWrittenByEncoderIsEnabled())
 575            // {
 576            //     WcfEventSource.Instance.StreamedMessageWrittenByEncoder(eventTraceActivity ?? EventTraceActivityHelpe
 577            // }
 1578        }
 579
 580        string ITraceSourceStringProvider.GetSourceString()
 581        {
 0582            return GetTraceSourceString();
 583        }
 584
 585        internal class MtomBufferedMessageData : BufferedMessageData
 586        {
 587            private MtomMessageEncoder _messageEncoder;
 588            private Pool<XmlDictionaryReader> _readerPool;
 589            internal string _contentType;
 590            private OnXmlDictionaryReaderClose _onClose;
 591
 592            public MtomBufferedMessageData(MtomMessageEncoder messageEncoder, int maxReaderPoolSize)
 10593                : base(messageEncoder._factory.RecycledStatePool)
 594            {
 10595                _messageEncoder = messageEncoder;
 10596                _readerPool = new Pool<XmlDictionaryReader>(maxReaderPoolSize);
 10597                _onClose = new OnXmlDictionaryReaderClose(OnXmlReaderClosed);
 10598            }
 599
 10600            public override MessageEncoder MessageEncoder => _messageEncoder;
 601
 10602            public override XmlDictionaryReaderQuotas Quotas => _messageEncoder._bufferedReadReaderQuotas;
 603
 604            protected override void OnClosed()
 605            {
 10606                _messageEncoder._factory.ReturnBufferedData(this);
 10607            }
 608
 609            protected override XmlDictionaryReader TakeXmlReader()
 610            {
 611                try
 612                {
 10613                    ArraySegment<byte> buffer = Buffer;
 614
 10615                    XmlDictionaryReader xmlReader = _readerPool.Take();
 10616                    if (_contentType == null || _messageEncoder.IsMTOMContentType(_contentType))
 617                    {
 10618                        if (xmlReader != null && xmlReader is IXmlMtomReaderInitializer)
 619                        {
 0620                            ((IXmlMtomReaderInitializer)xmlReader).SetInput(buffer.Array, buffer.Offset, buffer.Count, M
 621                        }
 622                        else
 623                        {
 10624                            xmlReader = XmlMtomReader.Create(buffer.Array, buffer.Offset, buffer.Count, MtomMessageEncod
 625                            // if (WcfEventSource.Instance.ReadPoolMissIsEnabled())
 626                            // {
 627                            //     WcfEventSource.Instance.ReadPoolMiss(xmlReader.GetType().Name);
 628                            // }
 629                        }
 630                    }
 631                    else
 632                    {
 0633                        if (xmlReader != null && xmlReader is IXmlTextReaderInitializer)
 634                        {
 0635                            ((IXmlTextReaderInitializer)xmlReader).SetInput(buffer.Array, buffer.Offset, buffer.Count, T
 636                        }
 637                        else
 638                        {
 0639                            xmlReader = XmlDictionaryReader.CreateTextReader(buffer.Array, buffer.Offset, buffer.Count, 
 640                            // if (WcfEventSource.Instance.ReadPoolMissIsEnabled())
 641                            // {
 642                            //     WcfEventSource.Instance.ReadPoolMiss(xmlReader.GetType().Name);
 643                            // }
 644                        }
 645                    }
 10646                    return xmlReader;
 647                }
 0648                catch (FormatException fe)
 649                {
 0650                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(
 0651                        SR.SFxErrorCreatingMtomReader, fe));
 652                }
 0653                catch (XmlException xe)
 654                {
 0655                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(
 0656                        SR.SFxErrorCreatingMtomReader, xe));
 657                }
 10658            }
 659
 660            protected override void ReturnXmlReader(XmlDictionaryReader xmlReader)
 661            {
 10662                if (xmlReader != null)
 10663                    _readerPool.Return(xmlReader);
 10664            }
 665        }
 666
 667        internal class MtomBufferedMessageWriter : BufferedMessageWriter
 668        {
 669            private MtomMessageEncoder _messageEncoder;
 670            internal bool _writeMessageHeaders;
 671            internal string _startInfo;
 672            internal string _startUri;
 673            internal string _boundary;
 10674            internal int _maxSizeInBytes = int.MaxValue;
 675            private XmlDictionaryWriter _writer;
 676
 10677            public MtomBufferedMessageWriter(MtomMessageEncoder messageEncoder)
 678            {
 10679                _messageEncoder = messageEncoder;
 10680            }
 681
 682            protected override XmlDictionaryWriter TakeXmlWriter(Stream stream)
 683            {
 10684                XmlDictionaryWriter returnedWriter = _writer;
 10685                if (returnedWriter == null)
 686                {
 10687                    returnedWriter = XmlMtomWriter.Create(stream, _messageEncoder._writeEncoding, _maxSizeInBytes, _star
 688                }
 689                else
 690                {
 0691                    _writer = null;
 0692                    ((IXmlMtomWriterInitializer)returnedWriter).SetOutput(stream, _messageEncoder._writeEncoding, _maxSi
 693                }
 10694                if (_messageEncoder._writeEncoding.WebName != "utf-8")
 0695                    returnedWriter.WriteStartDocument();
 10696                return returnedWriter;
 697            }
 698
 699            protected override void ReturnXmlWriter(XmlDictionaryWriter writer)
 700            {
 10701                writer.Close();
 702
 10703                if (_writer == null)
 10704                    _writer = writer;
 10705            }
 706        }
 707    }
 708}