Code:
/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / ServiceModel / System / ServiceModel / Channels / BinaryMessageEncoder.cs / 1 / BinaryMessageEncoder.cs
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------
namespace System.ServiceModel.Channels
{
using System.Collections.Generic;
using System.ServiceModel;
using System.IO;
using System.Runtime.Serialization;
using System.ServiceModel.Diagnostics;
using System.Text;
using System.Xml;
using System.Collections.ObjectModel;
class BinaryMessageEncoderFactory : MessageEncoderFactory
{
BinaryMessageEncoder messageEncoder;
MessageVersion messageVersion;
int maxReadPoolSize;
int maxWritePoolSize;
SynchronizedPool streamedWriterPool;
SynchronizedPool streamedReaderPool;
SynchronizedPool bufferedDataPool;
SynchronizedPool bufferedWriterPool;
SynchronizedPool recycledStatePool;
object thisLock;
//bool running;
const int maxPooledXmlReaderPerMessage = 2;
int maxSessionSize;
OnXmlDictionaryReaderClose onStreamedReaderClose;
XmlDictionaryReaderQuotas readerQuotas;
BinaryVersion binaryVersion;
public BinaryMessageEncoderFactory(MessageVersion messageVersion, int maxReadPoolSize, int maxWritePoolSize, int maxSessionSize,
XmlDictionaryReaderQuotas readerQuotas, BinaryVersion version)
{
this.messageVersion = messageVersion;
this.messageEncoder = new BinaryMessageEncoder(this, false, 0);
this.maxReadPoolSize = maxReadPoolSize;
this.maxWritePoolSize = maxWritePoolSize;
this.maxSessionSize = maxSessionSize;
this.thisLock = new object();
this.onStreamedReaderClose = new OnXmlDictionaryReaderClose(ReturnStreamedReader);
this.readerQuotas = new XmlDictionaryReaderQuotas();
if (readerQuotas != null)
readerQuotas.CopyTo(this.readerQuotas);
this.binaryVersion = version;
}
public override MessageEncoder Encoder
{
get
{
return messageEncoder;
}
}
public override MessageVersion MessageVersion
{
get { return messageVersion; }
}
object ThisLock
{
get { return thisLock; }
}
public static IXmlDictionary XmlDictionary
{
get { return XD.Dictionary; }
}
public int MaxWritePoolSize
{
get { return maxWritePoolSize; }
}
public XmlDictionaryReaderQuotas ReaderQuotas
{
get
{
return readerQuotas;
}
}
public int MaxReadPoolSize
{
get { return maxReadPoolSize; }
}
public int MaxSessionSize
{
get { return maxSessionSize; }
}
public override MessageEncoder CreateSessionEncoder()
{
return new BinaryMessageEncoder(this, true, maxSessionSize);
}
XmlDictionaryWriter TakeStreamedWriter(Stream stream)
{
if (streamedWriterPool == null)
{
lock (ThisLock)
{
if (streamedWriterPool == null)
{
//running = true;
streamedWriterPool = new SynchronizedPool(maxWritePoolSize);
}
}
}
XmlDictionaryWriter xmlWriter = streamedWriterPool.Take();
if (xmlWriter == null)
xmlWriter = XmlDictionaryWriter.CreateBinaryWriter(stream, binaryVersion.Dictionary, null, false);
else
((IXmlBinaryWriterInitializer)xmlWriter).SetOutput(stream, binaryVersion.Dictionary, null, false);
return xmlWriter;
}
void ReturnStreamedWriter(XmlDictionaryWriter xmlWriter)
{
xmlWriter.Close();
streamedWriterPool.Return(xmlWriter);
}
BinaryBufferedMessageWriter TakeBufferedWriter()
{
if (bufferedWriterPool == null)
{
lock (ThisLock)
{
if (bufferedWriterPool == null)
{
//running = true;
bufferedWriterPool = new SynchronizedPool(maxWritePoolSize);
}
}
}
BinaryBufferedMessageWriter messageWriter = bufferedWriterPool.Take();
if (messageWriter == null)
messageWriter = new BinaryBufferedMessageWriter(binaryVersion.Dictionary);
return messageWriter;
}
void ReturnMessageWriter(BinaryBufferedMessageWriter messageWriter)
{
bufferedWriterPool.Return(messageWriter);
}
XmlDictionaryReader TakeStreamedReader(Stream stream)
{
if (streamedReaderPool == null)
{
lock (ThisLock)
{
if (streamedReaderPool == null)
{
//running = true;
streamedReaderPool = new SynchronizedPool(maxReadPoolSize);
}
}
}
XmlDictionaryReader xmlReader = streamedReaderPool.Take();
if (xmlReader == null)
{
xmlReader = XmlDictionaryReader.CreateBinaryReader(stream,
binaryVersion.Dictionary,
readerQuotas,
null,
onStreamedReaderClose);
}
else
{
((IXmlBinaryReaderInitializer)xmlReader).SetInput(stream,
binaryVersion.Dictionary,
readerQuotas,
null,
onStreamedReaderClose);
}
return xmlReader;
}
void ReturnStreamedReader(XmlDictionaryReader xmlReader)
{
streamedReaderPool.Return(xmlReader);
}
BinaryBufferedMessageData TakeBufferedData(BinaryMessageEncoder messageEncoder)
{
if (bufferedDataPool == null)
{
lock (ThisLock)
{
if (bufferedDataPool == null)
{
//running = true;
bufferedDataPool = new SynchronizedPool(maxReadPoolSize);
}
}
}
BinaryBufferedMessageData messageData = bufferedDataPool.Take();
if (messageData == null)
messageData = new BinaryBufferedMessageData(this, maxPooledXmlReaderPerMessage);
messageData.SetMessageEncoder(messageEncoder);
return messageData;
}
void ReturnBufferedData(BinaryBufferedMessageData messageData)
{
messageData.SetMessageEncoder(null);
bufferedDataPool.Return(messageData);
}
SynchronizedPool RecycledStatePool
{
get
{
if (recycledStatePool == null)
{
lock (ThisLock)
{
if (recycledStatePool == null)
{
//running = true;
recycledStatePool = new SynchronizedPool(maxReadPoolSize);
}
}
}
return recycledStatePool;
}
}
class BinaryBufferedMessageData : BufferedMessageData
{
BinaryMessageEncoderFactory factory;
BinaryMessageEncoder messageEncoder;
Pool readerPool;
OnXmlDictionaryReaderClose onClose;
public BinaryBufferedMessageData(BinaryMessageEncoderFactory factory, int maxPoolSize)
: base(factory.RecycledStatePool)
{
this.factory = factory;
readerPool = new Pool(maxPoolSize);
onClose = new OnXmlDictionaryReaderClose(OnXmlReaderClosed);
}
public override MessageEncoder MessageEncoder
{
get { return messageEncoder; }
}
public override XmlDictionaryReaderQuotas Quotas
{
get { return factory.readerQuotas; }
}
public void SetMessageEncoder(BinaryMessageEncoder messageEncoder)
{
this.messageEncoder = messageEncoder;
}
protected override XmlDictionaryReader TakeXmlReader()
{
ArraySegment buffer = this.Buffer;
XmlDictionaryReader xmlReader = readerPool.Take();
if (xmlReader != null)
{
((IXmlBinaryReaderInitializer)xmlReader).SetInput(buffer.Array, buffer.Offset, buffer.Count,
factory.binaryVersion.Dictionary,
factory.readerQuotas,
messageEncoder.ReaderSession,
onClose);
}
else
{
xmlReader = XmlDictionaryReader.CreateBinaryReader(buffer.Array, buffer.Offset, buffer.Count,
factory.binaryVersion.Dictionary,
factory.readerQuotas,
messageEncoder.ReaderSession,
onClose);
}
return xmlReader;
}
protected override void ReturnXmlReader(XmlDictionaryReader reader)
{
readerPool.Return(reader);
}
protected override void OnClosed()
{
factory.ReturnBufferedData(this);
}
}
class BinaryBufferedMessageWriter : BufferedMessageWriter
{
XmlDictionaryWriter writer;
IXmlDictionary dictionary;
XmlBinaryWriterSession session;
public BinaryBufferedMessageWriter(IXmlDictionary dictionary)
{
this.dictionary = dictionary;
}
public BinaryBufferedMessageWriter(IXmlDictionary dictionary, XmlBinaryWriterSession session)
{
this.dictionary = dictionary;
this.session = session;
}
protected override XmlDictionaryWriter TakeXmlWriter(Stream stream)
{
XmlDictionaryWriter returnedWriter = writer;
if (returnedWriter == null)
{
returnedWriter = XmlDictionaryWriter.CreateBinaryWriter(stream, dictionary, session, false);
}
else
{
writer = null;
((IXmlBinaryWriterInitializer)returnedWriter).SetOutput(stream, dictionary, session, false);
}
return returnedWriter;
}
protected override void ReturnXmlWriter(XmlDictionaryWriter writer)
{
writer.Close();
if (this.writer == null)
this.writer = writer;
}
}
class BinaryMessageEncoder : MessageEncoder
{
BinaryMessageEncoderFactory factory;
bool isSession;
XmlBinaryWriterSessionWithQuota writerSession;
BinaryBufferedMessageWriter sessionMessageWriter;
XmlBinaryReaderSession readerSession;
XmlBinaryReaderSession readerSessionForLogging;
bool readerSessionForLoggingIsInvalid = false;
int writeIdCounter;
int idCounter;
int maxSessionSize;
int remainingReaderSessionSize;
bool isReaderSessionInvalid;
MessagePatterns messagePatterns;
public BinaryMessageEncoder(BinaryMessageEncoderFactory factory, bool isSession, int maxSessionSize)
{
this.factory = factory;
this.isSession = isSession;
this.maxSessionSize = maxSessionSize;
this.remainingReaderSessionSize = maxSessionSize;
}
public override string ContentType
{
get { return isSession ? factory.binaryVersion.SessionContentType : factory.binaryVersion.ContentType; }
}
public override MessageVersion MessageVersion
{
get { return factory.messageVersion; }
}
public override string MediaType
{
get { return isSession ? factory.binaryVersion.SessionContentType : factory.binaryVersion.ContentType; }
}
public XmlBinaryReaderSession ReaderSession
{
get { return readerSession; }
}
ArraySegment AddSessionInformationToMessage(ArraySegment messageData, BufferManager bufferManager, int maxMessageSize)
{
int dictionarySize = 0;
byte[] buffer = messageData.Array;
if (writerSession.HasNewStrings)
{
IList newStrings = writerSession.GetNewStrings();
for (int i = 0; i < newStrings.Count; i++)
{
int utf8ValueSize = Encoding.UTF8.GetByteCount(newStrings[i].Value);
dictionarySize += IntEncoder.GetEncodedSize(utf8ValueSize) + utf8ValueSize;
}
int messageSize = messageData.Offset + messageData.Count;
int remainingMessageSize = maxMessageSize - messageSize;
if (remainingMessageSize - dictionarySize < 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new QuotaExceededException(SR.GetString(SR.MaxSentMessageSizeExceeded, maxMessageSize)));
}
int requiredBufferSize = messageData.Offset + messageData.Count + dictionarySize;
if (buffer.Length < requiredBufferSize)
{
byte[] newBuffer = bufferManager.TakeBuffer(requiredBufferSize);
Buffer.BlockCopy(buffer, messageData.Offset, newBuffer, messageData.Offset, messageData.Count);
bufferManager.ReturnBuffer(buffer);
buffer = newBuffer;
}
Buffer.BlockCopy(buffer, messageData.Offset, buffer, messageData.Offset + dictionarySize, messageData.Count);
int offset = messageData.Offset;
for (int i = 0; i < newStrings.Count; i++)
{
string newString = newStrings[i].Value;
int utf8ValueSize = Encoding.UTF8.GetByteCount(newString);
offset += IntEncoder.Encode(utf8ValueSize, buffer, offset);
offset += Encoding.UTF8.GetBytes(newString, 0, newString.Length, buffer, offset);
}
writerSession.ClearNewStrings();
}
int headerSize = IntEncoder.GetEncodedSize(dictionarySize);
int newOffset = messageData.Offset - headerSize;
int newSize = headerSize + messageData.Count + dictionarySize;
IntEncoder.Encode(dictionarySize, buffer, newOffset);
return new ArraySegment(buffer, newOffset, newSize);
}
ArraySegment ExtractSessionInformationFromMessage(ArraySegment messageData)
{
if (isReaderSessionInvalid)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataException(SR.GetString(SR.BinaryEncoderSessionInvalid)));
}
byte[] buffer = messageData.Array;
int dictionarySize;
int headerSize;
int newOffset;
int newSize;
bool throwing = true;
try
{
IntDecoder decoder = new IntDecoder();
headerSize = decoder.Decode(buffer, messageData.Offset, messageData.Count);
dictionarySize = decoder.Value;
if (dictionarySize > messageData.Count)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataException(SR.GetString(SR.BinaryEncoderSessionMalformed)));
}
newOffset = messageData.Offset + headerSize + dictionarySize;
newSize = messageData.Count - headerSize - dictionarySize;
if (newSize < 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataException(SR.GetString(SR.BinaryEncoderSessionMalformed)));
}
if (dictionarySize > 0)
{
if (dictionarySize > remainingReaderSessionSize)
{
string message = SR.GetString(SR.BinaryEncoderSessionTooLarge, this.maxSessionSize);
Exception inner = new QuotaExceededException(message);
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(message, inner));
}
else
{
remainingReaderSessionSize -= dictionarySize;
}
int size = dictionarySize;
int offset = messageData.Offset + headerSize;
while (size > 0)
{
decoder.Reset();
int bytesDecoded = decoder.Decode(buffer, offset, size);
int utf8ValueSize = decoder.Value;
offset += bytesDecoded;
size -= bytesDecoded;
if (utf8ValueSize > size)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataException(SR.GetString(SR.BinaryEncoderSessionMalformed)));
}
string value = Encoding.UTF8.GetString(buffer, offset, utf8ValueSize);
offset += utf8ValueSize;
size -= utf8ValueSize;
readerSession.Add(idCounter, value);
idCounter++;
}
}
throwing = false;
}
finally
{
if (throwing)
{
isReaderSessionInvalid = true;
}
}
return new ArraySegment(buffer, newOffset, newSize);
}
public override Message ReadMessage(ArraySegment buffer, BufferManager bufferManager, string contentType)
{
if (bufferManager == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("bufferManager");
}
if (contentType != null && contentType != this.ContentType && string.Compare(contentType, this.ContentType, StringComparison.OrdinalIgnoreCase) != 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ProtocolException(SR.GetString(SR.EncoderUnrecognizedContentType, contentType, this.ContentType)));
}
if (isSession)
{
if (readerSession == null)
{
readerSession = new XmlBinaryReaderSession();
messagePatterns = new MessagePatterns(factory.binaryVersion.Dictionary, readerSession, this.MessageVersion);
}
try
{
buffer = ExtractSessionInformationFromMessage(buffer);
}
catch (InvalidDataException)
{
MessageLogger.LogMessage(buffer, MessageLoggingSource.Malformed);
throw;
}
}
BinaryBufferedMessageData messageData = factory.TakeBufferedData(this);
Message message;
if (messagePatterns != null)
{
message = messagePatterns.TryCreateMessage(buffer.Array, buffer.Offset, buffer.Count, bufferManager, messageData);
}
else
{
message = null;
}
if (message == null)
{
messageData.Open(buffer, bufferManager);
RecycledMessageState messageState = messageData.TakeMessageState();
if (messageState == null)
messageState = new RecycledMessageState();
message = new BufferedMessage(messageData, messageState);
}
message.Properties.Encoder = this;
if (MessageLogger.LogMessagesAtTransportLevel)
{
MessageLogger.LogMessage(ref message, MessageLoggingSource.TransportReceive);
}
return message;
}
public override Message ReadMessage(Stream stream, int maxSizeOfHeaders, string contentType)
{
if (stream == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("stream");
}
if (contentType != null && contentType != this.ContentType && string.Compare(contentType, this.ContentType, StringComparison.OrdinalIgnoreCase) != 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ProtocolException(SR.GetString(SR.EncoderUnrecognizedContentType, contentType, this.ContentType)));
}
XmlDictionaryReader reader = factory.TakeStreamedReader(stream);
Message message = Message.CreateMessage(reader, maxSizeOfHeaders, factory.messageVersion);
message.Properties.Encoder = this;
if (MessageLogger.LogMessagesAtTransportLevel)
{
MessageLogger.LogMessage(ref message, MessageLoggingSource.TransportReceive);
}
return message;
}
public override ArraySegment WriteMessage(Message message, int maxMessageSize, BufferManager bufferManager, int messageOffset)
{
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)));
}
message.Properties.Encoder = this;
if (isSession)
{
if (writerSession == null)
{
writerSession = new XmlBinaryWriterSessionWithQuota(maxSessionSize);
sessionMessageWriter = new BinaryBufferedMessageWriter(factory.binaryVersion.Dictionary, writerSession);
}
messageOffset += IntEncoder.MaxEncodedSize;
}
if (messageOffset < 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("messageOffset", messageOffset,
SR.GetString(SR.ValueMustBeNonNegative)));
}
if (messageOffset > maxMessageSize)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new QuotaExceededException(SR.GetString(SR.MaxSentMessageSizeExceeded, maxMessageSize)));
}
ThrowIfMismatchedMessageVersion(message);
BinaryBufferedMessageWriter messageWriter;
if (isSession)
{
messageWriter = sessionMessageWriter;
}
else
{
messageWriter = factory.TakeBufferedWriter();
}
ArraySegment messageData = messageWriter.WriteMessage(message, bufferManager, messageOffset, maxMessageSize);
if (MessageLogger.LogMessagesAtTransportLevel && !this.readerSessionForLoggingIsInvalid)
{
if (isSession)
{
if (this.readerSessionForLogging == null)
{
this.readerSessionForLogging = new XmlBinaryReaderSession();
}
if (this.writerSession.HasNewStrings)
{
foreach (XmlDictionaryString xmlDictionaryString in this.writerSession.GetNewStrings())
{
this.readerSessionForLogging.Add(this.writeIdCounter++, xmlDictionaryString.Value);
}
}
}
XmlDictionaryReader xmlDictionaryReader = XmlDictionaryReader.CreateBinaryReader(messageData.Array, messageData.Offset, messageData.Count, XD.Dictionary, XmlDictionaryReaderQuotas.Max, this.readerSessionForLogging, null);
MessageLogger.LogMessage(ref message, xmlDictionaryReader, MessageLoggingSource.TransportSend);
}
else
{
this.readerSessionForLoggingIsInvalid = true;
}
if (isSession)
{
messageData = AddSessionInformationToMessage(messageData, bufferManager, maxMessageSize);
}
else
{
factory.ReturnMessageWriter(messageWriter);
}
return messageData;
}
public override void WriteMessage(Message message, Stream stream)
{
if (message == null)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("message"));
if (stream == null)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("stream"));
ThrowIfMismatchedMessageVersion(message);
message.Properties.Encoder = this;
XmlDictionaryWriter xmlWriter = factory.TakeStreamedWriter(stream);
message.WriteMessage(xmlWriter);
xmlWriter.Flush();
factory.ReturnStreamedWriter(xmlWriter);
if (MessageLogger.LogMessagesAtTransportLevel)
{
MessageLogger.LogMessage(ref message, MessageLoggingSource.TransportSend);
}
}
}
class XmlBinaryWriterSessionWithQuota : XmlBinaryWriterSession
{
int bytesRemaining;
List newStrings;
public XmlBinaryWriterSessionWithQuota(int maxSessionSize)
{
bytesRemaining = maxSessionSize;
}
public override bool TryAdd(XmlDictionaryString s, out int key)
{
if (bytesRemaining == 0)
{
key = -1;
return false;
}
int bytesRequired = Encoding.UTF8.GetByteCount(s.Value);
bytesRequired += IntEncoder.GetEncodedSize(bytesRequired);
if (bytesRequired > bytesRemaining)
{
key = -1;
bytesRemaining = 0;
return false;
}
if (base.TryAdd(s, out key))
{
if (newStrings == null)
{
newStrings = new List();
}
newStrings.Add(s);
bytesRemaining -= bytesRequired;
return true;
}
else
{
return false;
}
}
public bool HasNewStrings
{
get { return newStrings != null; }
}
public IList GetNewStrings()
{
return newStrings;
}
public void ClearNewStrings()
{
newStrings = null;
}
}
}
class BinaryFormatBuilder
{
List bytes;
public BinaryFormatBuilder()
{
this.bytes = new List();
}
public int Count
{
get { return bytes.Count; }
}
public void AppendPrefixDictionaryElement(char prefix, int key)
{
this.AppendNode(XmlBinaryNodeType.PrefixDictionaryElementA + GetPrefixOffset(prefix));
this.AppendKey(key);
}
public void AppendDictionaryXmlnsAttribute(char prefix, int key)
{
this.AppendNode(XmlBinaryNodeType.DictionaryXmlnsAttribute);
this.AppendUtf8(prefix);
this.AppendKey(key);
}
public void AppendPrefixDictionaryAttribute(char prefix, int key, char value)
{
this.AppendNode(XmlBinaryNodeType.PrefixDictionaryAttributeA + GetPrefixOffset(prefix));
this.AppendKey(key);
if (value == '1')
{
this.AppendNode(XmlBinaryNodeType.OneText);
}
else
{
this.AppendNode(XmlBinaryNodeType.Chars8Text);
this.AppendUtf8(value);
}
}
public void AppendDictionaryAttribute(char prefix, int key, char value)
{
this.AppendNode(XmlBinaryNodeType.DictionaryAttribute);
this.AppendUtf8(prefix);
this.AppendKey(key);
this.AppendNode(XmlBinaryNodeType.Chars8Text);
this.AppendUtf8(value);
}
public void AppendDictionaryTextWithEndElement(int key)
{
this.AppendNode(XmlBinaryNodeType.DictionaryTextWithEndElement);
this.AppendKey(key);
}
public void AppendDictionaryTextWithEndElement()
{
this.AppendNode(XmlBinaryNodeType.DictionaryTextWithEndElement);
}
public void AppendUniqueIDWithEndElement()
{
this.AppendNode(XmlBinaryNodeType.UniqueIdTextWithEndElement);
}
public void AppendEndElement()
{
this.AppendNode(XmlBinaryNodeType.EndElement);
}
void AppendKey(int key)
{
if (key < 0 || key >= 0x4000)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("key", key,
SR.GetString(SR.ValueMustBeInRange, 0, 0x4000)));
if (key >= 0x80)
{
this.AppendByte((key & 0x7f) | 0x80);
this.AppendByte(key >> 7);
}
else
{
this.AppendByte(key);
}
}
void AppendNode(XmlBinaryNodeType value)
{
this.AppendByte((int)value);
}
void AppendByte(int value)
{
if (value < 0 || value > 0xFF)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", value,
SR.GetString(SR.ValueMustBeInRange, 0, 0xFF)));
this.bytes.Add((byte)value);
}
void AppendUtf8(char value)
{
AppendByte(1);
AppendByte((int)value);
}
public int GetStaticKey(int value)
{
return value * 2;
}
public int GetSessionKey(int value)
{
return value * 2 + 1;
}
int GetPrefixOffset(char prefix)
{
if (prefix < 'a' && prefix > 'z')
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("prefix", prefix,
SR.GetString(SR.ValueMustBeInRange, 'a', 'z')));
return prefix - 'a';
}
public byte[] ToByteArray()
{
byte[] array = this.bytes.ToArray();
this.bytes.Clear();
return array;
}
}
static class BinaryFormatParser
{
public static bool IsSessionKey(int value)
{
return (value & 1) != 0;
}
public static int GetSessionKey(int value)
{
return value / 2;
}
public static int GetStaticKey(int value)
{
return value / 2;
}
public static int ParseInt32(byte[] buffer, int offset, int size)
{
switch (size)
{
case 1:
return buffer[offset];
case 2:
return (buffer[offset] & 0x7f) + (buffer[offset + 1] << 7);
case 3:
return (buffer[offset] & 0x7f) + ((buffer[offset + 1] & 0x7f) << 7) + (buffer[offset + 2] << 14);
case 4:
return (buffer[offset] & 0x7f) + ((buffer[offset + 1] & 0x7f) << 7) + ((buffer[offset + 2] & 0x7f) << 14) + (buffer[offset + 3] << 21);
default:
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("size", size,
SR.GetString(SR.ValueMustBeInRange, 1, 4)));
}
}
public static int ParseKey(byte[] buffer, int offset, int size)
{
return ParseInt32(buffer, offset, size);
}
public unsafe static UniqueId ParseUniqueID(byte[] buffer, int offset, int size)
{
return new UniqueId(buffer, offset);
}
public static int MatchBytes(byte[] buffer, int offset, int size, byte[] buffer2)
{
if (size < buffer2.Length)
{
return 0;
}
int j = offset;
for (int i = 0; i < buffer2.Length; i++, j++)
{
if (buffer2[i] != buffer[j])
{
return 0;
}
}
return buffer2.Length;
}
public static bool MatchAttributeNode(byte[] buffer, int offset, int size)
{
const XmlBinaryNodeType minAttribute = XmlBinaryNodeType.ShortAttribute;
const XmlBinaryNodeType maxAttribute = XmlBinaryNodeType.DictionaryAttribute;
if (size < 1)
return false;
XmlBinaryNodeType nodeType = (XmlBinaryNodeType)buffer[offset];
return nodeType >= minAttribute && nodeType <= maxAttribute;
}
public static int MatchKey(byte[] buffer, int offset, int size)
{
return MatchInt32(buffer, offset, size);
}
public static int MatchInt32(byte[] buffer, int offset, int size)
{
if (size > 0)
{
if ((buffer[offset] & 0x80) == 0)
{
return 1;
}
}
if (size > 1)
{
if ((buffer[offset + 1] & 0x80) == 0)
{
return 2;
}
}
if (size > 2)
{
if ((buffer[offset + 2] & 0x80) == 0)
{
return 3;
}
}
if (size > 3)
{
if ((buffer[offset + 3] & 0x80) == 0)
{
return 4;
}
}
return 0;
}
public static int MatchUniqueID(byte[] buffer, int offset, int size)
{
if (size < 16)
return 0;
return 16;
}
}
class MessagePatterns
{
IXmlDictionary dictionary;
XmlBinaryReaderSession readerSession;
ToHeader toHeader;
static readonly byte[] commonFragment; //
static readonly byte[] requestFragment1; //
static readonly byte[] requestFragment2; // ... session-to-key
static readonly byte[] responseFragment1; //
static readonly byte[] responseFragment2; // static-anonymous-key
static readonly byte[] bodyFragment; //
const int ToValueSessionKey = 1;
MessageVersion messageVersion;
public MessagePatterns(IXmlDictionary dictionary, XmlBinaryReaderSession readerSession, MessageVersion messageVersion)
{
this.dictionary = dictionary;
this.readerSession = readerSession;
this.messageVersion = messageVersion;
}
static MessagePatterns()
{
BinaryFormatBuilder builder = new BinaryFormatBuilder();
MessageDictionary messageDictionary = XD.MessageDictionary;
Message12Dictionary message12Dictionary = XD.Message12Dictionary;
AddressingDictionary addressingDictionary = XD.AddressingDictionary;
Addressing10Dictionary addressing10Dictionary = XD.Addressing10Dictionary;
char messagePrefix = MessageStrings.Prefix[0];
char addressingPrefix = AddressingStrings.Prefix[0];
//
builder.AppendPrefixDictionaryElement(messagePrefix, builder.GetStaticKey(messageDictionary.Envelope.Key));
builder.AppendDictionaryXmlnsAttribute(messagePrefix, builder.GetStaticKey(message12Dictionary.Namespace.Key));
builder.AppendDictionaryXmlnsAttribute(addressingPrefix, builder.GetStaticKey(addressing10Dictionary.Namespace.Key));
//
builder.AppendPrefixDictionaryElement(messagePrefix, builder.GetStaticKey(messageDictionary.Header.Key));
// ...
builder.AppendPrefixDictionaryElement(addressingPrefix, builder.GetStaticKey(addressingDictionary.Action.Key));
builder.AppendPrefixDictionaryAttribute(messagePrefix, builder.GetStaticKey(messageDictionary.MustUnderstand.Key), '1');
builder.AppendDictionaryTextWithEndElement();
commonFragment = builder.ToByteArray();
// ...
builder.AppendPrefixDictionaryElement(addressingPrefix, builder.GetStaticKey(addressingDictionary.MessageId.Key));
builder.AppendUniqueIDWithEndElement();
requestFragment1 = builder.ToByteArray();
// static-anonymous-key
builder.AppendPrefixDictionaryElement(addressingPrefix, builder.GetStaticKey(addressingDictionary.ReplyTo.Key));
builder.AppendPrefixDictionaryElement(addressingPrefix, builder.GetStaticKey(addressingDictionary.Address.Key));
builder.AppendDictionaryTextWithEndElement(builder.GetStaticKey(addressing10Dictionary.Anonymous.Key));
builder.AppendEndElement();
// session-to-key
builder.AppendPrefixDictionaryElement(addressingPrefix, builder.GetStaticKey(addressingDictionary.To.Key));
builder.AppendPrefixDictionaryAttribute(messagePrefix, builder.GetStaticKey(messageDictionary.MustUnderstand.Key), '1');
builder.AppendDictionaryTextWithEndElement(builder.GetSessionKey(ToValueSessionKey));
//
builder.AppendEndElement();
//
builder.AppendPrefixDictionaryElement(messagePrefix, builder.GetStaticKey(messageDictionary.Body.Key));
requestFragment2 = builder.ToByteArray();
// ...
builder.AppendPrefixDictionaryElement(addressingPrefix, builder.GetStaticKey(addressingDictionary.RelatesTo.Key));
builder.AppendUniqueIDWithEndElement();
responseFragment1 = builder.ToByteArray();
// static-anonymous-key
builder.AppendPrefixDictionaryElement(addressingPrefix, builder.GetStaticKey(addressingDictionary.To.Key));
builder.AppendPrefixDictionaryAttribute(messagePrefix, builder.GetStaticKey(messageDictionary.MustUnderstand.Key), '1');
builder.AppendDictionaryTextWithEndElement(builder.GetStaticKey(addressing10Dictionary.Anonymous.Key));
//
builder.AppendEndElement();
//
builder.AppendPrefixDictionaryElement(messagePrefix, builder.GetStaticKey(messageDictionary.Body.Key));
responseFragment2 = builder.ToByteArray();
//
builder.AppendPrefixDictionaryElement(messagePrefix, builder.GetStaticKey(messageDictionary.Envelope.Key));
builder.AppendDictionaryXmlnsAttribute(messagePrefix, builder.GetStaticKey(message12Dictionary.Namespace.Key));
builder.AppendDictionaryXmlnsAttribute(addressingPrefix, builder.GetStaticKey(addressing10Dictionary.Namespace.Key));
//
builder.AppendPrefixDictionaryElement(messagePrefix, builder.GetStaticKey(messageDictionary.Body.Key));
bodyFragment = builder.ToByteArray();
}
public Message TryCreateMessage(byte[] buffer, int offset, int size, BufferManager bufferManager, BufferedMessageData messageData)
{
RelatesToHeader relatesToHeader;
MessageIDHeader messageIDHeader;
XmlDictionaryString toString;
int currentOffset = offset;
int remainingSize = size;
int bytesMatched = BinaryFormatParser.MatchBytes(buffer, currentOffset, remainingSize, commonFragment);
if (bytesMatched == 0)
return null;
currentOffset += bytesMatched;
remainingSize -= bytesMatched;
bytesMatched = BinaryFormatParser.MatchKey(buffer, currentOffset, remainingSize);
if (bytesMatched == 0)
return null;
int actionOffset = currentOffset;
int actionSize = bytesMatched;
currentOffset += bytesMatched;
remainingSize -= bytesMatched;
int totalBytesMatched;
bytesMatched = BinaryFormatParser.MatchBytes(buffer, currentOffset, remainingSize, requestFragment1);
if (bytesMatched != 0)
{
currentOffset += bytesMatched;
remainingSize -= bytesMatched;
bytesMatched = BinaryFormatParser.MatchUniqueID(buffer, currentOffset, remainingSize);
if (bytesMatched == 0)
return null;
int messageIDOffset = currentOffset;
int messageIDSize = bytesMatched;
currentOffset += bytesMatched;
remainingSize -= bytesMatched;
bytesMatched = BinaryFormatParser.MatchBytes(buffer, currentOffset, remainingSize, requestFragment2);
if (bytesMatched == 0)
return null;
currentOffset += bytesMatched;
remainingSize -= bytesMatched;
if (BinaryFormatParser.MatchAttributeNode(buffer, currentOffset, remainingSize))
return null;
UniqueId messageId = BinaryFormatParser.ParseUniqueID(buffer, messageIDOffset, messageIDSize);
messageIDHeader = MessageIDHeader.Create(messageId, messageVersion.Addressing);
relatesToHeader = null;
if (!readerSession.TryLookup(ToValueSessionKey, out toString))
return null;
totalBytesMatched = requestFragment1.Length + messageIDSize + requestFragment2.Length;
}
else
{
bytesMatched = BinaryFormatParser.MatchBytes(buffer, currentOffset, remainingSize, responseFragment1);
if (bytesMatched == 0)
return null;
currentOffset += bytesMatched;
remainingSize -= bytesMatched;
bytesMatched = BinaryFormatParser.MatchUniqueID(buffer, currentOffset, remainingSize);
if (bytesMatched == 0)
return null;
int messageIDOffset = currentOffset;
int messageIDSize = bytesMatched;
currentOffset += bytesMatched;
remainingSize -= bytesMatched;
bytesMatched = BinaryFormatParser.MatchBytes(buffer, currentOffset, remainingSize, responseFragment2);
if (bytesMatched == 0)
return null;
currentOffset += bytesMatched;
remainingSize -= bytesMatched;
if (BinaryFormatParser.MatchAttributeNode(buffer, currentOffset, remainingSize))
return null;
UniqueId messageId = BinaryFormatParser.ParseUniqueID(buffer, messageIDOffset, messageIDSize);
relatesToHeader = RelatesToHeader.Create(messageId, messageVersion.Addressing);
messageIDHeader = null;
toString = XD.Addressing10Dictionary.Anonymous;
totalBytesMatched = responseFragment1.Length + messageIDSize + responseFragment2.Length;
}
totalBytesMatched += commonFragment.Length + actionSize;
int actionKey = BinaryFormatParser.ParseKey(buffer, actionOffset, actionSize);
XmlDictionaryString actionString;
if (!TryLookupKey(actionKey, out actionString))
return null;
ActionHeader actionHeader = ActionHeader.Create(actionString, messageVersion.Addressing);
if (toHeader == null)
{
toHeader = ToHeader.Create(new Uri(toString.Value), messageVersion.Addressing);
}
int abandonedSize = totalBytesMatched - bodyFragment.Length;
offset += abandonedSize;
size -= abandonedSize;
Buffer.BlockCopy(bodyFragment, 0, buffer, offset, bodyFragment.Length);
messageData.Open(new ArraySegment(buffer, offset, size), bufferManager);
PatternMessage patternMessage = new PatternMessage(messageData, this.messageVersion);
MessageHeaders headers = patternMessage.Headers;
headers.AddActionHeader(actionHeader);
if (messageIDHeader != null)
{
headers.AddMessageIDHeader(messageIDHeader);
headers.AddReplyToHeader(ReplyToHeader.AnonymousReplyTo10);
}
else
{
headers.AddRelatesToHeader(relatesToHeader);
}
headers.AddToHeader(toHeader);
return patternMessage;
}
bool TryLookupKey(int key, out XmlDictionaryString result)
{
if (BinaryFormatParser.IsSessionKey(key))
{
return readerSession.TryLookup(BinaryFormatParser.GetSessionKey(key), out result);
}
else
{
return dictionary.TryLookup(BinaryFormatParser.GetStaticKey(key), out result);
}
}
sealed class PatternMessage : ReceivedMessage
{
IBufferedMessageData messageData;
MessageHeaders headers;
RecycledMessageState recycledMessageState;
MessageProperties properties;
XmlDictionaryReader reader;
public PatternMessage(IBufferedMessageData messageData, MessageVersion messageVersion)
{
this.messageData = messageData;
recycledMessageState = messageData.TakeMessageState();
if (recycledMessageState == null)
recycledMessageState = new RecycledMessageState();
properties = recycledMessageState.TakeProperties();
if (properties == null)
this.properties = new MessageProperties();
headers = recycledMessageState.TakeHeaders();
if (headers == null)
{
headers = new MessageHeaders(messageVersion);
}
else
{
headers.Init(messageVersion);
}
XmlDictionaryReader reader = messageData.GetMessageReader();
reader.ReadStartElement();
VerifyStartBody(reader, messageVersion.Envelope);
ReadStartBody(reader);
this.reader = reader;
}
public override MessageHeaders Headers
{
get
{
if (IsDisposed)
#pragma warning suppress 56503 // [....], Invalid State after dispose
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateMessageDisposedException());
return headers;
}
}
public override MessageProperties Properties
{
get
{
if (IsDisposed)
#pragma warning suppress 56503 // [....], Invalid State after dispose
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateMessageDisposedException());
return properties;
}
}
internal override RecycledMessageState RecycledMessageState
{
get { return recycledMessageState; }
}
public override MessageVersion Version
{
get
{
if (IsDisposed)
#pragma warning suppress 56503 // [....], Invalid State after dispose
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateMessageDisposedException());
return headers.MessageVersion;
}
}
XmlDictionaryReader GetBufferedReaderAtBody()
{
XmlDictionaryReader reader = messageData.GetMessageReader();
reader.ReadStartElement();
reader.ReadStartElement();
return reader;
}
protected override void OnBodyToString(XmlDictionaryWriter writer)
{
using (XmlDictionaryReader reader = GetBufferedReaderAtBody())
{
while (reader.NodeType != XmlNodeType.EndElement)
writer.WriteNode(reader, false);
}
}
protected override void OnClose()
{
Exception ex = null;
try
{
base.OnClose();
}
catch (Exception e)
{
if (DiagnosticUtility.IsFatal(e))
throw;
ex = e;
}
try
{
properties.Dispose();
}
catch (Exception e)
{
if (DiagnosticUtility.IsFatal(e))
throw;
if (ex == null)
ex = e;
}
try
{
if (reader != null)
{
reader.Close();
}
}
catch (Exception e)
{
if (DiagnosticUtility.IsFatal(e))
throw;
if (ex == null)
ex = e;
}
try
{
recycledMessageState.ReturnHeaders(headers);
recycledMessageState.ReturnProperties(properties);
messageData.ReturnMessageState(recycledMessageState);
recycledMessageState = null;
messageData.Close();
messageData = null;
}
catch (Exception e)
{
if (DiagnosticUtility.IsFatal(e))
throw;
if (ex == null)
ex = e;
}
if (ex != null)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(ex);
}
protected override MessageBuffer OnCreateBufferedCopy(int maxBufferSize)
{
return base.OnCreateBufferedCopy(maxBufferSize);
}
protected override XmlDictionaryReader OnGetReaderAtBodyContents()
{
XmlDictionaryReader reader = this.reader;
this.reader = null;
return reader;
}
protected override string OnGetBodyAttribute(string localName, string ns)
{
return null;
}
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- RightNameExpirationInfoPair.cs
- WebBrowsableAttribute.cs
- DataGridViewCellStyleConverter.cs
- Event.cs
- PageClientProxyGenerator.cs
- ModelUIElement3D.cs
- Condition.cs
- InstanceCompleteException.cs
- OleDbParameterCollection.cs
- BitmapEffectInput.cs
- SeverityFilter.cs
- KoreanCalendar.cs
- DataServiceHost.cs
- ChtmlSelectionListAdapter.cs
- BindingOperations.cs
- _HeaderInfoTable.cs
- Atom10FormatterFactory.cs
- KeyPullup.cs
- MapPathBasedVirtualPathProvider.cs
- HotSpot.cs
- MsmqSecureHashAlgorithm.cs
- DispatcherProcessingDisabled.cs
- XmlSchemaAny.cs
- StreamInfo.cs
- LiteralControl.cs
- FigureParaClient.cs
- NameGenerator.cs
- ValueChangedEventManager.cs
- EpmTargetPathSegment.cs
- GB18030Encoding.cs
- WebPartDisplayModeCancelEventArgs.cs
- IPGlobalProperties.cs
- EntityModelSchemaGenerator.cs
- DBSchemaRow.cs
- XmlTypeAttribute.cs
- ScrollBar.cs
- TextBlockAutomationPeer.cs
- RadioButtonAutomationPeer.cs
- BypassElement.cs
- DataPagerCommandEventArgs.cs
- RestrictedTransactionalPackage.cs
- SortFieldComparer.cs
- EncodingInfo.cs
- Buffer.cs
- OutputCacheSettings.cs
- ProjectionPath.cs
- HasCopySemanticsAttribute.cs
- WebPartVerb.cs
- XmlLinkedNode.cs
- SecurityAttributeGenerationHelper.cs
- XPathMultyIterator.cs
- WinInet.cs
- DataObject.cs
- DBConnection.cs
- BuildManagerHost.cs
- XmlDomTextWriter.cs
- StaticResourceExtension.cs
- ListenDesigner.cs
- DrawingCollection.cs
- HtmlTableRow.cs
- OracleInfoMessageEventArgs.cs
- AttributeSetAction.cs
- ApplicationActivator.cs
- ImageCodecInfo.cs
- ContentHostHelper.cs
- IPHostEntry.cs
- Misc.cs
- OutputCacheSettingsSection.cs
- TriggerAction.cs
- ReadOnlyHierarchicalDataSourceView.cs
- _Connection.cs
- Rectangle.cs
- FrameworkRichTextComposition.cs
- PresentationTraceSources.cs
- BulletedListEventArgs.cs
- DictionaryBase.cs
- XmlCharCheckingWriter.cs
- ObjectCloneHelper.cs
- _FixedSizeReader.cs
- FocusWithinProperty.cs
- _ConnectOverlappedAsyncResult.cs
- NamedPermissionSet.cs
- BadImageFormatException.cs
- RelatedView.cs
- GreenMethods.cs
- FixedSOMTable.cs
- CustomErrorsSectionWrapper.cs
- AutomationAttributeInfo.cs
- CachedPathData.cs
- SecurityTokenRequirement.cs
- DoubleAnimationBase.cs
- SystemWebExtensionsSectionGroup.cs
- DocumentPaginator.cs
- DbLambda.cs
- WindowsEditBox.cs
- DocumentPageHost.cs
- DictionarySectionHandler.cs
- RectangleGeometry.cs
- FilteredSchemaElementLookUpTable.cs
- SortFieldComparer.cs