|
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------
namespace System.ServiceModel
{
using System;
using System.Text;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Configuration;
using System.Globalization;
using System.Net;
using System.Net.Security;
using System.Runtime.Serialization;
using System.Security.Principal;
using System.ServiceModel.Channels;
using System.ServiceModel.Configuration;
using System.ServiceModel.Security;
using System.Xml;
using System.ComponentModel;
public class WSDualHttpBinding : Binding, IBindingRuntimePreferences
{
WSMessageEncoding messageEncoding;
ReliableSession reliableSession;
// private BindingElements
HttpTransportBindingElement httpTransport;
TextMessageEncodingBindingElement textEncoding;
MtomMessageEncodingBindingElement mtomEncoding;
TransactionFlowBindingElement txFlow;
ReliableSessionBindingElement session;
CompositeDuplexBindingElement compositeDuplex;
OneWayBindingElement oneWay;
WSDualHttpSecurity security = new WSDualHttpSecurity();
public WSDualHttpBinding(string configName)
: this()
{
ApplyConfiguration(configName);
}
public WSDualHttpBinding(WSDualHttpSecurityMode securityMode)
: this()
{
this.security.Mode = securityMode;
}
public WSDualHttpBinding()
{
Initialize();
}
WSDualHttpBinding(
HttpTransportBindingElement transport,
MessageEncodingBindingElement encoding,
TransactionFlowBindingElement txFlow,
ReliableSessionBindingElement session,
CompositeDuplexBindingElement compositeDuplex,
OneWayBindingElement oneWay,
WSDualHttpSecurity security)
: this()
{
this.security = security;
InitializeFrom(transport, encoding, txFlow, session, compositeDuplex, oneWay);
}
[DefaultValue(HttpTransportDefaults.BypassProxyOnLocal)]
public bool BypassProxyOnLocal
{
get { return httpTransport.BypassProxyOnLocal; }
set { httpTransport.BypassProxyOnLocal = value; }
}
[DefaultValue(null)]
public Uri ClientBaseAddress
{
get { return this.compositeDuplex.ClientBaseAddress; }
set { this.compositeDuplex.ClientBaseAddress = value; }
}
[DefaultValue(false)]
public bool TransactionFlow
{
get { return this.txFlow.Transactions; }
set { this.txFlow.Transactions = value; }
}
[DefaultValue(HttpTransportDefaults.HostNameComparisonMode)]
public HostNameComparisonMode HostNameComparisonMode
{
get { return httpTransport.HostNameComparisonMode; }
set { httpTransport.HostNameComparisonMode = value; }
}
[DefaultValue(TransportDefaults.MaxBufferPoolSize)]
public long MaxBufferPoolSize
{
get { return httpTransport.MaxBufferPoolSize; }
set
{
httpTransport.MaxBufferPoolSize = value;
}
}
[DefaultValue(TransportDefaults.MaxReceivedMessageSize)]
public long MaxReceivedMessageSize
{
get { return httpTransport.MaxReceivedMessageSize; }
set
{
if (value > int.MaxValue)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
new ArgumentOutOfRangeException("value.MaxReceivedMessageSize",
SR.GetString(SR.MaxReceivedMessageSizeMustBeInIntegerRange)));
}
httpTransport.MaxReceivedMessageSize = value;
mtomEncoding.MaxBufferSize = (int)value;
}
}
[DefaultValue(WSMessageEncoding.Text)]
public WSMessageEncoding MessageEncoding
{
get { return messageEncoding; }
set { messageEncoding = value; }
}
[DefaultValue(HttpTransportDefaults.ProxyAddress)]
public Uri ProxyAddress
{
get { return httpTransport.ProxyAddress; }
set { httpTransport.ProxyAddress = value; }
}
public XmlDictionaryReaderQuotas ReaderQuotas
{
get { return textEncoding.ReaderQuotas; }
set
{
if (value == null)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("value");
value.CopyTo(textEncoding.ReaderQuotas);
value.CopyTo(mtomEncoding.ReaderQuotas);
}
}
public ReliableSession ReliableSession
{
get
{
return reliableSession;
}
set
{
if (value == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("value"));
}
this.reliableSession.CopySettings(value);
}
}
public override string Scheme { get { return httpTransport.Scheme; } }
public EnvelopeVersion EnvelopeVersion
{
get { return EnvelopeVersion.Soap12; }
}
[TypeConverter(typeof(EncodingConverter))]
public System.Text.Encoding TextEncoding
{
get { return textEncoding.WriteEncoding; }
set
{
textEncoding.WriteEncoding = value;
mtomEncoding.WriteEncoding = value;
}
}
[DefaultValue(HttpTransportDefaults.UseDefaultWebProxy)]
public bool UseDefaultWebProxy
{
get { return httpTransport.UseDefaultWebProxy; }
set { httpTransport.UseDefaultWebProxy = value; }
}
public WSDualHttpSecurity Security
{
get { return this.security; }
set
{
if (value == null)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("value");
this.security = value;
}
}
bool IBindingRuntimePreferences.ReceiveSynchronously
{
get { return false; }
}
static TransactionFlowBindingElement GetDefaultTransactionFlowBindingElement()
{
TransactionFlowBindingElement tfbe = new TransactionFlowBindingElement(false);
tfbe.TransactionProtocol = TransactionProtocol.WSAtomicTransactionOctober2004;
return tfbe;
}
void Initialize()
{
this.httpTransport = new HttpTransportBindingElement();
this.messageEncoding = WSDualHttpBindingDefaults.MessageEncoding;
this.txFlow = GetDefaultTransactionFlowBindingElement();
this.session = new ReliableSessionBindingElement(true);
this.textEncoding = new TextMessageEncodingBindingElement();
this.textEncoding.MessageVersion = MessageVersion.Soap12WSAddressing10;
this.mtomEncoding = new MtomMessageEncodingBindingElement();
this.mtomEncoding.MessageVersion = MessageVersion.Soap12WSAddressing10;
this.compositeDuplex = new CompositeDuplexBindingElement();
this.reliableSession = new ReliableSession(session);
this.oneWay = new OneWayBindingElement();
}
void InitializeFrom(
HttpTransportBindingElement transport,
MessageEncodingBindingElement encoding,
TransactionFlowBindingElement txFlow,
ReliableSessionBindingElement session,
CompositeDuplexBindingElement compositeDuplex,
OneWayBindingElement oneWay)
{
// transport
this.BypassProxyOnLocal = transport.BypassProxyOnLocal;
this.HostNameComparisonMode = transport.HostNameComparisonMode;
this.MaxBufferPoolSize = transport.MaxBufferPoolSize;
this.MaxReceivedMessageSize = transport.MaxReceivedMessageSize;
this.ProxyAddress = transport.ProxyAddress;
this.UseDefaultWebProxy = transport.UseDefaultWebProxy;
// this binding only supports Text and Mtom encoding
if (encoding is TextMessageEncodingBindingElement)
{
this.MessageEncoding = WSMessageEncoding.Text;
TextMessageEncodingBindingElement text = (TextMessageEncodingBindingElement)encoding;
this.TextEncoding = text.WriteEncoding;
this.ReaderQuotas = text.ReaderQuotas;
}
else if (encoding is MtomMessageEncodingBindingElement)
{
messageEncoding = WSMessageEncoding.Mtom;
MtomMessageEncodingBindingElement mtom = (MtomMessageEncodingBindingElement)encoding;
this.TextEncoding = mtom.WriteEncoding;
this.ReaderQuotas = mtom.ReaderQuotas;
}
this.TransactionFlow = txFlow.Transactions;
this.ClientBaseAddress = compositeDuplex.ClientBaseAddress;
//session
if (session != null)
{
// only set properties that have standard binding manifestations
this.session.InactivityTimeout = session.InactivityTimeout;
this.session.Ordered = session.Ordered;
}
}
// check that properties of the HttpTransportBindingElement and
// MessageEncodingBindingElement not exposed as properties on WsHttpBinding
// match default values of the binding elements
bool IsBindingElementsMatch(HttpTransportBindingElement transport,
MessageEncodingBindingElement encoding,
TransactionFlowBindingElement txFlow,
ReliableSessionBindingElement session,
CompositeDuplexBindingElement compositeDuplex,
OneWayBindingElement oneWay)
{
if (!this.httpTransport.IsMatch(transport))
return false;
if (this.MessageEncoding == WSMessageEncoding.Text)
{
if (!this.textEncoding.IsMatch(encoding))
return false;
}
else if (this.MessageEncoding == WSMessageEncoding.Mtom)
{
if (!this.mtomEncoding.IsMatch(encoding))
return false;
}
if (!this.txFlow.IsMatch(txFlow))
return false;
if (!this.session.IsMatch(session))
return false;
if (!this.compositeDuplex.IsMatch(compositeDuplex))
return false;
if (!this.oneWay.IsMatch(oneWay))
{
return false;
}
return true;
}
void ApplyConfiguration(string configurationName)
{
WSDualHttpBindingCollectionElement section = WSDualHttpBindingCollectionElement.GetBindingCollectionElement();
WSDualHttpBindingElement element = section.Bindings[configurationName];
if (element == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ConfigurationErrorsException(
SR.GetString(SR.ConfigInvalidBindingConfigurationName,
configurationName,
ConfigurationStrings.WSDualHttpBindingCollectionElementName)));
}
else
{
element.ApplyConfiguration(this);
}
}
SecurityBindingElement CreateMessageSecurity()
{
return this.Security.CreateMessageSecurity();
}
static bool TryCreateSecurity(SecurityBindingElement securityElement, out WSDualHttpSecurity security)
{
return WSDualHttpSecurity.TryCreate(securityElement, out security);
}
public override BindingElementCollection CreateBindingElements()
{ // return collection of BindingElements
BindingElementCollection bindingElements = new BindingElementCollection();
// order of BindingElements is important
// add context
bindingElements.Add(txFlow);
// add session
bindingElements.Add(session);
// add security (optional)
SecurityBindingElement wsSecurity = CreateMessageSecurity();
if (wsSecurity != null)
{
bindingElements.Add(wsSecurity);
}
// add duplex
bindingElements.Add(compositeDuplex);
// add oneWay adapter
bindingElements.Add(oneWay);
// add encoding (text or mtom)
WSMessageEncodingHelper.SyncUpEncodingBindingElementProperties(textEncoding, mtomEncoding);
if (this.MessageEncoding == WSMessageEncoding.Text)
{
bindingElements.Add(textEncoding);
}
else if (this.MessageEncoding == WSMessageEncoding.Mtom)
{
bindingElements.Add(mtomEncoding);
}
// add transport
bindingElements.Add(httpTransport);
return bindingElements.Clone();
}
internal static bool TryCreate(BindingElementCollection elements, out Binding binding)
{
binding = null;
if (elements.Count > 7)
{
return false;
}
SecurityBindingElement sbe = null;
HttpTransportBindingElement transport = null;
MessageEncodingBindingElement encoding = null;
TransactionFlowBindingElement txFlow = null;
ReliableSessionBindingElement session = null;
CompositeDuplexBindingElement compositeDuplex = null;
OneWayBindingElement oneWay = null;
foreach (BindingElement element in elements)
{
if (element is SecurityBindingElement)
{
sbe = element as SecurityBindingElement;
}
else if (element is TransportBindingElement)
{
transport = element as HttpTransportBindingElement;
}
else if (element is MessageEncodingBindingElement)
{
encoding = element as MessageEncodingBindingElement;
}
else if (element is TransactionFlowBindingElement)
{
txFlow = element as TransactionFlowBindingElement;
}
else if (element is ReliableSessionBindingElement)
{
session = element as ReliableSessionBindingElement;
}
else if (element is CompositeDuplexBindingElement)
{
compositeDuplex = element as CompositeDuplexBindingElement;
}
else if (element is OneWayBindingElement)
{
oneWay = element as OneWayBindingElement;
}
else
{
return false;
}
}
if (transport == null)
{
return false;
}
if (encoding == null)
{
return false;
}
// this binding only supports Soap12
if (!encoding.CheckEncodingVersion(EnvelopeVersion.Soap12))
{
return false;
}
if (compositeDuplex == null)
{
return false;
}
if (oneWay == null)
{
return false;
}
if (session == null)
{
return false;
}
if (txFlow == null)
{
txFlow = GetDefaultTransactionFlowBindingElement();
}
WSDualHttpSecurity security;
if (!TryCreateSecurity(sbe, out security))
return false;
WSDualHttpBinding wSDualHttpBinding =
new WSDualHttpBinding(transport, encoding, txFlow, session, compositeDuplex, oneWay, security);
if (!wSDualHttpBinding.IsBindingElementsMatch(transport, encoding, txFlow, session, compositeDuplex, oneWay))
{
return false;
}
binding = wSDualHttpBinding;
return true;
}
[EditorBrowsable(EditorBrowsableState.Never)]
public bool ShouldSerializeReaderQuotas()
{
return (!EncoderDefaults.IsDefaultReaderQuotas(this.ReaderQuotas));
}
[EditorBrowsable(EditorBrowsableState.Never)]
public bool ShouldSerializeTextEncoding()
{
return (!this.TextEncoding.Equals(TextEncoderDefaults.Encoding));
}
[EditorBrowsable(EditorBrowsableState.Never)]
public bool ShouldSerializeReliableSession()
{
return this.ReliableSession.Ordered != ReliableSessionDefaults.Ordered
|| this.ReliableSession.InactivityTimeout != ReliableSessionDefaults.InactivityTimeout;
}
[EditorBrowsable(EditorBrowsableState.Never)]
public bool ShouldSerializeSecurity()
{
return this.Security.InternalShouldSerialize();
}
}
}
|