//------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //------------------------------------------------------------ namespace System.ServiceModel.Channels { using System.ServiceModel.Activation; using System.Collections.Generic; using System.Net; using System.Net.Security; using System.Net.Sockets; using System.Runtime.Serialization; using System.Security.Authentication.ExtendedProtection; using System.Xml; using System.ComponentModel; public class TcpTransportBindingElement : ConnectionOrientedTransportBindingElement { int listenBacklog; bool portSharingEnabled; bool teredoEnabled; TcpConnectionPoolSettings connectionPoolSettings; ExtendedProtectionPolicy extendedProtectionPolicy; bool isListenBacklogSet; public TcpTransportBindingElement() : base() { this.listenBacklog = TcpTransportDefaults.GetListenBacklog(); this.portSharingEnabled = TcpTransportDefaults.PortSharingEnabled; this.teredoEnabled = TcpTransportDefaults.TeredoEnabled; this.connectionPoolSettings = new TcpConnectionPoolSettings(); this.extendedProtectionPolicy = ChannelBindingUtility.DefaultPolicy; } protected TcpTransportBindingElement(TcpTransportBindingElement elementToBeCloned) : base(elementToBeCloned) { this.listenBacklog = elementToBeCloned.listenBacklog; this.isListenBacklogSet = elementToBeCloned.isListenBacklogSet; this.portSharingEnabled = elementToBeCloned.portSharingEnabled; this.teredoEnabled = elementToBeCloned.teredoEnabled; this.connectionPoolSettings = elementToBeCloned.connectionPoolSettings.Clone(); this.extendedProtectionPolicy = elementToBeCloned.ExtendedProtectionPolicy; } public TcpConnectionPoolSettings ConnectionPoolSettings { get { return this.connectionPoolSettings; } } public int ListenBacklog { get { return this.listenBacklog; } set { if (value <= 0) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", SR.GetString(SR.ValueMustBePositive))); } this.listenBacklog = value; this.isListenBacklogSet = true; } } internal bool IsListenBacklogSet { get { return this.isListenBacklogSet; } } // server [DefaultValue(TcpTransportDefaults.PortSharingEnabled)] public bool PortSharingEnabled { get { return this.portSharingEnabled; } set { this.portSharingEnabled = value; } } public override string Scheme { get { return "net.tcp"; } } // server [DefaultValue(TcpTransportDefaults.TeredoEnabled)] public bool TeredoEnabled { get { return this.teredoEnabled; } set { this.teredoEnabled = value; } } public ExtendedProtectionPolicy ExtendedProtectionPolicy { get { return this.extendedProtectionPolicy; } set { if (value == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("value"); } if (value.PolicyEnforcement == PolicyEnforcement.Always && !System.Security.Authentication.ExtendedProtection.ExtendedProtectionPolicy.OSSupportsExtendedProtection) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new PlatformNotSupportedException(SR.GetString(SR.ExtendedProtectionNotSupported))); } this.extendedProtectionPolicy = value; } } internal override string WsdlTransportUri { get { return TransportPolicyConstants.TcpTransportUri; } } public override BindingElement Clone() { return new TcpTransportBindingElement(this); } public override IChannelFactory BuildChannelFactory(BindingContext context) { if (context == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("context"); } if (!this.CanBuildChannelFactory(context)) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("TChannel", SR.GetString(SR.ChannelTypeNotSupported, typeof(TChannel))); } return (IChannelFactory)(object)new TcpChannelFactory(this, context); } public override IChannelListener BuildChannelListener(BindingContext context) { if (context == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("context"); } if (!this.CanBuildChannelListener(context)) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("TChannel", SR.GetString(SR.ChannelTypeNotSupported, typeof(TChannel))); } TcpChannelListener listener; if (typeof(TChannel) == typeof(IReplyChannel)) { listener = new TcpReplyChannelListener(this, context); } else if (typeof(TChannel) == typeof(IDuplexSessionChannel)) { listener = new TcpDuplexChannelListener(this, context); } else { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("TChannel", SR.GetString(SR.ChannelTypeNotSupported, typeof(TChannel))); } AspNetEnvironment.Current.ApplyHostedContext(listener, context); return (IChannelListener)(object)listener; } public override T GetProperty(BindingContext context) { if (context == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("context"); } if (typeof(T) == typeof(IBindingDeliveryCapabilities)) { return (T)(object)new BindingDeliveryCapabilitiesHelper(); } else if (typeof(T) == typeof(ExtendedProtectionPolicy)) { return (T)(object)this.ExtendedProtectionPolicy; } else if (typeof(T) == typeof(ITransportCompressionSupport)) { return (T)(object)new TransportCompressionSupportHelper(); } else { return base.GetProperty(context); } } internal override bool IsMatch(BindingElement b) { if (!base.IsMatch(b)) { return false; } TcpTransportBindingElement tcp = b as TcpTransportBindingElement; if (tcp == null) { return false; } if (this.listenBacklog != tcp.listenBacklog) { return false; } if (this.portSharingEnabled != tcp.portSharingEnabled) { return false; } if (this.teredoEnabled != tcp.teredoEnabled) { return false; } if (!this.connectionPoolSettings.IsMatch(tcp.connectionPoolSettings)) { return false; } if (!ChannelBindingUtility.AreEqual(this.ExtendedProtectionPolicy, tcp.ExtendedProtectionPolicy)) { return false; } return true; } [EditorBrowsable(EditorBrowsableState.Never)] public bool ShouldSerializeExtendedProtectionPolicy() { return !ChannelBindingUtility.AreEqual(this.ExtendedProtectionPolicy, ChannelBindingUtility.DefaultPolicy); } [EditorBrowsable(EditorBrowsableState.Never)] public bool ShouldSerializeListenBacklog() { return this.isListenBacklogSet; } class BindingDeliveryCapabilitiesHelper : IBindingDeliveryCapabilities { internal BindingDeliveryCapabilitiesHelper() { } bool IBindingDeliveryCapabilities.AssuresOrderedDelivery { get { return true; } } bool IBindingDeliveryCapabilities.QueuedDelivery { get { return false; } } } class TransportCompressionSupportHelper : ITransportCompressionSupport { public bool IsCompressionFormatSupported(CompressionFormat compressionFormat) { return true; } } } }