//---------------------------------------------------------------- // Copyright (c) Microsoft Corporation. All rights reserved. //---------------------------------------------------------------- namespace System.ServiceModel.Channels { using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics.CodeAnalysis; using System.Runtime; using System.ServiceModel.Description; using System.Xml; // was UdpTransportBindingElement public class UdpTransportBindingElement : TransportBindingElement, IPolicyExportExtension, ITransportPolicyImport, IWsdlExportExtension { int duplicateMessageHistoryLength; long maxPendingMessagesTotalSize; UdpRetransmissionSettings retransmissionSettings; int socketReceiveBufferSize; int timeToLive; [SuppressMessage(FxCop.Category.Usage, FxCop.Rule.DoNotCallOverridableMethodsInConstructors, Justification = "this call is intended")] public UdpTransportBindingElement() : base() { this.duplicateMessageHistoryLength = UdpConstants.Defaults.DuplicateMessageHistoryLength; this.maxPendingMessagesTotalSize = UdpConstants.Defaults.DefaultMaxPendingMessagesTotalSize; this.retransmissionSettings = new UdpRetransmissionSettings(); this.socketReceiveBufferSize = UdpConstants.Defaults.SocketReceiveBufferSize; this.timeToLive = UdpConstants.Defaults.TimeToLive; } internal UdpTransportBindingElement(UdpTransportBindingElement other) : base(other) { this.duplicateMessageHistoryLength = other.duplicateMessageHistoryLength; this.maxPendingMessagesTotalSize = other.maxPendingMessagesTotalSize; this.retransmissionSettings = other.retransmissionSettings.Clone(); this.socketReceiveBufferSize = other.socketReceiveBufferSize; this.timeToLive = other.timeToLive; this.MulticastInterfaceId = other.MulticastInterfaceId; } [DefaultValue(UdpConstants.Defaults.DuplicateMessageHistoryLength)] public int DuplicateMessageHistoryLength { get { return this.duplicateMessageHistoryLength; } set { const int min = 0; if (value < min) { throw FxTrace.Exception.ArgumentOutOfRange("value", value, SR.ArgumentOutOfMinRange(min)); } this.duplicateMessageHistoryLength = value; } } [DefaultValue(UdpConstants.Defaults.DefaultMaxPendingMessagesTotalSize)] public long MaxPendingMessagesTotalSize { get { return this.maxPendingMessagesTotalSize; } set { const long min = UdpConstants.MinPendingMessagesTotalSize; if (value < min) { throw FxTrace.Exception.ArgumentOutOfRange("value", value, SR.ArgumentOutOfMinRange(min)); } this.maxPendingMessagesTotalSize = value; } } [DefaultValue(UdpConstants.Defaults.MulticastInterfaceId)] public string MulticastInterfaceId { get; set; } public UdpRetransmissionSettings RetransmissionSettings { get { return this.retransmissionSettings; } set { if (value == null) { throw FxTrace.Exception.ArgumentNull("value"); } this.retransmissionSettings = value; } } public override string Scheme { get { return UdpConstants.Scheme; } } [DefaultValue(UdpConstants.Defaults.SocketReceiveBufferSize)] public int SocketReceiveBufferSize { get { return this.socketReceiveBufferSize; } set { if (value < UdpConstants.MinReceiveBufferSize) { throw FxTrace.Exception.ArgumentOutOfRange("value", value, SR.ArgumentOutOfMinRange(UdpConstants.MinReceiveBufferSize)); } this.socketReceiveBufferSize = value; } } [DefaultValue(UdpConstants.Defaults.TimeToLive)] public int TimeToLive { get { return this.timeToLive; } set { if (value < UdpConstants.MinTimeToLive || value > UdpConstants.MaxTimeToLive) { throw FxTrace.Exception.ArgumentOutOfRange("value", value, SR.ArgumentOutOfMinMaxRange(UdpConstants.MinTimeToLive, UdpConstants.MaxTimeToLive)); } this.timeToLive = value; } } public override IChannelFactory BuildChannelFactory(BindingContext context) { if (context == null) { throw FxTrace.Exception.ArgumentNull("context"); } if (!this.CanBuildChannelFactory(context)) { throw FxTrace.Exception.Argument("TChannel", SR.ChannelTypeNotSupported(typeof(TChannel))); } return (IChannelFactory)(object)new UdpChannelFactory(new UdpTransportBindingElement(this), context); } public override IChannelListener BuildChannelListener(BindingContext context) { if (context == null) { throw FxTrace.Exception.ArgumentNull("context"); } IChannelListener listener; if (typeof(TChannel) == typeof(IDuplexChannel)) { listener = (IChannelListener) new UdpDuplexChannelListener(new UdpTransportBindingElement(this), context); } else if (typeof(TChannel) == typeof(IReplyChannel)) { listener = (IChannelListener) new UdpReplyChannelListener(new UdpTransportBindingElement(this), context); } else { throw FxTrace.Exception.Argument("TChannel", SR.ChannelTypeNotSupported(typeof(TChannel))); } return (IChannelListener)(object)listener; } public override bool CanBuildChannelFactory(BindingContext context) { if (context == null) { throw FxTrace.Exception.ArgumentNull("context"); } return (typeof(TChannel) == typeof(IOutputChannel) || typeof(TChannel) == typeof(IDuplexChannel)); } public override bool CanBuildChannelListener(BindingContext context) { if (context == null) { throw FxTrace.Exception.ArgumentNull("context"); } // We don't need to return IBindingMulticastCapabilities, because IBindingMulticastCapabilities assumes // that you always use multicast for both send and receive. return (typeof(TChannel) == typeof(IDuplexChannel) || typeof(TChannel) == typeof(IReplyChannel)); } public override T GetProperty(BindingContext context) { if (context == null) { throw FxTrace.Exception.ArgumentNull("context"); } return base.GetProperty(context); } public override BindingElement Clone() { return new UdpTransportBindingElement(this); } [EditorBrowsable(EditorBrowsableState.Never)] public bool ShouldSerializeRetransmissionSettings() { return !this.RetransmissionSettings.IsMatch(new UdpRetransmissionSettings()); // only serialize non-default settings } [SuppressMessage(FxCop.Category.Design, FxCop.Rule.InterfaceMethodsShouldBeCallableByChildTypes, Justification = "no need to call this from derrived classes")] void IWsdlExportExtension.ExportContract(WsdlExporter exporter, WsdlContractConversionContext context) { } [SuppressMessage(FxCop.Category.Design, FxCop.Rule.InterfaceMethodsShouldBeCallableByChildTypes, Justification = "no need to call this from derrived classes")] void IWsdlExportExtension.ExportEndpoint(WsdlExporter exporter, WsdlEndpointConversionContext context) { if (exporter == null) { throw FxTrace.Exception.ArgumentNull("exporter"); } if (context == null) { throw FxTrace.Exception.ArgumentNull("context"); } MessageVersion messageVersion = context.Endpoint.Binding.GetProperty(new BindingParameterCollection()); if (messageVersion == null) { return; } AddressingVersion addressingVersion = messageVersion.Addressing; TransportBindingElement.ExportWsdlEndpoint(exporter, context, UdpConstants.WsdlSoapUdpTransportUri, addressingVersion); } [SuppressMessage(FxCop.Category.Design, FxCop.Rule.InterfaceMethodsShouldBeCallableByChildTypes, Justification = "no need to call this from derrived classes")] void IPolicyExportExtension.ExportPolicy(MetadataExporter exporter, PolicyConversionContext context) { if (exporter == null) { throw FxTrace.Exception.ArgumentNull("exporter"); } if (context == null) { throw FxTrace.Exception.ArgumentNull("context"); } MessageEncodingBindingElement encodingBindingElement = context.BindingElements.Find(); if (encodingBindingElement == null) { encodingBindingElement = new TextMessageEncodingBindingElement(); } WsdlExporter.WSAddressingHelper.AddWSAddressingAssertion(exporter, context, encodingBindingElement.MessageVersion.Addressing); UdpTransportBindingElementPolicy.ExportRetransmissionEnabledAssertion(this, context.GetBindingAssertions()); } [SuppressMessage(FxCop.Category.Design, FxCop.Rule.InterfaceMethodsShouldBeCallableByChildTypes, Justification = "no need to call this from derrived classes")] void ITransportPolicyImport.ImportPolicy(MetadataImporter importer, PolicyConversionContext policyContext) { ICollection bindingAssertions = policyContext.GetBindingAssertions(); XmlElement retransmitAssertion = null; foreach (XmlElement assertion in bindingAssertions) { if (assertion.LocalName.Equals(UdpConstants.RetransmissionEnabled, StringComparison.Ordinal)) { this.DuplicateMessageHistoryLength = UdpConstants.Defaults.DuplicateMessageHistoryLengthWithRetransmission; retransmitAssertion = assertion; } } if (retransmitAssertion != null) { bindingAssertions.Remove(retransmitAssertion); } } internal override bool IsMatch(BindingElement b) { if (!base.IsMatch(b)) { return false; } UdpTransportBindingElement udpTransport = b as UdpTransportBindingElement; if (udpTransport == null) { return false; } if (this.DuplicateMessageHistoryLength != udpTransport.DuplicateMessageHistoryLength) { return false; } if (this.MaxPendingMessagesTotalSize != udpTransport.MaxPendingMessagesTotalSize) { return false; } if (!String.Equals(this.MulticastInterfaceId, udpTransport.MulticastInterfaceId, StringComparison.OrdinalIgnoreCase)) { return false; } if (!this.RetransmissionSettings.IsMatch(udpTransport.RetransmissionSettings)) { return false; } if (this.TimeToLive != udpTransport.TimeToLive) { return false; } return true; } } }