331 lines
12 KiB
C#
331 lines
12 KiB
C#
|
//------------------------------------------------------------
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
//------------------------------------------------------------
|
||
|
namespace System.ServiceModel
|
||
|
{
|
||
|
using System.ComponentModel;
|
||
|
using System.Configuration;
|
||
|
using System.Runtime;
|
||
|
using System.ServiceModel.Channels;
|
||
|
using System.Xml;
|
||
|
using Config = System.ServiceModel.Configuration;
|
||
|
|
||
|
public class NetMsmqBinding : MsmqBindingBase
|
||
|
{
|
||
|
// private BindingElements
|
||
|
BinaryMessageEncodingBindingElement encoding;
|
||
|
NetMsmqSecurity security;
|
||
|
|
||
|
public NetMsmqBinding()
|
||
|
{
|
||
|
Initialize();
|
||
|
this.security = new NetMsmqSecurity();
|
||
|
}
|
||
|
|
||
|
public NetMsmqBinding(string configurationName)
|
||
|
{
|
||
|
Initialize();
|
||
|
this.security = new NetMsmqSecurity();
|
||
|
ApplyConfiguration(configurationName);
|
||
|
}
|
||
|
|
||
|
public NetMsmqBinding(NetMsmqSecurityMode securityMode)
|
||
|
{
|
||
|
if (!NetMsmqSecurityModeHelper.IsDefined(securityMode))
|
||
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidEnumArgumentException("mode", (int)securityMode, typeof(NetMsmqSecurityMode)));
|
||
|
Initialize();
|
||
|
this.security = new NetMsmqSecurity(securityMode);
|
||
|
}
|
||
|
|
||
|
NetMsmqBinding(NetMsmqSecurity security)
|
||
|
{
|
||
|
Initialize();
|
||
|
Fx.Assert(security != null, "Invalid (null) NetMsmqSecurity value");
|
||
|
this.security = security;
|
||
|
}
|
||
|
|
||
|
[DefaultValue(MsmqDefaults.QueueTransferProtocol)]
|
||
|
public QueueTransferProtocol QueueTransferProtocol
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return (this.transport as MsmqTransportBindingElement).QueueTransferProtocol;
|
||
|
}
|
||
|
set
|
||
|
{
|
||
|
(this.transport as MsmqTransportBindingElement).QueueTransferProtocol = value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public XmlDictionaryReaderQuotas ReaderQuotas
|
||
|
{
|
||
|
get { return encoding.ReaderQuotas; }
|
||
|
set
|
||
|
{
|
||
|
if (value == null)
|
||
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("value");
|
||
|
value.CopyTo(encoding.ReaderQuotas);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public NetMsmqSecurity Security
|
||
|
{
|
||
|
get { return this.security; }
|
||
|
set { this.security = value; }
|
||
|
}
|
||
|
|
||
|
public EnvelopeVersion EnvelopeVersion
|
||
|
{
|
||
|
get { return EnvelopeVersion.Soap12; }
|
||
|
}
|
||
|
|
||
|
[DefaultValue(TransportDefaults.MaxBufferPoolSize)]
|
||
|
public long MaxBufferPoolSize
|
||
|
{
|
||
|
get { return transport.MaxBufferPoolSize; }
|
||
|
set
|
||
|
{
|
||
|
transport.MaxBufferPoolSize = value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal int MaxPoolSize
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return (transport as MsmqTransportBindingElement).MaxPoolSize;
|
||
|
}
|
||
|
set
|
||
|
{
|
||
|
(transport as MsmqTransportBindingElement).MaxPoolSize = value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[DefaultValue(MsmqDefaults.UseActiveDirectory)]
|
||
|
public bool UseActiveDirectory
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return (transport as MsmqTransportBindingElement).UseActiveDirectory;
|
||
|
}
|
||
|
set
|
||
|
{
|
||
|
(transport as MsmqTransportBindingElement).UseActiveDirectory = value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
||
|
public bool ShouldSerializeReaderQuotas()
|
||
|
{
|
||
|
if (this.ReaderQuotas.MaxArrayLength != EncoderDefaults.MaxArrayLength)
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
if (this.ReaderQuotas.MaxBytesPerRead != EncoderDefaults.MaxBytesPerRead)
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
if (this.ReaderQuotas.MaxDepth != EncoderDefaults.MaxDepth)
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
if (this.ReaderQuotas.MaxNameTableCharCount != EncoderDefaults.MaxNameTableCharCount)
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
if (this.ReaderQuotas.MaxStringContentLength != EncoderDefaults.MaxStringContentLength)
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
||
|
public bool ShouldSerializeSecurity()
|
||
|
{
|
||
|
if (this.security.Mode != NetMsmqSecurity.DefaultMode)
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
if (this.security.Transport.MsmqAuthenticationMode != MsmqDefaults.MsmqAuthenticationMode ||
|
||
|
this.security.Transport.MsmqEncryptionAlgorithm != MsmqDefaults.MsmqEncryptionAlgorithm ||
|
||
|
this.security.Transport.MsmqSecureHashAlgorithm != MsmqDefaults.MsmqSecureHashAlgorithm ||
|
||
|
this.security.Transport.MsmqProtectionLevel != MsmqDefaults.MsmqProtectionLevel)
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
if (this.security.Message.AlgorithmSuite != MsmqDefaults.MessageSecurityAlgorithmSuite ||
|
||
|
this.security.Message.ClientCredentialType != MsmqDefaults.DefaultClientCredentialType)
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
void Initialize()
|
||
|
{
|
||
|
transport = new MsmqTransportBindingElement();
|
||
|
encoding = new BinaryMessageEncodingBindingElement();
|
||
|
}
|
||
|
|
||
|
void InitializeFrom(MsmqTransportBindingElement transport, BinaryMessageEncodingBindingElement encoding)
|
||
|
{
|
||
|
// only set properties that have standard binding manifestations: MaxPoolSize *is not* one of them
|
||
|
this.CustomDeadLetterQueue = transport.CustomDeadLetterQueue;
|
||
|
this.DeadLetterQueue = transport.DeadLetterQueue;
|
||
|
this.Durable = transport.Durable;
|
||
|
this.ExactlyOnce = transport.ExactlyOnce;
|
||
|
this.MaxReceivedMessageSize = transport.MaxReceivedMessageSize;
|
||
|
this.ReceiveRetryCount = transport.ReceiveRetryCount;
|
||
|
this.MaxRetryCycles = transport.MaxRetryCycles;
|
||
|
this.ReceiveErrorHandling = transport.ReceiveErrorHandling;
|
||
|
this.RetryCycleDelay = transport.RetryCycleDelay;
|
||
|
this.TimeToLive = transport.TimeToLive;
|
||
|
this.UseSourceJournal = transport.UseSourceJournal;
|
||
|
this.UseMsmqTracing = transport.UseMsmqTracing;
|
||
|
this.ReceiveContextEnabled = transport.ReceiveContextEnabled;
|
||
|
this.QueueTransferProtocol = transport.QueueTransferProtocol;
|
||
|
this.MaxBufferPoolSize = transport.MaxBufferPoolSize;
|
||
|
this.UseActiveDirectory = transport.UseActiveDirectory;
|
||
|
this.ValidityDuration = transport.ValidityDuration;
|
||
|
this.ReaderQuotas = encoding.ReaderQuotas;
|
||
|
}
|
||
|
|
||
|
// check that properties of the HttpTransportBindingElement and
|
||
|
// MessageEncodingBindingElement not exposed as properties on NetMsmqBinding
|
||
|
// match default values of the binding elements
|
||
|
bool IsBindingElementsMatch(MsmqTransportBindingElement transport, MessageEncodingBindingElement encoding)
|
||
|
{
|
||
|
// we do not have to check the transport match here: they always match
|
||
|
if (!this.GetTransport().IsMatch(transport))
|
||
|
return false;
|
||
|
|
||
|
if (!this.encoding.IsMatch(encoding))
|
||
|
return false;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void ApplyConfiguration(string configurationName)
|
||
|
{
|
||
|
Config.NetMsmqBindingCollectionElement section = Config.NetMsmqBindingCollectionElement.GetBindingCollectionElement();
|
||
|
Config.NetMsmqBindingElement element = section.Bindings[configurationName];
|
||
|
if (element == null)
|
||
|
{
|
||
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ConfigurationErrorsException(
|
||
|
SR.GetString(SR.ConfigInvalidBindingConfigurationName,
|
||
|
configurationName,
|
||
|
Config.ConfigurationStrings.NetMsmqBindingCollectionElementName)));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
element.ApplyConfiguration(this);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public override BindingElementCollection CreateBindingElements()
|
||
|
{ // return collection of BindingElements
|
||
|
BindingElementCollection bindingElements = new BindingElementCollection();
|
||
|
// order of BindingElements is important
|
||
|
// add security
|
||
|
SecurityBindingElement wsSecurity = CreateMessageSecurity();
|
||
|
if (wsSecurity != null)
|
||
|
{
|
||
|
bindingElements.Add(wsSecurity);
|
||
|
}
|
||
|
// add encoding (text or mtom)
|
||
|
bindingElements.Add(encoding);
|
||
|
// add transport
|
||
|
bindingElements.Add(GetTransport());
|
||
|
|
||
|
return bindingElements.Clone();
|
||
|
}
|
||
|
|
||
|
internal static bool TryCreate(BindingElementCollection elements, out Binding binding)
|
||
|
{
|
||
|
binding = null;
|
||
|
if (elements.Count > 3)
|
||
|
return false;
|
||
|
|
||
|
SecurityBindingElement security = null;
|
||
|
BinaryMessageEncodingBindingElement encoding = null;
|
||
|
MsmqTransportBindingElement transport = null;
|
||
|
|
||
|
foreach (BindingElement element in elements)
|
||
|
{
|
||
|
if (element is SecurityBindingElement)
|
||
|
security = element as SecurityBindingElement;
|
||
|
else if (element is TransportBindingElement)
|
||
|
transport = element as MsmqTransportBindingElement;
|
||
|
else if (element is MessageEncodingBindingElement)
|
||
|
encoding = element as BinaryMessageEncodingBindingElement;
|
||
|
else
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
UnifiedSecurityMode mode;
|
||
|
if (!IsValidTransport(transport, out mode))
|
||
|
return false;
|
||
|
|
||
|
if (encoding == null)
|
||
|
return false;
|
||
|
|
||
|
NetMsmqSecurity netMsmqSecurity;
|
||
|
if (!TryCreateSecurity(security, mode, out netMsmqSecurity))
|
||
|
return false;
|
||
|
|
||
|
NetMsmqBinding netMsmqBinding = new NetMsmqBinding(netMsmqSecurity);
|
||
|
netMsmqBinding.InitializeFrom(transport, encoding);
|
||
|
if (!netMsmqBinding.IsBindingElementsMatch(transport, encoding))
|
||
|
return false;
|
||
|
|
||
|
binding = netMsmqBinding;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
SecurityBindingElement CreateMessageSecurity()
|
||
|
{
|
||
|
if (this.security.Mode == NetMsmqSecurityMode.Message || this.security.Mode == NetMsmqSecurityMode.Both)
|
||
|
{
|
||
|
return this.security.CreateMessageSecurity();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static bool TryCreateSecurity(SecurityBindingElement sbe, UnifiedSecurityMode mode, out NetMsmqSecurity security)
|
||
|
{
|
||
|
if (sbe != null)
|
||
|
mode &= UnifiedSecurityMode.Message | UnifiedSecurityMode.Both;
|
||
|
else
|
||
|
mode &= ~(UnifiedSecurityMode.Message | UnifiedSecurityMode.Both);
|
||
|
|
||
|
NetMsmqSecurityMode netMsmqSecurityMode = NetMsmqSecurityModeHelper.ToSecurityMode(mode);
|
||
|
Fx.Assert(NetMsmqSecurityModeHelper.IsDefined(netMsmqSecurityMode), string.Format("Invalid NetMsmqSecurityMode value: {0}.", netMsmqSecurityMode.ToString()));
|
||
|
|
||
|
if (NetMsmqSecurity.TryCreate(sbe, netMsmqSecurityMode, out security))
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
MsmqBindingElementBase GetTransport()
|
||
|
{
|
||
|
this.security.ConfigureTransportSecurity(transport);
|
||
|
return transport;
|
||
|
}
|
||
|
|
||
|
static bool IsValidTransport(MsmqTransportBindingElement msmq, out UnifiedSecurityMode mode)
|
||
|
{
|
||
|
mode = (UnifiedSecurityMode)0;
|
||
|
if (msmq == null)
|
||
|
return false;
|
||
|
return NetMsmqSecurity.IsConfiguredTransportSecurity(msmq, out mode);
|
||
|
}
|
||
|
}
|
||
|
}
|