|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.ServiceModel;
using Microsoft.Xml;
using System.ComponentModel;
namespace System.ServiceModel.Channels
{
public sealed class BinaryMessageEncodingBindingElement : MessageEncodingBindingElement
{
private int _maxReadPoolSize;
private int _maxWritePoolSize;
private XmlDictionaryReaderQuotas _readerQuotas;
private int _maxSessionSize;
private BinaryVersion _binaryVersion;
private MessageVersion _messageVersion;
private CompressionFormat _compressionFormat;
private long _maxReceivedMessageSize;
public BinaryMessageEncodingBindingElement()
{
_maxReadPoolSize = EncoderDefaults.MaxReadPoolSize;
_maxWritePoolSize = EncoderDefaults.MaxWritePoolSize;
_readerQuotas = new XmlDictionaryReaderQuotas();
EncoderDefaults.ReaderQuotas.CopyTo(_readerQuotas);
_maxSessionSize = BinaryEncoderDefaults.MaxSessionSize;
_binaryVersion = BinaryEncoderDefaults.BinaryVersion;
_messageVersion = MessageVersion.CreateVersion(BinaryEncoderDefaults.EnvelopeVersion);
_compressionFormat = EncoderDefaults.DefaultCompressionFormat;
}
private BinaryMessageEncodingBindingElement(BinaryMessageEncodingBindingElement elementToBeCloned)
: base(elementToBeCloned)
{
_maxReadPoolSize = elementToBeCloned._maxReadPoolSize;
_maxWritePoolSize = elementToBeCloned._maxWritePoolSize;
_readerQuotas = new XmlDictionaryReaderQuotas();
elementToBeCloned._readerQuotas.CopyTo(_readerQuotas);
this.MaxSessionSize = elementToBeCloned.MaxSessionSize;
this.BinaryVersion = elementToBeCloned.BinaryVersion;
_messageVersion = elementToBeCloned._messageVersion;
this.CompressionFormat = elementToBeCloned.CompressionFormat;
_maxReceivedMessageSize = elementToBeCloned._maxReceivedMessageSize;
}
[DefaultValue(EncoderDefaults.DefaultCompressionFormat)]
public CompressionFormat CompressionFormat
{
get
{
return _compressionFormat;
}
set
{
_compressionFormat = value;
}
}
/* public */
private BinaryVersion BinaryVersion
{
get
{
return _binaryVersion;
}
set
{
if (value == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("value"));
}
_binaryVersion = value;
}
}
public override MessageVersion MessageVersion
{
get { return _messageVersion; }
set
{
if (value == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("value");
}
if (value.Envelope != BinaryEncoderDefaults.EnvelopeVersion)
{
string errorMsg = string.Format(SRServiceModel.UnsupportedEnvelopeVersion, this.GetType().FullName, BinaryEncoderDefaults.EnvelopeVersion, value.Envelope);
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(errorMsg));
}
_messageVersion = MessageVersion.CreateVersion(BinaryEncoderDefaults.EnvelopeVersion, value.Addressing);
}
}
[DefaultValue(EncoderDefaults.MaxReadPoolSize)]
public int MaxReadPoolSize
{
get
{
return _maxReadPoolSize;
}
set
{
if (value <= 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", value,
SRServiceModel.ValueMustBePositive));
}
_maxReadPoolSize = value;
}
}
[DefaultValue(EncoderDefaults.MaxWritePoolSize)]
public int MaxWritePoolSize
{
get
{
return _maxWritePoolSize;
}
set
{
if (value <= 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", value,
SRServiceModel.ValueMustBePositive));
}
_maxWritePoolSize = value;
}
}
public XmlDictionaryReaderQuotas ReaderQuotas
{
get
{
return _readerQuotas;
}
set
{
if (value == null)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("value");
value.CopyTo(_readerQuotas);
}
}
[DefaultValue(BinaryEncoderDefaults.MaxSessionSize)]
public int MaxSessionSize
{
get
{
return _maxSessionSize;
}
set
{
if (value < 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", value,
SRServiceModel.ValueMustBeNonNegative));
}
_maxSessionSize = value;
}
}
private void VerifyCompression(BindingContext context)
{
if (_compressionFormat != CompressionFormat.None)
{
ITransportCompressionSupport compressionSupport = context.GetInnerProperty<ITransportCompressionSupport>();
if (compressionSupport == null || !compressionSupport.IsCompressionFormatSupported(_compressionFormat))
{
throw FxTrace.Exception.AsError(new NotSupportedException(string.Format(
SRServiceModel.TransportDoesNotSupportCompression,
_compressionFormat.ToString(),
this.GetType().Name,
CompressionFormat.None.ToString())));
}
}
}
private void SetMaxReceivedMessageSizeFromTransport(BindingContext context)
{
TransportBindingElement transport = context.Binding.Elements.Find<TransportBindingElement>();
if (transport != null)
{
// We are guaranteed that a transport exists when building a binding;
// Allow the regular flow/checks to happen rather than throw here
// (InternalBuildChannelListener will call into the BindingContext. Validation happens there and it will throw)
_maxReceivedMessageSize = transport.MaxReceivedMessageSize;
}
}
public override IChannelFactory<TChannel> BuildChannelFactory<TChannel>(BindingContext context)
{
VerifyCompression(context);
SetMaxReceivedMessageSizeFromTransport(context);
return InternalBuildChannelFactory<TChannel>(context);
}
public override BindingElement Clone()
{
return new BinaryMessageEncodingBindingElement(this);
}
public override MessageEncoderFactory CreateMessageEncoderFactory()
{
return new BinaryMessageEncoderFactory(
this.MessageVersion,
this.MaxReadPoolSize,
this.MaxWritePoolSize,
this.MaxSessionSize,
this.ReaderQuotas,
_maxReceivedMessageSize,
this.BinaryVersion,
this.CompressionFormat);
}
public override T GetProperty<T>(BindingContext context)
{
if (context == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("context");
}
if (typeof(T) == typeof(XmlDictionaryReaderQuotas))
{
return (T)(object)_readerQuotas;
}
else
{
return base.GetProperty<T>(context);
}
}
internal override bool IsMatch(BindingElement b)
{
if (!base.IsMatch(b))
return false;
BinaryMessageEncodingBindingElement binary = b as BinaryMessageEncodingBindingElement;
if (binary == null)
return false;
if (_maxReadPoolSize != binary.MaxReadPoolSize)
return false;
if (_maxWritePoolSize != binary.MaxWritePoolSize)
return false;
// compare XmlDictionaryReaderQuotas
if (_readerQuotas.MaxStringContentLength != binary.ReaderQuotas.MaxStringContentLength)
return false;
if (_readerQuotas.MaxArrayLength != binary.ReaderQuotas.MaxArrayLength)
return false;
if (_readerQuotas.MaxBytesPerRead != binary.ReaderQuotas.MaxBytesPerRead)
return false;
if (_readerQuotas.MaxDepth != binary.ReaderQuotas.MaxDepth)
return false;
if (_readerQuotas.MaxNameTableCharCount != binary.ReaderQuotas.MaxNameTableCharCount)
return false;
if (this.MaxSessionSize != binary.MaxSessionSize)
return false;
if (this.CompressionFormat != binary.CompressionFormat)
return false;
return true;
}
[EditorBrowsable(EditorBrowsableState.Never)]
public bool ShouldSerializeReaderQuotas()
{
return (!EncoderDefaults.IsDefaultReaderQuotas(this.ReaderQuotas));
}
[EditorBrowsable(EditorBrowsableState.Never)]
public bool ShouldSerializeMessageVersion()
{
return (!_messageVersion.IsMatch(MessageVersion.Default));
}
}
}
|