|
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------
namespace System.ServiceModel.Channels
{
using System.Globalization;
using System.IO;
using System.Runtime;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Diagnostics;
using System.Text;
using System.Threading;
using System.Xml;
using System.ServiceModel.Diagnostics.Application;
using System.Runtime.Diagnostics;
class MtomMessageEncoderFactory : MessageEncoderFactory
{
MtomMessageEncoder messageEncoder;
public MtomMessageEncoderFactory(MessageVersion version, Encoding writeEncoding, int maxReadPoolSize, int maxWritePoolSize, int maxBufferSize, XmlDictionaryReaderQuotas quotas)
{
messageEncoder = new MtomMessageEncoder(version, writeEncoding, maxReadPoolSize, maxWritePoolSize, maxBufferSize, quotas);
}
public override MessageEncoder Encoder
{
get { return messageEncoder; }
}
public override MessageVersion MessageVersion
{
get { return messageEncoder.MessageVersion; }
}
public int MaxWritePoolSize
{
get { return messageEncoder.MaxWritePoolSize; }
}
public int MaxReadPoolSize
{
get { return messageEncoder.MaxReadPoolSize; }
}
public XmlDictionaryReaderQuotas ReaderQuotas
{
get
{
return messageEncoder.ReaderQuotas;
}
}
public int MaxBufferSize
{
get { return messageEncoder.MaxBufferSize; }
}
public static Encoding[] GetSupportedEncodings()
{
Encoding[] supported = TextEncoderDefaults.SupportedEncodings;
Encoding[] enc = new Encoding[supported.Length];
Array.Copy(supported, enc, supported.Length);
return enc;
}
}
// Some notes:
// The Encoding passed in is used for the SOAP envelope
class MtomMessageEncoder : MessageEncoder, ITraceSourceStringProvider
{
Encoding writeEncoding;
// Double-checked locking pattern requires volatile for read/write synchronization
volatile SynchronizedPool<XmlDictionaryWriter> streamedWriterPool;
volatile SynchronizedPool<XmlDictionaryReader> streamedReaderPool;
volatile SynchronizedPool<MtomBufferedMessageData> bufferedReaderPool;
volatile SynchronizedPool<MtomBufferedMessageWriter> bufferedWriterPool;
volatile SynchronizedPool<RecycledMessageState> recycledStatePool;
object thisLock;
MessageVersion version;
const int maxPooledXmlReadersPerMessage = 2;
int maxReadPoolSize;
int maxWritePoolSize;
static UriGenerator mimeBoundaryGenerator;
XmlDictionaryReaderQuotas readerQuotas;
XmlDictionaryReaderQuotas bufferedReadReaderQuotas;
int maxBufferSize;
OnXmlDictionaryReaderClose onStreamedReaderClose;
internal TextMessageEncoderFactory.ContentEncoding[] contentEncodingMap;
const string mtomMediaType = "multipart/related";
const string mtomContentType = mtomMediaType + "; type=\"application/xop+xml\"";
const string mtomStartUri = NamingHelper.DefaultNamespace + "0";
public MtomMessageEncoder(MessageVersion version, Encoding writeEncoding, int maxReadPoolSize, int maxWritePoolSize, int maxBufferSize, XmlDictionaryReaderQuotas quotas)
{
if (version == null)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("version");
if (writeEncoding == null)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("writeEncoding");
TextEncoderDefaults.ValidateEncoding(writeEncoding);
this.writeEncoding = writeEncoding;
this.maxReadPoolSize = maxReadPoolSize;
this.maxWritePoolSize = maxWritePoolSize;
this.readerQuotas = new XmlDictionaryReaderQuotas();
quotas.CopyTo(this.readerQuotas);
this.bufferedReadReaderQuotas = EncoderHelpers.GetBufferedReadQuotas(this.readerQuotas);
this.maxBufferSize = maxBufferSize;
this.onStreamedReaderClose = new OnXmlDictionaryReaderClose(ReturnStreamedReader);
this.thisLock = new object();
if (version.Envelope == EnvelopeVersion.Soap12)
{
this.contentEncodingMap = TextMessageEncoderFactory.Soap12Content;
}
else if (version.Envelope == EnvelopeVersion.Soap11)
{
this.contentEncodingMap = TextMessageEncoderFactory.Soap11Content;
}
else
{
Fx.Assert("Invalid MessageVersion");
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Invalid MessageVersion")));
}
this.version = version;
}
static UriGenerator MimeBoundaryGenerator
{
get
{
if (mimeBoundaryGenerator == null)
mimeBoundaryGenerator = new UriGenerator("uuid", "+");
return mimeBoundaryGenerator;
}
}
public override string ContentType
{
get { return mtomContentType; }
}
public int MaxWritePoolSize
{
get { return maxWritePoolSize; }
}
public int MaxReadPoolSize
{
get { return maxReadPoolSize; }
}
public XmlDictionaryReaderQuotas ReaderQuotas
{
get
{
return readerQuotas;
}
}
public int MaxBufferSize
{
get { return maxBufferSize; }
}
public override string MediaType
{
get { return mtomMediaType; }
}
public override MessageVersion MessageVersion
{
get { return version; }
}
internal bool IsMTOMContentType(string contentType)
{
// check for MTOM contentType: multipart/related; type=\"application/xop+xml\"
return IsContentTypeSupported(contentType, this.ContentType, this.MediaType);
}
internal bool IsTextContentType(string contentType)
{
// check for Text contentType: text/xml or application/soap+xml
string textMediaType = TextMessageEncoderFactory.GetMediaType(version);
string textContentType = TextMessageEncoderFactory.GetContentType(textMediaType, writeEncoding);
return IsContentTypeSupported(contentType, textContentType, textMediaType);
}
public override bool IsContentTypeSupported(string contentType)
{
if (contentType == null)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("contentType"));
return (IsMTOMContentType(contentType) || IsTextContentType(contentType));
}
internal override bool IsCharSetSupported(string charSet)
{
if (charSet == null || charSet.Length == 0)
return true;
Encoding tmp;
return TextEncoderDefaults.TryGetEncoding(charSet, out tmp);
}
string GenerateStartInfoString()
{
return (version.Envelope == EnvelopeVersion.Soap12) ? TextMessageEncoderFactory.Soap12MediaType : TextMessageEncoderFactory.Soap11MediaType;
}
public override Message ReadMessage(ArraySegment<byte> buffer, BufferManager bufferManager, string contentType)
{
if (bufferManager == null)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("bufferManager");
if (contentType == this.ContentType)
contentType = null;
if (TD.MtomMessageDecodingStartIsEnabled())
{
TD.MtomMessageDecodingStart();
}
MtomBufferedMessageData messageData = TakeBufferedReader();
messageData.ContentType = contentType;
messageData.Open(buffer, bufferManager);
RecycledMessageState messageState = messageData.TakeMessageState();
if (messageState == null)
messageState = new RecycledMessageState();
Message message = new BufferedMessage(messageData, messageState);
message.Properties.Encoder = this;
if (MessageLogger.LogMessagesAtTransportLevel)
MessageLogger.LogMessage(ref message, MessageLoggingSource.TransportReceive);
if (TD.MessageReadByEncoderIsEnabled() && buffer != null)
{
TD.MessageReadByEncoder(
EventTraceActivityHelper.TryExtractActivity(message, true),
buffer.Count,
this);
}
return message;
}
public override Message ReadMessage(Stream stream, int maxSizeOfHeaders, string contentType)
{
if (stream == null)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("stream"));
if (contentType == this.ContentType)
contentType = null;
if (TD.MtomMessageDecodingStartIsEnabled())
{
TD.MtomMessageDecodingStart();
}
XmlReader reader = TakeStreamedReader(stream, contentType);
Message message = Message.CreateMessage(reader, maxSizeOfHeaders, version);
message.Properties.Encoder = this;
if (TD.StreamedMessageReadByEncoderIsEnabled())
{
TD.StreamedMessageReadByEncoder(EventTraceActivityHelper.TryExtractActivity(message, true));
}
if (MessageLogger.LogMessagesAtTransportLevel)
MessageLogger.LogMessage(ref message, MessageLoggingSource.TransportReceive);
return message;
}
public override ArraySegment<byte> WriteMessage(Message message, int maxMessageSize, BufferManager bufferManager, int messageOffset)
{
return WriteMessage(message, maxMessageSize, bufferManager, messageOffset, GenerateStartInfoString(), null, null, true /*writeMessageHeaders*/);
}
internal string GetContentType(out string boundary)
{
string startInfo = GenerateStartInfoString();
boundary = MimeBoundaryGenerator.Next();
return FormatContentType(boundary, startInfo);
}
internal string FormatContentType(string boundary, string startInfo)
{
return String.Format(CultureInfo.InvariantCulture,
"{0};start=\"<{1}>\";boundary=\"{2}\";start-info=\"{3}\"",
mtomContentType, mtomStartUri, boundary, startInfo);
}
internal ArraySegment<byte> WriteMessage(Message message, int maxMessageSize, BufferManager bufferManager, int messageOffset, string boundary)
{
return WriteMessage(message, maxMessageSize, bufferManager, messageOffset, GenerateStartInfoString(), boundary, mtomStartUri, false /*writeMessageHeaders*/);
}
ArraySegment<byte> WriteMessage(Message message, int maxMessageSize, BufferManager bufferManager, int messageOffset, string startInfo, string boundary, string startUri, bool writeMessageHeaders)
{
if (message == null)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("message");
if (bufferManager == null)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("bufferManager");
if (maxMessageSize < 0)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("maxMessageSize", maxMessageSize,
SR.GetString(SR.ValueMustBeNonNegative)));
if (messageOffset < 0 || messageOffset > maxMessageSize)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("messageOffset", messageOffset,
SR.GetString(SR.ValueMustBeInRange, 0, maxMessageSize)));
ThrowIfMismatchedMessageVersion(message);
EventTraceActivity eventTraceActivity = null;
if (TD.MtomMessageEncodingStartIsEnabled())
{
eventTraceActivity = EventTraceActivityHelper.TryExtractActivity(message);
TD.MtomMessageEncodingStart(eventTraceActivity);
}
message.Properties.Encoder = this;
MtomBufferedMessageWriter messageWriter = TakeBufferedWriter();
messageWriter.StartInfo = startInfo;
messageWriter.Boundary = boundary;
messageWriter.StartUri = startUri;
messageWriter.WriteMessageHeaders = writeMessageHeaders;
messageWriter.MaxSizeInBytes = maxMessageSize;
ArraySegment<byte> messageData = messageWriter.WriteMessage(message, bufferManager, messageOffset, maxMessageSize);
ReturnMessageWriter(messageWriter);
if (TD.MessageWrittenByEncoderIsEnabled() && messageData != null)
{
TD.MessageWrittenByEncoder(
eventTraceActivity ?? EventTraceActivityHelper.TryExtractActivity(message),
messageData.Count,
this);
}
if (MessageLogger.LogMessagesAtTransportLevel)
{
string contentType = null;
if (boundary != null)
contentType = FormatContentType(boundary, startInfo ?? GenerateStartInfoString());
XmlDictionaryReader xmlDictionaryReader = XmlDictionaryReader.CreateMtomReader(messageData.Array, messageData.Offset, messageData.Count, MtomMessageEncoderFactory.GetSupportedEncodings(), contentType, XmlDictionaryReaderQuotas.Max, int.MaxValue, null);
MessageLogger.LogMessage(ref message, xmlDictionaryReader, MessageLoggingSource.TransportSend);
}
return messageData;
}
public override void WriteMessage(Message message, Stream stream)
{
WriteMessage(message, stream, GenerateStartInfoString(), null, null, true /*writeMessageHeaders*/);
}
internal void WriteMessage(Message message, Stream stream, string boundary)
{
WriteMessage(message, stream, GenerateStartInfoString(), boundary, mtomStartUri, false /*writeMessageHeaders*/);
}
public override IAsyncResult BeginWriteMessage(Message message, Stream stream, AsyncCallback callback, object state)
{
return new WriteMessageAsyncResult(message, stream, this, callback, state);
}
internal IAsyncResult BeginWriteMessage(Message message, Stream stream, string boundary, AsyncCallback callback, object state)
{
return new WriteMessageAsyncResult(message, stream, boundary, this, callback, state);
}
public override void EndWriteMessage(IAsyncResult result)
{
WriteMessageAsyncResult.End(result);
}
void WriteMessage(Message message, Stream stream, string startInfo, string boundary, string startUri, bool writeMessageHeaders)
{
if (message == null)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("message"));
if (stream == null)
throw TraceUtility.ThrowHelperError(new ArgumentNullException("stream"), message);
ThrowIfMismatchedMessageVersion(message);
EventTraceActivity eventTraceActivity = null;
if (TD.MtomMessageEncodingStartIsEnabled())
{
eventTraceActivity = EventTraceActivityHelper.TryExtractActivity(message);
TD.MtomMessageEncodingStart(eventTraceActivity);
}
message.Properties.Encoder = this;
if (MessageLogger.LogMessagesAtTransportLevel)
MessageLogger.LogMessage(ref message, MessageLoggingSource.TransportSend);
XmlDictionaryWriter xmlWriter = TakeStreamedWriter(stream, startInfo, boundary, startUri, writeMessageHeaders);
if (this.writeEncoding.WebName == "utf-8")
{
message.WriteMessage(xmlWriter);
}
else
{
xmlWriter.WriteStartDocument();
message.WriteMessage(xmlWriter);
xmlWriter.WriteEndDocument();
}
xmlWriter.Flush();
ReturnStreamedWriter(xmlWriter);
if (TD.StreamedMessageWrittenByEncoderIsEnabled())
{
TD.StreamedMessageWrittenByEncoder(eventTraceActivity ?? EventTraceActivityHelper.TryExtractActivity(message));
}
}
XmlDictionaryWriter TakeStreamedWriter(Stream stream, string startInfo, string boundary, string startUri, bool writeMessageHeaders)
{
if (streamedWriterPool == null)
{
lock (thisLock)
{
if (streamedWriterPool == null)
{
streamedWriterPool = new SynchronizedPool<XmlDictionaryWriter>(maxWritePoolSize);
}
}
}
XmlDictionaryWriter xmlWriter = streamedWriterPool.Take();
if (xmlWriter == null)
{
xmlWriter = XmlDictionaryWriter.CreateMtomWriter(stream, this.writeEncoding, int.MaxValue, startInfo, boundary, startUri, writeMessageHeaders, false);
if (TD.WritePoolMissIsEnabled())
{
TD.WritePoolMiss(xmlWriter.GetType().Name);
}
}
else
{
((IXmlMtomWriterInitializer)xmlWriter).SetOutput(stream, this.writeEncoding, int.MaxValue, startInfo, boundary, startUri, writeMessageHeaders, false);
}
return xmlWriter;
}
void ReturnStreamedWriter(XmlDictionaryWriter xmlWriter)
{
xmlWriter.Close();
streamedWriterPool.Return(xmlWriter);
}
MtomBufferedMessageWriter TakeBufferedWriter()
{
if (bufferedWriterPool == null)
{
lock (thisLock)
{
if (bufferedWriterPool == null)
{
bufferedWriterPool = new SynchronizedPool<MtomBufferedMessageWriter>(maxWritePoolSize);
}
}
}
MtomBufferedMessageWriter messageWriter = bufferedWriterPool.Take();
if (messageWriter == null)
{
messageWriter = new MtomBufferedMessageWriter(this);
if (TD.WritePoolMissIsEnabled())
{
TD.WritePoolMiss(messageWriter.GetType().Name);
}
}
return messageWriter;
}
void ReturnMessageWriter(MtomBufferedMessageWriter messageWriter)
{
bufferedWriterPool.Return(messageWriter);
}
MtomBufferedMessageData TakeBufferedReader()
{
if (bufferedReaderPool == null)
{
lock (thisLock)
{
if (bufferedReaderPool == null)
{
bufferedReaderPool = new SynchronizedPool<MtomBufferedMessageData>(maxReadPoolSize);
}
}
}
MtomBufferedMessageData messageData = bufferedReaderPool.Take();
if (messageData == null)
{
messageData = new MtomBufferedMessageData(this, maxPooledXmlReadersPerMessage);
if (TD.ReadPoolMissIsEnabled())
{
TD.ReadPoolMiss(messageData.GetType().Name);
}
}
return messageData;
}
void ReturnBufferedData(MtomBufferedMessageData messageData)
{
bufferedReaderPool.Return(messageData);
}
XmlReader TakeStreamedReader(Stream stream, string contentType)
{
if (streamedReaderPool == null)
{
lock (thisLock)
{
if (streamedReaderPool == null)
{
streamedReaderPool = new SynchronizedPool<XmlDictionaryReader>(maxReadPoolSize);
}
}
}
XmlDictionaryReader xmlReader = streamedReaderPool.Take();
try
{
if (contentType == null || IsMTOMContentType(contentType))
{
if (xmlReader != null && xmlReader is IXmlMtomReaderInitializer)
{
((IXmlMtomReaderInitializer)xmlReader).SetInput(stream, MtomMessageEncoderFactory.GetSupportedEncodings(), contentType, this.readerQuotas, this.maxBufferSize, onStreamedReaderClose);
}
else
{
xmlReader = XmlDictionaryReader.CreateMtomReader(stream, MtomMessageEncoderFactory.GetSupportedEncodings(), contentType, this.readerQuotas, this.maxBufferSize, onStreamedReaderClose);
if (TD.ReadPoolMissIsEnabled())
{
TD.ReadPoolMiss(xmlReader.GetType().Name);
}
}
}
else
{
if (xmlReader != null && xmlReader is IXmlTextReaderInitializer)
{
((IXmlTextReaderInitializer)xmlReader).SetInput(stream, TextMessageEncoderFactory.GetEncodingFromContentType(contentType, this.contentEncodingMap), this.readerQuotas, onStreamedReaderClose);
}
else
{
xmlReader = XmlDictionaryReader.CreateTextReader(stream, TextMessageEncoderFactory.GetEncodingFromContentType(contentType, this.contentEncodingMap), this.readerQuotas, onStreamedReaderClose);
if (TD.ReadPoolMissIsEnabled())
{
TD.ReadPoolMiss(xmlReader.GetType().Name);
}
}
}
}
catch (FormatException fe)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(
SR.GetString(SR.SFxErrorCreatingMtomReader), fe));
}
catch (XmlException xe)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(
SR.GetString(SR.SFxErrorCreatingMtomReader), xe));
}
return xmlReader;
}
void ReturnStreamedReader(XmlDictionaryReader xmlReader)
{
streamedReaderPool.Return(xmlReader);
}
SynchronizedPool<RecycledMessageState> RecycledStatePool
{
get
{
if (recycledStatePool == null)
{
lock (thisLock)
{
if (recycledStatePool == null)
{
recycledStatePool = new SynchronizedPool<RecycledMessageState>(maxReadPoolSize);
}
}
}
return recycledStatePool;
}
}
string ITraceSourceStringProvider.GetSourceString()
{
return base.GetTraceSourceString();
}
class MtomBufferedMessageData : BufferedMessageData
{
MtomMessageEncoder messageEncoder;
Pool<XmlDictionaryReader> readerPool;
internal string ContentType;
OnXmlDictionaryReaderClose onClose;
public MtomBufferedMessageData(MtomMessageEncoder messageEncoder, int maxReaderPoolSize)
: base(messageEncoder.RecycledStatePool)
{
this.messageEncoder = messageEncoder;
readerPool = new Pool<XmlDictionaryReader>(maxReaderPoolSize);
onClose = new OnXmlDictionaryReaderClose(OnXmlReaderClosed);
}
public override MessageEncoder MessageEncoder
{
get { return messageEncoder; }
}
public override XmlDictionaryReaderQuotas Quotas
{
get { return messageEncoder.bufferedReadReaderQuotas; }
}
protected override void OnClosed()
{
messageEncoder.ReturnBufferedData(this);
}
protected override XmlDictionaryReader TakeXmlReader()
{
try
{
ArraySegment<byte> buffer = this.Buffer;
XmlDictionaryReader xmlReader = readerPool.Take();
if (ContentType == null || messageEncoder.IsMTOMContentType(ContentType))
{
if (xmlReader != null && xmlReader is IXmlMtomReaderInitializer)
{
((IXmlMtomReaderInitializer)xmlReader).SetInput(buffer.Array, buffer.Offset, buffer.Count, MtomMessageEncoderFactory.GetSupportedEncodings(), ContentType, this.Quotas, this.messageEncoder.MaxBufferSize, onClose);
}
else
{
xmlReader = XmlDictionaryReader.CreateMtomReader(buffer.Array, buffer.Offset, buffer.Count, MtomMessageEncoderFactory.GetSupportedEncodings(), ContentType, this.Quotas, this.messageEncoder.MaxBufferSize, onClose);
if (TD.ReadPoolMissIsEnabled())
{
TD.ReadPoolMiss(xmlReader.GetType().Name);
}
}
}
else
{
if (xmlReader != null && xmlReader is IXmlTextReaderInitializer)
{
((IXmlTextReaderInitializer)xmlReader).SetInput(buffer.Array, buffer.Offset, buffer.Count, TextMessageEncoderFactory.GetEncodingFromContentType(ContentType, this.messageEncoder.contentEncodingMap), this.Quotas, onClose);
}
else
{
xmlReader = XmlDictionaryReader.CreateTextReader(buffer.Array, buffer.Offset, buffer.Count, TextMessageEncoderFactory.GetEncodingFromContentType(ContentType, this.messageEncoder.contentEncodingMap), this.Quotas, onClose);
if (TD.ReadPoolMissIsEnabled())
{
TD.ReadPoolMiss(xmlReader.GetType().Name);
}
}
}
return xmlReader;
}
catch (FormatException fe)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(
SR.GetString(SR.SFxErrorCreatingMtomReader), fe));
}
catch (XmlException xe)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(
SR.GetString(SR.SFxErrorCreatingMtomReader), xe));
}
}
protected override void ReturnXmlReader(XmlDictionaryReader xmlReader)
{
if (xmlReader != null)
readerPool.Return(xmlReader);
}
}
class MtomBufferedMessageWriter : BufferedMessageWriter
{
MtomMessageEncoder messageEncoder;
internal bool WriteMessageHeaders;
internal string StartInfo;
internal string StartUri;
internal string Boundary;
internal int MaxSizeInBytes = int.MaxValue;
XmlDictionaryWriter writer;
public MtomBufferedMessageWriter(MtomMessageEncoder messageEncoder)
{
this.messageEncoder = messageEncoder;
}
protected override XmlDictionaryWriter TakeXmlWriter(Stream stream)
{
XmlDictionaryWriter returnedWriter = writer;
if (returnedWriter == null)
{
returnedWriter = XmlDictionaryWriter.CreateMtomWriter(stream, messageEncoder.writeEncoding, MaxSizeInBytes, StartInfo, Boundary, StartUri, WriteMessageHeaders, false);
}
else
{
writer = null;
((IXmlMtomWriterInitializer)returnedWriter).SetOutput(stream, messageEncoder.writeEncoding, MaxSizeInBytes, StartInfo, Boundary, StartUri, WriteMessageHeaders, false);
}
if (messageEncoder.writeEncoding.WebName != "utf-8")
returnedWriter.WriteStartDocument();
return returnedWriter;
}
protected override void ReturnXmlWriter(XmlDictionaryWriter writer)
{
writer.Close();
if (this.writer == null)
this.writer = writer;
}
}
class WriteMessageAsyncResult : ScheduleActionItemAsyncResult
{
string boundary;
MtomMessageEncoder encoder;
Message message;
Stream stream;
bool writeBoundary;
public WriteMessageAsyncResult(Message message, Stream stream, MtomMessageEncoder encoder, AsyncCallback callback, object state)
: base(callback, state)
{
Fx.Assert(encoder != null, "encoder should never be null");
this.encoder = encoder;
this.message = message;
this.stream = stream;
Schedule();
}
public WriteMessageAsyncResult(Message message, Stream stream, string boundary, MtomMessageEncoder encoder, AsyncCallback callback, object state)
: base(callback, state)
{
Fx.Assert(encoder != null, "encoder should never be null");
this.encoder = encoder;
this.message = message;
this.stream = stream;
this.boundary = boundary;
this.writeBoundary = true;
Schedule();
}
protected override void OnDoWork()
{
this.encoder.WriteMessage(this.message, this.stream, this.encoder.GenerateStartInfoString(), string.IsNullOrEmpty(this.boundary) ? null : this.boundary, this.writeBoundary ? MtomMessageEncoder.mtomStartUri : null, !this.writeBoundary /*writeMessageHeaders*/);
}
}
}
}
|