| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494 |
- //------------------------------------------------------------
- // 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.ServiceModel.Configuration;
- using System.Xml;
- public class NetTcpBinding : Binding, IBindingRuntimePreferences
- {
- OptionalReliableSession reliableSession;
- // private BindingElements
- TcpTransportBindingElement transport;
- BinaryMessageEncodingBindingElement encoding;
- TransactionFlowBindingElement context;
- ReliableSessionBindingElement session;
- NetTcpSecurity security = new NetTcpSecurity();
- public NetTcpBinding() { Initialize(); }
- public NetTcpBinding(SecurityMode securityMode)
- : this()
- {
- this.security.Mode = securityMode;
- }
- public NetTcpBinding(SecurityMode securityMode, bool reliableSessionEnabled)
- : this(securityMode)
- {
- this.ReliableSession.Enabled = reliableSessionEnabled;
- }
- public NetTcpBinding(string configurationName)
- : this()
- {
- ApplyConfiguration(configurationName);
- }
- NetTcpBinding(TcpTransportBindingElement transport, BinaryMessageEncodingBindingElement encoding, TransactionFlowBindingElement context, ReliableSessionBindingElement session, NetTcpSecurity security)
- : this()
- {
- this.security = security;
- this.ReliableSession.Enabled = session != null;
- InitializeFrom(transport, encoding, context, session);
- }
- [DefaultValue(NetTcpDefaults.TransactionsEnabled)]
- public bool TransactionFlow
- {
- get { return context.Transactions; }
- set { context.Transactions = value; }
- }
- public TransactionProtocol TransactionProtocol
- {
- get { return this.context.TransactionProtocol; }
- set { this.context.TransactionProtocol = value; }
- }
- [DefaultValue(ConnectionOrientedTransportDefaults.TransferMode)]
- public TransferMode TransferMode
- {
- get { return this.transport.TransferMode; }
- set { this.transport.TransferMode = value; }
- }
- [DefaultValue(ConnectionOrientedTransportDefaults.HostNameComparisonMode)]
- public HostNameComparisonMode HostNameComparisonMode
- {
- get { return transport.HostNameComparisonMode; }
- set { transport.HostNameComparisonMode = value; }
- }
- [DefaultValue(TransportDefaults.MaxBufferPoolSize)]
- public long MaxBufferPoolSize
- {
- get { return transport.MaxBufferPoolSize; }
- set
- {
- transport.MaxBufferPoolSize = value;
- }
- }
- [DefaultValue(TransportDefaults.MaxBufferSize)]
- public int MaxBufferSize
- {
- get { return transport.MaxBufferSize; }
- set { transport.MaxBufferSize = value; }
- }
- public int MaxConnections
- {
- get { return transport.MaxPendingConnections; }
- set
- {
- transport.MaxPendingConnections = value;
- transport.ConnectionPoolSettings.MaxOutboundConnectionsPerEndpoint = value;
- }
- }
- internal bool IsMaxConnectionsSet
- {
- get { return transport.IsMaxPendingConnectionsSet; }
- }
- public int ListenBacklog
- {
- get { return transport.ListenBacklog; }
- set { transport.ListenBacklog = value; }
- }
- internal bool IsListenBacklogSet
- {
- get { return transport.IsListenBacklogSet; }
- }
- [DefaultValue(TransportDefaults.MaxReceivedMessageSize)]
- public long MaxReceivedMessageSize
- {
- get { return transport.MaxReceivedMessageSize; }
- set { transport.MaxReceivedMessageSize = value; }
- }
- [DefaultValue(TcpTransportDefaults.PortSharingEnabled)]
- public bool PortSharingEnabled
- {
- get { return transport.PortSharingEnabled; }
- set { transport.PortSharingEnabled = value; }
- }
- public XmlDictionaryReaderQuotas ReaderQuotas
- {
- get { return encoding.ReaderQuotas; }
- set
- {
- if (value == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("value");
- value.CopyTo(encoding.ReaderQuotas);
- }
- }
- bool IBindingRuntimePreferences.ReceiveSynchronously
- {
- get { return false; }
- }
- public OptionalReliableSession 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 transport.Scheme; } }
- public EnvelopeVersion EnvelopeVersion
- {
- get { return EnvelopeVersion.Soap12; }
- }
- public NetTcpSecurity Security
- {
- get { return security; }
- set
- {
- if (value == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("value");
- security = value;
- }
- }
- static TransactionFlowBindingElement GetDefaultTransactionFlowBindingElement()
- {
- return new TransactionFlowBindingElement(NetTcpDefaults.TransactionsEnabled);
- }
- void Initialize()
- {
- transport = new TcpTransportBindingElement();
- encoding = new BinaryMessageEncodingBindingElement();
- context = GetDefaultTransactionFlowBindingElement();
- session = new ReliableSessionBindingElement();
- this.reliableSession = new OptionalReliableSession(session);
- }
- void InitializeFrom(TcpTransportBindingElement transport, BinaryMessageEncodingBindingElement encoding, TransactionFlowBindingElement context, ReliableSessionBindingElement session)
- {
- Fx.Assert(transport != null, "Invalid (null) transport value.");
- Fx.Assert(encoding != null, "Invalid (null) encoding value.");
- Fx.Assert(context != null, "Invalid (null) context value.");
- Fx.Assert(security != null, "Invalid (null) security value.");
- // transport
- this.HostNameComparisonMode = transport.HostNameComparisonMode;
- this.MaxBufferPoolSize = transport.MaxBufferPoolSize;
- this.MaxBufferSize = transport.MaxBufferSize;
- if (transport.IsMaxPendingConnectionsSet)
- {
- this.MaxConnections = transport.MaxPendingConnections;
- }
- if (transport.IsListenBacklogSet)
- {
- this.ListenBacklog = transport.ListenBacklog;
- }
- this.MaxReceivedMessageSize = transport.MaxReceivedMessageSize;
- this.PortSharingEnabled = transport.PortSharingEnabled;
- this.TransferMode = transport.TransferMode;
- // encoding
- this.ReaderQuotas = encoding.ReaderQuotas;
- // context
- this.TransactionFlow = context.Transactions;
- this.TransactionProtocol = context.TransactionProtocol;
- //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 BasicHttpBinding
- // match default values of the binding elements
- bool IsBindingElementsMatch(TcpTransportBindingElement transport, BinaryMessageEncodingBindingElement encoding, TransactionFlowBindingElement context, ReliableSessionBindingElement session)
- {
- if (!this.transport.IsMatch(transport))
- return false;
- if (!this.encoding.IsMatch(encoding))
- return false;
- if (!this.context.IsMatch(context))
- return false;
- if (reliableSession.Enabled)
- {
- if (!this.session.IsMatch(session))
- return false;
- }
- else if (session != null)
- return false;
- return true;
- }
- void ApplyConfiguration(string configurationName)
- {
- NetTcpBindingCollectionElement section = NetTcpBindingCollectionElement.GetBindingCollectionElement();
- NetTcpBindingElement element = section.Bindings[configurationName];
- if (element == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ConfigurationErrorsException(
- SR.GetString(SR.ConfigInvalidBindingConfigurationName,
- configurationName,
- ConfigurationStrings.NetTcpBindingCollectionElementName)));
- }
- else
- {
- element.ApplyConfiguration(this);
- }
- }
- // In the Win8 profile, some settings for the binding security are not supported.
- void CheckSettings()
- {
- if (!UnsafeNativeMethods.IsTailoredApplication.Value)
- {
- return;
- }
- NetTcpSecurity security = this.Security;
- if (security == null)
- {
- return;
- }
- SecurityMode mode = security.Mode;
- if (mode == SecurityMode.None)
- {
- return;
- }
- else if (mode == SecurityMode.Message)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.UnsupportedSecuritySetting, "Mode", mode)));
- }
- // Message.ClientCredentialType = Certificate, IssuedToken or Windows are not supported.
- if (mode == SecurityMode.TransportWithMessageCredential)
- {
- MessageSecurityOverTcp message = security.Message;
- if (message != null)
- {
- MessageCredentialType mct = message.ClientCredentialType;
- if ((mct == MessageCredentialType.Certificate) || (mct == MessageCredentialType.IssuedToken) || (mct == MessageCredentialType.Windows))
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.UnsupportedSecuritySetting, "Message.ClientCredentialType", mct)));
- }
- }
- }
- // Transport.ClientCredentialType = Certificate is not supported.
- Fx.Assert((mode == SecurityMode.Transport) || (mode == SecurityMode.TransportWithMessageCredential), "Unexpected SecurityMode value: " + mode);
- TcpTransportSecurity transport = security.Transport;
- if ((transport != null) && (transport.ClientCredentialType == TcpClientCredentialType.Certificate))
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.UnsupportedSecuritySetting, "Transport.ClientCredentialType", transport.ClientCredentialType)));
- }
- }
- public override BindingElementCollection CreateBindingElements()
- {
- this.CheckSettings();
-
- // return collection of BindingElements
- BindingElementCollection bindingElements = new BindingElementCollection();
- // order of BindingElements is important
- // add context
- bindingElements.Add(context);
- // add session
- if (reliableSession.Enabled)
- bindingElements.Add(session);
- // add security (*optional)
- SecurityBindingElement wsSecurity = CreateMessageSecurity();
- if (wsSecurity != null)
- bindingElements.Add(wsSecurity);
- // add encoding
- bindingElements.Add(encoding);
- // add transport security
- BindingElement transportSecurity = CreateTransportSecurity();
- if (transportSecurity != null)
- {
- bindingElements.Add(transportSecurity);
- }
- transport.ExtendedProtectionPolicy = security.Transport.ExtendedProtectionPolicy;
- // add transport (tcp)
- bindingElements.Add(transport);
- return bindingElements.Clone();
- }
- internal static bool TryCreate(BindingElementCollection elements, out Binding binding)
- {
- binding = null;
- if (elements.Count > 6)
- return false;
- // collect all binding elements
- TcpTransportBindingElement transport = null;
- BinaryMessageEncodingBindingElement encoding = null;
- TransactionFlowBindingElement context = null;
- ReliableSessionBindingElement session = null;
- SecurityBindingElement wsSecurity = null;
- BindingElement transportSecurity = null;
- foreach (BindingElement element in elements)
- {
- if (element is SecurityBindingElement)
- wsSecurity = element as SecurityBindingElement;
- else if (element is TransportBindingElement)
- transport = element as TcpTransportBindingElement;
- else if (element is MessageEncodingBindingElement)
- encoding = element as BinaryMessageEncodingBindingElement;
- else if (element is TransactionFlowBindingElement)
- context = element as TransactionFlowBindingElement;
- else if (element is ReliableSessionBindingElement)
- session = element as ReliableSessionBindingElement;
- else
- {
- if (transportSecurity != null)
- return false;
- transportSecurity = element;
- }
- }
- if (transport == null)
- return false;
- if (encoding == null)
- return false;
- if (context == null)
- context = GetDefaultTransactionFlowBindingElement();
- TcpTransportSecurity tcpTransportSecurity = new TcpTransportSecurity();
- UnifiedSecurityMode mode = GetModeFromTransportSecurity(transportSecurity);
- NetTcpSecurity security;
- if (!TryCreateSecurity(wsSecurity, mode, session != null, transportSecurity, tcpTransportSecurity, out security))
- return false;
- if (!SetTransportSecurity(transportSecurity, security.Mode, tcpTransportSecurity))
- return false;
- NetTcpBinding netTcpBinding = new NetTcpBinding(transport, encoding, context, session, security);
- if (!netTcpBinding.IsBindingElementsMatch(transport, encoding, context, session))
- return false;
- binding = netTcpBinding;
- return true;
- }
- BindingElement CreateTransportSecurity()
- {
- return this.security.CreateTransportSecurity();
- }
- static UnifiedSecurityMode GetModeFromTransportSecurity(BindingElement transport)
- {
- return NetTcpSecurity.GetModeFromTransportSecurity(transport);
- }
- static bool SetTransportSecurity(BindingElement transport, SecurityMode mode, TcpTransportSecurity transportSecurity)
- {
- return NetTcpSecurity.SetTransportSecurity(transport, mode, transportSecurity);
- }
- SecurityBindingElement CreateMessageSecurity()
- {
- if (this.security.Mode == SecurityMode.Message || this.security.Mode == SecurityMode.TransportWithMessageCredential)
- {
- return this.security.CreateMessageSecurity(this.ReliableSession.Enabled);
- }
- else
- {
- return null;
- }
- }
- static bool TryCreateSecurity(SecurityBindingElement sbe, UnifiedSecurityMode mode, bool isReliableSession, BindingElement transportSecurity, TcpTransportSecurity tcpTransportSecurity, out NetTcpSecurity security)
- {
- if (sbe != null)
- mode &= UnifiedSecurityMode.Message | UnifiedSecurityMode.TransportWithMessageCredential;
- else
- mode &= ~(UnifiedSecurityMode.Message | UnifiedSecurityMode.TransportWithMessageCredential);
- SecurityMode securityMode = SecurityModeHelper.ToSecurityMode(mode);
- Fx.Assert(SecurityModeHelper.IsDefined(securityMode), string.Format("Invalid SecurityMode value: {0}.", securityMode.ToString()));
- if (NetTcpSecurity.TryCreate(sbe, securityMode, isReliableSession, transportSecurity, tcpTransportSecurity, out security))
- return true;
- return false;
- }
- [EditorBrowsable(EditorBrowsableState.Never)]
- public bool ShouldSerializeReaderQuotas()
- {
- return (!EncoderDefaults.IsDefaultReaderQuotas(this.ReaderQuotas));
- }
- [EditorBrowsable(EditorBrowsableState.Never)]
- public bool ShouldSerializeSecurity()
- {
- return this.security.InternalShouldSerialize();
- }
- [EditorBrowsable(EditorBrowsableState.Never)]
- public bool ShouldSerializeTransactionProtocol()
- {
- return (TransactionProtocol != NetTcpDefaults.TransactionProtocol);
- }
- [EditorBrowsable(EditorBrowsableState.Never)]
- public bool ShouldSerializeReliableSession()
- {
- return (this.ReliableSession.Ordered != ReliableSessionDefaults.Ordered
- || this.ReliableSession.InactivityTimeout != ReliableSessionDefaults.InactivityTimeout
- || this.ReliableSession.Enabled != ReliableSessionDefaults.Enabled);
- }
- [EditorBrowsable(EditorBrowsableState.Never)]
- public bool ShouldSerializeListenBacklog()
- {
- return transport.ShouldSerializeListenBacklog();
- }
- [EditorBrowsable(EditorBrowsableState.Never)]
- public bool ShouldSerializeMaxConnections()
- {
- return transport.ShouldSerializeListenBacklog();
- }
- }
- }
|